From e4014b2138267a3eea131e11284628a313db2235 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Wed, 26 Oct 2022 11:29:06 +0300 Subject: feat: store start location of each element Sponsored-by: author --- src/html.rs | 54 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/src/html.rs b/src/html.rs index abbe71d..6605333 100644 --- a/src/html.rs +++ b/src/html.rs @@ -73,9 +73,11 @@ pub fn parse(markdown: &str) -> Result { stack.push(Element::new(ElementTag::Body)); for (event, loc) in p { trace!("event {:?}", event); + let (line, col) = linecol.get(loc.start); + let loc = Location::new(line, col); match event { Event::Start(tag) => match tag { - Tag::Paragraph => stack.push_tag(ElementTag::P), + Tag::Paragraph => stack.push_tag(ElementTag::P, loc), Tag::Heading(level, id, classes) => { let tag = match level { HeadingLevel::H1 => ElementTag::H1, @@ -101,23 +103,23 @@ pub fn parse(markdown: &str) -> Result { } stack.push(h); } - Tag::BlockQuote => stack.push_tag(ElementTag::Blockquote), - Tag::CodeBlock(_) => stack.push_tag(ElementTag::Pre), - Tag::List(None) => stack.push_tag(ElementTag::Ul), + Tag::BlockQuote => stack.push_tag(ElementTag::Blockquote, loc), + Tag::CodeBlock(_) => stack.push_tag(ElementTag::Pre, loc), + Tag::List(None) => stack.push_tag(ElementTag::Ul, loc), Tag::List(Some(start)) => { - let mut e = Element::new(ElementTag::Ol); + let mut e = Element::new(ElementTag::Ol).with_location(loc); e.push_attribute(Attribute::new("start", &format!("{}", start))); stack.push(e); } - Tag::Item => stack.push_tag(ElementTag::Li), + Tag::Item => stack.push_tag(ElementTag::Li, loc), Tag::FootnoteDefinition(_) => unreachable!("{:?}", tag), - Tag::Table(_) => stack.push_tag(ElementTag::Table), - Tag::TableHead => stack.push_tag(ElementTag::Th), - Tag::TableRow => stack.push_tag(ElementTag::Tr), - Tag::TableCell => stack.push_tag(ElementTag::Td), - Tag::Emphasis => stack.push_tag(ElementTag::Em), - Tag::Strong => stack.push_tag(ElementTag::Strong), - Tag::Strikethrough => stack.push_tag(ElementTag::Del), + Tag::Table(_) => stack.push_tag(ElementTag::Table, loc), + Tag::TableHead => stack.push_tag(ElementTag::Th, loc), + Tag::TableRow => stack.push_tag(ElementTag::Tr, loc), + Tag::TableCell => stack.push_tag(ElementTag::Td, loc), + Tag::Emphasis => stack.push_tag(ElementTag::Em, loc), + Tag::Strong => stack.push_tag(ElementTag::Strong, loc), + Tag::Strikethrough => stack.push_tag(ElementTag::Del, loc), Tag::Link(_, url, title) => { let mut link = Element::new(ElementTag::A); link.push_attribute(Attribute::new("href", url.as_ref())); @@ -142,8 +144,7 @@ pub fn parse(markdown: &str) -> Result { let s = as_plain_text(e.children()); trace!("paragraph text: {:?}", s); if s.starts_with(": ") || s.contains("\n: ") { - let (line, col) = linecol.get(loc.start); - return Err(SiteError::DefinitionList(line, col)); + return Err(SiteError::DefinitionList(loc.line, loc.col)); } stack.append_child(Content::Elt(e)); } @@ -206,6 +207,7 @@ fn as_plain_text(content: &[Content]) -> String { #[derive(Debug, Clone)] pub struct Element { + loc: Option, tag: ElementTag, attrs: Vec, children: Vec, @@ -214,12 +216,18 @@ pub struct Element { impl Element { pub fn new(tag: ElementTag) -> Self { Self { + loc: None, tag, attrs: vec![], children: vec![], } } + fn with_location(mut self, loc: Location) -> Self { + self.loc = Some(loc); + self + } + fn push_attribute(&mut self, attr: Attribute) { self.attrs.push(attr); } @@ -420,6 +428,18 @@ pub enum Content { Html(String), } +#[derive(Debug, Clone, Copy)] +struct Location { + line: usize, + col: usize, +} + +impl Location { + fn new(line: usize, col: usize) -> Self { + Self { line, col } + } +} + struct Stack { stack: Vec, } @@ -438,8 +458,8 @@ impl Stack { self.stack.push(e); } - fn push_tag(&mut self, tag: ElementTag) { - self.push(Element::new(tag)); + fn push_tag(&mut self, tag: ElementTag, loc: Location) { + self.push(Element::new(tag).with_location(loc)); } fn pop(&mut self) -> Element { -- cgit v1.2.1