@breadstone-infrastructure/token-linter 0.0.231
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/CHANGELOG.md +10 -0
- package/LICENSE +21 -0
- package/README.md +72 -0
- package/cli/Cli.d.ts +10 -0
- package/cli/Cli.d.ts.map +1 -0
- package/cli/Cli.js +32 -0
- package/cli/Cli.js.map +1 -0
- package/cli/CliArgs.d.ts +2 -0
- package/cli/CliArgs.d.ts.map +1 -0
- package/cli/CliArgs.js +88 -0
- package/cli/CliArgs.js.map +1 -0
- package/cli/CliArgsConfig.d.ts +2 -0
- package/cli/CliArgsConfig.d.ts.map +1 -0
- package/cli/CliArgsConfig.js +12 -0
- package/cli/CliArgsConfig.js.map +1 -0
- package/cli/CliRun.d.ts +2 -0
- package/cli/CliRun.d.ts.map +1 -0
- package/cli/CliRun.js +34 -0
- package/cli/CliRun.js.map +1 -0
- package/cli/commands/LintCommand.d.ts +2 -0
- package/cli/commands/LintCommand.d.ts.map +1 -0
- package/cli/commands/LintCommand.js +66 -0
- package/cli/commands/LintCommand.js.map +1 -0
- package/cli/commands/LintCommandArgsConfig.d.ts +2 -0
- package/cli/commands/LintCommandArgsConfig.d.ts.map +1 -0
- package/cli/commands/LintCommandArgsConfig.js +46 -0
- package/cli/commands/LintCommandArgsConfig.js.map +1 -0
- package/cli/lint.d.ts +3 -0
- package/cli/lint.d.ts.map +1 -0
- package/cli/lint.js +55 -0
- package/cli/lint.js.map +1 -0
- package/config/TokenLinterConfigDiscovery.d.ts +16 -0
- package/config/TokenLinterConfigDiscovery.d.ts.map +1 -0
- package/config/TokenLinterConfigDiscovery.js +44 -0
- package/config/TokenLinterConfigDiscovery.js.map +1 -0
- package/config/defineConfig.d.ts +41 -0
- package/config/defineConfig.d.ts.map +1 -0
- package/config/defineConfig.js +37 -0
- package/config/defineConfig.js.map +1 -0
- package/core/interaction.d.ts +25 -0
- package/core/interaction.d.ts.map +1 -0
- package/core/interaction.js +45 -0
- package/core/interaction.js.map +1 -0
- package/core/loader.d.ts +21 -0
- package/core/loader.d.ts.map +1 -0
- package/core/loader.js +84 -0
- package/core/loader.js.map +1 -0
- package/core/rule-registry.d.ts +46 -0
- package/core/rule-registry.d.ts.map +1 -0
- package/core/rule-registry.js +73 -0
- package/core/rule-registry.js.map +1 -0
- package/core/rule.d.ts +46 -0
- package/core/rule.d.ts.map +1 -0
- package/core/rule.js +3 -0
- package/core/rule.js.map +1 -0
- package/core/runner.d.ts +23 -0
- package/core/runner.d.ts.map +1 -0
- package/core/runner.js +103 -0
- package/core/runner.js.map +1 -0
- package/index.d.ts +46 -0
- package/index.d.ts.map +1 -0
- package/index.js +47 -0
- package/index.js.map +1 -0
- package/models/lint-result.d.ts +14 -0
- package/models/lint-result.d.ts.map +1 -0
- package/models/lint-result.js +3 -0
- package/models/lint-result.js.map +1 -0
- package/models/rule-context.d.ts +18 -0
- package/models/rule-context.d.ts.map +1 -0
- package/models/rule-context.js +3 -0
- package/models/rule-context.js.map +1 -0
- package/models/rule-finding.d.ts +15 -0
- package/models/rule-finding.d.ts.map +1 -0
- package/models/rule-finding.js +3 -0
- package/models/rule-finding.js.map +1 -0
- package/models/rule-result.d.ts +11 -0
- package/models/rule-result.d.ts.map +1 -0
- package/models/rule-result.js +3 -0
- package/models/rule-result.js.map +1 -0
- package/models/rule-severity.d.ts +14 -0
- package/models/rule-severity.d.ts.map +1 -0
- package/models/rule-severity.js +10 -0
- package/models/rule-severity.js.map +1 -0
- package/models/token-entry.d.ts +11 -0
- package/models/token-entry.d.ts.map +1 -0
- package/models/token-entry.js +2 -0
- package/models/token-entry.js.map +1 -0
- package/models/token-linter-config.d.ts +30 -0
- package/models/token-linter-config.d.ts.map +1 -0
- package/models/token-linter-config.js +3 -0
- package/models/token-linter-config.js.map +1 -0
- package/orchestration/TokenLinterOrchestrator.d.ts +29 -0
- package/orchestration/TokenLinterOrchestrator.d.ts.map +1 -0
- package/orchestration/TokenLinterOrchestrator.js +98 -0
- package/orchestration/TokenLinterOrchestrator.js.map +1 -0
- package/package.json +20 -0
- package/presets/index.d.ts +2 -0
- package/presets/index.d.ts.map +1 -0
- package/presets/index.js +2 -0
- package/presets/index.js.map +1 -0
- package/presets/recommended.d.ts +23 -0
- package/presets/recommended.d.ts.map +1 -0
- package/presets/recommended.js +41 -0
- package/presets/recommended.js.map +1 -0
- package/reporters/console.reporter.d.ts +15 -0
- package/reporters/console.reporter.d.ts.map +1 -0
- package/reporters/console.reporter.js +75 -0
- package/reporters/console.reporter.js.map +1 -0
- package/reporters/json.reporter.d.ts +11 -0
- package/reporters/json.reporter.d.ts.map +1 -0
- package/reporters/json.reporter.js +37 -0
- package/reporters/json.reporter.js.map +1 -0
- package/reporters/reporter.d.ts +16 -0
- package/reporters/reporter.d.ts.map +1 -0
- package/reporters/reporter.js +3 -0
- package/reporters/reporter.js.map +1 -0
- package/reporters/summary.reporter.d.ts +12 -0
- package/reporters/summary.reporter.d.ts.map +1 -0
- package/reporters/summary.reporter.js +48 -0
- package/reporters/summary.reporter.js.map +1 -0
- package/rules/alphabetical-sort.rule.d.ts +19 -0
- package/rules/alphabetical-sort.rule.d.ts.map +1 -0
- package/rules/alphabetical-sort.rule.js +72 -0
- package/rules/alphabetical-sort.rule.js.map +1 -0
- package/rules/component-presence.rule.d.ts +29 -0
- package/rules/component-presence.rule.d.ts.map +1 -0
- package/rules/component-presence.rule.js +102 -0
- package/rules/component-presence.rule.js.map +1 -0
- package/rules/duplicate-value.rule.d.ts +17 -0
- package/rules/duplicate-value.rule.d.ts.map +1 -0
- package/rules/duplicate-value.rule.js +49 -0
- package/rules/duplicate-value.rule.js.map +1 -0
- package/rules/empty-json.rule.d.ts +52 -0
- package/rules/empty-json.rule.d.ts.map +1 -0
- package/rules/empty-json.rule.js +100 -0
- package/rules/empty-json.rule.js.map +1 -0
- package/rules/forbidden-key.rule.d.ts +57 -0
- package/rules/forbidden-key.rule.d.ts.map +1 -0
- package/rules/forbidden-key.rule.js +118 -0
- package/rules/forbidden-key.rule.js.map +1 -0
- package/rules/forbidden-value.rule.d.ts +53 -0
- package/rules/forbidden-value.rule.d.ts.map +1 -0
- package/rules/forbidden-value.rule.js +130 -0
- package/rules/forbidden-value.rule.js.map +1 -0
- package/rules/includes-consistency.rule.d.ts +30 -0
- package/rules/includes-consistency.rule.d.ts.map +1 -0
- package/rules/includes-consistency.rule.js +153 -0
- package/rules/includes-consistency.rule.js.map +1 -0
- package/rules/index.d.ts +7 -0
- package/rules/index.d.ts.map +1 -0
- package/rules/index.js +47 -0
- package/rules/index.js.map +1 -0
- package/rules/key-consistency.rule.d.ts +38 -0
- package/rules/key-consistency.rule.d.ts.map +1 -0
- package/rules/key-consistency.rule.js +161 -0
- package/rules/key-consistency.rule.js.map +1 -0
- package/rules/missing-includes.rule.d.ts +19 -0
- package/rules/missing-includes.rule.d.ts.map +1 -0
- package/rules/missing-includes.rule.js +51 -0
- package/rules/missing-includes.rule.js.map +1 -0
- package/rules/mixin-reference.rule.d.ts +28 -0
- package/rules/mixin-reference.rule.d.ts.map +1 -0
- package/rules/mixin-reference.rule.js +104 -0
- package/rules/mixin-reference.rule.js.map +1 -0
- package/rules/naming-convention.rule.d.ts +29 -0
- package/rules/naming-convention.rule.d.ts.map +1 -0
- package/rules/naming-convention.rule.js +112 -0
- package/rules/naming-convention.rule.js.map +1 -0
- package/rules/nested-depth.rule.d.ts +42 -0
- package/rules/nested-depth.rule.d.ts.map +1 -0
- package/rules/nested-depth.rule.js +72 -0
- package/rules/nested-depth.rule.js.map +1 -0
- package/rules/required-includes.rule.d.ts +60 -0
- package/rules/required-includes.rule.d.ts.map +1 -0
- package/rules/required-includes.rule.js +118 -0
- package/rules/required-includes.rule.js.map +1 -0
- package/rules/rule-options.d.ts +158 -0
- package/rules/rule-options.d.ts.map +1 -0
- package/rules/rule-options.js +89 -0
- package/rules/rule-options.js.map +1 -0
- package/rules/value-consistency.rule.d.ts +17 -0
- package/rules/value-consistency.rule.d.ts.map +1 -0
- package/rules/value-consistency.rule.js +69 -0
- package/rules/value-consistency.rule.js.map +1 -0
- package/rules/value-schema.rule.d.ts +18 -0
- package/rules/value-schema.rule.d.ts.map +1 -0
- package/rules/value-schema.rule.js +108 -0
- package/rules/value-schema.rule.js.map +1 -0
- package/rules/value-type.rule.d.ts +71 -0
- package/rules/value-type.rule.d.ts.map +1 -0
- package/rules/value-type.rule.js +176 -0
- package/rules/value-type.rule.js.map +1 -0
- package/utils.d.ts +55 -0
- package/utils.d.ts.map +1 -0
- package/utils.js +125 -0
- package/utils.js.map +1 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
// #region Imports
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import { RuleSeverity } from '../models/rule-severity.js';
|
|
4
|
+
import { METADATA_KEYS, isTokenValue } from '../utils.js';
|
|
5
|
+
// #endregion
|
|
6
|
+
// #region Constants
|
|
7
|
+
/**
|
|
8
|
+
* @description Default key-to-type constraints.
|
|
9
|
+
* Keys listed here must have values of the specified type in every component where they appear.
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
const DEFAULT_TYPE_CONSTRAINTS = {
|
|
13
|
+
transitionProperty: 'array',
|
|
14
|
+
tooltipTransitionProperty: 'array',
|
|
15
|
+
};
|
|
16
|
+
// #endregion
|
|
17
|
+
// #region Functions
|
|
18
|
+
/**
|
|
19
|
+
* @description Creates typed rule options for the `value-type` rule.
|
|
20
|
+
* @public
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```js
|
|
24
|
+
* ruleOptions: {
|
|
25
|
+
* ...valueTypeRuleOptions({ types: { transitionProperty: 'array' } }),
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export function valueTypeRuleOptions(options) {
|
|
30
|
+
return { 'value-type': options };
|
|
31
|
+
}
|
|
32
|
+
// #endregion
|
|
33
|
+
/**
|
|
34
|
+
* @description Enforces that specific token keys have values of a required type (string, array, or number).
|
|
35
|
+
* When auto-fix is enabled, values are coerced to the expected type where possible
|
|
36
|
+
* (e.g. a string is wrapped into a single-element array).
|
|
37
|
+
*
|
|
38
|
+
* The type constraints default to `{ transitionProperty: 'array', tooltipTransitionProperty: 'array' }`
|
|
39
|
+
* and can be overridden via `ruleOptions`:
|
|
40
|
+
*
|
|
41
|
+
* @example Configuration
|
|
42
|
+
* ```js
|
|
43
|
+
* export default defineConfig({
|
|
44
|
+
* rules: { 'value-type': 'error' },
|
|
45
|
+
* ruleOptions: {
|
|
46
|
+
* 'value-type': {
|
|
47
|
+
* types: {
|
|
48
|
+
* transitionProperty: 'array',
|
|
49
|
+
* tooltipTransitionProperty: 'array',
|
|
50
|
+
* },
|
|
51
|
+
* },
|
|
52
|
+
* },
|
|
53
|
+
* });
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* @public
|
|
57
|
+
*/
|
|
58
|
+
export class ValueTypeRule {
|
|
59
|
+
// #region Fields
|
|
60
|
+
name = 'value-type';
|
|
61
|
+
description = 'Enforces that specific token keys have values of a required type (string, array, number).';
|
|
62
|
+
defaultSeverity = RuleSeverity.Error;
|
|
63
|
+
fixable = true;
|
|
64
|
+
interactive = false;
|
|
65
|
+
// #endregion
|
|
66
|
+
// #region Methods
|
|
67
|
+
run(context) {
|
|
68
|
+
const findings = [];
|
|
69
|
+
const options = context.config.ruleOptions[this.name];
|
|
70
|
+
const typeConstraints = options?.types ?? DEFAULT_TYPE_CONSTRAINTS;
|
|
71
|
+
for (const entry of context.entries) {
|
|
72
|
+
for (const [key, val] of Object.entries(entry.content)) {
|
|
73
|
+
if (METADATA_KEYS.includes(key)) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (!(key in typeConstraints)) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (!isTokenValue(val)) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const expectedType = typeConstraints[key];
|
|
83
|
+
const actualType = this._getValueType(val.value);
|
|
84
|
+
if (actualType !== expectedType) {
|
|
85
|
+
findings.push({
|
|
86
|
+
component: entry.component,
|
|
87
|
+
theme: entry.theme,
|
|
88
|
+
key,
|
|
89
|
+
message: `Value of '${key}' in '${entry.component}' (${entry.theme}) must be ${expectedType}, but is ${actualType}.`,
|
|
90
|
+
severity: this.defaultSeverity,
|
|
91
|
+
filePath: entry.filePath,
|
|
92
|
+
fixed: false,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return { ruleName: this.name, findings, duration: 0 };
|
|
98
|
+
}
|
|
99
|
+
fix(context, findings) {
|
|
100
|
+
const options = context.config.ruleOptions[this.name];
|
|
101
|
+
const typeConstraints = options?.types ?? DEFAULT_TYPE_CONSTRAINTS;
|
|
102
|
+
const entryMap = new Map(context.entries.map(e => [e.filePath, e]));
|
|
103
|
+
const pendingWrites = new Map();
|
|
104
|
+
const result = [];
|
|
105
|
+
for (const finding of findings) {
|
|
106
|
+
const entry = finding.filePath ? entryMap.get(finding.filePath) : undefined;
|
|
107
|
+
if (!entry || !finding.key) {
|
|
108
|
+
result.push(finding);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
const expectedType = typeConstraints[finding.key];
|
|
112
|
+
if (!expectedType) {
|
|
113
|
+
result.push(finding);
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const content = pendingWrites.get(entry.filePath) ?? entry.content;
|
|
117
|
+
const tokenObj = content[finding.key];
|
|
118
|
+
if (!isTokenValue(tokenObj)) {
|
|
119
|
+
result.push(finding);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
const coerced = this._coerceValue(tokenObj.value, expectedType);
|
|
123
|
+
if (coerced !== undefined) {
|
|
124
|
+
tokenObj['value'] = coerced;
|
|
125
|
+
pendingWrites.set(entry.filePath, content);
|
|
126
|
+
result.push({ ...finding, fixed: true });
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
result.push(finding);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
for (const [filePath, content] of pendingWrites.entries()) {
|
|
133
|
+
fs.writeFileSync(filePath, JSON.stringify(content, null, 2) + '\n', 'utf-8');
|
|
134
|
+
}
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
_getValueType(value) {
|
|
138
|
+
if (Array.isArray(value)) {
|
|
139
|
+
return 'array';
|
|
140
|
+
}
|
|
141
|
+
if (typeof value === 'string') {
|
|
142
|
+
return 'string';
|
|
143
|
+
}
|
|
144
|
+
if (typeof value === 'number') {
|
|
145
|
+
return 'number';
|
|
146
|
+
}
|
|
147
|
+
return 'unknown';
|
|
148
|
+
}
|
|
149
|
+
_coerceValue(value, target) {
|
|
150
|
+
const currentType = this._getValueType(value);
|
|
151
|
+
if (currentType === target) {
|
|
152
|
+
return value;
|
|
153
|
+
}
|
|
154
|
+
// string → array: wrap in single-element array
|
|
155
|
+
if (currentType === 'string' && target === 'array') {
|
|
156
|
+
return [value];
|
|
157
|
+
}
|
|
158
|
+
// array → string: unwrap if single element
|
|
159
|
+
if (currentType === 'array' && target === 'string' && Array.isArray(value) && value.length === 1) {
|
|
160
|
+
return value[0];
|
|
161
|
+
}
|
|
162
|
+
// string → number: parse if numeric
|
|
163
|
+
if (currentType === 'string' && target === 'number') {
|
|
164
|
+
const num = Number(value);
|
|
165
|
+
if (!isNaN(num)) {
|
|
166
|
+
return num;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// number → string
|
|
170
|
+
if (currentType === 'number' && target === 'string') {
|
|
171
|
+
return String(value);
|
|
172
|
+
}
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=value-type.rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"value-type.rule.js","sourceRoot":"","sources":["../../src/rules/value-type.rule.ts"],"names":[],"mappings":"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"}
|
package/utils.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description Metadata keys in token JSON files that are not token definitions.
|
|
3
|
+
* @public
|
|
4
|
+
*/
|
|
5
|
+
export declare const METADATA_KEYS: ReadonlyArray<string>;
|
|
6
|
+
/**
|
|
7
|
+
* @description Checks if an object is a token value object with a `value` property.
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export declare function isTokenValue(obj: unknown): obj is {
|
|
11
|
+
value: unknown;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* @description Checks if an object is a nested token group containing sub-objects with `value`.
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
export declare function isNestedTokenGroup(obj: unknown): obj is Record<string, unknown>;
|
|
18
|
+
/**
|
|
19
|
+
* @description Extracts the string value from a token value object.
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
export declare function getTokenStringValue(obj: unknown): string | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* @description Retrieves all token keys from a content object, excluding metadata keys.
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
27
|
+
export declare function getTokenKeys(content: Record<string, unknown>): string[];
|
|
28
|
+
/**
|
|
29
|
+
* @description Collects all flat token entries including nested ones using dot notation for keys.
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
export declare function flattenTokenEntries(content: Record<string, unknown>, prefix?: string): Array<{
|
|
33
|
+
key: string;
|
|
34
|
+
value: unknown;
|
|
35
|
+
}>;
|
|
36
|
+
/**
|
|
37
|
+
* @description Groups token entries by component name.
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
export declare function groupByComponent<T extends {
|
|
41
|
+
component: string;
|
|
42
|
+
}>(entries: ReadonlyArray<T>): Map<string, T[]>;
|
|
43
|
+
/**
|
|
44
|
+
* @description Resolves the `$includes` array of a component entry to the set of token keys
|
|
45
|
+
* those mixins provide. Handles modifier syntax (e.g. `"color:background"` → `backgroundColor`).
|
|
46
|
+
* @public
|
|
47
|
+
*/
|
|
48
|
+
export declare function resolveMixinKeys(includes: ReadonlyArray<string>, mixinKeys: ReadonlyMap<string, ReadonlyArray<string>>): Set<string>;
|
|
49
|
+
/**
|
|
50
|
+
* @description Deep-clones a value and replaces occurrences of the source theme prefix with the target theme prefix
|
|
51
|
+
* in all CSS variable references (e.g. `--memphis-` → `--joy-`).
|
|
52
|
+
* @public
|
|
53
|
+
*/
|
|
54
|
+
export declare function replaceThemePrefix(value: unknown, sourceTheme: string, targetTheme: string): unknown;
|
|
55
|
+
//# sourceMappingURL=utils.d.ts.map
|
package/utils.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,aAAa,CAAC,MAAM,CAAiB,CAAC;AAMlE;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,CAEpE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAM/E;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAMpE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,CAEvE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,SAAK,GAAG,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,CAkBzH;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAY7G;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC5B,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,EAC/B,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,GACtD,GAAG,CAAC,MAAM,CAAC,CAuBb;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAoBpG"}
|
package/utils.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// #region Constants
|
|
2
|
+
/**
|
|
3
|
+
* @description Metadata keys in token JSON files that are not token definitions.
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export const METADATA_KEYS = ['$includes'];
|
|
7
|
+
// #endregion
|
|
8
|
+
// #region Functions
|
|
9
|
+
/**
|
|
10
|
+
* @description Checks if an object is a token value object with a `value` property.
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
export function isTokenValue(obj) {
|
|
14
|
+
return typeof obj === 'object' && obj !== null && 'value' in obj;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* @description Checks if an object is a nested token group containing sub-objects with `value`.
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
export function isNestedTokenGroup(obj) {
|
|
21
|
+
if (typeof obj !== 'object' || obj === null || 'value' in obj) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
return Object.values(obj).some(v => isTokenValue(v));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* @description Extracts the string value from a token value object.
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
export function getTokenStringValue(obj) {
|
|
31
|
+
if (isTokenValue(obj) && typeof obj.value === 'string') {
|
|
32
|
+
return obj.value;
|
|
33
|
+
}
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* @description Retrieves all token keys from a content object, excluding metadata keys.
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
export function getTokenKeys(content) {
|
|
41
|
+
return Object.keys(content).filter(key => !METADATA_KEYS.includes(key));
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* @description Collects all flat token entries including nested ones using dot notation for keys.
|
|
45
|
+
* @public
|
|
46
|
+
*/
|
|
47
|
+
export function flattenTokenEntries(content, prefix = '') {
|
|
48
|
+
const result = [];
|
|
49
|
+
for (const [key, val] of Object.entries(content)) {
|
|
50
|
+
if (METADATA_KEYS.includes(key)) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
54
|
+
if (isTokenValue(val)) {
|
|
55
|
+
result.push({ key: fullKey, value: val.value });
|
|
56
|
+
}
|
|
57
|
+
else if (isNestedTokenGroup(val)) {
|
|
58
|
+
result.push(...flattenTokenEntries(val, fullKey));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* @description Groups token entries by component name.
|
|
65
|
+
* @public
|
|
66
|
+
*/
|
|
67
|
+
export function groupByComponent(entries) {
|
|
68
|
+
const grouped = new Map();
|
|
69
|
+
for (const entry of entries) {
|
|
70
|
+
if (!grouped.has(entry.component)) {
|
|
71
|
+
grouped.set(entry.component, []);
|
|
72
|
+
}
|
|
73
|
+
grouped.get(entry.component).push(entry);
|
|
74
|
+
}
|
|
75
|
+
return grouped;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* @description Resolves the `$includes` array of a component entry to the set of token keys
|
|
79
|
+
* those mixins provide. Handles modifier syntax (e.g. `"color:background"` → `backgroundColor`).
|
|
80
|
+
* @public
|
|
81
|
+
*/
|
|
82
|
+
export function resolveMixinKeys(includes, mixinKeys) {
|
|
83
|
+
const resolved = new Set();
|
|
84
|
+
for (const include of includes) {
|
|
85
|
+
const colonIndex = include.indexOf(':');
|
|
86
|
+
const baseName = colonIndex >= 0 ? include.substring(0, colonIndex) : include;
|
|
87
|
+
const modifier = colonIndex >= 0 ? include.substring(colonIndex + 1) : undefined;
|
|
88
|
+
const keys = mixinKeys.get(baseName);
|
|
89
|
+
if (!keys) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
for (const key of keys) {
|
|
93
|
+
if (modifier) {
|
|
94
|
+
resolved.add(modifier + key);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
resolved.add(key);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return resolved;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* @description Deep-clones a value and replaces occurrences of the source theme prefix with the target theme prefix
|
|
105
|
+
* in all CSS variable references (e.g. `--memphis-` → `--joy-`).
|
|
106
|
+
* @public
|
|
107
|
+
*/
|
|
108
|
+
export function replaceThemePrefix(value, sourceTheme, targetTheme) {
|
|
109
|
+
if (typeof value === 'string') {
|
|
110
|
+
return value.replaceAll(`--${sourceTheme}-`, `--${targetTheme}-`);
|
|
111
|
+
}
|
|
112
|
+
if (Array.isArray(value)) {
|
|
113
|
+
return value.map(item => replaceThemePrefix(item, sourceTheme, targetTheme));
|
|
114
|
+
}
|
|
115
|
+
if (value !== null && typeof value === 'object') {
|
|
116
|
+
const result = {};
|
|
117
|
+
for (const [objKey, objVal] of Object.entries(value)) {
|
|
118
|
+
result[objKey] = replaceThemePrefix(objVal, sourceTheme, targetTheme);
|
|
119
|
+
}
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
return value;
|
|
123
|
+
}
|
|
124
|
+
// #endregion
|
|
125
|
+
//# sourceMappingURL=utils.js.map
|
package/utils.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
|