dispersa 0.4.2 → 1.0.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/README.md +73 -39
- package/dist/android-CRDfSB3_.d.cts +126 -0
- package/dist/android-DANJjjPO.d.ts +126 -0
- package/dist/builders.cjs +220 -64
- package/dist/builders.cjs.map +1 -1
- package/dist/builders.d.cts +15 -13
- package/dist/builders.d.ts +15 -13
- package/dist/builders.js +220 -64
- package/dist/builders.js.map +1 -1
- package/dist/cli/cli.js +120 -7
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/config.d.ts +321 -0
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/index.js +119 -7
- package/dist/cli/index.js.map +1 -1
- package/dist/dispersa-BC1kDF5u.d.ts +118 -0
- package/dist/dispersa-DL3J_Pmz.d.cts +118 -0
- package/dist/errors-qT4sJgSA.d.cts +104 -0
- package/dist/errors-qT4sJgSA.d.ts +104 -0
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.cts +1 -83
- package/dist/errors.d.ts +1 -83
- package/dist/errors.js.map +1 -1
- package/dist/filters.cjs.map +1 -1
- package/dist/filters.d.cts +2 -2
- package/dist/filters.d.ts +2 -2
- package/dist/filters.js.map +1 -1
- package/dist/{index-CNT2Meyf.d.cts → index-Dajm5rvM.d.ts} +311 -132
- package/dist/{index-CqdaN3X0.d.ts → index-De6SjZYH.d.cts} +311 -132
- package/dist/index.cjs +813 -355
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -329
- package/dist/index.d.ts +8 -329
- package/dist/index.js +807 -355
- package/dist/index.js.map +1 -1
- package/dist/lint.cjs +1017 -0
- package/dist/lint.cjs.map +1 -0
- package/dist/lint.d.cts +463 -0
- package/dist/lint.d.ts +463 -0
- package/dist/lint.js +997 -0
- package/dist/lint.js.map +1 -0
- package/dist/preprocessors.d.cts +2 -2
- package/dist/preprocessors.d.ts +2 -2
- package/dist/renderers.cjs.map +1 -1
- package/dist/renderers.d.cts +7 -6
- package/dist/renderers.d.ts +7 -6
- package/dist/renderers.js.map +1 -1
- package/dist/transforms.cjs +0 -12
- package/dist/transforms.cjs.map +1 -1
- package/dist/transforms.d.cts +3 -7
- package/dist/transforms.d.ts +3 -7
- package/dist/transforms.js +1 -12
- package/dist/transforms.js.map +1 -1
- package/dist/{types-CZb19kiq.d.ts → types-8MLtztK3.d.ts} +56 -1
- package/dist/{types-CussyWwe.d.cts → types-BHBHRm0a.d.cts} +56 -1
- package/dist/{types-BAv39mum.d.cts → types-BltzwVYK.d.cts} +1 -1
- package/dist/{types-DWKq-eJj.d.cts → types-CAdUV-fa.d.cts} +1 -1
- package/dist/{types-CzHa7YkW.d.ts → types-DztXKlka.d.ts} +1 -1
- package/dist/{types-Bc0kA7De.d.ts → types-TQHV1MrY.d.cts} +19 -1
- package/dist/{types-Bc0kA7De.d.cts → types-TQHV1MrY.d.ts} +19 -1
- package/dist/{types-BzNcG-rI.d.ts → types-ebxDimRz.d.ts} +1 -1
- package/package.json +11 -1
package/dist/index.cjs
CHANGED
|
@@ -5,7 +5,11 @@ var addFormats = require('ajv-formats');
|
|
|
5
5
|
var fs = require('fs');
|
|
6
6
|
var promises = require('fs/promises');
|
|
7
7
|
var path = require('path');
|
|
8
|
+
var module$1 = require('module');
|
|
9
|
+
var process2 = require('process');
|
|
10
|
+
var jiti = require('jiti');
|
|
8
11
|
var jsonPtr = require('json-ptr');
|
|
12
|
+
var changeCase = require('change-case');
|
|
9
13
|
var culori = require('culori');
|
|
10
14
|
var prettier = require('prettier');
|
|
11
15
|
|
|
@@ -32,6 +36,7 @@ function _interopNamespace(e) {
|
|
|
32
36
|
var Ajv__default = /*#__PURE__*/_interopDefault(Ajv);
|
|
33
37
|
var addFormats__default = /*#__PURE__*/_interopDefault(addFormats);
|
|
34
38
|
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
39
|
+
var process2__default = /*#__PURE__*/_interopDefault(process2);
|
|
35
40
|
var prettier__default = /*#__PURE__*/_interopDefault(prettier);
|
|
36
41
|
|
|
37
42
|
var __defProp = Object.defineProperty;
|
|
@@ -45,7 +50,7 @@ var __export = (target, all) => {
|
|
|
45
50
|
};
|
|
46
51
|
|
|
47
52
|
// src/shared/errors/index.ts
|
|
48
|
-
exports.DispersaError = void 0; exports.TokenReferenceError = void 0; exports.CircularReferenceError = void 0; exports.ValidationError = void 0; exports.FileOperationError = void 0; exports.ConfigurationError = void 0; exports.BasePermutationError = void 0; exports.ModifierError = void 0;
|
|
53
|
+
exports.DispersaError = void 0; exports.TokenReferenceError = void 0; exports.CircularReferenceError = void 0; exports.ValidationError = void 0; exports.FileOperationError = void 0; exports.ConfigurationError = void 0; exports.BasePermutationError = void 0; exports.ModifierError = void 0; exports.LintError = void 0;
|
|
49
54
|
var init_errors = __esm({
|
|
50
55
|
"src/shared/errors/index.ts"() {
|
|
51
56
|
exports.DispersaError = class extends Error {
|
|
@@ -128,23 +133,19 @@ var init_errors = __esm({
|
|
|
128
133
|
this.name = "ModifierError";
|
|
129
134
|
}
|
|
130
135
|
};
|
|
136
|
+
exports.LintError = class extends exports.DispersaError {
|
|
137
|
+
constructor(issues) {
|
|
138
|
+
const errorCount = issues.filter((i) => i.severity === "error").length;
|
|
139
|
+
const warningCount = issues.filter((i) => i.severity === "warn").length;
|
|
140
|
+
super(`Lint failed with ${errorCount} error(s) and ${warningCount} warning(s).`);
|
|
141
|
+
this.issues = issues;
|
|
142
|
+
this.name = "LintError";
|
|
143
|
+
}
|
|
144
|
+
};
|
|
131
145
|
}
|
|
132
146
|
});
|
|
133
147
|
|
|
134
148
|
// src/shared/utils/token-utils.ts
|
|
135
|
-
function formatDeprecationMessage(token, description = "", format = "bracket") {
|
|
136
|
-
if (token.$deprecated == null || token.$deprecated === false) {
|
|
137
|
-
return description;
|
|
138
|
-
}
|
|
139
|
-
const deprecationMsg = typeof token.$deprecated === "string" ? token.$deprecated : "";
|
|
140
|
-
if (format === "comment") {
|
|
141
|
-
const msg2 = deprecationMsg ? ` ${deprecationMsg}` : "";
|
|
142
|
-
return `DEPRECATED${msg2}`;
|
|
143
|
-
}
|
|
144
|
-
const msg = deprecationMsg ? `: ${deprecationMsg}` : "";
|
|
145
|
-
const prefix = `[DEPRECATED${msg}]`;
|
|
146
|
-
return description ? `${prefix} ${description}` : prefix;
|
|
147
|
-
}
|
|
148
149
|
function stripInternalTokenMetadata(tokens) {
|
|
149
150
|
const cleaned = {};
|
|
150
151
|
for (const [name, token] of Object.entries(tokens)) {
|
|
@@ -2498,7 +2499,7 @@ var init_schemas = __esm({
|
|
|
2498
2499
|
});
|
|
2499
2500
|
|
|
2500
2501
|
// src/validation/config-schemas.ts
|
|
2501
|
-
var resolverSchemaRef, basePluginProperties, commonRendererOptionsProperties, transformPluginSchema, rendererPluginSchema, filterPluginSchema, preprocessorPluginSchema, outputConfigSchema, dispersaOptionsSchema, buildConfigSchema;
|
|
2502
|
+
var resolverSchemaRef, basePluginProperties, commonRendererOptionsProperties, transformPluginSchema, rendererPluginSchema, filterPluginSchema, preprocessorPluginSchema, lintConfigSchema, outputConfigSchema, dispersaOptionsSchema, buildConfigSchema;
|
|
2502
2503
|
var init_config_schemas = __esm({
|
|
2503
2504
|
"src/validation/config-schemas.ts"() {
|
|
2504
2505
|
init_schemas();
|
|
@@ -2649,6 +2650,42 @@ var init_config_schemas = __esm({
|
|
|
2649
2650
|
}
|
|
2650
2651
|
}
|
|
2651
2652
|
};
|
|
2653
|
+
lintConfigSchema = {
|
|
2654
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
2655
|
+
type: "object",
|
|
2656
|
+
properties: {
|
|
2657
|
+
enabled: {
|
|
2658
|
+
type: "boolean",
|
|
2659
|
+
description: "Enable linting (default: false, opt-in)"
|
|
2660
|
+
},
|
|
2661
|
+
failOnError: {
|
|
2662
|
+
type: "boolean",
|
|
2663
|
+
description: "Fail build on lint errors (default: true)"
|
|
2664
|
+
},
|
|
2665
|
+
plugins: {
|
|
2666
|
+
type: "object",
|
|
2667
|
+
description: "Plugins to load (by object or module path string)",
|
|
2668
|
+
additionalProperties: {
|
|
2669
|
+
oneOf: [{ type: "string" }, { type: "object" }]
|
|
2670
|
+
}
|
|
2671
|
+
},
|
|
2672
|
+
rules: {
|
|
2673
|
+
type: "object",
|
|
2674
|
+
description: "Rule configurations",
|
|
2675
|
+
additionalProperties: {
|
|
2676
|
+
oneOf: [
|
|
2677
|
+
{ type: "string", enum: ["off", "warn", "error"] },
|
|
2678
|
+
{
|
|
2679
|
+
type: "array",
|
|
2680
|
+
minItems: 2,
|
|
2681
|
+
items: [{ type: "string", enum: ["off", "warn", "error"] }, { type: "object" }]
|
|
2682
|
+
}
|
|
2683
|
+
]
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2686
|
+
},
|
|
2687
|
+
additionalProperties: false
|
|
2688
|
+
};
|
|
2652
2689
|
outputConfigSchema = {
|
|
2653
2690
|
$schema: "http://json-schema.org/draft-07/schema#",
|
|
2654
2691
|
type: "object",
|
|
@@ -2766,10 +2803,20 @@ var init_config_schemas = __esm({
|
|
|
2766
2803
|
description: "Resolver configuration - file path or ResolverDocument object"
|
|
2767
2804
|
},
|
|
2768
2805
|
buildPath: { type: "string" },
|
|
2806
|
+
validation: {
|
|
2807
|
+
type: "object",
|
|
2808
|
+
properties: {
|
|
2809
|
+
mode: { type: "string", enum: ["error", "warn", "off"] }
|
|
2810
|
+
}
|
|
2811
|
+
},
|
|
2769
2812
|
hooks: {
|
|
2770
2813
|
type: "object",
|
|
2771
2814
|
description: "Global build lifecycle hooks (functions, validated at runtime)",
|
|
2772
2815
|
additionalProperties: true
|
|
2816
|
+
},
|
|
2817
|
+
lint: {
|
|
2818
|
+
...lintConfigSchema,
|
|
2819
|
+
description: "Linting configuration"
|
|
2773
2820
|
}
|
|
2774
2821
|
},
|
|
2775
2822
|
additionalProperties: false
|
|
@@ -3317,7 +3364,7 @@ function indentStr(width, level) {
|
|
|
3317
3364
|
function buildGeneratedFileHeader() {
|
|
3318
3365
|
return [
|
|
3319
3366
|
"// Generated by Dispersa - do not edit manually",
|
|
3320
|
-
"// https://github.com/
|
|
3367
|
+
"// https://github.com/dispersa-core/dispersa"
|
|
3321
3368
|
].join("\n");
|
|
3322
3369
|
}
|
|
3323
3370
|
function toSafeIdentifier(name, keywords, capitalize) {
|
|
@@ -3529,6 +3576,94 @@ var init_utils = __esm({
|
|
|
3529
3576
|
}
|
|
3530
3577
|
});
|
|
3531
3578
|
|
|
3579
|
+
// src/renderers/metadata.ts
|
|
3580
|
+
function sanitizeText(text, format) {
|
|
3581
|
+
switch (format) {
|
|
3582
|
+
case "css":
|
|
3583
|
+
case "tailwind":
|
|
3584
|
+
return text.replace(/\*\//g, "*\\/").replace(/\r?\n/g, " ").trim();
|
|
3585
|
+
case "kotlin":
|
|
3586
|
+
return text.replace(/\*\//g, "* /").replace(/\r?\n/g, " ").trim();
|
|
3587
|
+
case "js":
|
|
3588
|
+
case "swift":
|
|
3589
|
+
return text.replace(/\r?\n/g, " ").trim();
|
|
3590
|
+
default:
|
|
3591
|
+
return text.trim();
|
|
3592
|
+
}
|
|
3593
|
+
}
|
|
3594
|
+
function buildDeprecationText(token) {
|
|
3595
|
+
if (token.$deprecated == null || token.$deprecated === false) {
|
|
3596
|
+
return "";
|
|
3597
|
+
}
|
|
3598
|
+
const msg = typeof token.$deprecated === "string" ? token.$deprecated : "";
|
|
3599
|
+
return msg ? `DEPRECATED: ${msg}` : "DEPRECATED";
|
|
3600
|
+
}
|
|
3601
|
+
function buildTokenDescriptionComment(token, format) {
|
|
3602
|
+
if (!token.$description || token.$description === "") {
|
|
3603
|
+
return void 0;
|
|
3604
|
+
}
|
|
3605
|
+
const text = sanitizeText(token.$description, format);
|
|
3606
|
+
switch (format) {
|
|
3607
|
+
case "css":
|
|
3608
|
+
case "tailwind":
|
|
3609
|
+
return `/* ${text} */`;
|
|
3610
|
+
case "js":
|
|
3611
|
+
return `// ${text}`;
|
|
3612
|
+
case "swift":
|
|
3613
|
+
return `/// ${text}`;
|
|
3614
|
+
case "kotlin":
|
|
3615
|
+
return `/** ${text} */`;
|
|
3616
|
+
default:
|
|
3617
|
+
return void 0;
|
|
3618
|
+
}
|
|
3619
|
+
}
|
|
3620
|
+
function buildTokenDeprecationComment(token, format) {
|
|
3621
|
+
const text = buildDeprecationText(token);
|
|
3622
|
+
if (!text) {
|
|
3623
|
+
return void 0;
|
|
3624
|
+
}
|
|
3625
|
+
switch (format) {
|
|
3626
|
+
case "css":
|
|
3627
|
+
case "tailwind":
|
|
3628
|
+
return `/* ${text} */`;
|
|
3629
|
+
case "js":
|
|
3630
|
+
return `// ${text}`;
|
|
3631
|
+
case "swift":
|
|
3632
|
+
return `/// ${text}`;
|
|
3633
|
+
case "kotlin":
|
|
3634
|
+
return `/** ${text} */`;
|
|
3635
|
+
default:
|
|
3636
|
+
return void 0;
|
|
3637
|
+
}
|
|
3638
|
+
}
|
|
3639
|
+
function buildModifierComment(modifier, context) {
|
|
3640
|
+
return `/* Modifier: ${modifier}=${context} */`;
|
|
3641
|
+
}
|
|
3642
|
+
function buildSwiftDeprecationAttribute(token) {
|
|
3643
|
+
if (token.$deprecated == null || token.$deprecated === false) {
|
|
3644
|
+
return void 0;
|
|
3645
|
+
}
|
|
3646
|
+
const msg = typeof token.$deprecated === "string" ? token.$deprecated : "";
|
|
3647
|
+
if (msg) {
|
|
3648
|
+
return `@available(*, deprecated, message: "${sanitizeText(msg, "swift")}")`;
|
|
3649
|
+
}
|
|
3650
|
+
return "@available(*, deprecated)";
|
|
3651
|
+
}
|
|
3652
|
+
function buildKotlinDeprecationAnnotation(token) {
|
|
3653
|
+
if (token.$deprecated == null || token.$deprecated === false) {
|
|
3654
|
+
return void 0;
|
|
3655
|
+
}
|
|
3656
|
+
const msg = typeof token.$deprecated === "string" ? token.$deprecated : "";
|
|
3657
|
+
if (msg) {
|
|
3658
|
+
return `@Deprecated(message = "${sanitizeText(msg, "kotlin")}")`;
|
|
3659
|
+
}
|
|
3660
|
+
return "@Deprecated";
|
|
3661
|
+
}
|
|
3662
|
+
var init_metadata = __esm({
|
|
3663
|
+
"src/renderers/metadata.ts"() {
|
|
3664
|
+
}
|
|
3665
|
+
});
|
|
3666
|
+
|
|
3532
3667
|
// src/renderers/bundlers/js.ts
|
|
3533
3668
|
var js_exports = {};
|
|
3534
3669
|
__export(js_exports, {
|
|
@@ -3633,7 +3768,7 @@ async function bundleAsJsModule(bundleData, resolver, options, formatTokens) {
|
|
|
3633
3768
|
}
|
|
3634
3769
|
const metadata = buildMetadata(resolver);
|
|
3635
3770
|
const jsBlocks = [];
|
|
3636
|
-
for (const { tokens, modifierInputs } of bundleData) {
|
|
3771
|
+
for (const { tokens, modifierInputs, isBase } of bundleData) {
|
|
3637
3772
|
const cleanTokens = stripInternalMetadata(tokens);
|
|
3638
3773
|
const key = buildStableDashKey({
|
|
3639
3774
|
modifierInputs,
|
|
@@ -3641,10 +3776,30 @@ async function bundleAsJsModule(bundleData, resolver, options, formatTokens) {
|
|
|
3641
3776
|
defaults: metadata.defaults
|
|
3642
3777
|
});
|
|
3643
3778
|
const camelKey = toCamelKey(key);
|
|
3779
|
+
const normalizedInputs = normalizeModifierInputs(modifierInputs);
|
|
3780
|
+
const modifierParts = [];
|
|
3781
|
+
for (const dim of metadata.dimensions) {
|
|
3782
|
+
const value = normalizedInputs[dim.toLowerCase()];
|
|
3783
|
+
if (value) {
|
|
3784
|
+
modifierParts.push(`${dim}=${value}`);
|
|
3785
|
+
}
|
|
3786
|
+
}
|
|
3644
3787
|
const formattedJs = await formatTokens(cleanTokens);
|
|
3645
3788
|
const tokenObject = extractObjectFromJsModule(formattedJs);
|
|
3646
3789
|
const indentedObject = tokenObject.replace(/\n/g, "\n ");
|
|
3647
|
-
|
|
3790
|
+
let comment;
|
|
3791
|
+
if (modifierParts.length > 0) {
|
|
3792
|
+
const modifierPart = modifierParts[0];
|
|
3793
|
+
const eqIndex = modifierPart.indexOf("=");
|
|
3794
|
+
const modifier = modifierPart.slice(0, eqIndex);
|
|
3795
|
+
const context = modifierPart.slice(eqIndex + 1);
|
|
3796
|
+
comment = buildModifierComment(modifier, context);
|
|
3797
|
+
} else if (isBase) {
|
|
3798
|
+
comment = "// Base permutation";
|
|
3799
|
+
} else {
|
|
3800
|
+
comment = `// ${key}`;
|
|
3801
|
+
}
|
|
3802
|
+
jsBlocks.push(` ${comment}
|
|
3648
3803
|
${JSON.stringify(camelKey)}: ${indentedObject}`);
|
|
3649
3804
|
}
|
|
3650
3805
|
return assembleJsBundle(metadata, jsBlocks, options?.generateHelper ?? false);
|
|
@@ -3652,6 +3807,7 @@ async function bundleAsJsModule(bundleData, resolver, options, formatTokens) {
|
|
|
3652
3807
|
var init_js = __esm({
|
|
3653
3808
|
"src/renderers/bundlers/js.ts"() {
|
|
3654
3809
|
init_errors();
|
|
3810
|
+
init_metadata();
|
|
3655
3811
|
init_utils();
|
|
3656
3812
|
}
|
|
3657
3813
|
});
|
|
@@ -4021,7 +4177,8 @@ var BuildOrchestrator = class {
|
|
|
4021
4177
|
resolver,
|
|
4022
4178
|
config.transforms,
|
|
4023
4179
|
config.preprocessors,
|
|
4024
|
-
config.filters
|
|
4180
|
+
config.filters,
|
|
4181
|
+
config.lint
|
|
4025
4182
|
);
|
|
4026
4183
|
return this.executeBuild(buildPath, config, permutations2, resolver);
|
|
4027
4184
|
}
|
|
@@ -4032,7 +4189,8 @@ var BuildOrchestrator = class {
|
|
|
4032
4189
|
modifierInputs,
|
|
4033
4190
|
config.transforms,
|
|
4034
4191
|
config.preprocessors,
|
|
4035
|
-
config.filters
|
|
4192
|
+
config.filters,
|
|
4193
|
+
config.lint
|
|
4036
4194
|
);
|
|
4037
4195
|
return { tokens, modifierInputs: resolvedInputs };
|
|
4038
4196
|
})
|
|
@@ -4293,7 +4451,358 @@ var OutputProcessor = class {
|
|
|
4293
4451
|
|
|
4294
4452
|
// src/build/pipeline/token-pipeline.ts
|
|
4295
4453
|
init_resolver_loader();
|
|
4296
|
-
|
|
4454
|
+
|
|
4455
|
+
// src/lint/plugin-loader.ts
|
|
4456
|
+
init_errors();
|
|
4457
|
+
var PluginLoader = class {
|
|
4458
|
+
cwd;
|
|
4459
|
+
jiti = null;
|
|
4460
|
+
cache = /* @__PURE__ */ new Map();
|
|
4461
|
+
constructor(options = {}) {
|
|
4462
|
+
this.cwd = options.cwd ?? process2__default.default.cwd();
|
|
4463
|
+
}
|
|
4464
|
+
/**
|
|
4465
|
+
* Load a plugin from an inline object or module path
|
|
4466
|
+
*
|
|
4467
|
+
* @param source - Plugin object or module path string
|
|
4468
|
+
* @returns Loaded plugin
|
|
4469
|
+
* @throws {ConfigurationError} If plugin cannot be loaded or is invalid
|
|
4470
|
+
*/
|
|
4471
|
+
async load(source) {
|
|
4472
|
+
if (this.isPluginObject(source)) {
|
|
4473
|
+
this.validatePlugin(source);
|
|
4474
|
+
return source;
|
|
4475
|
+
}
|
|
4476
|
+
const modulePath = source;
|
|
4477
|
+
const cached = this.cache.get(modulePath);
|
|
4478
|
+
if (cached) {
|
|
4479
|
+
return cached;
|
|
4480
|
+
}
|
|
4481
|
+
const plugin = await this.loadFromModule(modulePath);
|
|
4482
|
+
this.validatePlugin(plugin);
|
|
4483
|
+
this.cache.set(modulePath, plugin);
|
|
4484
|
+
return plugin;
|
|
4485
|
+
}
|
|
4486
|
+
/**
|
|
4487
|
+
* Load multiple plugins
|
|
4488
|
+
*
|
|
4489
|
+
* @param plugins - Record of namespace to plugin source
|
|
4490
|
+
* @returns Record of namespace to loaded plugin
|
|
4491
|
+
*/
|
|
4492
|
+
async loadAll(plugins) {
|
|
4493
|
+
const entries = Object.entries(plugins);
|
|
4494
|
+
const loaded = await Promise.all(
|
|
4495
|
+
entries.map(async ([namespace, source]) => [namespace, await this.load(source)])
|
|
4496
|
+
);
|
|
4497
|
+
return Object.fromEntries(loaded);
|
|
4498
|
+
}
|
|
4499
|
+
/**
|
|
4500
|
+
* Check if source is an inline plugin object
|
|
4501
|
+
*/
|
|
4502
|
+
isPluginObject(source) {
|
|
4503
|
+
return typeof source !== "string";
|
|
4504
|
+
}
|
|
4505
|
+
/**
|
|
4506
|
+
* Load a plugin from a module path
|
|
4507
|
+
*/
|
|
4508
|
+
async loadFromModule(modulePath) {
|
|
4509
|
+
const resolvedPath = path.isAbsolute(modulePath) ? modulePath : path.resolve(this.cwd, modulePath);
|
|
4510
|
+
const isFilePath = modulePath.startsWith("./") || modulePath.startsWith("../") || path.isAbsolute(modulePath);
|
|
4511
|
+
try {
|
|
4512
|
+
if (isFilePath) {
|
|
4513
|
+
return await this.loadFromFile(resolvedPath);
|
|
4514
|
+
}
|
|
4515
|
+
return await this.loadFromPackage(modulePath);
|
|
4516
|
+
} catch (error) {
|
|
4517
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4518
|
+
throw new exports.ConfigurationError(`Failed to load lint plugin '${modulePath}': ${message}`);
|
|
4519
|
+
}
|
|
4520
|
+
}
|
|
4521
|
+
/**
|
|
4522
|
+
* Load a plugin from a file path using jiti (supports TypeScript)
|
|
4523
|
+
*/
|
|
4524
|
+
async loadFromFile(filePath) {
|
|
4525
|
+
this.jiti ??= jiti.createJiti(this.cwd, {
|
|
4526
|
+
interopDefault: true
|
|
4527
|
+
});
|
|
4528
|
+
const loaded = await this.jiti(filePath);
|
|
4529
|
+
const plugin = this.extractPlugin(loaded);
|
|
4530
|
+
if (!plugin) {
|
|
4531
|
+
throw new exports.ConfigurationError(`Plugin file '${filePath}' does not export a valid LintPlugin`);
|
|
4532
|
+
}
|
|
4533
|
+
return plugin;
|
|
4534
|
+
}
|
|
4535
|
+
/**
|
|
4536
|
+
* Load a plugin from a package name
|
|
4537
|
+
*/
|
|
4538
|
+
async loadFromPackage(packageName) {
|
|
4539
|
+
const require2 = module$1.createRequire(this.cwd);
|
|
4540
|
+
let resolvedPath;
|
|
4541
|
+
try {
|
|
4542
|
+
resolvedPath = require2.resolve(packageName, { paths: [this.cwd] });
|
|
4543
|
+
} catch {
|
|
4544
|
+
try {
|
|
4545
|
+
resolvedPath = require2.resolve(packageName);
|
|
4546
|
+
} catch {
|
|
4547
|
+
throw new exports.ConfigurationError(
|
|
4548
|
+
`Cannot find package '${packageName}'. Make sure it is installed.`
|
|
4549
|
+
);
|
|
4550
|
+
}
|
|
4551
|
+
}
|
|
4552
|
+
this.jiti ??= jiti.createJiti(this.cwd, {
|
|
4553
|
+
interopDefault: true
|
|
4554
|
+
});
|
|
4555
|
+
const loaded = await this.jiti(resolvedPath);
|
|
4556
|
+
const plugin = this.extractPlugin(loaded);
|
|
4557
|
+
if (!plugin) {
|
|
4558
|
+
throw new exports.ConfigurationError(`Package '${packageName}' does not export a valid LintPlugin`);
|
|
4559
|
+
}
|
|
4560
|
+
return plugin;
|
|
4561
|
+
}
|
|
4562
|
+
/**
|
|
4563
|
+
* Extract plugin from loaded module
|
|
4564
|
+
*
|
|
4565
|
+
* Supports multiple export patterns:
|
|
4566
|
+
* - export default plugin
|
|
4567
|
+
* - export const plugin = {...}
|
|
4568
|
+
* - module.exports = plugin (CJS)
|
|
4569
|
+
*/
|
|
4570
|
+
extractPlugin(loaded) {
|
|
4571
|
+
if (!loaded || typeof loaded !== "object") {
|
|
4572
|
+
return null;
|
|
4573
|
+
}
|
|
4574
|
+
const module = loaded;
|
|
4575
|
+
if (module.default && this.isValidPluginStructure(module.default)) {
|
|
4576
|
+
return module.default;
|
|
4577
|
+
}
|
|
4578
|
+
if (module.plugin && this.isValidPluginStructure(module.plugin)) {
|
|
4579
|
+
return module.plugin;
|
|
4580
|
+
}
|
|
4581
|
+
if (this.isValidPluginStructure(loaded)) {
|
|
4582
|
+
return loaded;
|
|
4583
|
+
}
|
|
4584
|
+
return null;
|
|
4585
|
+
}
|
|
4586
|
+
/**
|
|
4587
|
+
* Check if object has required plugin structure
|
|
4588
|
+
*/
|
|
4589
|
+
isValidPluginStructure(obj) {
|
|
4590
|
+
if (!obj || typeof obj !== "object") {
|
|
4591
|
+
return false;
|
|
4592
|
+
}
|
|
4593
|
+
const plugin = obj;
|
|
4594
|
+
const rules = plugin.rules;
|
|
4595
|
+
if (plugin.meta === void 0 || typeof plugin.meta !== "object" || !plugin.meta.name || rules === void 0 || Object.keys(rules).length === 0) {
|
|
4596
|
+
return false;
|
|
4597
|
+
}
|
|
4598
|
+
return true;
|
|
4599
|
+
}
|
|
4600
|
+
/**
|
|
4601
|
+
* Validate a loaded plugin
|
|
4602
|
+
*/
|
|
4603
|
+
validatePlugin(plugin) {
|
|
4604
|
+
if (!plugin.meta) {
|
|
4605
|
+
throw new exports.ConfigurationError("Lint plugin must have a meta property with name");
|
|
4606
|
+
}
|
|
4607
|
+
if (!plugin.meta.name) {
|
|
4608
|
+
throw new exports.ConfigurationError("Lint plugin meta.name is required");
|
|
4609
|
+
}
|
|
4610
|
+
if (!plugin.rules || typeof plugin.rules !== "object" || Object.keys(plugin.rules).length === 0) {
|
|
4611
|
+
throw new exports.ConfigurationError(
|
|
4612
|
+
`Lint plugin '${plugin.meta.name}' must have a non-empty rules object`
|
|
4613
|
+
);
|
|
4614
|
+
}
|
|
4615
|
+
for (const [ruleName, rule] of Object.entries(plugin.rules)) {
|
|
4616
|
+
if (!rule.meta) {
|
|
4617
|
+
throw new exports.ConfigurationError(
|
|
4618
|
+
`Rule '${ruleName}' in plugin '${plugin.meta.name}' is missing meta property`
|
|
4619
|
+
);
|
|
4620
|
+
}
|
|
4621
|
+
if (!rule.meta.messages || typeof rule.meta.messages !== "object") {
|
|
4622
|
+
throw new exports.ConfigurationError(
|
|
4623
|
+
`Rule '${ruleName}' in plugin '${plugin.meta.name}' is missing meta.messages`
|
|
4624
|
+
);
|
|
4625
|
+
}
|
|
4626
|
+
if (typeof rule.create !== "function") {
|
|
4627
|
+
throw new exports.ConfigurationError(
|
|
4628
|
+
`Rule '${ruleName}' in plugin '${plugin.meta.name}' is missing create function`
|
|
4629
|
+
);
|
|
4630
|
+
}
|
|
4631
|
+
}
|
|
4632
|
+
}
|
|
4633
|
+
/**
|
|
4634
|
+
* Clear the plugin cache
|
|
4635
|
+
*/
|
|
4636
|
+
clearCache() {
|
|
4637
|
+
this.cache.clear();
|
|
4638
|
+
}
|
|
4639
|
+
};
|
|
4640
|
+
|
|
4641
|
+
// src/lint/lint-runner.ts
|
|
4642
|
+
var LintRunner = class {
|
|
4643
|
+
config;
|
|
4644
|
+
pluginLoader;
|
|
4645
|
+
resolvedConfig = null;
|
|
4646
|
+
warn;
|
|
4647
|
+
constructor(config) {
|
|
4648
|
+
this.config = config;
|
|
4649
|
+
this.pluginLoader = new PluginLoader();
|
|
4650
|
+
this.warn = config.onWarn ?? console.warn;
|
|
4651
|
+
}
|
|
4652
|
+
/**
|
|
4653
|
+
* Run all configured rules against the provided tokens
|
|
4654
|
+
*
|
|
4655
|
+
* Rules are executed in parallel for performance. Issues are collected
|
|
4656
|
+
* and returned with counts by severity.
|
|
4657
|
+
*
|
|
4658
|
+
* @param tokens - Resolved tokens to lint
|
|
4659
|
+
* @returns Lint result with issues and counts
|
|
4660
|
+
*/
|
|
4661
|
+
async run(tokens) {
|
|
4662
|
+
this.resolvedConfig ??= await this.resolveConfig();
|
|
4663
|
+
const { rules, plugins } = this.resolvedConfig;
|
|
4664
|
+
const issues = [];
|
|
4665
|
+
if (Object.keys(rules).length === 0) {
|
|
4666
|
+
return { issues: [], errorCount: 0, warningCount: 0 };
|
|
4667
|
+
}
|
|
4668
|
+
const rulePromises = Object.entries(rules).map(async ([ruleId, ruleConfig]) => {
|
|
4669
|
+
const { severity, options } = ruleConfig;
|
|
4670
|
+
const rule = this.resolveRule(ruleId, plugins);
|
|
4671
|
+
if (!rule) {
|
|
4672
|
+
this.warn(`[lint] Unknown rule '${ruleId}' - no plugin provides this rule`);
|
|
4673
|
+
return [];
|
|
4674
|
+
}
|
|
4675
|
+
const reports = [];
|
|
4676
|
+
const applicableTokens = this.filterTokensByAppliesTo(tokens, rule.meta.appliesTo);
|
|
4677
|
+
const mergedOptions = rule.defaultOptions ? { ...rule.defaultOptions, ...options } : options;
|
|
4678
|
+
const context = {
|
|
4679
|
+
id: ruleId,
|
|
4680
|
+
options: mergedOptions,
|
|
4681
|
+
tokens: applicableTokens,
|
|
4682
|
+
report: (descriptor) => {
|
|
4683
|
+
reports.push(descriptor);
|
|
4684
|
+
}
|
|
4685
|
+
};
|
|
4686
|
+
try {
|
|
4687
|
+
await rule.create(context);
|
|
4688
|
+
} catch (error) {
|
|
4689
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4690
|
+
return [
|
|
4691
|
+
{
|
|
4692
|
+
ruleId: "lint/rule-error",
|
|
4693
|
+
severity: "error",
|
|
4694
|
+
message: `Rule '${ruleId}' failed: ${message}`,
|
|
4695
|
+
tokenName: "(rule execution)",
|
|
4696
|
+
tokenPath: []
|
|
4697
|
+
}
|
|
4698
|
+
];
|
|
4699
|
+
}
|
|
4700
|
+
return reports.map((report) => {
|
|
4701
|
+
const messageTemplate = rule.meta.messages[report.messageId];
|
|
4702
|
+
const message = messageTemplate ? this.interpolateMessage(messageTemplate, report.data) : report.messageId;
|
|
4703
|
+
return {
|
|
4704
|
+
ruleId,
|
|
4705
|
+
severity,
|
|
4706
|
+
message,
|
|
4707
|
+
tokenName: report.token.name,
|
|
4708
|
+
tokenPath: report.token.path
|
|
4709
|
+
};
|
|
4710
|
+
});
|
|
4711
|
+
});
|
|
4712
|
+
const allIssues = await Promise.all(rulePromises);
|
|
4713
|
+
issues.push(...allIssues.flat());
|
|
4714
|
+
const errorCount = issues.filter((i) => i.severity === "error").length;
|
|
4715
|
+
const warningCount = issues.filter((i) => i.severity === "warn").length;
|
|
4716
|
+
return { issues, errorCount, warningCount };
|
|
4717
|
+
}
|
|
4718
|
+
/**
|
|
4719
|
+
* Resolve configuration: load plugins, parse rule configs
|
|
4720
|
+
*/
|
|
4721
|
+
async resolveConfig() {
|
|
4722
|
+
const { plugins: pluginSources = {}, rules: ruleConfigs = {} } = this.config;
|
|
4723
|
+
const plugins = await this.pluginLoader.loadAll(pluginSources);
|
|
4724
|
+
const rules = {};
|
|
4725
|
+
for (const [ruleId, config] of Object.entries(ruleConfigs)) {
|
|
4726
|
+
const resolved = this.resolveRuleConfig(config);
|
|
4727
|
+
if (resolved) {
|
|
4728
|
+
rules[ruleId] = resolved;
|
|
4729
|
+
}
|
|
4730
|
+
}
|
|
4731
|
+
return {
|
|
4732
|
+
enabled: true,
|
|
4733
|
+
failOnError: this.config.failOnError ?? true,
|
|
4734
|
+
plugins,
|
|
4735
|
+
rules
|
|
4736
|
+
};
|
|
4737
|
+
}
|
|
4738
|
+
filterTokensByAppliesTo(tokens, appliesTo) {
|
|
4739
|
+
if (!appliesTo || appliesTo === "all") {
|
|
4740
|
+
return tokens;
|
|
4741
|
+
}
|
|
4742
|
+
const filtered = {};
|
|
4743
|
+
for (const [name, token] of Object.entries(tokens)) {
|
|
4744
|
+
if (token.$type && appliesTo.includes(token.$type)) {
|
|
4745
|
+
filtered[name] = token;
|
|
4746
|
+
}
|
|
4747
|
+
}
|
|
4748
|
+
return filtered;
|
|
4749
|
+
}
|
|
4750
|
+
/**
|
|
4751
|
+
* Parse rule configuration into resolved format
|
|
4752
|
+
*/
|
|
4753
|
+
resolveRuleConfig(config) {
|
|
4754
|
+
if (typeof config === "string") {
|
|
4755
|
+
if (config === "off") {
|
|
4756
|
+
return null;
|
|
4757
|
+
}
|
|
4758
|
+
return { severity: config, options: {} };
|
|
4759
|
+
}
|
|
4760
|
+
const [severity, options = {}] = config;
|
|
4761
|
+
if (severity === "off") {
|
|
4762
|
+
return null;
|
|
4763
|
+
}
|
|
4764
|
+
return { severity, options };
|
|
4765
|
+
}
|
|
4766
|
+
/**
|
|
4767
|
+
* Resolve a rule from plugins by rule ID
|
|
4768
|
+
*
|
|
4769
|
+
* Rule IDs are formatted as 'namespace/rule-name'
|
|
4770
|
+
*/
|
|
4771
|
+
resolveRule(ruleId, plugins) {
|
|
4772
|
+
const separatorIndex = ruleId.indexOf("/");
|
|
4773
|
+
if (separatorIndex === -1) {
|
|
4774
|
+
return null;
|
|
4775
|
+
}
|
|
4776
|
+
const namespace = ruleId.slice(0, separatorIndex);
|
|
4777
|
+
const ruleName = ruleId.slice(separatorIndex + 1);
|
|
4778
|
+
const plugin = plugins[namespace];
|
|
4779
|
+
if (!plugin) {
|
|
4780
|
+
return null;
|
|
4781
|
+
}
|
|
4782
|
+
return plugin.rules[ruleName] ?? null;
|
|
4783
|
+
}
|
|
4784
|
+
/**
|
|
4785
|
+
* Interpolate message template with data
|
|
4786
|
+
*
|
|
4787
|
+
* Replaces {{key}} placeholders with values from data
|
|
4788
|
+
*/
|
|
4789
|
+
interpolateMessage(template, data) {
|
|
4790
|
+
if (!data) {
|
|
4791
|
+
return template;
|
|
4792
|
+
}
|
|
4793
|
+
return template.replace(/\{\{(\w+)\}\}/g, (_, key) => {
|
|
4794
|
+
const value = data[key];
|
|
4795
|
+
return value !== void 0 ? String(value) : `{{${key}}}`;
|
|
4796
|
+
});
|
|
4797
|
+
}
|
|
4798
|
+
/**
|
|
4799
|
+
* Clear the plugin cache
|
|
4800
|
+
*/
|
|
4801
|
+
clearCache() {
|
|
4802
|
+
this.pluginLoader.clearCache();
|
|
4803
|
+
this.resolvedConfig = null;
|
|
4804
|
+
}
|
|
4805
|
+
};
|
|
4297
4806
|
|
|
4298
4807
|
// src/shared/constants.ts
|
|
4299
4808
|
var DEFAULT_MAX_ALIAS_DEPTH = 10;
|
|
@@ -5488,6 +5997,10 @@ var ResolutionEngine = class {
|
|
|
5488
5997
|
return typeof obj === "object" && obj !== null && "contexts" in obj && typeof obj.contexts === "object";
|
|
5489
5998
|
}
|
|
5490
5999
|
};
|
|
6000
|
+
|
|
6001
|
+
// src/build/pipeline/token-pipeline.ts
|
|
6002
|
+
init_errors();
|
|
6003
|
+
init_validation_handler();
|
|
5491
6004
|
init_errors();
|
|
5492
6005
|
|
|
5493
6006
|
// src/shared/utils/path-utils.ts
|
|
@@ -5980,6 +6493,8 @@ var TokenPipeline = class {
|
|
|
5980
6493
|
resolverLoader;
|
|
5981
6494
|
tokenParser;
|
|
5982
6495
|
aliasResolver;
|
|
6496
|
+
lintRunner = null;
|
|
6497
|
+
lintConfigCache = null;
|
|
5983
6498
|
constructor(options = {}) {
|
|
5984
6499
|
this.options = options;
|
|
5985
6500
|
this.validationHandler = new ValidationHandler(options.validation);
|
|
@@ -5999,8 +6514,9 @@ var TokenPipeline = class {
|
|
|
5999
6514
|
* 6. Parse and flatten token structure
|
|
6000
6515
|
* 7. Resolve alias references
|
|
6001
6516
|
* 8. Strip $root from token names/paths (DTCG structural mechanism, transparent in output)
|
|
6002
|
-
* 9.
|
|
6003
|
-
* 10. Apply
|
|
6517
|
+
* 9. Run lint rules (if enabled)
|
|
6518
|
+
* 10. Apply filters (if provided) — runs first to remove tokens before transforms
|
|
6519
|
+
* 11. Apply transforms (if provided) — runs on the already-filtered token set
|
|
6004
6520
|
*
|
|
6005
6521
|
* Each stage is explicitly typed to ensure correct order and prevent temporal coupling.
|
|
6006
6522
|
*
|
|
@@ -6009,9 +6525,11 @@ var TokenPipeline = class {
|
|
|
6009
6525
|
* @param transformList - Optional transforms to apply
|
|
6010
6526
|
* @param preprocessorList - Optional preprocessors to apply
|
|
6011
6527
|
* @param filterList - Optional filters to apply before transforms
|
|
6012
|
-
* @
|
|
6528
|
+
* @param lintConfig - Optional lint configuration for this run
|
|
6529
|
+
* @returns Final tokens, resolution engine, and lint result
|
|
6013
6530
|
*/
|
|
6014
|
-
async resolve(resolver, modifierInputs, transformList, preprocessorList, filterList) {
|
|
6531
|
+
async resolve(resolver, modifierInputs, transformList, preprocessorList, filterList, lintConfig) {
|
|
6532
|
+
const effectiveLintConfig = lintConfig ?? this.options.lint;
|
|
6015
6533
|
const stage1 = await this.loadResolver(resolver);
|
|
6016
6534
|
const engine = this.createEngine(stage1);
|
|
6017
6535
|
const result = await this.runPipelineStages(
|
|
@@ -6019,29 +6537,32 @@ var TokenPipeline = class {
|
|
|
6019
6537
|
modifierInputs,
|
|
6020
6538
|
preprocessorList,
|
|
6021
6539
|
filterList,
|
|
6022
|
-
transformList
|
|
6540
|
+
transformList,
|
|
6541
|
+
effectiveLintConfig
|
|
6023
6542
|
);
|
|
6024
6543
|
return {
|
|
6025
6544
|
tokens: result.tokens,
|
|
6026
6545
|
resolutionEngine: result.resolutionEngine,
|
|
6027
|
-
modifierInputs: result.modifierInputs
|
|
6546
|
+
modifierInputs: result.modifierInputs,
|
|
6547
|
+
lintResult: result.lintResult
|
|
6028
6548
|
};
|
|
6029
6549
|
}
|
|
6030
6550
|
/**
|
|
6031
|
-
* Run pipeline stages 3-
|
|
6551
|
+
* Run pipeline stages 3-11 on a pre-created engine
|
|
6032
6552
|
*
|
|
6033
6553
|
* Shared by both `resolve()` (single permutation) and
|
|
6034
6554
|
* `resolveAllPermutations()` (parallel permutations) to keep the
|
|
6035
6555
|
* stage sequence defined in exactly one place.
|
|
6036
6556
|
*/
|
|
6037
|
-
async runPipelineStages(engine, modifierInputs, preprocessorList, filterList, transformList) {
|
|
6557
|
+
async runPipelineStages(engine, modifierInputs, preprocessorList, filterList, transformList, lintConfig) {
|
|
6038
6558
|
const rawTokens = await this.resolveTokens(engine, modifierInputs);
|
|
6039
6559
|
const preprocessed = await this.preprocessTokens(rawTokens, preprocessorList);
|
|
6040
6560
|
const refResolved = await this.resolveReferences(preprocessed);
|
|
6041
6561
|
const flattened = this.flattenTokens(refResolved);
|
|
6042
6562
|
const aliasResolved = this.resolveAliases(flattened);
|
|
6043
6563
|
const rootStripped = this.stripRootTokenNames(aliasResolved);
|
|
6044
|
-
const
|
|
6564
|
+
const linted = await this.runLintStage(rootStripped, lintConfig);
|
|
6565
|
+
const filtered = this.applyFilterStage(linted, filterList);
|
|
6045
6566
|
return this.applyTransformStage(filtered, transformList);
|
|
6046
6567
|
}
|
|
6047
6568
|
/**
|
|
@@ -6154,6 +6675,47 @@ var TokenPipeline = class {
|
|
|
6154
6675
|
}
|
|
6155
6676
|
return { ...stage, aliasResolvedTokens: result };
|
|
6156
6677
|
}
|
|
6678
|
+
/**
|
|
6679
|
+
* Stage 9: Run lint rules against tokens
|
|
6680
|
+
*
|
|
6681
|
+
* Linting runs after alias resolution and $root stripping but before
|
|
6682
|
+
* filters and transforms. This ensures rules see the full token set
|
|
6683
|
+
* with resolved values.
|
|
6684
|
+
*/
|
|
6685
|
+
async runLintStage(stage, lintConfig) {
|
|
6686
|
+
if (!lintConfig?.enabled) {
|
|
6687
|
+
return stage;
|
|
6688
|
+
}
|
|
6689
|
+
if (!this.lintRunner || !this.isLintConfigEqual(this.lintConfigCache, lintConfig)) {
|
|
6690
|
+
this.lintRunner = new LintRunner({
|
|
6691
|
+
plugins: lintConfig.plugins,
|
|
6692
|
+
rules: lintConfig.rules,
|
|
6693
|
+
onWarn: (msg) => this.validationHandler.warn(msg)
|
|
6694
|
+
});
|
|
6695
|
+
this.lintConfigCache = lintConfig;
|
|
6696
|
+
}
|
|
6697
|
+
const lintResult = await this.lintRunner.run(stage.aliasResolvedTokens);
|
|
6698
|
+
if (lintResult.errorCount > 0 && lintConfig.failOnError !== false) {
|
|
6699
|
+
throw new exports.LintError(lintResult.issues);
|
|
6700
|
+
}
|
|
6701
|
+
for (const issue of lintResult.issues.filter((i) => i.severity === "warn")) {
|
|
6702
|
+
this.validationHandler.warn(
|
|
6703
|
+
`[${issue.ruleId}] ${issue.message} (token: ${issue.tokenName})`
|
|
6704
|
+
);
|
|
6705
|
+
}
|
|
6706
|
+
return { ...stage, lintResult };
|
|
6707
|
+
}
|
|
6708
|
+
isLintConfigEqual(a, b) {
|
|
6709
|
+
if (!a || !b) return false;
|
|
6710
|
+
if (a.enabled !== b.enabled) return false;
|
|
6711
|
+
if (a.failOnError !== b.failOnError) return false;
|
|
6712
|
+
if (a.plugins !== b.plugins) return false;
|
|
6713
|
+
if (a.rules !== b.rules) return false;
|
|
6714
|
+
return true;
|
|
6715
|
+
}
|
|
6716
|
+
/**
|
|
6717
|
+
* Stage 10: Apply filters to the linted token set
|
|
6718
|
+
*/
|
|
6157
6719
|
applyFilterStage(stage, filterList) {
|
|
6158
6720
|
let tokens = stage.aliasResolvedTokens;
|
|
6159
6721
|
if (filterList !== void 0 && filterList.length > 0) {
|
|
@@ -6162,7 +6724,7 @@ var TokenPipeline = class {
|
|
|
6162
6724
|
return { ...stage, aliasResolvedTokens: tokens };
|
|
6163
6725
|
}
|
|
6164
6726
|
/**
|
|
6165
|
-
* Stage
|
|
6727
|
+
* Stage 11: Apply transforms to the filtered token set
|
|
6166
6728
|
*/
|
|
6167
6729
|
applyTransformStage(stage, transformList) {
|
|
6168
6730
|
let tokens = stage.aliasResolvedTokens;
|
|
@@ -6196,8 +6758,10 @@ var TokenPipeline = class {
|
|
|
6196
6758
|
* @param transformList - Optional transforms to apply
|
|
6197
6759
|
* @param preprocessorList - Optional preprocessors to apply
|
|
6198
6760
|
* @param filterList - Optional filters to apply before transforms
|
|
6761
|
+
* @param lintConfig - Optional lint configuration for this run
|
|
6199
6762
|
*/
|
|
6200
|
-
async resolveAllPermutations(resolver, transformList, preprocessorList, filterList) {
|
|
6763
|
+
async resolveAllPermutations(resolver, transformList, preprocessorList, filterList, lintConfig) {
|
|
6764
|
+
const effectiveLintConfig = lintConfig ?? this.options.lint;
|
|
6201
6765
|
const stage1 = await this.loadResolver(resolver);
|
|
6202
6766
|
const discoveryEngine = this.createEngine(stage1);
|
|
6203
6767
|
const permutationInputs = discoveryEngine.resolutionEngine.generatePermutations();
|
|
@@ -6210,11 +6774,13 @@ var TokenPipeline = class {
|
|
|
6210
6774
|
modifierInputs,
|
|
6211
6775
|
preprocessorList,
|
|
6212
6776
|
filterList,
|
|
6213
|
-
transformList
|
|
6777
|
+
transformList,
|
|
6778
|
+
effectiveLintConfig
|
|
6214
6779
|
);
|
|
6215
6780
|
return {
|
|
6216
6781
|
tokens: result.tokens,
|
|
6217
|
-
modifierInputs: result.modifierInputs
|
|
6782
|
+
modifierInputs: result.modifierInputs,
|
|
6783
|
+
lintResult: result.lintResult
|
|
6218
6784
|
};
|
|
6219
6785
|
})
|
|
6220
6786
|
);
|
|
@@ -6235,286 +6801,106 @@ var TokenPipeline = class {
|
|
|
6235
6801
|
init_errors();
|
|
6236
6802
|
init_token_utils();
|
|
6237
6803
|
init_validator();
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
const errors = this.validator.validateDispersaOptions(options);
|
|
6256
|
-
if (errors.length > 0) {
|
|
6257
|
-
throw new exports.ConfigurationError(
|
|
6258
|
-
`Invalid Dispersa options: ${this.validator.getErrorMessage(errors)}`
|
|
6259
|
-
);
|
|
6260
|
-
}
|
|
6261
|
-
this.pipeline = new TokenPipeline({ validation: options.validation });
|
|
6262
|
-
this.outputProcessor = new OutputProcessor();
|
|
6263
|
-
this.orchestrator = new BuildOrchestrator(this.pipeline, this.outputProcessor);
|
|
6264
|
-
}
|
|
6265
|
-
/**
|
|
6266
|
-
* Builds design tokens from a resolver configuration
|
|
6267
|
-
*
|
|
6268
|
-
* Processes tokens through the resolution pipeline, applies preprocessors,
|
|
6269
|
-
* transforms, and filters, then generates output files in multiple formats
|
|
6270
|
-
* for specified outputs.
|
|
6271
|
-
*
|
|
6272
|
-
* **Runtime Validation:**
|
|
6273
|
-
* This method validates the build configuration
|
|
6274
|
-
* and all output configurations before processing, throwing helpful errors for
|
|
6275
|
-
* invalid inputs.
|
|
6276
|
-
*
|
|
6277
|
-
* **Permutation Handling:**
|
|
6278
|
-
* - If `config.permutations` is provided and non-empty, builds those specific permutations
|
|
6279
|
-
* - If `config.permutations` is undefined or empty, auto-discovers all permutations from resolver
|
|
6280
|
-
*
|
|
6281
|
-
* @param config - Build configuration
|
|
6282
|
-
* @param config.resolver - Resolver configuration (file path or inline object, optional if set in constructor)
|
|
6283
|
-
* @param config.outputs - Array of output configurations (renderers, transforms, filters)
|
|
6284
|
-
* @param config.buildPath - Output directory for generated files (omit for in-memory mode, optional if set in constructor)
|
|
6285
|
-
* @param config.transforms - Global transforms to apply to all tokens
|
|
6286
|
-
* @param config.preprocessors - Global preprocessors to apply before parsing
|
|
6287
|
-
* @param config.permutations - Array of modifier inputs for generating variations
|
|
6288
|
-
* @returns Build result with success status and generated output files
|
|
6289
|
-
* @throws {ConfigurationError} If configuration is invalid
|
|
6290
|
-
* @throws {FileOperationError} If file operations fail
|
|
6291
|
-
*
|
|
6292
|
-
* @example Basic build
|
|
6293
|
-
* ```typescript
|
|
6294
|
-
* const dispersa = new Dispersa({
|
|
6295
|
-
* resolver: './tokens.resolver.json',
|
|
6296
|
-
* buildPath: './output'
|
|
6297
|
-
* })
|
|
6298
|
-
*
|
|
6299
|
-
* const result = await dispersa.build({
|
|
6300
|
-
* outputs: [
|
|
6301
|
-
* css({
|
|
6302
|
-
* name: 'css',
|
|
6303
|
-
* file: 'tokens.css',
|
|
6304
|
-
* preset: 'bundle',
|
|
6305
|
-
* selector: ':root',
|
|
6306
|
-
* transforms: [nameKebabCase()]
|
|
6307
|
-
* })
|
|
6308
|
-
* ]
|
|
6309
|
-
* })
|
|
6310
|
-
* ```
|
|
6311
|
-
*
|
|
6312
|
-
* @example With filters and multiple presets
|
|
6313
|
-
* ```typescript
|
|
6314
|
-
* const result = await dispersa.build({
|
|
6315
|
-
* resolver: './tokens.resolver.json',
|
|
6316
|
-
* outputs: [
|
|
6317
|
-
* css({
|
|
6318
|
-
* name: 'css',
|
|
6319
|
-
* file: 'tokens.css',
|
|
6320
|
-
* preset: 'bundle',
|
|
6321
|
-
* selector: ':root', // All themes in one file
|
|
6322
|
-
* transforms: [nameKebabCase()]
|
|
6323
|
-
* }),
|
|
6324
|
-
* json({
|
|
6325
|
-
* name: 'json',
|
|
6326
|
-
* file: 'tokens-{theme}.json', // Separate file per theme
|
|
6327
|
-
* preset: 'standalone',
|
|
6328
|
-
* structure: 'flat'
|
|
6329
|
-
* })
|
|
6330
|
-
* ],
|
|
6331
|
-
* buildPath: './output',
|
|
6332
|
-
* permutations: [
|
|
6333
|
-
* { theme: 'light' },
|
|
6334
|
-
* { theme: 'dark' }
|
|
6335
|
-
* ]
|
|
6336
|
-
* })
|
|
6337
|
-
* ```
|
|
6338
|
-
*/
|
|
6339
|
-
async build(config) {
|
|
6340
|
-
try {
|
|
6341
|
-
return await this.buildOrThrow(config);
|
|
6342
|
-
} catch (error) {
|
|
6343
|
-
return {
|
|
6344
|
-
success: false,
|
|
6345
|
-
outputs: [],
|
|
6346
|
-
errors: [toBuildError(error)]
|
|
6347
|
-
};
|
|
6348
|
-
}
|
|
6349
|
-
}
|
|
6350
|
-
/**
|
|
6351
|
-
* Builds design tokens and throws on any failure.
|
|
6352
|
-
*
|
|
6353
|
-
* Unlike {@link build}, which catches errors and returns them inside
|
|
6354
|
-
* `BuildResult.errors`, this method propagates the first error as an
|
|
6355
|
-
* exception. Use it when you want fail-fast behavior in CLI or CI workflows.
|
|
6356
|
-
*
|
|
6357
|
-
* @param config - Build configuration specifying resolver, outputs, transforms, etc.
|
|
6358
|
-
* @returns A successful `BuildResult` (never contains errors)
|
|
6359
|
-
* @throws {ConfigurationError} When the build config or resolver is invalid
|
|
6360
|
-
* @throws {DispersaError} When token resolution, transforms, or rendering fails
|
|
6361
|
-
*
|
|
6362
|
-
* @example
|
|
6363
|
-
* ```typescript
|
|
6364
|
-
* try {
|
|
6365
|
-
* const result = await dispersa.buildOrThrow({
|
|
6366
|
-
* resolver: './tokens.resolver.json',
|
|
6367
|
-
* outputs: [css({ name: 'css', file: 'tokens.css' })],
|
|
6368
|
-
* buildPath: './output',
|
|
6369
|
-
* })
|
|
6370
|
-
* } catch (error) {
|
|
6371
|
-
* process.exit(1)
|
|
6372
|
-
* }
|
|
6373
|
-
* ```
|
|
6374
|
-
*/
|
|
6375
|
-
async buildOrThrow(config) {
|
|
6376
|
-
const configErrors = this.validator.validateBuildConfig(config);
|
|
6377
|
-
if (configErrors.length > 0) {
|
|
6378
|
-
throw new exports.ConfigurationError(
|
|
6379
|
-
`Invalid build configuration: ${this.validator.getErrorMessage(configErrors)}`
|
|
6380
|
-
);
|
|
6381
|
-
}
|
|
6382
|
-
for (const output of config.outputs) {
|
|
6383
|
-
const outputErrors = this.validator.validateOutputConfig(output);
|
|
6384
|
-
if (outputErrors.length > 0) {
|
|
6385
|
-
throw new exports.ConfigurationError(
|
|
6386
|
-
`Invalid output '${output.name}': ${this.validator.getErrorMessage(outputErrors)}`
|
|
6387
|
-
);
|
|
6388
|
-
}
|
|
6389
|
-
}
|
|
6390
|
-
const { resolver, buildPath } = this.resolveConfig(config);
|
|
6391
|
-
return this.orchestrator.build(resolver, buildPath, config);
|
|
6804
|
+
function createValidator() {
|
|
6805
|
+
return new SchemaValidator();
|
|
6806
|
+
}
|
|
6807
|
+
function createPipeline(options) {
|
|
6808
|
+
return new TokenPipeline({ validation: options?.validation });
|
|
6809
|
+
}
|
|
6810
|
+
function createOutputProcessor() {
|
|
6811
|
+
return new OutputProcessor();
|
|
6812
|
+
}
|
|
6813
|
+
function createOrchestrator(pipeline, outputProcessor) {
|
|
6814
|
+
return new BuildOrchestrator(pipeline, outputProcessor);
|
|
6815
|
+
}
|
|
6816
|
+
function resolveConfig(config, options) {
|
|
6817
|
+
const resolver = config.resolver ?? options?.resolver;
|
|
6818
|
+
const buildPath = config.buildPath ?? options?.buildPath ?? "";
|
|
6819
|
+
if (!resolver) {
|
|
6820
|
+
throw new exports.ConfigurationError("resolver is required in build config");
|
|
6392
6821
|
}
|
|
6393
|
-
|
|
6394
|
-
|
|
6395
|
-
|
|
6396
|
-
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
|
|
6400
|
-
|
|
6401
|
-
* @param config - Build configuration
|
|
6402
|
-
* @param modifierInputs - Modifier values (e.g., `{ theme: 'dark' }`)
|
|
6403
|
-
* @returns Build result (success, outputs, optional errors)
|
|
6404
|
-
*/
|
|
6405
|
-
async buildPermutation(config, modifierInputs = {}) {
|
|
6406
|
-
return await this.build({
|
|
6407
|
-
...config,
|
|
6408
|
-
permutations: [modifierInputs]
|
|
6409
|
-
});
|
|
6822
|
+
return { resolver, buildPath };
|
|
6823
|
+
}
|
|
6824
|
+
function validateBuildConfig(validator, config) {
|
|
6825
|
+
const configErrors = validator.validateBuildConfig(config);
|
|
6826
|
+
if (configErrors.length > 0) {
|
|
6827
|
+
throw new exports.ConfigurationError(
|
|
6828
|
+
`Invalid build configuration: ${validator.getErrorMessage(configErrors)}`
|
|
6829
|
+
);
|
|
6410
6830
|
}
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
resolveConfig(config) {
|
|
6415
|
-
const resolver = config.resolver ?? this.options.resolver;
|
|
6416
|
-
const buildPath = config.buildPath ?? this.options.buildPath ?? "";
|
|
6417
|
-
if (!resolver) {
|
|
6831
|
+
for (const output of config.outputs) {
|
|
6832
|
+
const outputErrors = validator.validateOutputConfig(output);
|
|
6833
|
+
if (outputErrors.length > 0) {
|
|
6418
6834
|
throw new exports.ConfigurationError(
|
|
6419
|
-
|
|
6835
|
+
`Invalid output '${output.name}': ${validator.getErrorMessage(outputErrors)}`
|
|
6420
6836
|
);
|
|
6421
6837
|
}
|
|
6422
|
-
return { resolver, buildPath };
|
|
6423
6838
|
}
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
* ```typescript
|
|
6439
|
-
* const tokens = await dispersa.resolveTokens(
|
|
6440
|
-
* './tokens.resolver.json',
|
|
6441
|
-
* { theme: 'dark' }
|
|
6442
|
-
* )
|
|
6443
|
-
*
|
|
6444
|
-
* console.log(tokens['color.background'].$value) // '#1a1a1a'
|
|
6445
|
-
* ```
|
|
6446
|
-
*/
|
|
6447
|
-
async resolveTokens(resolver, modifierInputs = {}) {
|
|
6448
|
-
const { tokens } = await this.pipeline.resolve(resolver, modifierInputs);
|
|
6449
|
-
return stripInternalTokenMetadata(tokens);
|
|
6450
|
-
}
|
|
6451
|
-
/**
|
|
6452
|
-
* Resolves tokens for all permutations defined in the resolver
|
|
6453
|
-
*
|
|
6454
|
-
* Auto-discovers all possible permutations from the resolver's modifier
|
|
6455
|
-
* definitions and resolves tokens for each one. Useful for generating
|
|
6456
|
-
* comprehensive token sets or validating all theme variations.
|
|
6457
|
-
*
|
|
6458
|
-
* @param resolver - Resolver configuration (file path or inline object)
|
|
6459
|
-
* @returns Array of resolved token sets with their modifier inputs
|
|
6460
|
-
* @throws {FileOperationError} If resolver file cannot be read
|
|
6461
|
-
* @throws {TokenReferenceError} If token references cannot be resolved (when validate is enabled)
|
|
6462
|
-
*
|
|
6463
|
-
* @example
|
|
6464
|
-
* ```typescript
|
|
6465
|
-
* const permutations = await dispersa.resolveAllPermutations(
|
|
6466
|
-
* './tokens.resolver.json'
|
|
6467
|
-
* )
|
|
6468
|
-
*
|
|
6469
|
-
* permutations.forEach(({ tokens, modifierInputs }) => {
|
|
6470
|
-
* console.log(`Theme: ${modifierInputs.theme}`)
|
|
6471
|
-
* console.log(`Tokens: ${Object.keys(tokens).length}`)
|
|
6472
|
-
* })
|
|
6473
|
-
* ```
|
|
6474
|
-
*/
|
|
6475
|
-
async resolveAllPermutations(resolver) {
|
|
6476
|
-
const permutations = await this.pipeline.resolveAllPermutations(resolver);
|
|
6477
|
-
return permutations.map(({ tokens, modifierInputs }) => ({
|
|
6478
|
-
tokens: stripInternalTokenMetadata(tokens),
|
|
6479
|
-
modifierInputs
|
|
6480
|
-
}));
|
|
6839
|
+
}
|
|
6840
|
+
async function resolvePipeline(pipeline, resolver, modifierInputs) {
|
|
6841
|
+
const { tokens } = await pipeline.resolve(resolver, modifierInputs);
|
|
6842
|
+
return stripInternalTokenMetadata(tokens);
|
|
6843
|
+
}
|
|
6844
|
+
async function build(config) {
|
|
6845
|
+
try {
|
|
6846
|
+
return await buildOrThrow(config);
|
|
6847
|
+
} catch (error) {
|
|
6848
|
+
return {
|
|
6849
|
+
success: false,
|
|
6850
|
+
outputs: [],
|
|
6851
|
+
errors: [toBuildError(error)]
|
|
6852
|
+
};
|
|
6481
6853
|
}
|
|
6482
|
-
|
|
6483
|
-
|
|
6484
|
-
|
|
6485
|
-
|
|
6486
|
-
|
|
6487
|
-
|
|
6488
|
-
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
|
|
6502
|
-
|
|
6503
|
-
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
moduleName: options?.moduleName ?? "Tokens",
|
|
6514
|
-
includeValues: true
|
|
6515
|
-
});
|
|
6854
|
+
}
|
|
6855
|
+
async function buildOrThrow(config) {
|
|
6856
|
+
const validator = createValidator();
|
|
6857
|
+
validateBuildConfig(validator, config);
|
|
6858
|
+
const { resolver, buildPath } = resolveConfig(config);
|
|
6859
|
+
const pipeline = createPipeline({ validation: config.validation });
|
|
6860
|
+
const outputProcessor = createOutputProcessor();
|
|
6861
|
+
const orchestrator = createOrchestrator(pipeline, outputProcessor);
|
|
6862
|
+
return orchestrator.build(resolver, buildPath, config);
|
|
6863
|
+
}
|
|
6864
|
+
async function buildPermutation(config, modifierInputs = {}) {
|
|
6865
|
+
return build({
|
|
6866
|
+
...config,
|
|
6867
|
+
permutations: [modifierInputs]
|
|
6868
|
+
});
|
|
6869
|
+
}
|
|
6870
|
+
async function resolveTokens(resolver, modifierInputs = {}, validation) {
|
|
6871
|
+
const pipeline = createPipeline({ validation });
|
|
6872
|
+
return resolvePipeline(pipeline, resolver, modifierInputs);
|
|
6873
|
+
}
|
|
6874
|
+
async function lint(options) {
|
|
6875
|
+
const { resolver, modifierInputs = {}, validation, ...lintConfig } = options;
|
|
6876
|
+
const pipeline = createPipeline({ validation });
|
|
6877
|
+
const tokens = await resolvePipeline(pipeline, resolver, modifierInputs);
|
|
6878
|
+
const runner = new LintRunner({
|
|
6879
|
+
...lintConfig,
|
|
6880
|
+
failOnError: lintConfig.failOnError ?? true
|
|
6881
|
+
});
|
|
6882
|
+
const result = await runner.run(tokens);
|
|
6883
|
+
if (result.errorCount > 0 && lintConfig.failOnError !== false) {
|
|
6884
|
+
throw new exports.LintError(result.issues);
|
|
6516
6885
|
}
|
|
6517
|
-
|
|
6886
|
+
return result;
|
|
6887
|
+
}
|
|
6888
|
+
async function resolveAllPermutations(resolver) {
|
|
6889
|
+
const pipeline = createPipeline();
|
|
6890
|
+
const permutations = await pipeline.resolveAllPermutations(resolver);
|
|
6891
|
+
return permutations.map(({ tokens, modifierInputs }) => ({
|
|
6892
|
+
tokens: stripInternalTokenMetadata(tokens),
|
|
6893
|
+
modifierInputs
|
|
6894
|
+
}));
|
|
6895
|
+
}
|
|
6896
|
+
async function generateTypes(tokens, fileName, options) {
|
|
6897
|
+
const typeWriter = new TypeWriter();
|
|
6898
|
+
await typeWriter.write(tokens, {
|
|
6899
|
+
fileName,
|
|
6900
|
+
moduleName: options?.moduleName ?? "Tokens",
|
|
6901
|
+
includeValues: true
|
|
6902
|
+
});
|
|
6903
|
+
}
|
|
6518
6904
|
|
|
6519
6905
|
// src/tokens/types.ts
|
|
6520
6906
|
function isColorToken(token) {
|
|
@@ -6541,6 +6927,17 @@ function isTransitionToken(token) {
|
|
|
6541
6927
|
function isGradientToken(token) {
|
|
6542
6928
|
return token.$type === "gradient";
|
|
6543
6929
|
}
|
|
6930
|
+
function nameKebabCase() {
|
|
6931
|
+
return {
|
|
6932
|
+
transform: (token) => {
|
|
6933
|
+
const name = changeCase.kebabCase(token.path.join(" "));
|
|
6934
|
+
return {
|
|
6935
|
+
...token,
|
|
6936
|
+
name
|
|
6937
|
+
};
|
|
6938
|
+
}
|
|
6939
|
+
};
|
|
6940
|
+
}
|
|
6544
6941
|
function isColorObject(value) {
|
|
6545
6942
|
return typeof value === "object" && value !== null && "colorSpace" in value && "components" in value;
|
|
6546
6943
|
}
|
|
@@ -6618,6 +7015,7 @@ function durationObjectToString(duration) {
|
|
|
6618
7015
|
init_errors();
|
|
6619
7016
|
init_token_utils();
|
|
6620
7017
|
init_utils();
|
|
7018
|
+
init_metadata();
|
|
6621
7019
|
var toSRGB = culori.converter("rgb");
|
|
6622
7020
|
var toP3 = culori.converter("p3");
|
|
6623
7021
|
var KOTLIN_KEYWORDS = /* @__PURE__ */ new Set([
|
|
@@ -6668,9 +7066,6 @@ function resolveColorFormat(format) {
|
|
|
6668
7066
|
function escapeKotlinString(str) {
|
|
6669
7067
|
return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\$/g, "\\$");
|
|
6670
7068
|
}
|
|
6671
|
-
function escapeKDoc(str) {
|
|
6672
|
-
return str.replace(/\*\//g, "* /").replace(/\r?\n/g, " ").trim();
|
|
6673
|
-
}
|
|
6674
7069
|
function formatKotlinNumber(value) {
|
|
6675
7070
|
return Number.isInteger(value) ? `${value}.0` : String(value);
|
|
6676
7071
|
}
|
|
@@ -6802,8 +7197,13 @@ var AndroidRenderer = class {
|
|
|
6802
7197
|
const kotlinName = this.buildFlatKotlinName(token);
|
|
6803
7198
|
const kotlinValue = this.formatKotlinValue(token, options, baseDepth + 1);
|
|
6804
7199
|
const annotation = this.typeAnnotationSuffix(token);
|
|
6805
|
-
|
|
6806
|
-
|
|
7200
|
+
const descriptionComment = buildTokenDescriptionComment(token, "kotlin");
|
|
7201
|
+
if (descriptionComment) {
|
|
7202
|
+
lines.push(`${valIndent}${descriptionComment}`);
|
|
7203
|
+
}
|
|
7204
|
+
const deprecation = buildKotlinDeprecationAnnotation(token);
|
|
7205
|
+
if (deprecation) {
|
|
7206
|
+
lines.push(`${valIndent}${deprecation}`);
|
|
6807
7207
|
}
|
|
6808
7208
|
lines.push(
|
|
6809
7209
|
`${valIndent}${options.visPrefix}val ${kotlinName}${annotation} = ${kotlinValue}`
|
|
@@ -6839,8 +7239,13 @@ var AndroidRenderer = class {
|
|
|
6839
7239
|
const kotlinName = toSafeIdentifier(key, KOTLIN_KEYWORDS, false);
|
|
6840
7240
|
const kotlinValue = this.formatKotlinValue(token, options, depth);
|
|
6841
7241
|
const annotation = this.typeAnnotationSuffix(token);
|
|
6842
|
-
|
|
6843
|
-
|
|
7242
|
+
const descriptionComment = buildTokenDescriptionComment(token, "kotlin");
|
|
7243
|
+
if (descriptionComment) {
|
|
7244
|
+
lines.push(`${pad}${descriptionComment}`);
|
|
7245
|
+
}
|
|
7246
|
+
const deprecation = buildKotlinDeprecationAnnotation(token);
|
|
7247
|
+
if (deprecation) {
|
|
7248
|
+
lines.push(`${pad}${deprecation}`);
|
|
6844
7249
|
}
|
|
6845
7250
|
lines.push(`${pad}${options.visPrefix}val ${kotlinName}${annotation} = ${kotlinValue}`);
|
|
6846
7251
|
}
|
|
@@ -7617,10 +8022,8 @@ function stableInputsKey(modifierInputs) {
|
|
|
7617
8022
|
|
|
7618
8023
|
// src/renderers/css.ts
|
|
7619
8024
|
init_utils();
|
|
8025
|
+
init_metadata();
|
|
7620
8026
|
var CssRenderer = class _CssRenderer {
|
|
7621
|
-
sanitizeCssCommentText(text) {
|
|
7622
|
-
return text.replace(/\*\//g, "*\\/").replace(/\r?\n/g, " ").trim();
|
|
7623
|
-
}
|
|
7624
8027
|
async format(context, options) {
|
|
7625
8028
|
const opts = {
|
|
7626
8029
|
preset: options?.preset ?? "bundle",
|
|
@@ -7700,12 +8103,13 @@ var CssRenderer = class _CssRenderer {
|
|
|
7700
8103
|
}
|
|
7701
8104
|
pushTokenLines(lines, token, tokens, referenceTokens, preserveReferences, indent, newline, space) {
|
|
7702
8105
|
const entries = this.buildCssEntries(token, tokens, referenceTokens, preserveReferences);
|
|
7703
|
-
|
|
7704
|
-
|
|
7705
|
-
lines.push(`${indent}
|
|
8106
|
+
const deprecationComment = buildTokenDeprecationComment(token, "css");
|
|
8107
|
+
if (deprecationComment) {
|
|
8108
|
+
lines.push(`${indent}${deprecationComment}${newline}`);
|
|
7706
8109
|
}
|
|
7707
|
-
|
|
7708
|
-
|
|
8110
|
+
const descriptionComment = buildTokenDescriptionComment(token, "css");
|
|
8111
|
+
if (descriptionComment) {
|
|
8112
|
+
lines.push(`${indent}${descriptionComment}${newline}`);
|
|
7709
8113
|
}
|
|
7710
8114
|
for (const entry of entries) {
|
|
7711
8115
|
lines.push(`${indent}--${entry.name}:${space}${entry.value};${newline}`);
|
|
@@ -8345,6 +8749,7 @@ function cssRenderer() {
|
|
|
8345
8749
|
|
|
8346
8750
|
// src/renderers/ios.ts
|
|
8347
8751
|
init_utils();
|
|
8752
|
+
init_metadata();
|
|
8348
8753
|
var toSRGB2 = culori.converter("rgb");
|
|
8349
8754
|
var toP32 = culori.converter("p3");
|
|
8350
8755
|
var SWIFT_TYPE_GROUP_MAP = {
|
|
@@ -8488,9 +8893,13 @@ var IosRenderer = class {
|
|
|
8488
8893
|
const swiftValue = this.formatSwiftValue(token, options);
|
|
8489
8894
|
const typeAnnotation = this.getTypeAnnotation(token);
|
|
8490
8895
|
const annotation = typeAnnotation ? `: ${typeAnnotation}` : "";
|
|
8491
|
-
const docComment =
|
|
8896
|
+
const docComment = buildTokenDescriptionComment(token, "swift");
|
|
8492
8897
|
if (docComment) {
|
|
8493
|
-
lines.push(docComment);
|
|
8898
|
+
lines.push(`${indent}${docComment}`);
|
|
8899
|
+
}
|
|
8900
|
+
const deprecationAttr = buildSwiftDeprecationAttribute(token);
|
|
8901
|
+
if (deprecationAttr) {
|
|
8902
|
+
lines.push(`${indent}${deprecationAttr}`);
|
|
8494
8903
|
}
|
|
8495
8904
|
lines.push(`${indent}${access3} ${staticPrefix}${swiftName}${annotation} = ${swiftValue}`);
|
|
8496
8905
|
}
|
|
@@ -8505,15 +8914,6 @@ var IosRenderer = class {
|
|
|
8505
8914
|
}
|
|
8506
8915
|
return Array.from(imports).sort();
|
|
8507
8916
|
}
|
|
8508
|
-
/**
|
|
8509
|
-
* Builds a `///` doc comment from a token's `$description`, if present.
|
|
8510
|
-
*/
|
|
8511
|
-
buildDocComment(token, indent) {
|
|
8512
|
-
if (!token.$description) {
|
|
8513
|
-
return void 0;
|
|
8514
|
-
}
|
|
8515
|
-
return `${indent}/// ${token.$description}`;
|
|
8516
|
-
}
|
|
8517
8917
|
/**
|
|
8518
8918
|
* Builds a qualified Swift name from a token's path, preserving parent
|
|
8519
8919
|
* hierarchy segments to avoid duplicate identifiers.
|
|
@@ -8904,6 +9304,7 @@ function iosRenderer() {
|
|
|
8904
9304
|
// src/renderers/js-module.ts
|
|
8905
9305
|
init_utils();
|
|
8906
9306
|
init_token_utils();
|
|
9307
|
+
init_metadata();
|
|
8907
9308
|
var JsModuleRenderer = class {
|
|
8908
9309
|
async format(context, options) {
|
|
8909
9310
|
const opts = {
|
|
@@ -8941,17 +9342,10 @@ var JsModuleRenderer = class {
|
|
|
8941
9342
|
return outputTree(files);
|
|
8942
9343
|
}
|
|
8943
9344
|
async formatTokens(tokens, options) {
|
|
8944
|
-
const opts = {
|
|
8945
|
-
preset: options.preset ?? "standalone",
|
|
8946
|
-
structure: options.structure ?? "nested",
|
|
8947
|
-
minify: options.minify ?? false,
|
|
8948
|
-
moduleName: options.moduleName ?? "tokens",
|
|
8949
|
-
generateHelper: options.generateHelper ?? false
|
|
8950
|
-
};
|
|
8951
9345
|
const lines = [];
|
|
8952
|
-
lines.push(...this.formatAsObject(tokens,
|
|
9346
|
+
lines.push(...this.formatAsObject(tokens, options));
|
|
8953
9347
|
const code = lines.join("\n");
|
|
8954
|
-
if (
|
|
9348
|
+
if (options.minify) {
|
|
8955
9349
|
return code;
|
|
8956
9350
|
}
|
|
8957
9351
|
return await prettier__default.default.format(code, {
|
|
@@ -8964,20 +9358,53 @@ var JsModuleRenderer = class {
|
|
|
8964
9358
|
trailingComma: "es5"
|
|
8965
9359
|
});
|
|
8966
9360
|
}
|
|
8967
|
-
/**
|
|
8968
|
-
* Format as default export object
|
|
8969
|
-
*/
|
|
8970
9361
|
formatAsObject(tokens, options) {
|
|
8971
9362
|
const lines = [];
|
|
8972
|
-
const
|
|
9363
|
+
const tokenMap = this.buildTokenMap(tokens);
|
|
8973
9364
|
const varName = options.moduleName !== "" ? options.moduleName : "tokens";
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
|
|
9365
|
+
if (options.structure === "flat") {
|
|
9366
|
+
lines.push(`const ${varName} = {`);
|
|
9367
|
+
this.addFlatProperties(lines, tokens, 1);
|
|
9368
|
+
lines.push("}");
|
|
9369
|
+
} else {
|
|
9370
|
+
lines.push(`const ${varName} = {`);
|
|
9371
|
+
const tokenObj = this.tokensToPlainObject(tokens, "nested");
|
|
9372
|
+
this.addNestedProperties(lines, tokenObj, tokenMap, 1);
|
|
9373
|
+
lines.push("}");
|
|
9374
|
+
}
|
|
8977
9375
|
lines.push("");
|
|
8978
9376
|
lines.push(`export default ${varName}`);
|
|
8979
9377
|
return lines;
|
|
8980
9378
|
}
|
|
9379
|
+
buildTokenMap(tokens) {
|
|
9380
|
+
const map = /* @__PURE__ */ new Map();
|
|
9381
|
+
for (const [name, token] of Object.entries(tokens)) {
|
|
9382
|
+
map.set(name, token);
|
|
9383
|
+
}
|
|
9384
|
+
return map;
|
|
9385
|
+
}
|
|
9386
|
+
addFlatProperties(lines, tokens, indent) {
|
|
9387
|
+
const indentStr2 = " ".repeat(indent);
|
|
9388
|
+
const sortedEntries = getSortedTokenEntries(tokens);
|
|
9389
|
+
for (let i = 0; i < sortedEntries.length; i++) {
|
|
9390
|
+
const [name, token] = sortedEntries[i];
|
|
9391
|
+
const isLast = i === sortedEntries.length - 1;
|
|
9392
|
+
this.pushTokenComments(lines, token, indentStr2);
|
|
9393
|
+
lines.push(
|
|
9394
|
+
`${indentStr2}${this.quoteKey(name)}: ${JSON.stringify(token.$value)}${isLast ? "" : ","}`
|
|
9395
|
+
);
|
|
9396
|
+
}
|
|
9397
|
+
}
|
|
9398
|
+
pushTokenComments(lines, token, indent) {
|
|
9399
|
+
const deprecationComment = buildTokenDeprecationComment(token, "js");
|
|
9400
|
+
if (deprecationComment) {
|
|
9401
|
+
lines.push(`${indent}${deprecationComment}`);
|
|
9402
|
+
}
|
|
9403
|
+
const descriptionComment = buildTokenDescriptionComment(token, "js");
|
|
9404
|
+
if (descriptionComment) {
|
|
9405
|
+
lines.push(`${indent}${descriptionComment}`);
|
|
9406
|
+
}
|
|
9407
|
+
}
|
|
8981
9408
|
tokensToPlainObject(tokens, structure) {
|
|
8982
9409
|
if (structure === "nested") {
|
|
8983
9410
|
return buildNestedTokenObject(tokens, (token) => token.$value);
|
|
@@ -8988,7 +9415,7 @@ var JsModuleRenderer = class {
|
|
|
8988
9415
|
}
|
|
8989
9416
|
return result;
|
|
8990
9417
|
}
|
|
8991
|
-
|
|
9418
|
+
addNestedProperties(lines, obj, tokenMap, indent) {
|
|
8992
9419
|
const indentStr2 = " ".repeat(indent);
|
|
8993
9420
|
const entries = Object.entries(obj).sort(([keyA], [keyB]) => keyA.localeCompare(keyB));
|
|
8994
9421
|
for (let i = 0; i < entries.length; i++) {
|
|
@@ -9000,19 +9427,20 @@ var JsModuleRenderer = class {
|
|
|
9000
9427
|
const isLast = i === entries.length - 1;
|
|
9001
9428
|
const isNestedObject = typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9002
9429
|
if (!isNestedObject) {
|
|
9430
|
+
const token = tokenMap.get(key);
|
|
9431
|
+
if (token) {
|
|
9432
|
+
this.pushTokenComments(lines, token, indentStr2);
|
|
9433
|
+
}
|
|
9003
9434
|
lines.push(
|
|
9004
9435
|
`${indentStr2}${this.quoteKey(key)}: ${JSON.stringify(value)}${isLast ? "" : ","}`
|
|
9005
9436
|
);
|
|
9006
9437
|
continue;
|
|
9007
9438
|
}
|
|
9008
9439
|
lines.push(`${indentStr2}${this.quoteKey(key)}: {`);
|
|
9009
|
-
this.
|
|
9440
|
+
this.addNestedProperties(lines, value, tokenMap, indent + 1);
|
|
9010
9441
|
lines.push(`${indentStr2}}${isLast ? "" : ","}`);
|
|
9011
9442
|
}
|
|
9012
9443
|
}
|
|
9013
|
-
/**
|
|
9014
|
-
* Quote key if necessary
|
|
9015
|
-
*/
|
|
9016
9444
|
quoteKey(key) {
|
|
9017
9445
|
if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key)) {
|
|
9018
9446
|
return key;
|
|
@@ -9248,6 +9676,7 @@ function resolveOptions(options) {
|
|
|
9248
9676
|
|
|
9249
9677
|
// src/renderers/tailwind.ts
|
|
9250
9678
|
init_utils();
|
|
9679
|
+
init_metadata();
|
|
9251
9680
|
var TAILWIND_NAMESPACE_MAP = {
|
|
9252
9681
|
color: "color",
|
|
9253
9682
|
dimension: "spacing",
|
|
@@ -9301,6 +9730,14 @@ var TailwindRenderer = class {
|
|
|
9301
9730
|
for (const [, token] of getSortedTokenEntries(tokens)) {
|
|
9302
9731
|
const varName = this.buildVariableName(token);
|
|
9303
9732
|
const varValue = this.formatValue(token);
|
|
9733
|
+
const deprecationComment = buildTokenDeprecationComment(token, "tailwind");
|
|
9734
|
+
if (deprecationComment) {
|
|
9735
|
+
lines.push(`${indent}${deprecationComment}${newline}`);
|
|
9736
|
+
}
|
|
9737
|
+
const descriptionComment = buildTokenDescriptionComment(token, "tailwind");
|
|
9738
|
+
if (descriptionComment) {
|
|
9739
|
+
lines.push(`${indent}${descriptionComment}${newline}`);
|
|
9740
|
+
}
|
|
9304
9741
|
lines.push(`${indent}--${varName}:${space}${varValue};${newline}`);
|
|
9305
9742
|
}
|
|
9306
9743
|
lines.push(`}${newline}`);
|
|
@@ -9327,6 +9764,14 @@ var TailwindRenderer = class {
|
|
|
9327
9764
|
for (const [, token] of getSortedTokenEntries(tokens)) {
|
|
9328
9765
|
const varName = this.buildVariableName(token);
|
|
9329
9766
|
const varValue = this.formatValue(token);
|
|
9767
|
+
const deprecationComment = buildTokenDeprecationComment(token, "tailwind");
|
|
9768
|
+
if (deprecationComment) {
|
|
9769
|
+
lines.push(`${tokenIndent}${deprecationComment}${newline}`);
|
|
9770
|
+
}
|
|
9771
|
+
const descriptionComment = buildTokenDescriptionComment(token, "tailwind");
|
|
9772
|
+
if (descriptionComment) {
|
|
9773
|
+
lines.push(`${tokenIndent}${descriptionComment}${newline}`);
|
|
9774
|
+
}
|
|
9330
9775
|
lines.push(`${tokenIndent}--${varName}:${space}${varValue};${newline}`);
|
|
9331
9776
|
}
|
|
9332
9777
|
if (hasMediaQuery) {
|
|
@@ -9487,7 +9932,7 @@ function css(config) {
|
|
|
9487
9932
|
file,
|
|
9488
9933
|
renderer: cssRenderer(),
|
|
9489
9934
|
options: { preset, ...rendererOptions },
|
|
9490
|
-
transforms,
|
|
9935
|
+
transforms: [nameKebabCase(), ...transforms ?? []],
|
|
9491
9936
|
filters,
|
|
9492
9937
|
hooks
|
|
9493
9938
|
};
|
|
@@ -9599,16 +10044,26 @@ init_errors();
|
|
|
9599
10044
|
* This source code is licensed under the MIT license found in the
|
|
9600
10045
|
* LICENSE file in the root directory of this source tree.
|
|
9601
10046
|
*/
|
|
10047
|
+
/**
|
|
10048
|
+
* @license MIT
|
|
10049
|
+
* Copyright (c) 2025-present Dispersa
|
|
10050
|
+
*
|
|
10051
|
+
* This source code is licensed under the MIT license found in the
|
|
10052
|
+
* LICENSE file in the root directory of this source tree.
|
|
10053
|
+
*/
|
|
9602
10054
|
/**
|
|
9603
10055
|
* @license
|
|
9604
10056
|
* Copyright (c) 2025 Dispersa Contributors
|
|
9605
10057
|
* SPDX-License-Identifier: MIT
|
|
9606
10058
|
*/
|
|
9607
10059
|
|
|
9608
|
-
exports.Dispersa = Dispersa;
|
|
9609
10060
|
exports.android = android;
|
|
10061
|
+
exports.build = build;
|
|
10062
|
+
exports.buildOrThrow = buildOrThrow;
|
|
10063
|
+
exports.buildPermutation = buildPermutation;
|
|
9610
10064
|
exports.css = css;
|
|
9611
10065
|
exports.defineRenderer = defineRenderer;
|
|
10066
|
+
exports.generateTypes = generateTypes;
|
|
9612
10067
|
exports.ios = ios;
|
|
9613
10068
|
exports.isBorderToken = isBorderToken;
|
|
9614
10069
|
exports.isColorToken = isColorToken;
|
|
@@ -9621,7 +10076,10 @@ exports.isTransitionToken = isTransitionToken;
|
|
|
9621
10076
|
exports.isTypographyToken = isTypographyToken;
|
|
9622
10077
|
exports.js = js;
|
|
9623
10078
|
exports.json = json;
|
|
10079
|
+
exports.lint = lint;
|
|
9624
10080
|
exports.outputTree = outputTree;
|
|
10081
|
+
exports.resolveAllPermutations = resolveAllPermutations;
|
|
10082
|
+
exports.resolveTokens = resolveTokens;
|
|
9625
10083
|
exports.tailwind = tailwind;
|
|
9626
10084
|
//# sourceMappingURL=index.cjs.map
|
|
9627
10085
|
//# sourceMappingURL=index.cjs.map
|