diff options
Diffstat (limited to 'src/html.rs')
-rw-r--r-- | src/html.rs | 91 |
1 files changed, 78 insertions, 13 deletions
diff --git a/src/html.rs b/src/html.rs index 7237258..b39872b 100644 --- a/src/html.rs +++ b/src/html.rs @@ -72,7 +72,7 @@ impl HtmlPage { } /// Parse Markdown text into an HTML element. -pub fn parse(markdown: &str) -> Result<Element, HtmlError> { +pub fn parse(filename: &Path, markdown: &str) -> Result<Element, HtmlError> { let mut options = Options::empty(); options.insert(Options::ENABLE_HEADING_ATTRIBUTES); options.insert(Options::ENABLE_STRIKETHROUGH); @@ -85,7 +85,7 @@ pub fn parse(markdown: &str) -> Result<Element, HtmlError> { for (event, loc) in p { trace!("event {:?}", event); let (line, col) = linecol.get(loc.start); - let loc = Location::new(line, col); + let loc = Location::new(filename, line, col); match event { Event::Start(tag) => match tag { Tag::Paragraph => stack.push_tag(ElementTag::P, loc), @@ -162,7 +162,7 @@ pub fn parse(markdown: &str) -> Result<Element, HtmlError> { let s = as_plain_text(e.children()); trace!("paragraph text: {:?}", s); if s.starts_with(": ") || s.contains("\n: ") { - return Err(HtmlError::DefinitionList(loc.line, loc.col)); + return Err(HtmlError::DefinitionList(loc)); } stack.append_child(Content::Elt(e)); } @@ -254,8 +254,12 @@ impl Element { } /// Get location. - pub fn location(&self) -> &Option<Location> { - &self.loc + pub fn location(&self) -> Location { + if let Some(loc) = &self.loc { + loc.clone() + } else { + Location::unknown() + } } fn set_block_attributes(&mut self, block_attrs: Vec<BlockAttr>) { @@ -543,15 +547,76 @@ impl Content { } /// Location of element in source file. -#[derive(Debug, Clone, Copy)] -pub struct Location { - line: usize, - col: usize, +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum Location { + /// A known location. + Known { + /// Name of file. + filename: PathBuf, + /// Line in file. + line: usize, + /// Column in line. + col: usize, + }, + /// An unknown location. + Unknown, } impl Location { - fn new(line: usize, col: usize) -> Self { - Self { line, col } + fn new(filename: &Path, line: usize, col: usize) -> Self { + Self::Known { + filename: filename.into(), + line, + col, + } + } + + /// Create an unknown location. + pub fn unknown() -> Self { + Self::Unknown + } + + /// Report name of source file from where this element comes from. + pub fn filename(&self) -> &Path { + if let Self::Known { + filename, + line: _, + col: _, + } = self + { + filename + } else { + Path::new("") + } + } + + /// Report row and column in source where this element comes from. + pub fn rowcol(&self) -> (usize, usize) { + if let Self::Known { + filename: _, + line, + col, + } = self + { + (*line, *col) + } else { + (0, 0) + } + } +} + +impl std::fmt::Display for Location { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + if let Self::Known { + filename, + line, + col, + } = self + { + write!(f, "{}:{}:{}", filename.display(), line, col) + } else { + write!(f, "(unknown location)") + } } } @@ -616,8 +681,8 @@ pub enum HtmlError { /// Input contains an attempt to use a definition list in /// Markdown. - #[error("attempt to use definition lists in Markdown: line {0}, column {1}")] - DefinitionList(usize, usize), + #[error("attempt to use definition lists in Markdown: {0}")] + DefinitionList(Location), /// String formatting error. This is likely a programming error. #[error("string formatting error: {0}")] |