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.
Files changed (62) hide show
  1. package/README.md +73 -39
  2. package/dist/android-CRDfSB3_.d.cts +126 -0
  3. package/dist/android-DANJjjPO.d.ts +126 -0
  4. package/dist/builders.cjs +220 -64
  5. package/dist/builders.cjs.map +1 -1
  6. package/dist/builders.d.cts +15 -13
  7. package/dist/builders.d.ts +15 -13
  8. package/dist/builders.js +220 -64
  9. package/dist/builders.js.map +1 -1
  10. package/dist/cli/cli.js +120 -7
  11. package/dist/cli/cli.js.map +1 -1
  12. package/dist/cli/config.d.ts +321 -0
  13. package/dist/cli/config.js.map +1 -1
  14. package/dist/cli/index.js +119 -7
  15. package/dist/cli/index.js.map +1 -1
  16. package/dist/dispersa-BC1kDF5u.d.ts +118 -0
  17. package/dist/dispersa-DL3J_Pmz.d.cts +118 -0
  18. package/dist/errors-qT4sJgSA.d.cts +104 -0
  19. package/dist/errors-qT4sJgSA.d.ts +104 -0
  20. package/dist/errors.cjs.map +1 -1
  21. package/dist/errors.d.cts +1 -83
  22. package/dist/errors.d.ts +1 -83
  23. package/dist/errors.js.map +1 -1
  24. package/dist/filters.cjs.map +1 -1
  25. package/dist/filters.d.cts +2 -2
  26. package/dist/filters.d.ts +2 -2
  27. package/dist/filters.js.map +1 -1
  28. package/dist/{index-CNT2Meyf.d.cts → index-Dajm5rvM.d.ts} +311 -132
  29. package/dist/{index-CqdaN3X0.d.ts → index-De6SjZYH.d.cts} +311 -132
  30. package/dist/index.cjs +813 -355
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts +8 -329
  33. package/dist/index.d.ts +8 -329
  34. package/dist/index.js +807 -355
  35. package/dist/index.js.map +1 -1
  36. package/dist/lint.cjs +1017 -0
  37. package/dist/lint.cjs.map +1 -0
  38. package/dist/lint.d.cts +463 -0
  39. package/dist/lint.d.ts +463 -0
  40. package/dist/lint.js +997 -0
  41. package/dist/lint.js.map +1 -0
  42. package/dist/preprocessors.d.cts +2 -2
  43. package/dist/preprocessors.d.ts +2 -2
  44. package/dist/renderers.cjs.map +1 -1
  45. package/dist/renderers.d.cts +7 -6
  46. package/dist/renderers.d.ts +7 -6
  47. package/dist/renderers.js.map +1 -1
  48. package/dist/transforms.cjs +0 -12
  49. package/dist/transforms.cjs.map +1 -1
  50. package/dist/transforms.d.cts +3 -7
  51. package/dist/transforms.d.ts +3 -7
  52. package/dist/transforms.js +1 -12
  53. package/dist/transforms.js.map +1 -1
  54. package/dist/{types-CZb19kiq.d.ts → types-8MLtztK3.d.ts} +56 -1
  55. package/dist/{types-CussyWwe.d.cts → types-BHBHRm0a.d.cts} +56 -1
  56. package/dist/{types-BAv39mum.d.cts → types-BltzwVYK.d.cts} +1 -1
  57. package/dist/{types-DWKq-eJj.d.cts → types-CAdUV-fa.d.cts} +1 -1
  58. package/dist/{types-CzHa7YkW.d.ts → types-DztXKlka.d.ts} +1 -1
  59. package/dist/{types-Bc0kA7De.d.ts → types-TQHV1MrY.d.cts} +19 -1
  60. package/dist/{types-Bc0kA7De.d.cts → types-TQHV1MrY.d.ts} +19 -1
  61. package/dist/{types-BzNcG-rI.d.ts → types-ebxDimRz.d.ts} +1 -1
  62. package/package.json +11 -1
@@ -0,0 +1,463 @@
1
+ import { o as LintRule, m as LintConfig, n as LintResult, p as LintPlugin, q as LintFormatter } from './index-De6SjZYH.cjs';
2
+ export { A as AnyLintRule, x as LintBuildConfig, z as LintIssue, G as LintOutputFormat, u as LintReportDescriptor, t as LintRuleContext, s as LintRuleMeta, y as ResolvedLintConfig, w as ResolvedRuleConfig, v as RuleConfig, I as RuleConfigFor, H as RulesRegistry, r as Severity, T as TypedRulesConfig } from './index-De6SjZYH.cjs';
3
+ export { L as LintOptions } from './dispersa-DL3J_Pmz.cjs';
4
+ import { L as InternalResolvedTokens } from './types-TQHV1MrY.cjs';
5
+ import './types-CAdUV-fa.cjs';
6
+ import './types-BHBHRm0a.cjs';
7
+ import 'json-schema-to-ts';
8
+ import './types-BltzwVYK.cjs';
9
+
10
+ /**
11
+ * @license MIT
12
+ * Copyright (c) 2025-present Dispersa
13
+ *
14
+ * This source code is licensed under the MIT license found in the
15
+ * LICENSE file in the root directory of this source tree.
16
+ */
17
+ /**
18
+ * @fileoverview Factory function for creating type-safe lint rules
19
+ *
20
+ * Use `createRule()` to define rules with full TypeScript inference
21
+ * for message IDs and options.
22
+ */
23
+
24
+ /**
25
+ * Factory function for creating type-safe lint rules
26
+ *
27
+ * This function provides no runtime behavior - it simply returns the rule
28
+ * as-is. Its purpose is to provide type inference and autocomplete for
29
+ * message IDs and options.
30
+ *
31
+ * @template MessageIds - Union type of message IDs this rule can produce
32
+ * @template Options - Rule-specific options type
33
+ *
34
+ * @param rule - The rule definition
35
+ * @returns The same rule definition with full type inference
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * import { createRule } from 'dispersa/lint'
40
+ *
41
+ * export const requireDescription = createRule<
42
+ * 'MISSING_DESCRIPTION' | 'TOO_SHORT',
43
+ * { minLength?: number }
44
+ * >({
45
+ * meta: {
46
+ * name: 'require-description',
47
+ * description: 'Require tokens to have descriptions',
48
+ * messages: {
49
+ * MISSING_DESCRIPTION: "Token '{{name}}' is missing a description",
50
+ * TOO_SHORT: "Token '{{name}}' description is too short ({{length}} chars, min {{minLength}})",
51
+ * },
52
+ * },
53
+ * defaultOptions: { minLength: 10 },
54
+ * create({ tokens, report, options }) {
55
+ * for (const token of Object.values(tokens)) {
56
+ * if (!token.$description) {
57
+ * report({ token, messageId: 'MISSING_DESCRIPTION', data: { name: token.name } })
58
+ * } else if (token.$description.length < options.minLength) {
59
+ * report({
60
+ * token,
61
+ * messageId: 'TOO_SHORT',
62
+ * data: { name: token.name, length: token.$description.length, minLength: options.minLength },
63
+ * })
64
+ * }
65
+ * }
66
+ * },
67
+ * })
68
+ * ```
69
+ */
70
+ declare function createRule<MessageIds extends string, Options extends Record<string, unknown> = Record<string, never>>(rule: LintRule<MessageIds, Options>): LintRule<MessageIds, Options>;
71
+ /**
72
+ * Helper type for extracting options type from a rule
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * const myRule = createRule<'MSG', { format: string }>({ ... })
77
+ * type MyOptions = RuleOptions<typeof myRule> // { format: string }
78
+ * ```
79
+ */
80
+ type RuleOptions<T extends LintRule> = T extends LintRule<string, infer O> ? O : never;
81
+ /**
82
+ * Helper type for extracting message IDs from a rule
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * const myRule = createRule<'MSG1' | 'MSG2', { format: string }>({ ... })
87
+ * type MyMessages = RuleMessages<typeof myRule> // 'MSG1' | 'MSG2'
88
+ * ```
89
+ */
90
+ type RuleMessages<T extends LintRule> = T extends LintRule<infer M, Record<string, unknown>> ? M : never;
91
+
92
+ /**
93
+ * @license MIT
94
+ * Copyright (c) 2025-present Dispersa
95
+ *
96
+ * This source code is licensed under the MIT license found in the
97
+ * LICENSE file in the root directory of this source tree.
98
+ */
99
+ /**
100
+ * @fileoverview Lint runner that executes rules in parallel against tokens
101
+ *
102
+ * The lint runner is responsible for:
103
+ * - Loading plugins and resolving rule configurations
104
+ * - Executing rules in parallel for performance
105
+ * - Collecting and aggregating lint issues
106
+ * - Interpolating message templates with data
107
+ */
108
+
109
+ type LintRunnerOptions = LintConfig & {
110
+ /** Callback for runner warnings (e.g. unknown rule). Defaults to console.warn. */
111
+ onWarn?: (message: string) => void;
112
+ };
113
+ /**
114
+ * Executes lint rules against a set of tokens
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * const config: LintConfig = {
119
+ * plugins: {
120
+ * dispersa: dispersaPlugin,
121
+ * },
122
+ * rules: {
123
+ * 'dispersa/require-description': 'warn',
124
+ * 'dispersa/naming-convention': ['error', { format: 'kebab-case' }],
125
+ * },
126
+ * }
127
+ *
128
+ * const runner = new LintRunner(config)
129
+ * const result = await runner.run(tokens)
130
+ *
131
+ * console.log(`Found ${result.errorCount} errors, ${result.warningCount} warnings`)
132
+ * ```
133
+ */
134
+ declare class LintRunner {
135
+ private config;
136
+ private pluginLoader;
137
+ private resolvedConfig;
138
+ private warn;
139
+ constructor(config: LintRunnerOptions);
140
+ /**
141
+ * Run all configured rules against the provided tokens
142
+ *
143
+ * Rules are executed in parallel for performance. Issues are collected
144
+ * and returned with counts by severity.
145
+ *
146
+ * @param tokens - Resolved tokens to lint
147
+ * @returns Lint result with issues and counts
148
+ */
149
+ run(tokens: InternalResolvedTokens): Promise<LintResult>;
150
+ /**
151
+ * Resolve configuration: load plugins, parse rule configs
152
+ */
153
+ private resolveConfig;
154
+ private filterTokensByAppliesTo;
155
+ /**
156
+ * Parse rule configuration into resolved format
157
+ */
158
+ private resolveRuleConfig;
159
+ /**
160
+ * Resolve a rule from plugins by rule ID
161
+ *
162
+ * Rule IDs are formatted as 'namespace/rule-name'
163
+ */
164
+ private resolveRule;
165
+ /**
166
+ * Interpolate message template with data
167
+ *
168
+ * Replaces {{key}} placeholders with values from data
169
+ */
170
+ private interpolateMessage;
171
+ /**
172
+ * Clear the plugin cache
173
+ */
174
+ clearCache(): void;
175
+ }
176
+
177
+ /**
178
+ * @license MIT
179
+ * Copyright (c) 2025-present Dispersa
180
+ *
181
+ * This source code is licensed under the MIT license found in the
182
+ * LICENSE file in the root directory of this source tree.
183
+ */
184
+
185
+ type PluginLoaderOptions = {
186
+ /**
187
+ * Base directory for resolving relative plugin paths
188
+ * @default process.cwd()
189
+ */
190
+ cwd?: string;
191
+ };
192
+ /**
193
+ * Loads lint plugins from various sources
194
+ *
195
+ * Handles:
196
+ * - Inline `LintPlugin` objects (returned as-is)
197
+ * - Package names (e.g., '@dispersa/lint-plugin-a11y')
198
+ * - Relative file paths (e.g., './plugins/my-plugin.ts')
199
+ * - Absolute file paths
200
+ *
201
+ * @security **Warning**: Loading plugins from external packages or file paths
202
+ * executes arbitrary code. Only load plugins from trusted sources.
203
+ * For programmatic usage, prefer passing plugin objects directly rather than
204
+ * strings that trigger dynamic imports.
205
+ *
206
+ * @example
207
+ * ```typescript
208
+ * const loader = new PluginLoader({ cwd: process.cwd() })
209
+ *
210
+ * // Load from inline object
211
+ * const plugin1 = await loader.load(myPlugin)
212
+ *
213
+ * // Load from package
214
+ * const plugin2 = await loader.load('@dispersa/lint-plugin-a11y')
215
+ *
216
+ * // Load from file
217
+ * const plugin3 = await loader.load('./plugins/custom.ts')
218
+ * ```
219
+ */
220
+ declare class PluginLoader {
221
+ private cwd;
222
+ private jiti;
223
+ private cache;
224
+ constructor(options?: PluginLoaderOptions);
225
+ /**
226
+ * Load a plugin from an inline object or module path
227
+ *
228
+ * @param source - Plugin object or module path string
229
+ * @returns Loaded plugin
230
+ * @throws {ConfigurationError} If plugin cannot be loaded or is invalid
231
+ */
232
+ load(source: LintPlugin | string): Promise<LintPlugin>;
233
+ /**
234
+ * Load multiple plugins
235
+ *
236
+ * @param plugins - Record of namespace to plugin source
237
+ * @returns Record of namespace to loaded plugin
238
+ */
239
+ loadAll(plugins: Record<string, LintPlugin | string>): Promise<Record<string, LintPlugin>>;
240
+ /**
241
+ * Check if source is an inline plugin object
242
+ */
243
+ private isPluginObject;
244
+ /**
245
+ * Load a plugin from a module path
246
+ */
247
+ private loadFromModule;
248
+ /**
249
+ * Load a plugin from a file path using jiti (supports TypeScript)
250
+ */
251
+ private loadFromFile;
252
+ /**
253
+ * Load a plugin from a package name
254
+ */
255
+ private loadFromPackage;
256
+ /**
257
+ * Extract plugin from loaded module
258
+ *
259
+ * Supports multiple export patterns:
260
+ * - export default plugin
261
+ * - export const plugin = {...}
262
+ * - module.exports = plugin (CJS)
263
+ */
264
+ private extractPlugin;
265
+ /**
266
+ * Check if object has required plugin structure
267
+ */
268
+ private isValidPluginStructure;
269
+ /**
270
+ * Validate a loaded plugin
271
+ */
272
+ private validatePlugin;
273
+ /**
274
+ * Clear the plugin cache
275
+ */
276
+ clearCache(): void;
277
+ }
278
+
279
+ type NamingConventionOptions = {
280
+ /**
281
+ * Naming format to enforce
282
+ * - 'kebab-case': color-brand-primary, red-500, blue-600
283
+ * - 'camelCase': colorBrandPrimary
284
+ * - 'PascalCase': ColorBrandPrimary
285
+ * - 'snake_case': color_brand_primary
286
+ * - 'screaming-snake': COLOR_BRAND_PRIMARY
287
+ */
288
+ format?: 'kebab-case' | 'camelCase' | 'PascalCase' | 'snake_case' | 'screaming-snake';
289
+ /** Token name patterns to ignore (glob patterns) */
290
+ ignore?: string[];
291
+ /** Custom regex pattern to validate against */
292
+ pattern?: string;
293
+ /**
294
+ * Allow purely numeric path segments (e.g., spacing.0, spacing.1)
295
+ * Common in design system scales. Default: true
296
+ */
297
+ allowNumericSegments?: boolean;
298
+ };
299
+ declare const namingConvention: LintRule<"INVALID_FORMAT" | "INVALID_SEGMENT", NamingConventionOptions>;
300
+
301
+ type NoDeprecatedUsageOptions = {
302
+ /** Token name patterns to ignore (glob patterns) */
303
+ ignore?: string[];
304
+ };
305
+ declare const noDeprecatedUsage: LintRule<"REFERENCES_DEPRECATED", NoDeprecatedUsageOptions>;
306
+
307
+ type NoDuplicateValuesOptions = {
308
+ /** Token name patterns to ignore (glob patterns) */
309
+ ignore?: string[];
310
+ /** Only check specific token types */
311
+ types?: string[];
312
+ };
313
+ declare const noDuplicateValues: LintRule<"DUPLICATE_VALUE", NoDuplicateValuesOptions>;
314
+
315
+ /**
316
+ * @license MIT
317
+ * Copyright (c) 2025-present Dispersa
318
+ *
319
+ * This source code is licensed under the MIT license found in the
320
+ * LICENSE file in the root directory of this source tree.
321
+ */
322
+ /**
323
+ * @fileoverview Types for path-schema rule
324
+ */
325
+ /**
326
+ * Definition of a named path segment
327
+ */
328
+ type SegmentDefinition = {
329
+ /** Allowed values (array of strings or regex pattern, or single regex) */
330
+ values: string[] | RegExp | Array<string | RegExp>;
331
+ /** Human-readable description */
332
+ description?: string;
333
+ /** Whether this segment is optional */
334
+ optional?: boolean;
335
+ };
336
+ /**
337
+ * Transition rule for context-aware segment validation
338
+ */
339
+ type TransitionRule = {
340
+ /** Segment value or pattern to match (from) */
341
+ from: string | string[] | RegExp;
342
+ /** Allowed/forbidden segment values or patterns (to) */
343
+ to: string | string[] | RegExp;
344
+ /** Whether transition is allowed. Default: true */
345
+ allow?: boolean;
346
+ };
347
+ /**
348
+ * Path pattern (string with {segment} placeholders)
349
+ */
350
+ type PathPattern = string;
351
+ /**
352
+ * Configuration for path-schema rule
353
+ */
354
+ type PathSchemaConfig = {
355
+ /**
356
+ * Named segment definitions.
357
+ * Maps segment name to allowed values/description.
358
+ *
359
+ * @example
360
+ * ```typescript
361
+ * {
362
+ * domain: { values: ['color', 'spacing'], description: 'Token domain' },
363
+ * layer: { values: ['base', 'semantic', 'component'] },
364
+ * scale: { values: ['xs', 'sm', 'md', 'lg', 'xl'] },
365
+ * brand: { values: /^[a-z]+$/, description: 'Brand name' },
366
+ * }
367
+ * ```
368
+ */
369
+ segments?: Record<string, SegmentDefinition>;
370
+ /**
371
+ * Valid path patterns using {segment} placeholders.
372
+ *
373
+ * @example
374
+ * ```typescript
375
+ * [
376
+ * 'color.base.{brand}',
377
+ * 'color.semantic.{element}.{role}',
378
+ * 'color.component.{component}.{element}.{state}',
379
+ * ]
380
+ * ```
381
+ */
382
+ paths?: PathPattern[];
383
+ /**
384
+ * Context-aware transition rules.
385
+ * Alternative to patterns - define which segments can follow which.
386
+ *
387
+ * @example
388
+ * ```typescript
389
+ * [
390
+ * { from: 'color', to: ['base', 'semantic', 'component'] },
391
+ * { from: 'semantic', to: ['text', 'bg', 'border'] },
392
+ * { from: 'semantic', to: 'component', allow: false },
393
+ * ]
394
+ * ```
395
+ */
396
+ transitions?: TransitionRule[];
397
+ /**
398
+ * Token name patterns to ignore (glob patterns)
399
+ */
400
+ ignore?: string[];
401
+ };
402
+
403
+ declare const pathSchema: LintRule<"INVALID_PATH" | "UNKNOWN_SEGMENT" | "FORBIDDEN_TRANSITION", PathSchemaConfig>;
404
+
405
+ type RequireDescriptionOptions = {
406
+ /** Minimum length for description. Default: 1 */
407
+ minLength?: number;
408
+ /** Token name patterns to ignore (glob patterns) */
409
+ ignore?: string[];
410
+ };
411
+ declare const requireDescription: LintRule<"MISSING_DESCRIPTION" | "TOO_SHORT", RequireDescriptionOptions>;
412
+
413
+ /**
414
+ * @license MIT
415
+ * Copyright (c) 2025-present Dispersa
416
+ *
417
+ * This source code is licensed under the MIT license found in the
418
+ * LICENSE file in the root directory of this source tree.
419
+ */
420
+ /**
421
+ * @fileoverview Built-in lint rules and dispersa plugin
422
+ */
423
+
424
+ declare const dispersaPlugin: LintPlugin;
425
+ declare const recommendedConfig: LintConfig;
426
+ declare const strictConfig: LintConfig;
427
+ declare const minimalConfig: LintConfig;
428
+
429
+ declare module '../types' {
430
+ interface RulesRegistry {
431
+ 'dispersa/require-description': RequireDescriptionOptions;
432
+ 'dispersa/naming-convention': NamingConventionOptions;
433
+ 'dispersa/no-deprecated-usage': NoDeprecatedUsageOptions;
434
+ 'dispersa/no-duplicate-values': NoDuplicateValuesOptions;
435
+ 'dispersa/path-schema': PathSchemaConfig;
436
+ }
437
+ }
438
+
439
+ /**
440
+ * @license MIT
441
+ * Copyright (c) 2025-present Dispersa
442
+ *
443
+ * This source code is licensed under the MIT license found in the
444
+ * LICENSE file in the root directory of this source tree.
445
+ */
446
+ /**
447
+ * @fileoverview Lint output formatter interface and utilities
448
+ */
449
+
450
+ /**
451
+ * Format lint results as JSON
452
+ */
453
+ declare const formatLintJson: LintFormatter;
454
+ /**
455
+ * Format lint results in a human-readable stylish format
456
+ */
457
+ declare const formatLintStylish: LintFormatter;
458
+ /**
459
+ * Format lint results for CI output (compact, parseable)
460
+ */
461
+ declare const formatLintCompact: LintFormatter;
462
+
463
+ export { LintConfig, LintFormatter, LintPlugin, LintResult, LintRule, LintRunner, type LintRunnerOptions, type NamingConventionOptions, type NoDeprecatedUsageOptions, type NoDuplicateValuesOptions, type PathSchemaConfig, PluginLoader, type PluginLoaderOptions, type RequireDescriptionOptions, type RuleMessages, type RuleOptions, type SegmentDefinition, type TransitionRule, createRule, dispersaPlugin, formatLintCompact, formatLintJson, formatLintStylish, minimalConfig, namingConvention, noDeprecatedUsage, noDuplicateValues, pathSchema, recommendedConfig, requireDescription, strictConfig };