@dsgraph/rules 0.0.0-stage → 0.3.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 -0
- package/README.md +19 -2
- package/dist/check.d.ts +18 -0
- package/dist/check.d.ts.map +1 -0
- package/dist/check.js +122 -0
- package/dist/check.js.map +1 -0
- package/dist/color.d.ts +8 -0
- package/dist/color.d.ts.map +1 -0
- package/dist/color.js +25 -0
- package/dist/color.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/presets.d.ts +4 -0
- package/dist/presets.d.ts.map +1 -0
- package/dist/presets.js +27 -0
- package/dist/presets.js.map +1 -0
- package/dist/rules/code.d.ts +9 -0
- package/dist/rules/code.d.ts.map +1 -0
- package/dist/rules/code.js +188 -0
- package/dist/rules/code.js.map +1 -0
- package/dist/rules/layers.d.ts +4 -0
- package/dist/rules/layers.d.ts.map +1 -0
- package/dist/rules/layers.js +70 -0
- package/dist/rules/layers.js.map +1 -0
- package/dist/rules/tokens.d.ts +9 -0
- package/dist/rules/tokens.d.ts.map +1 -0
- package/dist/rules/tokens.js +195 -0
- package/dist/rules/tokens.js.map +1 -0
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +34 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Adam Reznik
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @dsgraph/rules
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Rule engine and built-in rules. Parse diagnostics are reported as findings too; every severity is configurable.
|
|
4
|
+
|
|
5
|
+
| Rule | Default |
|
|
6
|
+
|---|---|
|
|
7
|
+
| `token/deprecated-reference` | warning |
|
|
8
|
+
| `naming/normalized-collision` | warning |
|
|
9
|
+
| `color/hex-mismatch` | warning |
|
|
10
|
+
| `color/out-of-gamut` | info |
|
|
11
|
+
| `palette/non-monotonic`, `palette/duplicate-stops` | warning |
|
|
12
|
+
| `a11y/contrast-matrix` | off — set `text`, `surfaces`, `min`, `acknowledged` |
|
|
13
|
+
| `layer/alias-depth`, `layer/allowed-sources` | off — on in the `two-layer` preset |
|
|
14
|
+
|
|
15
|
+
Presets (architecture patterns only): `recommended`, `dtcg-strict`, `two-layer`.
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { check } from '@dsgraph/rules'
|
|
19
|
+
const findings = await check(graph, { extends: ['recommended'], rules: { 'color/out-of-gamut': 'off' } })
|
|
20
|
+
```
|
package/dist/check.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type CodeIndex, type Config, type DsGraph, type Finding, type Severity } from '@dsgraph/core';
|
|
2
|
+
import type { Rule } from './types.js';
|
|
3
|
+
export declare const RULES: readonly Rule[];
|
|
4
|
+
export interface Setting {
|
|
5
|
+
severity: Severity | 'off';
|
|
6
|
+
options: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
/** Rule defaults → presets from `extends` (in order) → `rules` from the config. */
|
|
9
|
+
export declare function resolveSettings(config: Config, rules?: readonly Rule[]): Map<string, Setting>;
|
|
10
|
+
/**
|
|
11
|
+
* Runs the rules over a graph. Parse diagnostics of the snapshot are reported as findings too;
|
|
12
|
+
* their severity can be overridden (or turned off) by code in `rules`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function check(graph: DsGraph, config?: Config, extraRules?: readonly Rule[], opts?: {
|
|
15
|
+
code?: CodeIndex;
|
|
16
|
+
}): Promise<Finding[]>;
|
|
17
|
+
export declare function countBySeverity(findings: readonly Finding[]): Record<Severity, number>;
|
|
18
|
+
//# sourceMappingURL=check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EACd,KAAK,MAAM,EAEX,KAAK,OAAO,EACZ,KAAK,OAAO,EACZ,KAAK,QAAQ,EAGd,MAAM,eAAe,CAAA;AAatB,OAAO,KAAK,EAAE,IAAI,EAAe,MAAM,YAAY,CAAA;AAEnD,eAAO,MAAM,KAAK,EAAE,SAAS,IAAI,EAehC,CAAA;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,QAAQ,GAAG,KAAK,CAAA;IAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACjC;AAID,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,SAAS,IAAI,EAAU,GAAG,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAqBpG;AAED;;;GAGG;AACH,wBAAsB,KAAK,CACzB,KAAK,EAAE,OAAO,EACd,MAAM,GAAE,MAAW,EACnB,UAAU,GAAE,SAAS,IAAI,EAAO,EAChC,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,SAAS,CAAA;CAAO,GAC9B,OAAO,CAAC,OAAO,EAAE,CAAC,CAiEpB;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAItF"}
|
package/dist/check.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { canonicalize, sha256Hex, VarMatcher, } from '@dsgraph/core';
|
|
2
|
+
import { PRESETS } from './presets.js';
|
|
3
|
+
import { deprecatedUsage, hardcodedColor, offScale, unknownToken, unusedToken } from './rules/code.js';
|
|
4
|
+
import { aliasDepth, allowedSources } from './rules/layers.js';
|
|
5
|
+
import { contrastMatrix, deprecatedReference, duplicateStops, hexMismatch, nonMonotonicPalette, normalizedCollision, outOfGamut, } from './rules/tokens.js';
|
|
6
|
+
export const RULES = [
|
|
7
|
+
deprecatedReference,
|
|
8
|
+
normalizedCollision,
|
|
9
|
+
hexMismatch,
|
|
10
|
+
outOfGamut,
|
|
11
|
+
nonMonotonicPalette,
|
|
12
|
+
duplicateStops,
|
|
13
|
+
contrastMatrix,
|
|
14
|
+
aliasDepth,
|
|
15
|
+
allowedSources,
|
|
16
|
+
hardcodedColor,
|
|
17
|
+
offScale,
|
|
18
|
+
deprecatedUsage,
|
|
19
|
+
unknownToken,
|
|
20
|
+
unusedToken,
|
|
21
|
+
];
|
|
22
|
+
const RANK = { error: 3, warning: 2, info: 1 };
|
|
23
|
+
/** Rule defaults → presets from `extends` (in order) → `rules` from the config. */
|
|
24
|
+
export function resolveSettings(config, rules = RULES) {
|
|
25
|
+
const settings = new Map();
|
|
26
|
+
for (const r of rules)
|
|
27
|
+
settings.set(r.id, { severity: r.defaultSeverity, options: {} });
|
|
28
|
+
const apply = (entries) => {
|
|
29
|
+
for (const [id, value] of Object.entries(entries)) {
|
|
30
|
+
const prev = settings.get(id) ?? { severity: 'warning', options: {} };
|
|
31
|
+
if (Array.isArray(value))
|
|
32
|
+
settings.set(id, {
|
|
33
|
+
severity: value[0],
|
|
34
|
+
options: { ...prev.options, ...value[1] },
|
|
35
|
+
});
|
|
36
|
+
else
|
|
37
|
+
settings.set(id, { ...prev, severity: value });
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
for (const name of config.extends ?? ['recommended']) {
|
|
41
|
+
const preset = PRESETS[name];
|
|
42
|
+
if (!preset)
|
|
43
|
+
throw new Error(`Unknown preset "${name}". Available: ${Object.keys(PRESETS).join(', ')}`);
|
|
44
|
+
apply(preset);
|
|
45
|
+
}
|
|
46
|
+
apply(config.rules ?? {});
|
|
47
|
+
return settings;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Runs the rules over a graph. Parse diagnostics of the snapshot are reported as findings too;
|
|
51
|
+
* their severity can be overridden (or turned off) by code in `rules`.
|
|
52
|
+
*/
|
|
53
|
+
export async function check(graph, config = {}, extraRules = [], opts = {}) {
|
|
54
|
+
const rules = [...RULES, ...extraRules];
|
|
55
|
+
const settings = resolveSettings(config, rules);
|
|
56
|
+
const code = opts.code;
|
|
57
|
+
const vars = code
|
|
58
|
+
? new VarMatcher(graph, code.uses.map((u) => u.name), config.code?.prefix)
|
|
59
|
+
: undefined;
|
|
60
|
+
const drafts = [];
|
|
61
|
+
const byOrigin = new Map();
|
|
62
|
+
for (const t of graph.tokens())
|
|
63
|
+
byOrigin.set(`${t.origin.file}#${t.origin.pointer}`, t.id);
|
|
64
|
+
for (const d of graph.snapshot.diagnostics) {
|
|
65
|
+
const severity = settings.get(d.code)?.severity ?? d.severity;
|
|
66
|
+
if (severity === 'off')
|
|
67
|
+
continue;
|
|
68
|
+
const node = d.loc ? byOrigin.get(`${d.loc.file}#${d.loc.pointer}`) : undefined;
|
|
69
|
+
const f = { rule: d.code, severity, message: d.message, nodes: node ? [node] : [] };
|
|
70
|
+
if (d.loc)
|
|
71
|
+
f.loc = d.loc;
|
|
72
|
+
drafts.push(f);
|
|
73
|
+
}
|
|
74
|
+
for (const rule of rules) {
|
|
75
|
+
const setting = settings.get(rule.id);
|
|
76
|
+
if (setting.severity === 'off')
|
|
77
|
+
continue;
|
|
78
|
+
const ctx = {
|
|
79
|
+
graph,
|
|
80
|
+
options: setting.options,
|
|
81
|
+
config,
|
|
82
|
+
...(code && vars ? { code, vars } : {}),
|
|
83
|
+
report(r) {
|
|
84
|
+
const f = {
|
|
85
|
+
rule: rule.id,
|
|
86
|
+
severity: r.severity && RANK[r.severity] < RANK[setting.severity]
|
|
87
|
+
? r.severity
|
|
88
|
+
: setting.severity,
|
|
89
|
+
message: r.message,
|
|
90
|
+
nodes: r.nodes,
|
|
91
|
+
};
|
|
92
|
+
if (r.evidence)
|
|
93
|
+
f.evidence = r.evidence;
|
|
94
|
+
if (r.when)
|
|
95
|
+
f.when = r.when;
|
|
96
|
+
if (r.loc)
|
|
97
|
+
f.loc = r.loc;
|
|
98
|
+
else if (r.token)
|
|
99
|
+
f.loc = r.token.origin;
|
|
100
|
+
drafts.push(f);
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
rule.run(ctx);
|
|
104
|
+
}
|
|
105
|
+
const findings = [];
|
|
106
|
+
for (const d of drafts)
|
|
107
|
+
findings.push({
|
|
108
|
+
// Findings in code differ by position; findings on tokens keep the ids they had.
|
|
109
|
+
id: `${d.rule}#${(await sha256Hex(canonicalize(d.loc?.line ? { n: d.nodes, w: d.when, m: d.message, l: d.loc } : { n: d.nodes, w: d.when, m: d.message }))).slice(0, 12)}`,
|
|
110
|
+
...d,
|
|
111
|
+
});
|
|
112
|
+
return findings.sort((a, b) => RANK[b.severity] - RANK[a.severity] ||
|
|
113
|
+
a.rule.localeCompare(b.rule) ||
|
|
114
|
+
a.message.localeCompare(b.message));
|
|
115
|
+
}
|
|
116
|
+
export function countBySeverity(findings) {
|
|
117
|
+
const out = { error: 0, warning: 0, info: 0 };
|
|
118
|
+
for (const f of findings)
|
|
119
|
+
out[f.severity]++;
|
|
120
|
+
return out;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,YAAY,EAIZ,SAAS,EACT,UAAU,GACX,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AACtG,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAC9D,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,WAAW,EACX,mBAAmB,EACnB,mBAAmB,EACnB,UAAU,GACX,MAAM,mBAAmB,CAAA;AAG1B,MAAM,CAAC,MAAM,KAAK,GAAoB;IACpC,mBAAmB;IACnB,mBAAmB;IACnB,WAAW;IACX,UAAU;IACV,mBAAmB;IACnB,cAAc;IACd,cAAc;IACd,UAAU;IACV,cAAc;IACd,cAAc;IACd,QAAQ;IACR,eAAe;IACf,YAAY;IACZ,WAAW;CACZ,CAAA;AAOD,MAAM,IAAI,GAA6B,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAA;AAExE,mFAAmF;AACnF,MAAM,UAAU,eAAe,CAAC,MAAc,EAAE,KAAK,GAAoB,KAAK;IAC5E,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAmB,CAAA;IAC3C,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,eAAe,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAA;IACvF,MAAM,KAAK,GAAG,CAAC,OAAgC,EAAE,EAAE;QACjD,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAkB,EAAE,OAAO,EAAE,EAAE,EAAE,CAAA;YAC9E,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;gBACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE;oBACf,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAwB;oBACzC,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,GAAI,KAAK,CAAC,CAAC,CAAY,EAAE;iBACtD,CAAC,CAAA;;gBACC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,KAA4B,EAAE,CAAC,CAAA;QAC5E,CAAC;IACH,CAAC,CAAA;IACD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,OAAO,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;QACrD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;QAC5B,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,iBAAiB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACvG,KAAK,CAAC,MAAM,CAAC,CAAA;IACf,CAAC;IACD,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAA;IACzB,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CACzB,KAAc,EACd,MAAM,GAAW,EAAE,EACnB,UAAU,GAAoB,EAAE,EAChC,IAAI,GAAyB,EAAE;IAE/B,MAAM,KAAK,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,UAAU,CAAC,CAAA;IACvC,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;IACtB,MAAM,IAAI,GAAG,IAAI;QACf,CAAC,CAAC,IAAI,UAAU,CACZ,KAAK,EACL,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAC5B,MAAM,CAAC,IAAI,EAAE,MAAM,CACpB;QACH,CAAC,CAAC,SAAS,CAAA;IACb,MAAM,MAAM,GAA+B,EAAE,CAAA;IAE7C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAA;IAC1C,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAA;IAC1F,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;QAC3C,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,QAAQ,IAAI,CAAC,CAAC,QAAQ,CAAA;QAC7D,IAAI,QAAQ,KAAK,KAAK;YAAE,SAAQ;QAChC,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QAC/E,MAAM,CAAC,GAAwB,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;QACxG,IAAI,CAAC,CAAC,GAAG;YAAE,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAA;QACxB,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAChB,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAE,CAAA;QACtC,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK;YAAE,SAAQ;QACxC,MAAM,GAAG,GAAgB;YACvB,KAAK;YACL,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,MAAM;YACN,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvC,MAAM,CAAC,CAAC;gBACN,MAAM,CAAC,GAAwB;oBAC7B,IAAI,EAAE,IAAI,CAAC,EAAE;oBACb,QAAQ,EACN,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,QAAoB,CAAC;wBACjE,CAAC,CAAC,CAAC,CAAC,QAAQ;wBACZ,CAAC,CAAE,OAAO,CAAC,QAAqB;oBACpC,OAAO,EAAE,CAAC,CAAC,OAAO;oBAClB,KAAK,EAAE,CAAC,CAAC,KAAK;iBACf,CAAA;gBACD,IAAI,CAAC,CAAC,QAAQ;oBAAE,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAA;gBACvC,IAAI,CAAC,CAAC,IAAI;oBAAE,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAA;gBAC3B,IAAI,CAAC,CAAC,GAAG;oBAAE,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAA;qBACnB,IAAI,CAAC,CAAC,KAAK;oBAAE,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAA;gBACxC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YAChB,CAAC;SACF,CAAA;QACD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACf,CAAC;IAED,MAAM,QAAQ,GAAc,EAAE,CAAA;IAC9B,KAAK,MAAM,CAAC,IAAI,MAAM;QACpB,QAAQ,CAAC,IAAI,CAAC;YACZ,iFAAiF;YACjF,EAAE,EAAE,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE;YAC1K,GAAG,CAAC;SACL,CAAC,CAAA;IACJ,OAAO,QAAQ,CAAC,IAAI,CAClB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;QACnC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC;QAC5B,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CACrC,CAAA;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAA4B;IAC1D,MAAM,GAAG,GAA6B,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAA;IACvE,KAAK,MAAM,CAAC,IAAI,QAAQ;QAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAA;IAC3C,OAAO,GAAG,CAAA;AACZ,CAAC"}
|
package/dist/color.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ColorValue } from '@dsgraph/core';
|
|
2
|
+
type Rgba = [number, number, number, number];
|
|
3
|
+
/** sRGB channels (0–1, clamped) and alpha of a canonical color value. */
|
|
4
|
+
export declare function rgba(c: ColorValue): Rgba;
|
|
5
|
+
/** WCAG 2.x contrast ratio of text over a surface; translucent surfaces sit on white. */
|
|
6
|
+
export declare function contrastRatio(text: ColorValue, surface: ColorValue): number;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=color.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.d.ts","sourceRoot":"","sources":["../src/color.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAY,MAAM,eAAe,CAAA;AAIzD,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAE5C,yEAAyE;AACzE,wBAAgB,IAAI,CAAC,CAAC,EAAE,UAAU,GAAG,IAAI,CAIxC;AAYD,yFAAyF;AACzF,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,GAAG,MAAM,CAK3E"}
|
package/dist/color.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { toCulori } from '@dsgraph/core';
|
|
2
|
+
import { converter } from 'culori';
|
|
3
|
+
const toRgb = converter('rgb');
|
|
4
|
+
/** sRGB channels (0–1, clamped) and alpha of a canonical color value. */
|
|
5
|
+
export function rgba(c) {
|
|
6
|
+
const rgb = toRgb(toCulori(c));
|
|
7
|
+
const clamp = (v) => Math.min(1, Math.max(0, v ?? 0));
|
|
8
|
+
return [clamp(rgb.r), clamp(rgb.g), clamp(rgb.b), c.alpha];
|
|
9
|
+
}
|
|
10
|
+
/** Composites `top` over an opaque `bottom`. */
|
|
11
|
+
function over(top, bottom) {
|
|
12
|
+
return [0, 1, 2].map((i) => top[i] * top[3] + bottom[i] * (1 - top[3]));
|
|
13
|
+
}
|
|
14
|
+
function luminance([r, g, b]) {
|
|
15
|
+
const lin = (v) => (v <= 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4);
|
|
16
|
+
return 0.2126 * lin(r) + 0.7152 * lin(g) + 0.0722 * lin(b);
|
|
17
|
+
}
|
|
18
|
+
/** WCAG 2.x contrast ratio of text over a surface; translucent surfaces sit on white. */
|
|
19
|
+
export function contrastRatio(text, surface) {
|
|
20
|
+
const bg = over(rgba(surface), [1, 1, 1]);
|
|
21
|
+
const fg = over(rgba(text), bg);
|
|
22
|
+
const [l1, l2] = [luminance(fg), luminance(bg)].sort((a, b) => b - a);
|
|
23
|
+
return (l1 + 0.05) / (l2 + 0.05);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=color.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.js","sourceRoot":"","sources":["../src/color.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,QAAQ,EAAE,MAAM,eAAe,CAAA;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAElC,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;AAG9B,yEAAyE;AACzE,MAAM,UAAU,IAAI,CAAC,CAAa;IAChC,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAsD,CAAA;IACnF,MAAM,KAAK,GAAG,CAAC,CAAqB,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACzE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAA;AAC5D,CAAC;AAED,gDAAgD;AAChD,SAAS,IAAI,CAAC,GAAS,EAAE,MAAgC;IACvD,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAE,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAE,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAA6B,CAAA;AACvG,CAAC;AAED,SAAS,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAA2B;IACpD,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,IAAI,GAAG,CAAC,CAAA;IACpF,OAAO,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAA;AAC5D,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,aAAa,CAAC,IAAgB,EAAE,OAAmB;IACjE,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IACzC,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAA;IAC/B,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAqB,CAAA;IACzF,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,CAAA;AAClC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { check, countBySeverity, RULES, resolveSettings, type Setting } from './check.js';
|
|
2
|
+
export { contrastRatio, rgba } from './color.js';
|
|
3
|
+
export { PRESETS } from './presets.js';
|
|
4
|
+
export type { Finding, Rule, RuleContext } from './types.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,OAAO,EAAE,MAAM,YAAY,CAAA;AACzF,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,EAAgB,MAAM,YAAY,CAAA;AACzF,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,wGAAwG;AACxG,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAwB/D,CAAA"}
|
package/dist/presets.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Presets follow architecture patterns only — never specific design systems (neutrality principle). */
|
|
2
|
+
export const PRESETS = {
|
|
3
|
+
/** Sensible defaults; equal to the rules' default severities. */
|
|
4
|
+
recommended: {
|
|
5
|
+
'token/deprecated-reference': 'warning',
|
|
6
|
+
'naming/normalized-collision': 'warning',
|
|
7
|
+
'color/hex-mismatch': 'warning',
|
|
8
|
+
'color/out-of-gamut': 'info',
|
|
9
|
+
'palette/non-monotonic': 'warning',
|
|
10
|
+
'palette/duplicate-stops': 'warning',
|
|
11
|
+
},
|
|
12
|
+
/** Only what DTCG 2025.10 requires: legacy syntax and non-standard values become errors. */
|
|
13
|
+
'dtcg-strict': {
|
|
14
|
+
'dtcg/legacy-syntax': 'error',
|
|
15
|
+
'dtcg/invalid-unit': 'error',
|
|
16
|
+
'dtcg/invalid-font-weight': 'error',
|
|
17
|
+
'dtcg/unknown-type': 'error',
|
|
18
|
+
'dtcg/typography-missing-field': 'error',
|
|
19
|
+
'tokens/non-json': 'error',
|
|
20
|
+
},
|
|
21
|
+
/** Two layers: `core` holds raw values and aliases nothing; `semantic` references `core` directly. */
|
|
22
|
+
'two-layer': {
|
|
23
|
+
'layer/allowed-sources': ['warning', { allow: { core: [], semantic: ['core', 'semantic'] } }],
|
|
24
|
+
'layer/alias-depth': ['warning', { layer: 'semantic', max: 0 }],
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=presets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.js","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"AAEA,wGAAwG;AACxG,MAAM,CAAC,MAAM,OAAO,GAAgD;IAClE,iEAAiE;IACjE,WAAW,EAAE;QACX,4BAA4B,EAAE,SAAS;QACvC,6BAA6B,EAAE,SAAS;QACxC,oBAAoB,EAAE,SAAS;QAC/B,oBAAoB,EAAE,MAAM;QAC5B,uBAAuB,EAAE,SAAS;QAClC,yBAAyB,EAAE,SAAS;KACrC;IACD,4FAA4F;IAC5F,aAAa,EAAE;QACb,oBAAoB,EAAE,OAAO;QAC7B,mBAAmB,EAAE,OAAO;QAC5B,0BAA0B,EAAE,OAAO;QACnC,mBAAmB,EAAE,OAAO;QAC5B,+BAA+B,EAAE,OAAO;QACxC,iBAAiB,EAAE,OAAO;KAC3B;IACD,sGAAsG;IACtG,WAAW,EAAE;QACX,uBAAuB,EAAE,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC;QAC7F,mBAAmB,EAAE,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;KAChE;CACF,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Rule, RuleContext } from '../types.js';
|
|
2
|
+
export declare const hardcodedColor: Rule;
|
|
3
|
+
export declare const offScale: Rule;
|
|
4
|
+
export declare const deprecatedUsage: Rule;
|
|
5
|
+
export declare const unknownToken: Rule;
|
|
6
|
+
/** Tokens the code reads, with everything they take their values from. */
|
|
7
|
+
export declare function usedTokens(ctx: Pick<RuleContext, 'graph' | 'code' | 'vars'>): Set<string>;
|
|
8
|
+
export declare const unusedToken: Rule;
|
|
9
|
+
//# sourceMappingURL=code.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code.d.ts","sourceRoot":"","sources":["../../src/rules/code.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAoDpD,eAAO,MAAM,cAAc,EAAE,IA8B5B,CAAA;AAED,eAAO,MAAM,QAAQ,EAAE,IAiCtB,CAAA;AAED,eAAO,MAAM,eAAe,EAAE,IAoB7B,CAAA;AAED,eAAO,MAAM,YAAY,EAAE,IAkB1B,CAAA;AAED,0EAA0E;AAC1E,wBAAgB,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CASzF;AAED,eAAO,MAAM,WAAW,EAAE,IAazB,CAAA"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { matchGlob, nearestTokens, normalizeName, } from '@dsgraph/core';
|
|
2
|
+
const asArray = (v) => Array.isArray(v) ? v.filter((x) => typeof x === 'string') : [];
|
|
3
|
+
/** `exceptions: { files: ["src/legacy/**"], values: ["#000", "100%"] }` */
|
|
4
|
+
function excepted(options) {
|
|
5
|
+
const ex = (options.exceptions ?? {});
|
|
6
|
+
const files = asArray(ex.files);
|
|
7
|
+
const values = new Set(asArray(ex.values).map((v) => v.toLowerCase()));
|
|
8
|
+
return (l) => (files.length > 0 && matchGlob(l.file, files)) ||
|
|
9
|
+
(l.text !== undefined && values.has(l.text.toLowerCase()));
|
|
10
|
+
}
|
|
11
|
+
const locOf = (l) => ({
|
|
12
|
+
file: l.file,
|
|
13
|
+
line: l.line,
|
|
14
|
+
column: l.column,
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* Which scale a property takes values from, by token names. Spacing falls back to every dimension
|
|
18
|
+
* when names say nothing; radii and font sizes are not compared with spacing.
|
|
19
|
+
*/
|
|
20
|
+
const FAMILIES = [
|
|
21
|
+
{ property: /radius$/i, names: /(^|\.)(radius|radii|rounded|corner|round)(\.|$)/, strict: true },
|
|
22
|
+
{ property: /^font-size$/i, names: /(^|\.)(font|text|type|typography)(\.|$)/, strict: true },
|
|
23
|
+
{
|
|
24
|
+
property: /.*/,
|
|
25
|
+
names: /(^|\.)(space|spacing|spacer|gap|gutter|inset|size|sizing|stack|layout)(\.|$)/,
|
|
26
|
+
strict: false,
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
function scaleOf(graph, property, cache) {
|
|
30
|
+
const family = FAMILIES.find((f) => f.property.test(property));
|
|
31
|
+
let tokens = cache.get(family.names);
|
|
32
|
+
if (!tokens) {
|
|
33
|
+
const all = graph.tokens({ type: 'dimension' });
|
|
34
|
+
const named = all.filter((t) => family.names.test(normalizeName(t.id)));
|
|
35
|
+
tokens = named.length || family.strict ? named : all;
|
|
36
|
+
cache.set(family.names, tokens);
|
|
37
|
+
}
|
|
38
|
+
return tokens;
|
|
39
|
+
}
|
|
40
|
+
function nearestIn(graph, l, among) {
|
|
41
|
+
const all = nearestTokens(graph, { type: l.type, value: l.value }, graph.defaultInput(), among ? 10_000 : 1);
|
|
42
|
+
return among ? all.find((m) => among.has(m.token.id)) : all[0];
|
|
43
|
+
}
|
|
44
|
+
export const hardcodedColor = {
|
|
45
|
+
id: 'style/hardcoded-color',
|
|
46
|
+
description: 'A color in a style is written by hand instead of taken from a token.',
|
|
47
|
+
defaultSeverity: 'warning',
|
|
48
|
+
run({ graph, code, options, report }) {
|
|
49
|
+
if (!code || graph.tokens({ type: 'color' }).length === 0)
|
|
50
|
+
return;
|
|
51
|
+
const skip = excepted(options);
|
|
52
|
+
const memo = new Map();
|
|
53
|
+
for (const l of code.literals) {
|
|
54
|
+
if (l.type !== 'color' || skip(l))
|
|
55
|
+
continue;
|
|
56
|
+
const key = l.text.toLowerCase();
|
|
57
|
+
if (!memo.has(key))
|
|
58
|
+
memo.set(key, nearestIn(graph, l));
|
|
59
|
+
const near = memo.get(key);
|
|
60
|
+
if (!near)
|
|
61
|
+
continue;
|
|
62
|
+
report({
|
|
63
|
+
message: near.exact
|
|
64
|
+
? `Color "${l.text}" in ${l.property} is written by hand; use "${near.token.id}"`
|
|
65
|
+
: `Color "${l.text}" in ${l.property} is not in the palette; closest is "${near.token.id}" (ΔE ${near.distance})`,
|
|
66
|
+
nodes: [near.token.id],
|
|
67
|
+
evidence: {
|
|
68
|
+
value: l.text,
|
|
69
|
+
property: l.property,
|
|
70
|
+
selector: l.selector,
|
|
71
|
+
token: near.token.id,
|
|
72
|
+
deltaE: near.distance,
|
|
73
|
+
},
|
|
74
|
+
loc: locOf(l),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
export const offScale = {
|
|
80
|
+
id: 'style/off-scale',
|
|
81
|
+
description: 'A spacing, radius or font size in a style is written by hand: on the scale (use the token) or off it.',
|
|
82
|
+
defaultSeverity: 'warning',
|
|
83
|
+
run({ graph, code, options, report }) {
|
|
84
|
+
if (!code || graph.tokens({ type: 'dimension' }).length === 0)
|
|
85
|
+
return;
|
|
86
|
+
const skip = excepted(options);
|
|
87
|
+
const scales = new Map();
|
|
88
|
+
for (const l of code.literals) {
|
|
89
|
+
if (l.type !== 'dimension' || skip(l))
|
|
90
|
+
continue;
|
|
91
|
+
const scale = scaleOf(graph, l.property, scales);
|
|
92
|
+
const near = nearestIn(graph, l, new Set(scale.map((t) => t.id)));
|
|
93
|
+
if (!near)
|
|
94
|
+
continue;
|
|
95
|
+
const px = near.value;
|
|
96
|
+
report({
|
|
97
|
+
message: near.exact
|
|
98
|
+
? `"${l.text}" in ${l.property} is on the scale; use "${near.token.id}"`
|
|
99
|
+
: `"${l.text}" in ${l.property} is off the scale; closest is "${near.token.id}" (${px.value}${px.unit})`,
|
|
100
|
+
nodes: [near.token.id],
|
|
101
|
+
evidence: {
|
|
102
|
+
value: l.text,
|
|
103
|
+
property: l.property,
|
|
104
|
+
selector: l.selector,
|
|
105
|
+
token: near.token.id,
|
|
106
|
+
distance: near.distance,
|
|
107
|
+
},
|
|
108
|
+
loc: locOf(l),
|
|
109
|
+
// A value that has a token is a quick fix; one that has none is a design question.
|
|
110
|
+
...(near.exact ? { severity: 'info' } : {}),
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
export const deprecatedUsage = {
|
|
116
|
+
id: 'usage/deprecated',
|
|
117
|
+
description: 'The code uses a deprecated token.',
|
|
118
|
+
defaultSeverity: 'warning',
|
|
119
|
+
run({ code, vars, options, report }) {
|
|
120
|
+
if (!code || !vars)
|
|
121
|
+
return;
|
|
122
|
+
const skip = excepted(options);
|
|
123
|
+
for (const u of code.uses) {
|
|
124
|
+
if (skip(u))
|
|
125
|
+
continue;
|
|
126
|
+
const t = vars.token(u.name);
|
|
127
|
+
if (!t?.deprecated)
|
|
128
|
+
continue;
|
|
129
|
+
const replacement = t.deprecated.replacement;
|
|
130
|
+
report({
|
|
131
|
+
message: `"${u.name}" is deprecated${replacement ? `; use "${replacement}"` : ''}`,
|
|
132
|
+
nodes: [t.id],
|
|
133
|
+
evidence: { reason: t.deprecated.reason, replacement, property: u.property },
|
|
134
|
+
loc: locOf(u),
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
export const unknownToken = {
|
|
140
|
+
id: 'usage/unknown-token',
|
|
141
|
+
description: "The code uses a design-system variable that is not in the tokens (removed, renamed or misspelled). Needs the system's prefix, configured or learned.",
|
|
142
|
+
defaultSeverity: 'error',
|
|
143
|
+
run({ code, vars, options, report }) {
|
|
144
|
+
if (!code || !vars)
|
|
145
|
+
return;
|
|
146
|
+
const skip = excepted(options);
|
|
147
|
+
for (const u of code.uses) {
|
|
148
|
+
if (skip(u) || !vars.isSystemName(u.name) || vars.token(u.name))
|
|
149
|
+
continue;
|
|
150
|
+
report({
|
|
151
|
+
message: `"${u.name}" is not a token${u.fallback ? `; the fallback "${u.fallback}" is used instead` : ''}`,
|
|
152
|
+
nodes: [],
|
|
153
|
+
evidence: { property: u.property, fallback: u.fallback },
|
|
154
|
+
loc: locOf(u),
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
/** Tokens the code reads, with everything they take their values from. */
|
|
160
|
+
export function usedTokens(ctx) {
|
|
161
|
+
const used = new Set();
|
|
162
|
+
for (const u of ctx.code?.uses ?? []) {
|
|
163
|
+
const t = ctx.vars?.token(u.name);
|
|
164
|
+
if (!t || used.has(t.id))
|
|
165
|
+
continue;
|
|
166
|
+
used.add(t.id);
|
|
167
|
+
for (const d of ctx.graph.dependencies(t.id, { transitive: true }))
|
|
168
|
+
used.add(d);
|
|
169
|
+
}
|
|
170
|
+
return used;
|
|
171
|
+
}
|
|
172
|
+
export const unusedToken = {
|
|
173
|
+
id: 'token/unused',
|
|
174
|
+
description: 'A token is not used by the code, directly or through another token.',
|
|
175
|
+
defaultSeverity: 'info',
|
|
176
|
+
run(ctx) {
|
|
177
|
+
const { graph, code, report } = ctx;
|
|
178
|
+
if (!code || code.uses.length === 0)
|
|
179
|
+
return;
|
|
180
|
+
const used = usedTokens(ctx);
|
|
181
|
+
for (const t of graph.tokens()) {
|
|
182
|
+
if (used.has(t.id) || t.deprecated)
|
|
183
|
+
continue;
|
|
184
|
+
report({ message: `"${t.id}" is not used in the code`, nodes: [t.id], token: t });
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
//# sourceMappingURL=code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code.js","sourceRoot":"","sources":["../../src/rules/code.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layers.d.ts","sourceRoot":"","sources":["../../src/rules/layers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAWvC,eAAO,MAAM,UAAU,EAAE,IAkCxB,CAAA;AAED,eAAO,MAAM,cAAc,EAAE,IAqB5B,CAAA"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { matchPath } from '@dsgraph/core';
|
|
2
|
+
/** Whole-value alias targets of a token across all its contexts. */
|
|
3
|
+
function wholeTargets(graph, id) {
|
|
4
|
+
const t = graph.token(id);
|
|
5
|
+
if (!t)
|
|
6
|
+
return [];
|
|
7
|
+
return [
|
|
8
|
+
...new Set(t.values.flatMap((v) => v.refs.filter((r) => !r.property && !r.targetPath).map((r) => r.to))),
|
|
9
|
+
];
|
|
10
|
+
}
|
|
11
|
+
export const aliasDepth = {
|
|
12
|
+
id: 'layer/alias-depth',
|
|
13
|
+
description: 'Tokens of a layer reference tokens of the same layer deeper than allowed.',
|
|
14
|
+
defaultSeverity: 'off',
|
|
15
|
+
run({ graph, options, report }) {
|
|
16
|
+
const layer = typeof options.layer === 'string' ? options.layer : 'semantic';
|
|
17
|
+
const max = typeof options.max === 'number' ? options.max : 0;
|
|
18
|
+
const allow = (Array.isArray(options.allow) ? options.allow : [])
|
|
19
|
+
.filter((a) => typeof a === 'string')
|
|
20
|
+
.map((a) => a.split('->').map((s) => s.trim()));
|
|
21
|
+
const allowed = (from, to) => allow.some(([f, t]) => matchPath(from, f) && matchPath(to, t));
|
|
22
|
+
const memo = new Map();
|
|
23
|
+
const depth = (id, seen) => {
|
|
24
|
+
if (memo.has(id))
|
|
25
|
+
return memo.get(id);
|
|
26
|
+
let d = 0;
|
|
27
|
+
for (const to of wholeTargets(graph, id)) {
|
|
28
|
+
if (graph.token(to)?.layer !== layer || seen.has(to) || allowed(id, to))
|
|
29
|
+
continue;
|
|
30
|
+
d = Math.max(d, 1 + depth(to, new Set([...seen, to])));
|
|
31
|
+
}
|
|
32
|
+
memo.set(id, d);
|
|
33
|
+
return d;
|
|
34
|
+
};
|
|
35
|
+
for (const t of graph.tokens({ layer })) {
|
|
36
|
+
const d = depth(t.id, new Set([t.id]));
|
|
37
|
+
if (d > max)
|
|
38
|
+
report({
|
|
39
|
+
message: `"${t.id}" goes through ${d} ${layer} alias${d > 1 ? 'es' : ''} (max ${max})`,
|
|
40
|
+
nodes: [t.id, ...wholeTargets(graph, t.id)],
|
|
41
|
+
evidence: { depth: d, max, chain: graph.chain(t.id) },
|
|
42
|
+
token: t,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
export const allowedSources = {
|
|
48
|
+
id: 'layer/allowed-sources',
|
|
49
|
+
description: 'Tokens of a layer reference only the layers allowed for it.',
|
|
50
|
+
defaultSeverity: 'off',
|
|
51
|
+
run({ graph, options, report }) {
|
|
52
|
+
const allow = (options.allow ?? {});
|
|
53
|
+
for (const [, from, to] of graph.edges('aliases')) {
|
|
54
|
+
const source = graph.token(from);
|
|
55
|
+
const target = graph.token(to);
|
|
56
|
+
const fromLayer = source?.layer;
|
|
57
|
+
if (!source || !target || !fromLayer || !(fromLayer in allow))
|
|
58
|
+
continue;
|
|
59
|
+
const permitted = Array.isArray(allow[fromLayer]) ? allow[fromLayer] : [];
|
|
60
|
+
if (!permitted.includes(target.layer ?? ''))
|
|
61
|
+
report({
|
|
62
|
+
message: `"${from}" (${fromLayer}) references "${to}" (${target.layer ?? 'no layer'}); ${fromLayer} may reference ${permitted.length ? permitted.join(', ') : 'nothing'}`,
|
|
63
|
+
nodes: [from, to],
|
|
64
|
+
evidence: { fromLayer, toLayer: target.layer, allowed: permitted },
|
|
65
|
+
token: source,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=layers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layers.js","sourceRoot":"","sources":["../../src/rules/layers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Rule } from '../types.js';
|
|
2
|
+
export declare const deprecatedReference: Rule;
|
|
3
|
+
export declare const normalizedCollision: Rule;
|
|
4
|
+
export declare const hexMismatch: Rule;
|
|
5
|
+
export declare const outOfGamut: Rule;
|
|
6
|
+
export declare const nonMonotonicPalette: Rule;
|
|
7
|
+
export declare const duplicateStops: Rule;
|
|
8
|
+
export declare const contrastMatrix: Rule;
|
|
9
|
+
//# sourceMappingURL=tokens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/rules/tokens.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAKvC,eAAO,MAAM,mBAAmB,EAAE,IAkBjC,CAAA;AAED,eAAO,MAAM,mBAAmB,EAAE,IAkBjC,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,IA2BzB,CAAA;AAED,eAAO,MAAM,UAAU,EAAE,IAkBxB,CAAA;AAiBD,eAAO,MAAM,mBAAmB,EAAE,IA2BjC,CAAA;AAED,eAAO,MAAM,cAAc,EAAE,IAiB5B,CAAA;AAED,eAAO,MAAM,cAAc,EAAE,IA2C5B,CAAA"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { colorToHex, compareValues, isInSrgbGamut, matchPath, normalizeName, toOklab, } from '@dsgraph/core';
|
|
2
|
+
import { contrastRatio } from '../color.js';
|
|
3
|
+
const asArray = (v) => Array.isArray(v) ? v.filter((x) => typeof x === 'string') : [];
|
|
4
|
+
export const deprecatedReference = {
|
|
5
|
+
id: 'token/deprecated-reference',
|
|
6
|
+
description: 'A token references a deprecated token.',
|
|
7
|
+
defaultSeverity: 'warning',
|
|
8
|
+
run({ graph, report }) {
|
|
9
|
+
for (const [, from, to] of graph.edges('aliases')) {
|
|
10
|
+
const source = graph.token(from);
|
|
11
|
+
const target = graph.token(to);
|
|
12
|
+
if (!source || !target?.deprecated || source.deprecated)
|
|
13
|
+
continue;
|
|
14
|
+
const replacement = target.deprecated.replacement;
|
|
15
|
+
report({
|
|
16
|
+
message: `"${from}" references deprecated "${to}"${replacement ? `; use "${replacement}"` : ''}`,
|
|
17
|
+
nodes: [from, to],
|
|
18
|
+
evidence: { reason: target.deprecated.reason, replacement },
|
|
19
|
+
token: source,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
export const normalizedCollision = {
|
|
25
|
+
id: 'naming/normalized-collision',
|
|
26
|
+
description: 'Different tokens map to the same name in code (CSS, Figma) after normalization.',
|
|
27
|
+
defaultSeverity: 'warning',
|
|
28
|
+
run({ graph, report }) {
|
|
29
|
+
const byName = new Map();
|
|
30
|
+
for (const t of graph.tokens()) {
|
|
31
|
+
const n = normalizeName(t.id);
|
|
32
|
+
byName.set(n, [...(byName.get(n) ?? []), t.id]);
|
|
33
|
+
}
|
|
34
|
+
for (const [name, ids] of byName)
|
|
35
|
+
if (ids.length > 1)
|
|
36
|
+
report({
|
|
37
|
+
message: `${ids.map((i) => `"${i}"`).join(', ')} all normalize to "${name}"`,
|
|
38
|
+
nodes: ids,
|
|
39
|
+
evidence: { name },
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
export const hexMismatch = {
|
|
44
|
+
id: 'color/hex-mismatch',
|
|
45
|
+
description: 'The hex fallback of a color does not match its components.',
|
|
46
|
+
defaultSeverity: 'warning',
|
|
47
|
+
run({ graph, report }) {
|
|
48
|
+
for (const t of graph.tokens({ type: 'color' })) {
|
|
49
|
+
for (const v of t.values) {
|
|
50
|
+
const c = v.value;
|
|
51
|
+
if (!c?.hex)
|
|
52
|
+
continue;
|
|
53
|
+
const actual = colorToHex(c);
|
|
54
|
+
const diff = [1, 3, 5].some((i) => Math.abs(Number.parseInt(actual.slice(i, i + 2), 16) - Number.parseInt(c.hex.slice(i, i + 2), 16)) > 1);
|
|
55
|
+
if (diff)
|
|
56
|
+
report({
|
|
57
|
+
message: `"${t.id}": hex ${c.hex} does not match the color (${actual})`,
|
|
58
|
+
nodes: [t.id],
|
|
59
|
+
evidence: { hex: c.hex, computed: actual },
|
|
60
|
+
when: v.when,
|
|
61
|
+
token: t,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
export const outOfGamut = {
|
|
68
|
+
id: 'color/out-of-gamut',
|
|
69
|
+
description: 'A wide-gamut color is outside sRGB and has no hex fallback.',
|
|
70
|
+
defaultSeverity: 'info',
|
|
71
|
+
run({ graph, report }) {
|
|
72
|
+
for (const t of graph.tokens({ type: 'color' }))
|
|
73
|
+
for (const v of t.values) {
|
|
74
|
+
const c = v.value;
|
|
75
|
+
if (c && !c.hex && !isInSrgbGamut(c))
|
|
76
|
+
report({
|
|
77
|
+
message: `"${t.id}" is outside sRGB; add a hex fallback for sRGB targets`,
|
|
78
|
+
nodes: [t.id],
|
|
79
|
+
evidence: { space: c.space },
|
|
80
|
+
when: v.when,
|
|
81
|
+
token: t,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
/** Color ramps: siblings whose last name segment is a number (`blue.100`, `blue-500`), at least 3 stops. */
|
|
87
|
+
function ramps(graph) {
|
|
88
|
+
const groups = new Map();
|
|
89
|
+
for (const t of graph.tokens({ type: 'color' })) {
|
|
90
|
+
const segs = normalizeName(t.id).split('.');
|
|
91
|
+
const step = Number(segs.at(-1));
|
|
92
|
+
if (segs.length < 2 || !/^\d+$/.test(segs.at(-1)) || !Number.isFinite(step))
|
|
93
|
+
continue;
|
|
94
|
+
const key = segs.slice(0, -1).join('.');
|
|
95
|
+
groups.set(key, [...(groups.get(key) ?? []), { id: t.id, step }]);
|
|
96
|
+
}
|
|
97
|
+
return [...groups]
|
|
98
|
+
.filter(([, stops]) => stops.length >= 3)
|
|
99
|
+
.map(([name, stops]) => ({ name, stops: stops.sort((a, b) => a.step - b.step) }));
|
|
100
|
+
}
|
|
101
|
+
export const nonMonotonicPalette = {
|
|
102
|
+
id: 'palette/non-monotonic',
|
|
103
|
+
description: 'Lightness of a numeric color ramp does not change in one direction.',
|
|
104
|
+
defaultSeverity: 'warning',
|
|
105
|
+
run({ graph, report }) {
|
|
106
|
+
for (const { name, stops } of ramps(graph)) {
|
|
107
|
+
const l = stops.map((s) => {
|
|
108
|
+
const v = graph.value(s.id);
|
|
109
|
+
return v ? toOklab(v)[0] : Number.NaN;
|
|
110
|
+
});
|
|
111
|
+
const dir = Math.sign(l.at(-1) - l[0]);
|
|
112
|
+
for (let i = 1; i < stops.length; i++) {
|
|
113
|
+
const step = l[i] - l[i - 1];
|
|
114
|
+
if (Number.isNaN(step) || Math.abs(step) < 1e-4)
|
|
115
|
+
continue;
|
|
116
|
+
if (Math.sign(step) !== dir)
|
|
117
|
+
report({
|
|
118
|
+
message: `Ramp "${name}": lightness goes the wrong way from ${stops[i - 1].step} to ${stops[i].step}`,
|
|
119
|
+
nodes: [stops[i - 1].id, stops[i].id],
|
|
120
|
+
evidence: {
|
|
121
|
+
ramp: name,
|
|
122
|
+
from: Math.round(l[i - 1] * 1000) / 1000,
|
|
123
|
+
to: Math.round(l[i] * 1000) / 1000,
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
export const duplicateStops = {
|
|
131
|
+
id: 'palette/duplicate-stops',
|
|
132
|
+
description: 'Two steps of a numeric color ramp have the same color.',
|
|
133
|
+
defaultSeverity: 'warning',
|
|
134
|
+
run({ graph, report }) {
|
|
135
|
+
for (const { name, stops } of ramps(graph))
|
|
136
|
+
for (let i = 1; i < stops.length; i++) {
|
|
137
|
+
const a = graph.value(stops[i - 1].id);
|
|
138
|
+
const b = graph.value(stops[i].id);
|
|
139
|
+
if (a && b && compareValues('color', a, b).result !== 'changed')
|
|
140
|
+
report({
|
|
141
|
+
message: `Ramp "${name}": steps ${stops[i - 1].step} and ${stops[i].step} are the same color`,
|
|
142
|
+
nodes: [stops[i - 1].id, stops[i].id],
|
|
143
|
+
evidence: { ramp: name },
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
export const contrastMatrix = {
|
|
149
|
+
id: 'a11y/contrast-matrix',
|
|
150
|
+
description: 'Every text role over every surface role meets the minimum WCAG contrast in every context.',
|
|
151
|
+
defaultSeverity: 'off',
|
|
152
|
+
run({ graph, options, report }) {
|
|
153
|
+
const text = asArray(options.text);
|
|
154
|
+
const surfaces = asArray(options.surfaces);
|
|
155
|
+
const min = typeof options.min === 'number' ? options.min : 4.5;
|
|
156
|
+
const acknowledged = new Set(asArray(options.acknowledged));
|
|
157
|
+
if (text.length === 0 || surfaces.length === 0)
|
|
158
|
+
return;
|
|
159
|
+
const textTokens = graph.tokens({ type: 'color' }).filter((t) => text.some((p) => matchPath(t.id, p)));
|
|
160
|
+
const surfaceTokens = graph
|
|
161
|
+
.tokens({ type: 'color' })
|
|
162
|
+
.filter((t) => surfaces.some((p) => matchPath(t.id, p)));
|
|
163
|
+
const inputs = graph.inputs().slice(0, 64);
|
|
164
|
+
for (const fg of textTokens)
|
|
165
|
+
for (const bg of surfaceTokens) {
|
|
166
|
+
if (fg.id === bg.id)
|
|
167
|
+
continue;
|
|
168
|
+
const failing = new Map();
|
|
169
|
+
for (const input of inputs) {
|
|
170
|
+
const f = graph.value(fg.id, input);
|
|
171
|
+
const b = graph.value(bg.id, input);
|
|
172
|
+
if (!f || !b)
|
|
173
|
+
continue;
|
|
174
|
+
const ratio = Math.round(contrastRatio(f, b) * 100) / 100;
|
|
175
|
+
if (ratio < min)
|
|
176
|
+
failing.set(JSON.stringify(input), { when: input, ratio });
|
|
177
|
+
}
|
|
178
|
+
if (failing.size === 0)
|
|
179
|
+
continue;
|
|
180
|
+
const pair = `${fg.id} × ${bg.id}`;
|
|
181
|
+
const worst = [...failing.values()].sort((a, b) => a.ratio - b.ratio)[0];
|
|
182
|
+
const all = failing.size === inputs.length;
|
|
183
|
+
const finding = {
|
|
184
|
+
message: `${pair}: contrast ${worst.ratio} is below ${min}${all ? '' : ` in ${failing.size} of ${inputs.length} contexts`}`,
|
|
185
|
+
nodes: [fg.id, bg.id],
|
|
186
|
+
evidence: { ratio: worst.ratio, min, contexts: [...failing.values()].map((f) => f.when) },
|
|
187
|
+
...(all ? {} : { when: worst.when }),
|
|
188
|
+
};
|
|
189
|
+
report(acknowledged.has(pair)
|
|
190
|
+
? { ...finding, severity: 'info', message: `${finding.message} (acknowledged)` }
|
|
191
|
+
: finding);
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
//# sourceMappingURL=tokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/rules/tokens.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { CodeIndex, Config, DsGraph, Finding, Loc, Severity, Token, VarMatcher, When } from '@dsgraph/core';
|
|
2
|
+
export interface RuleContext {
|
|
3
|
+
graph: DsGraph;
|
|
4
|
+
options: Record<string, unknown>;
|
|
5
|
+
config: Config;
|
|
6
|
+
/** The project's code, when checked with it (`--code`, `code` in the config). */
|
|
7
|
+
code?: CodeIndex;
|
|
8
|
+
/** Custom property names in the code to tokens; present with `code`. */
|
|
9
|
+
vars?: VarMatcher;
|
|
10
|
+
report(finding: {
|
|
11
|
+
message: string;
|
|
12
|
+
nodes: string[];
|
|
13
|
+
evidence?: Record<string, unknown>;
|
|
14
|
+
when?: When;
|
|
15
|
+
token?: Token;
|
|
16
|
+
/** Where in the code; takes precedence over the token's origin. */
|
|
17
|
+
loc?: Loc;
|
|
18
|
+
severity?: Severity;
|
|
19
|
+
}): void;
|
|
20
|
+
}
|
|
21
|
+
/** A rule is a pure function of the graph and its options (spec section 7.4). */
|
|
22
|
+
export interface Rule {
|
|
23
|
+
id: string;
|
|
24
|
+
description: string;
|
|
25
|
+
defaultSeverity: Severity | 'off';
|
|
26
|
+
run(ctx: RuleContext): void;
|
|
27
|
+
}
|
|
28
|
+
export type { Finding };
|
|
29
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,MAAM,EACN,OAAO,EACP,OAAO,EACP,GAAG,EACH,QAAQ,EACR,KAAK,EACL,UAAU,EACV,IAAI,EACL,MAAM,eAAe,CAAA;AAEtB,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAChC,MAAM,EAAE,MAAM,CAAA;IACd,iFAAiF;IACjF,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,wEAAwE;IACxE,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB,MAAM,CAAC,OAAO,EAAE;QACd,OAAO,EAAE,MAAM,CAAA;QACf,KAAK,EAAE,MAAM,EAAE,CAAA;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAClC,IAAI,CAAC,EAAE,IAAI,CAAA;QACX,KAAK,CAAC,EAAE,KAAK,CAAA;QACb,mEAAmE;QACnE,GAAG,CAAC,EAAE,GAAG,CAAA;QACT,QAAQ,CAAC,EAAE,QAAQ,CAAA;KACpB,GAAG,IAAI,CAAA;CACT;AAED,iFAAiF;AACjF,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,QAAQ,GAAG,KAAK,CAAA;IACjC,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAAA;CAC5B;AAED,YAAY,EAAE,OAAO,EAAE,CAAA"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsgraph/rules",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Rule engine and built-in rules for dsgraph: layers, contrast, palettes, deprecations, naming.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/specsure/specsure.git",
|
|
20
|
+
"directory": "packages/dsgraph-rules"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/specsure/specsure/tree/main/packages/dsgraph-rules#readme",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/specsure/specsure/issues"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=20.19"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@dsgraph/core": "0.3.0",
|
|
31
|
+
"culori": "4.0.2"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/culori": "4.0.1"
|
|
35
|
+
}
|
|
36
|
+
}
|