71 lines
2.1 KiB
Rust
71 lines
2.1 KiB
Rust
use crate::generator::highlight::highlight;
|
|
use pulldown_cmark::{CodeBlockKind, Event, Tag};
|
|
|
|
pub fn new<'a, I: Iterator<Item = Event<'a>>>(iter: I) -> Highlight<'a, I> {
|
|
Highlight { iter }
|
|
}
|
|
|
|
pub struct Highlight<'a, I: Iterator<Item = Event<'a>>> {
|
|
iter: I,
|
|
}
|
|
|
|
impl<'a, I: Iterator<Item = Event<'a>>> Iterator for Highlight<'a, I> {
|
|
type Item = Event<'a>;
|
|
|
|
fn next(&mut self) -> Option<Event<'a>> {
|
|
match self.iter.next() {
|
|
Some(Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(label)))) => {
|
|
let code = self.consume_code_block();
|
|
let mut highlighted = highlight(&code, &label);
|
|
highlighted.insert_str(
|
|
0,
|
|
&format!("<pre class=\"highlight\" data-lang=\"{}\"><code>", label),
|
|
);
|
|
highlighted.push_str("</code></pre>");
|
|
Some(Event::Html(highlighted.into()))
|
|
}
|
|
e => e,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a, I: Iterator<Item = Event<'a>>> Highlight<'a, I> {
|
|
fn consume_code_block(&mut self) -> String {
|
|
let mut buf = String::new();
|
|
loop {
|
|
match self.iter.next() {
|
|
Some(Event::End(Tag::CodeBlock(CodeBlockKind::Fenced(_)))) => {
|
|
break;
|
|
}
|
|
Some(Event::Text(s)) => {
|
|
buf.push_str(&s);
|
|
}
|
|
e => panic!("unexpected event in fenced code block: {:?}", e),
|
|
}
|
|
}
|
|
buf
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use pulldown_cmark::{html, Parser};
|
|
|
|
fn render(s: &str) -> String {
|
|
let mut out = String::new();
|
|
let parser = Parser::new(s);
|
|
let heading_anchors = super::new(parser);
|
|
html::push_html(&mut out, heading_anchors);
|
|
out
|
|
}
|
|
|
|
#[test]
|
|
fn test_higlight_markdown() {
|
|
assert_eq!(
|
|
render("```js\nfoo(bar, 123)\n```".into()),
|
|
r#"<pre class="highlight" data-lang="js"><code><span class="hl-fn">foo</span>(<span class="hl-var">bar</span>, <span class="hl-num">123</span>)
|
|
</code></pre>"#
|
|
);
|
|
}
|
|
}
|