design-constraint-validator 1.0.0 → 2.0.1

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 (121) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +229 -659
  3. package/adapters/README.md +46 -46
  4. package/adapters/css.ts +116 -116
  5. package/adapters/decisionthemes.d.ts +44 -0
  6. package/adapters/decisionthemes.d.ts.map +1 -0
  7. package/adapters/decisionthemes.js +35 -0
  8. package/adapters/decisionthemes.ts +59 -0
  9. package/adapters/js.ts +14 -14
  10. package/adapters/json.ts +45 -45
  11. package/cli/build-css.ts +32 -32
  12. package/cli/commands/build.ts +65 -65
  13. package/cli/commands/graph.d.ts.map +1 -1
  14. package/cli/commands/graph.js +26 -10
  15. package/cli/commands/graph.ts +180 -137
  16. package/cli/commands/index.ts +7 -7
  17. package/cli/commands/patch-apply.ts +80 -80
  18. package/cli/commands/patch.ts +22 -22
  19. package/cli/commands/set.d.ts.map +1 -1
  20. package/cli/commands/set.js +12 -4
  21. package/cli/commands/set.ts +239 -225
  22. package/cli/commands/utils.ts +50 -50
  23. package/cli/commands/validate.d.ts.map +1 -1
  24. package/cli/commands/validate.js +89 -33
  25. package/cli/commands/validate.ts +180 -115
  26. package/cli/commands/why.d.ts.map +1 -1
  27. package/cli/commands/why.js +86 -20
  28. package/cli/commands/why.ts +158 -46
  29. package/cli/config-schema.ts +27 -27
  30. package/cli/config.ts +35 -35
  31. package/cli/constraint-registry.d.ts +101 -0
  32. package/cli/constraint-registry.d.ts.map +1 -0
  33. package/cli/constraint-registry.js +225 -0
  34. package/cli/constraint-registry.ts +304 -0
  35. package/cli/constraints-loader.d.ts.map +1 -0
  36. package/cli/cross-axis-loader.d.ts +91 -0
  37. package/cli/cross-axis-loader.d.ts.map +1 -0
  38. package/cli/cross-axis-loader.js +222 -0
  39. package/cli/cross-axis-loader.ts +289 -0
  40. package/cli/dcv.js +4 -0
  41. package/cli/dcv.ts +111 -107
  42. package/cli/engine-helpers.d.ts.map +1 -1
  43. package/cli/graph-poset.ts +74 -74
  44. package/cli/json-output.d.ts +69 -0
  45. package/cli/json-output.d.ts.map +1 -0
  46. package/cli/json-output.js +109 -0
  47. package/cli/json-output.ts +184 -0
  48. package/cli/result.ts +27 -27
  49. package/cli/run.ts +54 -54
  50. package/cli/smoke-test.ts +40 -40
  51. package/cli/types.d.ts +6 -0
  52. package/cli/types.d.ts.map +1 -1
  53. package/cli/types.ts +84 -78
  54. package/cli/version-banner.d.ts +20 -0
  55. package/cli/version-banner.d.ts.map +1 -0
  56. package/cli/version-banner.js +49 -0
  57. package/cli/version-banner.ts +61 -0
  58. package/core/breakpoints.ts +50 -50
  59. package/core/cli-format.ts +31 -31
  60. package/core/color.ts +148 -148
  61. package/core/constraints/cross-axis.ts +114 -114
  62. package/core/constraints/monotonic-lightness.ts +38 -38
  63. package/core/constraints/monotonic.ts +74 -74
  64. package/core/constraints/threshold.ts +43 -43
  65. package/core/constraints/wcag.ts +70 -70
  66. package/core/cross-axis-config.d.ts.map +1 -1
  67. package/core/engine.d.ts +95 -0
  68. package/core/engine.d.ts.map +1 -1
  69. package/core/engine.js +22 -0
  70. package/core/engine.ts +167 -65
  71. package/core/flatten.ts +116 -116
  72. package/core/image-export.ts +48 -48
  73. package/core/index.d.ts +9 -30
  74. package/core/index.d.ts.map +1 -1
  75. package/core/index.js +7 -54
  76. package/core/index.ts +10 -72
  77. package/core/patch.ts +134 -134
  78. package/core/poset.ts +311 -311
  79. package/core/why.ts +63 -63
  80. package/package.json +96 -90
  81. package/themes/color.lg.order.json +15 -15
  82. package/themes/color.md.order.json +15 -15
  83. package/themes/color.order.json +15 -15
  84. package/themes/color.sm.order.json +15 -15
  85. package/themes/cross-axis.rules.json +35 -35
  86. package/themes/cross-axis.sm.rules.json +12 -12
  87. package/themes/layout.lg.order.json +18 -18
  88. package/themes/layout.md.order.json +18 -18
  89. package/themes/layout.order.json +18 -18
  90. package/themes/layout.sm.order.json +18 -18
  91. package/themes/spacing.order.json +14 -14
  92. package/themes/typography.lg.order.json +15 -15
  93. package/themes/typography.md.order.json +15 -15
  94. package/themes/typography.order.json +15 -15
  95. package/themes/typography.sm.order.json +15 -15
  96. package/cli/engine-helpers.d.ts +0 -8
  97. package/cli/engine-helpers.js +0 -70
  98. package/cli/engine-helpers.ts +0 -61
  99. package/core/cross-axis-config.d.ts +0 -5
  100. package/core/cross-axis-config.js +0 -144
  101. package/core/cross-axis-config.ts +0 -152
  102. package/dist/test-overrides-removal.json +0 -4
  103. package/dist/tmp.patch.json +0 -35
  104. package/tokens/overrides/base.json +0 -22
  105. package/tokens/overrides/lg.json +0 -20
  106. package/tokens/overrides/md.json +0 -16
  107. package/tokens/overrides/sm.json +0 -16
  108. package/tokens/overrides/viol.color.json +0 -6
  109. package/tokens/overrides/viol.typography.json +0 -6
  110. package/tokens/tokens.demo-violations.json +0 -116
  111. package/tokens/tokens.example.json +0 -128
  112. package/tokens/tokens.json +0 -67
  113. package/tokens/tokens.multi-violations.json +0 -21
  114. package/tokens/tokens.schema.d.ts +0 -2298
  115. package/tokens/tokens.schema.d.ts.map +0 -1
  116. package/tokens/tokens.schema.js +0 -148
  117. package/tokens/tokens.schema.ts +0 -196
  118. package/tokens/tokens.test.json +0 -38
  119. package/tokens/tokens.touch-violation.json +0 -8
  120. package/tokens/typography.classes.css +0 -11
  121. package/tokens/typography.css +0 -20
