Skip to main content

inline_runs_highlight/
inline_runs_highlight.rs

1//! inline_runs_highlight — exercises sub-word inline backgrounds.
2//!
3//! Three paragraphs:
4//!
5//! - **A search-result row** with the matched term highlighted mid-word.
6//! - **A diff-style line** with added / removed tinted spans flowing
7//!   inside one prose paragraph (no per-word `<span>` chrome — the
8//!   shaper places the rects at the actual glyph extents).
9//! - **A wrapping highlight** that splits across two lines so the rect
10//!   per-line emission is visible in the artifact.
11//!
12//! Inspect `out/inline_runs_highlight.draw_ops.txt` — each Attr line
13//! reports `runs=N bg_runs=M`, and the SVG fallback emits one
14//! `<rect data-node="…run-bg">` per highlighted run on the first line.
15//! The wgpu / vulkano paths shape once and emit one quad per line per
16//! styled span.
17//!
18//! Run: `cargo run -p aetna-core --example inline_runs_highlight`
19
20use aetna_core::prelude::*;
21
22const HIGHLIGHT_YELLOW: Color = Color::token("inline-mark", 240, 210, 90, 200);
23const DIFF_ADD: Color = Color::token("diff-add", 64, 130, 88, 220);
24const DIFF_REMOVE: Color = Color::token("diff-remove", 180, 70, 80, 220);
25
26fn fixture() -> El {
27    column([
28        h2("Inline run backgrounds"),
29        paragraph(
30            "RunStyle.bg paints a per-line solid quad behind the glyphs of \
31             a styled span — the shaper computes the rect from the actual \
32             glyph extents, so wrapping splits the highlight cleanly.",
33        )
34        .muted(),
35        // Search-result style.
36        text_runs([
37            text("…the matcher finds "),
38            text("aetna").background(HIGHLIGHT_YELLOW).bold(),
39            text(" in "),
40            text("aetna_core::widgets").mono(),
41            text(" — the highlight tracks the glyph extent."),
42        ])
43        .wrap_text()
44        .width(Size::Fill(1.0))
45        .height(Size::Hug),
46        // Diff-style: add + remove tints inside the same line.
47        text_runs([
48            text("- "),
49            text("error::Custom").mono().background(DIFF_REMOVE),
50            text("(\"too narrow\")"),
51            hard_break(),
52            text("+ "),
53            text("error::WrapTooNarrow").mono().background(DIFF_ADD),
54            text(" { available }"),
55        ])
56        .wrap_text()
57        .width(Size::Fill(1.0))
58        .height(Size::Hug),
59        // Wrapping highlight: long span that spans two lines.
60        text_runs([
61            text("Long highlight: "),
62            text("the quick brown fox jumps over the lazy dog and keeps going")
63                .background(HIGHLIGHT_YELLOW),
64            text(" — the rect is split per line."),
65        ])
66        .wrap_text()
67        .width(Size::Fill(1.0))
68        .height(Size::Hug),
69    ])
70    .gap(tokens::SPACE_4)
71    .padding(tokens::SPACE_7)
72    .width(Size::Fixed(640.0))
73}
74
75fn main() -> std::io::Result<()> {
76    let mut root = fixture();
77
78    let viewport = Rect::new(0.0, 0.0, 640.0, 360.0);
79    let bundle = render_bundle(&mut root, viewport);
80
81    let out_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("out");
82    let written = write_bundle(&bundle, &out_dir, "inline_runs_highlight")?;
83    for p in &written {
84        println!("wrote {}", p.display());
85    }
86
87    if !bundle.lint.findings.is_empty() {
88        eprintln!("\nlint findings ({}):", bundle.lint.findings.len());
89        eprint!("{}", bundle.lint.text());
90    }
91
92    Ok(())
93}