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.
- package/LICENSE +21 -21
- package/README.md +229 -659
- package/adapters/README.md +46 -46
- package/adapters/css.ts +116 -116
- package/adapters/decisionthemes.d.ts +44 -0
- package/adapters/decisionthemes.d.ts.map +1 -0
- package/adapters/decisionthemes.js +35 -0
- package/adapters/decisionthemes.ts +59 -0
- package/adapters/js.ts +14 -14
- package/adapters/json.ts +45 -45
- package/cli/build-css.ts +32 -32
- package/cli/commands/build.ts +65 -65
- package/cli/commands/graph.d.ts.map +1 -1
- package/cli/commands/graph.js +26 -10
- package/cli/commands/graph.ts +180 -137
- package/cli/commands/index.ts +7 -7
- package/cli/commands/patch-apply.ts +80 -80
- package/cli/commands/patch.ts +22 -22
- package/cli/commands/set.d.ts.map +1 -1
- package/cli/commands/set.js +12 -4
- package/cli/commands/set.ts +239 -225
- package/cli/commands/utils.ts +50 -50
- package/cli/commands/validate.d.ts.map +1 -1
- package/cli/commands/validate.js +89 -33
- package/cli/commands/validate.ts +180 -115
- package/cli/commands/why.d.ts.map +1 -1
- package/cli/commands/why.js +86 -20
- package/cli/commands/why.ts +158 -46
- package/cli/config-schema.ts +27 -27
- package/cli/config.ts +35 -35
- package/cli/constraint-registry.d.ts +101 -0
- package/cli/constraint-registry.d.ts.map +1 -0
- package/cli/constraint-registry.js +225 -0
- package/cli/constraint-registry.ts +304 -0
- package/cli/constraints-loader.d.ts.map +1 -0
- package/cli/cross-axis-loader.d.ts +91 -0
- package/cli/cross-axis-loader.d.ts.map +1 -0
- package/cli/cross-axis-loader.js +222 -0
- package/cli/cross-axis-loader.ts +289 -0
- package/cli/dcv.js +4 -0
- package/cli/dcv.ts +111 -107
- package/cli/engine-helpers.d.ts.map +1 -1
- package/cli/graph-poset.ts +74 -74
- package/cli/json-output.d.ts +69 -0
- package/cli/json-output.d.ts.map +1 -0
- package/cli/json-output.js +109 -0
- package/cli/json-output.ts +184 -0
- package/cli/result.ts +27 -27
- package/cli/run.ts +54 -54
- package/cli/smoke-test.ts +40 -40
- package/cli/types.d.ts +6 -0
- package/cli/types.d.ts.map +1 -1
- package/cli/types.ts +84 -78
- package/cli/version-banner.d.ts +20 -0
- package/cli/version-banner.d.ts.map +1 -0
- package/cli/version-banner.js +49 -0
- package/cli/version-banner.ts +61 -0
- package/core/breakpoints.ts +50 -50
- package/core/cli-format.ts +31 -31
- package/core/color.ts +148 -148
- package/core/constraints/cross-axis.ts +114 -114
- package/core/constraints/monotonic-lightness.ts +38 -38
- package/core/constraints/monotonic.ts +74 -74
- package/core/constraints/threshold.ts +43 -43
- package/core/constraints/wcag.ts +70 -70
- package/core/cross-axis-config.d.ts.map +1 -1
- package/core/engine.d.ts +95 -0
- package/core/engine.d.ts.map +1 -1
- package/core/engine.js +22 -0
- package/core/engine.ts +167 -65
- package/core/flatten.ts +116 -116
- package/core/image-export.ts +48 -48
- package/core/index.d.ts +9 -30
- package/core/index.d.ts.map +1 -1
- package/core/index.js +7 -54
- package/core/index.ts +10 -72
- package/core/patch.ts +134 -134
- package/core/poset.ts +311 -311
- package/core/why.ts +63 -63
- package/package.json +96 -90
- package/themes/color.lg.order.json +15 -15
- package/themes/color.md.order.json +15 -15
- package/themes/color.order.json +15 -15
- package/themes/color.sm.order.json +15 -15
- package/themes/cross-axis.rules.json +35 -35
- package/themes/cross-axis.sm.rules.json +12 -12
- package/themes/layout.lg.order.json +18 -18
- package/themes/layout.md.order.json +18 -18
- package/themes/layout.order.json +18 -18
- package/themes/layout.sm.order.json +18 -18
- package/themes/spacing.order.json +14 -14
- package/themes/typography.lg.order.json +15 -15
- package/themes/typography.md.order.json +15 -15
- package/themes/typography.order.json +15 -15
- package/themes/typography.sm.order.json +15 -15
- package/cli/engine-helpers.d.ts +0 -8
- package/cli/engine-helpers.js +0 -70
- package/cli/engine-helpers.ts +0 -61
- package/core/cross-axis-config.d.ts +0 -5
- package/core/cross-axis-config.js +0 -144
- package/core/cross-axis-config.ts +0 -152
- package/dist/test-overrides-removal.json +0 -4
- package/dist/tmp.patch.json +0 -35
- package/tokens/overrides/base.json +0 -22
- package/tokens/overrides/lg.json +0 -20
- package/tokens/overrides/md.json +0 -16
- package/tokens/overrides/sm.json +0 -16
- package/tokens/overrides/viol.color.json +0 -6
- package/tokens/overrides/viol.typography.json +0 -6
- package/tokens/tokens.demo-violations.json +0 -116
- package/tokens/tokens.example.json +0 -128
- package/tokens/tokens.json +0 -67
- package/tokens/tokens.multi-violations.json +0 -21
- package/tokens/tokens.schema.d.ts +0 -2298
- package/tokens/tokens.schema.d.ts.map +0 -1
- package/tokens/tokens.schema.js +0 -148
- package/tokens/tokens.schema.ts +0 -196
- package/tokens/tokens.test.json +0 -38
- package/tokens/tokens.touch-violation.json +0 -8
- package/tokens/typography.classes.css +0 -11
- 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;
|
package/cli/types.d.ts.map
CHANGED
|
@@ -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;
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
output?: string;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
export interface
|
|
73
|
-
|
|
74
|
-
output?: string;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
export
|
|
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
|
+
}
|
package/core/breakpoints.ts
CHANGED
|
@@ -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
|
+
}
|
package/core/cli-format.ts
CHANGED
|
@@ -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
|
+
}
|