package/cli/smoke-test.ts CHANGED
@@ -1,40 +1,40 @@
1
- // cli/smoke-test.ts
2
- import { writeFileSync, readFileSync, mkdirSync } from "node:fs";
3
- import { dirname } from "node:path";
4
- import { flattenTokens } from "../core/flatten.js";
5
- import { Engine } from "../core/engine.js";
6
- import { WcagContrastPlugin } from "../core/constraints/wcag.js";
7
- import { patchToCss } from "../adapters/css.js";
8
-
9
- // 1. Flatten tokens
10
- const tokensRoot = JSON.parse(readFileSync("tokens/tokens.example.json", "utf8"));
11
- const { flat, edges } = flattenTokens(tokensRoot);
12
-
13
- // 2. Build engine
14
- const init: Record<string, string | number> = {};
15
- for (const [id, t] of Object.entries(flat)) init[id] = t.value;
16
-
17
- const engine = new Engine(init, edges).use(
18
- WcagContrastPlugin([
19
- { fg: "color.role.text.default", bg: "color.role.bg.surface", min: 4.5, where: "Body text" },
20
- ])
21
- );
22
-
23
- // 3. Commit one change
24
- const overrideId = "color.palette.brand.600";
25
- const overrideValue = "#FF00FF"; // A loud magenta to make it obvious
26
- const result = engine.commit(overrideId, overrideValue);
27
-
28
- console.log("--- Smoke Test ---");
29
- console.log(`Committed: ${overrideId} = ${overrideValue}`);
30
- console.log("Affected:", result.affected);
31
- console.log("Issues:", result.issues);
32
- console.log("Patch:", result.patch);
33
-
34
- // 4. Write overrides.css using the adapter
35
- const css = patchToCss(result.patch);
36
- const outFile = "css/overrides.css";
37
- mkdirSync(dirname(outFile), { recursive: true });
38
- writeFileSync(outFile, css);
39
- console.log(`\nWrote ${outFile}`);
40
- console.log("--- End Smoke Test ---");
1
+ // cli/smoke-test.ts
2
+ import { writeFileSync, readFileSync, mkdirSync } from "node:fs";
3
+ import { dirname } from "node:path";
4
+ import { flattenTokens } from "../core/flatten.js";
5
+ import { Engine } from "../core/engine.js";
6
+ import { WcagContrastPlugin } from "../core/constraints/wcag.js";
7
+ import { patchToCss } from "../adapters/css.js";
8
+
9
+ // 1. Flatten tokens
10
+ const tokensRoot = JSON.parse(readFileSync("tokens/tokens.example.json", "utf8"));
11
+ const { flat, edges } = flattenTokens(tokensRoot);
12
+
13
+ // 2. Build engine
14
+ const init: Record<string, string | number> = {};
15
+ for (const [id, t] of Object.entries(flat)) init[id] = t.value;
16
+
17
+ const engine = new Engine(init, edges).use(
18
+ WcagContrastPlugin([
19
+ { fg: "color.role.text.default", bg: "color.role.bg.surface", min: 4.5, where: "Body text" },
20
+ ])
21
+ );
22
+
23
+ // 3. Commit one change
24
+ const overrideId = "color.palette.brand.600";
25
+ const overrideValue = "#FF00FF"; // A loud magenta to make it obvious
26
+ const result = engine.commit(overrideId, overrideValue);
27
+
28
+ console.log("--- Smoke Test ---");
29
+ console.log(`Committed: ${overrideId} = ${overrideValue}`);
30
+ console.log("Affected:", result.affected);
31
+ console.log("Issues:", result.issues);
32
+ console.log("Patch:", result.patch);
33
+
34
+ // 4. Write overrides.css using the adapter
35
+ const css = patchToCss(result.patch);
36
+ const outFile = "css/overrides.css";
37
+ mkdirSync(dirname(outFile), { recursive: true });
38
+ writeFileSync(outFile, css);
39
+ console.log(`\nWrote ${outFile}`);
40
+ console.log("--- End Smoke Test ---");
package/cli/types.d.ts CHANGED
@@ -18,6 +18,7 @@ export type OverridesTree = {
18
18
  export interface GlobalOptions {
19
19
  tokens?: string;
20
20
  config?: string;
21
+ theme?: string;
21
22
  verbose?: boolean;
22
23
  quiet?: boolean;
23
24
  breakpoint?: 'sm' | 'md' | 'lg';
@@ -47,6 +48,11 @@ export interface ValidateOptions extends GlobalOptions {
47
48
  perf?: boolean;
48
49
  budgetTotalMs?: number;
49
50
  budgetPerBpMs?: number;
51
+ format?: 'text' | 'json';
52
+ output?: string;
53
+ receipt?: string;
54
+ failOn?: 'off' | 'warn' | 'error';
55
+ summary?: 'none' | 'table' | 'json';
50
56
  }
51
57
  export interface GraphOptions extends GlobalOptions {
52
58
  output?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,MAAM,WAAW,cAAc;IAAG,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE;AAChH,MAAM,MAAM,SAAS,GAAG,eAAe,CAAC;AACxC,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AACrD,MAAM,WAAW,aAAa;IAAG,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;CAAE;AAClE,MAAM,MAAM,aAAa,GAAG;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,aAAa,CAAA;CAAE,GAAG,aAAa,CAAC;AAE3F,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAChC,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AACD,MAAM,WAAW,UAAW,SAAQ,aAAa;IAC/C,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AACD,MAAM,WAAW,YAAa,SAAQ,aAAa;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AACD,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACpD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AACD,MAAM,WAAW,YAAa,SAAQ,aAAa;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;IACpD,SAAS,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AACD,MAAM,WAAW,UAAW,SAAQ,aAAa;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3B;AACD,MAAM,WAAW,YAAa,SAAQ,aAAa;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AACD,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AACD,YAAY,EAAE,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"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"}
package/cli/types.ts CHANGED
@@ -1,78 +1,84 @@
1
- import type { TokenValue } from '../core/flatten.js';
2
- import type { Breakpoint } from '../core/breakpoints.js';
3
- import type { DcvConfigParsed } from './config-schema.js';
4
-
5
- export interface WcagRuleConfig { foreground: string; background: string; ratio?: number; description?: string }
6
- export type DcvConfig = DcvConfigParsed;
7
- export type ValuesPatch = Record<string, TokenValue>;
8
- export interface OverridesLeaf { $value?: string | number | null }
9
- export type OverridesTree = { [k: string]: OverridesTree | OverridesLeaf } & OverridesLeaf;
10
-
11
- export interface GlobalOptions {
12
- tokens?: string;
13
- config?: string;
14
- verbose?: boolean;
15
- quiet?: boolean;
16
- breakpoint?: 'sm' | 'md' | 'lg';
17
- allBreakpoints?: boolean;
18
- }
19
- export interface SetOptions extends GlobalOptions {
20
- expressions: string[];
21
- output?: string;
22
- format?: 'json' | 'css' | 'js';
23
- theme?: string;
24
- write?: boolean;
25
- json?: string;
26
- unset?: string[];
27
- }
28
- export interface BuildOptions extends GlobalOptions {
29
- output?: string;
30
- format?: 'css' | 'json' | 'js';
31
- watch?: boolean;
32
- theme?: string;
33
- mapper?: string;
34
- dryRun?: boolean;
35
- allFormats?: boolean;
36
- }
37
- export interface ValidateOptions extends GlobalOptions {
38
- strict?: boolean;
39
- constraints?: string[];
40
- perf?: boolean;
41
- budgetTotalMs?: number;
42
- budgetPerBpMs?: number;
43
- }
44
- export interface GraphOptions extends GlobalOptions {
45
- output?: string;
46
- format?: 'dot' | 'mermaid' | 'json' | 'svg' | 'png';
47
- imageFrom?: 'mermaid' | 'dot';
48
- filter?: string;
49
- hasse?: string;
50
- filterPrefix?: string;
51
- excludePrefix?: string;
52
- onlyViolations?: boolean;
53
- highlightViolations?: boolean;
54
- violationColor?: string;
55
- labelViolations?: boolean;
56
- labelTruncate?: number;
57
- minSeverity?: 'warn' | 'error';
58
- focus?: string;
59
- radius?: number;
60
- tokens?: string;
61
- }
62
- export interface WhyOptions extends GlobalOptions {
63
- tokenId: string;
64
- format?: 'json' | 'table';
65
- }
66
- export interface PatchOptions extends GlobalOptions {
67
- overrides?: string; // path to flat overrides json or inline json
68
- output?: string;
69
- format?: 'json' | 'css' | 'js';
70
- tokens?: string;
71
- }
72
- export interface PatchApplyOptions extends GlobalOptions {
73
- patch: string; // path or inline patch JSON
74
- output?: string; // where to write updated tokens (if omitted, prints result)
75
- tokens?: string; // source tokens file (baseline)
76
- dryRun?: boolean; // if true do not write
77
- }
78
- export type { Breakpoint };
1
+ import type { TokenValue } from '../core/flatten.js';
2
+ import type { Breakpoint } from '../core/breakpoints.js';
3
+ import type { DcvConfigParsed } from './config-schema.js';
4
+
5
+ export interface WcagRuleConfig { foreground: string; background: string; ratio?: number; description?: string }
6
+ export type DcvConfig = DcvConfigParsed;
7
+ export type ValuesPatch = Record<string, TokenValue>;
8
+ export interface OverridesLeaf { $value?: string | number | null }
9
+ export type OverridesTree = { [k: string]: OverridesTree | OverridesLeaf } & OverridesLeaf;
10
+
11
+ export interface GlobalOptions {
12
+ tokens?: string;
13
+ config?: string;
14
+ theme?: string;
15
+ verbose?: boolean;
16
+ quiet?: boolean;
17
+ breakpoint?: 'sm' | 'md' | 'lg';
18
+ allBreakpoints?: boolean;
19
+ }
20
+ export interface SetOptions extends GlobalOptions {
21
+ expressions: string[];
22
+ output?: string;
23
+ format?: 'json' | 'css' | 'js';
24
+ theme?: string;
25
+ write?: boolean;
26
+ json?: string;
27
+ unset?: string[];
28
+ }
29
+ export interface BuildOptions extends GlobalOptions {
30
+ output?: string;
31
+ format?: 'css' | 'json' | 'js';
32
+ watch?: boolean;
33
+ theme?: string;
34
+ mapper?: string;
35
+ dryRun?: boolean;
36
+ allFormats?: boolean;
37
+ }
38
+ export interface ValidateOptions extends GlobalOptions {
39
+ strict?: boolean;
40
+ constraints?: string[];
41
+ perf?: boolean;
42
+ budgetTotalMs?: number;
43
+ budgetPerBpMs?: number;
44
+ format?: 'text' | 'json';
45
+ output?: string;
46
+ receipt?: string;
47
+ failOn?: 'off' | 'warn' | 'error';
48
+ summary?: 'none' | 'table' | 'json';
49
+ }
50
+ export interface GraphOptions extends GlobalOptions {
51
+ output?: string;
52
+ format?: 'dot' | 'mermaid' | 'json' | 'svg' | 'png';
53
+ imageFrom?: 'mermaid' | 'dot';
54
+ filter?: string;
55
+ hasse?: string;
56
+ filterPrefix?: string;
57
+ excludePrefix?: string;
58
+ onlyViolations?: boolean;
59
+ highlightViolations?: boolean;
60
+ violationColor?: string;
61
+ labelViolations?: boolean;
62
+ labelTruncate?: number;
63
+ minSeverity?: 'warn' | 'error';
64
+ focus?: string;
65
+ radius?: number;
66
+ tokens?: string;
67
+ }
68
+ export interface WhyOptions extends GlobalOptions {
69
+ tokenId: string;
70
+ format?: 'json' | 'table';
71
+ }
72
+ export interface PatchOptions extends GlobalOptions {
73
+ overrides?: string; // path to flat overrides json or inline json
74
+ output?: string;
75
+ format?: 'json' | 'css' | 'js';
76
+ tokens?: string;
77
+ }
78
+ export interface PatchApplyOptions extends GlobalOptions {
79
+ patch: string; // path or inline patch JSON
80
+ output?: string; // where to write updated tokens (if omitted, prints result)
81
+ tokens?: string; // source tokens file (baseline)
82
+ dryRun?: boolean; // if true do not write
83
+ }
84
+ export type { Breakpoint };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Version banner utility
3
+ * Displays DCV version info when validation runs
4
+ */
5
+ /**
6
+ * Print DCV version banner
7
+ * Shows: DCV v{version} | {repo_url}
8
+ */
9
+ export declare function printVersionBanner(options?: {
10
+ quiet?: boolean;
11
+ }): void;
12
+ /**
13
+ * Get version string for JSON output
14
+ */
15
+ export declare function getVersionInfo(): {
16
+ name: string;
17
+ version: string;
18
+ repository: string;
19
+ };
20
+ //# sourceMappingURL=version-banner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-banner.d.ts","sourceRoot":"","sources":["version-banner.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAkCH;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAOtE;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAOtF"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Version banner utility
3
+ * Displays DCV version info when validation runs
4
+ */
5
+ import { readFileSync } from 'node:fs';
6
+ import { join, dirname } from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+ const __dirname = dirname(fileURLToPath(import.meta.url));
9
+ let cachedPkg = null;
10
+ function getPackageInfo() {
11
+ if (cachedPkg)
12
+ return cachedPkg;
13
+ try {
14
+ const pkgPath = join(__dirname, '../package.json');
15
+ const pkgContent = readFileSync(pkgPath, 'utf-8');
16
+ cachedPkg = JSON.parse(pkgContent);
17
+ return cachedPkg;
18
+ }
19
+ catch {
20
+ // Fallback if package.json not found
21
+ return {
22
+ name: 'design-constraint-validator',
23
+ version: '2.0.0',
24
+ homepage: 'https://github.com/CseperkePapp/design-constraint-validator'
25
+ };
26
+ }
27
+ }
28
+ /**
29
+ * Print DCV version banner
30
+ * Shows: DCV v{version} | {repo_url}
31
+ */
32
+ export function printVersionBanner(options) {
33
+ if (options?.quiet)
34
+ return;
35
+ const pkg = getPackageInfo();
36
+ const repoUrl = pkg.homepage || 'https://github.com/CseperkePapp/design-constraint-validator';
37
+ console.log(`\x1b[2m${pkg.name} v${pkg.version} | ${repoUrl}\x1b[0m`);
38
+ }
39
+ /**
40
+ * Get version string for JSON output
41
+ */
42
+ export function getVersionInfo() {
43
+ const pkg = getPackageInfo();
44
+ return {
45
+ name: pkg.name,
46
+ version: pkg.version,
47
+ repository: pkg.homepage || 'https://github.com/CseperkePapp/design-constraint-validator'
48
+ };
49
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Version banner utility
3
+ * Displays DCV version info when validation runs
4
+ */
5
+
6
+ import { readFileSync } from 'node:fs';
7
+ import { join, dirname } from 'node:path';
8
+ import { fileURLToPath } from 'node:url';
9
+
10
+ const __dirname = dirname(fileURLToPath(import.meta.url));
11
+
12
+ interface PackageJson {
13
+ name: string;
14
+ version: string;
15
+ homepage?: string;
16
+ }
17
+
18
+ let cachedPkg: PackageJson | null = null;
19
+
20
+ function getPackageInfo(): PackageJson {
21
+ if (cachedPkg) return cachedPkg;
22
+
23
+ try {
24
+ const pkgPath = join(__dirname, '../package.json');
25
+ const pkgContent = readFileSync(pkgPath, 'utf-8');
26
+ cachedPkg = JSON.parse(pkgContent);
27
+ return cachedPkg!;
28
+ } catch {
29
+ // Fallback if package.json not found
30
+ return {
31
+ name: 'design-constraint-validator',
32
+ version: '2.0.0',
33
+ homepage: 'https://github.com/CseperkePapp/design-constraint-validator'
34
+ };
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Print DCV version banner
40
+ * Shows: DCV v{version} | {repo_url}
41
+ */
42
+ export function printVersionBanner(options?: { quiet?: boolean }): void {
43
+ if (options?.quiet) return;
44
+
45
+ const pkg = getPackageInfo();
46
+ const repoUrl = pkg.homepage || 'https://github.com/CseperkePapp/design-constraint-validator';
47
+
48
+ console.log(`\x1b[2m${pkg.name} v${pkg.version} | ${repoUrl}\x1b[0m`);
49
+ }
50
+
51
+ /**
52
+ * Get version string for JSON output
53
+ */
54
+ export function getVersionInfo(): { name: string; version: string; repository: string } {
55
+ const pkg = getPackageInfo();
56
+ return {
57
+ name: pkg.name,
58
+ version: pkg.version,
59
+ repository: pkg.homepage || 'https://github.com/CseperkePapp/design-constraint-validator'
60
+ };
61
+ }
@@ -1,50 +1,50 @@
1
- // core/breakpoints.ts
2
- import fs from "node:fs";
3
- import type { TokenNode } from "./flatten.js";
4
-
5
- export type Breakpoint = "sm" | "md" | "lg";
6
-
7
- export function parseBreakpoints(argv: string[]): Breakpoint[] {
8
- const allIdx = argv.indexOf("--all-breakpoints");
9
- if (allIdx >= 0) return ["sm", "md", "lg"];
10
- const bpIdx = argv.indexOf("--breakpoint");
11
- if (bpIdx >= 0) return [argv[bpIdx + 1] as Breakpoint];
12
- return []; // no BP slicing requested
13
- }
14
-
15
- export function loadJsonSafe<T = unknown>(path: string): T | null {
16
- try {
17
- const data = JSON.parse(fs.readFileSync(path, "utf8"));
18
- return data;
19
- } catch {
20
- return null;
21
- }
22
- }
23
-
24
- export function loadOrders(axis: string, bp?: Breakpoint): [string, "<=" | ">=", string][] {
25
- const withBp = bp ? loadJsonSafe<{ order: unknown[] }>(`themes/${axis}.${bp}.order.json`) : null;
26
- if (withBp?.order) return withBp.order as [string, "<=" | ">=", string][];
27
- const global = loadJsonSafe<{ order: unknown[] }>(`themes/${axis}.order.json`);
28
- return (global?.order ?? []) as [string, "<=" | ">=", string][];
29
- }
30
-
31
- export function mergeTokens(base: unknown, overlay: unknown): TokenNode {
32
- if (!overlay) return base as TokenNode;
33
- if (typeof base !== "object" || base === null) return overlay as TokenNode;
34
- const out = Array.isArray(base) ? [...base] : { ...base };
35
- for (const k of Object.keys(overlay as Record<string, unknown>)) {
36
- (out as Record<string, unknown>)[k] = mergeTokens((base as Record<string, unknown>)?.[k], (overlay as Record<string, unknown>)[k]);
37
- }
38
- return out as TokenNode;
39
- }
40
-
41
- /** Load tokens with optional breakpoint override: base + overrides/<bp>.json */
42
- /**
43
- * Load tokens with override precedence: base < local < breakpoint
44
- */
45
- export function loadTokensWithBreakpoint(bp?: Breakpoint): TokenNode {
46
- const base = loadJsonSafe<TokenNode>("tokens/tokens.example.json") ?? {};
47
- const local = loadJsonSafe<TokenNode>("tokens/overrides/local.json");
48
- const ov = bp ? loadJsonSafe<TokenNode>(`tokens/overrides/${bp}.json`) : null;
49
- return mergeTokens(mergeTokens(base, local), ov);
50
- }
1
+ // core/breakpoints.ts
2
+ import fs from "node:fs";
3
+ import type { TokenNode } from "./flatten.js";
4
+
5
+ export type Breakpoint = "sm" | "md" | "lg";
6
+
7
+ export function parseBreakpoints(argv: string[]): Breakpoint[] {
8
+ const allIdx = argv.indexOf("--all-breakpoints");
9
+ if (allIdx >= 0) return ["sm", "md", "lg"];
10
+ const bpIdx = argv.indexOf("--breakpoint");
11
+ if (bpIdx >= 0) return [argv[bpIdx + 1] as Breakpoint];
12
+ return []; // no BP slicing requested
13
+ }
14
+
15
+ export function loadJsonSafe<T = unknown>(path: string): T | null {
16
+ try {
17
+ const data = JSON.parse(fs.readFileSync(path, "utf8"));
18
+ return data;
19
+ } catch {
20
+ return null;
21
+ }
22
+ }
23
+
24
+ export function loadOrders(axis: string, bp?: Breakpoint): [string, "<=" | ">=", string][] {
25
+ const withBp = bp ? loadJsonSafe<{ order: unknown[] }>(`themes/${axis}.${bp}.order.json`) : null;
26
+ if (withBp?.order) return withBp.order as [string, "<=" | ">=", string][];
27
+ const global = loadJsonSafe<{ order: unknown[] }>(`themes/${axis}.order.json`);
28
+ return (global?.order ?? []) as [string, "<=" | ">=", string][];
29
+ }
30
+
31
+ export function mergeTokens(base: unknown, overlay: unknown): TokenNode {
32
+ if (!overlay) return base as TokenNode;
33
+ if (typeof base !== "object" || base === null) return overlay as TokenNode;
34
+ const out = Array.isArray(base) ? [...base] : { ...base };
35
+ for (const k of Object.keys(overlay as Record<string, unknown>)) {
36
+ (out as Record<string, unknown>)[k] = mergeTokens((base as Record<string, unknown>)?.[k], (overlay as Record<string, unknown>)[k]);
37
+ }
38
+ return out as TokenNode;
39
+ }
40
+
41
+ /** Load tokens with optional breakpoint override: base + overrides/<bp>.json */
42
+ /**
43
+ * Load tokens with override precedence: base < local < breakpoint
44
+ */
45
+ export function loadTokensWithBreakpoint(bp?: Breakpoint): TokenNode {
46
+ const base = loadJsonSafe<TokenNode>("tokens/tokens.example.json") ?? {};
47
+ const local = loadJsonSafe<TokenNode>("tokens/overrides/local.json");
48
+ const ov = bp ? loadJsonSafe<TokenNode>(`tokens/overrides/${bp}.json`) : null;
49
+ return mergeTokens(mergeTokens(base, local), ov);
50
+ }
@@ -1,31 +1,31 @@
1
- // core/cli-format.ts
2
- export function pad(s: string, w: number) {
3
- if (s.length >= w) return s;
4
- return s + " ".repeat(w - s.length);
5
- }
6
-
7
- export function trunc(s: string, w: number) {
8
- return s.length <= w ? s : s.slice(0, Math.max(0, w - 1)) + "…";
9
- }
10
-
11
- export function levenshtein(a: string, b: string): number {
12
- const dp = Array(b.length + 1).fill(0).map((_, j) => j);
13
- for (let i = 1; i <= a.length; i++) {
14
- let prev = i - 1, cur = i;
15
- for (let j = 1; j <= b.length; j++) {
16
- const tmp = cur;
17
- cur = Math.min(dp[j] + 1, cur + 1, prev + (a[i - 1] === b[j - 1] ? 0 : 1));
18
- dp[j] = tmp;
19
- prev = tmp;
20
- }
21
- dp[b.length] = cur;
22
- }
23
- return dp[b.length];
24
- }
25
-
26
- export function suggestIds(id: string, candidates: string[], k = 3): { id: string; d: number }[] {
27
- return candidates
28
- .map(c => ({ id: c, d: levenshtein(id, c) }))
29
- .sort((x, y) => x.d - y.d)
30
- .slice(0, k);
31
- }
1
+ // core/cli-format.ts
2
+ export function pad(s: string, w: number) {
3
+ if (s.length >= w) return s;
4
+ return s + " ".repeat(w - s.length);
5
+ }
6
+
7
+ export function trunc(s: string, w: number) {
8
+ return s.length <= w ? s : s.slice(0, Math.max(0, w - 1)) + "…";
9
+ }
10
+
11
+ export function levenshtein(a: string, b: string): number {
12
+ const dp = Array(b.length + 1).fill(0).map((_, j) => j);
13
+ for (let i = 1; i <= a.length; i++) {
14
+ let prev = i - 1, cur = i;
15
+ for (let j = 1; j <= b.length; j++) {
16
+ const tmp = cur;
17
+ cur = Math.min(dp[j] + 1, cur + 1, prev + (a[i - 1] === b[j - 1] ? 0 : 1));
18
+ dp[j] = tmp;
19
+ prev = tmp;
20
+ }
21
+ dp[b.length] = cur;
22
+ }
23
+ return dp[b.length];
24
+ }
25
+
26
+ export function suggestIds(id: string, candidates: string[], k = 3): { id: string; d: number }[] {
27
+ return candidates
28
+ .map(c => ({ id: c, d: levenshtein(id, c) }))
29
+ .sort((x, y) => x.d - y.d)
30
+ .slice(0, k);
31
+ }