Add line highlighting support to ClassedHTMLGenerator#611
Add line highlighting support to ClassedHTMLGenerator#611Madoshakalaka wants to merge 3 commits intotrishume:masterfrom
Conversation
Add new constructor `new_with_class_style_and_highlighted_lines` that accepts 1-indexed line numbers to wrap in `<span class="hl">`. The wrapper correctly closes and reopens scope spans that cross line boundaries, keeping the HTML well-nested. The newline character is placed outside the highlight wrapper so `display: inline-block` styling works without collapsing consecutive highlighted lines. Also emit a `.hl` CSS rule in `css_for_theme_with_class_style` using the theme's `lineHighlight` color (with alpha support) when available.
|
After some investigation, I realized comment based syntax highlighting comes from docusaurus, as opposed to prism.js Not sure if it's a good idea to include it in syntect, open to suggestions. |
Introduce a ClassedRenderer trait that decouples syntax parsing from HTML generation, allowing custom renderers to control per-token and per-line output without accessing SCOPE_REPO. - Add ClassedRenderer trait with begin_line/end_line/begin_scope/ end_scope/write_text hooks; begin_scope receives pre-resolved atom strings so consumers never touch the scope repository - Add DefaultClassedRenderer reproducing the original <span> output - Rename ClassedHTMLGenerator to ClassedHighlighter<R>, parameterized by renderer; keep ClassedHTMLGenerator as a deprecated type alias - Add LineHighlightingRenderer<R> composable wrapper for line highlighting with proper scope span close/reopen at boundaries - Add Scope::with_atom_strs() closure-based API for reading atom strings without exposing the scope repository - Remove SCOPE_REPO and lock_global_scope_repo from the public API - Optimize locking: repo locked once per line instead of per scope Addresses trishume#626, provides the extension points needed by trishume#611.
|
I've been working on #626 and opened a draft PR (#627) that introduces a The idea is that Usage would look like: let style = ClassStyle::Spaced;
let renderer = LineHighlightingRenderer::new(
DefaultClassedRenderer::new(style),
&[1, 4, 7], // 0-indexed line numbers to highlight
);
let mut gen = ClassedHighlighter::new_with_renderer(syntax, &syntax_set, style, renderer);
for line in LinesWithEndings::from(code) {
gen.parse_html_for_line_which_includes_newline(line)?;
}
let html = gen.finalize();
// Highlighted lines are wrapped in <span class="hl">...</span>There are a couple of things that would need work to fully cover this PR's scope:
Would appreciate any feedback on whether this direction works for the Yew documentation use case. |
|
Update on #627: the draft PR has evolved since my previous comment. Here's where things stand now:
A line-highlighting renderer would look roughly like: use syntect::parsing::Scope;
use syntect::renderer::ScopeRenderer;
use syntect::html::HtmlScopeRenderer;
struct LineHighlightingRenderer {
inner: HtmlScopeRenderer,
highlighted_lines: Vec<usize>, // 0-based line indices
}
impl ScopeRenderer for LineHighlightingRenderer {
fn begin_line(&mut self, line_index: usize, scope_stack: &[Scope], output: &mut String) {
if self.highlighted_lines.contains(&line_index) {
output.push_str("<span class=\"hl\">");
}
}
fn end_line(&mut self, line_index: usize, scope_stack: &[Scope], output: &mut String) {
if self.highlighted_lines.contains(&line_index) {
output.push_str("</span>");
}
}
fn begin_scope(&mut self, atom_strs: &[&str], scope: Scope, scope_stack: &[Scope], output: &mut String) -> bool {
self.inner.begin_scope(atom_strs, scope, scope_stack, output)
}
fn end_scope(&mut self, output: &mut String) {
self.inner.end_scope(output);
}
fn write_text(&mut self, text: &str, output: &mut String) -> Result<(), std::fmt::Error> {
self.inner.write_text(text, output)
}
}This is simpler than the previous |
Background
I'm a Yew maintainer working on yewstack/yew#2779 - replacing our currently docusaurus based https://yew.rs documentation site to a Rust/Yew based one.
Docusaurus supports line-hightling with prism.js
so that (note the line number 7)
```toml title="Cargo.toml" {7} [package] name = "yew-app" version = "0.1.0" edition = "2021" [dependencies] yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] } ```shows as:

multi non-adjecent lines is possible through comma separated line ranges like:
```rust {3-11,18-19,21-28}This PR adds line-highlighting support to syntect
Line Hightlighting API
Visualization
I did some visualization on my branch:
Gap
prism.js supports comment based line hightlighting, which is very practical in some scenarios: