@motion-proto/live-tokens 0.78.0 → 0.80.0

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.
Files changed (172) hide show
  1. package/.claude/skills/live-tokens-check-compliance/SKILL.md +49 -38
  2. package/.claude/skills/live-tokens-create-component/SKILL.md +23 -28
  3. package/.claude/skills/live-tokens-create-component/references/contract-tests.md +61 -0
  4. package/.claude/skills/live-tokens-create-component/references/sketch-mode.md +2 -2
  5. package/.claude/skills/live-tokens-create-component/references/token-naming.md +6 -15
  6. package/.claude/skills/live-tokens-create-page/SKILL.md +6 -4
  7. package/.claude/skills/live-tokens-create-theme/references/design-directions.md +1 -1
  8. package/.claude/skills/live-tokens-pick-component/SKILL.md +3 -3
  9. package/.claude/skills/live-tokens-set-colors/references/color-anchors.md +1 -1
  10. package/.claude/skills/live-tokens-set-geometry/SKILL.md +1 -1
  11. package/.claude/skills/live-tokens-set-geometry/references/geometry-anchors.md +1 -1
  12. package/CHANGELOG.md +271 -0
  13. package/README.md +10 -16
  14. package/bin/check-component.mjs +154 -551
  15. package/bin/check-page.mjs +57 -541
  16. package/bin/cli.mjs +93 -16
  17. package/bin/contractRunner.mjs +37 -91
  18. package/bin/lib/buildChecks.mjs +32 -0
  19. package/bin/lib/catalogue.mjs +161 -34
  20. package/bin/lib/componentSource.mjs +152 -0
  21. package/bin/lib/cssValues.mjs +9 -0
  22. package/bin/lib/dataDir.mjs +126 -0
  23. package/bin/lib/findings.mjs +103 -12
  24. package/bin/lib/fixers.mjs +64 -0
  25. package/bin/lib/geometry.mjs +92 -0
  26. package/bin/lib/pageSource.mjs +230 -0
  27. package/bin/lib/report.mjs +57 -59
  28. package/bin/lib/tokenVocabulary.mjs +104 -34
  29. package/bin/migrate-build-script.mjs +66 -0
  30. package/bin/migrate.mjs +5 -0
  31. package/bin/rules/componentStructure.mjs +344 -0
  32. package/bin/rules/componentUse.mjs +313 -0
  33. package/bin/rules/importsAndRoutes.mjs +136 -0
  34. package/bin/rules/testRuns.mjs +122 -0
  35. package/bin/rules/tokens.mjs +426 -0
  36. package/bin/setup-claude.mjs +1 -2
  37. package/dist-plugin/{chunk-PDNL4NC5.js → chunk-D4WRIKEZ.js} +7 -2
  38. package/dist-plugin/{chunk-SWXRVZKT.js → chunk-REBHE3ZM.js} +414 -1
  39. package/dist-plugin/index.cjs +470 -19
  40. package/dist-plugin/index.d.cts +1 -0
  41. package/dist-plugin/index.d.ts +1 -0
  42. package/dist-plugin/index.js +87 -55
  43. package/dist-plugin/migrateData/index.cjs +422 -4
  44. package/dist-plugin/migrateData/index.js +2 -2
  45. package/dist-plugin/setColors/index.cjs +414 -1
  46. package/dist-plugin/setColors/index.d.cts +1 -1
  47. package/dist-plugin/setColors/index.d.ts +1 -1
  48. package/dist-plugin/setColors/index.js +1 -1
  49. package/dist-plugin/setGeometry/index.cjs +423 -13
  50. package/dist-plugin/setGeometry/index.d.cts +3 -3
  51. package/dist-plugin/setGeometry/index.d.ts +3 -3
  52. package/dist-plugin/setGeometry/index.js +10 -13
  53. package/dist-plugin/setType/index.d.cts +1 -1
  54. package/dist-plugin/setType/index.d.ts +1 -1
  55. package/dist-plugin/{themeTypes-BxRtuN5V.d.cts → themeTypes-B8_Idrp4.d.cts} +2 -2
  56. package/dist-plugin/{themeTypes-BxRtuN5V.d.ts → themeTypes-B8_Idrp4.d.ts} +2 -2
  57. package/package.json +2 -2
  58. package/src/editor/component-editor/CalloutEditor.svelte +2 -2
  59. package/src/editor/component-editor/CollapsibleSectionEditor.svelte +14 -15
  60. package/src/editor/component-editor/CornerBadgeEditor.svelte +14 -14
  61. package/src/editor/component-editor/DialogEditor.svelte +5 -5
  62. package/src/editor/component-editor/InlineEditActionsEditor.svelte +2 -2
  63. package/src/editor/component-editor/RadioButtonEditor.svelte +21 -21
  64. package/src/editor/component-editor/SectionDividerEditor.svelte +7 -7
  65. package/src/editor/component-editor/SegmentedControlEditor.svelte +5 -5
  66. package/src/editor/component-editor/SideNavigationEditor.svelte +25 -25
  67. package/src/editor/component-editor/TabBarEditor.svelte +6 -6
  68. package/src/editor/component-editor/TableEditor.svelte +6 -6
  69. package/src/editor/component-editor/ToggleEditor.svelte +2 -2
  70. package/src/editor/component-editor/index.ts +3 -0
  71. package/src/editor/component-editor/registry.ts +57 -1
  72. package/src/editor/component-editor/scaffolding/TokenLayout.svelte +14 -14
  73. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +3 -0
  74. package/src/editor/component-editor/scaffolding/types.ts +15 -0
  75. package/src/editor/core/components/adjustAliases.ts +4 -4
  76. package/src/editor/core/components/aliasKinds.ts +20 -19
  77. package/src/editor/core/sketch/sketchLayer.ts +3 -3
  78. package/src/editor/core/themes/migrateComponentConfig.ts +14 -6
  79. package/src/editor/core/themes/migrations/2026-09-13-badge-brand.ts +42 -0
  80. package/src/editor/core/themes/migrations/2026-09-13-collapsiblesection-open.ts +33 -0
  81. package/src/editor/core/themes/migrations/2026-09-13-cornerbadge-prefix.ts +70 -0
  82. package/src/editor/core/themes/migrations/2026-09-13-hairline.ts +92 -0
  83. package/src/editor/core/themes/migrations/2026-09-13-indicator.ts +54 -0
  84. package/src/editor/core/themes/migrations/2026-09-13-sectiondivider-surface.ts +36 -0
  85. package/src/editor/core/themes/migrations/2026-09-13-selected-state.ts +124 -0
  86. package/src/editor/core/themes/migrations/2026-09-13-toggle-label.ts +31 -0
  87. package/src/editor/core/themes/migrations/index.ts +16 -0
  88. package/src/editor/core/themes/themeService.ts +3 -3
  89. package/src/editor/core/themes/themeTypes.ts +13 -15
  90. package/src/editor/docs/Docs.svelte +1 -1
  91. package/src/editor/docs/content/light-and-dark.md +3 -3
  92. package/src/editor/docs/content.generated.ts +1 -1
  93. package/src/editor/index.ts +1 -0
  94. package/src/editor/overlay/LiveEditorOverlay.svelte +15 -0
  95. package/src/editor/skill-atlas/SkillAtlas.svelte +4 -4
  96. package/src/editor/skill-atlas/TreeNodeCard.svelte +4 -4
  97. package/src/editor/skill-atlas/skillSources.generated.ts +11 -14
  98. package/src/editor/skill-atlas/skillTrees.ts +1 -3
  99. package/src/editor/skill-atlas/trees/check-compliance.ts +37 -149
  100. package/src/editor/skill-atlas/trees/create-component.ts +62 -64
  101. package/src/editor/skill-atlas/trees/create-page.ts +38 -17
  102. package/src/editor/skill-atlas/trees/pick-component.ts +3 -3
  103. package/src/editor/skill-atlas/trees/set-geometry.ts +1 -1
  104. package/src/editor/ui/UIPaletteSelector.svelte +11 -15
  105. package/src/editor/ui/variantScales.ts +8 -8
  106. package/src/live-tokens/data/themes/autumn.json +188 -188
  107. package/src/live-tokens/data/themes/halloween.json +188 -188
  108. package/src/live-tokens/data/themes/midnight-study.json +245 -245
  109. package/src/live-tokens/data/themes/ocean.json +188 -188
  110. package/src/live-tokens/data/themes/royal-velvet.json +188 -188
  111. package/src/live-tokens/data/themes/sketchy.json +188 -188
  112. package/src/live-tokens/data/themes/spring-meadow.json +188 -188
  113. package/src/live-tokens/data/themes/sunset.json +188 -188
  114. package/src/system/components/Badge.svelte +27 -23
  115. package/src/system/components/Button.svelte +13 -7
  116. package/src/system/components/Callout.svelte +16 -11
  117. package/src/system/components/Card.svelte +22 -15
  118. package/src/system/components/CodeSnippet.svelte +10 -6
  119. package/src/system/components/CollapsibleSection.svelte +81 -76
  120. package/src/system/components/CornerBadge.svelte +78 -72
  121. package/src/system/components/Dialog.svelte +21 -18
  122. package/src/system/components/IconButton.svelte +13 -9
  123. package/src/system/components/Image.svelte +14 -8
  124. package/src/system/components/ImageLightbox.svelte +10 -6
  125. package/src/system/components/InlineEditActions.svelte +17 -14
  126. package/src/system/components/Input.svelte +13 -7
  127. package/src/system/components/MenuSelect.svelte +13 -7
  128. package/src/system/components/Notification.svelte +17 -11
  129. package/src/system/components/Panel.svelte +13 -6
  130. package/src/system/components/ProgressBar.svelte +10 -5
  131. package/src/system/components/RadioButton.svelte +33 -30
  132. package/src/system/components/SectionDivider.svelte +28 -21
  133. package/src/system/components/SegmentedControl.svelte +27 -23
  134. package/src/system/components/SideNavigation.svelte +175 -171
  135. package/src/system/components/Slider.svelte +11 -7
  136. package/src/system/components/TabBar.svelte +53 -49
  137. package/src/system/components/Table.svelte +20 -15
  138. package/src/system/components/Toggle.svelte +14 -10
  139. package/src/system/components/Tooltip.svelte +10 -6
  140. package/src/system/styles/CONVENTIONS.md +3 -4
  141. package/src/testing-js/chunk-3UKGXCDL.js +48 -0
  142. package/src/testing-js/chunk-3UKGXCDL.js.map +1 -0
  143. package/src/testing-js/{chunk-FAFOAWYL.js → chunk-Q3YIAAG3.js} +17 -3
  144. package/src/testing-js/chunk-Q3YIAAG3.js.map +1 -0
  145. package/src/testing-js/{chunk-GNIUPIU2.js → chunk-U7OJE5DU.js} +18 -18
  146. package/src/testing-js/chunk-U7OJE5DU.js.map +1 -0
  147. package/src/testing-js/{chunk-4JQX6WWL.js → chunk-ZMZQZ33J.js} +474 -166
  148. package/src/testing-js/chunk-ZMZQZ33J.js.map +1 -0
  149. package/src/testing-js/component-behavior.contract.js +155 -0
  150. package/src/testing-js/component-behavior.contract.js.map +1 -0
  151. package/src/testing-js/component-editor.contract.js +6 -4
  152. package/src/testing-js/component-editor.contract.js.map +1 -1
  153. package/src/testing-js/component-render.contract.js +14 -10
  154. package/src/testing-js/component-render.contract.js.map +1 -1
  155. package/src/testing-js/index.d.ts +44 -4
  156. package/src/testing-js/index.js +13 -7
  157. package/src/testing-js/index.js.map +1 -1
  158. package/src/testing-js/page-compliance.contract.js +48 -10
  159. package/src/testing-js/page-compliance.contract.js.map +1 -1
  160. package/src/testing-js/registry.contract.js +5 -3
  161. package/src/testing-js/registry.contract.js.map +1 -1
  162. package/src/testing-js/{vitest-C-wNWcoA.d.ts → vitest-BMLIbDs2.d.ts} +8 -2
  163. package/src/testing-js/vitest.d.ts +1 -1
  164. package/src/testing-js/vitest.js +2 -1
  165. package/template/package.json +1 -2
  166. package/template/vite.config.ts +3 -2
  167. package/.claude/skills/live-tokens-create-component/SKILL copy.md +0 -196
  168. package/.claude/skills/live-tokens-fix-findings/SKILL.md +0 -105
  169. package/src/editor/skill-atlas/trees/fix-findings.ts +0 -504
  170. package/src/testing-js/chunk-4JQX6WWL.js.map +0 -1
  171. package/src/testing-js/chunk-FAFOAWYL.js.map +0 -1
  172. package/src/testing-js/chunk-GNIUPIU2.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../testing/page-compliance.contract.ts","../editor/ui/sections/textStyles.ts","../editor/core/palettes/contrast.ts","../testing/support/pageHarness.ts"],"sourcesContent":["import { test } from '@playwright/test';\nimport { TEXT_STYLES } from '../editor/ui/sections/textStyles';\nimport { allContracts } from './contracts';\nimport {\n PageHarness,\n pageTargets,\n pageViewports,\n restingPaintSpec,\n type ContractPaintSpec,\n} from './support/pageHarness';\n\nconst targets = pageTargets();\nconst viewports = pageViewports();\n\nconst bundles = TEXT_STYLES.map((style) => ({ name: style.name, prefix: style.prefix }));\n\nasync function paintSpecs(): Promise<ContractPaintSpec[]> {\n const contracts = await allContracts();\n return contracts\n .map((contract) => restingPaintSpec(contract))\n .filter((spec): spec is ContractPaintSpec => spec !== null);\n}\n\nasync function componentRoots(): Promise<string[]> {\n const contracts = await allContracts();\n return contracts\n .map((contract) => contract.parts[contract.root])\n .filter((declared): declared is string => typeof declared === 'string');\n}\n\nfor (const target of targets) {\n for (const viewport of viewports) {\n const at = `${viewport.width}x${viewport.height}`;\n\n test(`page-component-paint | ${target.source} | ${at}`, async ({ page }) => {\n const specs = await paintSpecs();\n const harness = await PageHarness.open(page, target, viewport);\n const inapplicable = await harness.assertComponentPaint(specs);\n test.skip(inapplicable !== null, inapplicable ?? '');\n });\n\n test(`page-text-style | ${target.source} | ${at}`, async ({ page }) => {\n const roots = await componentRoots();\n const harness = await PageHarness.open(page, target, viewport);\n const inapplicable = await harness.assertTextStyle(bundles, roots);\n test.skip(inapplicable !== null, inapplicable ?? '');\n });\n\n test(`page-contrast | ${target.source} | ${at}`, async ({ page }) => {\n const roots = await componentRoots();\n const harness = await PageHarness.open(page, target, viewport);\n const inapplicable = await harness.assertContrast(roots);\n test.skip(inapplicable !== null, inapplicable ?? '');\n });\n\n test(`page-grid | ${target.source} | ${at}`, async ({ page }) => {\n const harness = await PageHarness.open(page, target, viewport);\n const inapplicable = await harness.assertGrid();\n test.skip(inapplicable !== null, inapplicable ?? '');\n });\n\n test(`page-overflow | ${target.source} | ${at}`, async ({ page }) => {\n const specs = await paintSpecs();\n const harness = await PageHarness.open(page, target, viewport);\n const inapplicable = await harness.assertOverflow(specs);\n test.skip(inapplicable !== null, inapplicable ?? '');\n });\n }\n}\n","/**\n * Registry of the semantic text styles rendered by TextStylesSection.\n * Each style is a bundle of alias tokens declared in tokens.css; the prefix\n * joins with a kind suffix (`-font-family`, `-font-size`, …) to form each\n * axis variable the editor's pickers target.\n *\n * Family/size/weight/letter-spacing/line-height are editable on every style.\n * `hasTextTransform` marks the one style (eyebrow) that also exposes a\n * text-transform picker — the only axis that exists on just one style.\n */\n\nexport interface TextStyle {\n name: string;\n label: string;\n /** Variable prefix, e.g. `--heading-xl`; suffixes form each axis var. */\n prefix: string;\n /** Element (or class) this style is the default for. */\n defaultElement: string;\n preview: string;\n /** Whether this style exposes an editable `-text-transform` axis. */\n hasTextTransform?: boolean;\n}\n\nexport const TEXT_STYLES: TextStyle[] = [\n {\n name: 'heading-xl',\n label: 'Heading XL',\n prefix: '--heading-xl',\n defaultElement: 'h1',\n preview: 'Page title',\n },\n {\n name: 'heading-lg',\n label: 'Heading LG',\n prefix: '--heading-lg',\n defaultElement: 'h2',\n preview: 'Section heading',\n },\n {\n name: 'heading-md',\n label: 'Heading MD',\n prefix: '--heading-md',\n defaultElement: 'h3',\n preview: 'Subsection heading',\n },\n {\n name: 'heading-sm',\n label: 'Heading SM',\n prefix: '--heading-sm',\n defaultElement: 'h4',\n preview: 'Minor heading',\n },\n {\n name: 'body-md',\n label: 'Body MD',\n prefix: '--body-md',\n defaultElement: 'p',\n preview: 'Body copy for comfortable reading.',\n },\n {\n name: 'body-sm',\n label: 'Body SM',\n prefix: '--body-sm',\n defaultElement: 'small',\n preview: 'Captions and secondary text.',\n },\n {\n name: 'editorial-xl',\n label: 'Editorial XL',\n prefix: '--editorial-xl',\n defaultElement: 'editorial-xl',\n preview: 'Pull quotes and opening statements.',\n },\n {\n name: 'editorial-lg',\n label: 'Editorial LG',\n prefix: '--editorial-lg',\n defaultElement: 'editorial-lg',\n preview: 'Standfirsts and section ledes.',\n },\n {\n name: 'editorial-md',\n label: 'Editorial MD',\n prefix: '--editorial-md',\n defaultElement: 'editorial-md',\n preview: 'Long-form reading, set in the editorial face.',\n },\n {\n name: 'editorial-sm',\n label: 'Editorial SM',\n prefix: '--editorial-sm',\n defaultElement: 'editorial-sm',\n preview: 'Captions, credits, and asides.',\n },\n {\n name: 'code',\n label: 'Code',\n prefix: '--code',\n defaultElement: 'code',\n preview: 'const total = sum(items);',\n },\n {\n name: 'eyebrow',\n label: 'Eyebrow',\n prefix: '--eyebrow',\n defaultElement: 'eyebrow',\n preview: 'Overline label',\n hasTextTransform: true,\n },\n];\n","// WCAG 2.1 contrast math + an OKLCH-lightness solver.\n//\n// The solver is the engine behind the \"Derive accessible text\" action: given a\n// surface hex and a target ratio, it finds the lightness (at fixed hue) whose\n// gamut-clamped color clears the ratio. Contrast is monotonic in L only on one\n// side of the surface's own lightness, so `direction` selects the branch.\n\nimport { hexToOklch, oklchToHex, gamutClamp } from './oklch';\n\nexport const AA_BODY = 4.5;\nexport const AA_LARGE = 3.0;\n\nfunction linearizeChannel(v8: number): number {\n const s = v8 / 255;\n return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);\n}\n\nexport function relativeLuminance(hex: string): number {\n const r = linearizeChannel(parseInt(hex.slice(1, 3), 16));\n const g = linearizeChannel(parseInt(hex.slice(3, 5), 16));\n const b = linearizeChannel(parseInt(hex.slice(5, 7), 16));\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n}\n\nexport function contrastRatio(a: string, b: string): number {\n const la = relativeLuminance(a);\n const lb = relativeLuminance(b);\n const hi = Math.max(la, lb);\n const lo = Math.min(la, lb);\n return (hi + 0.05) / (lo + 0.05);\n}\n\nexport interface FindLOptions {\n against: string;\n ratio: number;\n direction: 'lighter' | 'darker';\n c: number;\n h: number;\n margin?: number;\n /** Reachable-L window. The Text derivation multiplies seed L by a curve\n * factor clamped to [0,2], so a family can only reach L ∈ [0, min(1,2·seedL)].\n * The solver passes that ceiling as `lMax` so the returned L is realisable. */\n lMin?: number;\n lMax?: number;\n}\n\nexport interface FindLResult {\n l: number;\n c: number;\n hex: string;\n}\n\n/**\n * Binary-search OKLCH lightness for a color that clears `ratio` against\n * `against`, staying on the `direction` side of the surface (the monotonic\n * branch). If the ratio is unreachable at chroma `c` within the window, decay\n * chroma toward 0 and retry — achromatic extremes reach the full 1..21 range.\n * The result is re-verified with `contrastRatio` after the hex round-trip and\n * nudged one step if 8-bit quantization ate the margin (Global invariant 8).\n */\nexport function findLForContrast(opts: FindLOptions): FindLResult {\n const { against, ratio, direction, c, h } = opts;\n const margin = opts.margin ?? 0.05;\n const lMin = opts.lMin ?? 0;\n const lMax = opts.lMax ?? 1;\n const target = ratio + margin;\n const againstL = hexToOklch(against).l;\n\n const evalAt = (l: number, cc: number) => {\n const g = gamutClamp(l, cc, h);\n const hex = oklchToHex(g.l, g.c, g.h);\n return { hex, chroma: g.c, ratio: contrastRatio(hex, against) };\n };\n\n // Returns the boundary solution at a fixed chroma, or null if `target` is\n // unreachable within the window at that chroma. `extreme` is the window end\n // with the most contrast (top L for lighter, bottom L for darker).\n const solveAtChroma = (cc: number): { l: number; hex: string; chroma: number } | null => {\n const lighter = direction === 'lighter';\n const lo0 = lighter ? Math.max(lMin, againstL) : lMin;\n const hi0 = lighter ? lMax : Math.min(lMax, againstL);\n if (lo0 >= hi0) return null; // no room to move to the requested side within the window\n const extreme = lighter ? hi0 : lo0;\n if (evalAt(extreme, cc).ratio < target) return null;\n let lo = lo0;\n let hi = hi0;\n for (let i = 0; i < 24; i++) {\n const mid = (lo + hi) / 2;\n const meets = evalAt(mid, cc).ratio >= target;\n // Contrast rises toward `extreme`; keep the half that still meets target.\n if (lighter ? meets : !meets) hi = mid;\n else lo = mid;\n }\n const at = lighter ? hi : lo;\n const e = evalAt(at, cc);\n return { l: at, hex: e.hex, chroma: e.chroma };\n };\n\n let sol = solveAtChroma(c);\n if (!sol) {\n if (!solveAtChroma(0)) {\n // Even achromatic can't reach the target within the window — return the\n // extreme (best effort); the caller reports it as unmet.\n const extremeL = direction === 'lighter' ? lMax : lMin;\n const e = evalAt(extremeL, 0);\n return { l: extremeL, c: 0, hex: e.hex };\n }\n let lo = 0;\n let hi = c;\n for (let i = 0; i < 24; i++) {\n const mid = (lo + hi) / 2;\n if (solveAtChroma(mid)) lo = mid;\n else hi = mid;\n }\n sol = solveAtChroma(lo)!;\n }\n\n let { l, hex, chroma } = sol;\n const step = direction === 'lighter' ? 0.004 : -0.004;\n for (let k = 0; k < 12 && contrastRatio(hex, against) < ratio; k++) {\n l = Math.min(lMax, Math.max(lMin, l + step));\n const g = gamutClamp(l, chroma, h);\n l = g.l;\n chroma = g.c;\n hex = oklchToHex(g.l, g.c, g.h);\n }\n return { l, c: chroma, hex };\n}\n","import type { ElementHandle, Page } from '@playwright/test';\nimport {\n DEFAULT_PAGE_VIEWPORTS,\n PAGES_ENV,\n PAGE_VIEWPORTS_ENV,\n type PageViewport,\n} from '../config';\nimport { AA_BODY, AA_LARGE, contrastRatio } from '../../editor/core/palettes/contrast';\nimport { isInapplicable, type ComponentContract, type PaintMap } from '../componentContract';\n\nexport type PageRule =\n | 'page-component-paint'\n | 'page-text-style'\n | 'page-contrast'\n | 'page-grid'\n | 'page-overflow';\n\n/**\n * A failed obligation on a rendered page, carrying the rule id the CLI reports\n * it under and the page file line the finding anchors on.\n */\nexport class PageViolation extends Error {\n constructor(\n readonly rule: PageRule,\n readonly source: string,\n readonly line: number,\n message: string,\n ) {\n super(`[${rule}] ${source}:${line}: ${message}`);\n this.name = 'PageViolation';\n }\n}\n\nexport interface PageTarget {\n /** Page file the finding anchors on, relative to the project root. */\n source: string;\n route: string;\n}\n\n/** The wrapper `LiveTokensRouter` renders every consumer page inside. */\nconst PAGE_CONTAINER = '[data-live-tokens-page]';\n\n/** The router's own chrome: the editor overlay and the column guides. Inside\n * the container and never part of the page. */\nconst CHROME = '[data-live-tokens-chrome]';\n\nexport function pageTargets(): PageTarget[] {\n const raw = process.env[PAGES_ENV];\n if (!raw) return [];\n return JSON.parse(raw) as PageTarget[];\n}\n\nexport function pageViewports(): PageViewport[] {\n const raw = process.env[PAGE_VIEWPORTS_ENV];\n if (!raw) return DEFAULT_PAGE_VIEWPORTS;\n return JSON.parse(raw) as PageViewport[];\n}\n\n/**\n * A state a resting instance on a page is not in. The component contracts key\n * their paint maps by the editor's own tab labels, which name interaction\n * states (hover, focused), component states (disabled, selected, error, on),\n * and views that only exist once something is opened (an active tab, a menu\n * and its options). Everything else — a bare label, `base`, `default`, and the\n * structural part labels (Header, Body, Footer, ...) — paints at rest.\n */\nconst TRANSIENT_STATE = /\\b(?:hover|active|disabled|focused|error|selected|open|menu|option|on)\\b/;\n\nfunction restingState(label: string | undefined): boolean {\n return label === undefined || !TRANSIENT_STATE.test(label.toLowerCase());\n}\n\ninterface PaintCheck {\n part: string;\n /** Null for the contract's own root part, which is the instance itself. */\n selector: string | null;\n pseudo: string | null;\n css: string;\n variable: string;\n}\n\ninterface PaintEntry {\n /** The contract's own variant label, lowercased, as the finding names it. */\n variant: string | null;\n /** Source of the RegExp an instance's class tokens are tested against. Null\n * for an entry every instance is in. */\n pattern: string | null;\n checks: PaintCheck[];\n}\n\n/**\n * A class token names a variant when it is the variant's own word or carries\n * it as a suffix: the three spellings the shipped components use are bare\n * (`button primary`), component-prefixed (`badge badge-primary`), and\n * axis-prefixed (`es-root variant-divider`). A contract's variant label is the\n * editor's prose (`With Divider`), so each of its words is a key as well as\n * the whole label, which is what reaches the `divider` the markup spells.\n */\nfunction variantPattern(label: string | undefined | null): string | null {\n if (!label) return null;\n const words = label.toLowerCase().split(/\\s+/);\n const keys = [...new Set([words.join('-'), ...words])]\n .map((key) => key.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'));\n return `(?:^|-)(?:${keys.join('|')})$`;\n}\n\nexport interface ContractPaintSpec {\n id: string;\n root: string;\n entries: PaintEntry[];\n}\n\nfunction paintChecks(contract: ComponentContract, map: PaintMap): PaintCheck[] {\n const checks: PaintCheck[] = [];\n for (const [part, properties] of Object.entries(map)) {\n const declared = contract.parts[part];\n if (declared === undefined) continue;\n const locator = typeof declared === 'string' ? { selector: declared } : declared;\n // A portalled part is rendered by an interaction, so no resting page\n // instance has one.\n if (typeof declared !== 'string' && declared.portal) continue;\n for (const [css, variable] of Object.entries(properties)) {\n checks.push({\n part,\n selector: part === contract.root ? null : locator.selector,\n pseudo: (typeof declared === 'string' ? undefined : declared.pseudo) ?? null,\n css,\n variable,\n });\n }\n }\n return checks;\n}\n\n/**\n * What a contract obliges of an instance sitting at rest on a page: the paint\n * maps that need no state tab, no editor control, and no interaction. A\n * variant-keyed entry carries the pattern its instances' root classes have to\n * name.\n */\nexport function restingPaintSpec(contract: ComponentContract): ContractPaintSpec | null {\n const rootSelector = contract.parts[contract.root];\n if (typeof rootSelector !== 'string') return null;\n const entries: PaintEntry[] = [];\n // `contract.view` opens the component editor: its `setup` drives preview\n // controls no page has and its `state` names a tab. Only `variant` carries\n // onto a page, so an entry inherits that and nothing else.\n const inherited = contract.view ?? {};\n for (const expectation of contract.properties) {\n if ((expectation.setup ?? []).length > 0) continue;\n if (!restingState(expectation.state)) continue;\n const checks = paintChecks(contract, expectation.paints);\n if (checks.length === 0) continue;\n const variant = (expectation.variant ?? inherited.variant)?.toLowerCase() ?? null;\n entries.push({ variant, pattern: variantPattern(variant), checks });\n }\n // A component whose only resting paint map hangs off a state tab still\n // paints its default state on a page.\n if (!isInapplicable(contract.states)) {\n for (const state of contract.states) {\n if (!state.paints || !restingState(state.state)) continue;\n if ((state.setup ?? []).length > 0) continue;\n const checks = paintChecks(contract, state.paints);\n if (checks.length === 0) continue;\n const variant = (state.variant ?? inherited.variant)?.toLowerCase() ?? null;\n entries.push({ variant, pattern: variantPattern(variant), checks });\n }\n }\n if (entries.length === 0) return null;\n return { id: contract.id, root: rootSelector, entries };\n}\n\nexport interface PaintFailure {\n id: string;\n variant: string | null;\n line: number;\n part: string;\n css: string;\n variable: string;\n actual: string;\n expected: string;\n}\n\nexport interface UncoveredInstance {\n id: string;\n line: number;\n /** The variants the contract offers, none of which this instance's root\n * classes name. */\n variants: string[];\n}\n\nexport interface PaintObservation {\n instances: number;\n asserted: number;\n failures: PaintFailure[];\n /** Instances every variant-keyed entry passed over: decision 6's exception,\n * reported per instance rather than silently passed. */\n uncovered: UncoveredInstance[];\n}\n\nexport interface TextObservation {\n elements: number;\n failures: { line: number; tag: string; nearest: string; axis: string; actual: string; expected: string }[];\n}\n\nexport interface TextBundle {\n name: string;\n prefix: string;\n}\n\nexport interface ContrastPair {\n line: number;\n tag: string;\n /** Computed text colour, composited over the surface when translucent. */\n color: string;\n background: string;\n colorToken: string | null;\n backgroundToken: string | null;\n fontSize: number;\n fontWeight: number;\n}\n\nexport interface ContrastObservation {\n pairs: ContrastPair[];\n /** Why a run of text carries no pair, counted by reason. */\n skipped: Record<string, number>;\n}\n\nexport interface GridChildFailure {\n line: number;\n tag: string;\n edge: 'left' | 'right';\n /** Distance from the nearest track edge, in px. */\n off: number;\n}\n\nexport interface GridObservation {\n grids: number;\n children: number;\n failures: GridChildFailure[];\n /** The page's own outermost element, which a missing grid anchors on. */\n pageLine: number;\n}\n\nexport interface OverflowFailure {\n line: number;\n tag: string;\n kind: 'document' | 'element' | 'instance';\n detail: string;\n}\n\nexport interface OverflowObservation {\n elements: number;\n failures: OverflowFailure[];\n}\n\nconst TEXT_AXES = ['fontFamily', 'fontSize', 'fontWeight', 'lineHeight', 'letterSpacing'] as const;\n\n/** Displays that make an element a block of its own. Text sitting directly in\n * anything else is a run inside a line, and the line's own block owns it. */\nconst BLOCK_DISPLAYS = ['block', 'flow-root', 'list-item', 'flex', 'grid', 'table-cell', 'table-caption'];\n\n/** Sub-pixel track positions and a browser's own rounding put an edge that is\n * on the line up to a pixel off it. */\nconst GRID_TOLERANCE = 1;\n\n/** Below this the page is one column, so the grid rule has nothing to hold a\n * section to. */\nconst GRID_VIEWPORT = 768;\n\n/** WCAG's large-text sizes: the AA floor drops to 3:1 at either. */\nconst LARGE_TEXT_PX = 24;\nconst LARGE_BOLD_PX = 18.66;\nconst BOLD = 700;\n\n/** Findings name CSS properties as a page's own stylesheet spells them. */\nconst cssName = (camel: string) => camel.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);\n\n/** The line the finding anchors on, the rest named in the message, and what\n * the rule looked at to find them: one rerun after each repair walks the\n * whole list. */\nfunction report<T>(failures: T[], scope: string, describe: (failure: T) => string): string {\n const lines = failures.map(describe);\n return lines.length === 1 ? lines[0] : `${lines.length} of ${scope}\\n${lines.join('\\n')}`;\n}\n\nfunction hex(rgb: string): string {\n const [r, g, b] = rgb.match(/\\d+/g)!.map(Number);\n return `#${[r, g, b].map((c) => c.toString(16).padStart(2, '0')).join('')}`;\n}\n\n/** The AA floor the pair has to clear, which its own size and weight set. */\nfunction aaFloor(pair: ContrastPair): number {\n const large = pair.fontSize >= LARGE_TEXT_PX\n || (pair.fontSize >= LARGE_BOLD_PX && pair.fontWeight >= BOLD);\n return large ? AA_LARGE : AA_BODY;\n}\n\n/** A reason reads as prose: `a gradient (2), a blend mode (1)`. */\nfunction reasons(skipped: Record<string, number>): string {\n return Object.entries(skipped).map(([reason, count]) => `${reason} (${count})`).join(', ');\n}\n\n/** The page under test, and what the rules read off it. */\nexport class PageHarness {\n private constructor(\n readonly page: Page,\n readonly target: PageTarget,\n readonly viewport: PageViewport,\n ) {}\n\n static async open(page: Page, target: PageTarget, viewport: PageViewport): Promise<PageHarness> {\n await installPageProbe(page);\n await page.setViewportSize(viewport);\n await page.goto(target.route);\n await page.locator(PAGE_CONTAINER).waitFor();\n // The lazy route module, then the theme's own custom properties: a page\n // measured before either lands reads the browser's defaults as the\n // theme's values.\n await page.waitForFunction((selectors) => {\n const container = document.querySelector(selectors.container);\n if (!container) return false;\n const content = [...container.children].some((child) => !child.matches(selectors.chrome));\n const themed = getComputedStyle(document.documentElement)\n .getPropertyValue('--body-md-font-size').trim().length > 0;\n return content && themed;\n }, { container: PAGE_CONTAINER, chrome: CHROME });\n await page.waitForLoadState('networkidle');\n await page.evaluate(async () => {\n await document.fonts.ready;\n const frame = () => new Promise<void>((resolve) => requestAnimationFrame(() => resolve()));\n await frame();\n await frame();\n });\n return new PageHarness(page, target, viewport);\n }\n\n fail(rule: PageRule, line: number, message: string): never {\n throw new PageViolation(rule, this.target.source, line, message);\n }\n\n /** Every shipped instance on the page, as the contract root selectors find\n * them, with the variant its own root classes name. */\n async instances(specs: ContractPaintSpec[]): Promise<{ id: string; variant: string | null; line: number }[]> {\n return this.page.evaluate(({ specs: list, container, chrome, source }) => {\n const found: { id: string; variant: string | null; line: number }[] = [];\n const root = document.querySelector(container);\n if (!root) return found;\n for (const spec of list) {\n const keyed: { variant: string | null; pattern: RegExp }[] = [];\n for (const entry of spec.entries) {\n if (entry.pattern !== null) keyed.push({ variant: entry.variant, pattern: new RegExp(entry.pattern) });\n }\n for (const element of root.querySelectorAll(spec.root)) {\n if (element.closest(chrome)) continue;\n const classes = [...element.classList];\n const matched = keyed.find(({ pattern }) => classes.some((name) => pattern.test(name)));\n found.push({\n id: spec.id,\n variant: matched?.variant ?? null,\n line: window.__liveTokensPageLine(element, source),\n });\n }\n }\n return found;\n }, { specs, container: PAGE_CONTAINER, chrome: CHROME, source: this.target.source });\n }\n\n /**\n * Every element that renders text of its own: block-level, inside the page\n * container, outside the router's chrome, and outside every shipped\n * component root, whose slot typography the component owns.\n */\n async textElements(componentRoots: string[]): Promise<{ line: number; tag: string; axes: Record<string, string> }[]> {\n return this.page.evaluate(({ roots, container, chrome, source, axes, displays }) => {\n const found: { line: number; tag: string; axes: Record<string, string> }[] = [];\n const root = document.querySelector(container);\n if (!root) return found;\n const inComponent = roots.join(', ');\n for (const element of root.querySelectorAll<HTMLElement>('*')) {\n if (element.closest(chrome)) continue;\n if (inComponent && element.closest(inComponent)) continue;\n const ownText = [...element.childNodes]\n .some((node) => node.nodeType === Node.TEXT_NODE && (node.textContent ?? '').trim().length > 0);\n if (!ownText) continue;\n const style = getComputedStyle(element);\n if (!displays.includes(style.display)) continue;\n found.push({\n line: window.__liveTokensPageLine(element, source),\n tag: element.tagName.toLowerCase(),\n axes: Object.fromEntries(axes.map((axis) => [axis, (style as unknown as Record<string, string>)[axis] ?? ''])),\n });\n }\n return found;\n }, {\n roots: componentRoots,\n container: PAGE_CONTAINER,\n chrome: CHROME,\n source: this.target.source,\n axes: [...TEXT_AXES],\n displays: BLOCK_DISPLAYS,\n });\n }\n\n /** The page file line the element was written on, from Svelte's dev-build\n * element metadata. */\n async lineOf(element: ElementHandle<Element>): Promise<number> {\n return element.evaluate((node, source) => window.__liveTokensPageLine(node, source), this.target.source);\n }\n\n /** Every resting paint obligation, measured on the instances themselves. */\n async observePaints(specs: ContractPaintSpec[]): Promise<PaintObservation> {\n return this.page.evaluate(({ specs: list, container, chrome, source }) => {\n const failures: PaintObservation['failures'] = [];\n const uncovered: UncoveredInstance[] = [];\n let instances = 0;\n let asserted = 0;\n const root = document.querySelector(container);\n if (!root) return { instances, asserted, failures, uncovered };\n\n // The value a CSS property takes from the raw token, measured beside the\n // part so inherited font size and colour resolve the same way. A token\n // holding `#fff` and a computed `rgb(255, 255, 255)` are the same paint,\n // and only the browser can say so.\n //\n // The part's own font size is seeded onto the probe first: a unitless\n // line height and an `em` letter spacing resolve against it, and a\n // component that sets its own font size (every Button does) makes the\n // parent's the wrong ruler. A `font-size` token overwrites the seed and\n // still resolves its own relative units against the parent, as it must.\n const normalize = (node: Element, css: string, raw: string): string => {\n const probe = document.createElement('div');\n probe.style.display = 'none';\n // A border width computes to 0 while the border style is `none`, so\n // the probe would answer 0px for every stroke thickness.\n probe.style.borderStyle = 'solid';\n probe.style.outlineStyle = 'solid';\n probe.style.fontSize = getComputedStyle(node).fontSize;\n (node.parentElement ?? document.body).appendChild(probe);\n probe.style.setProperty(css.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`), raw);\n const computed = (getComputedStyle(probe) as unknown as Record<string, string>)[css];\n probe.remove();\n return (computed ?? '').trim();\n };\n\n for (const spec of list) {\n const patterns = spec.entries.map((entry) => (entry.pattern === null ? null : new RegExp(entry.pattern)));\n const variants = [...new Set(spec.entries.map((entry) => entry.variant).filter((v): v is string => v !== null))];\n for (const element of root.querySelectorAll(spec.root)) {\n if (element.closest(chrome)) continue;\n instances++;\n const classes = [...element.classList];\n const line = window.__liveTokensPageLine(element, source);\n let covered = false;\n for (const [index, entry] of spec.entries.entries()) {\n const pattern = patterns[index];\n if (pattern && !classes.some((name) => pattern.test(name))) continue;\n covered = true;\n for (const check of entry.checks) {\n const part = check.selector === null ? element : element.querySelector(check.selector);\n if (!part) continue;\n const style = getComputedStyle(part, check.pseudo ?? undefined);\n const token = style.getPropertyValue(check.variable).trim();\n if (!token) continue;\n const expected = normalize(part, check.css, token);\n const actual = ((style as unknown as Record<string, string>)[check.css] ?? '').trim();\n asserted++;\n if (actual !== expected) {\n failures.push({\n id: spec.id,\n variant: entry.variant,\n line,\n part: check.part,\n css: check.css,\n variable: check.variable,\n actual,\n expected,\n });\n }\n }\n }\n // One Badge naming its variant says nothing about the next one, so\n // decision 6's exception is counted per instance.\n if (!covered) uncovered.push({ id: spec.id, line, variants });\n }\n }\n return { instances, asserted, failures, uncovered };\n }, { specs, container: PAGE_CONTAINER, chrome: CHROME, source: this.target.source });\n }\n\n /** Every run of text on the page, against the theme's own style bundles as\n * they resolve at this viewport. */\n async observeTextStyles(bundles: TextBundle[], componentRoots: string[]): Promise<TextObservation> {\n const elements = await this.textElements(componentRoots);\n const expected = await this.page.evaluate(({ list, axes }) => {\n const style = getComputedStyle(document.documentElement);\n const probe = document.createElement('div');\n probe.style.position = 'absolute';\n probe.style.visibility = 'hidden';\n document.body.appendChild(probe);\n const resolved: Record<string, Record<string, string>> = {};\n for (const bundle of list) {\n // One probe per bundle, carrying all five axes at once: a unitless\n // line height and an `em` letter spacing resolve against the bundle's\n // own font size, so five separately measured values would not be the\n // bundle. The reset clears an axis the previous bundle set.\n probe.style.cssText = 'position:absolute;visibility:hidden';\n for (const axis of axes) {\n probe.style.setProperty(\n axis.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`),\n style.getPropertyValue(`${bundle.prefix}-${axis.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)}`).trim(),\n );\n }\n const computed = getComputedStyle(probe) as unknown as Record<string, string>;\n resolved[bundle.name] = Object.fromEntries(axes.map((axis) => [axis, (computed[axis] ?? '').trim()]));\n }\n probe.remove();\n return resolved;\n }, { list: bundles, axes: [...TEXT_AXES] });\n\n const failures: TextObservation['failures'] = [];\n for (const element of elements) {\n let best = { name: '', misses: [] as string[], distance: Number.POSITIVE_INFINITY };\n for (const bundle of bundles) {\n const misses: string[] = TEXT_AXES.filter((axis) => element.axes[axis] !== expected[bundle.name][axis]);\n if (misses.length === 0) { best = { name: bundle.name, misses: [], distance: 0 }; break; }\n // Family and size are what identify a bundle by eye, so a bundle that\n // matches both and misses a weight is nearer than one that misses the\n // face, even on the same count.\n const distance = misses.length\n + (misses.includes('fontFamily') ? 0.4 : 0)\n + (misses.includes('fontSize') ? 0.2 : 0);\n if (distance < best.distance) best = { name: bundle.name, misses, distance };\n }\n if (best.misses.length === 0) continue;\n const axis = best.misses[0];\n failures.push({\n line: element.line,\n tag: element.tag,\n nearest: best.name,\n axis,\n actual: element.axes[axis],\n expected: expected[best.name][axis],\n });\n }\n return { elements: elements.length, failures };\n }\n\n /**\n * Every text and surface pair the page composes, with the tokens whose\n * resolved values match them. The ratio itself is computed by the caller\n * from the editor's own WCAG helper, so one implementation answers for the\n * palette editor and for a page.\n */\n async observeContrast(componentRoots: string[]): Promise<ContrastObservation> {\n return this.page.evaluate(({ roots, container, chrome, source, displays }) => {\n const pairs: ContrastPair[] = [];\n const skipped: Record<string, number> = {};\n const skip = (reason: string) => { skipped[reason] = (skipped[reason] ?? 0) + 1; };\n const root = document.querySelector(container);\n if (!root) return { pairs, skipped };\n\n // The theme states its colours in `oklch()`, which Chromium keeps in the\n // computed value, so no string parse reaches the channels. A 1x1 canvas\n // in `copy` mode answers with the pixel the screen shows, gamut-clamped\n // the same way, for any colour syntax including a future one. An invalid\n // or `transparent` value leaves the cleared pixel, which reads as alpha 0\n // and is what \"paints nothing here\" means.\n const canvas = document.createElement('canvas');\n canvas.width = 1;\n canvas.height = 1;\n const ctx = canvas.getContext('2d', { willReadFrequently: true })!;\n ctx.globalCompositeOperation = 'copy';\n const rgba = (value: string): [number, number, number, number] => {\n ctx.fillStyle = 'rgba(0, 0, 0, 0)';\n ctx.fillStyle = value;\n ctx.fillRect(0, 0, 1, 1);\n const [r, g, b, a] = ctx.getImageData(0, 0, 1, 1).data;\n return [r, g, b, a / 255];\n };\n const key = ([r, g, b]: [number, number, number, number]) => `${r},${g},${b}`;\n const css = (c: [number, number, number, number]) =>\n (c[3] === 1 ? `rgb(${c[0]}, ${c[1]}, ${c[2]})` : `rgba(${c[0]}, ${c[1]}, ${c[2]}, ${c[3]})`);\n\n // A finding names the token when one resolves to the colour it measured.\n const probe = document.createElement('div');\n probe.style.display = 'none';\n document.body.appendChild(probe);\n const named = new Map<string, string>();\n const rootStyle = getComputedStyle(document.documentElement);\n for (const name of rootStyle) {\n if (!name.startsWith('--')) continue;\n probe.style.color = '';\n probe.style.color = `var(${name})`;\n const resolved = getComputedStyle(probe).color;\n if (!resolved) continue;\n const colour = rgba(resolved);\n if (colour[3] === 0) continue;\n if (!named.has(key(colour))) named.set(key(colour), name);\n }\n probe.remove();\n\n const over = (\n front: [number, number, number, number],\n back: [number, number, number, number],\n ): [number, number, number, number] => [\n Math.round(front[0] * front[3] + back[0] * (1 - front[3])),\n Math.round(front[1] * front[3] + back[1] * (1 - front[3])),\n Math.round(front[2] * front[3] + back[2] * (1 - front[3])),\n 1,\n ];\n\n const inComponent = roots.join(', ');\n for (const element of root.querySelectorAll<HTMLElement>('*')) {\n if (element.closest(chrome)) continue;\n if (inComponent && element.closest(inComponent)) continue;\n const ownText = [...element.childNodes]\n .some((node) => node.nodeType === Node.TEXT_NODE && (node.textContent ?? '').trim().length > 0);\n if (!ownText) continue;\n const style = getComputedStyle(element);\n if (!displays.includes(style.display)) continue;\n if (style.visibility !== 'visible') continue;\n const colour = rgba(style.color);\n if (colour[3] === 0) continue;\n\n let surface: [number, number, number, number] | null = null;\n let reason: string | null = null;\n for (let node: Element | null = element; node; node = node.parentElement) {\n const behind = getComputedStyle(node);\n if (behind.mixBlendMode !== 'normal') { reason = 'a blend mode'; break; }\n if (behind.backgroundImage !== 'none') { reason = 'a gradient or an image behind the text'; break; }\n const paint = rgba(behind.backgroundColor);\n if (paint[3] === 1) { surface = paint; break; }\n if (paint[3] > 0) { reason = 'a translucent surface'; break; }\n }\n if (!surface) {\n skip(reason ?? 'no opaque surface behind the text');\n continue;\n }\n pairs.push({\n line: window.__liveTokensPageLine(element, source),\n tag: element.tagName.toLowerCase(),\n color: css(colour[3] === 1 ? colour : over(colour, surface)),\n background: css(surface),\n colorToken: named.get(key(colour[3] === 1 ? colour : over(colour, surface))) ?? null,\n backgroundToken: named.get(key(surface)) ?? null,\n fontSize: parseFloat(style.fontSize),\n fontWeight: parseInt(style.fontWeight, 10) || 400,\n });\n }\n return { pairs, skipped };\n }, {\n roots: componentRoots,\n container: PAGE_CONTAINER,\n chrome: CHROME,\n source: this.target.source,\n displays: BLOCK_DISPLAYS,\n });\n }\n\n /** Where each section of the page sits against the column grid it draws. */\n async observeGrid(): Promise<GridObservation> {\n return this.page.evaluate(({ container, chrome, source, tolerance }) => {\n const failures: GridChildFailure[] = [];\n let grids = 0;\n let children = 0;\n const root = document.querySelector(container);\n if (!root) return { grids, children, failures, pageLine: 1 };\n const own = [...root.children].find((child) => !child.matches(chrome));\n const pageLine = own ? window.__liveTokensPageLine(own, source) : 1;\n\n const columns = parseInt(\n getComputedStyle(document.documentElement).getPropertyValue('--columns-count').trim(),\n 10,\n );\n if (!columns) return { grids, children, failures, pageLine };\n\n for (const grid of root.querySelectorAll('*')) {\n if (grid.closest(chrome)) continue;\n const style = getComputedStyle(grid);\n const tracks = style.gridTemplateColumns.split(/\\s+/).map(parseFloat);\n if (tracks.length !== columns || tracks.some((track) => !Number.isFinite(track))) continue;\n grids++;\n const box = grid.getBoundingClientRect();\n const gap = parseFloat(style.columnGap) || 0;\n let offset = box.left + parseFloat(style.borderLeftWidth) + parseFloat(style.paddingLeft);\n const lines: number[] = [];\n for (const track of tracks) {\n lines.push(offset);\n offset += track;\n lines.push(offset);\n offset += gap;\n }\n const nearest = (edge: number) =>\n lines.reduce((best, line) => (Math.abs(line - edge) < Math.abs(best - edge) ? line : best), lines[0]);\n\n const items = getComputedStyle(grid).justifyItems;\n for (const child of grid.children) {\n if (child.matches(chrome)) continue;\n const kid = getComputedStyle(child);\n if (kid.display === 'none' || kid.display === 'contents') continue;\n // Out of flow: the grid places its containing block, not the box.\n if (kid.position === 'absolute' || kid.position === 'fixed') continue;\n // The border box, which is the edge the eye reads. A margin that\n // insets a stretched section moves that edge off the line, and the\n // finding is the same one a reader would raise.\n const { left, right } = child.getBoundingClientRect();\n children++;\n // Self-alignment is the grid's own way of insetting a box in the\n // area it placed: a centred section is still on the grid, and only\n // the edge its alignment pins has to land on a line. A margin, a\n // width, or a transform is not the grid's vocabulary, so a stretched\n // item answers for both edges.\n const align = kid.justifySelf === 'auto' ? items : kid.justifySelf;\n const centred = align === 'center';\n const pinned: ('left' | 'right')[] = centred ? []\n : align === 'start' || align === 'flex-start' || align === 'left' ? ['left']\n : align === 'end' || align === 'flex-end' || align === 'right' ? ['right']\n : ['left', 'right'];\n if (centred) {\n const before = left - Math.max(...lines.filter((line) => line <= left + tolerance), lines[0]);\n const after = Math.min(...lines.filter((line) => line >= right - tolerance), lines[lines.length - 1]) - right;\n if (Math.abs(before - after) > tolerance) {\n failures.push({\n line: window.__liveTokensPageLine(child, source),\n tag: child.tagName.toLowerCase(),\n edge: before > after ? 'left' : 'right',\n off: Math.round((before - after) * 10) / 10,\n });\n }\n continue;\n }\n for (const edge of pinned) {\n const at = edge === 'left' ? left : right;\n const off = at - nearest(at);\n if (Math.abs(off) <= tolerance) continue;\n failures.push({\n line: window.__liveTokensPageLine(child, source),\n tag: child.tagName.toLowerCase(),\n edge,\n off: Math.round(off * 10) / 10,\n });\n }\n }\n }\n return { grids, children, failures, pageLine };\n }, { container: PAGE_CONTAINER, chrome: CHROME, source: this.target.source, tolerance: GRID_TOLERANCE });\n }\n\n /** What the page pushes past the viewport, past its own container, or past\n * the box that clips it. */\n async observeOverflow(specs: ContractPaintSpec[]): Promise<OverflowObservation> {\n return this.page.evaluate(({ specs: list, container, chrome, source, tolerance }) => {\n const failures: OverflowFailure[] = [];\n let elements = 0;\n const root = document.querySelector(container);\n if (!root) return { elements, failures };\n const own = [...root.children].find((child) => !child.matches(chrome));\n const pageLine = own ? window.__liveTokensPageLine(own, source) : 1;\n\n const page = document.documentElement;\n if (page.scrollWidth > window.innerWidth + tolerance) {\n failures.push({\n line: pageLine,\n tag: 'html',\n kind: 'document',\n detail: `the document scrolls to ${page.scrollWidth}px at a ${window.innerWidth}px viewport`,\n });\n }\n\n for (const element of root.querySelectorAll('*')) {\n if (element.closest(chrome)) continue;\n const style = getComputedStyle(element);\n if (style.display === 'none' || style.display === 'contents') continue;\n // An inline box reports 0 for both, so every one of them would read as\n // overflowing its own zero width.\n if (element.clientWidth === 0) continue;\n elements++;\n if (style.overflowX === 'auto' || style.overflowX === 'scroll') continue;\n if (element.scrollWidth > element.clientWidth + tolerance) {\n failures.push({\n line: window.__liveTokensPageLine(element, source),\n tag: element.tagName.toLowerCase(),\n kind: 'element',\n detail: `<${element.tagName.toLowerCase()}> holds ${element.scrollWidth}px of content in `\n + `${element.clientWidth}px, and its overflow-x is ${style.overflowX}`,\n });\n }\n }\n\n const clips = (style: CSSStyleDeclaration) =>\n style.overflowX !== 'visible' || style.overflowY !== 'visible';\n for (const spec of list) {\n for (const instance of root.querySelectorAll(spec.root)) {\n if (instance.closest(chrome)) continue;\n let clipper: Element | null = null;\n for (let node = instance.parentElement; node; node = node.parentElement) {\n if (clips(getComputedStyle(node))) { clipper = node; break; }\n }\n if (!clipper) continue;\n const box = instance.getBoundingClientRect();\n const bounds = clipper.getBoundingClientRect();\n const past = [\n box.left < bounds.left - tolerance ? `${Math.round(bounds.left - box.left)}px past the left edge` : null,\n box.right > bounds.right + tolerance ? `${Math.round(box.right - bounds.right)}px past the right edge` : null,\n ].filter((side): side is string => side !== null);\n if (past.length === 0) continue;\n failures.push({\n line: window.__liveTokensPageLine(instance, source),\n tag: spec.id,\n kind: 'instance',\n detail: `${spec.id} sits ${past.join(' and ')} of the `\n + `<${clipper.tagName.toLowerCase()}> that clips it`,\n });\n }\n }\n return { elements, failures };\n }, { specs, container: PAGE_CONTAINER, chrome: CHROME, source: this.target.source, tolerance: 1 });\n }\n\n /**\n * Every rule reports the same three ways: it throws a `PageViolation` the\n * runner turns into a finding, returns a reason the run records as\n * `inapplicable`, or returns null, which is the pass. The suite files hold\n * no rule of their own so the defect fixtures measure what a consumer runs.\n */\n async assertComponentPaint(specs: ContractPaintSpec[]): Promise<string | null> {\n const observed = await this.observePaints(specs);\n if (observed.instances === 0) return `${this.target.source} renders no shipped component`;\n if (observed.failures.length > 0) {\n this.fail(\n 'page-component-paint',\n observed.failures[0].line,\n report(observed.failures, `${observed.asserted} contracted paints`, (failure) =>\n `line ${failure.line}: ${failure.id}${failure.variant ? ` (${failure.variant})` : ''} `\n + `paints ${failure.part} ${cssName(failure.css)}: ${failure.actual}, `\n + `but ${failure.variable} resolves to ${failure.expected}`),\n );\n }\n // A page holding an instance the rule cannot place in a variant is a page\n // the rule did not prove.\n if (observed.uncovered.length > 0) {\n return `${this.target.source}: no entry names the variant of `\n + observed.uncovered\n .map((instance) => `${instance.id} at line ${instance.line}, which offers ${instance.variants.join(', ')}`)\n .join('; ');\n }\n if (observed.asserted === 0) {\n return `no contracted part of a shipped instance is rendered on ${this.target.source}`;\n }\n return null;\n }\n\n async assertTextStyle(bundles: TextBundle[], componentRoots: string[]): Promise<string | null> {\n const observed = await this.observeTextStyles(bundles, componentRoots);\n if (observed.elements === 0) return `${this.target.source} renders no text outside a shipped component`;\n if (observed.failures.length > 0) {\n this.fail(\n 'page-text-style',\n observed.failures[0].line,\n report(observed.failures, `${observed.elements} runs of text`, (failure) =>\n `line ${failure.line}: <${failure.tag}> is in no shipped text style. `\n + `Nearest is ${failure.nearest}: its ${cssName(failure.axis)} is ${failure.expected}, `\n + `the element's is ${failure.actual}`),\n );\n }\n return null;\n }\n\n async assertContrast(componentRoots: string[]): Promise<string | null> {\n const observed = await this.observeContrast(componentRoots);\n const failures = observed.pairs\n .map((pair) => ({ pair, ratio: contrastRatio(hex(pair.color), hex(pair.background)), floor: aaFloor(pair) }))\n .filter(({ ratio, floor }) => ratio < floor);\n if (failures.length > 0) {\n const names = (colour: string, token: string | null) => (token ? `${token} (${colour})` : colour);\n this.fail(\n 'page-contrast',\n failures[0].pair.line,\n report(failures, `${observed.pairs.length} text and surface pairs`, ({ pair, ratio, floor }) =>\n `line ${pair.line}: <${pair.tag}> at ${pair.fontSize}px/${pair.fontWeight} sets `\n + `${names(pair.color, pair.colorToken)} on ${names(pair.background, pair.backgroundToken)}, `\n + `a ratio of ${ratio.toFixed(2)} against the ${floor} AA floor`),\n );\n }\n if (observed.pairs.length === 0) {\n const why = reasons(observed.skipped);\n return why\n ? `no text on ${this.target.source} sits on a surface the rule can read: ${why}`\n : `${this.target.source} renders no text outside a shipped component`;\n }\n return null;\n }\n\n async assertGrid(): Promise<string | null> {\n if (this.viewport.width < GRID_VIEWPORT) {\n return `the page is one column at ${this.viewport.width}px, below the ${GRID_VIEWPORT}px the grid needs`;\n }\n const observed = await this.observeGrid();\n if (observed.grids === 0) {\n this.fail(\n 'page-grid',\n observed.pageLine,\n `${this.target.source} draws no column grid: no element on it has as many tracks as `\n + '--columns-count. The page is the column grid, so its sections sit on one',\n );\n }\n if (observed.failures.length > 0) {\n this.fail(\n 'page-grid',\n observed.failures[0].line,\n report(observed.failures, `${observed.children} sections on ${observed.grids} column grids`, (failure) =>\n `line ${failure.line}: <${failure.tag}> sits ${Math.abs(failure.off)}px `\n + `to the ${failure.off < 0 ? 'left' : 'right'} of the nearest column line on its ${failure.edge}`),\n );\n }\n return null;\n }\n\n async assertOverflow(specs: ContractPaintSpec[]): Promise<string | null> {\n const observed = await this.observeOverflow(specs);\n if (observed.failures.length > 0) {\n this.fail(\n 'page-overflow',\n observed.failures[0].line,\n report(observed.failures, `${observed.elements} boxes`, (failure) =>\n `line ${failure.line}: ${failure.detail}`),\n );\n }\n return null;\n }\n}\n\n/** Installed on every page the run opens, so each rule reads the line the same\n * way. Svelte's dev build stamps every element with the file and line it was\n * written on; an element a component rendered carries the component's file, so\n * the nearest ancestor the page file names is the line of the instance. */\nexport async function installPageProbe(page: Page): Promise<void> {\n await page.addInitScript(() => {\n window.__liveTokensPageLine = (node: Element, source: string): number => {\n for (let element: Element | null = node; element; element = element.parentElement) {\n const loc = (element as { __svelte_meta?: { loc?: { file?: string; line?: number } } }).__svelte_meta?.loc;\n if (!loc || typeof loc.file !== 'string' || typeof loc.line !== 'number') continue;\n if (loc.file.split('\\\\').join('/').endsWith(source)) return loc.line;\n }\n return 1;\n };\n });\n}\n\ndeclare global {\n interface Window {\n __liveTokensPageLine: (node: Element, source: string) => number;\n }\n}\n"],"mappings":"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","names":["hex","componentRoots","bundles","axis"]}
1
+ {"version":3,"sources":["../testing/page-compliance.contract.ts","../editor/ui/sections/textStyles.ts","../editor/core/palettes/contrast.ts","../testing/support/pageHarness.ts"],"sourcesContent":["import { test } from '@playwright/test';\nimport { TEXT_STYLES } from '../editor/ui/sections/textStyles';\nimport { allContracts } from './contracts';\nimport {\n PageHarness,\n pageTargets,\n pageViewports,\n restingPaintSpec,\n type ContractPaintSpec,\n} from './support/pageHarness';\n\nconst targets = pageTargets();\nconst viewports = pageViewports();\n\nconst bundles = TEXT_STYLES.map((style) => ({ name: style.name, prefix: style.prefix }));\n\nasync function paintSpecs(): Promise<ContractPaintSpec[]> {\n const contracts = await allContracts();\n return contracts\n .map((contract) => restingPaintSpec(contract))\n .filter((spec): spec is ContractPaintSpec => spec !== null);\n}\n\nasync function componentRoots(): Promise<string[]> {\n const contracts = await allContracts();\n return contracts\n .map((contract) => contract.parts[contract.root])\n .filter((declared): declared is string => typeof declared === 'string');\n}\n\nfor (const target of targets) {\n for (const viewport of viewports) {\n const at = `${viewport.width}x${viewport.height}`;\n\n test(`page-component-paint | ${target.source} | ${at}`, async ({ page }) => {\n const specs = await paintSpecs();\n const harness = await PageHarness.open(page, target, viewport);\n const inapplicable = await harness.assertComponentPaint(specs);\n test.skip(inapplicable !== null, inapplicable ?? '');\n });\n\n test(`page-text-style | ${target.source} | ${at}`, async ({ page }) => {\n const roots = await componentRoots();\n const harness = await PageHarness.open(page, target, viewport);\n const inapplicable = await harness.assertTextStyle(bundles, roots);\n test.skip(inapplicable !== null, inapplicable ?? '');\n });\n\n test(`page-contrast | ${target.source} | ${at}`, async ({ page }) => {\n const roots = await componentRoots();\n const harness = await PageHarness.open(page, target, viewport);\n const inapplicable = await harness.assertContrast(roots);\n test.skip(inapplicable !== null, inapplicable ?? '');\n });\n\n test(`page-grid | ${target.source} | ${at}`, async ({ page }) => {\n const harness = await PageHarness.open(page, target, viewport);\n const inapplicable = await harness.assertGrid();\n test.skip(inapplicable !== null, inapplicable ?? '');\n });\n\n test(`page-overflow | ${target.source} | ${at}`, async ({ page }) => {\n const specs = await paintSpecs();\n const harness = await PageHarness.open(page, target, viewport);\n const inapplicable = await harness.assertOverflow(specs);\n test.skip(inapplicable !== null, inapplicable ?? '');\n });\n }\n}\n","/**\n * Registry of the semantic text styles rendered by TextStylesSection.\n * Each style is a bundle of alias tokens declared in tokens.css; the prefix\n * joins with a kind suffix (`-font-family`, `-font-size`, …) to form each\n * axis variable the editor's pickers target.\n *\n * Family/size/weight/letter-spacing/line-height are editable on every style.\n * `hasTextTransform` marks the one style (eyebrow) that also exposes a\n * text-transform picker — the only axis that exists on just one style.\n */\n\nexport interface TextStyle {\n name: string;\n label: string;\n /** Variable prefix, e.g. `--heading-xl`; suffixes form each axis var. */\n prefix: string;\n /** Element (or class) this style is the default for. */\n defaultElement: string;\n preview: string;\n /** Whether this style exposes an editable `-text-transform` axis. */\n hasTextTransform?: boolean;\n}\n\nexport const TEXT_STYLES: TextStyle[] = [\n {\n name: 'heading-xl',\n label: 'Heading XL',\n prefix: '--heading-xl',\n defaultElement: 'h1',\n preview: 'Page title',\n },\n {\n name: 'heading-lg',\n label: 'Heading LG',\n prefix: '--heading-lg',\n defaultElement: 'h2',\n preview: 'Section heading',\n },\n {\n name: 'heading-md',\n label: 'Heading MD',\n prefix: '--heading-md',\n defaultElement: 'h3',\n preview: 'Subsection heading',\n },\n {\n name: 'heading-sm',\n label: 'Heading SM',\n prefix: '--heading-sm',\n defaultElement: 'h4',\n preview: 'Minor heading',\n },\n {\n name: 'body-md',\n label: 'Body MD',\n prefix: '--body-md',\n defaultElement: 'p',\n preview: 'Body copy for comfortable reading.',\n },\n {\n name: 'body-sm',\n label: 'Body SM',\n prefix: '--body-sm',\n defaultElement: 'small',\n preview: 'Captions and secondary text.',\n },\n {\n name: 'editorial-xl',\n label: 'Editorial XL',\n prefix: '--editorial-xl',\n defaultElement: 'editorial-xl',\n preview: 'Pull quotes and opening statements.',\n },\n {\n name: 'editorial-lg',\n label: 'Editorial LG',\n prefix: '--editorial-lg',\n defaultElement: 'editorial-lg',\n preview: 'Standfirsts and section ledes.',\n },\n {\n name: 'editorial-md',\n label: 'Editorial MD',\n prefix: '--editorial-md',\n defaultElement: 'editorial-md',\n preview: 'Long-form reading, set in the editorial face.',\n },\n {\n name: 'editorial-sm',\n label: 'Editorial SM',\n prefix: '--editorial-sm',\n defaultElement: 'editorial-sm',\n preview: 'Captions, credits, and asides.',\n },\n {\n name: 'code',\n label: 'Code',\n prefix: '--code',\n defaultElement: 'code',\n preview: 'const total = sum(items);',\n },\n {\n name: 'eyebrow',\n label: 'Eyebrow',\n prefix: '--eyebrow',\n defaultElement: 'eyebrow',\n preview: 'Overline label',\n hasTextTransform: true,\n },\n];\n","// WCAG 2.1 contrast math + an OKLCH-lightness solver.\n//\n// The solver is the engine behind the \"Derive accessible text\" action: given a\n// surface hex and a target ratio, it finds the lightness (at fixed hue) whose\n// gamut-clamped color clears the ratio. Contrast is monotonic in L only on one\n// side of the surface's own lightness, so `direction` selects the branch.\n\nimport { hexToOklch, oklchToHex, gamutClamp } from './oklch';\n\nexport const AA_BODY = 4.5;\nexport const AA_LARGE = 3.0;\n\nfunction linearizeChannel(v8: number): number {\n const s = v8 / 255;\n return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);\n}\n\nexport function relativeLuminance(hex: string): number {\n const r = linearizeChannel(parseInt(hex.slice(1, 3), 16));\n const g = linearizeChannel(parseInt(hex.slice(3, 5), 16));\n const b = linearizeChannel(parseInt(hex.slice(5, 7), 16));\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n}\n\nexport function contrastRatio(a: string, b: string): number {\n const la = relativeLuminance(a);\n const lb = relativeLuminance(b);\n const hi = Math.max(la, lb);\n const lo = Math.min(la, lb);\n return (hi + 0.05) / (lo + 0.05);\n}\n\nexport interface FindLOptions {\n against: string;\n ratio: number;\n direction: 'lighter' | 'darker';\n c: number;\n h: number;\n margin?: number;\n /** Reachable-L window. The Text derivation multiplies seed L by a curve\n * factor clamped to [0,2], so a family can only reach L ∈ [0, min(1,2·seedL)].\n * The solver passes that ceiling as `lMax` so the returned L is realisable. */\n lMin?: number;\n lMax?: number;\n}\n\nexport interface FindLResult {\n l: number;\n c: number;\n hex: string;\n}\n\n/**\n * Binary-search OKLCH lightness for a color that clears `ratio` against\n * `against`, staying on the `direction` side of the surface (the monotonic\n * branch). If the ratio is unreachable at chroma `c` within the window, decay\n * chroma toward 0 and retry — achromatic extremes reach the full 1..21 range.\n * The result is re-verified with `contrastRatio` after the hex round-trip and\n * nudged one step if 8-bit quantization ate the margin (Global invariant 8).\n */\nexport function findLForContrast(opts: FindLOptions): FindLResult {\n const { against, ratio, direction, c, h } = opts;\n const margin = opts.margin ?? 0.05;\n const lMin = opts.lMin ?? 0;\n const lMax = opts.lMax ?? 1;\n const target = ratio + margin;\n const againstL = hexToOklch(against).l;\n\n const evalAt = (l: number, cc: number) => {\n const g = gamutClamp(l, cc, h);\n const hex = oklchToHex(g.l, g.c, g.h);\n return { hex, chroma: g.c, ratio: contrastRatio(hex, against) };\n };\n\n // Returns the boundary solution at a fixed chroma, or null if `target` is\n // unreachable within the window at that chroma. `extreme` is the window end\n // with the most contrast (top L for lighter, bottom L for darker).\n const solveAtChroma = (cc: number): { l: number; hex: string; chroma: number } | null => {\n const lighter = direction === 'lighter';\n const lo0 = lighter ? Math.max(lMin, againstL) : lMin;\n const hi0 = lighter ? lMax : Math.min(lMax, againstL);\n if (lo0 >= hi0) return null; // no room to move to the requested side within the window\n const extreme = lighter ? hi0 : lo0;\n if (evalAt(extreme, cc).ratio < target) return null;\n let lo = lo0;\n let hi = hi0;\n for (let i = 0; i < 24; i++) {\n const mid = (lo + hi) / 2;\n const meets = evalAt(mid, cc).ratio >= target;\n // Contrast rises toward `extreme`; keep the half that still meets target.\n if (lighter ? meets : !meets) hi = mid;\n else lo = mid;\n }\n const at = lighter ? hi : lo;\n const e = evalAt(at, cc);\n return { l: at, hex: e.hex, chroma: e.chroma };\n };\n\n let sol = solveAtChroma(c);\n if (!sol) {\n if (!solveAtChroma(0)) {\n // Even achromatic can't reach the target within the window — return the\n // extreme (best effort); the caller reports it as unmet.\n const extremeL = direction === 'lighter' ? lMax : lMin;\n const e = evalAt(extremeL, 0);\n return { l: extremeL, c: 0, hex: e.hex };\n }\n let lo = 0;\n let hi = c;\n for (let i = 0; i < 24; i++) {\n const mid = (lo + hi) / 2;\n if (solveAtChroma(mid)) lo = mid;\n else hi = mid;\n }\n sol = solveAtChroma(lo)!;\n }\n\n let { l, hex, chroma } = sol;\n const step = direction === 'lighter' ? 0.004 : -0.004;\n for (let k = 0; k < 12 && contrastRatio(hex, against) < ratio; k++) {\n l = Math.min(lMax, Math.max(lMin, l + step));\n const g = gamutClamp(l, chroma, h);\n l = g.l;\n chroma = g.c;\n hex = oklchToHex(g.l, g.c, g.h);\n }\n return { l, c: chroma, hex };\n}\n","import type { ElementHandle, Page } from '@playwright/test';\nimport {\n DEFAULT_PAGE_VIEWPORTS,\n PAGES_ENV,\n PAGE_VIEWPORTS_ENV,\n type PageViewport,\n} from '../config';\nimport { AA_BODY, AA_LARGE, contrastRatio } from '../../editor/core/palettes/contrast';\nimport { isInapplicable, type ComponentContract, type PaintMap } from '../componentContract';\n\nexport type PageRule =\n | 'page-component-paint'\n | 'page-text-style'\n | 'page-contrast'\n | 'page-grid'\n | 'page-overflow';\n\n/**\n * A failed obligation on a rendered page, carrying the rule id the CLI reports\n * it under and the page file line the finding anchors on.\n */\nexport class PageViolation extends Error {\n constructor(\n readonly rule: PageRule,\n readonly source: string,\n readonly line: number,\n message: string,\n ) {\n super(`[${rule}] ${source}:${line}: ${message}`);\n this.name = 'PageViolation';\n }\n}\n\nexport interface PageTarget {\n /** Page file the finding anchors on, relative to the project root. */\n source: string;\n route: string;\n}\n\n/** The wrapper `LiveTokensRouter` renders every consumer page inside. */\nconst PAGE_CONTAINER = '[data-live-tokens-page]';\n\n/** The router's own chrome: the editor overlay and the column guides. Inside\n * the container and never part of the page. */\nconst CHROME = '[data-live-tokens-chrome]';\n\nexport function pageTargets(): PageTarget[] {\n const raw = process.env[PAGES_ENV];\n if (!raw) return [];\n return JSON.parse(raw) as PageTarget[];\n}\n\nexport function pageViewports(): PageViewport[] {\n const raw = process.env[PAGE_VIEWPORTS_ENV];\n if (!raw) return DEFAULT_PAGE_VIEWPORTS;\n return JSON.parse(raw) as PageViewport[];\n}\n\n/**\n * A state a resting instance on a page is not in. The component contracts key\n * their paint maps by the editor's own tab labels, which name interaction\n * states (hover, focused), component states (disabled, selected, error, on),\n * and views that only exist once something is opened (an active tab, a menu\n * and its options). Everything else — a bare label, `base`, `default`, and the\n * structural part labels (Header, Body, Footer, ...) — paints at rest.\n */\nconst TRANSIENT_STATE = /\\b(?:hover|active|disabled|focused|error|selected|open|menu|option|on)\\b/;\n\nfunction restingState(label: string | undefined): boolean {\n return label === undefined || !TRANSIENT_STATE.test(label.toLowerCase());\n}\n\ninterface PaintCheck {\n part: string;\n /** Null for the contract's own root part, which is the instance itself. */\n selector: string | null;\n pseudo: string | null;\n css: string;\n variable: string;\n}\n\ninterface PaintEntry {\n /** The contract's own variant label, lowercased, as the finding names it. */\n variant: string | null;\n /** Source of the RegExp an instance's class tokens are tested against. Null\n * for an entry every instance is in. */\n pattern: string | null;\n checks: PaintCheck[];\n}\n\n/**\n * A class token names a variant when it is the variant's own word or carries\n * it as a suffix: the three spellings the shipped components use are bare\n * (`button primary`), component-prefixed (`badge badge-brand`), and\n * axis-prefixed (`es-root variant-hairline`). A contract's variant label is the\n * editor's prose (`With Hairline`), so each of its words is a key as well as\n * the whole label, which is what reaches the `hairline` the markup spells.\n */\nfunction variantPattern(label: string | undefined | null): string | null {\n if (!label) return null;\n const words = label.toLowerCase().split(/\\s+/);\n const keys = [...new Set([words.join('-'), ...words])]\n .map((key) => key.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'));\n return `(?:^|-)(?:${keys.join('|')})$`;\n}\n\nexport interface ContractPaintSpec {\n id: string;\n root: string;\n entries: PaintEntry[];\n}\n\nfunction paintChecks(contract: ComponentContract, map: PaintMap): PaintCheck[] {\n const checks: PaintCheck[] = [];\n for (const [part, properties] of Object.entries(map)) {\n const declared = contract.parts[part];\n if (declared === undefined) continue;\n const locator = typeof declared === 'string' ? { selector: declared } : declared;\n // A portalled part is rendered by an interaction, so no resting page\n // instance has one.\n if (typeof declared !== 'string' && declared.portal) continue;\n for (const [css, variable] of Object.entries(properties)) {\n checks.push({\n part,\n selector: part === contract.root ? null : locator.selector,\n pseudo: (typeof declared === 'string' ? undefined : declared.pseudo) ?? null,\n css,\n variable,\n });\n }\n }\n return checks;\n}\n\n/**\n * What a contract obliges of an instance sitting at rest on a page: the paint\n * maps that need no state tab, no editor control, and no interaction. A\n * variant-keyed entry carries the pattern its instances' root classes have to\n * name.\n */\nexport function restingPaintSpec(contract: ComponentContract): ContractPaintSpec | null {\n const rootSelector = contract.parts[contract.root];\n if (typeof rootSelector !== 'string') return null;\n const entries: PaintEntry[] = [];\n // `contract.view` opens the component editor: its `setup` drives preview\n // controls no page has and its `state` names a tab. Only `variant` carries\n // onto a page, so an entry inherits that and nothing else.\n const inherited = contract.view ?? {};\n for (const expectation of contract.properties) {\n if ((expectation.setup ?? []).length > 0) continue;\n if (!restingState(expectation.state)) continue;\n const checks = paintChecks(contract, expectation.paints);\n if (checks.length === 0) continue;\n const variant = (expectation.variant ?? inherited.variant)?.toLowerCase() ?? null;\n entries.push({ variant, pattern: variantPattern(variant), checks });\n }\n // A component whose only resting paint map hangs off a state tab still\n // paints its default state on a page.\n if (!isInapplicable(contract.states)) {\n for (const state of contract.states) {\n if (!state.paints || !restingState(state.state)) continue;\n if ((state.setup ?? []).length > 0) continue;\n const checks = paintChecks(contract, state.paints);\n if (checks.length === 0) continue;\n const variant = (state.variant ?? inherited.variant)?.toLowerCase() ?? null;\n entries.push({ variant, pattern: variantPattern(variant), checks });\n }\n }\n if (entries.length === 0) return null;\n return { id: contract.id, root: rootSelector, entries };\n}\n\nexport interface PaintFailure {\n id: string;\n variant: string | null;\n line: number;\n part: string;\n css: string;\n variable: string;\n actual: string;\n expected: string;\n}\n\nexport interface UncoveredInstance {\n id: string;\n line: number;\n /** The variants the contract offers, none of which this instance's root\n * classes name. */\n variants: string[];\n}\n\nexport interface PaintObservation {\n instances: number;\n asserted: number;\n failures: PaintFailure[];\n /** Instances every variant-keyed entry passed over: decision 6's exception,\n * reported per instance rather than silently passed. */\n uncovered: UncoveredInstance[];\n}\n\nexport interface TextObservation {\n elements: number;\n failures: { line: number; tag: string; nearest: string; axis: string; actual: string; expected: string }[];\n}\n\nexport interface TextBundle {\n name: string;\n prefix: string;\n}\n\nexport interface ContrastPair {\n line: number;\n tag: string;\n /** Computed text colour, composited over the surface when translucent. */\n color: string;\n background: string;\n colorToken: string | null;\n backgroundToken: string | null;\n fontSize: number;\n fontWeight: number;\n}\n\nexport interface ContrastObservation {\n pairs: ContrastPair[];\n /** Why a run of text carries no pair, counted by reason. */\n skipped: Record<string, number>;\n}\n\nexport interface GridChildFailure {\n line: number;\n tag: string;\n edge: 'left' | 'right';\n /** Distance from the nearest track edge, in px. */\n off: number;\n}\n\nexport interface GridObservation {\n grids: number;\n children: number;\n failures: GridChildFailure[];\n /** The page's own outermost element, which a missing grid anchors on. */\n pageLine: number;\n}\n\nexport interface OverflowFailure {\n line: number;\n tag: string;\n kind: 'document' | 'element' | 'instance';\n detail: string;\n}\n\nexport interface OverflowObservation {\n elements: number;\n failures: OverflowFailure[];\n}\n\nconst TEXT_AXES = ['fontFamily', 'fontSize', 'fontWeight', 'lineHeight', 'letterSpacing'] as const;\n\n/** Displays that make an element a block of its own. Text sitting directly in\n * anything else is a run inside a line, and the line's own block owns it. */\nconst BLOCK_DISPLAYS = ['block', 'flow-root', 'list-item', 'flex', 'grid', 'table-cell', 'table-caption'];\n\n/** Sub-pixel track positions and a browser's own rounding put an edge that is\n * on the line up to a pixel off it. */\nconst GRID_TOLERANCE = 1;\n\n/** Below this the page is one column, so the grid rule has nothing to hold a\n * section to. */\nconst GRID_VIEWPORT = 768;\n\n/** How long the page has to hold still before a rule measures it, and how\n * long to wait for that before measuring anyway. */\nconst SETTLE_QUIET_MS = 300;\nconst SETTLE_BUDGET_MS = 5_000;\n\n/** WCAG's large-text sizes: the AA floor drops to 3:1 at either. */\nconst LARGE_TEXT_PX = 24;\nconst LARGE_BOLD_PX = 18.66;\nconst BOLD = 700;\n\n/** Findings name CSS properties as a page's own stylesheet spells them. */\nconst cssName = (camel: string) => camel.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);\n\n/** The line the finding anchors on, the rest named in the message, and what\n * the rule looked at to find them: one rerun after each repair walks the\n * whole list. */\nfunction report<T>(failures: T[], scope: string, describe: (failure: T) => string): string {\n const lines = failures.map(describe);\n return lines.length === 1 ? lines[0] : `${lines.length} of ${scope}\\n${lines.join('\\n')}`;\n}\n\nfunction hex(rgb: string): string {\n const [r, g, b] = rgb.match(/\\d+/g)!.map(Number);\n return `#${[r, g, b].map((c) => c.toString(16).padStart(2, '0')).join('')}`;\n}\n\n/** The AA floor the pair has to clear, which its own size and weight set. */\nfunction aaFloor(pair: ContrastPair): number {\n const large = pair.fontSize >= LARGE_TEXT_PX\n || (pair.fontSize >= LARGE_BOLD_PX && pair.fontWeight >= BOLD);\n return large ? AA_LARGE : AA_BODY;\n}\n\n/** A reason reads as prose: `a gradient (2), a blend mode (1)`. */\nfunction reasons(skipped: Record<string, number>): string {\n return Object.entries(skipped).map(([reason, count]) => `${reason} (${count})`).join(', ');\n}\n\n/** The page under test, and what the rules read off it. */\nexport class PageHarness {\n private constructor(\n readonly page: Page,\n readonly target: PageTarget,\n readonly viewport: PageViewport,\n ) {}\n\n static async open(page: Page, target: PageTarget, viewport: PageViewport): Promise<PageHarness> {\n await installPageProbe(page);\n await page.setViewportSize(viewport);\n await page.goto(target.route);\n await page.locator(PAGE_CONTAINER).waitFor();\n // The lazy route module: until it mounts, the container holds the dev\n // overlay and nothing of the page itself.\n await page.waitForFunction((selectors) => {\n const container = document.querySelector(selectors.container);\n if (!container) return false;\n return [...container.children].some((child) => !child.matches(selectors.chrome));\n }, { container: PAGE_CONTAINER, chrome: CHROME });\n await page.waitForLoadState('networkidle');\n await PageHarness.settle(page);\n return new PageHarness(page, target, viewport);\n }\n\n /**\n * Every rule here measures geometry, and the geometry moves for as long as\n * the theme's own values, the route's stylesheet, and the fonts are still\n * arriving. A twelve-column grid inside 32px of padding reaches 384px at a\n * 390px viewport with the theme's 32px `--columns-gutter`, and 120px with\n * the 8px gutter `tokens.css` computes there on its own, so the same page\n * reads as overflowing or not depending on what has landed. Waiting on a single custom property settles nothing:\n * `--body-md-font-size`, the property this gate used to read, is one\n * `tokens.css` sets itself, and a trace of the boot has it true 84ms before\n * the page container exists at all. What a rule needs instead is a page that\n * has stopped moving. The budget bounds a page that never does.\n */\n private static async settle(page: Page): Promise<void> {\n await page.evaluate(async ({ quietMs, budgetMs }) => {\n await document.fonts.ready;\n const root = document.documentElement;\n // `root.style.length` counts the custom properties the dev-time theme\n // projection writes inline, which land without moving anything.\n const signature = () => [\n root.scrollWidth, root.scrollHeight, root.clientWidth, root.clientHeight,\n root.style.length, document.fonts.size, document.fonts.status,\n ].join('|');\n const frame = () => new Promise<void>((resolve) => requestAnimationFrame(() => resolve()));\n const deadline = performance.now() + budgetMs;\n let last = signature();\n let quietSince = performance.now();\n while (performance.now() < deadline) {\n await frame();\n const now = signature();\n if (now !== last) {\n last = now;\n quietSince = performance.now();\n continue;\n }\n if (performance.now() - quietSince >= quietMs) return;\n }\n }, { quietMs: SETTLE_QUIET_MS, budgetMs: SETTLE_BUDGET_MS });\n }\n\n fail(rule: PageRule, line: number, message: string): never {\n throw new PageViolation(rule, this.target.source, line, message);\n }\n\n /** Every shipped instance on the page, as the contract root selectors find\n * them, with the variant its own root classes name. */\n async instances(specs: ContractPaintSpec[]): Promise<{ id: string; variant: string | null; line: number }[]> {\n return this.page.evaluate(({ specs: list, container, chrome, source }) => {\n const found: { id: string; variant: string | null; line: number }[] = [];\n const root = document.querySelector(container);\n if (!root) return found;\n for (const spec of list) {\n const keyed: { variant: string | null; pattern: RegExp }[] = [];\n for (const entry of spec.entries) {\n if (entry.pattern !== null) keyed.push({ variant: entry.variant, pattern: new RegExp(entry.pattern) });\n }\n for (const element of root.querySelectorAll(spec.root)) {\n if (element.closest(chrome)) continue;\n const classes = [...element.classList];\n const matched = keyed.find(({ pattern }) => classes.some((name) => pattern.test(name)));\n found.push({\n id: spec.id,\n variant: matched?.variant ?? null,\n line: window.__liveTokensPageLine(element, source),\n });\n }\n }\n return found;\n }, { specs, container: PAGE_CONTAINER, chrome: CHROME, source: this.target.source });\n }\n\n /**\n * Every element that renders text of its own: block-level, inside the page\n * container, outside the router's chrome, and outside every shipped\n * component root, whose slot typography the component owns.\n */\n async textElements(componentRoots: string[]): Promise<{ line: number; tag: string; axes: Record<string, string> }[]> {\n return this.page.evaluate(({ roots, container, chrome, source, axes, displays }) => {\n const found: { line: number; tag: string; axes: Record<string, string> }[] = [];\n const root = document.querySelector(container);\n if (!root) return found;\n const inComponent = roots.join(', ');\n for (const element of root.querySelectorAll<HTMLElement>('*')) {\n if (element.closest(chrome)) continue;\n if (inComponent && element.closest(inComponent)) continue;\n const ownText = [...element.childNodes]\n .some((node) => node.nodeType === Node.TEXT_NODE && (node.textContent ?? '').trim().length > 0);\n if (!ownText) continue;\n const style = getComputedStyle(element);\n if (!displays.includes(style.display)) continue;\n found.push({\n line: window.__liveTokensPageLine(element, source),\n tag: element.tagName.toLowerCase(),\n axes: Object.fromEntries(axes.map((axis) => [axis, (style as unknown as Record<string, string>)[axis] ?? ''])),\n });\n }\n return found;\n }, {\n roots: componentRoots,\n container: PAGE_CONTAINER,\n chrome: CHROME,\n source: this.target.source,\n axes: [...TEXT_AXES],\n displays: BLOCK_DISPLAYS,\n });\n }\n\n /** The page file line the element was written on, from Svelte's dev-build\n * element metadata. */\n async lineOf(element: ElementHandle<Element>): Promise<number> {\n return element.evaluate((node, source) => window.__liveTokensPageLine(node, source), this.target.source);\n }\n\n /** Every resting paint obligation, measured on the instances themselves. */\n async observePaints(specs: ContractPaintSpec[]): Promise<PaintObservation> {\n return this.page.evaluate(({ specs: list, container, chrome, source }) => {\n const failures: PaintObservation['failures'] = [];\n const uncovered: UncoveredInstance[] = [];\n let instances = 0;\n let asserted = 0;\n const root = document.querySelector(container);\n if (!root) return { instances, asserted, failures, uncovered };\n\n // The value a CSS property takes from the raw token, measured beside the\n // part so inherited font size and colour resolve the same way. A token\n // holding `#fff` and a computed `rgb(255, 255, 255)` are the same paint,\n // and only the browser can say so.\n //\n // The part's own font size is seeded onto the probe first: a unitless\n // line height and an `em` letter spacing resolve against it, and a\n // component that sets its own font size (every Button does) makes the\n // parent's the wrong ruler. A `font-size` token overwrites the seed and\n // still resolves its own relative units against the parent, as it must.\n const normalize = (node: Element, css: string, raw: string): string => {\n const probe = document.createElement('div');\n probe.style.display = 'none';\n // A border width computes to 0 while the border style is `none`, so\n // the probe would answer 0px for every stroke thickness.\n probe.style.borderStyle = 'solid';\n probe.style.outlineStyle = 'solid';\n probe.style.fontSize = getComputedStyle(node).fontSize;\n (node.parentElement ?? document.body).appendChild(probe);\n probe.style.setProperty(css.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`), raw);\n const computed = (getComputedStyle(probe) as unknown as Record<string, string>)[css];\n probe.remove();\n return (computed ?? '').trim();\n };\n\n for (const spec of list) {\n const patterns = spec.entries.map((entry) => (entry.pattern === null ? null : new RegExp(entry.pattern)));\n const variants = [...new Set(spec.entries.map((entry) => entry.variant).filter((v): v is string => v !== null))];\n for (const element of root.querySelectorAll(spec.root)) {\n if (element.closest(chrome)) continue;\n instances++;\n const classes = [...element.classList];\n const line = window.__liveTokensPageLine(element, source);\n let covered = false;\n for (const [index, entry] of spec.entries.entries()) {\n const pattern = patterns[index];\n if (pattern && !classes.some((name) => pattern.test(name))) continue;\n covered = true;\n for (const check of entry.checks) {\n const part = check.selector === null ? element : element.querySelector(check.selector);\n if (!part) continue;\n const style = getComputedStyle(part, check.pseudo ?? undefined);\n const token = style.getPropertyValue(check.variable).trim();\n if (!token) continue;\n const expected = normalize(part, check.css, token);\n const actual = ((style as unknown as Record<string, string>)[check.css] ?? '').trim();\n asserted++;\n if (actual !== expected) {\n failures.push({\n id: spec.id,\n variant: entry.variant,\n line,\n part: check.part,\n css: check.css,\n variable: check.variable,\n actual,\n expected,\n });\n }\n }\n }\n // One Badge naming its variant says nothing about the next one, so\n // decision 6's exception is counted per instance.\n if (!covered) uncovered.push({ id: spec.id, line, variants });\n }\n }\n return { instances, asserted, failures, uncovered };\n }, { specs, container: PAGE_CONTAINER, chrome: CHROME, source: this.target.source });\n }\n\n /** Every run of text on the page, against the theme's own style bundles as\n * they resolve at this viewport. */\n async observeTextStyles(bundles: TextBundle[], componentRoots: string[]): Promise<TextObservation> {\n const elements = await this.textElements(componentRoots);\n const expected = await this.page.evaluate(({ list, axes }) => {\n const style = getComputedStyle(document.documentElement);\n const probe = document.createElement('div');\n probe.style.position = 'absolute';\n probe.style.visibility = 'hidden';\n document.body.appendChild(probe);\n const resolved: Record<string, Record<string, string>> = {};\n for (const bundle of list) {\n // One probe per bundle, carrying all five axes at once: a unitless\n // line height and an `em` letter spacing resolve against the bundle's\n // own font size, so five separately measured values would not be the\n // bundle. The reset clears an axis the previous bundle set.\n probe.style.cssText = 'position:absolute;visibility:hidden';\n for (const axis of axes) {\n probe.style.setProperty(\n axis.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`),\n style.getPropertyValue(`${bundle.prefix}-${axis.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)}`).trim(),\n );\n }\n const computed = getComputedStyle(probe) as unknown as Record<string, string>;\n resolved[bundle.name] = Object.fromEntries(axes.map((axis) => [axis, (computed[axis] ?? '').trim()]));\n }\n probe.remove();\n return resolved;\n }, { list: bundles, axes: [...TEXT_AXES] });\n\n const failures: TextObservation['failures'] = [];\n for (const element of elements) {\n let best = { name: '', misses: [] as string[], distance: Number.POSITIVE_INFINITY };\n for (const bundle of bundles) {\n const misses: string[] = TEXT_AXES.filter((axis) => element.axes[axis] !== expected[bundle.name][axis]);\n if (misses.length === 0) { best = { name: bundle.name, misses: [], distance: 0 }; break; }\n // Family and size are what identify a bundle by eye, so a bundle that\n // matches both and misses a weight is nearer than one that misses the\n // face, even on the same count.\n const distance = misses.length\n + (misses.includes('fontFamily') ? 0.4 : 0)\n + (misses.includes('fontSize') ? 0.2 : 0);\n if (distance < best.distance) best = { name: bundle.name, misses, distance };\n }\n if (best.misses.length === 0) continue;\n const axis = best.misses[0];\n failures.push({\n line: element.line,\n tag: element.tag,\n nearest: best.name,\n axis,\n actual: element.axes[axis],\n expected: expected[best.name][axis],\n });\n }\n return { elements: elements.length, failures };\n }\n\n /**\n * Every text and surface pair the page composes, with the tokens whose\n * resolved values match them. The ratio itself is computed by the caller\n * from the editor's own WCAG helper, so one implementation answers for the\n * palette editor and for a page.\n */\n async observeContrast(componentRoots: string[]): Promise<ContrastObservation> {\n return this.page.evaluate(({ roots, container, chrome, source, displays }) => {\n const pairs: ContrastPair[] = [];\n const skipped: Record<string, number> = {};\n const skip = (reason: string) => { skipped[reason] = (skipped[reason] ?? 0) + 1; };\n const root = document.querySelector(container);\n if (!root) return { pairs, skipped };\n\n // The theme states its colours in `oklch()`, which Chromium keeps in the\n // computed value, so no string parse reaches the channels. A 1x1 canvas\n // in `copy` mode answers with the pixel the screen shows, gamut-clamped\n // the same way, for any colour syntax including a future one. An invalid\n // or `transparent` value leaves the cleared pixel, which reads as alpha 0\n // and is what \"paints nothing here\" means.\n const canvas = document.createElement('canvas');\n canvas.width = 1;\n canvas.height = 1;\n const ctx = canvas.getContext('2d', { willReadFrequently: true })!;\n ctx.globalCompositeOperation = 'copy';\n const rgba = (value: string): [number, number, number, number] => {\n ctx.fillStyle = 'rgba(0, 0, 0, 0)';\n ctx.fillStyle = value;\n ctx.fillRect(0, 0, 1, 1);\n const [r, g, b, a] = ctx.getImageData(0, 0, 1, 1).data;\n return [r, g, b, a / 255];\n };\n const key = ([r, g, b]: [number, number, number, number]) => `${r},${g},${b}`;\n const css = (c: [number, number, number, number]) =>\n (c[3] === 1 ? `rgb(${c[0]}, ${c[1]}, ${c[2]})` : `rgba(${c[0]}, ${c[1]}, ${c[2]}, ${c[3]})`);\n\n // A finding names the token when one resolves to the colour it measured.\n const probe = document.createElement('div');\n probe.style.display = 'none';\n document.body.appendChild(probe);\n const named = new Map<string, string>();\n const rootStyle = getComputedStyle(document.documentElement);\n for (const name of rootStyle) {\n if (!name.startsWith('--')) continue;\n probe.style.color = '';\n probe.style.color = `var(${name})`;\n const resolved = getComputedStyle(probe).color;\n if (!resolved) continue;\n const colour = rgba(resolved);\n if (colour[3] === 0) continue;\n if (!named.has(key(colour))) named.set(key(colour), name);\n }\n probe.remove();\n\n const over = (\n front: [number, number, number, number],\n back: [number, number, number, number],\n ): [number, number, number, number] => [\n Math.round(front[0] * front[3] + back[0] * (1 - front[3])),\n Math.round(front[1] * front[3] + back[1] * (1 - front[3])),\n Math.round(front[2] * front[3] + back[2] * (1 - front[3])),\n 1,\n ];\n\n const inComponent = roots.join(', ');\n for (const element of root.querySelectorAll<HTMLElement>('*')) {\n if (element.closest(chrome)) continue;\n if (inComponent && element.closest(inComponent)) continue;\n const ownText = [...element.childNodes]\n .some((node) => node.nodeType === Node.TEXT_NODE && (node.textContent ?? '').trim().length > 0);\n if (!ownText) continue;\n const style = getComputedStyle(element);\n if (!displays.includes(style.display)) continue;\n if (style.visibility !== 'visible') continue;\n const colour = rgba(style.color);\n if (colour[3] === 0) continue;\n\n let surface: [number, number, number, number] | null = null;\n let reason: string | null = null;\n for (let node: Element | null = element; node; node = node.parentElement) {\n const behind = getComputedStyle(node);\n if (behind.mixBlendMode !== 'normal') { reason = 'a blend mode'; break; }\n if (behind.backgroundImage !== 'none') { reason = 'a gradient or an image behind the text'; break; }\n const paint = rgba(behind.backgroundColor);\n if (paint[3] === 1) { surface = paint; break; }\n if (paint[3] > 0) { reason = 'a translucent surface'; break; }\n }\n if (!surface) {\n skip(reason ?? 'no opaque surface behind the text');\n continue;\n }\n pairs.push({\n line: window.__liveTokensPageLine(element, source),\n tag: element.tagName.toLowerCase(),\n color: css(colour[3] === 1 ? colour : over(colour, surface)),\n background: css(surface),\n colorToken: named.get(key(colour[3] === 1 ? colour : over(colour, surface))) ?? null,\n backgroundToken: named.get(key(surface)) ?? null,\n fontSize: parseFloat(style.fontSize),\n fontWeight: parseInt(style.fontWeight, 10) || 400,\n });\n }\n return { pairs, skipped };\n }, {\n roots: componentRoots,\n container: PAGE_CONTAINER,\n chrome: CHROME,\n source: this.target.source,\n displays: BLOCK_DISPLAYS,\n });\n }\n\n /** Where each section of the page sits against the column grid it draws. */\n async observeGrid(): Promise<GridObservation> {\n return this.page.evaluate(({ container, chrome, source, tolerance }) => {\n const failures: GridChildFailure[] = [];\n let grids = 0;\n let children = 0;\n const root = document.querySelector(container);\n if (!root) return { grids, children, failures, pageLine: 1 };\n const own = [...root.children].find((child) => !child.matches(chrome));\n const pageLine = own ? window.__liveTokensPageLine(own, source) : 1;\n\n const columns = parseInt(\n getComputedStyle(document.documentElement).getPropertyValue('--columns-count').trim(),\n 10,\n );\n if (!columns) return { grids, children, failures, pageLine };\n\n for (const grid of root.querySelectorAll('*')) {\n if (grid.closest(chrome)) continue;\n const style = getComputedStyle(grid);\n const tracks = style.gridTemplateColumns.split(/\\s+/).map(parseFloat);\n if (tracks.length !== columns || tracks.some((track) => !Number.isFinite(track))) continue;\n grids++;\n const box = grid.getBoundingClientRect();\n const gap = parseFloat(style.columnGap) || 0;\n let offset = box.left + parseFloat(style.borderLeftWidth) + parseFloat(style.paddingLeft);\n const lines: number[] = [];\n for (const track of tracks) {\n lines.push(offset);\n offset += track;\n lines.push(offset);\n offset += gap;\n }\n const nearest = (edge: number) =>\n lines.reduce((best, line) => (Math.abs(line - edge) < Math.abs(best - edge) ? line : best), lines[0]);\n\n const items = getComputedStyle(grid).justifyItems;\n for (const child of grid.children) {\n if (child.matches(chrome)) continue;\n const kid = getComputedStyle(child);\n if (kid.display === 'none' || kid.display === 'contents') continue;\n // Out of flow: the grid places its containing block, not the box.\n if (kid.position === 'absolute' || kid.position === 'fixed') continue;\n // The border box, which is the edge the eye reads. A margin that\n // insets a stretched section moves that edge off the line, and the\n // finding is the same one a reader would raise.\n const { left, right } = child.getBoundingClientRect();\n children++;\n // Self-alignment is the grid's own way of insetting a box in the\n // area it placed: a centred section is still on the grid, and only\n // the edge its alignment pins has to land on a line. A margin, a\n // width, or a transform is not the grid's vocabulary, so a stretched\n // item answers for both edges.\n const align = kid.justifySelf === 'auto' ? items : kid.justifySelf;\n const centred = align === 'center';\n const pinned: ('left' | 'right')[] = centred ? []\n : align === 'start' || align === 'flex-start' || align === 'left' ? ['left']\n : align === 'end' || align === 'flex-end' || align === 'right' ? ['right']\n : ['left', 'right'];\n if (centred) {\n const before = left - Math.max(...lines.filter((line) => line <= left + tolerance), lines[0]);\n const after = Math.min(...lines.filter((line) => line >= right - tolerance), lines[lines.length - 1]) - right;\n if (Math.abs(before - after) > tolerance) {\n failures.push({\n line: window.__liveTokensPageLine(child, source),\n tag: child.tagName.toLowerCase(),\n edge: before > after ? 'left' : 'right',\n off: Math.round((before - after) * 10) / 10,\n });\n }\n continue;\n }\n for (const edge of pinned) {\n const at = edge === 'left' ? left : right;\n const off = at - nearest(at);\n if (Math.abs(off) <= tolerance) continue;\n failures.push({\n line: window.__liveTokensPageLine(child, source),\n tag: child.tagName.toLowerCase(),\n edge,\n off: Math.round(off * 10) / 10,\n });\n }\n }\n }\n return { grids, children, failures, pageLine };\n }, { container: PAGE_CONTAINER, chrome: CHROME, source: this.target.source, tolerance: GRID_TOLERANCE });\n }\n\n /** What the page pushes past the viewport, past its own container, or past\n * the box that clips it. */\n async observeOverflow(specs: ContractPaintSpec[]): Promise<OverflowObservation> {\n return this.page.evaluate(({ specs: list, container, chrome, source, tolerance }) => {\n const failures: OverflowFailure[] = [];\n let elements = 0;\n const root = document.querySelector(container);\n if (!root) return { elements, failures };\n const own = [...root.children].find((child) => !child.matches(chrome));\n const pageLine = own ? window.__liveTokensPageLine(own, source) : 1;\n\n const page = document.documentElement;\n if (page.scrollWidth > window.innerWidth + tolerance) {\n failures.push({\n line: pageLine,\n tag: 'html',\n kind: 'document',\n detail: `the document scrolls to ${page.scrollWidth}px at a ${window.innerWidth}px viewport`,\n });\n }\n\n for (const element of root.querySelectorAll('*')) {\n if (element.closest(chrome)) continue;\n const style = getComputedStyle(element);\n if (style.display === 'none' || style.display === 'contents') continue;\n // An inline box reports 0 for both, so every one of them would read as\n // overflowing its own zero width.\n if (element.clientWidth === 0) continue;\n elements++;\n if (style.overflowX === 'auto' || style.overflowX === 'scroll') continue;\n if (element.scrollWidth > element.clientWidth + tolerance) {\n failures.push({\n line: window.__liveTokensPageLine(element, source),\n tag: element.tagName.toLowerCase(),\n kind: 'element',\n detail: `<${element.tagName.toLowerCase()}> holds ${element.scrollWidth}px of content in `\n + `${element.clientWidth}px, and its overflow-x is ${style.overflowX}`,\n });\n }\n }\n\n const clips = (style: CSSStyleDeclaration) =>\n style.overflowX !== 'visible' || style.overflowY !== 'visible';\n for (const spec of list) {\n for (const instance of root.querySelectorAll(spec.root)) {\n if (instance.closest(chrome)) continue;\n let clipper: Element | null = null;\n for (let node = instance.parentElement; node; node = node.parentElement) {\n if (clips(getComputedStyle(node))) { clipper = node; break; }\n }\n if (!clipper) continue;\n const box = instance.getBoundingClientRect();\n const bounds = clipper.getBoundingClientRect();\n const past = [\n box.left < bounds.left - tolerance ? `${Math.round(bounds.left - box.left)}px past the left edge` : null,\n box.right > bounds.right + tolerance ? `${Math.round(box.right - bounds.right)}px past the right edge` : null,\n ].filter((side): side is string => side !== null);\n if (past.length === 0) continue;\n failures.push({\n line: window.__liveTokensPageLine(instance, source),\n tag: spec.id,\n kind: 'instance',\n detail: `${spec.id} sits ${past.join(' and ')} of the `\n + `<${clipper.tagName.toLowerCase()}> that clips it`,\n });\n }\n }\n return { elements, failures };\n }, { specs, container: PAGE_CONTAINER, chrome: CHROME, source: this.target.source, tolerance: 1 });\n }\n\n /**\n * Every rule reports the same three ways: it throws a `PageViolation` the\n * runner turns into a finding, returns a reason the run records as\n * `inapplicable`, or returns null, which is the pass. The suite files hold\n * no rule of their own so the defect fixtures measure what a consumer runs.\n */\n async assertComponentPaint(specs: ContractPaintSpec[]): Promise<string | null> {\n const observed = await this.observePaints(specs);\n if (observed.instances === 0) return `${this.target.source} renders no shipped component`;\n if (observed.failures.length > 0) {\n this.fail(\n 'page-component-paint',\n observed.failures[0].line,\n report(observed.failures, `${observed.asserted} contracted paints`, (failure) =>\n `line ${failure.line}: ${failure.id}${failure.variant ? ` (${failure.variant})` : ''} `\n + `paints ${failure.part} ${cssName(failure.css)}: ${failure.actual}, `\n + `but ${failure.variable} resolves to ${failure.expected}`),\n );\n }\n // A page holding an instance the rule cannot place in a variant is a page\n // the rule did not prove.\n if (observed.uncovered.length > 0) {\n return `${this.target.source}: no entry names the variant of `\n + observed.uncovered\n .map((instance) => `${instance.id} at line ${instance.line}, which offers ${instance.variants.join(', ')}`)\n .join('; ');\n }\n if (observed.asserted === 0) {\n return `no contracted part of a shipped instance is rendered on ${this.target.source}`;\n }\n return null;\n }\n\n async assertTextStyle(bundles: TextBundle[], componentRoots: string[]): Promise<string | null> {\n const observed = await this.observeTextStyles(bundles, componentRoots);\n if (observed.elements === 0) return `${this.target.source} renders no text outside a shipped component`;\n if (observed.failures.length > 0) {\n this.fail(\n 'page-text-style',\n observed.failures[0].line,\n report(observed.failures, `${observed.elements} runs of text`, (failure) =>\n `line ${failure.line}: <${failure.tag}> is in no shipped text style. `\n + `Nearest is ${failure.nearest}: its ${cssName(failure.axis)} is ${failure.expected}, `\n + `the element's is ${failure.actual}`),\n );\n }\n return null;\n }\n\n async assertContrast(componentRoots: string[]): Promise<string | null> {\n const observed = await this.observeContrast(componentRoots);\n const failures = observed.pairs\n .map((pair) => ({ pair, ratio: contrastRatio(hex(pair.color), hex(pair.background)), floor: aaFloor(pair) }))\n .filter(({ ratio, floor }) => ratio < floor);\n if (failures.length > 0) {\n const names = (colour: string, token: string | null) => (token ? `${token} (${colour})` : colour);\n this.fail(\n 'page-contrast',\n failures[0].pair.line,\n report(failures, `${observed.pairs.length} text and surface pairs`, ({ pair, ratio, floor }) =>\n `line ${pair.line}: <${pair.tag}> at ${pair.fontSize}px/${pair.fontWeight} sets `\n + `${names(pair.color, pair.colorToken)} on ${names(pair.background, pair.backgroundToken)}, `\n + `a ratio of ${ratio.toFixed(2)} against the ${floor} AA floor`),\n );\n }\n if (observed.pairs.length === 0) {\n const why = reasons(observed.skipped);\n return why\n ? `no text on ${this.target.source} sits on a surface the rule can read: ${why}`\n : `${this.target.source} renders no text outside a shipped component`;\n }\n return null;\n }\n\n async assertGrid(): Promise<string | null> {\n if (this.viewport.width < GRID_VIEWPORT) {\n return `the page is one column at ${this.viewport.width}px, below the ${GRID_VIEWPORT}px the grid needs`;\n }\n const observed = await this.observeGrid();\n if (observed.grids === 0) {\n this.fail(\n 'page-grid',\n observed.pageLine,\n `${this.target.source} draws no column grid: no element on it has as many tracks as `\n + '--columns-count. The page is the column grid, so its sections sit on one',\n );\n }\n if (observed.failures.length > 0) {\n this.fail(\n 'page-grid',\n observed.failures[0].line,\n report(observed.failures, `${observed.children} sections on ${observed.grids} column grids`, (failure) =>\n `line ${failure.line}: <${failure.tag}> sits ${Math.abs(failure.off)}px `\n + `to the ${failure.off < 0 ? 'left' : 'right'} of the nearest column line on its ${failure.edge}`),\n );\n }\n return null;\n }\n\n async assertOverflow(specs: ContractPaintSpec[]): Promise<string | null> {\n const observed = await this.observeOverflow(specs);\n if (observed.failures.length > 0) {\n this.fail(\n 'page-overflow',\n observed.failures[0].line,\n report(observed.failures, `${observed.elements} boxes`, (failure) =>\n `line ${failure.line}: ${failure.detail}`),\n );\n }\n return null;\n }\n}\n\n/** Installed on every page the run opens, so each rule reads the line the same\n * way. Svelte's dev build stamps every element with the file and line it was\n * written on; an element a component rendered carries the component's file, so\n * the nearest ancestor the page file names is the line of the instance. */\nexport async function installPageProbe(page: Page): Promise<void> {\n await page.addInitScript(() => {\n window.__liveTokensPageLine = (node: Element, source: string): number => {\n for (let element: Element | null = node; element; element = element.parentElement) {\n const loc = (element as { __svelte_meta?: { loc?: { file?: string; line?: number } } }).__svelte_meta?.loc;\n if (!loc || typeof loc.file !== 'string' || typeof loc.line !== 'number') continue;\n if (loc.file.split('\\\\').join('/').endsWith(source)) return loc.line;\n }\n return 1;\n };\n });\n}\n\ndeclare global {\n interface Window {\n __liveTokensPageLine: (node: Element, source: string) => number;\n }\n}\n"],"mappings":"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","names":["hex","componentRoots","bundles","axis"]}
@@ -25,9 +25,11 @@ describe("component registry contract", () => {
25
25
  requested ? `no component is registered under the id "${requested}"` : "no component is registered"
26
26
  ).not.toEqual([]);
27
27
  });
28
- it("registers every component authored in the project", () => {
29
- const ids = new Set(entries.map((entry) => entry.id));
30
- expect(authored.filter((id) => !ids.has(id))).toEqual([]);
28
+ describe.each(authored.map((id) => [id]))("%s", (id) => {
29
+ it("is registered", () => {
30
+ const ids = new Set(entries.map((entry) => entry.id));
31
+ expect(ids.has(id), `${id} is authored in the project and registered nowhere`).toBe(true);
32
+ });
31
33
  });
32
34
  describe.each(targets.map((entry) => [entry.id, entry]))("%s", (_id, entry) => {
33
35
  it("meets the registry contract", () => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../testing/registry.contract.ts"],"sourcesContent":["// @vitest-environment happy-dom\n/**\n * The registry contract, run against the project's own registrations.\n *\n * The setup module is what puts a consumer's components in the registry.\n * Importing an editor does not register it, and importing the app's entry point\n * would mount the app, so the project names a module that registers and stops\n * there. Without one, the run covers the components the package registers\n * itself.\n */\nimport path from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { describe, expect, it } from 'vitest';\nimport { checkRegistryEntry } from '../editor/component-editor/contract';\nimport { getComponentRegistryEntries } from '../editor/component-editor/registry';\n// @ts-expect-error — plain .mjs module, no types\nimport { discoverComponents } from '../../bin/check-component.mjs';\n\nconst REGISTRY_SETUP_ENV = 'LIVE_TOKENS_REGISTRY_SETUP';\n\nconst setupModule = process.env[REGISTRY_SETUP_ENV];\nif (setupModule) await import(pathToFileURL(path.resolve(setupModule)).href);\n\n/** `<package>/src/testing/` is this file's directory in the repository and in\n * an installed copy alike, so the package root is two levels up. */\nconst packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');\nconst consumerRoot = process.cwd();\nconst componentConfigsDir = path.resolve(\n process.env.LIVE_TOKENS_DATA_DIR ?? 'src/live-tokens/data',\n 'component-configs',\n);\n\nconst entries = getComponentRegistryEntries();\nconst requested = process.env.LIVE_TOKENS_COMPONENT;\nconst targets = requested ? entries.filter((entry) => entry.id === requested) : entries;\n\n/** Ids authored in this project. `discoverComponents` reports the runtime and\n * editor pair on disk, which is a different question from what the registry\n * holds: a component can exist as files and never be registered. */\nconst authored: string[] = discoverComponents(consumerRoot);\n\ndescribe('component registry contract', () => {\n it('selects at least one component', () => {\n expect(\n targets.map((entry) => entry.id),\n requested\n ? `no component is registered under the id \"${requested}\"`\n : 'no component is registered',\n ).not.toEqual([]);\n });\n\n it('registers every component authored in the project', () => {\n const ids = new Set(entries.map((entry) => entry.id));\n expect(authored.filter((id) => !ids.has(id))).toEqual([]);\n });\n\n describe.each(targets.map((entry) => [entry.id, entry] as const))('%s', (_id, entry) => {\n it('meets the registry contract', () => {\n // A shipped component's `sourceFile` is relative to the package; a\n // consumer's is relative to their own project.\n const projectRoot = entry.origin === 'system' ? packageRoot : consumerRoot;\n expect(checkRegistryEntry(entry, { projectRoot, componentConfigsDir })).toEqual([]);\n });\n });\n});\n"],"mappings":";AAUA,OAAO,UAAU;AACjB,SAAS,eAAe,qBAAqB;AAC7C,SAAS,UAAU,QAAQ,UAAU;AACrC,SAAS,0BAA0B;AACnC,SAAS,mCAAmC;AAE5C,SAAS,0BAA0B;AAEnC,IAAM,qBAAqB;AAE3B,IAAM,cAAc,QAAQ,IAAI,kBAAkB;AAClD,IAAI,YAAa,OAAM,OAAO,cAAc,KAAK,QAAQ,WAAW,CAAC,EAAE;AAIvE,IAAM,cAAc,KAAK,QAAQ,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC,GAAG,MAAM,IAAI;AACzF,IAAM,eAAe,QAAQ,IAAI;AACjC,IAAM,sBAAsB,KAAK;AAAA,EAC/B,QAAQ,IAAI,wBAAwB;AAAA,EACpC;AACF;AAEA,IAAM,UAAU,4BAA4B;AAC5C,IAAM,YAAY,QAAQ,IAAI;AAC9B,IAAM,UAAU,YAAY,QAAQ,OAAO,CAAC,UAAU,MAAM,OAAO,SAAS,IAAI;AAKhF,IAAM,WAAqB,mBAAmB,YAAY;AAE1D,SAAS,+BAA+B,MAAM;AAC5C,KAAG,kCAAkC,MAAM;AACzC;AAAA,MACE,QAAQ,IAAI,CAAC,UAAU,MAAM,EAAE;AAAA,MAC/B,YACI,4CAA4C,SAAS,MACrD;AAAA,IACN,EAAE,IAAI,QAAQ,CAAC,CAAC;AAAA,EAClB,CAAC;AAED,KAAG,qDAAqD,MAAM;AAC5D,UAAM,MAAM,IAAI,IAAI,QAAQ,IAAI,CAAC,UAAU,MAAM,EAAE,CAAC;AACpD,WAAO,SAAS,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,EAC1D,CAAC;AAED,WAAS,KAAK,QAAQ,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,KAAK,CAAU,CAAC,EAAE,MAAM,CAAC,KAAK,UAAU;AACtF,OAAG,+BAA+B,MAAM;AAGtC,YAAM,cAAc,MAAM,WAAW,WAAW,cAAc;AAC9D,aAAO,mBAAmB,OAAO,EAAE,aAAa,oBAAoB,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,IACpF,CAAC;AAAA,EACH,CAAC;AACH,CAAC;","names":[]}
1
+ {"version":3,"sources":["../testing/registry.contract.ts"],"sourcesContent":["// @vitest-environment happy-dom\n/**\n * The registry contract, run against the project's own registrations.\n *\n * The setup module is what puts a consumer's components in the registry.\n * Importing an editor does not register it, and importing the app's entry point\n * would mount the app, so the project names a module that registers and stops\n * there. Without one, the run covers the components the package registers\n * itself.\n */\nimport path from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { describe, expect, it } from 'vitest';\nimport { checkRegistryEntry } from '../editor/component-editor/contract';\nimport { getComponentRegistryEntries } from '../editor/component-editor/registry';\n// @ts-expect-error — plain .mjs module, no types\nimport { discoverComponents } from '../../bin/check-component.mjs';\n\nconst REGISTRY_SETUP_ENV = 'LIVE_TOKENS_REGISTRY_SETUP';\n\nconst setupModule = process.env[REGISTRY_SETUP_ENV];\nif (setupModule) await import(pathToFileURL(path.resolve(setupModule)).href);\n\n/** `<package>/src/testing/` is this file's directory in the repository and in\n * an installed copy alike, so the package root is two levels up. */\nconst packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');\nconst consumerRoot = process.cwd();\nconst componentConfigsDir = path.resolve(\n process.env.LIVE_TOKENS_DATA_DIR ?? 'src/live-tokens/data',\n 'component-configs',\n);\n\nconst entries = getComponentRegistryEntries();\nconst requested = process.env.LIVE_TOKENS_COMPONENT;\nconst targets = requested ? entries.filter((entry) => entry.id === requested) : entries;\n\n/** Ids authored in this project. `discoverComponents` reports the runtime and\n * editor pair on disk, which is a different question from what the registry\n * holds: a component can exist as files and never be registered. */\nconst authored: string[] = discoverComponents(consumerRoot);\n\ndescribe('component registry contract', () => {\n it('selects at least one component', () => {\n expect(\n targets.map((entry) => entry.id),\n requested\n ? `no component is registered under the id \"${requested}\"`\n : 'no component is registered',\n ).not.toEqual([]);\n });\n\n // One assertion per authored id, not one over the whole list: a failure that\n // names no component reaches the CLI as `tests-setup`, which means the\n // tooling never ran, and buries the id that is actually missing.\n describe.each(authored.map((id) => [id] as const))('%s', (id) => {\n it('is registered', () => {\n const ids = new Set(entries.map((entry) => entry.id));\n expect(ids.has(id), `${id} is authored in the project and registered nowhere`).toBe(true);\n });\n });\n\n describe.each(targets.map((entry) => [entry.id, entry] as const))('%s', (_id, entry) => {\n it('meets the registry contract', () => {\n // A shipped component's `sourceFile` is relative to the package; a\n // consumer's is relative to their own project.\n const projectRoot = entry.origin === 'system' ? packageRoot : consumerRoot;\n expect(checkRegistryEntry(entry, { projectRoot, componentConfigsDir })).toEqual([]);\n });\n });\n});\n"],"mappings":";AAUA,OAAO,UAAU;AACjB,SAAS,eAAe,qBAAqB;AAC7C,SAAS,UAAU,QAAQ,UAAU;AACrC,SAAS,0BAA0B;AACnC,SAAS,mCAAmC;AAE5C,SAAS,0BAA0B;AAEnC,IAAM,qBAAqB;AAE3B,IAAM,cAAc,QAAQ,IAAI,kBAAkB;AAClD,IAAI,YAAa,OAAM,OAAO,cAAc,KAAK,QAAQ,WAAW,CAAC,EAAE;AAIvE,IAAM,cAAc,KAAK,QAAQ,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC,GAAG,MAAM,IAAI;AACzF,IAAM,eAAe,QAAQ,IAAI;AACjC,IAAM,sBAAsB,KAAK;AAAA,EAC/B,QAAQ,IAAI,wBAAwB;AAAA,EACpC;AACF;AAEA,IAAM,UAAU,4BAA4B;AAC5C,IAAM,YAAY,QAAQ,IAAI;AAC9B,IAAM,UAAU,YAAY,QAAQ,OAAO,CAAC,UAAU,MAAM,OAAO,SAAS,IAAI;AAKhF,IAAM,WAAqB,mBAAmB,YAAY;AAE1D,SAAS,+BAA+B,MAAM;AAC5C,KAAG,kCAAkC,MAAM;AACzC;AAAA,MACE,QAAQ,IAAI,CAAC,UAAU,MAAM,EAAE;AAAA,MAC/B,YACI,4CAA4C,SAAS,MACrD;AAAA,IACN,EAAE,IAAI,QAAQ,CAAC,CAAC;AAAA,EAClB,CAAC;AAKD,WAAS,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,EAAE,CAAU,CAAC,EAAE,MAAM,CAAC,OAAO;AAC/D,OAAG,iBAAiB,MAAM;AACxB,YAAM,MAAM,IAAI,IAAI,QAAQ,IAAI,CAAC,UAAU,MAAM,EAAE,CAAC;AACpD,aAAO,IAAI,IAAI,EAAE,GAAG,GAAG,EAAE,oDAAoD,EAAE,KAAK,IAAI;AAAA,IAC1F,CAAC;AAAA,EACH,CAAC;AAED,WAAS,KAAK,QAAQ,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,KAAK,CAAU,CAAC,EAAE,MAAM,CAAC,KAAK,UAAU;AACtF,OAAG,+BAA+B,MAAM;AAGtC,YAAM,cAAc,MAAM,WAAW,WAAW,cAAc;AAC9D,aAAO,mBAAmB,OAAO,EAAE,aAAa,oBAAoB,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,IACpF,CAAC;AAAA,EACH,CAAC;AACH,CAAC;","names":[]}
@@ -68,8 +68,8 @@ declare function resolveTestingConfig(config?: LiveTokensTestingConfig, root?: s
68
68
  declare function devServerCommand(command: string, host: string, port: number): string;
69
69
 
70
70
  interface VitestConfigOptions {
71
- /** Files the run collects. Default: the shipped registry contract, matched
72
- * both in this package and in an installed copy of it. */
71
+ /** Files the run collects. Default: the shipped registry and behavior
72
+ * contracts, matched both in this package and in an installed copy. */
73
73
  include?: string[];
74
74
  exclude?: string[];
75
75
  setupFiles?: string[];
@@ -79,6 +79,12 @@ interface VitestConfigOptions {
79
79
  * components. Reaches the run as an environment variable because the
80
80
  * contract file resolves the path itself. */
81
81
  registrySetup?: string;
82
+ /** Module `selectedContracts()` imports a project's own `ComponentContract[]`
83
+ * from, same env-var seam as `registrySetup` and mirroring
84
+ * `createPlaywrightConfig`'s own use of it: the behavior contract's
85
+ * `describe.each` runs at module top, before a test can resolve anything
86
+ * for it. */
87
+ contractsModule?: string;
82
88
  }
83
89
  /**
84
90
  * The project's Vite config plus what the registry contract needs on top.
@@ -1,3 +1,3 @@
1
1
  import 'vite';
2
2
  import 'vitest/config';
3
- export { L as LiveTokensTestingConfig, R as ResolvedTestingConfig, V as VitestConfigOptions, d as createVitestConfig, e as defineTestingConfig, r as resolveTestingConfig } from './vitest-C-wNWcoA.js';
3
+ export { L as LiveTokensTestingConfig, R as ResolvedTestingConfig, V as VitestConfigOptions, d as createVitestConfig, e as defineTestingConfig, r as resolveTestingConfig } from './vitest-BMLIbDs2.js';
@@ -1,10 +1,11 @@
1
1
  import {
2
2
  createVitestConfig
3
- } from "./chunk-FAFOAWYL.js";
3
+ } from "./chunk-Q3YIAAG3.js";
4
4
  import {
5
5
  defineTestingConfig,
6
6
  resolveTestingConfig
7
7
  } from "./chunk-NB3NZRBM.js";
8
+ import "./chunk-ZMZQZ33J.js";
8
9
  export {
9
10
  createVitestConfig,
10
11
  defineTestingConfig,
@@ -5,10 +5,9 @@
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "vite",
8
- "build": "npm run check:design && vite build",
8
+ "build": "vite build",
9
9
  "preview": "vite preview",
10
10
  "check": "svelte-check --tsconfig ./tsconfig.json",
11
- "check:design": "live-tokens check-page && live-tokens check-component",
12
11
  "test:design": "live-tokens check-component --tests && live-tokens check-page --tests",
13
12
  "postinstall": "live-tokens setup-claude --force || exit 0"
14
13
  },
@@ -5,8 +5,9 @@ import { themeFileApi } from '@motion-proto/live-tokens/vite-plugin';
5
5
  export default defineConfig({
6
6
  plugins: [
7
7
  svelte({ preprocess: vitePreprocess() }),
8
- // Dev-only: persists editor changes to src/system/styles/tokens.css and
9
- // the JSON under src/live-tokens/data/. No effect on `vite build`.
8
+ // In dev, persists editor changes to src/system/styles/tokens.css and the
9
+ // JSON under src/live-tokens/data/. In `vite build`, runs the design checks
10
+ // first and stops the build on an error.
10
11
  themeFileApi({ tokensCssPath: 'src/system/styles/tokens.css' }),
11
12
  ],
12
13
  });