@afokapu/atdd-bun 0.10.96 → 0.10.97

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -399,7 +399,7 @@ relationships:
399
399
  control: "internal"
400
400
  foundation: "finish_to_start"
401
401
  origin: "@afokapu/atdd-bun"
402
- reason: "Bun realization of the core obligation coder.design.primitives, checked over .tsx, .jsx, .html and .css"
402
+ reason: "Bun realization of the core obligation coder.design.primitives, checked over .tsx, .jsx, .html, .css and HTML authored in .ts/.mts literals"
403
403
  source_ref: "coder.bun.design-primitives"
404
404
  strength: "important"
405
405
  target_ref: "coder.design.primitives"
@@ -429,7 +429,7 @@ relationships:
429
429
  control: "internal"
430
430
  foundation: "finish_to_start"
431
431
  origin: "@afokapu/atdd-bun"
432
- reason: "Bun realization of the core obligation coder.design.token-color, checked over .tsx, .jsx, .html and .css"
432
+ reason: "Bun realization of the core obligation coder.design.token-color, checked over .tsx, .jsx, .html, .css and HTML authored in .ts/.mts literals"
433
433
  source_ref: "coder.bun.design-token-color"
434
434
  strength: "important"
435
435
  target_ref: "coder.design.token-color"
@@ -439,7 +439,7 @@ relationships:
439
439
  control: "internal"
440
440
  foundation: "finish_to_start"
441
441
  origin: "@afokapu/atdd-bun"
442
- reason: "Bun realization of the core obligation coder.design.token-hardcoded, checked over .tsx, .jsx, .html and .css"
442
+ reason: "Bun realization of the core obligation coder.design.token-hardcoded, checked over .tsx, .jsx, .html, .css and HTML authored in .ts/.mts literals"
443
443
  source_ref: "coder.bun.design-token-hardcoded"
444
444
  strength: "important"
445
445
  target_ref: "coder.design.token-hardcoded"
@@ -92,7 +92,7 @@ relationships:
92
92
  control: "internal"
93
93
  foundation: "finish_to_start"
94
94
  origin: "@afokapu/atdd-bun"
95
- reason: "Bun realization of the core obligation coder.design.primitives, checked over .tsx, .jsx, .html and .css"
95
+ reason: "Bun realization of the core obligation coder.design.primitives, checked over .tsx, .jsx, .html, .css and HTML authored in .ts/.mts literals"
96
96
  source_ref: "coder.bun.design-primitives"
97
97
  strength: "important"
98
98
  target_ref: "coder.design.primitives"
@@ -122,7 +122,7 @@ relationships:
122
122
  control: "internal"
123
123
  foundation: "finish_to_start"
124
124
  origin: "@afokapu/atdd-bun"
125
- reason: "Bun realization of the core obligation coder.design.token-color, checked over .tsx, .jsx, .html and .css"
125
+ reason: "Bun realization of the core obligation coder.design.token-color, checked over .tsx, .jsx, .html, .css and HTML authored in .ts/.mts literals"
126
126
  source_ref: "coder.bun.design-token-color"
127
127
  strength: "important"
128
128
  target_ref: "coder.design.token-color"
@@ -132,7 +132,7 @@ relationships:
132
132
  control: "internal"
133
133
  foundation: "finish_to_start"
134
134
  origin: "@afokapu/atdd-bun"
135
- reason: "Bun realization of the core obligation coder.design.token-hardcoded, checked over .tsx, .jsx, .html and .css"
135
+ reason: "Bun realization of the core obligation coder.design.token-hardcoded, checked over .tsx, .jsx, .html, .css and HTML authored in .ts/.mts literals"
136
136
  source_ref: "coder.bun.design-token-hardcoded"
137
137
  strength: "important"
138
138
  target_ref: "coder.design.token-hardcoded"
@@ -5,16 +5,20 @@ status: active
5
5
  name: App components compose design-system primitives for interactive controls
6
6
  statement: An app component (`.tsx`/`.jsx` outside the design root) MUST render interactive controls through a design-system
7
7
  primitive rather than a raw `<button>`, `<input>`, `<select>`, or `<textarea>`, so controls stay themed, accessible,
8
- and consistent. Bun realization of `coder.design.primitives`, mirroring `coder.vite.design-primitives`.
8
+ and consistent. The same obligation covers controls authored as HTML in the bodies of string, template, and
9
+ tagged-template literals in `.ts`/`.mts` files outside the design root — the shape an htmx/Bun server-rendered
10
+ app writes. Bun realization of `coder.design.primitives`, mirroring `coder.vite.design-primitives`.
9
11
  terms:
10
12
  - term_id: design_root
11
13
  text: 'a directory named `design`, `design_system`, or `design-system`. The first directory beneath it names the
12
14
  layer: `tokens` or `foundations`, `primitives`, `components`, `templates`. A repository with no design root
13
15
  is not judged (self-scoping): there is no system to connect to yet.'
14
16
  - term_id: raw_control
15
- text: a lowercase `<button`, `<input`, `<select`, or `<textarea` element written in app code.
17
+ text: 'a lowercase `<button`, `<input`, `<select`, or `<textarea` element written in app code — in JSX, or in the
18
+ body of a string/template/tagged-template literal in a `.ts`/`.mts` file, followed by whitespace, `>`, or `/`.'
16
19
  content:
17
- summary: Flags raw interactive platform elements in component source outside the design root.
20
+ summary: Flags raw interactive platform elements in component source and in `.ts`/`.mts` literal HTML outside the
21
+ design root.
18
22
  normative_text: Controls are where focus, disabled, error, and loading states live. Each raw control re-implements
19
23
  them, and each re-implementation diverges.
20
24
  fix_hint: |
@@ -38,6 +42,9 @@ content:
38
42
  - Test files (`*.test.*`, `*.spec.*`) and vendored/build directories are never scanned.
39
43
  - The design system's own primitives render the raw elements and are not scanned.
40
44
  - Plain `.html` templates cannot import components and are out of scope.
45
+ - 'Only literal text is judged in `.ts`/`.mts` files: code position (comparisons, angle-bracket type
46
+ assertions), comments, and regex literals are never treated as markup, and a control spanning a `${…}`
47
+ interpolation is read on its literal chunks alone.'
41
48
  metadata:
42
49
  aliases:
43
50
  - BUN-DESIGN-PRIMITIVES-001
@@ -5,8 +5,10 @@ status: active
5
5
  name: UI files use color tokens, not raw color literals
6
6
  statement: Outside the tokens layer, a UI file (`.tsx`, `.jsx`, `.html`, `.htm`, `.css`) MUST NOT write a raw color
7
7
  literal — `#rgb`/`#rrggbb`/`#rrggbbaa`, `rgb()`/`rgba()`, `hsl()`/`hsla()` — in a CSS declaration, a `style` attribute,
8
- a `<style>` block, a JSX `style={{…}}` object, or a `fill`/`stroke`/`bgcolor` attribute. Colors come from tokens
9
- (`var(--…)`). Bun realization of `coder.design.token-color`, mirroring `coder.vite.design-token-color`.
8
+ a `<style>` block, a JSX `style={{…}}` object, or a `fill`/`stroke`/`bgcolor` attribute. The same declarations are
9
+ judged in inline `style="…"` attributes and `<style>` text authored in the HTML a `.ts`/`.mts` file renders from
10
+ string/template/tagged-template literals. Colors come from tokens (`var(--…)`). Bun realization of
11
+ `coder.design.token-color`, mirroring `coder.vite.design-token-color`.
10
12
  terms:
11
13
  - term_id: design_root
12
14
  text: 'a directory named `design`, `design_system`, or `design-system`. The first directory beneath it names the
@@ -16,8 +18,8 @@ terms:
16
18
  text: 'a hex, rgb(a), or hsl(a) color written in a declaration value. Selectors are not values: `#fade:hover {`
17
19
  is never read as a color.'
18
20
  content:
19
- summary: Reads declarations from stylesheets, style attributes, style blocks, and JSX style objects, and flags
20
- raw color literals in their values.
21
+ summary: Reads declarations from stylesheets, style attributes, style blocks, JSX style objects, and `.ts`/`.mts`
22
+ literal HTML, and flags raw color literals in their values.
21
23
  normative_text: A raw color is a theme decision made in one place. It does not follow dark mode, it drifts from
22
24
  the palette, and nobody can find it when the palette changes.
23
25
  fix_hint: |
@@ -42,6 +44,8 @@ content:
42
44
  - 'Custom property definitions (`--danger: #b91c1c`) define tokens wherever they live and are not flagged.'
43
45
  - The tokens/foundations layer is where raw colors are defined and is not scanned.
44
46
  - Named colors (`red`, `white`) and `currentColor`/`transparent` are not flagged.
47
+ - 'Only literal text is judged in `.ts`/`.mts` files: code, comments, and regex literals are never read as
48
+ declarations, and a value spanning a `${…}` interpolation is judged on its literal chunks alone.'
45
49
  metadata:
46
50
  aliases:
47
51
  - BUN-DESIGN-TOKEN-COLOR-001
@@ -6,8 +6,9 @@ name: UI files take spacing, radii, and durations from foundations
6
6
  statement: Outside the tokens layer, a UI file MUST NOT hardcode a spacing, inset, or border-radius length greater
7
7
  than 1px (`margin`, `padding`, `gap`, `inset`, `top`/`right`/`bottom`/`left`, `border-radius`), nor a non-zero
8
8
  duration in `transition`/`animation`. A bare number in a JSX style object for those properties counts as a length.
9
- These values come from foundations tokens. Bun realization of `coder.design.token-hardcoded` and of the raw-pixel
10
- part of `coder.design.foundations`.
9
+ The same declarations are judged in inline `style="…"` attributes and `<style>` text authored in the HTML a
10
+ `.ts`/`.mts` file renders from string/template/tagged-template literals. These values come from foundations
11
+ tokens. Bun realization of `coder.design.token-hardcoded` and of the raw-pixel part of `coder.design.foundations`.
11
12
  terms:
12
13
  - term_id: design_root
13
14
  text: 'a directory named `design`, `design_system`, or `design-system`. The first directory beneath it names the
@@ -43,6 +44,8 @@ content:
43
44
  - 'Custom property definitions (`--space-3: 12px`) define tokens wherever they live and are not flagged.'
44
45
  - The tokens/foundations layer defines these values and is not scanned.
45
46
  - Widths, heights, and font sizes are out of scope for this rule.
47
+ - 'Only literal text is judged in `.ts`/`.mts` files: code, comments, and regex literals are never read as
48
+ declarations, and a value spanning a `${…}` interpolation is judged on its literal chunks alone.'
46
49
  metadata:
47
50
  aliases:
48
51
  - BUN-DESIGN-TOKEN-HARDCODED-001
@@ -71,14 +71,17 @@ export function designTarget(file, specifier) {
71
71
  return d ? { layer: d.layer, layerName: d.layerName, root: d.root, path: t.path } : null;
72
72
  }
73
73
 
