diff options
Diffstat (limited to 'src/md/visitor/structure.rs')
-rw-r--r-- | src/md/visitor/structure.rs | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/src/md/visitor/structure.rs b/src/md/visitor/structure.rs new file mode 100644 index 0000000..d8faef6 --- /dev/null +++ b/src/md/visitor/structure.rs @@ -0,0 +1,100 @@ +use crate::md::panhelper; + +use pandoc_ast::{Block, Inline, MutVisitor}; + +// A structure element in the document: a heading or a scenario snippet. +#[derive(Debug)] +pub enum Element { + // Headings consist of the text and the level of the heading. + Heading(String, i64), + + // Scenario snippets consist just of the unparsed text. + Snippet(String), +} + +impl Element { + pub fn heading(text: &str, level: i64) -> Element { + Element::Heading(text.to_string(), level) + } + + pub fn snippet(text: &str) -> Element { + Element::Snippet(text.to_string()) + } +} + +// A MutVisitor for extracting document structure. +pub struct StructureVisitor { + pub elements: Vec<Element>, +} + +impl StructureVisitor { + pub fn new() -> Self { + Self { elements: vec![] } + } +} + +impl MutVisitor for StructureVisitor { + fn visit_vec_block(&mut self, vec_block: &mut Vec<Block>) { + use panhelper::is_class; + for block in vec_block { + match block { + Block::Header(level, _attr, inlines) => { + let text = join(inlines); + let heading = Element::heading(&text, *level); + self.elements.push(heading); + } + Block::CodeBlock(attr, s) => { + if is_class(attr, "scenario") { + let snippet = Element::snippet(s); + self.elements.push(snippet); + } + } + _ => { + self.visit_block(block); + } + } + } + } +} + +fn join(vec: &[Inline]) -> String { + let mut buf = String::new(); + join_into_buffer(vec, &mut buf); + buf +} + +fn join_into_buffer(vec: &[Inline], buf: &mut String) { + for item in vec { + match item { + Inline::Str(s) => buf.push_str(s), + Inline::Emph(v) => join_into_buffer(v, buf), + Inline::Strong(v) => join_into_buffer(v, buf), + Inline::Strikeout(v) => join_into_buffer(v, buf), + Inline::Superscript(v) => join_into_buffer(v, buf), + Inline::Subscript(v) => join_into_buffer(v, buf), + Inline::SmallCaps(v) => join_into_buffer(v, buf), + Inline::Quoted(qt, v) => { + let q = match qt { + pandoc_ast::QuoteType::SingleQuote => "'", + pandoc_ast::QuoteType::DoubleQuote => "\"", + }; + buf.push_str(q); + join_into_buffer(v, buf); + buf.push_str(q); + } + Inline::Cite(_, v) => join_into_buffer(v, buf), + Inline::Code(_attr, s) => buf.push_str(s), + Inline::Space => buf.push(' '), + Inline::SoftBreak => buf.push(' '), + Inline::LineBreak => buf.push(' '), + Inline::Math(_, s) => buf.push_str(s), + Inline::RawInline(_, s) => buf.push_str(s), + Inline::Link(_, v, _) => join_into_buffer(v, buf), + Inline::Image(_, v, _) => join_into_buffer(v, buf), + Inline::Note(_) => buf.push_str(""), + Inline::Span(_attr, v) => join_into_buffer(v, buf), + #[cfg(feature = "pandoc_ast_08")] + Inline::Underline(v) => join_into_buffer(v, buf), + } + } +} |