| //! A simple markdown parser that can write formatted text to the terminal | |
| //! | |
| //! Entrypoint is `MdStream::parse_str(...)` | |
| use std::io; | |
| mod parse; | |
| mod term; | |
| /// An AST representation of a Markdown document | |
| #[derive(Clone, Debug, Default, PartialEq)] | |
| pub struct MdStream<'a>(Vec<MdTree<'a>>); | |
| impl<'a> MdStream<'a> { | |
| /// Parse a markdown string to a tokenstream | |
| #[must_use] | |
| pub fn parse_str(s: &str) -> MdStream<'_> { | |
| parse::entrypoint(s) | |
| } | |
| /// Write formatted output to a stdout buffer, optionally with | |
| /// a formatter for code blocks | |
| pub fn write_anstream_buf( | |
| &self, | |
| buf: &mut Vec<u8>, | |
| formatter: Option<&(dyn Fn(&str, &mut Vec<u8>) -> io::Result<()> + 'static)>, | |
| ) -> io::Result<()> { | |
| term::entrypoint(self, buf, formatter) | |
| } | |
| } | |
| /// Create an anstream buffer with the `Always` color choice | |
| pub fn create_stdout_bufwtr() -> anstream::Stdout { | |
| anstream::Stdout::always(std::io::stdout()) | |
| } | |
| /// A single tokentree within a Markdown document | |
| #[derive(Clone, Debug, PartialEq)] | |
| pub enum MdTree<'a> { | |
| /// Leaf types | |
| Comment(&'a str), | |
| CodeBlock { | |
| txt: &'a str, | |
| lang: Option<&'a str>, | |
| }, | |
| CodeInline(&'a str), | |
| Strong(&'a str), | |
| Emphasis(&'a str), | |
| Strikethrough(&'a str), | |
| PlainText(&'a str), | |
| /// [Foo](www.foo.com) or simple anchor <www.foo.com> | |
| Link { | |
| disp: &'a str, | |
| link: &'a str, | |
| }, | |
| /// `[Foo link][ref]` | |
| RefLink { | |
| disp: &'a str, | |
| id: Option<&'a str>, | |
| }, | |
| /// [ref]: www.foo.com | |
| LinkDef { | |
| id: &'a str, | |
| link: &'a str, | |
| }, | |
| /// Break bewtween two paragraphs (double `\n`), not directly parsed but | |
| /// added later | |
| ParagraphBreak, | |
| /// Break bewtween two lines (single `\n`) | |
| LineBreak, | |
| HorizontalRule, | |
| Heading(u8, MdStream<'a>), | |
| OrderedListItem(u16, MdStream<'a>), | |
| UnorderedListItem(MdStream<'a>), | |
| } | |
| impl<'a> From<Vec<MdTree<'a>>> for MdStream<'a> { | |
| fn from(value: Vec<MdTree<'a>>) -> Self { | |
| Self(value) | |
| } | |
| } |