home
NOTE: Under Construction - I'm in the middle of upgrading my site and lots of stuff is kinda broken. Please forgive the mess.

Wrap Syntax Highlighted Lines With Spans To Make Line Numbers

October 2023

See [TODO: make ilinks work] for a less complicated way to do things.

This is the code I'm using with the syntect syntax highlighter in rust to wrap each output line with a `html tag. Doing so provides a way to add line numbers to code blocks using `::before()`css` in the page's CSS.

Code
//! ```cargo
//! [dependencies]
//! syntect = { version = "5.1.0"}
//! ```

use syntect::easy::HighlightLines;
use syntect::highlighting::{Style, ThemeSet};
use syntect::html::{styled_line_to_highlighted_html, IncludeBackground};
use syntect::parsing::SyntaxSet;
use syntect::util::LinesWithEndings;

fn main() {
    let language = "HTML";
    let code = "<div>\n  Hello, Highligher\n</div>";
    let text = highlight_code_with_line_spans(code, language);
    print!("{}", text);
}

fn highlight_code_with_line_spans(code: &str, language: &str) -> String {
    let mut the_lines = vec![];
    let ps = SyntaxSet::load_defaults_newlines();
    let ts = ThemeSet::load_defaults();
    let syntax = ps.find_syntax_by_name(language).unwrap();
    let mut h = HighlightLines::new(syntax, &ts.themes["base16-ocean.dark"]);
    for line in LinesWithEndings::from(code) {
        let ranges: Vec<(Style, &str)> = h.highlight_line(line.trim_end(), &ps).unwrap();
        let highlighted_line = styled_line_to_highlighted_html(&ranges[..], IncludeBackground::No);
        let mut spanned_line = String::from(r#"<span class="lineHighlight">"#);
        spanned_line.push_str(&highlighted_line.unwrap());
        spanned_line.push_str("</span>");
        the_lines.push(spanned_line);
    }
    the_lines.join("\n")
}
Results
<div>
  Hello, Highligher
</div>
═══ § ═══