feat(lang-check): extend the content-style gate to .astro pages #243

Sammanfogat
supernaut sammanfogade 1 incheckning från work/141 in i main 2026-09-21 09:24:34 +00:00
Ägare

The gate read src/content/**/*.md and src/i18n/*.ts. The violations that motivated the glossary work were in src/pages/pricing.astro, which it never read. A check that reports clean over the surface where the bug was gives false assurance.

No new dependency. @astrojs/compiler is only a transitive dependency of @astrojs/check and is not resolvable from project code under pnpm's strict node_modules, and all three real violations were plain template text, not attribute values. maskAstroSyntax() in scripts/check-content-style.mjs walks an .astro file once and blanks everything that is not rendered prose: the frontmatter fence, HTML comments, tags including multi-line and quoted attributes, <script> and <style> bodies, and top-level {expression} blocks. It replaces with spaces and keeps every newline, so line numbers never shift and the existing rules, tests and lang-check-ignore-next-line suppression all work unchanged.

scopeForFile() now treats src/pages/**/*.astro without an en segment as Swedish, src/pages/en/** as English, and everything else as the existing lenient chrome scope.

Three rules were missing entirely, file scope aside: sv-term/runner (the glossary row existed with no rule behind it), sv-short/dvs and sv-short/mm. Added, with guide text in docs/content-style.md per its own "Adding a rule" process.

Proven against the real faults, replayed from the pre-#136 blob:

src/pages/pricing.astro:60   sv-short/mm      > projekt, wiki, mm.
src/pages/pricing.astro:103  sv-term/runner   > Dedikerad runner för kontinuerlig integration (CI)
src/pages/pricing.astro:141  sv-short/dvs     > ... dvs kodlagring
TOTAL: 4 (runner appears twice in that file)

Clean on current main: ✓ content style: no candidates in 141 file(s) (74 .md, 4 .ts, 63 .astro, up from 78 files).

Regression test in scripts/check-content-style.test.mjs: a fixture carrying all three violations plus an import path, a frontmatter identifier, a class name and an href holding the same substrings, asserting exactly the three rules fire and nothing from the code. Plus scope tests for astro pages, the ignore directive as an HTML comment, and a <style> body that would fail without masking.

lefthook's pre-commit glob gains src/**/*.astro. The CI sweep runs bare pnpm lang-check, so it picks up the extended default targets.

Two known gaps, stated rather than hidden

  • An {} expression wrapping nested JSX, for example {cond && <p>text</p>}, is masked opaquely, so prose nested that deep is not checked. One occurrence exists, a dev-only notice in src/components/legal-entity.astro. Nothing on a governed page uses the pattern.
  • Prose passed as a component prop, for example <Card title="...">, is masked with the rest of the attribute. No governed page does this today.

Verified: pnpm lint, pnpm check, pnpm test (367 passed), pnpm lang-check.

Closes #141

The gate read `src/content/**/*.md` and `src/i18n/*.ts`. The violations that motivated the glossary work were in `src/pages/pricing.astro`, which it never read. A check that reports clean over the surface where the bug was gives false assurance. No new dependency. `@astrojs/compiler` is only a transitive dependency of `@astrojs/check` and is not resolvable from project code under pnpm's strict `node_modules`, and all three real violations were plain template text, not attribute values. `maskAstroSyntax()` in `scripts/check-content-style.mjs` walks an `.astro` file once and blanks everything that is not rendered prose: the frontmatter fence, HTML comments, tags including multi-line and quoted attributes, `<script>` and `<style>` bodies, and top-level `{expression}` blocks. It replaces with spaces and keeps every newline, so line numbers never shift and the existing rules, tests and `lang-check-ignore-next-line` suppression all work unchanged. `scopeForFile()` now treats `src/pages/**/*.astro` without an `en` segment as Swedish, `src/pages/en/**` as English, and everything else as the existing lenient chrome scope. Three rules were missing entirely, file scope aside: `sv-term/runner` (the glossary row existed with no rule behind it), `sv-short/dvs` and `sv-short/mm`. Added, with guide text in `docs/content-style.md` per its own "Adding a rule" process. Proven against the real faults, replayed from the pre-#136 blob: ``` src/pages/pricing.astro:60 sv-short/mm > projekt, wiki, mm. src/pages/pricing.astro:103 sv-term/runner > Dedikerad runner för kontinuerlig integration (CI) src/pages/pricing.astro:141 sv-short/dvs > ... dvs kodlagring TOTAL: 4 (runner appears twice in that file) ``` Clean on current main: `✓ content style: no candidates in 141 file(s)` (74 `.md`, 4 `.ts`, 63 `.astro`, up from 78 files). Regression test in `scripts/check-content-style.test.mjs`: a fixture carrying all three violations plus an import path, a frontmatter identifier, a class name and an href holding the same substrings, asserting exactly the three rules fire and nothing from the code. Plus scope tests for astro pages, the ignore directive as an HTML comment, and a `<style>` body that would fail without masking. lefthook's pre-commit glob gains `src/**/*.astro`. The CI sweep runs bare `pnpm lang-check`, so it picks up the extended default targets. ## Two known gaps, stated rather than hidden - An `{}` expression wrapping nested JSX, for example `{cond && <p>text</p>}`, is masked opaquely, so prose nested that deep is not checked. One occurrence exists, a dev-only notice in `src/components/legal-entity.astro`. Nothing on a governed page uses the pattern. - Prose passed as a component prop, for example `<Card title="...">`, is masked with the rest of the attribute. No governed page does this today. Verified: `pnpm lint`, `pnpm check`, `pnpm test` (367 passed), `pnpm lang-check`. Closes #141
supernaut lade till 1 incheckning 2026-09-20 22:33:46 +00:00
feat(lang-check): extend the content-style gate to .astro pages
Alla kontroller lyckades
ci / ci (pull_request) Successful in 1m20s
0338ab5c08
Mask everything in an .astro file that isn't rendered prose (frontmatter,
tags, comments, script/style bodies, {expression} blocks) and run the
existing line-based rules over what's left, so a template's own text nodes
are checked without flagging class names, import paths or attribute values.

Also add the runner/dvs/mm rules the gate never had, so lang-check would
have caught the three real faults #136 fixed in pricing.astro. The ignore
directive works inside .astro as an HTML comment, and both lefthook and the
default target list now include src/**/*.astro.
supernaut tvångsskickade work/141 från 0338ab5c08
Alla kontroller lyckades
ci / ci (pull_request) Successful in 1m20s
till f6da09d48e
Alla kontroller lyckades
ci / ci (pull_request) Successful in 1m24s
2026-09-21 08:26:46 +00:00
Jämför
supernaut sammanfogade incheckning b36c84eda7 till main 2026-09-21 09:24:34 +00:00
supernaut tog bort grenen work/141 2026-09-21 09:24:34 +00:00
Logga in för att delta i denna konversation.
Inga granskare
Ingen milstolpe
Inget projekt
Inga tilldelade
1 deltagare
Notiser
Förfallodatum
Förfallodatumet är ogiltigt eller utanför gränserna. Använd formatet "åååå-mm-dd".

Inget förfallodatum satt.

Beroenden

Inga beroenden satta

Referens
bitborg/bitborg-web!243
Ingen beskrivning angiven.