use pulldown_cmark::{Event, Parser, Tag, TagEnd};
use std::ops::Range;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum BlockKind {
ItemStart,
ItemEnd,
QuoteStart,
QuoteEnd,
HeadingStart,
Rule,
Other,
}
impl BlockKind {
pub(crate) fn of(event: &Event<'_>) -> Self {
match event {
Event::Start(Tag::Item) => Self::ItemStart,
Event::End(TagEnd::Item) => Self::ItemEnd,
Event::Start(Tag::BlockQuote(_)) => Self::QuoteStart,
Event::End(TagEnd::BlockQuote(_)) => Self::QuoteEnd,
Event::Start(Tag::Heading { .. }) => Self::HeadingStart,
Event::Rule => Self::Rule,
_ => Self::Other,
}
}
}
#[derive(Default)]
pub(crate) struct BlockFacts {
pub(crate) events: Vec<(BlockKind, Range<usize>)>,
}
impl BlockFacts {
pub(crate) fn push(&mut self, event: &Event<'_>, range: &Range<usize>) {
let kind = BlockKind::of(event);
if kind != BlockKind::Other || self.events.last().is_none_or(|(last, _)| *last != BlockKind::Other) {
self.events
.push((kind, if kind == BlockKind::Other { 0..0 } else { range.clone() }));
}
}
pub(crate) fn parse(content: &str) -> Self {
let mut facts = Self::default();
for (event, range) in
Parser::new_ext(content, crate::utils::parser_options::rumdl_parser_options_for(content)).into_offset_iter()
{
facts.push(&event, &range);
}
facts
}
}