test(lsp): add hemplate highlighting fixture

Add repo-owned hemplate highlighting fixture and golden capture contract without editor packaging or a second parser.

req: diagnostics/004

req: diagnostics/008
This commit is contained in:
slhx agent
2026-06-26 00:20:11 +02:00
parent 34327d6b8f
commit 2e55406a24
5 changed files with 80 additions and 5 deletions
+3 -1
View File
@@ -87,7 +87,9 @@ expression parsing, selector behavior, generated Rust facts, or build
validation. Those remain with `hemx-build`, `hemx-lsp`, normal HTML tooling, and validation. Those remain with `hemx-build`, `hemx-lsp`, normal HTML tooling, and
Rust tooling. Repo tests for highlighting should therefore be fixture/query tests Rust tooling. Repo tests for highlighting should therefore be fixture/query tests
for captures over these token classes; provider packaging or visual editor smoke for captures over these token classes; provider packaging or visual editor smoke
is a separate release slice and cannot become syntax authority. req: diagnostics/004 req: diagnostics/008 is a separate release slice and cannot become syntax authority. The current
repo-owned fixture and golden capture contract live in
`docs/fixtures/hemplate-highlighting/`. req: diagnostics/004 req: diagnostics/008
## VS Code and Cursor ## VS Code and Cursor
@@ -0,0 +1,17 @@
capture literal
@attribute.hemx data-hemx-root
@attribute.hemx data-hemx-form
@attribute.hemx data-hemx-handle
@attribute.hemx data-hemx-slot
@attribute.dynamic.hemplate +class
@keyword.control.hemplate h-if
@keyword.control.hemplate h-for
@keyword.control.hemplate h-key
@keyword.control.hemplate h-match
@keyword.control.hemplate h-case
@punctuation.special.hemplate.escaped.open {+
@punctuation.special.hemplate.escaped.close +}
@punctuation.special.hemplate.trusted.open {+=
@punctuation.special.hemplate.trusted.close =+}
@embedded.rust.hemplate result.title
@embedded.rust.hemplate result.summary_html
1 capture literal
2 @attribute.hemx data-hemx-root
3 @attribute.hemx data-hemx-form
4 @attribute.hemx data-hemx-handle
5 @attribute.hemx data-hemx-slot
6 @attribute.dynamic.hemplate +class
7 @keyword.control.hemplate h-if
8 @keyword.control.hemplate h-for
9 @keyword.control.hemplate h-key
10 @keyword.control.hemplate h-match
11 @keyword.control.hemplate h-case
12 @punctuation.special.hemplate.escaped.open {+
13 @punctuation.special.hemplate.escaped.close +}
14 @punctuation.special.hemplate.trusted.open {+=
15 @punctuation.special.hemplate.trusted.close =+}
16 @embedded.rust.hemplate result.title
17 @embedded.rust.hemplate result.summary_html
@@ -0,0 +1,18 @@
<main data-hemx-root="demo">
<form data-hemx-form="search" data-hemx-handle="run_search">
<input +class="self.search_class" name="query" />
</form>
<section h-if="self.show_results">
<template h-for="result in &self.results" h-key="result.id">
<article data-hemx-slot="result_row">
<h2>{+ result.title +}</h2>
<div>{+= result.summary_html =+}</div>
</article>
</template>
</section>
<template h-match="self.state">
<p h-case="ViewState::Empty">No results</p>
</template>
</main>
+38
View File
@@ -903,6 +903,44 @@ mod tests {
assert!(value.contains("docs/hemplate-syntax.md")); assert!(value.contains("docs/hemplate-syntax.md"));
} }
#[test]
fn hemplate_highlighting_fixture_covers_documented_overlay_tokens() {
// req: diagnostics/004 req: diagnostics/008
let fixture = include_str!("../../docs/fixtures/hemplate-highlighting/hemplate.heml");
let captures = include_str!("../../docs/fixtures/hemplate-highlighting/captures.tsv");
let allowed_captures = [
"@attribute.hemx",
"@attribute.dynamic.hemplate",
"@keyword.control.hemplate",
"@punctuation.special.hemplate.escaped.open",
"@punctuation.special.hemplate.escaped.close",
"@punctuation.special.hemplate.trusted.open",
"@punctuation.special.hemplate.trusted.close",
"@embedded.rust.hemplate",
]
.into_iter()
.collect::<std::collections::BTreeSet<_>>();
let mut seen = std::collections::BTreeSet::new();
for (index, line) in captures.lines().enumerate().skip(1) {
let (capture, literal) = line
.split_once('\t')
.unwrap_or_else(|| panic!("capture row {index} must be TSV"));
assert!(
allowed_captures.contains(capture),
"unexpected capture `{capture}` in row {index}"
);
assert!(
fixture.contains(literal),
"highlight fixture missing literal `{literal}` for capture `{capture}`"
);
seen.insert(capture);
}
assert_eq!(
seen, allowed_captures,
"highlight fixture should exercise every documented overlay capture class"
);
}
#[test] #[test]
fn workout_template_fields_are_available_from_repo_facts() { fn workout_template_fields_are_available_from_repo_facts() {
// req: diagnostics/006 // req: diagnostics/006
+4 -4
View File
@@ -1,7 +1,7 @@
--- ---
id: SLICE-0011 id: SLICE-0011
type: slice type: slice
status: ready status: done
parent: NS-0003 parent: NS-0003
title: Add hemplate highlighting fixtures and query tests title: Add hemplate highlighting fixtures and query tests
refs: refs:
@@ -26,8 +26,8 @@ Create repo-owned highlighting fixtures that prove documented hemplate syntax re
## Verification ## Verification
- Preferred future command: a repo-owned tree-sitter/query fixture test, once the crate/tool location is chosen. - `cargo test -p hemx-lsp`
- Until then, manual proof must name the exact editor/query runner and fixture. - `workledger check`
## Non-goals ## Non-goals
@@ -36,4 +36,4 @@ Create repo-owned highlighting fixtures that prove documented hemplate syntax re
## Evidence ## Evidence
The fixture list maps directly to the documented syntax surface. Done at commit `34327d6` follow-up and verified with `cargo test -p hemx-lsp`: `docs/fixtures/hemplate-highlighting/hemplate.heml` covers the documented overlay token classes and `captures.tsv` records the golden capture names without requiring editor package publishing or a second parser.