Skip to content

Commit dd6218f

Browse files
committed
test: correct issue-ledger fidelity surfaced by the audit
A fidelity audit re-tested each documented issue's ACTUAL reported repro (not the ledger's hand-simplified `src`/`input`) against parse5/the official grammar. It found cases graded ✓ via a weaker proxy that dropped the facet the issue hinges on (the same failure mode as #2060). Honest corrections — no grammar behavior change beyond the separate #97 fix: HTML - tmbundle#82: the case used a paired `<script>…</script>` proxy, never the issue's SELF-CLOSING `<script …/>`. parse5 keeps a raw-text `<script/>` OPEN (the rest is its text content — `/>` is not self-closing on non-void elements); Monogram AND the official both follow this, so it is both-pass / parse5-correct, not a miss. Repointed to the real self-close repro. - tmbundle#115: the `src` actually tested `>`-inside-a-quoted-value (= vscode#130284); real tmbundle#115 is a feature request to flag end-tags-with-attributes as invalid (no tokenization bug). Relabeled to its true subject. Vue - #4291: NOT a grammar bug. The generated grammar always embedded source.tsx / source.js.jsx for `<script lang="tsx"|"jsx">`; test/vue-grammar-harness.ts just never REGISTERED those dialects, so vscode-textmate dropped the includes and the body fell to source.js. Registered them (the official fixture embeds them too); all four langs now resolve to their declared scope. Hardened #4291 + added #4291-jsx. - #3999: `want: embedded` accepted both source.ts AND source.js, blind to the issue's .ts→.js family flip. Strengthened to assert the ts family + storage.type.interface.ts with a force-wrapped start tag (Monogram passes the real repro). TypeScript / TSX - #994: the case tested a TS generic-parameter default; real #994 is a JSDoc `@template [Output=Value]` default, which BOTH grammars miss. Repointed + monoGap (a genuine both-miss now shown honestly: TS 27/27 → 25/26). - #1033: the case tested a JSX generic type-argument; real #1033 is a generic ARROW with a default + destructured param. Repointed — and it is an only-Monogram WIN (the official breaks `=>`→invalid.illegal.attribute), so official TSX 6/11 → 5/11. - Hardened several TS/TSX cases (#1050/#978/#995/#890/#973/#983/#884, TSX#794) to the issues' richer real repros (cascade victims / dropped wrappers). Monogram passes each. test-issues 350→359/0, tsx-highlight 56/56. README ledger regenerated to the honest grades. (#1027 left as-is — its issue body is a screenshot with no reproducible code.)
1 parent 43dc683 commit dd6218f

7 files changed

Lines changed: 202 additions & 90 deletions

File tree

README.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,13 @@ The same question, every language at once: take the bugs reported against each *
4646

4747
<!-- issues:start -->
4848
<!-- generated by `npm run bench:issues` — do not edit by hand -->
49-
_Each hand-written **official** grammar vs Monogram's **derived** one, on the bugs filed against it: **TypeScript 27/27** (official 9/27) · **TSX 11/11** (official 6/11) · **HTML 20/20** (official 13/20) · **Vue 22/22** (official 16/22). Per-issue detail below — auto-generated by `npm run bench:issues`._
49+
_Each hand-written **official** grammar vs Monogram's **derived** one, on the bugs filed against it: **TypeScript 25/26** (official 8/26) · **TSX 11/11** (official 5/11) · **HTML 20/20** (official 13/20) · **Vue 23/23** (official 18/23). Per-issue detail below — auto-generated by `npm run bench:issues`._
5050

5151
#### TypeScript
5252
| issue | Monogram | official |
5353
|---|:--:|:--:|
54-
| [#1050](https://github.com/microsoft/TypeScript-TmLanguage/issues/1050) — typeof y < string is a relational operator not generic || · |
55-
| [#978](https://github.com/microsoft/TypeScript-TmLanguage/issues/978) — typeof x < string then function || · |
54+
| [#1050](https://github.com/microsoft/TypeScript-TmLanguage/issues/1050) — typeof y < string is a relational operator not generic (cascade victim intact) || · |
55+
| [#978](https://github.com/microsoft/TypeScript-TmLanguage/issues/978) — typeof x < string then function (cascade victim intact) || · |
5656
| [#859](https://github.com/microsoft/TypeScript-TmLanguage/issues/859) — as cast inside < > comparison || · |
5757
| [#1020](https://github.com/microsoft/TypeScript-TmLanguage/issues/1020) — new Map<number, number>; (no parens) || · |
5858
| [#855](https://github.com/microsoft/TypeScript-TmLanguage/issues/855) — new Map</* comment */string, IArgs>() || · |
@@ -64,13 +64,13 @@ _Each hand-written **official** grammar vs Monogram's **derived** one, on the bu
6464
| [#1025](https://github.com/microsoft/TypeScript-TmLanguage/issues/1025) — for-of without surrounding space keeps `of` a loop keyword || · |
6565
| [#815](https://github.com/microsoft/TypeScript-TmLanguage/issues/815) — a class method named `new` is a method name, not the operator || · |
6666
| [#992](https://github.com/microsoft/TypeScript-TmLanguage/issues/992) — casting to a type named `type` does not break highlighting || · |
67-
| [#995](https://github.com/microsoft/TypeScript-TmLanguage/issues/995) — paren-wrapped `as keyof typeof` assertion tokenizes || · |
6867
| [#891](https://github.com/microsoft/TypeScript-TmLanguage/issues/891)`from` as an ordinary variable is not a keyword || · |
6968
| [#814](https://github.com/microsoft/TypeScript-TmLanguage/issues/814)`a instanceof B & c` keeps the operand a value, not a type || · |
7069
| [#950](https://github.com/microsoft/TypeScript-TmLanguage/issues/950) — default import named `type` — the binding is a variable, not the `type` keyword || · |
7170
| [#1058](https://github.com/microsoft/TypeScript-TmLanguage/issues/1058)`import defer` should scope `defer` as a keyword || · |
71+
| [#994](https://github.com/microsoft/TypeScript-TmLanguage/issues/994) — JSDoc `@template [Output=Value]` default — the param name is uncolored (both miss) | · | · |
7272

73-
<details><summary>… and 9 more both grammars already handle (✓ / ✓)</summary>
73+
<details><summary>… and 8 more both grammars already handle (✓ / ✓)</summary>
7474

7575
| issue | Monogram | official |
7676
|---|:--:|:--:|
@@ -79,7 +79,6 @@ _Each hand-written **official** grammar vs Monogram's **derived** one, on the bu
7979
| [#788](https://github.com/microsoft/TypeScript-TmLanguage/issues/788) — optional chaining ?. is the optional accessor |||
8080
| [#881](https://github.com/microsoft/TypeScript-TmLanguage/issues/881)`override` modifier on a method is storage.modifier |||
8181
| [#1066](https://github.com/microsoft/TypeScript-TmLanguage/issues/1066) — triple-slash reference directive is a comment |||
82-
| [#994](https://github.com/microsoft/TypeScript-TmLanguage/issues/994) — default type-parameter value is colored |||
8382
| [#1027](https://github.com/microsoft/TypeScript-TmLanguage/issues/1027) — nested generic `>>` closes two type-arg lists, not a shift |||
8483
| [#956](https://github.com/microsoft/TypeScript-TmLanguage/issues/956)`as const satisfies Foo` colors the satisfies keyword and the type |||
8584
| [#907](https://github.com/microsoft/TypeScript-TmLanguage/issues/907)`typeof x extends string ? 1 : 2` conditional-type ternary |||
@@ -93,13 +92,13 @@ _Each hand-written **official** grammar vs Monogram's **derived** one, on the bu
9392
| [#979](https://github.com/microsoft/TypeScript-TmLanguage/issues/979)`const` modifier on a type parameter in `.tsx` || · |
9493
| [#1042](https://github.com/microsoft/TypeScript-TmLanguage/issues/1042)/[#990](https://github.com/microsoft/TypeScript-TmLanguage/issues/990) — default generic arrow function in `.tsx` || · |
9594
| [#627](https://github.com/microsoft/TypeScript-TmLanguage/issues/627) — member-expression JSX tag name || · |
95+
| [#1033](https://github.com/microsoft/TypeScript-TmLanguage/issues/1033) — generic arrow with a default + destructured param in `.tsx` || · |
9696
| [#825](https://github.com/microsoft/TypeScript-TmLanguage/issues/825)`<` and tag name on separate lines || · |
9797

98-
<details><summary>… and 6 more both grammars already handle (✓ / ✓)</summary>
98+
<details><summary>… and 5 more both grammars already handle (✓ / ✓)</summary>
9999

100100
| issue | Monogram | official |
101101
|---|:--:|:--:|
102-
| [#1033](https://github.com/microsoft/TypeScript-TmLanguage/issues/1033) — JSX component with a generic type argument |||
103102
| [#794](https://github.com/microsoft/TypeScript-TmLanguage/issues/794) — non-null `!` then `/` (division) in a JSX-attribute object |||
104103
| [#585](https://github.com/microsoft/TypeScript-TmLanguage/issues/585)`//` line comment inside a JSX open tag |||
105104
| [#754](https://github.com/microsoft/TypeScript-TmLanguage/issues/754) — JSX element right after a `/**/` block comment |||
@@ -128,14 +127,14 @@ _Each hand-written **official** grammar vs Monogram's **derived** one, on the bu
128127
| [tmbundle#84](https://github.com/textmate/html.tmbundle/issues/84) — tag name a prefix of a sibling (`<i>`/`<input>`) |||
129128
| [tmbundle#117](https://github.com/textmate/html.tmbundle/issues/117) — SVG camelCase tag name |||
130129
| [tmbundle#122](https://github.com/textmate/html.tmbundle/issues/122)`<` inside a quoted attr value |||
131-
| [tmbundle#115](https://github.com/textmate/html.tmbundle/issues/115)`>` inside a quoted attr value |||
132-
| [tmbundle#97](https://github.com/textmate/html.tmbundle/issues/97)space before `>` in an end tag |||
130+
| [vscode#130284](https://github.com/microsoft/vscode/issues/130284)`>` inside a quoted attr value does not close the tag early |||
131+
| [tmbundle#97](https://github.com/textmate/html.tmbundle/issues/97)whitespace (incl. a line feed) before `>` in a raw-text end tag |||
133132
| [tmbundle#81](https://github.com/textmate/html.tmbundle/issues/81) — character entity `&amp;` in text |||
134133
| [tmbundle#102](https://github.com/textmate/html.tmbundle/issues/102)`<style>` element CSS is tokenized, not a flat blob |||
135134
| [tmbundle#50](https://github.com/textmate/html.tmbundle/issues/50)`onclick=` event-handler value is colored as JS |||
136135
| [tmbundle#85](https://github.com/textmate/html.tmbundle/issues/85)`//</script>` on its own line still closes the script |||
137136
| [tmbundle#51](https://github.com/textmate/html.tmbundle/issues/51) — self-closing `/` is tag punctuation |||
138-
| [tmbundle#82](https://github.com/textmate/html.tmbundle/issues/82)`<script type="application/json">` body is not parsed as HTML |||
137+
| [tmbundle#82](https://github.com/textmate/html.tmbundle/issues/82)a `/>`-style `<script src=… />` does NOT self-close — its body is the script content |||
139138

140139
</details>
141140

@@ -147,9 +146,8 @@ _Each hand-written **official** grammar vs Monogram's **derived** one, on the bu
147146
| [#2060](https://github.com/vuejs/language-tools/issues/2060)-inline-adjacent — an unterminated union before a same-line `` </script> ``, then a second `<script setup>` block || · |
148147
| [#5660](https://github.com/vuejs/language-tools/issues/5660)`as const` cast in a v-for value || · |
149148
| [#4716](https://github.com/vuejs/language-tools/issues/4716)/[#5571](https://github.com/vuejs/language-tools/issues/5571)`as` cast followed by another attribute || · |
150-
| [#4291](https://github.com/vuejs/language-tools/issues/4291)`<script lang="tsx">` body is embedded code || · |
151149

152-
<details><summary>… and 16 more both grammars already handle (✓ / ✓)</summary>
150+
<details><summary>… and 18 more both grammars already handle (✓ / ✓)</summary>
153151

154152
| issue | Monogram | official |
155153
|---|:--:|:--:|
@@ -160,10 +158,12 @@ _Each hand-written **official** grammar vs Monogram's **derived** one, on the bu
160158
| [#6039](https://github.com/vuejs/language-tools/issues/6039)/[#4741](https://github.com/vuejs/language-tools/issues/4741)`<` operator in {{ }} (not a tag!) |||
161159
| [#5722](https://github.com/vuejs/language-tools/issues/5722) — negated ternary + quotes in {{ }} |||
162160
| [#5538](https://github.com/vuejs/language-tools/issues/5538)/[#2060](https://github.com/vuejs/language-tools/issues/2060) — trailing `export type` before `` </script> `` |||
163-
| [#3999](https://github.com/vuejs/language-tools/issues/3999) — multi-line `<script>` start tag doesn't break the code after it |||
161+
| [#3999](https://github.com/vuejs/language-tools/issues/3999)a force-wrapped multi-line `<script lang="ts">` start tag keeps the body as the `ts` family (no .ts→.js flip) |||
164162
| [#4769](https://github.com/vuejs/language-tools/issues/4769) — tag name starting with `template` |||
165163
| [#5701](https://github.com/vuejs/language-tools/issues/5701)`{{` inside a `<script>` string |||
166164
| [#6070](https://github.com/vuejs/language-tools/issues/6070) — capitalized component then a `<style>` block |||
165+
| [#4291](https://github.com/vuejs/language-tools/issues/4291)`<script lang="tsx">` body embeds the DECLARED `source.tsx` (not a source.js fallback) |||
166+
| [#4291](https://github.com/vuejs/language-tools/issues/4291)-jsx — `<script lang="jsx">` body embeds the DECLARED `source.js.jsx` |||
167167
| generic="T" — `generic="T extends U">` type-param list embeds as TS |||
168168
| [#4410](https://github.com/vuejs/language-tools/issues/4410) — dynamic directive argument `:[attr]` |||
169169
| [#3727](https://github.com/vuejs/language-tools/issues/3727)`.prop` modifier shorthand |||

test/html-issue-cases.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ export const cases: HtmlCase[] = [
2828
at: 'animateTransform', want: isTag },
2929
{ id: 'tmbundle#122', title: '`<` inside a quoted attr value', src: '<a data-q="a < b">y</a>',
3030
at: 'b', want: isString }, // still inside the string, not a new tag
31-
{ id: 'tmbundle#115', title: '`>` inside a quoted attr value', src: '<button title="a > b">go</button>',
32-
at: 'go', want: isText }, // the `>` didn't close the tag early
33-
{ id: 'tmbundle#97', title: 'space before `>` in an end tag', src: '<section>x</section >',
34-
at: 'section', nth: 1, want: isTag }, // the close tag name is still a tag
31+
{ id: 'vscode#130284', title: '`>` inside a quoted attr value does not close the tag early', src: '<button title="a > b">go</button>',
32+
at: 'go', want: isText }, // the `>` is inside the VALUE, so the start tag is not closed at it and `go` is the element's text (NOT swallowed). RELABELLED from tmbundle#115 — that earlier cite was wrong: textmate/html.tmbundle#115 is a FEATURE REQUEST to flag an end tag carrying attributes (`</div id="x">`) as invalid (which neither grammar does, and isn't a tokenization bug); this snippet actually exercises the `>`-in-attribute-value case = microsoft/vscode#130284
33+
{ id: 'tmbundle#97', title: 'whitespace (incl. a line feed) before `>` in a raw-text end tag', src: '<script src="d"></script\n><p>zz</p>',
34+
at: 'zz', want: s => isText(s) && !isJs(s) }, // HTML5 allows ws (incl. line feeds) before `>` in an end tag → parse5 CLOSES the <script> (it is empty) and `<p>zz</p>` is a sibling. The text `zz` must therefore be HTML text, NOT leaked into the embedded source.js (which is what Monogram did before the deferred-`>` close rules: `</script`→keyword.operator, `<p>zz<`→string.regexp.js). Both engines now close it (a former Monogram-only gap vs parse5)
3535
{ id: 'tmbundle#108', title: 'nested `<svg>` is a valid tag, not flagged invalid', src: '<svg><svg></svg></svg>',
3636
at: 'svg', nth: 1, want: s => isTag(s) && !s.includes('invalid') }, // official's SVG-child whitelist marks a nested <svg> invalid.illegal; Monogram's generic nesting accepts it
3737

@@ -94,6 +94,6 @@ export const cases: HtmlCase[] = [
9494
// `source.js-ignored-vscode` leak on EVERY close `<`, the #65/#74 cases Monogram keeps clean.)
9595
{ id: 'tmbundle#51', title: 'self-closing `/` is tag punctuation', src: '<img src="a.png" />',
9696
at: '/', want: isTagPunct }, // both scope the `/` of `/>` as punctuation.definition.tag (was plain text in old TextMate)
97-
{ id: 'tmbundle#82', title: '`<script type="application/json">` body is not parsed as HTML', src: '<script type="application/json">{"k":1}</script>',
98-
at: 'k', want: s => !isTag(s) && !s.includes('invalid') && !s.includes('.error') }, // the JSON body broke HTML highlighting historically; now neither treats its `{...}` as markup — official drops it into source.unknown, Monogram tokenizes it via source.js (JSON ⊂ JS), and `</script>` still closes
97+
{ id: 'tmbundle#82', title: 'a `/>`-style `<script src=… />` does NOT self-close — its body is the script content', src: '<script src="x" /></head><body>hi</body>',
98+
at: 'hi', want: s => isJs(s) && !isTag(s) }, // `<script>` is a RAW-TEXT element: per HTML5 (and parse5, the oracle) a trailing `/>` is NOT self-closing, so parse5 keeps the script OPEN and everything after it — `</head><body>hi</body>` — is its TEXT CONTENT (parse5: <body> parses EMPTY, "hi" lives inside the script node). Monogram cascades that content into its embedded source.js BY CONSTRUCTION (parse5-faithful: `hi` is source.js, NOT an HTML tag). VS Code's grammar does the same here (it does not honour `/>` on a raw-text element either) → both engines are parse5-correct. This REPLACES an unrelated paired-`<script>…</script>` JSON proxy that never exercised the self-close at all.
9999
];

0 commit comments

Comments
 (0)