mod atters;
pub mod block;
pub mod hooks;
pub mod inline;
mod table;
pub mod visitor;
use crate::markdown::ast::options::AstOptions;
use crate::markdown::ast::parsers::hooks::ParseHooks;
use crate::markdown::ast::tokens::{span::Span, token::Block};
use inline::LinkRefMap;
#[cfg(feature = "npm")]
use napi_derive::napi;
use serde::Serialize;
#[cfg_attr(feature = "npm", napi(object))]
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct Document {
#[serde(rename = "type")]
pub node_type: String,
pub file_name: Option<String>,
pub pos: Span,
pub children: Vec<Block>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub link_references: Vec<crate::markdown::ast::tokens::token::LinkReferenceDefinition>,
}
impl Default for Document {
fn default() -> Self {
Self {
node_type: "root".to_string(),
file_name: None,
pos: Span::default(),
children: Vec::new(),
link_references: Vec::new(),
}
}
}
impl Document {
pub fn parse(input: &str, opts: &AstOptions, file_name: Option<String>) -> Self {
md_to_ast(input, opts, file_name)
}
}
pub fn md_to_ast(input: &str, opts: &AstOptions, file_name: Option<String>) -> Document {
md_to_ast_with_hooks(input, opts, file_name, &ParseHooks::empty())
}
pub fn md_to_ast_with_hooks(
input: &str,
opts: &AstOptions,
file_name: Option<String>,
hooks: &ParseHooks,
) -> Document {
let line_starts = block::compute_line_starts(input);
let lines: Vec<&str> = input.lines().collect();
let mut ref_map: LinkRefMap = LinkRefMap::new();
let mut ref_defs: Vec<crate::markdown::ast::tokens::token::LinkReferenceDefinition> =
Vec::new();
for (line_idx, line) in lines.iter().enumerate() {
if block::is_link_ref_def(line) {
if let Some(def) = block::parse_link_ref_def_line(line, line_idx, &line_starts, input) {
ref_map.insert(def.label.clone(), (def.url.clone(), def.title.clone()));
ref_defs.push(def);
}
}
}
let mut p = block::ParserState::new(
input,
&lines,
&line_starts,
opts,
file_name.clone(),
&ref_map,
hooks,
);
let start = p.position_at(0);
let mut blocks = Vec::new();
while !p.is_done() {
if p.skip_blank_lines() {
continue;
}
if let Some(block) = p.parse_block() {
blocks.push(block);
} else {
p.advance(); }
}
let end = p.position_at(p.pos.min(p.lines.len()));
Document {
node_type: "root".to_string(),
pos: Span::new(start, end),
file_name,
children: blocks,
link_references: ref_defs,
}
}