
Most modules have such a blank line, but some don't. Inserting the blank line makes it clearer that the `//!` comments are describing the entire module, rather than the `use` declaration(s) that immediately follows.
77 lines
1.9 KiB
Rust
77 lines
1.9 KiB
Rust
//! A simple markdown parser that can write formatted text to the terminal
|
|
//!
|
|
//! Entrypoint is `MdStream::parse_str(...)`
|
|
|
|
use std::io;
|
|
|
|
use termcolor::{Buffer, BufferWriter, ColorChoice};
|
|
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 termcolor buffer
|
|
pub fn write_termcolor_buf(&self, buf: &mut Buffer) -> io::Result<()> {
|
|
term::entrypoint(self, buf)
|
|
}
|
|
}
|
|
|
|
/// Create a termcolor buffer with the `Always` color choice
|
|
pub fn create_stdout_bufwtr() -> BufferWriter {
|
|
BufferWriter::stdout(ColorChoice::Always)
|
|
}
|
|
|
|
/// 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)
|
|
}
|
|
}
|