74
- export function masked(file) {
74
+ export function masked(file, opts) {
75
75
  const text = readText(file);
76
76
  if (text === null) return null;
77
- return { text, code: extname(file) === ".css" ? text.replace(/\/\*[\s\S]*?\*\//g, (c) => c.replace(/[^\n]/g, " ")) : maskLiteralsAndComments(text) };
77
+ return { text, code: extname(file) === ".css" ? text.replace(/\/\*[\s\S]*?\*\//g, (c) => c.replace(/[^\n]/g, " ")) : maskLiteralsAndComments(text, opts) };
78
78
  }
79
79
 
80
80
  export const isUi = (file) => UI_EXT.has(extname(file));
81
81
  export const isComponentSource = (file) => extname(file) === ".tsx" || extname(file) === ".jsx";
82
+ // `.ts`/`.mts` app files render HTML from string/template/tagged-template literals: the
83
+ // literals-only mask keeps those bodies visible for the design rules that judge rendered markup.
84
+ export const isTsSource = (file) => { const e = extname(file); return e === ".ts" || e === ".mts"; };
82
85
  export const hasDesignRoot = (files) => files.some((file) => designOf(file));
83
86
 
84
87
  const kebab = (prop) => prop.replace(/[A-Z]/g, (c) => "-" + c.toLowerCase());
@@ -1,16 +1,25 @@
1
1
  #!/usr/bin/env bun
2
2
  // Detector: coder.bun.design-primitives
3
3
  // App components (outside the design root) render interactive controls through the
4
- // design-system primitive, not raw <button>/<input>/<select>/<textarea>.
5
- import { readRoots, readExcludes, readText, emit, locate } from "../../../lib/scan.mjs";
6
- import { scope, designOf, isComponentSource, masked } from "./_design.mjs";
4
+ // design-system primitive, not raw <button>/<input>/<select>/<textarea> — including the
5
+ // HTML an app renders from string/template/tagged-template literals in .ts/.mts files,
6
+ // the shape an htmx/Bun server-rendered app actually writes.
7
+ import { readRoots, readExcludes, emit, locate } from "../../../lib/scan.mjs";
8
+ import { scope, designOf, isComponentSource, isTsSource, masked } from "./_design.mjs";
7
9
 
8
10
  const RULE_ID = "coder.bun.design-primitives";
9
11
  const violations = [];
10
12
  for (const file of scope(readRoots(), readExcludes())) {
11
- if (!isComponentSource(file) || designOf(file)) continue;
12
- const m = masked(file);
13
- for (const c of (m?.code ?? "").matchAll(/<(button|input|select|textarea)\b/g)) violations.push({ rule_id: RULE_ID, file, ...locate(m.text, c.index), evidence: `raw <${c[1]}> in app code; compose the design-system primitive instead` });
13
+ if (designOf(file)) continue;
14
+ // Component sources are judged on code with literals masked; .ts/.mts sources on literal
15
+ // bodies with code masked (the keepLiterals mode), so a match is always authored markup.
16
+ const component = isComponentSource(file), literalHtml = !component && isTsSource(file);
17
+ if (!component && !literalHtml) continue;
18
+ const m = masked(file, literalHtml ? { keepLiterals: true } : undefined);
19
+ if (!m) continue;
20
+ const pattern = component ? /<(button|input|select|textarea)\b/g : /<(button|input|select|textarea)(?=[\s/>])/g;
21
+ for (const c of m.code.matchAll(pattern))
22
+ violations.push({ rule_id: RULE_ID, file, ...locate(m.text, c.index), evidence: `raw <${c[1]}> in app code; compose the design-system primitive instead` });
14
23
  }
15
24
  process.stderr.write(`bun-detector[design-primitives]: ${violations.length} violation(s)\n`);
16
25
  emit(violations);
@@ -3,19 +3,23 @@
3
3
  // Outside the tokens layer, UI files (.tsx/.jsx/.html/.css) take colors from tokens
4
4
  // (`var(--…)`), never raw hex, rgb(), or hsl() literals. Defining a custom
5
5
  // property (`--danger: #b91c1c`) is defining a token, not using a raw value.
6
- import { readRoots, readExcludes, readText, emit, locate } from "../../../lib/scan.mjs";
7
- import { scope, designOf, isUi, declarations } from "./_design.mjs";
6
+ // The same declarations are judged in the HTML a .ts/.mts file renders from
7
+ // string/template/tagged-template literals, read through the literals-only mask.
8
+ import { readRoots, readExcludes, emit, locate } from "../../../lib/scan.mjs";
9
+ import { scope, designOf, isUi, isTsSource, masked, declarations } from "./_design.mjs";
8
10
 
9
11
  const RULE_ID = "coder.bun.design-token-color";
10
12
  const COLOR_RE = /#[0-9a-fA-F]{3,8}\b|\b(?:rgba?|hsla?)\s*\(/;
11
13
  const violations = [];
12
14
  for (const file of scope(readRoots(), readExcludes())) {
13
- if (!isUi(file) || designOf(file)?.layer === 0) continue;
14
- const text = readText(file);
15
- for (const d of declarations(file, text ?? "")) {
15
+ const literalHtml = !isUi(file) && isTsSource(file);
16
+ if ((!isUi(file) && !literalHtml) || designOf(file)?.layer === 0) continue;
17
+ const src = masked(file, literalHtml ? { keepLiterals: true } : undefined);
18
+ if (!src) continue;
19
+ for (const d of declarations(file, literalHtml ? src.code : src.text)) {
16
20
  if (d.prop.startsWith("--")) continue;
17
21
  const hit = d.value.match(COLOR_RE);
18
- if (hit) violations.push({ rule_id: RULE_ID, file, ...locate(text, d.index), evidence: `${d.prop} uses the raw color ${hit[0].replace(/\s*\($/, "()")}; reference a color token (var(--…)) instead` });
22
+ if (hit) violations.push({ rule_id: RULE_ID, file, ...locate(src.text, d.index), evidence: `${d.prop} uses the raw color ${hit[0].replace(/\s*\($/, "()")}; reference a color token (var(--…)) instead` });
19
23
  }
20
24
  }
21
25
  process.stderr.write(`bun-detector[design-token-color]: ${violations.length} violation(s)\n`);
@@ -3,8 +3,10 @@
3
3
  // Outside the tokens layer, spacing, radii, and durations come from foundations.
4
4
  // 0 and 1px (hairline borders) are not design decisions and are allowed. Custom
5
5
  // property definitions (`--space-3: 12px`) define tokens and are never judged.
6
- import { readRoots, readExcludes, readText, emit, locate } from "../../../lib/scan.mjs";
7
- import { scope, designOf, isUi, declarations } from "./_design.mjs";
6
+ // The same declarations are judged in the HTML a .ts/.mts file renders from
7
+ // string/template/tagged-template literals, read through the literals-only mask.
8
+ import { readRoots, readExcludes, emit, locate } from "../../../lib/scan.mjs";
9
+ import { scope, designOf, isUi, isTsSource, masked, declarations } from "./_design.mjs";
8
10
 
9
11
  const RULE_ID = "coder.bun.design-token-hardcoded";
10
12
  const LENGTH_PROP = /^(margin|padding|gap|row-gap|column-gap|inset|top|right|bottom|left|border-radius)(-|$)/;
@@ -12,16 +14,18 @@ const DURATION_PROP = /^(transition|animation)(-|$)/;
12
14
  const violations = [];
13
15
  const report = (file, text, d, value) => violations.push({ rule_id: RULE_ID, file, ...locate(text, d.index), evidence: `${d.prop}: ${value} is hardcoded; use a foundations token (var(--…))` });
14
16
  for (const file of scope(readRoots(), readExcludes())) {
15
- if (!isUi(file) || designOf(file)?.layer === 0) continue;
16
- const text = readText(file);
17
- for (const d of declarations(file, text ?? "")) {
17
+ const literalHtml = !isUi(file) && isTsSource(file);
18
+ if ((!isUi(file) && !literalHtml) || designOf(file)?.layer === 0) continue;
19
+ const src = masked(file, literalHtml ? { keepLiterals: true } : undefined);
20
+ if (!src) continue;
21
+ for (const d of declarations(file, literalHtml ? src.code : src.text)) {
18
22
  if (LENGTH_PROP.test(d.prop)) {
19
- if (d.numeric) { if (Math.abs(Number(d.value)) > 1) report(file, text, d, d.value); continue; }
23
+ if (d.numeric) { if (Math.abs(Number(d.value)) > 1) report(file, src.text, d, d.value); continue; }
20
24
  const px = [...d.value.matchAll(/(-?\d*\.?\d+)px\b/g)].find((m) => Math.abs(Number(m[1])) > 1);
21
- if (px) report(file, text, d, px[0]);
25
+ if (px) report(file, src.text, d, px[0]);
22
26
  } else if (DURATION_PROP.test(d.prop)) {
23
27
  const time = [...d.value.matchAll(/(\d*\.?\d+)(ms|s)\b/g)].find((m) => Number(m[1]) > 0);
24
- if (time) report(file, text, d, time[0]);
28
+ if (time) report(file, src.text, d, time[0]);
25
29
  }
26
30
  }
27
31
  }
package/integrity.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
- "version": "0.10.96",
2
+ "version": "0.10.97",
3
3
  "files": {
4
4
  "HOOK_AUDIT.md": "5329d840db37671b1918f688ead26865473b87db73dbc75f7c8b2a8bbe8d6d43",
5
5
  "PLANNER_PORT.md": "fb5935bac8b7ac18994de21e43ace3a5ef8cd55f85b0e3349fca261280054f11",
6
6
  "README.md": "8f0e45595fc10bb6f033b81b67246e57bb3f5bbaf62b35ba950beb5f9f82a938",
7
7
  "bunfig.toml": "b9fc65eca9014c5179380259d70e76385a6a80788fa9a2df5fb3eaa5554fd2fe",
8
8
  "conventions/_profiles/architecture.yaml": "f1808768b720a4e476047e4a0912002ca673946562cea9aeef5d0c214828d93a",
9
- "conventions/_profiles/coder.yaml": "3fb191556a64c9ebcf249516afa189afca24da9b22fd40b2fc66908196cdfb78",
10
- "conventions/_profiles/design.yaml": "25a02a67152d49728ad3517f6510da7285116fa69c56cbda55613a7cfcfd3b89",
9
+ "conventions/_profiles/coder.yaml": "53693363c6623b5b12ece1c746c8cf4f052615310fc5683160d8de8be7d8e0c9",
10
+ "conventions/_profiles/design.yaml": "e76c87d2fbf1c1f1ecc9a24247be93b6915062939636678a9983ec23fe5f7af6",
11
11
  "conventions/_profiles/docs.yaml": "05485c3b32f1757e77c42e331eec1db651cb52ef57fc4e8607bb2f73b056cbb3",
12
12
  "conventions/_profiles/flow.yaml": "ca23ee662bf2fff590fee7a5b06816d720969531510bb35fb4ae3289c2871802",
13
13
  "conventions/_profiles/htmx.yaml": "38fc8b3e1a53429e16977ed63e83e751b203deffe9b338ea171050fb64641559",
@@ -51,9 +51,9 @@
51
51
  "conventions/coder.bun/coder.bun.design-dependency-flow.convention.yaml": "8c99a0293f6a3e527c8aa99b2d5634695627c6daf8e37398fa25667a0e47dbff",
52
52
  "conventions/coder.bun/coder.bun.design-hierarchy-import.convention.yaml": "59ca34fb9c6ec72b6ad7a099a5a8bceaa79a646226cf05eb0bb5c99854804dd2",
53
53
  "conventions/coder.bun/coder.bun.design-orphan-export.convention.yaml": "ca36d04d8cc961e04974f65fd774c2dbfab92fe64846010cdb27fc220fb0d935",
54
- "conventions/coder.bun/coder.bun.design-primitives.convention.yaml": "e54b431ffa6c9f501b3160d49b660590954f0446c43ade9141ac5ebce2adc095",
55
- "conventions/coder.bun/coder.bun.design-token-color.convention.yaml": "cd2270f3e94f958f529aa3e56b79037a87b8eddfb22d9a3244e12fcd32dcda9e",
56
- "conventions/coder.bun/coder.bun.design-token-hardcoded.convention.yaml": "908173a1f715d7f4826855df1b668f9db363fc6e89900a9a764911f55e73c3f8",
54
+ "conventions/coder.bun/coder.bun.design-primitives.convention.yaml": "b32a5bbbcc4f515fee2cb5f545e142f30ff610d87eca0d25d224dad100644282",
55
+ "conventions/coder.bun/coder.bun.design-token-color.convention.yaml": "d0deecd6b7cf6b770af4ce6954a8c9e3470e1040dd2143dd648746ad43d875fb",
56
+ "conventions/coder.bun/coder.bun.design-token-hardcoded.convention.yaml": "c46afb4a4c8babcce0a4ffcf361c1e0181343b8c76b73311f094380fd4285a22",
57
57
  "conventions/coder.bun/coder.bun.design-tokens-pure.convention.yaml": "8f7e768ac3041dc3d3285a03fdcabd0d376695bcfab0233166e107fb2f1419c8",
58
58
  "conventions/coder.bun/coder.bun.design-wagons-import.convention.yaml": "76595759544ce81bf9b0e0ee1d59f7a2f5cc446105697b23a5c545a8939bcb28",
59
59
  "conventions/coder.bun/coder.bun.dto-mapper.convention.yaml": "c524b5f37db6ae4f7558fc3ec672aa1c5b764738a0f25a20062d736fed6bbcb3",
@@ -231,14 +231,14 @@
231
231
  "detectors/bun_clean_architecture_detector/fixtures/dirty/features/billing/integration/client.ts": "51ed50a6489f782fa8d5de2c1c3863bd7554a5918d2f6d26c0f65a86228e482c",
232
232
  "detectors/bun_clean_architecture_detector/fixtures/dirty/features/billing/presentation/api.ts": "109fdfcff0043c1cfea5e8faef029a2398f82cb852c6ab96bfaa113b05c47ece",
233
233
  "detectors/bun_design_system_detector/atdd.implementation.yaml": "3370a481643a736a5309c9ca77f08b89c60a559bbfb898d4c8b64fbe59fc31c6",
234
- "detectors/bun_design_system_detector/checks/_design.mjs": "e39190baa3c7e1daa353c2891c0a7e2fa69dd6ae6d8b685e9b1d09cf8fc0c909",
234
+ "detectors/bun_design_system_detector/checks/_design.mjs": "a05659748126f8bddb567ec2cda4afc8f5647e42ca488f5874436af861396842",
235
235
  "detectors/bun_design_system_detector/checks/_map.json": "564138c6a771f052023ec93f3c47832fd5e7511c5b13f6a40a09c25ccc3c4fb5",
236
236
  "detectors/bun_design_system_detector/checks/design_connected.mjs": "ff7976f22efe5957a3c8b6c29b8c950b5877336ab3870a232b1e42d49d97060c",
237
237
  "detectors/bun_design_system_detector/checks/design_dependency_flow.mjs": "159121d5a158b50dcf0c585153adb94c2207e9b07ae05b1eb78cd5ffc9cf7027",
238
238
  "detectors/bun_design_system_detector/checks/design_orphan_export.mjs": "655da3f5592f6e8e6719c01532acf2424da6a3fcf255891d7dd52483cc6b17ce",
239
- "detectors/bun_design_system_detector/checks/design_primitives.mjs": "825daa3e19033ccb7224eae4f1f1656c5c9e87293d8729fe612415ae4fbda52e",
240
- "detectors/bun_design_system_detector/checks/design_token_color.mjs": "aaed884142185f55d101016904b93635dc3d7f657bb7894487a419e264cb1b72",
241
- "detectors/bun_design_system_detector/checks/design_token_hardcoded.mjs": "d5c800bacbb7eeb80e0cbc016e08bff99b4f6940b3e8704f19534daf2d58920f",
239
+ "detectors/bun_design_system_detector/checks/design_primitives.mjs": "bc534e1b6b01c9157f91f9f32bbef1be059fba0f3a6e604b82464ff4c7cc7142",
240
+ "detectors/bun_design_system_detector/checks/design_token_color.mjs": "6624e87b6f496219ed6649e296e1782d74b5837a3437e6539bbefb82b8f295cd",
241
+ "detectors/bun_design_system_detector/checks/design_token_hardcoded.mjs": "1698b5c2ab10d669a3d8bd44190b92c6ebd73367b9f92c2dda73d2a79d85ffd6",
242
242
  "detectors/bun_design_system_detector/checks/design_tokens_pure.mjs": "9fd668df42c7a6a7d7949bb5975ba3c6925abcb908d626a573f56800f96e32d9",
243
243
  "detectors/bun_design_system_detector/checks/design_wagons_import.mjs": "5cbd9776bcc3defdd4f28cbc228b3164ef1a694c64c86b151a1cd67f9687dd21",
244
244
  "detectors/bun_design_system_detector/detect.mjs": "f8eb9cda3e35b8a808614a9655fd80574e506d1a438fcc15e68c0b7fdd833dcc",
@@ -1035,7 +1035,7 @@
1035
1035
  "lib/imports.mjs": "3db4979269488fa26f6e7aefded6ece9c646be6587a10e249821a5a208109962",
1036
1036
  "lib/interlocking.mjs": "d0803d080ac7d7477c51be70112df1e85213d339fd3c6b71f75f26145fa8accd",
1037
1037
  "lib/journey-chain.mjs": "bdafc9cc3da4ade644aebacc6e1015e29285b764465588d764b7c581bade9025",
1038
- "lib/scan.mjs": "02b0fa864cab24157a8f27b50a87a2bb66a875f90cf6632c753c4627d61456ef",
1038
+ "lib/scan.mjs": "b6973e411ecd14c548a055c871e01e948f002b772042136be8401f38d998e687",
1039
1039
  "planner-nodes/ENFORCEMENT_SCOPE.yaml": "d8ec7039c219857f3d77af5d4d84612b533b69c1a5fcef935fbf46470adafed4",
1040
1040
  "planner-nodes/nodes/planner.acceptance.abstract-fields-required.convention.yaml": "bd565693f0ae861f0561ad2f7a91a8c55f9a209c3acd59c5750cfcffd96a85d8",
1041
1041
  "planner-nodes/nodes/planner.acceptance.authoring-guidelines.convention.yaml": "16348dceed5868041b832bde766e9c8d4a950d4032f1f3066b357644081a3b17",
@@ -1255,7 +1255,7 @@
1255
1255
  "planner-schemas/train.schema.json": "d6fbac9067c1bffeb84eb79a71228441055af6e6e7ba141dd4e0bcb079345ec0",
1256
1256
  "planner-schemas/wagon.schema.json": "12353e46d2216d2deef754615b629a696bd8a7bb35326379e7ef2b221a5ece3a",
1257
1257
  "planner-schemas/wmbt.schema.json": "7a3a5693bfcf01340667c2be4a3c48e74f34b1af7e8dc13372c0de06b7f4fe12",
1258
- "relationships.yaml": "5860a308ebc3ee7fa8172fc2c6633984000ab3003f0ae4b6fa28db48879eda22",
1258
+ "relationships.yaml": "fccaf745b383fe527b7db9022233037bdf5b5cc3d495bb40da3cca4746f5e241",
1259
1259
  "src/agent.ts": "6d6c6e75908af8fbab13432f0001b0374bb25cf3dee46ba218dfd67e0090cb56",
1260
1260
  "src/ci.ts": "b5c57dd87fc780b2b272156b68830d14e695a1a28300dec46a06f71864e0c59e",
1261
1261
  "src/cli.ts": "d93c3aebb78e752fd96347a5b177c0ed0697010c6e2533e116de93e772cd65a8",
package/lib/scan.mjs CHANGED
@@ -132,6 +132,29 @@ function regexMayStart(text, i) {
132
132
  return false;
133
133
  }
134
134
 
135
+ // The index just past the `${` substitution opening at `i` (text[i] === "$", text[i+1] === "{").
136
+ // A `${ … }` substitution is code: it may hold strings, braces and templates of its own
137
+ // (escaped backticks included), so the substitution ends only at the matching `}` outside them.
138
+ function substitutionEnd(text, i) {
139
+ const n = text.length;
140
+ let depth = 1;
141
+ let j = i + 2;
142
+ while (j < n && depth > 0) {
143
+ const d = text[j];
144
+ if (d === "`") { j = templateEnd(text, j); continue; }
145
+ if (d === '"' || d === "'") {
146
+ let k = j + 1;
147
+ while (k < n && text[k] !== d && text[k] !== "\n") k += text[k] === "\\" ? 2 : 1;
148
+ j = k + 1;
149
+ continue;
150
+ }
151
+ if (d === "{") depth++;
152
+ else if (d === "}") depth--;
153
+ j++;
154
+ }
155
+ return j;
156
+ }
157
+
135
158
  // The index just past the template literal opening at `start`. A `${ … }` substitution is code: it may hold strings,
136
159
  // braces and templates of its own (escaped backticks included), so the template ends only at a backtick outside them.
137
160
  function templateEnd(text, start) {
@@ -141,30 +164,39 @@ function templateEnd(text, start) {
141
164
  const c = text[j];
142
165
  if (c === "\\") { j += 2; continue; }
143
166
  if (c === "`") return j + 1;
144
- if (c === "$" && text[j + 1] === "{") {
145
- let depth = 1;
146
- j += 2;
147
- while (j < n && depth > 0) {
148
- const d = text[j];
149
- if (d === "`") { j = templateEnd(text, j); continue; }
150
- if (d === '"' || d === "'") {
151
- let k = j + 1;
152
- while (k < n && text[k] !== d && text[k] !== "\n") k += text[k] === "\\" ? 2 : 1;
153
- j = k + 1;
154
- continue;
155
- }
156
- if (d === "{") depth++;
157
- else if (d === "}") depth--;
158
- j++;
159
- }
160
- continue;
161
- }
167
+ if (c === "$" && text[j + 1] === "{") { j = substitutionEnd(text, j); continue; }
162
168
  j++;
163
169
  }
164
170
  return n;
165
171
  }
166
172
 
167
- export function maskLiteralsAndComments(text) {
173
+ // Inside the template literal spanning [from, to): keep the literal text (already in `out`),
174
+ // blank the `${` / `}` delimiters, and mask the substitution code by the same rule — a string
175
+ // or template of its own inside the substitution is still a literal body, and stays kept.
176
+ function maskTemplateLiterals(text, out, from, to, blank) {
177
+ let j = from;
178
+ while (j < to) {
179
+ if (text[j] === "\\") { j += 2; continue; }
180
+ if (text[j] !== "$" || text[j + 1] !== "{") { j++; continue; }
181
+ const k = Math.min(substitutionEnd(text, j), to); // just past the closing `}`
182
+ const body = j + 2, end = k - 1;
183
+ blank(j, body);
184
+ if (end > body) out.splice(body, end - body, ...maskLiteralsAndComments(text.slice(body, end), KEEP_LITERALS).split(""));
185
+ blank(end, k);
186
+ j = k;
187
+ }
188
+ }
189
+
190
+ // Mask string literals, template literals and comments with spaces of equal
191
+ // length, preserving every line and column offset. A check that greps raw source
192
+ // otherwise fires on the rule's own name inside a comment or a doc string — the
193
+ // classic detector false positive.
194
+ // With `keepLiterals` the payload inverts: literal BODIES stay while code, comments and
195
+ // regex literals are blanked — the mode for checks whose subject is the HTML a `.ts` file
196
+ // renders from string/template/tagged-template literals, so a match can only ever come
197
+ // from markup an author wrote in a literal.
198
+ const KEEP_LITERALS = { keepLiterals: true };
199
+ export function maskLiteralsAndComments(text, { keepLiterals = false } = {}) {
168
200
  const out = text.split("");
169
201
  let i = 0;
170
202
  const n = text.length;
@@ -199,7 +231,8 @@ export function maskLiteralsAndComments(text) {
199
231
  i = j + 1;
200
232
  } else if (ch === "`") {
201
233
  const j = templateEnd(text, i);
202
- blank(i + 1, j - 1 >= i + 1 ? j - 1 : i + 1);
234
+ if (keepLiterals) maskTemplateLiterals(text, out, i + 1, j - 1 >= i + 1 ? j - 1 : i + 1, blank);
235
+ else blank(i + 1, j - 1 >= i + 1 ? j - 1 : i + 1);
203
236
  i = j;
204
237
  } else if (ch === '"' || ch === "'") {
205
238
  let j = i + 1;
@@ -208,9 +241,10 @@ export function maskLiteralsAndComments(text) {
208
241
  if (text[j] === ch) { j++; break; }
209
242
  j++;
210
243
  }
211
- blank(i + 1, j - 1 >= i + 1 ? j - 1 : i + 1);
244
+ if (!keepLiterals) blank(i + 1, j - 1 >= i + 1 ? j - 1 : i + 1);
212
245
  i = j;
213
246
  } else {
247
+ if (keepLiterals) blank(i, i + 1);
214
248
  i++;
215
249
  }
216
250
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@afokapu/atdd-bun",
3
- "version": "0.10.96",
3
+ "version": "0.10.97",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/afokapu/atdd-bun.git"
@@ -4413,7 +4413,7 @@ edges:
4413
4413
  constraint: mandatory
4414
4414
  control: internal
4415
4415
  foundation: finish_to_start
4416
- reason: "Bun realization of the core obligation coder.design.token-color, checked over .tsx, .jsx, .html and .css"
4416
+ reason: "Bun realization of the core obligation coder.design.token-color, checked over .tsx, .jsx, .html, .css and HTML authored in .ts/.mts literals"
4417
4417
  source_ref: coder.bun.design-token-color
4418
4418
  strength: important
4419
4419
  target_ref: coder.design.token-color
@@ -4423,7 +4423,7 @@ edges:
4423
4423
  constraint: mandatory
4424
4424
  control: internal
4425
4425
  foundation: finish_to_start
4426
- reason: "Bun realization of the core obligation coder.design.token-hardcoded, checked over .tsx, .jsx, .html and .css"
4426
+ reason: "Bun realization of the core obligation coder.design.token-hardcoded, checked over .tsx, .jsx, .html, .css and HTML authored in .ts/.mts literals"
4427
4427
  source_ref: coder.bun.design-token-hardcoded
4428
4428
  strength: important
4429
4429
  target_ref: coder.design.token-hardcoded
@@ -4433,7 +4433,7 @@ edges:
4433
4433
  constraint: mandatory
4434
4434
  control: internal
4435
4435
  foundation: finish_to_start
4436
- reason: "Bun realization of the core obligation coder.design.primitives, checked over .tsx, .jsx, .html and .css"
4436
+ reason: "Bun realization of the core obligation coder.design.primitives, checked over .tsx, .jsx, .html, .css and HTML authored in .ts/.mts literals"
4437
4437
  source_ref: coder.bun.design-primitives
4438
4438
  strength: important
4439
4439
  target_ref: coder.design.primitives