design-constraint-validator 1.0.0 → 1.1.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.
- package/LICENSE +21 -21
- package/README.md +215 -659
- package/adapters/README.md +46 -46
- package/adapters/css.ts +116 -116
- 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 +86 -33
- package/cli/commands/validate.ts +176 -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 +30 -0
- package/cli/constraints-loader.d.ts.map +1 -0
- package/cli/constraints-loader.js +58 -0
- package/cli/constraints-loader.ts +83 -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 +33 -0
- package/cli/engine-helpers.d.ts.map +1 -1
- package/cli/engine-helpers.js +87 -22
- package/cli/engine-helpers.ts +133 -61
- package/cli/graph-poset.ts +74 -74
- package/cli/json-output.d.ts +64 -0
- package/cli/json-output.d.ts.map +1 -0
- package/cli/json-output.js +107 -0
- package/cli/json-output.ts +177 -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/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 +29 -0
- package/core/cross-axis-config.d.ts.map +1 -1
- package/core/cross-axis-config.js +29 -0
- package/core/cross-axis-config.ts +181 -151
- 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/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/dcv.js
CHANGED
|
@@ -47,7 +47,11 @@ cli.command('build', 'Build token outputs', y => y
|
|
|
47
47
|
cli.command('validate', 'Validate constraints', y => y
|
|
48
48
|
.option('fail-on', { type: 'string', choices: ['off', 'warn', 'error'], default: 'error' })
|
|
49
49
|
.option('summary', { type: 'string', choices: ['none', 'table', 'json'], default: 'none' })
|
|
50
|
+
.option('format', { type: 'string', choices: ['text', 'json'], default: 'text', describe: 'Output format' })
|
|
51
|
+
.option('output', { type: 'string', describe: 'Write JSON output to file' })
|
|
52
|
+
.option('receipt', { type: 'string', describe: 'Generate validation receipt with audit trail' })
|
|
50
53
|
.option('tokens', { type: 'string', default: 'tokens/tokens.example.json' })
|
|
54
|
+
.option('theme', { type: 'string', describe: 'Apply named theme tokens before validation' })
|
|
51
55
|
.option('breakpoint', { type: 'string' })
|
|
52
56
|
.option('all-breakpoints', { type: 'boolean' })
|
|
53
57
|
.option('perf', { type: 'boolean', describe: 'Print timing info' })
|
package/cli/dcv.ts
CHANGED
|
@@ -1,107 +1,111 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Clean minimal DCV CLI entrypoint
|
|
3
|
-
import yargs from 'yargs/yargs';
|
|
4
|
-
import { hideBin } from 'yargs/helpers';
|
|
5
|
-
import { spawnSync } from 'node:child_process';
|
|
6
|
-
import { createRequire } from 'module';
|
|
7
|
-
import path from 'node:path';
|
|
8
|
-
import { type SetOptions, type BuildOptions, type ValidateOptions, type GraphOptions, type WhyOptions, type PatchOptions, type PatchApplyOptions } from './types.js';
|
|
9
|
-
import { setCommand, buildCommand, validateCommand, graphCommand, whyCommand, patchCommand, patchApplyCommand } from './commands/index.js';
|
|
10
|
-
|
|
11
|
-
// Early intercept: experimental graph diff helper
|
|
12
|
-
(() => {
|
|
13
|
-
const args = process.argv.slice(2);
|
|
14
|
-
if (args[0] === 'graph' && args[1] === 'diff') {
|
|
15
|
-
const pass = args.slice(2);
|
|
16
|
-
const require = createRequire(import.meta.url);
|
|
17
|
-
const tsx = (() => { try { return require.resolve('tsx/dist/cli.mjs'); } catch { return path.resolve('node_modules/tsx/dist/cli.mjs'); }})();
|
|
18
|
-
const r = spawnSync(process.execPath, [tsx, path.resolve('scripts/graph-diff.ts'), ...pass], { stdio: 'inherit', env: process.env });
|
|
19
|
-
process.exit(r.status ?? 0);
|
|
20
|
-
}
|
|
21
|
-
})();
|
|
22
|
-
|
|
23
|
-
const cli = yargs(hideBin(process.argv))
|
|
24
|
-
.scriptName('dcv')
|
|
25
|
-
.parserConfiguration({ 'camel-case-expansion': false })
|
|
26
|
-
.option('quiet', { type: 'boolean' });
|
|
27
|
-
|
|
28
|
-
cli.command<SetOptions>('set <expressions..>', 'Set token values', y => y
|
|
29
|
-
.positional('expressions', { type: 'string', array: true })
|
|
30
|
-
.option('dry-run', { type: 'boolean', default: false })
|
|
31
|
-
.option('write', { type: 'boolean' })
|
|
32
|
-
.option('json', { type: 'string' })
|
|
33
|
-
.option('unset', { type: 'array', string: true })
|
|
34
|
-
.option('format', { type: 'string', choices: ['json','css','js'], default: 'json' })
|
|
35
|
-
.option('output', { type: 'string' })
|
|
36
|
-
.option('theme', { type: 'string' })
|
|
37
|
-
.option('tokens', { type: 'string', default: 'tokens/tokens.example.json' }),
|
|
38
|
-
a => setCommand(a)
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
cli.command<BuildOptions>('build', 'Build token outputs', y => y
|
|
42
|
-
.option('format', { type: 'string', choices: ['css','json','js'], default: 'css' })
|
|
43
|
-
.option('all-formats', { type: 'boolean', default: false })
|
|
44
|
-
.option('output', { type: 'string' })
|
|
45
|
-
.option('mapper', { type: 'string' })
|
|
46
|
-
.option('theme', { type: 'string' })
|
|
47
|
-
.option('dry-run', { type: 'boolean', default: false })
|
|
48
|
-
.option('tokens', { type: 'string', default: 'tokens/tokens.example.json' }),
|
|
49
|
-
a => buildCommand(a)
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
cli.command<ValidateOptions>('validate', 'Validate constraints', y => y
|
|
53
|
-
.option('fail-on', { type: 'string', choices: ['off','warn','error'], default: 'error' })
|
|
54
|
-
.option('summary', { type: 'string', choices: ['none','table','json'], default: 'none' })
|
|
55
|
-
.option('
|
|
56
|
-
.option('
|
|
57
|
-
.option('
|
|
58
|
-
.option('
|
|
59
|
-
.option('
|
|
60
|
-
.option('
|
|
61
|
-
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
.option('
|
|
70
|
-
.option('
|
|
71
|
-
.option('
|
|
72
|
-
.option('
|
|
73
|
-
.option('
|
|
74
|
-
.option('
|
|
75
|
-
.option('
|
|
76
|
-
.option('
|
|
77
|
-
.option('
|
|
78
|
-
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Clean minimal DCV CLI entrypoint
|
|
3
|
+
import yargs from 'yargs/yargs';
|
|
4
|
+
import { hideBin } from 'yargs/helpers';
|
|
5
|
+
import { spawnSync } from 'node:child_process';
|
|
6
|
+
import { createRequire } from 'module';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { type SetOptions, type BuildOptions, type ValidateOptions, type GraphOptions, type WhyOptions, type PatchOptions, type PatchApplyOptions } from './types.js';
|
|
9
|
+
import { setCommand, buildCommand, validateCommand, graphCommand, whyCommand, patchCommand, patchApplyCommand } from './commands/index.js';
|
|
10
|
+
|
|
11
|
+
// Early intercept: experimental graph diff helper
|
|
12
|
+
(() => {
|
|
13
|
+
const args = process.argv.slice(2);
|
|
14
|
+
if (args[0] === 'graph' && args[1] === 'diff') {
|
|
15
|
+
const pass = args.slice(2);
|
|
16
|
+
const require = createRequire(import.meta.url);
|
|
17
|
+
const tsx = (() => { try { return require.resolve('tsx/dist/cli.mjs'); } catch { return path.resolve('node_modules/tsx/dist/cli.mjs'); }})();
|
|
18
|
+
const r = spawnSync(process.execPath, [tsx, path.resolve('scripts/graph-diff.ts'), ...pass], { stdio: 'inherit', env: process.env });
|
|
19
|
+
process.exit(r.status ?? 0);
|
|
20
|
+
}
|
|
21
|
+
})();
|
|
22
|
+
|
|
23
|
+
const cli = yargs(hideBin(process.argv))
|
|
24
|
+
.scriptName('dcv')
|
|
25
|
+
.parserConfiguration({ 'camel-case-expansion': false })
|
|
26
|
+
.option('quiet', { type: 'boolean' });
|
|
27
|
+
|
|
28
|
+
cli.command<SetOptions>('set <expressions..>', 'Set token values', y => y
|
|
29
|
+
.positional('expressions', { type: 'string', array: true })
|
|
30
|
+
.option('dry-run', { type: 'boolean', default: false })
|
|
31
|
+
.option('write', { type: 'boolean' })
|
|
32
|
+
.option('json', { type: 'string' })
|
|
33
|
+
.option('unset', { type: 'array', string: true })
|
|
34
|
+
.option('format', { type: 'string', choices: ['json','css','js'], default: 'json' })
|
|
35
|
+
.option('output', { type: 'string' })
|
|
36
|
+
.option('theme', { type: 'string' })
|
|
37
|
+
.option('tokens', { type: 'string', default: 'tokens/tokens.example.json' }),
|
|
38
|
+
a => setCommand(a)
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
cli.command<BuildOptions>('build', 'Build token outputs', y => y
|
|
42
|
+
.option('format', { type: 'string', choices: ['css','json','js'], default: 'css' })
|
|
43
|
+
.option('all-formats', { type: 'boolean', default: false })
|
|
44
|
+
.option('output', { type: 'string' })
|
|
45
|
+
.option('mapper', { type: 'string' })
|
|
46
|
+
.option('theme', { type: 'string' })
|
|
47
|
+
.option('dry-run', { type: 'boolean', default: false })
|
|
48
|
+
.option('tokens', { type: 'string', default: 'tokens/tokens.example.json' }),
|
|
49
|
+
a => buildCommand(a)
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
cli.command<ValidateOptions>('validate', 'Validate constraints', y => y
|
|
53
|
+
.option('fail-on', { type: 'string', choices: ['off','warn','error'], default: 'error' })
|
|
54
|
+
.option('summary', { type: 'string', choices: ['none','table','json'], default: 'none' })
|
|
55
|
+
.option('format', { type: 'string', choices: ['text','json'], default: 'text', describe: 'Output format' })
|
|
56
|
+
.option('output', { type: 'string', describe: 'Write JSON output to file' })
|
|
57
|
+
.option('receipt', { type: 'string', describe: 'Generate validation receipt with audit trail' })
|
|
58
|
+
.option('tokens', { type: 'string', default: 'tokens/tokens.example.json' })
|
|
59
|
+
.option('theme', { type: 'string', describe: 'Apply named theme tokens before validation' })
|
|
60
|
+
.option('breakpoint', { type: 'string' })
|
|
61
|
+
.option('all-breakpoints', { type: 'boolean' })
|
|
62
|
+
.option('perf', { type: 'boolean', describe: 'Print timing info' })
|
|
63
|
+
.option('budget-total-ms', { type: 'number', describe: 'Fail if total validation exceeds this (ms)' })
|
|
64
|
+
.option('budget-per-bp-ms', { type: 'number', describe: 'Fail if any single breakpoint exceeds this (ms)' }),
|
|
65
|
+
a => validateCommand(a)
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
cli.command<GraphOptions>('graph', 'Generate dependency / constraint graph', y => y
|
|
69
|
+
.option('format', { type: 'string', choices: ['json','mermaid','dot','svg','png'], default: 'json' })
|
|
70
|
+
.option('bundle', { type: 'boolean', describe: 'When used with --hasse export mermaid+dot (+image if svg/png requested)' })
|
|
71
|
+
.option('hasse', { type: 'string' })
|
|
72
|
+
.option('filter-prefix', { type: 'string' })
|
|
73
|
+
.option('exclude-prefix', { type: 'string' })
|
|
74
|
+
.option('only-violations', { type: 'boolean' })
|
|
75
|
+
.option('highlight-violations', { type: 'boolean' })
|
|
76
|
+
.option('label-violations', { type: 'boolean' })
|
|
77
|
+
.option('label-truncate', { type: 'number', default: 0 })
|
|
78
|
+
.option('min-severity', { type: 'string', choices: ['warn','error'], default: 'warn' })
|
|
79
|
+
.option('focus', { type: 'string' })
|
|
80
|
+
.option('radius', { type: 'number', default: 1 })
|
|
81
|
+
.option('tokens', { type: 'string', default: 'tokens/tokens.example.json' }),
|
|
82
|
+
a => graphCommand(a)
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
cli.command<WhyOptions>('why <tokenId>', 'Explain token provenance', y => y
|
|
86
|
+
.positional('tokenId', { type: 'string', demandOption: true })
|
|
87
|
+
.option('format', { type: 'string', choices: ['json','table'], default: 'json' })
|
|
88
|
+
.option('tokens', { type: 'string', default: 'tokens/tokens.example.json' }),
|
|
89
|
+
a => whyCommand(a)
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
cli.command<PatchOptions>('patch', 'Export patch (diff) from overrides', y => y
|
|
93
|
+
.option('overrides', { type: 'string', describe: 'Path or inline JSON of flat overrides' })
|
|
94
|
+
.option('format', { type: 'string', choices: ['json','css','js'], default: 'json' })
|
|
95
|
+
.option('output', { type: 'string' })
|
|
96
|
+
.option('tokens', { type: 'string', default: 'tokens/tokens.example.json' }),
|
|
97
|
+
a => patchCommand(a)
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
cli.command<PatchApplyOptions>('patch:apply <patch>', 'Apply patch document to tokens', y => y
|
|
101
|
+
.positional('patch', { type: 'string', demandOption: true })
|
|
102
|
+
.option('tokens', { type: 'string', default: 'tokens/tokens.example.json' })
|
|
103
|
+
.option('output', { type: 'string', describe: 'Write updated tokens to this file' })
|
|
104
|
+
.option('dry-run', { type: 'boolean', default: false }),
|
|
105
|
+
a => patchApplyCommand(a)
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
cli.help().alias('h','help').strict().wrap(cli.terminalWidth());
|
|
109
|
+
cli.parse();
|
|
110
|
+
|
|
111
|
+
// EOF
|
package/cli/engine-helpers.d.ts
CHANGED
|
@@ -1,8 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @deprecated This module is deprecated. Use constraint-registry.ts instead.
|
|
3
|
+
*
|
|
4
|
+
* Phase 3A (Architectural Cleanup): This file contains legacy constraint loading logic
|
|
5
|
+
* that has been replaced by the centralized constraint-registry.ts module.
|
|
6
|
+
*
|
|
7
|
+
* Migration guide:
|
|
8
|
+
* - Replace createEngine() or createValidationEngine() with:
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { Engine } from '../core/engine.js';
|
|
11
|
+
* import { flattenTokens, type FlatToken } from '../core/flatten.js';
|
|
12
|
+
* import { setupConstraints } from './constraint-registry.js';
|
|
13
|
+
*
|
|
14
|
+
* const { flat, edges } = flattenTokens(tokens);
|
|
15
|
+
* const init = {};
|
|
16
|
+
* for (const t of Object.values(flat)) {
|
|
17
|
+
* init[(t as FlatToken).id] = (t as FlatToken).value;
|
|
18
|
+
* }
|
|
19
|
+
* const engine = new Engine(init, edges);
|
|
20
|
+
* const knownIds = new Set(Object.keys(init));
|
|
21
|
+
* setupConstraints(engine, { config, bp }, { knownIds });
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* This file will be removed in a future major version.
|
|
25
|
+
*/
|
|
1
26
|
import { type TokenNode } from '../core/flatten.js';
|
|
2
27
|
import { Engine } from '../core/engine.js';
|
|
3
28
|
import { loadTokensWithBreakpoint, type Breakpoint } from '../core/breakpoints.js';
|
|
4
29
|
import type { DcvConfig } from './types.js';
|
|
30
|
+
/**
|
|
31
|
+
* @deprecated Use constraint-registry.ts setupConstraints() instead.
|
|
32
|
+
* This function will be removed in a future major version.
|
|
33
|
+
*/
|
|
5
34
|
export declare function createEngine(tokensRoot: TokenNode, config?: DcvConfig): Engine;
|
|
35
|
+
/**
|
|
36
|
+
* @deprecated Use constraint-registry.ts setupConstraints() instead.
|
|
37
|
+
* This function will be removed in a future major version.
|
|
38
|
+
*/
|
|
6
39
|
export declare function createValidationEngine(tokensRoot: TokenNode, bp: Breakpoint | undefined, config: DcvConfig): Engine;
|
|
7
40
|
export { loadTokensWithBreakpoint };
|
|
8
41
|
//# sourceMappingURL=engine-helpers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine-helpers.d.ts","sourceRoot":"","sources":["engine-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,EAAkB,MAAM,oBAAoB,CAAC;AACnF,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAI3C,OAAO,EAA8B,wBAAwB,EAAE,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAC/G,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"engine-helpers.d.ts","sourceRoot":"","sources":["engine-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAiB,KAAK,SAAS,EAAkB,MAAM,oBAAoB,CAAC;AACnF,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAI3C,OAAO,EAA8B,wBAAwB,EAAE,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAC/G,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAgE5C;;;GAGG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,SAAS,EAAE,MAAM,GAAE,SAAc,GAAG,MAAM,CAQlF;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,GAAG,SAAS,EAAE,MAAM,EAAE,SAAS,GAAG,MAAM,CAgBnH;AAED,OAAO,EAAE,wBAAwB,EAAE,CAAC"}
|
package/cli/engine-helpers.js
CHANGED
|
@@ -1,15 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @deprecated This module is deprecated. Use constraint-registry.ts instead.
|
|
3
|
+
*
|
|
4
|
+
* Phase 3A (Architectural Cleanup): This file contains legacy constraint loading logic
|
|
5
|
+
* that has been replaced by the centralized constraint-registry.ts module.
|
|
6
|
+
*
|
|
7
|
+
* Migration guide:
|
|
8
|
+
* - Replace createEngine() or createValidationEngine() with:
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { Engine } from '../core/engine.js';
|
|
11
|
+
* import { flattenTokens, type FlatToken } from '../core/flatten.js';
|
|
12
|
+
* import { setupConstraints } from './constraint-registry.js';
|
|
13
|
+
*
|
|
14
|
+
* const { flat, edges } = flattenTokens(tokens);
|
|
15
|
+
* const init = {};
|
|
16
|
+
* for (const t of Object.values(flat)) {
|
|
17
|
+
* init[(t as FlatToken).id] = (t as FlatToken).value;
|
|
18
|
+
* }
|
|
19
|
+
* const engine = new Engine(init, edges);
|
|
20
|
+
* const knownIds = new Set(Object.keys(init));
|
|
21
|
+
* setupConstraints(engine, { config, bp }, { knownIds });
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* This file will be removed in a future major version.
|
|
25
|
+
*/
|
|
1
26
|
import { flattenTokens } from '../core/flatten.js';
|
|
2
27
|
import { Engine } from '../core/engine.js';
|
|
3
28
|
import { MonotonicPlugin, parseSize as parseSizePx } from '../core/constraints/monotonic.js';
|
|
4
29
|
import { MonotonicLightness } from '../core/constraints/monotonic-lightness.js';
|
|
5
30
|
import { WcagContrastPlugin } from '../core/constraints/wcag.js';
|
|
6
31
|
import { loadOrders as loadOrdersBP, loadTokensWithBreakpoint } from '../core/breakpoints.js';
|
|
7
|
-
|
|
8
|
-
const { flat, edges } = flattenTokens(tokensRoot);
|
|
9
|
-
const init = {};
|
|
10
|
-
for (const [id, token] of Object.entries(flat))
|
|
11
|
-
init[id] = token.value;
|
|
12
|
-
const engine = new Engine(init, edges);
|
|
32
|
+
function applyMonotonicPlugins(engine, bp) {
|
|
13
33
|
function loadOrders(path) {
|
|
14
34
|
try {
|
|
15
35
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
@@ -19,10 +39,11 @@ export function createEngine(tokensRoot, config = {}) {
|
|
|
19
39
|
return [];
|
|
20
40
|
}
|
|
21
41
|
}
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const
|
|
42
|
+
const suffix = bp ? `.${bp}` : '';
|
|
43
|
+
const typOrders = loadOrders(`themes/typography${suffix}.order.json`);
|
|
44
|
+
const spacingOrders = loadOrders(`themes/spacing${suffix}.order.json`);
|
|
45
|
+
const layoutOrders = loadOrders(`themes/layout${suffix}.order.json`);
|
|
46
|
+
const colorOrders = loadOrders(`themes/color${suffix}.order.json`);
|
|
26
47
|
if (typOrders.length)
|
|
27
48
|
engine.use(MonotonicPlugin(typOrders, parseSizePx, 'monotonic-typography'));
|
|
28
49
|
if (spacingOrders.length)
|
|
@@ -31,24 +52,71 @@ export function createEngine(tokensRoot, config = {}) {
|
|
|
31
52
|
engine.use(MonotonicPlugin(layoutOrders, parseSizePx, 'monotonic-layout'));
|
|
32
53
|
if (colorOrders.length)
|
|
33
54
|
engine.use(MonotonicLightness(colorOrders));
|
|
34
|
-
|
|
35
|
-
|
|
55
|
+
}
|
|
56
|
+
function applyWcagPlugins(engine, config) {
|
|
57
|
+
const constraintsCfg = config.constraints ?? {};
|
|
58
|
+
if (constraintsCfg.wcag) {
|
|
59
|
+
const wcagRules = constraintsCfg.wcag.map((r) => ({
|
|
60
|
+
fg: r.foreground,
|
|
61
|
+
bg: r.background,
|
|
62
|
+
min: r.ratio || 4.5,
|
|
63
|
+
where: r.description || 'Unknown',
|
|
64
|
+
}));
|
|
36
65
|
engine.use(WcagContrastPlugin(wcagRules));
|
|
37
66
|
}
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
67
|
+
const enableDefaults = constraintsCfg.enableBuiltInWcagDefaults === undefined
|
|
68
|
+
? true
|
|
69
|
+
: !!constraintsCfg.enableBuiltInWcagDefaults;
|
|
70
|
+
if (enableDefaults) {
|
|
71
|
+
const defaultWcagPairs = [
|
|
72
|
+
{
|
|
73
|
+
fg: 'color.role.text.default',
|
|
74
|
+
bg: 'color.role.bg.surface',
|
|
75
|
+
min: 4.5,
|
|
76
|
+
where: 'Body text on surface',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
fg: 'color.role.accent.default',
|
|
80
|
+
bg: 'color.role.bg.surface',
|
|
81
|
+
min: 3.0,
|
|
82
|
+
where: 'Accent on surface',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
fg: 'color.role.focus.ring',
|
|
86
|
+
bg: 'color.role.bg.surface',
|
|
87
|
+
min: 3.0,
|
|
88
|
+
where: 'Focus ring on surface',
|
|
89
|
+
backdrop: '#ffffff',
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
engine.use(WcagContrastPlugin(defaultWcagPairs));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* @deprecated Use constraint-registry.ts setupConstraints() instead.
|
|
97
|
+
* This function will be removed in a future major version.
|
|
98
|
+
*/
|
|
99
|
+
export function createEngine(tokensRoot, config = {}) {
|
|
100
|
+
const { flat, edges } = flattenTokens(tokensRoot);
|
|
101
|
+
const init = {};
|
|
102
|
+
for (const [id, token] of Object.entries(flat))
|
|
103
|
+
init[id] = token.value;
|
|
104
|
+
const engine = new Engine(init, edges);
|
|
105
|
+
applyMonotonicPlugins(engine, undefined);
|
|
106
|
+
applyWcagPlugins(engine, config);
|
|
44
107
|
return engine;
|
|
45
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* @deprecated Use constraint-registry.ts setupConstraints() instead.
|
|
111
|
+
* This function will be removed in a future major version.
|
|
112
|
+
*/
|
|
46
113
|
export function createValidationEngine(tokensRoot, bp, config) {
|
|
47
114
|
const { flat, edges } = flattenTokens(tokensRoot);
|
|
48
115
|
const init = {};
|
|
49
116
|
for (const t of Object.values(flat))
|
|
50
117
|
init[t.id] = t.value;
|
|
51
118
|
const engine = new Engine(init, edges);
|
|
119
|
+
// Use breakpoint-aware order loading where available
|
|
52
120
|
const typ = loadOrdersBP('typography', bp);
|
|
53
121
|
const spc = loadOrdersBP('spacing', bp);
|
|
54
122
|
const lay = loadOrdersBP('layout', bp);
|
|
@@ -61,10 +129,7 @@ export function createValidationEngine(tokensRoot, bp, config) {
|
|
|
61
129
|
engine.use(MonotonicPlugin(lay, parseSizePx, 'monotonic-layout'));
|
|
62
130
|
if (col.length)
|
|
63
131
|
engine.use(MonotonicLightness(col));
|
|
64
|
-
|
|
65
|
-
const wcagRules = config.constraints.wcag.map((rule) => ({ fg: rule.foreground, bg: rule.background, min: rule.ratio || 4.5, where: rule.description || 'Unknown' }));
|
|
66
|
-
engine.use(WcagContrastPlugin(wcagRules));
|
|
67
|
-
}
|
|
132
|
+
applyWcagPlugins(engine, config);
|
|
68
133
|
return engine;
|
|
69
134
|
}
|
|
70
135
|
export { loadTokensWithBreakpoint };
|
package/cli/engine-helpers.ts
CHANGED
|
@@ -1,61 +1,133 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
const
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @deprecated This module is deprecated. Use constraint-registry.ts instead.
|
|
3
|
+
*
|
|
4
|
+
* Phase 3A (Architectural Cleanup): This file contains legacy constraint loading logic
|
|
5
|
+
* that has been replaced by the centralized constraint-registry.ts module.
|
|
6
|
+
*
|
|
7
|
+
* Migration guide:
|
|
8
|
+
* - Replace createEngine() or createValidationEngine() with:
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { Engine } from '../core/engine.js';
|
|
11
|
+
* import { flattenTokens, type FlatToken } from '../core/flatten.js';
|
|
12
|
+
* import { setupConstraints } from './constraint-registry.js';
|
|
13
|
+
*
|
|
14
|
+
* const { flat, edges } = flattenTokens(tokens);
|
|
15
|
+
* const init = {};
|
|
16
|
+
* for (const t of Object.values(flat)) {
|
|
17
|
+
* init[(t as FlatToken).id] = (t as FlatToken).value;
|
|
18
|
+
* }
|
|
19
|
+
* const engine = new Engine(init, edges);
|
|
20
|
+
* const knownIds = new Set(Object.keys(init));
|
|
21
|
+
* setupConstraints(engine, { config, bp }, { knownIds });
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* This file will be removed in a future major version.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import { flattenTokens, type TokenNode, type FlatToken } from '../core/flatten.js';
|
|
28
|
+
import { Engine } from '../core/engine.js';
|
|
29
|
+
import { MonotonicPlugin, parseSize as parseSizePx } from '../core/constraints/monotonic.js';
|
|
30
|
+
import { MonotonicLightness } from '../core/constraints/monotonic-lightness.js';
|
|
31
|
+
import { WcagContrastPlugin } from '../core/constraints/wcag.js';
|
|
32
|
+
import { loadOrders as loadOrdersBP, loadTokensWithBreakpoint, type Breakpoint } from '../core/breakpoints.js';
|
|
33
|
+
import type { DcvConfig } from './types.js';
|
|
34
|
+
|
|
35
|
+
function applyMonotonicPlugins(engine: Engine, bp: Breakpoint | undefined): void {
|
|
36
|
+
function loadOrders(path: string) {
|
|
37
|
+
try {
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
39
|
+
return JSON.parse(require('node:fs').readFileSync(path, 'utf8')).order as [string, '<='|'>=', string][];
|
|
40
|
+
} catch { return []; }
|
|
41
|
+
}
|
|
42
|
+
const suffix = bp ? `.${bp}` : '';
|
|
43
|
+
const typOrders = loadOrders(`themes/typography${suffix}.order.json`);
|
|
44
|
+
const spacingOrders = loadOrders(`themes/spacing${suffix}.order.json`);
|
|
45
|
+
const layoutOrders = loadOrders(`themes/layout${suffix}.order.json`);
|
|
46
|
+
const colorOrders = loadOrders(`themes/color${suffix}.order.json`);
|
|
47
|
+
if (typOrders.length) engine.use(MonotonicPlugin(typOrders, parseSizePx, 'monotonic-typography'));
|
|
48
|
+
if (spacingOrders.length) engine.use(MonotonicPlugin(spacingOrders, parseSizePx, 'monotonic-spacing'));
|
|
49
|
+
if (layoutOrders.length) engine.use(MonotonicPlugin(layoutOrders, parseSizePx, 'monotonic-layout'));
|
|
50
|
+
if (colorOrders.length) engine.use(MonotonicLightness(colorOrders));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function applyWcagPlugins(engine: Engine, config: DcvConfig): void {
|
|
54
|
+
const constraintsCfg = config.constraints ?? {};
|
|
55
|
+
|
|
56
|
+
if (constraintsCfg.wcag) {
|
|
57
|
+
const wcagRules = constraintsCfg.wcag.map((r: any) => ({
|
|
58
|
+
fg: r.foreground,
|
|
59
|
+
bg: r.background,
|
|
60
|
+
min: r.ratio || 4.5,
|
|
61
|
+
where: r.description || 'Unknown',
|
|
62
|
+
}));
|
|
63
|
+
engine.use(WcagContrastPlugin(wcagRules));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const enableDefaults =
|
|
67
|
+
constraintsCfg.enableBuiltInWcagDefaults === undefined
|
|
68
|
+
? true
|
|
69
|
+
: !!constraintsCfg.enableBuiltInWcagDefaults;
|
|
70
|
+
|
|
71
|
+
if (enableDefaults) {
|
|
72
|
+
const defaultWcagPairs = [
|
|
73
|
+
{
|
|
74
|
+
fg: 'color.role.text.default',
|
|
75
|
+
bg: 'color.role.bg.surface',
|
|
76
|
+
min: 4.5,
|
|
77
|
+
where: 'Body text on surface',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
fg: 'color.role.accent.default',
|
|
81
|
+
bg: 'color.role.bg.surface',
|
|
82
|
+
min: 3.0,
|
|
83
|
+
where: 'Accent on surface',
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
fg: 'color.role.focus.ring',
|
|
87
|
+
bg: 'color.role.bg.surface',
|
|
88
|
+
min: 3.0,
|
|
89
|
+
where: 'Focus ring on surface',
|
|
90
|
+
backdrop: '#ffffff',
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
engine.use(WcagContrastPlugin(defaultWcagPairs));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @deprecated Use constraint-registry.ts setupConstraints() instead.
|
|
99
|
+
* This function will be removed in a future major version.
|
|
100
|
+
*/
|
|
101
|
+
export function createEngine(tokensRoot: TokenNode, config: DcvConfig = {}): Engine {
|
|
102
|
+
const { flat, edges } = flattenTokens(tokensRoot);
|
|
103
|
+
const init: Record<string, string | number> = {};
|
|
104
|
+
for (const [id, token] of Object.entries(flat)) init[id] = (token as FlatToken).value;
|
|
105
|
+
const engine = new Engine(init, edges);
|
|
106
|
+
applyMonotonicPlugins(engine, undefined);
|
|
107
|
+
applyWcagPlugins(engine, config);
|
|
108
|
+
return engine;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @deprecated Use constraint-registry.ts setupConstraints() instead.
|
|
113
|
+
* This function will be removed in a future major version.
|
|
114
|
+
*/
|
|
115
|
+
export function createValidationEngine(tokensRoot: TokenNode, bp: Breakpoint | undefined, config: DcvConfig): Engine {
|
|
116
|
+
const { flat, edges } = flattenTokens(tokensRoot);
|
|
117
|
+
const init: Record<string, string | number> = {};
|
|
118
|
+
for (const t of Object.values(flat)) init[(t as FlatToken).id] = (t as FlatToken).value;
|
|
119
|
+
const engine = new Engine(init, edges);
|
|
120
|
+
// Use breakpoint-aware order loading where available
|
|
121
|
+
const typ = loadOrdersBP('typography', bp);
|
|
122
|
+
const spc = loadOrdersBP('spacing', bp);
|
|
123
|
+
const lay = loadOrdersBP('layout', bp);
|
|
124
|
+
const col = loadOrdersBP('color', bp);
|
|
125
|
+
if (typ.length) engine.use(MonotonicPlugin(typ, parseSizePx, 'monotonic-typography'));
|
|
126
|
+
if (spc.length) engine.use(MonotonicPlugin(spc, parseSizePx, 'monotonic-spacing'));
|
|
127
|
+
if (lay.length) engine.use(MonotonicPlugin(lay, parseSizePx, 'monotonic-layout'));
|
|
128
|
+
if (col.length) engine.use(MonotonicLightness(col));
|
|
129
|
+
applyWcagPlugins(engine, config);
|
|
130
|
+
return engine;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export { loadTokensWithBreakpoint };
|