Implement the highlighted src intermediate format.

I am going to remove the enum because I realized plain src blocks can just be highlighted src blocks with only RawText entries.
This commit is contained in:
Tom Alexander 2025-02-22 15:44:45 -05:00
parent c067ca9cc8
commit e34e2ef75f
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE

View File

@ -24,11 +24,23 @@ pub(crate) struct PlainSrcBlock {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) struct HighlightedSrcBlock { pub(crate) struct HighlightedSrcBlock {
pub(crate) lines: Vec<String>, pub(crate) lines: Vec<HighlightedSrcLine>,
pub(crate) language: Option<String>, pub(crate) language: Option<String>,
pub(crate) post_blank: organic::types::PostBlank, pub(crate) post_blank: organic::types::PostBlank,
} }
#[derive(Debug, Clone)]
pub(crate) struct HighlightedSrcLine {
pub(crate) children: Vec<HighlightedSrcSegment>,
}
#[derive(Debug, Clone)]
pub(crate) enum HighlightedSrcSegment {
RawText(String),
HighlightStart { name: String },
HighlightEnd,
}
intermediate!( intermediate!(
ISrcBlock, ISrcBlock,
&'orig organic::types::SrcBlock<'parse>, &'orig organic::types::SrcBlock<'parse>,
@ -97,6 +109,14 @@ intermediate!(
} }
); );
impl HighlightedSrcLine {
pub(crate) fn new() -> HighlightedSrcLine {
HighlightedSrcLine {
children: Vec::new(),
}
}
}
fn ascii_whitespace_value(c: char) -> usize { fn ascii_whitespace_value(c: char) -> usize {
match c { match c {
' ' => 1, ' ' => 1,
@ -107,7 +127,7 @@ fn ascii_whitespace_value(c: char) -> usize {
} }
} }
fn highlight_nix<L>(lines: &[L]) -> Result<Vec<String>, CustomError> fn highlight_nix<L>(lines: &[L]) -> Result<Vec<HighlightedSrcLine>, CustomError>
where where
L: Borrow<str>, L: Borrow<str>,
{ {
@ -126,28 +146,43 @@ where
.highlight(&config, combined_text.as_bytes(), None, |_| None) .highlight(&config, combined_text.as_bytes(), None, |_| None)
.unwrap(); .unwrap();
let mut highlighted_text = Vec::new(); let mut highlighted_text: Vec<HighlightedSrcLine> = Vec::with_capacity(lines.len());
let mut current_line = HighlightedSrcLine::new();
for event in highlights { for event in highlights {
match event.unwrap() { match event.unwrap() {
HighlightEvent::Source { start, end } => { HighlightEvent::Source { start, end } => {
highlighted_text.push(Cow::Borrowed(&combined_text[start..end])); let mut span = &combined_text[start..end];
while let Some(line_break_index) = span.find('\n') {
let first_line = &span[..(line_break_index + 1)];
current_line
.children
.push(HighlightedSrcSegment::RawText(first_line.to_owned()));
highlighted_text.push(current_line);
current_line = HighlightedSrcLine::new();
span = &span[(line_break_index + 1)..];
}
if !span.is_empty() {
current_line
.children
.push(HighlightedSrcSegment::RawText(span.to_owned()));
}
} }
HighlightEvent::HighlightStart(s) => { HighlightEvent::HighlightStart(s) => {
let class_name = format!("srchl_{}", highlight_names[s.0]); current_line
highlighted_text.push(Cow::Owned(format!(r#"<span class="{}">"#, class_name))); .children
.push(HighlightedSrcSegment::HighlightStart {
name: highlight_names[s.0].to_owned(),
});
} }
HighlightEvent::HighlightEnd => { HighlightEvent::HighlightEnd => {
highlighted_text.push(Cow::Borrowed(r#"</span>"#)); current_line
.children
.push(HighlightedSrcSegment::HighlightEnd);
} }
} }
} }
let highlighted_text = highlighted_text.join(""); Ok(highlighted_text)
let lines = highlighted_text
.split_inclusive('\n')
.map(str::to_owned)
.collect();
Ok(lines)
} }
// use tree_sitter::Parser; // use tree_sitter::Parser;