@breadstone-infrastructure/token-linter 0.0.231
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/LICENSE +21 -0
- package/README.md +72 -0
- package/cli/Cli.d.ts +10 -0
- package/cli/Cli.d.ts.map +1 -0
- package/cli/Cli.js +32 -0
- package/cli/Cli.js.map +1 -0
- package/cli/CliArgs.d.ts +2 -0
- package/cli/CliArgs.d.ts.map +1 -0
- package/cli/CliArgs.js +88 -0
- package/cli/CliArgs.js.map +1 -0
- package/cli/CliArgsConfig.d.ts +2 -0
- package/cli/CliArgsConfig.d.ts.map +1 -0
- package/cli/CliArgsConfig.js +12 -0
- package/cli/CliArgsConfig.js.map +1 -0
- package/cli/CliRun.d.ts +2 -0
- package/cli/CliRun.d.ts.map +1 -0
- package/cli/CliRun.js +34 -0
- package/cli/CliRun.js.map +1 -0
- package/cli/commands/LintCommand.d.ts +2 -0
- package/cli/commands/LintCommand.d.ts.map +1 -0
- package/cli/commands/LintCommand.js +66 -0
- package/cli/commands/LintCommand.js.map +1 -0
- package/cli/commands/LintCommandArgsConfig.d.ts +2 -0
- package/cli/commands/LintCommandArgsConfig.d.ts.map +1 -0
- package/cli/commands/LintCommandArgsConfig.js +46 -0
- package/cli/commands/LintCommandArgsConfig.js.map +1 -0
- package/cli/lint.d.ts +3 -0
- package/cli/lint.d.ts.map +1 -0
- package/cli/lint.js +55 -0
- package/cli/lint.js.map +1 -0
- package/config/TokenLinterConfigDiscovery.d.ts +16 -0
- package/config/TokenLinterConfigDiscovery.d.ts.map +1 -0
- package/config/TokenLinterConfigDiscovery.js +44 -0
- package/config/TokenLinterConfigDiscovery.js.map +1 -0
- package/config/defineConfig.d.ts +41 -0
- package/config/defineConfig.d.ts.map +1 -0
- package/config/defineConfig.js +37 -0
- package/config/defineConfig.js.map +1 -0
- package/core/interaction.d.ts +25 -0
- package/core/interaction.d.ts.map +1 -0
- package/core/interaction.js +45 -0
- package/core/interaction.js.map +1 -0
- package/core/loader.d.ts +21 -0
- package/core/loader.d.ts.map +1 -0
- package/core/loader.js +84 -0
- package/core/loader.js.map +1 -0
- package/core/rule-registry.d.ts +46 -0
- package/core/rule-registry.d.ts.map +1 -0
- package/core/rule-registry.js +73 -0
- package/core/rule-registry.js.map +1 -0
- package/core/rule.d.ts +46 -0
- package/core/rule.d.ts.map +1 -0
- package/core/rule.js +3 -0
- package/core/rule.js.map +1 -0
- package/core/runner.d.ts +23 -0
- package/core/runner.d.ts.map +1 -0
- package/core/runner.js +103 -0
- package/core/runner.js.map +1 -0
- package/index.d.ts +46 -0
- package/index.d.ts.map +1 -0
- package/index.js +47 -0
- package/index.js.map +1 -0
- package/models/lint-result.d.ts +14 -0
- package/models/lint-result.d.ts.map +1 -0
- package/models/lint-result.js +3 -0
- package/models/lint-result.js.map +1 -0
- package/models/rule-context.d.ts +18 -0
- package/models/rule-context.d.ts.map +1 -0
- package/models/rule-context.js +3 -0
- package/models/rule-context.js.map +1 -0
- package/models/rule-finding.d.ts +15 -0
- package/models/rule-finding.d.ts.map +1 -0
- package/models/rule-finding.js +3 -0
- package/models/rule-finding.js.map +1 -0
- package/models/rule-result.d.ts +11 -0
- package/models/rule-result.d.ts.map +1 -0
- package/models/rule-result.js +3 -0
- package/models/rule-result.js.map +1 -0
- package/models/rule-severity.d.ts +14 -0
- package/models/rule-severity.d.ts.map +1 -0
- package/models/rule-severity.js +10 -0
- package/models/rule-severity.js.map +1 -0
- package/models/token-entry.d.ts +11 -0
- package/models/token-entry.d.ts.map +1 -0
- package/models/token-entry.js +2 -0
- package/models/token-entry.js.map +1 -0
- package/models/token-linter-config.d.ts +30 -0
- package/models/token-linter-config.d.ts.map +1 -0
- package/models/token-linter-config.js +3 -0
- package/models/token-linter-config.js.map +1 -0
- package/orchestration/TokenLinterOrchestrator.d.ts +29 -0
- package/orchestration/TokenLinterOrchestrator.d.ts.map +1 -0
- package/orchestration/TokenLinterOrchestrator.js +98 -0
- package/orchestration/TokenLinterOrchestrator.js.map +1 -0
- package/package.json +20 -0
- package/presets/index.d.ts +2 -0
- package/presets/index.d.ts.map +1 -0
- package/presets/index.js +2 -0
- package/presets/index.js.map +1 -0
- package/presets/recommended.d.ts +23 -0
- package/presets/recommended.d.ts.map +1 -0
- package/presets/recommended.js +41 -0
- package/presets/recommended.js.map +1 -0
- package/reporters/console.reporter.d.ts +15 -0
- package/reporters/console.reporter.d.ts.map +1 -0
- package/reporters/console.reporter.js +75 -0
- package/reporters/console.reporter.js.map +1 -0
- package/reporters/json.reporter.d.ts +11 -0
- package/reporters/json.reporter.d.ts.map +1 -0
- package/reporters/json.reporter.js +37 -0
- package/reporters/json.reporter.js.map +1 -0
- package/reporters/reporter.d.ts +16 -0
- package/reporters/reporter.d.ts.map +1 -0
- package/reporters/reporter.js +3 -0
- package/reporters/reporter.js.map +1 -0
- package/reporters/summary.reporter.d.ts +12 -0
- package/reporters/summary.reporter.d.ts.map +1 -0
- package/reporters/summary.reporter.js +48 -0
- package/reporters/summary.reporter.js.map +1 -0
- package/rules/alphabetical-sort.rule.d.ts +19 -0
- package/rules/alphabetical-sort.rule.d.ts.map +1 -0
- package/rules/alphabetical-sort.rule.js +72 -0
- package/rules/alphabetical-sort.rule.js.map +1 -0
- package/rules/component-presence.rule.d.ts +29 -0
- package/rules/component-presence.rule.d.ts.map +1 -0
- package/rules/component-presence.rule.js +102 -0
- package/rules/component-presence.rule.js.map +1 -0
- package/rules/duplicate-value.rule.d.ts +17 -0
- package/rules/duplicate-value.rule.d.ts.map +1 -0
- package/rules/duplicate-value.rule.js +49 -0
- package/rules/duplicate-value.rule.js.map +1 -0
- package/rules/empty-json.rule.d.ts +52 -0
- package/rules/empty-json.rule.d.ts.map +1 -0
- package/rules/empty-json.rule.js +100 -0
- package/rules/empty-json.rule.js.map +1 -0
- package/rules/forbidden-key.rule.d.ts +57 -0
- package/rules/forbidden-key.rule.d.ts.map +1 -0
- package/rules/forbidden-key.rule.js +118 -0
- package/rules/forbidden-key.rule.js.map +1 -0
- package/rules/forbidden-value.rule.d.ts +53 -0
- package/rules/forbidden-value.rule.d.ts.map +1 -0
- package/rules/forbidden-value.rule.js +130 -0
- package/rules/forbidden-value.rule.js.map +1 -0
- package/rules/includes-consistency.rule.d.ts +30 -0
- package/rules/includes-consistency.rule.d.ts.map +1 -0
- package/rules/includes-consistency.rule.js +153 -0
- package/rules/includes-consistency.rule.js.map +1 -0
- package/rules/index.d.ts +7 -0
- package/rules/index.d.ts.map +1 -0
- package/rules/index.js +47 -0
- package/rules/index.js.map +1 -0
- package/rules/key-consistency.rule.d.ts +38 -0
- package/rules/key-consistency.rule.d.ts.map +1 -0
- package/rules/key-consistency.rule.js +161 -0
- package/rules/key-consistency.rule.js.map +1 -0
- package/rules/missing-includes.rule.d.ts +19 -0
- package/rules/missing-includes.rule.d.ts.map +1 -0
- package/rules/missing-includes.rule.js +51 -0
- package/rules/missing-includes.rule.js.map +1 -0
- package/rules/mixin-reference.rule.d.ts +28 -0
- package/rules/mixin-reference.rule.d.ts.map +1 -0
- package/rules/mixin-reference.rule.js +104 -0
- package/rules/mixin-reference.rule.js.map +1 -0
- package/rules/naming-convention.rule.d.ts +29 -0
- package/rules/naming-convention.rule.d.ts.map +1 -0
- package/rules/naming-convention.rule.js +112 -0
- package/rules/naming-convention.rule.js.map +1 -0
- package/rules/nested-depth.rule.d.ts +42 -0
- package/rules/nested-depth.rule.d.ts.map +1 -0
- package/rules/nested-depth.rule.js +72 -0
- package/rules/nested-depth.rule.js.map +1 -0
- package/rules/required-includes.rule.d.ts +60 -0
- package/rules/required-includes.rule.d.ts.map +1 -0
- package/rules/required-includes.rule.js +118 -0
- package/rules/required-includes.rule.js.map +1 -0
- package/rules/rule-options.d.ts +158 -0
- package/rules/rule-options.d.ts.map +1 -0
- package/rules/rule-options.js +89 -0
- package/rules/rule-options.js.map +1 -0
- package/rules/value-consistency.rule.d.ts +17 -0
- package/rules/value-consistency.rule.d.ts.map +1 -0
- package/rules/value-consistency.rule.js +69 -0
- package/rules/value-consistency.rule.js.map +1 -0
- package/rules/value-schema.rule.d.ts +18 -0
- package/rules/value-schema.rule.d.ts.map +1 -0
- package/rules/value-schema.rule.js +108 -0
- package/rules/value-schema.rule.js.map +1 -0
- package/rules/value-type.rule.d.ts +71 -0
- package/rules/value-type.rule.d.ts.map +1 -0
- package/rules/value-type.rule.js +176 -0
- package/rules/value-type.rule.js.map +1 -0
- package/utils.d.ts +55 -0
- package/utils.d.ts.map +1 -0
- package/utils.js +125 -0
- package/utils.js.map +1 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// #region Imports
|
|
2
|
+
import { bold, ConsoleLogger, gray, green, red, yellow } from '@breadstone-infrastructure/utilities';
|
|
3
|
+
import { RuleSeverity } from '../models/rule-severity.js';
|
|
4
|
+
// #endregion
|
|
5
|
+
/**
|
|
6
|
+
* @description Outputs lint results as formatted console output with severity colors.
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export class ConsoleReporter {
|
|
10
|
+
// #region Fields
|
|
11
|
+
name = 'console';
|
|
12
|
+
_logger = new ConsoleLogger();
|
|
13
|
+
// #endregion
|
|
14
|
+
// #region Methods
|
|
15
|
+
report(result) {
|
|
16
|
+
this._logger.info('');
|
|
17
|
+
for (const ruleResult of result.results) {
|
|
18
|
+
this.reportRule(ruleResult);
|
|
19
|
+
}
|
|
20
|
+
this.reportSummary(result);
|
|
21
|
+
}
|
|
22
|
+
reportRule(ruleResult) {
|
|
23
|
+
if (ruleResult.findings.length === 0) {
|
|
24
|
+
this._logger.info(green(` ✔ Passed - ${ruleResult.ruleName}`));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
this._logger.info(bold(` Rule: ${ruleResult.ruleName}`));
|
|
28
|
+
this._logger.info(gray(` ${'─'.repeat(60)}`));
|
|
29
|
+
for (const finding of ruleResult.findings) {
|
|
30
|
+
const severityLabel = this.formatSeverity(finding.severity);
|
|
31
|
+
const fixedLabel = finding.fixed ? green(' [FIXED]') : '';
|
|
32
|
+
const location = [finding.component, finding.theme].filter(Boolean).join(' / ');
|
|
33
|
+
this._logger.info(` ${severityLabel} ${gray(`[${location}]`)} ${finding.message}${fixedLabel}`);
|
|
34
|
+
}
|
|
35
|
+
this._logger.info('');
|
|
36
|
+
}
|
|
37
|
+
reportSummary(result) {
|
|
38
|
+
this._logger.info(gray(` ${'═'.repeat(60)}`));
|
|
39
|
+
this._logger.info(bold(' Summary'));
|
|
40
|
+
const parts = [];
|
|
41
|
+
if (result.totalErrors > 0) {
|
|
42
|
+
parts.push(red(`${result.totalErrors} error(s)`));
|
|
43
|
+
}
|
|
44
|
+
if (result.totalWarnings > 0) {
|
|
45
|
+
parts.push(yellow(`${result.totalWarnings} warning(s)`));
|
|
46
|
+
}
|
|
47
|
+
if (result.totalInfos > 0) {
|
|
48
|
+
parts.push(gray(`${result.totalInfos} info(s)`));
|
|
49
|
+
}
|
|
50
|
+
if (result.totalFixes > 0) {
|
|
51
|
+
parts.push(green(`${result.totalFixes} fix(es) applied`));
|
|
52
|
+
}
|
|
53
|
+
if (parts.length === 0) {
|
|
54
|
+
this._logger.info(green(' All checks passed.'));
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
this._logger.info(` ${parts.join(' | ')}`);
|
|
58
|
+
}
|
|
59
|
+
this._logger.info(gray(` Duration: ${result.duration}ms`));
|
|
60
|
+
this._logger.info('');
|
|
61
|
+
}
|
|
62
|
+
formatSeverity(severity) {
|
|
63
|
+
switch (severity) {
|
|
64
|
+
case RuleSeverity.Error:
|
|
65
|
+
return red(bold('ERROR'));
|
|
66
|
+
case RuleSeverity.Warning:
|
|
67
|
+
return yellow(bold('WARN '));
|
|
68
|
+
case RuleSeverity.Info:
|
|
69
|
+
return gray(bold('INFO '));
|
|
70
|
+
default:
|
|
71
|
+
return gray(' ');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=console.reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console.reporter.js","sourceRoot":"","sources":["../../src/reporters/console.reporter.ts"],"names":[],"mappings":"AAAA,kBAAkB;AAElB,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,sCAAsC,CAAC;AAGrG,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG1D,aAAa;AAEb;;;GAGG;AACH,MAAM,OAAO,eAAe;IAExB,iBAAiB;IAED,IAAI,GAAG,SAAS,CAAC;IAChB,OAAO,GAAG,IAAI,aAAa,EAAE,CAAC;IAE/C,aAAa;IAEb,kBAAkB;IAEX,MAAM,CAAC,MAAmB;QAC7B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEtB,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACtC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAChC,CAAC;QAED,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAEO,UAAU,CAAC,UAAuB;QACtC,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YAEhE,OAAO;QACX,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAC1D,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAE/C,KAAK,MAAM,OAAO,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;YACxC,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC5D,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAEhF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,aAAa,IAAI,IAAI,CAAC,IAAI,QAAQ,GAAG,CAAC,IAAI,OAAO,CAAC,OAAO,GAAG,UAAU,EAAE,CAAC,CAAC;QACrG,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC;IAEO,aAAa,CAAC,MAAmB;QACrC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;QAErC,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,IAAI,MAAM,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,WAAW,WAAW,CAAC,CAAC,CAAC;QACtD,CAAC;QAED,IAAI,MAAM,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,aAAa,aAAa,CAAC,CAAC,CAAC;QAC7D,CAAC;QAED,IAAI,MAAM,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;YACxB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,UAAU,UAAU,CAAC,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,MAAM,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;YACxB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,UAAU,kBAAkB,CAAC,CAAC,CAAC;QAC9D,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAC;QACrD,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAClD,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC;QAC5D,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC;IAEO,cAAc,CAAC,QAAsB;QACzC,QAAQ,QAAQ,EAAE,CAAC;YACf,KAAK,YAAY,CAAC,KAAK;gBACnB,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;YAC9B,KAAK,YAAY,CAAC,OAAO;gBACrB,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;YACjC,KAAK,YAAY,CAAC,IAAI;gBAClB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;YAC/B;gBACI,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;IACL,CAAC;CAGJ"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ILintResult } from '../models/lint-result.js';
|
|
2
|
+
import type { IReporter } from './reporter.js';
|
|
3
|
+
/**
|
|
4
|
+
* @description Outputs lint results as structured JSON for CI/pipeline consumption.
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export declare class JsonReporter implements IReporter {
|
|
8
|
+
readonly name = "json";
|
|
9
|
+
report(result: ILintResult): void;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=json.reporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.reporter.d.ts","sourceRoot":"","sources":["../../src/reporters/json.reporter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI/C;;;GAGG;AACH,qBAAa,YAAa,YAAW,SAAS;IAI1C,SAAgB,IAAI,UAAU;IAMvB,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;CA2B3C"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// #region Imports
|
|
2
|
+
// #endregion
|
|
3
|
+
/**
|
|
4
|
+
* @description Outputs lint results as structured JSON for CI/pipeline consumption.
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export class JsonReporter {
|
|
8
|
+
// #region Fields
|
|
9
|
+
name = 'json';
|
|
10
|
+
// #endregion
|
|
11
|
+
// #region Methods
|
|
12
|
+
report(result) {
|
|
13
|
+
const output = {
|
|
14
|
+
totalErrors: result.totalErrors,
|
|
15
|
+
totalWarnings: result.totalWarnings,
|
|
16
|
+
totalInfos: result.totalInfos,
|
|
17
|
+
totalFixes: result.totalFixes,
|
|
18
|
+
duration: result.duration,
|
|
19
|
+
rules: result.results.map(r => ({
|
|
20
|
+
rule: r.ruleName,
|
|
21
|
+
findingsCount: r.findings.length,
|
|
22
|
+
duration: r.duration,
|
|
23
|
+
findings: r.findings.map(f => ({
|
|
24
|
+
component: f.component,
|
|
25
|
+
theme: f.theme,
|
|
26
|
+
key: f.key,
|
|
27
|
+
message: f.message,
|
|
28
|
+
severity: f.severity,
|
|
29
|
+
filePath: f.filePath,
|
|
30
|
+
fixed: f.fixed,
|
|
31
|
+
})),
|
|
32
|
+
})),
|
|
33
|
+
};
|
|
34
|
+
console.log(JSON.stringify(output, null, 2));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=json.reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.reporter.js","sourceRoot":"","sources":["../../src/reporters/json.reporter.ts"],"names":[],"mappings":"AAAA,kBAAkB;AAKlB,aAAa;AAEb;;;GAGG;AACH,MAAM,OAAO,YAAY;IAErB,iBAAiB;IAED,IAAI,GAAG,MAAM,CAAC;IAE9B,aAAa;IAEb,kBAAkB;IAEX,MAAM,CAAC,MAAmB;QAC7B,MAAM,MAAM,GAAG;YACX,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,aAAa,EAAE,MAAM,CAAC,aAAa;YACnC,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC5B,IAAI,EAAE,CAAC,CAAC,QAAQ;gBAChB,aAAa,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM;gBAChC,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBAC3B,SAAS,EAAE,CAAC,CAAC,SAAS;oBACtB,KAAK,EAAE,CAAC,CAAC,KAAK;oBACd,GAAG,EAAE,CAAC,CAAC,GAAG;oBACV,OAAO,EAAE,CAAC,CAAC,OAAO;oBAClB,QAAQ,EAAE,CAAC,CAAC,QAAQ;oBACpB,QAAQ,EAAE,CAAC,CAAC,QAAQ;oBACpB,KAAK,EAAE,CAAC,CAAC,KAAK;iBACjB,CAAC,CAAC;aACN,CAAC,CAAC;SACN,CAAC;QAEF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC;CAGJ"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ILintResult } from '../models/lint-result.js';
|
|
2
|
+
/**
|
|
3
|
+
* @description Contract for a token linter output reporter.
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export interface IReporter {
|
|
7
|
+
/**
|
|
8
|
+
* @description Unique identifier of the reporter.
|
|
9
|
+
*/
|
|
10
|
+
readonly name: string;
|
|
11
|
+
/**
|
|
12
|
+
* @description Formats and outputs the lint result.
|
|
13
|
+
*/
|
|
14
|
+
report(result: ILintResult): void;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=reporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../../src/reporters/reporter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAI5D;;;GAGG;AACH,MAAM,WAAW,SAAS;IAEtB;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;CACrC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../../src/reporters/reporter.ts"],"names":[],"mappings":"AAAA,kBAAkB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ILintResult } from '../models/lint-result.js';
|
|
2
|
+
import type { IReporter } from './reporter.js';
|
|
3
|
+
/**
|
|
4
|
+
* @description Outputs a compact summary of lint results with per-rule pass/fail counts.
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export declare class SummaryReporter implements IReporter {
|
|
8
|
+
readonly name = "summary";
|
|
9
|
+
private readonly _logger;
|
|
10
|
+
report(result: ILintResult): void;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=summary.reporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summary.reporter.d.ts","sourceRoot":"","sources":["../../src/reporters/summary.reporter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI/C;;;GAGG;AACH,qBAAa,eAAgB,YAAW,SAAS;IAI7C,SAAgB,IAAI,aAAa;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAMxC,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;CA2C3C"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// #region Imports
|
|
2
|
+
import { bold, ConsoleLogger, gray, green, red, yellow } from '@breadstone-infrastructure/utilities';
|
|
3
|
+
// #endregion
|
|
4
|
+
/**
|
|
5
|
+
* @description Outputs a compact summary of lint results with per-rule pass/fail counts.
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
export class SummaryReporter {
|
|
9
|
+
// #region Fields
|
|
10
|
+
name = 'summary';
|
|
11
|
+
_logger = new ConsoleLogger();
|
|
12
|
+
// #endregion
|
|
13
|
+
// #region Methods
|
|
14
|
+
report(result) {
|
|
15
|
+
this._logger.info('');
|
|
16
|
+
this._logger.info(bold(' Token Linter Summary'));
|
|
17
|
+
this._logger.info(gray(` ${'─'.repeat(40)}`));
|
|
18
|
+
for (const ruleResult of result.results) {
|
|
19
|
+
const count = ruleResult.findings.length;
|
|
20
|
+
if (count === 0) {
|
|
21
|
+
this._logger.info(` ${green('✓')} ${ruleResult.ruleName}`);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
const fixedCount = ruleResult.findings.filter(f => f.fixed).length;
|
|
25
|
+
const label = fixedCount > 0
|
|
26
|
+
? `${count} finding(s), ${fixedCount} fixed`
|
|
27
|
+
: `${count} finding(s)`;
|
|
28
|
+
this._logger.info(` ${yellow('✗')} ${ruleResult.ruleName} — ${label}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
this._logger.info(gray(` ${'─'.repeat(40)}`));
|
|
32
|
+
if (result.totalErrors > 0) {
|
|
33
|
+
this._logger.info(red(` ${result.totalErrors} error(s)`));
|
|
34
|
+
}
|
|
35
|
+
if (result.totalWarnings > 0) {
|
|
36
|
+
this._logger.info(yellow(` ${result.totalWarnings} warning(s)`));
|
|
37
|
+
}
|
|
38
|
+
if (result.totalFixes > 0) {
|
|
39
|
+
this._logger.info(green(` ${result.totalFixes} fix(es) applied`));
|
|
40
|
+
}
|
|
41
|
+
if (result.totalErrors === 0 && result.totalWarnings === 0) {
|
|
42
|
+
this._logger.info(green(' All checks passed.'));
|
|
43
|
+
}
|
|
44
|
+
this._logger.info(gray(` Duration: ${result.duration}ms`));
|
|
45
|
+
this._logger.info('');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=summary.reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summary.reporter.js","sourceRoot":"","sources":["../../src/reporters/summary.reporter.ts"],"names":[],"mappings":"AAAA,kBAAkB;AAElB,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,sCAAsC,CAAC;AAIrG,aAAa;AAEb;;;GAGG;AACH,MAAM,OAAO,eAAe;IAExB,iBAAiB;IAED,IAAI,GAAG,SAAS,CAAC;IAChB,OAAO,GAAG,IAAI,aAAa,EAAE,CAAC;IAE/C,aAAa;IAEb,kBAAkB;IAEX,MAAM,CAAC,MAAmB;QAC7B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACtB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,CAAC;QAClD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAE/C,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACtC,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC;YAEzC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;gBACd,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;YAChE,CAAC;iBAAM,CAAC;gBACJ,MAAM,UAAU,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;gBACnE,MAAM,KAAK,GAAG,UAAU,GAAG,CAAC;oBACxB,CAAC,CAAC,GAAG,KAAK,gBAAgB,UAAU,QAAQ;oBAC5C,CAAC,CAAC,GAAG,KAAK,aAAa,CAAC;gBAE5B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,QAAQ,MAAM,KAAK,EAAE,CAAC,CAAC;YAC5E,CAAC;QACL,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAE/C,IAAI,MAAM,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,WAAW,WAAW,CAAC,CAAC,CAAC;QAC/D,CAAC;QAED,IAAI,MAAM,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,MAAM,CAAC,aAAa,aAAa,CAAC,CAAC,CAAC;QACtE,CAAC;QAED,IAAI,MAAM,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,UAAU,kBAAkB,CAAC,CAAC,CAAC;QACvE,CAAC;QAED,IAAI,MAAM,CAAC,WAAW,KAAK,CAAC,IAAI,MAAM,CAAC,aAAa,KAAK,CAAC,EAAE,CAAC;YACzD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC;QAC5D,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC;CAGJ"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { IRule } from '../core/rule.js';
|
|
2
|
+
import type { IRuleContext } from '../models/rule-context.js';
|
|
3
|
+
import type { IRuleFinding } from '../models/rule-finding.js';
|
|
4
|
+
import type { IRuleResult } from '../models/rule-result.js';
|
|
5
|
+
import { RuleSeverity } from '../models/rule-severity.js';
|
|
6
|
+
/**
|
|
7
|
+
* @description Ensures token keys are sorted alphabetically within each file. Auto-fixable.
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export declare class AlphabeticalSortRule implements IRule {
|
|
11
|
+
readonly name = "alphabetical-sort";
|
|
12
|
+
readonly description = "Ensures token keys are sorted alphabetically. Auto-fixable.";
|
|
13
|
+
readonly defaultSeverity: RuleSeverity;
|
|
14
|
+
readonly fixable = true;
|
|
15
|
+
readonly interactive = false;
|
|
16
|
+
run(context: IRuleContext): IRuleResult;
|
|
17
|
+
fix(context: IRuleContext, findings: ReadonlyArray<IRuleFinding>): IRuleFinding[];
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=alphabetical-sort.rule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alphabetical-sort.rule.d.ts","sourceRoot":"","sources":["../../src/rules/alphabetical-sort.rule.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAI1D;;;GAGG;AACH,qBAAa,oBAAqB,YAAW,KAAK;IAI9C,SAAgB,IAAI,uBAAuB;IAC3C,SAAgB,WAAW,iEAAiE;IAC5F,SAAgB,eAAe,EAAE,YAAY,CAAwB;IACrE,SAAgB,OAAO,QAAQ;IAC/B,SAAgB,WAAW,SAAS;IAM7B,GAAG,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW;IAsCvC,GAAG,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,CAAC,YAAY,CAAC,GAAG,YAAY,EAAE;CAkC3F"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// #region Imports
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import { RuleSeverity } from '../models/rule-severity.js';
|
|
4
|
+
// #endregion
|
|
5
|
+
/**
|
|
6
|
+
* @description Ensures token keys are sorted alphabetically within each file. Auto-fixable.
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export class AlphabeticalSortRule {
|
|
10
|
+
// #region Fields
|
|
11
|
+
name = 'alphabetical-sort';
|
|
12
|
+
description = 'Ensures token keys are sorted alphabetically. Auto-fixable.';
|
|
13
|
+
defaultSeverity = RuleSeverity.Warning;
|
|
14
|
+
fixable = true;
|
|
15
|
+
interactive = false;
|
|
16
|
+
// #endregion
|
|
17
|
+
// #region Methods
|
|
18
|
+
run(context) {
|
|
19
|
+
const findings = [];
|
|
20
|
+
for (const entry of context.entries) {
|
|
21
|
+
const keys = Object.keys(entry.content);
|
|
22
|
+
if (keys.length === 0) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const sortedKeys = [...keys].sort((a, b) => a.localeCompare(b));
|
|
26
|
+
let needsSort = !keys.every((key, i) => key === sortedKeys[i]);
|
|
27
|
+
// Also check $includes array sorting
|
|
28
|
+
if (!needsSort && Array.isArray(entry.content['$includes'])) {
|
|
29
|
+
const includes = entry.content['$includes'];
|
|
30
|
+
const sortedIncludes = [...includes].sort((a, b) => a.localeCompare(b));
|
|
31
|
+
needsSort = !includes.every((val, i) => val === sortedIncludes[i]);
|
|
32
|
+
}
|
|
33
|
+
if (!needsSort) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
findings.push({
|
|
37
|
+
component: entry.component,
|
|
38
|
+
theme: entry.theme,
|
|
39
|
+
message: `Keys in '${entry.component}' (${entry.theme}) are not sorted alphabetically.`,
|
|
40
|
+
severity: this.defaultSeverity,
|
|
41
|
+
filePath: entry.filePath,
|
|
42
|
+
fixed: false,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return { ruleName: this.name, findings, duration: 0 };
|
|
46
|
+
}
|
|
47
|
+
fix(context, findings) {
|
|
48
|
+
const entryMap = new Map(context.entries.map(e => [e.filePath, e]));
|
|
49
|
+
const result = [];
|
|
50
|
+
for (const finding of findings) {
|
|
51
|
+
const entry = finding.filePath ? entryMap.get(finding.filePath) : undefined;
|
|
52
|
+
if (!entry) {
|
|
53
|
+
result.push(finding);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const keys = Object.keys(entry.content);
|
|
57
|
+
const sortedKeys = [...keys].sort((a, b) => a.localeCompare(b));
|
|
58
|
+
const sorted = sortedKeys.reduce((acc, key) => {
|
|
59
|
+
acc[key] = entry.content[key];
|
|
60
|
+
return acc;
|
|
61
|
+
}, {});
|
|
62
|
+
// Sort $includes array values
|
|
63
|
+
if (Array.isArray(entry.content['$includes'])) {
|
|
64
|
+
sorted['$includes'] = [...entry.content['$includes']].sort((a, b) => a.localeCompare(b));
|
|
65
|
+
}
|
|
66
|
+
fs.writeFileSync(entry.filePath, JSON.stringify(sorted, null, 2) + '\n', 'utf-8');
|
|
67
|
+
result.push({ ...finding, fixed: true });
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=alphabetical-sort.rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alphabetical-sort.rule.js","sourceRoot":"","sources":["../../src/rules/alphabetical-sort.rule.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { IRule } from '../core/rule.js';
|
|
2
|
+
import type { IRuleContext } from '../models/rule-context.js';
|
|
3
|
+
import type { IRuleFinding } from '../models/rule-finding.js';
|
|
4
|
+
import type { IRuleResult } from '../models/rule-result.js';
|
|
5
|
+
import { RuleSeverity } from '../models/rule-severity.js';
|
|
6
|
+
/**
|
|
7
|
+
* @description Ensures all themes contain the same set of component token files.
|
|
8
|
+
*
|
|
9
|
+
* @example Interactive prompt
|
|
10
|
+
* ```
|
|
11
|
+
* ? Component 'card' is missing in theme 'joy'.
|
|
12
|
+
* > Create from 'memphis'
|
|
13
|
+
* Create from 'cosmopolitan'
|
|
14
|
+
* Skip
|
|
15
|
+
* Skip all remaining
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
export declare class ComponentPresenceRule implements IRule {
|
|
21
|
+
readonly name = "component-presence";
|
|
22
|
+
readonly description = "Ensures all themes contain the same set of component token files.";
|
|
23
|
+
readonly defaultSeverity: RuleSeverity;
|
|
24
|
+
readonly fixable = false;
|
|
25
|
+
readonly interactive = true;
|
|
26
|
+
run(context: IRuleContext): IRuleResult;
|
|
27
|
+
interact(context: IRuleContext, findings: ReadonlyArray<IRuleFinding>): Promise<IRuleFinding[]>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=component-presence.rule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-presence.rule.d.ts","sourceRoot":"","sources":["../../src/rules/component-presence.rule.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAM1D;;;;;;;;;;;;;GAaG;AACH,qBAAa,qBAAsB,YAAW,KAAK;IAI/C,SAAgB,IAAI,wBAAwB;IAC5C,SAAgB,WAAW,uEAAuE;IAClG,SAAgB,eAAe,EAAE,YAAY,CAAsB;IACnE,SAAgB,OAAO,SAAS;IAChC,SAAgB,WAAW,QAAQ;IAM5B,GAAG,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW;IA+BjC,QAAQ,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;CAiE/G"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// #region Imports
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { promptSelect, SKIP, SKIP_ALL } from '../core/interaction.js';
|
|
5
|
+
import { RuleSeverity } from '../models/rule-severity.js';
|
|
6
|
+
import { replaceThemePrefix } from '../utils.js';
|
|
7
|
+
// #endregion
|
|
8
|
+
/**
|
|
9
|
+
* @description Ensures all themes contain the same set of component token files.
|
|
10
|
+
*
|
|
11
|
+
* @example Interactive prompt
|
|
12
|
+
* ```
|
|
13
|
+
* ? Component 'card' is missing in theme 'joy'.
|
|
14
|
+
* > Create from 'memphis'
|
|
15
|
+
* Create from 'cosmopolitan'
|
|
16
|
+
* Skip
|
|
17
|
+
* Skip all remaining
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
export class ComponentPresenceRule {
|
|
23
|
+
// #region Fields
|
|
24
|
+
name = 'component-presence';
|
|
25
|
+
description = 'Ensures all themes contain the same set of component token files.';
|
|
26
|
+
defaultSeverity = RuleSeverity.Error;
|
|
27
|
+
fixable = false;
|
|
28
|
+
interactive = true;
|
|
29
|
+
// #endregion
|
|
30
|
+
// #region Methods
|
|
31
|
+
run(context) {
|
|
32
|
+
const findings = [];
|
|
33
|
+
const themeMap = new Map();
|
|
34
|
+
for (const theme of context.themes) {
|
|
35
|
+
themeMap.set(theme, new Set());
|
|
36
|
+
}
|
|
37
|
+
for (const entry of context.entries) {
|
|
38
|
+
themeMap.get(entry.theme)?.add(entry.component);
|
|
39
|
+
}
|
|
40
|
+
const allComponents = new Set(context.entries.map(e => e.component));
|
|
41
|
+
for (const component of allComponents) {
|
|
42
|
+
for (const theme of context.themes) {
|
|
43
|
+
if (!themeMap.get(theme)?.has(component)) {
|
|
44
|
+
findings.push({
|
|
45
|
+
component,
|
|
46
|
+
theme,
|
|
47
|
+
message: `Component '${component}' is missing in theme '${theme}'.`,
|
|
48
|
+
severity: this.defaultSeverity,
|
|
49
|
+
fixed: false,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return { ruleName: this.name, findings, duration: 0 };
|
|
55
|
+
}
|
|
56
|
+
async interact(context, findings) {
|
|
57
|
+
const result = [];
|
|
58
|
+
let skipAll = false;
|
|
59
|
+
for (const finding of findings) {
|
|
60
|
+
if (skipAll) {
|
|
61
|
+
result.push(finding);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const sourceEntries = context.entries.filter((e) => e.component === finding.component && e.theme !== finding.theme);
|
|
65
|
+
if (sourceEntries.length === 0) {
|
|
66
|
+
result.push(finding);
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const choices = sourceEntries.map((entry) => ({
|
|
70
|
+
name: `create-from-${entry.theme}`,
|
|
71
|
+
message: `Create from '${entry.theme}'`,
|
|
72
|
+
}));
|
|
73
|
+
const action = await promptSelect(finding.message, choices);
|
|
74
|
+
if (action === SKIP_ALL) {
|
|
75
|
+
skipAll = true;
|
|
76
|
+
result.push(finding);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (action === SKIP) {
|
|
80
|
+
result.push(finding);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const sourceTheme = action.startsWith('create-from-') ? action.substring(12) : undefined;
|
|
84
|
+
const sourceEntry = sourceTheme ? sourceEntries.find((e) => e.theme === sourceTheme) : undefined;
|
|
85
|
+
if (sourceEntry) {
|
|
86
|
+
const targetPath = sourceEntry.filePath.replace(`/${sourceEntry.theme}/`, `/${finding.theme}/`);
|
|
87
|
+
const targetDir = path.dirname(targetPath);
|
|
88
|
+
if (!fs.existsSync(targetDir)) {
|
|
89
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
90
|
+
}
|
|
91
|
+
const newContent = replaceThemePrefix(sourceEntry.content, sourceEntry.theme, finding.theme);
|
|
92
|
+
fs.writeFileSync(targetPath, JSON.stringify(newContent, null, 2) + '\n', 'utf-8');
|
|
93
|
+
result.push({ ...finding, fixed: true });
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
result.push(finding);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=component-presence.rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-presence.rule.js","sourceRoot":"","sources":["../../src/rules/component-presence.rule.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { IRule } from '../core/rule.js';
|
|
2
|
+
import type { IRuleContext } from '../models/rule-context.js';
|
|
3
|
+
import type { IRuleResult } from '../models/rule-result.js';
|
|
4
|
+
import { RuleSeverity } from '../models/rule-severity.js';
|
|
5
|
+
/**
|
|
6
|
+
* @description Detects duplicate token values within the same component that could be abstracted into a shared variable.
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export declare class DuplicateValueRule implements IRule {
|
|
10
|
+
readonly name = "duplicate-value";
|
|
11
|
+
readonly description = "Detects duplicate token values within the same component that could be abstracted.";
|
|
12
|
+
readonly defaultSeverity: RuleSeverity;
|
|
13
|
+
readonly fixable = false;
|
|
14
|
+
readonly interactive = false;
|
|
15
|
+
run(context: IRuleContext): IRuleResult;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=duplicate-value.rule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duplicate-value.rule.d.ts","sourceRoot":"","sources":["../../src/rules/duplicate-value.rule.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAK1D;;;GAGG;AACH,qBAAa,kBAAmB,YAAW,KAAK;IAI5C,SAAgB,IAAI,qBAAqB;IACzC,SAAgB,WAAW,wFAAwF;IACnH,SAAgB,eAAe,EAAE,YAAY,CAAqB;IAClE,SAAgB,OAAO,SAAS;IAChC,SAAgB,WAAW,SAAS;IAM7B,GAAG,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW;CAuCjD"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// #region Imports
|
|
2
|
+
import { RuleSeverity } from '../models/rule-severity.js';
|
|
3
|
+
import { flattenTokenEntries } from '../utils.js';
|
|
4
|
+
// #endregion
|
|
5
|
+
/**
|
|
6
|
+
* @description Detects duplicate token values within the same component that could be abstracted into a shared variable.
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export class DuplicateValueRule {
|
|
10
|
+
// #region Fields
|
|
11
|
+
name = 'duplicate-value';
|
|
12
|
+
description = 'Detects duplicate token values within the same component that could be abstracted.';
|
|
13
|
+
defaultSeverity = RuleSeverity.Info;
|
|
14
|
+
fixable = false;
|
|
15
|
+
interactive = false;
|
|
16
|
+
// #endregion
|
|
17
|
+
// #region Methods
|
|
18
|
+
run(context) {
|
|
19
|
+
const findings = [];
|
|
20
|
+
for (const entry of context.entries) {
|
|
21
|
+
const flatEntries = flattenTokenEntries(entry.content);
|
|
22
|
+
const valueMap = new Map();
|
|
23
|
+
for (const { key, value } of flatEntries) {
|
|
24
|
+
if (typeof value !== 'string') {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const trimmed = value.trim();
|
|
28
|
+
if (!valueMap.has(trimmed)) {
|
|
29
|
+
valueMap.set(trimmed, []);
|
|
30
|
+
}
|
|
31
|
+
valueMap.get(trimmed).push(key);
|
|
32
|
+
}
|
|
33
|
+
for (const [value, keys] of valueMap.entries()) {
|
|
34
|
+
if (keys.length > 1) {
|
|
35
|
+
findings.push({
|
|
36
|
+
component: entry.component,
|
|
37
|
+
theme: entry.theme,
|
|
38
|
+
message: `Duplicate value '${value}' used by keys: ${keys.join(', ')}. Consider extracting to a shared variable.`,
|
|
39
|
+
severity: this.defaultSeverity,
|
|
40
|
+
filePath: entry.filePath,
|
|
41
|
+
fixed: false,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return { ruleName: this.name, findings, duration: 0 };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=duplicate-value.rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duplicate-value.rule.js","sourceRoot":"","sources":["../../src/rules/duplicate-value.rule.ts"],"names":[],"mappings":"AAAA,kBAAkB;AAMlB,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,aAAa;AAEb;;;GAGG;AACH,MAAM,OAAO,kBAAkB;IAE3B,iBAAiB;IAED,IAAI,GAAG,iBAAiB,CAAC;IACzB,WAAW,GAAG,oFAAoF,CAAC;IACnG,eAAe,GAAiB,YAAY,CAAC,IAAI,CAAC;IAClD,OAAO,GAAG,KAAK,CAAC;IAChB,WAAW,GAAG,KAAK,CAAC;IAEpC,aAAa;IAEb,kBAAkB;IAEX,GAAG,CAAC,OAAqB;QAC5B,MAAM,QAAQ,GAAmB,EAAE,CAAC;QAEpC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YAClC,MAAM,WAAW,GAAG,mBAAmB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACvD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAoB,CAAC;YAE7C,KAAK,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,WAAW,EAAE,CAAC;gBACvC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;oBAC5B,SAAS;gBACb,CAAC;gBAED,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;gBAE7B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;oBACzB,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBAC9B,CAAC;gBAED,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACrC,CAAC;YAED,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;gBAC7C,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAClB,QAAQ,CAAC,IAAI,CAAC;wBACV,SAAS,EAAE,KAAK,CAAC,SAAS;wBAC1B,KAAK,EAAE,KAAK,CAAC,KAAK;wBAClB,OAAO,EAAE,oBAAoB,KAAK,mBAAmB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,6CAA6C;wBACjH,QAAQ,EAAE,IAAI,CAAC,eAAe;wBAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;wBACxB,KAAK,EAAE,KAAK;qBACf,CAAC,CAAC;gBACP,CAAC;YACL,CAAC;QACL,CAAC;QAED,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IAC1D,CAAC;CAGJ"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { IRule } from '../core/rule.js';
|
|
2
|
+
import type { IRuleContext } from '../models/rule-context.js';
|
|
3
|
+
import type { IRuleFinding } from '../models/rule-finding.js';
|
|
4
|
+
import type { IRuleResult } from '../models/rule-result.js';
|
|
5
|
+
import { RuleSeverity } from '../models/rule-severity.js';
|
|
6
|
+
import type { IRuleOptionsEntry, IRuleOptionValues } from '../models/token-linter-config.js';
|
|
7
|
+
/**
|
|
8
|
+
* @description Options for the `empty-json` rule.
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
export interface IEmptyJsonRuleOptions extends IRuleOptionValues {
|
|
12
|
+
/**
|
|
13
|
+
* @description When `true`, files that contain only `$includes` (but no token keys) are not flagged.
|
|
14
|
+
* @default false
|
|
15
|
+
*/
|
|
16
|
+
readonly allowIncludes?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* @description Creates typed rule options for the `empty-json` rule.
|
|
20
|
+
* @public
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```js
|
|
24
|
+
* ruleOptions: {
|
|
25
|
+
* ...emptyJsonRuleOptions({ allowIncludes: true }),
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function emptyJsonRuleOptions(options: IEmptyJsonRuleOptions): IRuleOptionsEntry;
|
|
30
|
+
/**
|
|
31
|
+
* @description Detects component token files with no token definitions.
|
|
32
|
+
*
|
|
33
|
+
* @example Interactive prompt
|
|
34
|
+
* ```
|
|
35
|
+
* ? Component 'divider' in theme 'joy' has no token definitions.
|
|
36
|
+
* > Delete file
|
|
37
|
+
* Skip
|
|
38
|
+
* Skip all remaining
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* @public
|
|
42
|
+
*/
|
|
43
|
+
export declare class EmptyJsonRule implements IRule {
|
|
44
|
+
readonly name = "empty-json";
|
|
45
|
+
readonly description = "Detects component token files with no token definitions.";
|
|
46
|
+
readonly defaultSeverity: RuleSeverity;
|
|
47
|
+
readonly fixable = false;
|
|
48
|
+
readonly interactive = true;
|
|
49
|
+
run(context: IRuleContext): IRuleResult;
|
|
50
|
+
interact(_context: IRuleContext, findings: ReadonlyArray<IRuleFinding>): Promise<IRuleFinding[]>;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=empty-json.rule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"empty-json.rule.d.ts","sourceRoot":"","sources":["../../src/rules/empty-json.rule.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAO7F;;;GAGG;AACH,MAAM,WAAW,qBAAsB,SAAQ,iBAAiB;IAE5D;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CACpC;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,iBAAiB,CAEtF;AAID;;;;;;;;;;;;GAYG;AACH,qBAAa,aAAc,YAAW,KAAK;IAIvC,SAAgB,IAAI,gBAAgB;IACpC,SAAgB,WAAW,8DAA8D;IACzF,SAAgB,eAAe,EAAE,YAAY,CAAwB;IACrE,SAAgB,OAAO,SAAS;IAChC,SAAgB,WAAW,QAAQ;IAM5B,GAAG,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW;IA2BjC,QAAQ,CAAC,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;CA4ChH"}
|