dispersa 0.4.3 → 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 +65 -30
- package/dist/android-CRDfSB3_.d.cts +126 -0
- package/dist/android-DANJjjPO.d.ts +126 -0
- package/dist/builders.cjs +206 -62
- package/dist/builders.cjs.map +1 -1
- package/dist/builders.d.cts +12 -11
- package/dist/builders.d.ts +12 -11
- package/dist/builders.js +206 -62
- 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 +799 -353
- 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 +793 -353
- 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.d.cts +2 -2
- package/dist/transforms.d.ts +2 -2
- 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,6 +5,9 @@ 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');
|
|
9
12
|
var changeCase = require('change-case');
|
|
10
13
|
var culori = require('culori');
|
|
@@ -33,6 +36,7 @@ function _interopNamespace(e) {
|
|
|
33
36
|
var Ajv__default = /*#__PURE__*/_interopDefault(Ajv);
|
|
34
37
|
var addFormats__default = /*#__PURE__*/_interopDefault(addFormats);
|
|
35
38
|
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
39
|
+
var process2__default = /*#__PURE__*/_interopDefault(process2);
|
|
36
40
|
var prettier__default = /*#__PURE__*/_interopDefault(prettier);
|
|
37
41
|
|
|
38
42
|
var __defProp = Object.defineProperty;
|
|
@@ -46,7 +50,7 @@ var __export = (target, all) => {
|
|
|
46
50
|
};
|
|
47
51
|
|
|
48
52
|
// src/shared/errors/index.ts
|
|
49
|
-
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;
|
|
50
54
|
var init_errors = __esm({
|
|
51
55
|
"src/shared/errors/index.ts"() {
|
|
52
56
|
exports.DispersaError = class extends Error {
|
|
@@ -129,23 +133,19 @@ var init_errors = __esm({
|
|
|
129
133
|
this.name = "ModifierError";
|
|
130
134
|
}
|
|
131
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
|
+
};
|
|
132
145
|
}
|
|
133
146
|
});
|
|
134
147
|
|
|
135
148
|
// src/shared/utils/token-utils.ts
|
|
136
|
-
function formatDeprecationMessage(token, description = "", format = "bracket") {
|
|
137
|
-
if (token.$deprecated == null || token.$deprecated === false) {
|
|
138
|
-
return description;
|
|
139
|
-
}
|
|
140
|
-
const deprecationMsg = typeof token.$deprecated === "string" ? token.$deprecated : "";
|
|
141
|
-
if (format === "comment") {
|
|
142
|
-
const msg2 = deprecationMsg ? ` ${deprecationMsg}` : "";
|
|
143
|
-
return `DEPRECATED${msg2}`;
|
|
144
|
-
}
|
|
145
|
-
const msg = deprecationMsg ? `: ${deprecationMsg}` : "";
|
|
146
|
-
const prefix = `[DEPRECATED${msg}]`;
|
|
147
|
-
return description ? `${prefix} ${description}` : prefix;
|
|
148
|
-
}
|
|
149
149
|
function stripInternalTokenMetadata(tokens) {
|
|
150
150
|
const cleaned = {};
|
|
151
151
|
for (const [name, token] of Object.entries(tokens)) {
|
|
@@ -2499,7 +2499,7 @@ var init_schemas = __esm({
|
|
|
2499
2499
|
});
|
|
2500
2500
|
|
|
2501
2501
|
// src/validation/config-schemas.ts
|
|
2502
|
-
var resolverSchemaRef, basePluginProperties, commonRendererOptionsProperties, transformPluginSchema, rendererPluginSchema, filterPluginSchema, preprocessorPluginSchema, outputConfigSchema, dispersaOptionsSchema, buildConfigSchema;
|
|
2502
|
+
var resolverSchemaRef, basePluginProperties, commonRendererOptionsProperties, transformPluginSchema, rendererPluginSchema, filterPluginSchema, preprocessorPluginSchema, lintConfigSchema, outputConfigSchema, dispersaOptionsSchema, buildConfigSchema;
|
|
2503
2503
|
var init_config_schemas = __esm({
|
|
2504
2504
|
"src/validation/config-schemas.ts"() {
|
|
2505
2505
|
init_schemas();
|
|
@@ -2650,6 +2650,42 @@ var init_config_schemas = __esm({
|
|
|
2650
2650
|
}
|
|
2651
2651
|
}
|
|
2652
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
|
+
};
|
|
2653
2689
|
outputConfigSchema = {
|
|
2654
2690
|
$schema: "http://json-schema.org/draft-07/schema#",
|
|
2655
2691
|
type: "object",
|
|
@@ -2767,10 +2803,20 @@ var init_config_schemas = __esm({
|
|
|
2767
2803
|
description: "Resolver configuration - file path or ResolverDocument object"
|
|
2768
2804
|
},
|
|
2769
2805
|
buildPath: { type: "string" },
|
|
2806
|
+
validation: {
|
|
2807
|
+
type: "object",
|
|
2808
|
+
properties: {
|
|
2809
|
+
mode: { type: "string", enum: ["error", "warn", "off"] }
|
|
2810
|
+
}
|
|
2811
|
+
},
|
|
2770
2812
|
hooks: {
|
|
2771
2813
|
type: "object",
|
|
2772
2814
|
description: "Global build lifecycle hooks (functions, validated at runtime)",
|
|
2773
2815
|
additionalProperties: true
|
|
2816
|
+
},
|
|
2817
|
+
lint: {
|
|
2818
|
+
...lintConfigSchema,
|
|
2819
|
+
description: "Linting configuration"
|
|
2774
2820
|
}
|
|
2775
2821
|
},
|
|
2776
2822
|
additionalProperties: false
|
|
@@ -3530,6 +3576,94 @@ var init_utils = __esm({
|
|
|
3530
3576
|
}
|
|
3531
3577
|
});
|
|
3532
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
|
+
|
|
3533
3667
|
// src/renderers/bundlers/js.ts
|
|
3534
3668
|
var js_exports = {};
|
|
3535
3669
|
__export(js_exports, {
|
|
@@ -3634,7 +3768,7 @@ async function bundleAsJsModule(bundleData, resolver, options, formatTokens) {
|
|
|
3634
3768
|
}
|
|
3635
3769
|
const metadata = buildMetadata(resolver);
|
|
3636
3770
|
const jsBlocks = [];
|
|
3637
|
-
for (const { tokens, modifierInputs } of bundleData) {
|
|
3771
|
+
for (const { tokens, modifierInputs, isBase } of bundleData) {
|
|
3638
3772
|
const cleanTokens = stripInternalMetadata(tokens);
|
|
3639
3773
|
const key = buildStableDashKey({
|
|
3640
3774
|
modifierInputs,
|
|
@@ -3642,10 +3776,30 @@ async function bundleAsJsModule(bundleData, resolver, options, formatTokens) {
|
|
|
3642
3776
|
defaults: metadata.defaults
|
|
3643
3777
|
});
|
|
3644
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
|
+
}
|
|
3645
3787
|
const formattedJs = await formatTokens(cleanTokens);
|
|
3646
3788
|
const tokenObject = extractObjectFromJsModule(formattedJs);
|
|
3647
3789
|
const indentedObject = tokenObject.replace(/\n/g, "\n ");
|
|
3648
|
-
|
|
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}
|
|
3649
3803
|
${JSON.stringify(camelKey)}: ${indentedObject}`);
|
|
3650
3804
|
}
|
|
3651
3805
|
return assembleJsBundle(metadata, jsBlocks, options?.generateHelper ?? false);
|
|
@@ -3653,6 +3807,7 @@ async function bundleAsJsModule(bundleData, resolver, options, formatTokens) {
|
|
|
3653
3807
|
var init_js = __esm({
|
|
3654
3808
|
"src/renderers/bundlers/js.ts"() {
|
|
3655
3809
|
init_errors();
|
|
3810
|
+
init_metadata();
|
|
3656
3811
|
init_utils();
|
|
3657
3812
|
}
|
|
3658
3813
|
});
|
|
@@ -4022,7 +4177,8 @@ var BuildOrchestrator = class {
|
|
|
4022
4177
|
resolver,
|
|
4023
4178
|
config.transforms,
|
|
4024
4179
|
config.preprocessors,
|
|
4025
|
-
config.filters
|
|
4180
|
+
config.filters,
|
|
4181
|
+
config.lint
|
|
4026
4182
|
);
|
|
4027
4183
|
return this.executeBuild(buildPath, config, permutations2, resolver);
|
|
4028
4184
|
}
|
|
@@ -4033,7 +4189,8 @@ var BuildOrchestrator = class {
|
|
|
4033
4189
|
modifierInputs,
|
|
4034
4190
|
config.transforms,
|
|
4035
4191
|
config.preprocessors,
|
|
4036
|
-
config.filters
|
|
4192
|
+
config.filters,
|
|
4193
|
+
config.lint
|
|
4037
4194
|
);
|
|
4038
4195
|
return { tokens, modifierInputs: resolvedInputs };
|
|
4039
4196
|
})
|
|
@@ -4294,7 +4451,358 @@ var OutputProcessor = class {
|
|
|
4294
4451
|
|
|
4295
4452
|
// src/build/pipeline/token-pipeline.ts
|
|
4296
4453
|
init_resolver_loader();
|
|
4297
|
-
|
|
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
|
+
};
|
|
4298
4806
|
|
|
4299
4807
|
// src/shared/constants.ts
|
|
4300
4808
|
var DEFAULT_MAX_ALIAS_DEPTH = 10;
|
|
@@ -5489,6 +5997,10 @@ var ResolutionEngine = class {
|
|
|
5489
5997
|
return typeof obj === "object" && obj !== null && "contexts" in obj && typeof obj.contexts === "object";
|
|
5490
5998
|
}
|
|
5491
5999
|
};
|
|
6000
|
+
|
|
6001
|
+
// src/build/pipeline/token-pipeline.ts
|
|
6002
|
+
init_errors();
|
|
6003
|
+
init_validation_handler();
|
|
5492
6004
|
init_errors();
|
|
5493
6005
|
|
|
5494
6006
|
// src/shared/utils/path-utils.ts
|
|
@@ -5981,6 +6493,8 @@ var TokenPipeline = class {
|
|
|
5981
6493
|
resolverLoader;
|
|
5982
6494
|
tokenParser;
|
|
5983
6495
|
aliasResolver;
|
|
6496
|
+
lintRunner = null;
|
|
6497
|
+
lintConfigCache = null;
|
|
5984
6498
|
constructor(options = {}) {
|
|
5985
6499
|
this.options = options;
|
|
5986
6500
|
this.validationHandler = new ValidationHandler(options.validation);
|
|
@@ -6000,8 +6514,9 @@ var TokenPipeline = class {
|
|
|
6000
6514
|
* 6. Parse and flatten token structure
|
|
6001
6515
|
* 7. Resolve alias references
|
|
6002
6516
|
* 8. Strip $root from token names/paths (DTCG structural mechanism, transparent in output)
|
|
6003
|
-
* 9.
|
|
6004
|
-
* 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
|
|
6005
6520
|
*
|
|
6006
6521
|
* Each stage is explicitly typed to ensure correct order and prevent temporal coupling.
|
|
6007
6522
|
*
|
|
@@ -6010,9 +6525,11 @@ var TokenPipeline = class {
|
|
|
6010
6525
|
* @param transformList - Optional transforms to apply
|
|
6011
6526
|
* @param preprocessorList - Optional preprocessors to apply
|
|
6012
6527
|
* @param filterList - Optional filters to apply before transforms
|
|
6013
|
-
* @
|
|
6528
|
+
* @param lintConfig - Optional lint configuration for this run
|
|
6529
|
+
* @returns Final tokens, resolution engine, and lint result
|
|
6014
6530
|
*/
|
|
6015
|
-
async resolve(resolver, modifierInputs, transformList, preprocessorList, filterList) {
|
|
6531
|
+
async resolve(resolver, modifierInputs, transformList, preprocessorList, filterList, lintConfig) {
|
|
6532
|
+
const effectiveLintConfig = lintConfig ?? this.options.lint;
|
|
6016
6533
|
const stage1 = await this.loadResolver(resolver);
|
|
6017
6534
|
const engine = this.createEngine(stage1);
|
|
6018
6535
|
const result = await this.runPipelineStages(
|
|
@@ -6020,29 +6537,32 @@ var TokenPipeline = class {
|
|
|
6020
6537
|
modifierInputs,
|
|
6021
6538
|
preprocessorList,
|
|
6022
6539
|
filterList,
|
|
6023
|
-
transformList
|
|
6540
|
+
transformList,
|
|
6541
|
+
effectiveLintConfig
|
|
6024
6542
|
);
|
|
6025
6543
|
return {
|
|
6026
6544
|
tokens: result.tokens,
|
|
6027
6545
|
resolutionEngine: result.resolutionEngine,
|
|
6028
|
-
modifierInputs: result.modifierInputs
|
|
6546
|
+
modifierInputs: result.modifierInputs,
|
|
6547
|
+
lintResult: result.lintResult
|
|
6029
6548
|
};
|
|
6030
6549
|
}
|
|
6031
6550
|
/**
|
|
6032
|
-
* Run pipeline stages 3-
|
|
6551
|
+
* Run pipeline stages 3-11 on a pre-created engine
|
|
6033
6552
|
*
|
|
6034
6553
|
* Shared by both `resolve()` (single permutation) and
|
|
6035
6554
|
* `resolveAllPermutations()` (parallel permutations) to keep the
|
|
6036
6555
|
* stage sequence defined in exactly one place.
|
|
6037
6556
|
*/
|
|
6038
|
-
async runPipelineStages(engine, modifierInputs, preprocessorList, filterList, transformList) {
|
|
6557
|
+
async runPipelineStages(engine, modifierInputs, preprocessorList, filterList, transformList, lintConfig) {
|
|
6039
6558
|
const rawTokens = await this.resolveTokens(engine, modifierInputs);
|
|
6040
6559
|
const preprocessed = await this.preprocessTokens(rawTokens, preprocessorList);
|
|
6041
6560
|
const refResolved = await this.resolveReferences(preprocessed);
|
|
6042
6561
|
const flattened = this.flattenTokens(refResolved);
|
|
6043
6562
|
const aliasResolved = this.resolveAliases(flattened);
|
|
6044
6563
|
const rootStripped = this.stripRootTokenNames(aliasResolved);
|
|
6045
|
-
const
|
|
6564
|
+
const linted = await this.runLintStage(rootStripped, lintConfig);
|
|
6565
|
+
const filtered = this.applyFilterStage(linted, filterList);
|
|
6046
6566
|
return this.applyTransformStage(filtered, transformList);
|
|
6047
6567
|
}
|
|
6048
6568
|
/**
|
|
@@ -6155,6 +6675,47 @@ var TokenPipeline = class {
|
|
|
6155
6675
|
}
|
|
6156
6676
|
return { ...stage, aliasResolvedTokens: result };
|
|
6157
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
|
+
*/
|
|
6158
6719
|
applyFilterStage(stage, filterList) {
|
|
6159
6720
|
let tokens = stage.aliasResolvedTokens;
|
|
6160
6721
|
if (filterList !== void 0 && filterList.length > 0) {
|
|
@@ -6163,7 +6724,7 @@ var TokenPipeline = class {
|
|
|
6163
6724
|
return { ...stage, aliasResolvedTokens: tokens };
|
|
6164
6725
|
}
|
|
6165
6726
|
/**
|
|
6166
|
-
* Stage
|
|
6727
|
+
* Stage 11: Apply transforms to the filtered token set
|
|
6167
6728
|
*/
|
|
6168
6729
|
applyTransformStage(stage, transformList) {
|
|
6169
6730
|
let tokens = stage.aliasResolvedTokens;
|
|
@@ -6197,8 +6758,10 @@ var TokenPipeline = class {
|
|
|
6197
6758
|
* @param transformList - Optional transforms to apply
|
|
6198
6759
|
* @param preprocessorList - Optional preprocessors to apply
|
|
6199
6760
|
* @param filterList - Optional filters to apply before transforms
|
|
6761
|
+
* @param lintConfig - Optional lint configuration for this run
|
|
6200
6762
|
*/
|
|
6201
|
-
async resolveAllPermutations(resolver, transformList, preprocessorList, filterList) {
|
|
6763
|
+
async resolveAllPermutations(resolver, transformList, preprocessorList, filterList, lintConfig) {
|
|
6764
|
+
const effectiveLintConfig = lintConfig ?? this.options.lint;
|
|
6202
6765
|
const stage1 = await this.loadResolver(resolver);
|
|
6203
6766
|
const discoveryEngine = this.createEngine(stage1);
|
|
6204
6767
|
const permutationInputs = discoveryEngine.resolutionEngine.generatePermutations();
|
|
@@ -6211,11 +6774,13 @@ var TokenPipeline = class {
|
|
|
6211
6774
|
modifierInputs,
|
|
6212
6775
|
preprocessorList,
|
|
6213
6776
|
filterList,
|
|
6214
|
-
transformList
|
|
6777
|
+
transformList,
|
|
6778
|
+
effectiveLintConfig
|
|
6215
6779
|
);
|
|
6216
6780
|
return {
|
|
6217
6781
|
tokens: result.tokens,
|
|
6218
|
-
modifierInputs: result.modifierInputs
|
|
6782
|
+
modifierInputs: result.modifierInputs,
|
|
6783
|
+
lintResult: result.lintResult
|
|
6219
6784
|
};
|
|
6220
6785
|
})
|
|
6221
6786
|
);
|
|
@@ -6236,286 +6801,106 @@ var TokenPipeline = class {
|
|
|
6236
6801
|
init_errors();
|
|
6237
6802
|
init_token_utils();
|
|
6238
6803
|
init_validator();
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
const errors = this.validator.validateDispersaOptions(options);
|
|
6257
|
-
if (errors.length > 0) {
|
|
6258
|
-
throw new exports.ConfigurationError(
|
|
6259
|
-
`Invalid Dispersa options: ${this.validator.getErrorMessage(errors)}`
|
|
6260
|
-
);
|
|
6261
|
-
}
|
|
6262
|
-
this.pipeline = new TokenPipeline({ validation: options.validation });
|
|
6263
|
-
this.outputProcessor = new OutputProcessor();
|
|
6264
|
-
this.orchestrator = new BuildOrchestrator(this.pipeline, this.outputProcessor);
|
|
6265
|
-
}
|
|
6266
|
-
/**
|
|
6267
|
-
* Builds design tokens from a resolver configuration
|
|
6268
|
-
*
|
|
6269
|
-
* Processes tokens through the resolution pipeline, applies preprocessors,
|
|
6270
|
-
* transforms, and filters, then generates output files in multiple formats
|
|
6271
|
-
* for specified outputs.
|
|
6272
|
-
*
|
|
6273
|
-
* **Runtime Validation:**
|
|
6274
|
-
* This method validates the build configuration
|
|
6275
|
-
* and all output configurations before processing, throwing helpful errors for
|
|
6276
|
-
* invalid inputs.
|
|
6277
|
-
*
|
|
6278
|
-
* **Permutation Handling:**
|
|
6279
|
-
* - If `config.permutations` is provided and non-empty, builds those specific permutations
|
|
6280
|
-
* - If `config.permutations` is undefined or empty, auto-discovers all permutations from resolver
|
|
6281
|
-
*
|
|
6282
|
-
* @param config - Build configuration
|
|
6283
|
-
* @param config.resolver - Resolver configuration (file path or inline object, optional if set in constructor)
|
|
6284
|
-
* @param config.outputs - Array of output configurations (renderers, transforms, filters)
|
|
6285
|
-
* @param config.buildPath - Output directory for generated files (omit for in-memory mode, optional if set in constructor)
|
|
6286
|
-
* @param config.transforms - Global transforms to apply to all tokens
|
|
6287
|
-
* @param config.preprocessors - Global preprocessors to apply before parsing
|
|
6288
|
-
* @param config.permutations - Array of modifier inputs for generating variations
|
|
6289
|
-
* @returns Build result with success status and generated output files
|
|
6290
|
-
* @throws {ConfigurationError} If configuration is invalid
|
|
6291
|
-
* @throws {FileOperationError} If file operations fail
|
|
6292
|
-
*
|
|
6293
|
-
* @example Basic build
|
|
6294
|
-
* ```typescript
|
|
6295
|
-
* const dispersa = new Dispersa({
|
|
6296
|
-
* resolver: './tokens.resolver.json',
|
|
6297
|
-
* buildPath: './output'
|
|
6298
|
-
* })
|
|
6299
|
-
*
|
|
6300
|
-
* const result = await dispersa.build({
|
|
6301
|
-
* outputs: [
|
|
6302
|
-
* css({
|
|
6303
|
-
* name: 'css',
|
|
6304
|
-
* file: 'tokens.css',
|
|
6305
|
-
* preset: 'bundle',
|
|
6306
|
-
* selector: ':root',
|
|
6307
|
-
* transforms: [nameKebabCase()]
|
|
6308
|
-
* })
|
|
6309
|
-
* ]
|
|
6310
|
-
* })
|
|
6311
|
-
* ```
|
|
6312
|
-
*
|
|
6313
|
-
* @example With filters and multiple presets
|
|
6314
|
-
* ```typescript
|
|
6315
|
-
* const result = await dispersa.build({
|
|
6316
|
-
* resolver: './tokens.resolver.json',
|
|
6317
|
-
* outputs: [
|
|
6318
|
-
* css({
|
|
6319
|
-
* name: 'css',
|
|
6320
|
-
* file: 'tokens.css',
|
|
6321
|
-
* preset: 'bundle',
|
|
6322
|
-
* selector: ':root', // All themes in one file
|
|
6323
|
-
* transforms: [nameKebabCase()]
|
|
6324
|
-
* }),
|
|
6325
|
-
* json({
|
|
6326
|
-
* name: 'json',
|
|
6327
|
-
* file: 'tokens-{theme}.json', // Separate file per theme
|
|
6328
|
-
* preset: 'standalone',
|
|
6329
|
-
* structure: 'flat'
|
|
6330
|
-
* })
|
|
6331
|
-
* ],
|
|
6332
|
-
* buildPath: './output',
|
|
6333
|
-
* permutations: [
|
|
6334
|
-
* { theme: 'light' },
|
|
6335
|
-
* { theme: 'dark' }
|
|
6336
|
-
* ]
|
|
6337
|
-
* })
|
|
6338
|
-
* ```
|
|
6339
|
-
*/
|
|
6340
|
-
async build(config) {
|
|
6341
|
-
try {
|
|
6342
|
-
return await this.buildOrThrow(config);
|
|
6343
|
-
} catch (error) {
|
|
6344
|
-
return {
|
|
6345
|
-
success: false,
|
|
6346
|
-
outputs: [],
|
|
6347
|
-
errors: [toBuildError(error)]
|
|
6348
|
-
};
|
|
6349
|
-
}
|
|
6350
|
-
}
|
|
6351
|
-
/**
|
|
6352
|
-
* Builds design tokens and throws on any failure.
|
|
6353
|
-
*
|
|
6354
|
-
* Unlike {@link build}, which catches errors and returns them inside
|
|
6355
|
-
* `BuildResult.errors`, this method propagates the first error as an
|
|
6356
|
-
* exception. Use it when you want fail-fast behavior in CLI or CI workflows.
|
|
6357
|
-
*
|
|
6358
|
-
* @param config - Build configuration specifying resolver, outputs, transforms, etc.
|
|
6359
|
-
* @returns A successful `BuildResult` (never contains errors)
|
|
6360
|
-
* @throws {ConfigurationError} When the build config or resolver is invalid
|
|
6361
|
-
* @throws {DispersaError} When token resolution, transforms, or rendering fails
|
|
6362
|
-
*
|
|
6363
|
-
* @example
|
|
6364
|
-
* ```typescript
|
|
6365
|
-
* try {
|
|
6366
|
-
* const result = await dispersa.buildOrThrow({
|
|
6367
|
-
* resolver: './tokens.resolver.json',
|
|
6368
|
-
* outputs: [css({ name: 'css', file: 'tokens.css' })],
|
|
6369
|
-
* buildPath: './output',
|
|
6370
|
-
* })
|
|
6371
|
-
* } catch (error) {
|
|
6372
|
-
* process.exit(1)
|
|
6373
|
-
* }
|
|
6374
|
-
* ```
|
|
6375
|
-
*/
|
|
6376
|
-
async buildOrThrow(config) {
|
|
6377
|
-
const configErrors = this.validator.validateBuildConfig(config);
|
|
6378
|
-
if (configErrors.length > 0) {
|
|
6379
|
-
throw new exports.ConfigurationError(
|
|
6380
|
-
`Invalid build configuration: ${this.validator.getErrorMessage(configErrors)}`
|
|
6381
|
-
);
|
|
6382
|
-
}
|
|
6383
|
-
for (const output of config.outputs) {
|
|
6384
|
-
const outputErrors = this.validator.validateOutputConfig(output);
|
|
6385
|
-
if (outputErrors.length > 0) {
|
|
6386
|
-
throw new exports.ConfigurationError(
|
|
6387
|
-
`Invalid output '${output.name}': ${this.validator.getErrorMessage(outputErrors)}`
|
|
6388
|
-
);
|
|
6389
|
-
}
|
|
6390
|
-
}
|
|
6391
|
-
const { resolver, buildPath } = this.resolveConfig(config);
|
|
6392
|
-
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");
|
|
6393
6821
|
}
|
|
6394
|
-
|
|
6395
|
-
|
|
6396
|
-
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
|
|
6400
|
-
|
|
6401
|
-
|
|
6402
|
-
* @param config - Build configuration
|
|
6403
|
-
* @param modifierInputs - Modifier values (e.g., `{ theme: 'dark' }`)
|
|
6404
|
-
* @returns Build result (success, outputs, optional errors)
|
|
6405
|
-
*/
|
|
6406
|
-
async buildPermutation(config, modifierInputs = {}) {
|
|
6407
|
-
return await this.build({
|
|
6408
|
-
...config,
|
|
6409
|
-
permutations: [modifierInputs]
|
|
6410
|
-
});
|
|
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
|
+
);
|
|
6411
6830
|
}
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
resolveConfig(config) {
|
|
6416
|
-
const resolver = config.resolver ?? this.options.resolver;
|
|
6417
|
-
const buildPath = config.buildPath ?? this.options.buildPath ?? "";
|
|
6418
|
-
if (!resolver) {
|
|
6831
|
+
for (const output of config.outputs) {
|
|
6832
|
+
const outputErrors = validator.validateOutputConfig(output);
|
|
6833
|
+
if (outputErrors.length > 0) {
|
|
6419
6834
|
throw new exports.ConfigurationError(
|
|
6420
|
-
|
|
6835
|
+
`Invalid output '${output.name}': ${validator.getErrorMessage(outputErrors)}`
|
|
6421
6836
|
);
|
|
6422
6837
|
}
|
|
6423
|
-
return { resolver, buildPath };
|
|
6424
6838
|
}
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
* ```typescript
|
|
6440
|
-
* const tokens = await dispersa.resolveTokens(
|
|
6441
|
-
* './tokens.resolver.json',
|
|
6442
|
-
* { theme: 'dark' }
|
|
6443
|
-
* )
|
|
6444
|
-
*
|
|
6445
|
-
* console.log(tokens['color.background'].$value) // '#1a1a1a'
|
|
6446
|
-
* ```
|
|
6447
|
-
*/
|
|
6448
|
-
async resolveTokens(resolver, modifierInputs = {}) {
|
|
6449
|
-
const { tokens } = await this.pipeline.resolve(resolver, modifierInputs);
|
|
6450
|
-
return stripInternalTokenMetadata(tokens);
|
|
6451
|
-
}
|
|
6452
|
-
/**
|
|
6453
|
-
* Resolves tokens for all permutations defined in the resolver
|
|
6454
|
-
*
|
|
6455
|
-
* Auto-discovers all possible permutations from the resolver's modifier
|
|
6456
|
-
* definitions and resolves tokens for each one. Useful for generating
|
|
6457
|
-
* comprehensive token sets or validating all theme variations.
|
|
6458
|
-
*
|
|
6459
|
-
* @param resolver - Resolver configuration (file path or inline object)
|
|
6460
|
-
* @returns Array of resolved token sets with their modifier inputs
|
|
6461
|
-
* @throws {FileOperationError} If resolver file cannot be read
|
|
6462
|
-
* @throws {TokenReferenceError} If token references cannot be resolved (when validate is enabled)
|
|
6463
|
-
*
|
|
6464
|
-
* @example
|
|
6465
|
-
* ```typescript
|
|
6466
|
-
* const permutations = await dispersa.resolveAllPermutations(
|
|
6467
|
-
* './tokens.resolver.json'
|
|
6468
|
-
* )
|
|
6469
|
-
*
|
|
6470
|
-
* permutations.forEach(({ tokens, modifierInputs }) => {
|
|
6471
|
-
* console.log(`Theme: ${modifierInputs.theme}`)
|
|
6472
|
-
* console.log(`Tokens: ${Object.keys(tokens).length}`)
|
|
6473
|
-
* })
|
|
6474
|
-
* ```
|
|
6475
|
-
*/
|
|
6476
|
-
async resolveAllPermutations(resolver) {
|
|
6477
|
-
const permutations = await this.pipeline.resolveAllPermutations(resolver);
|
|
6478
|
-
return permutations.map(({ tokens, modifierInputs }) => ({
|
|
6479
|
-
tokens: stripInternalTokenMetadata(tokens),
|
|
6480
|
-
modifierInputs
|
|
6481
|
-
}));
|
|
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
|
+
};
|
|
6482
6853
|
}
|
|
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
|
-
|
|
6514
|
-
moduleName: options?.moduleName ?? "Tokens",
|
|
6515
|
-
includeValues: true
|
|
6516
|
-
});
|
|
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);
|
|
6517
6885
|
}
|
|
6518
|
-
|
|
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
|
+
}
|
|
6519
6904
|
|
|
6520
6905
|
// src/tokens/types.ts
|
|
6521
6906
|
function isColorToken(token) {
|
|
@@ -6630,6 +7015,7 @@ function durationObjectToString(duration) {
|
|
|
6630
7015
|
init_errors();
|
|
6631
7016
|
init_token_utils();
|
|
6632
7017
|
init_utils();
|
|
7018
|
+
init_metadata();
|
|
6633
7019
|
var toSRGB = culori.converter("rgb");
|
|
6634
7020
|
var toP3 = culori.converter("p3");
|
|
6635
7021
|
var KOTLIN_KEYWORDS = /* @__PURE__ */ new Set([
|
|
@@ -6680,9 +7066,6 @@ function resolveColorFormat(format) {
|
|
|
6680
7066
|
function escapeKotlinString(str) {
|
|
6681
7067
|
return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\$/g, "\\$");
|
|
6682
7068
|
}
|
|
6683
|
-
function escapeKDoc(str) {
|
|
6684
|
-
return str.replace(/\*\//g, "* /").replace(/\r?\n/g, " ").trim();
|
|
6685
|
-
}
|
|
6686
7069
|
function formatKotlinNumber(value) {
|
|
6687
7070
|
return Number.isInteger(value) ? `${value}.0` : String(value);
|
|
6688
7071
|
}
|
|
@@ -6814,8 +7197,13 @@ var AndroidRenderer = class {
|
|
|
6814
7197
|
const kotlinName = this.buildFlatKotlinName(token);
|
|
6815
7198
|
const kotlinValue = this.formatKotlinValue(token, options, baseDepth + 1);
|
|
6816
7199
|
const annotation = this.typeAnnotationSuffix(token);
|
|
6817
|
-
|
|
6818
|
-
|
|
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}`);
|
|
6819
7207
|
}
|
|
6820
7208
|
lines.push(
|
|
6821
7209
|
`${valIndent}${options.visPrefix}val ${kotlinName}${annotation} = ${kotlinValue}`
|
|
@@ -6851,8 +7239,13 @@ var AndroidRenderer = class {
|
|
|
6851
7239
|
const kotlinName = toSafeIdentifier(key, KOTLIN_KEYWORDS, false);
|
|
6852
7240
|
const kotlinValue = this.formatKotlinValue(token, options, depth);
|
|
6853
7241
|
const annotation = this.typeAnnotationSuffix(token);
|
|
6854
|
-
|
|
6855
|
-
|
|
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}`);
|
|
6856
7249
|
}
|
|
6857
7250
|
lines.push(`${pad}${options.visPrefix}val ${kotlinName}${annotation} = ${kotlinValue}`);
|
|
6858
7251
|
}
|
|
@@ -7629,10 +8022,8 @@ function stableInputsKey(modifierInputs) {
|
|
|
7629
8022
|
|
|
7630
8023
|
// src/renderers/css.ts
|
|
7631
8024
|
init_utils();
|
|
8025
|
+
init_metadata();
|
|
7632
8026
|
var CssRenderer = class _CssRenderer {
|
|
7633
|
-
sanitizeCssCommentText(text) {
|
|
7634
|
-
return text.replace(/\*\//g, "*\\/").replace(/\r?\n/g, " ").trim();
|
|
7635
|
-
}
|
|
7636
8027
|
async format(context, options) {
|
|
7637
8028
|
const opts = {
|
|
7638
8029
|
preset: options?.preset ?? "bundle",
|
|
@@ -7712,12 +8103,13 @@ var CssRenderer = class _CssRenderer {
|
|
|
7712
8103
|
}
|
|
7713
8104
|
pushTokenLines(lines, token, tokens, referenceTokens, preserveReferences, indent, newline, space) {
|
|
7714
8105
|
const entries = this.buildCssEntries(token, tokens, referenceTokens, preserveReferences);
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
lines.push(`${indent}
|
|
8106
|
+
const deprecationComment = buildTokenDeprecationComment(token, "css");
|
|
8107
|
+
if (deprecationComment) {
|
|
8108
|
+
lines.push(`${indent}${deprecationComment}${newline}`);
|
|
7718
8109
|
}
|
|
7719
|
-
|
|
7720
|
-
|
|
8110
|
+
const descriptionComment = buildTokenDescriptionComment(token, "css");
|
|
8111
|
+
if (descriptionComment) {
|
|
8112
|
+
lines.push(`${indent}${descriptionComment}${newline}`);
|
|
7721
8113
|
}
|
|
7722
8114
|
for (const entry of entries) {
|
|
7723
8115
|
lines.push(`${indent}--${entry.name}:${space}${entry.value};${newline}`);
|
|
@@ -8357,6 +8749,7 @@ function cssRenderer() {
|
|
|
8357
8749
|
|
|
8358
8750
|
// src/renderers/ios.ts
|
|
8359
8751
|
init_utils();
|
|
8752
|
+
init_metadata();
|
|
8360
8753
|
var toSRGB2 = culori.converter("rgb");
|
|
8361
8754
|
var toP32 = culori.converter("p3");
|
|
8362
8755
|
var SWIFT_TYPE_GROUP_MAP = {
|
|
@@ -8500,9 +8893,13 @@ var IosRenderer = class {
|
|
|
8500
8893
|
const swiftValue = this.formatSwiftValue(token, options);
|
|
8501
8894
|
const typeAnnotation = this.getTypeAnnotation(token);
|
|
8502
8895
|
const annotation = typeAnnotation ? `: ${typeAnnotation}` : "";
|
|
8503
|
-
const docComment =
|
|
8896
|
+
const docComment = buildTokenDescriptionComment(token, "swift");
|
|
8504
8897
|
if (docComment) {
|
|
8505
|
-
lines.push(docComment);
|
|
8898
|
+
lines.push(`${indent}${docComment}`);
|
|
8899
|
+
}
|
|
8900
|
+
const deprecationAttr = buildSwiftDeprecationAttribute(token);
|
|
8901
|
+
if (deprecationAttr) {
|
|
8902
|
+
lines.push(`${indent}${deprecationAttr}`);
|
|
8506
8903
|
}
|
|
8507
8904
|
lines.push(`${indent}${access3} ${staticPrefix}${swiftName}${annotation} = ${swiftValue}`);
|
|
8508
8905
|
}
|
|
@@ -8517,15 +8914,6 @@ var IosRenderer = class {
|
|
|
8517
8914
|
}
|
|
8518
8915
|
return Array.from(imports).sort();
|
|
8519
8916
|
}
|
|
8520
|
-
/**
|
|
8521
|
-
* Builds a `///` doc comment from a token's `$description`, if present.
|
|
8522
|
-
*/
|
|
8523
|
-
buildDocComment(token, indent) {
|
|
8524
|
-
if (!token.$description) {
|
|
8525
|
-
return void 0;
|
|
8526
|
-
}
|
|
8527
|
-
return `${indent}/// ${token.$description}`;
|
|
8528
|
-
}
|
|
8529
8917
|
/**
|
|
8530
8918
|
* Builds a qualified Swift name from a token's path, preserving parent
|
|
8531
8919
|
* hierarchy segments to avoid duplicate identifiers.
|
|
@@ -8916,6 +9304,7 @@ function iosRenderer() {
|
|
|
8916
9304
|
// src/renderers/js-module.ts
|
|
8917
9305
|
init_utils();
|
|
8918
9306
|
init_token_utils();
|
|
9307
|
+
init_metadata();
|
|
8919
9308
|
var JsModuleRenderer = class {
|
|
8920
9309
|
async format(context, options) {
|
|
8921
9310
|
const opts = {
|
|
@@ -8953,17 +9342,10 @@ var JsModuleRenderer = class {
|
|
|
8953
9342
|
return outputTree(files);
|
|
8954
9343
|
}
|
|
8955
9344
|
async formatTokens(tokens, options) {
|
|
8956
|
-
const opts = {
|
|
8957
|
-
preset: options.preset ?? "standalone",
|
|
8958
|
-
structure: options.structure ?? "nested",
|
|
8959
|
-
minify: options.minify ?? false,
|
|
8960
|
-
moduleName: options.moduleName ?? "tokens",
|
|
8961
|
-
generateHelper: options.generateHelper ?? false
|
|
8962
|
-
};
|
|
8963
9345
|
const lines = [];
|
|
8964
|
-
lines.push(...this.formatAsObject(tokens,
|
|
9346
|
+
lines.push(...this.formatAsObject(tokens, options));
|
|
8965
9347
|
const code = lines.join("\n");
|
|
8966
|
-
if (
|
|
9348
|
+
if (options.minify) {
|
|
8967
9349
|
return code;
|
|
8968
9350
|
}
|
|
8969
9351
|
return await prettier__default.default.format(code, {
|
|
@@ -8976,20 +9358,53 @@ var JsModuleRenderer = class {
|
|
|
8976
9358
|
trailingComma: "es5"
|
|
8977
9359
|
});
|
|
8978
9360
|
}
|
|
8979
|
-
/**
|
|
8980
|
-
* Format as default export object
|
|
8981
|
-
*/
|
|
8982
9361
|
formatAsObject(tokens, options) {
|
|
8983
9362
|
const lines = [];
|
|
8984
|
-
const
|
|
9363
|
+
const tokenMap = this.buildTokenMap(tokens);
|
|
8985
9364
|
const varName = options.moduleName !== "" ? options.moduleName : "tokens";
|
|
8986
|
-
|
|
8987
|
-
|
|
8988
|
-
|
|
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
|
+
}
|
|
8989
9375
|
lines.push("");
|
|
8990
9376
|
lines.push(`export default ${varName}`);
|
|
8991
9377
|
return lines;
|
|
8992
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
|
+
}
|
|
8993
9408
|
tokensToPlainObject(tokens, structure) {
|
|
8994
9409
|
if (structure === "nested") {
|
|
8995
9410
|
return buildNestedTokenObject(tokens, (token) => token.$value);
|
|
@@ -9000,7 +9415,7 @@ var JsModuleRenderer = class {
|
|
|
9000
9415
|
}
|
|
9001
9416
|
return result;
|
|
9002
9417
|
}
|
|
9003
|
-
|
|
9418
|
+
addNestedProperties(lines, obj, tokenMap, indent) {
|
|
9004
9419
|
const indentStr2 = " ".repeat(indent);
|
|
9005
9420
|
const entries = Object.entries(obj).sort(([keyA], [keyB]) => keyA.localeCompare(keyB));
|
|
9006
9421
|
for (let i = 0; i < entries.length; i++) {
|
|
@@ -9012,19 +9427,20 @@ var JsModuleRenderer = class {
|
|
|
9012
9427
|
const isLast = i === entries.length - 1;
|
|
9013
9428
|
const isNestedObject = typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9014
9429
|
if (!isNestedObject) {
|
|
9430
|
+
const token = tokenMap.get(key);
|
|
9431
|
+
if (token) {
|
|
9432
|
+
this.pushTokenComments(lines, token, indentStr2);
|
|
9433
|
+
}
|
|
9015
9434
|
lines.push(
|
|
9016
9435
|
`${indentStr2}${this.quoteKey(key)}: ${JSON.stringify(value)}${isLast ? "" : ","}`
|
|
9017
9436
|
);
|
|
9018
9437
|
continue;
|
|
9019
9438
|
}
|
|
9020
9439
|
lines.push(`${indentStr2}${this.quoteKey(key)}: {`);
|
|
9021
|
-
this.
|
|
9440
|
+
this.addNestedProperties(lines, value, tokenMap, indent + 1);
|
|
9022
9441
|
lines.push(`${indentStr2}}${isLast ? "" : ","}`);
|
|
9023
9442
|
}
|
|
9024
9443
|
}
|
|
9025
|
-
/**
|
|
9026
|
-
* Quote key if necessary
|
|
9027
|
-
*/
|
|
9028
9444
|
quoteKey(key) {
|
|
9029
9445
|
if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key)) {
|
|
9030
9446
|
return key;
|
|
@@ -9260,6 +9676,7 @@ function resolveOptions(options) {
|
|
|
9260
9676
|
|
|
9261
9677
|
// src/renderers/tailwind.ts
|
|
9262
9678
|
init_utils();
|
|
9679
|
+
init_metadata();
|
|
9263
9680
|
var TAILWIND_NAMESPACE_MAP = {
|
|
9264
9681
|
color: "color",
|
|
9265
9682
|
dimension: "spacing",
|
|
@@ -9313,6 +9730,14 @@ var TailwindRenderer = class {
|
|
|
9313
9730
|
for (const [, token] of getSortedTokenEntries(tokens)) {
|
|
9314
9731
|
const varName = this.buildVariableName(token);
|
|
9315
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
|
+
}
|
|
9316
9741
|
lines.push(`${indent}--${varName}:${space}${varValue};${newline}`);
|
|
9317
9742
|
}
|
|
9318
9743
|
lines.push(`}${newline}`);
|
|
@@ -9339,6 +9764,14 @@ var TailwindRenderer = class {
|
|
|
9339
9764
|
for (const [, token] of getSortedTokenEntries(tokens)) {
|
|
9340
9765
|
const varName = this.buildVariableName(token);
|
|
9341
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
|
+
}
|
|
9342
9775
|
lines.push(`${tokenIndent}--${varName}:${space}${varValue};${newline}`);
|
|
9343
9776
|
}
|
|
9344
9777
|
if (hasMediaQuery) {
|
|
@@ -9611,16 +10044,26 @@ init_errors();
|
|
|
9611
10044
|
* This source code is licensed under the MIT license found in the
|
|
9612
10045
|
* LICENSE file in the root directory of this source tree.
|
|
9613
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
|
+
*/
|
|
9614
10054
|
/**
|
|
9615
10055
|
* @license
|
|
9616
10056
|
* Copyright (c) 2025 Dispersa Contributors
|
|
9617
10057
|
* SPDX-License-Identifier: MIT
|
|
9618
10058
|
*/
|
|
9619
10059
|
|
|
9620
|
-
exports.Dispersa = Dispersa;
|
|
9621
10060
|
exports.android = android;
|
|
10061
|
+
exports.build = build;
|
|
10062
|
+
exports.buildOrThrow = buildOrThrow;
|
|
10063
|
+
exports.buildPermutation = buildPermutation;
|
|
9622
10064
|
exports.css = css;
|
|
9623
10065
|
exports.defineRenderer = defineRenderer;
|
|
10066
|
+
exports.generateTypes = generateTypes;
|
|
9624
10067
|
exports.ios = ios;
|
|
9625
10068
|
exports.isBorderToken = isBorderToken;
|
|
9626
10069
|
exports.isColorToken = isColorToken;
|
|
@@ -9633,7 +10076,10 @@ exports.isTransitionToken = isTransitionToken;
|
|
|
9633
10076
|
exports.isTypographyToken = isTypographyToken;
|
|
9634
10077
|
exports.js = js;
|
|
9635
10078
|
exports.json = json;
|
|
10079
|
+
exports.lint = lint;
|
|
9636
10080
|
exports.outputTree = outputTree;
|
|
10081
|
+
exports.resolveAllPermutations = resolveAllPermutations;
|
|
10082
|
+
exports.resolveTokens = resolveTokens;
|
|
9637
10083
|
exports.tailwind = tailwind;
|
|
9638
10084
|
//# sourceMappingURL=index.cjs.map
|
|
9639
10085
|
//# sourceMappingURL=index.cjs.map
|