@better-i18n/cli 0.2.2 → 0.2.3
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 +53 -0
- package/dist/analyzer/index.d.ts.map +1 -1
- package/dist/analyzer/index.js +25 -0
- package/dist/analyzer/index.js.map +1 -1
- package/dist/analyzer/types.d.ts +1 -0
- package/dist/analyzer/types.d.ts.map +1 -1
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +2 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/context/detector.js +16 -0
- package/dist/context/detector.js.map +1 -1
- package/dist/doctor/index.d.ts +2 -0
- package/dist/doctor/index.d.ts.map +1 -1
- package/dist/doctor/index.js +109 -9
- package/dist/doctor/index.js.map +1 -1
- package/dist/doctor/score.d.ts +12 -6
- package/dist/doctor/score.d.ts.map +1 -1
- package/dist/doctor/score.js +41 -14
- package/dist/doctor/score.js.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/reporters/doctor-eslint.d.ts.map +1 -1
- package/dist/reporters/doctor-eslint.js +60 -16
- package/dist/reporters/doctor-eslint.js.map +1 -1
- package/dist/reporters/doctor-report.d.ts +9 -4
- package/dist/reporters/doctor-report.d.ts.map +1 -1
- package/dist/reporters/doctor-report.js +69 -9
- package/dist/reporters/doctor-report.js.map +1 -1
- package/dist/rules/categories.d.ts.map +1 -1
- package/dist/rules/categories.js +9 -0
- package/dist/rules/categories.js.map +1 -1
- package/dist/rules/health/missing-translations.js +2 -2
- package/dist/rules/health/missing-translations.js.map +1 -1
- package/dist/rules/health/orphan-keys.js +2 -2
- package/dist/rules/health/orphan-keys.js.map +1 -1
- package/dist/rules/health/placeholder-mismatch.js +3 -3
- package/dist/rules/health/placeholder-mismatch.js.map +1 -1
- package/dist/rules/registry.d.ts +2 -0
- package/dist/rules/registry.d.ts.map +1 -1
- package/dist/utils/key-comparison.d.ts.map +1 -1
- package/dist/utils/key-comparison.js +5 -1
- package/dist/utils/key-comparison.js.map +1 -1
- package/package.json +1 -1
package/dist/doctor/score.js
CHANGED
|
@@ -7,12 +7,18 @@
|
|
|
7
7
|
* per occurrence because each hardcoded string is an independent task
|
|
8
8
|
* that requires its own t() wrapping.
|
|
9
9
|
*
|
|
10
|
-
* Overall score: 100 - (errors x 3.0) - (
|
|
11
|
-
* Category score: 100 - (errors x 5.0) - (
|
|
10
|
+
* Overall score: 100 - (errors x 3.0) - Σ min(ruleWarnings x 0.15, 20)
|
|
11
|
+
* Category score: 100 - (errors x 5.0) - Σ min(ruleWarnings x 0.5, 80)
|
|
12
|
+
*
|
|
13
|
+
* Per-rule warning cap: Each rule can penalize the overall score by at most
|
|
14
|
+
* MAX_RULE_WARNING_PENALTY (20) points, and each category by at most
|
|
15
|
+
* MAX_RULE_CAT_PENALTY (80) points. This prevents a single rule with
|
|
16
|
+
* thousands of warnings (e.g. missing-in-remote) from zeroing the score.
|
|
17
|
+
* Errors are NOT capped.
|
|
12
18
|
*
|
|
13
19
|
* Calibration targets:
|
|
14
20
|
* 0E, 0W → 100
|
|
15
|
-
* 0E, 104W → 84
|
|
21
|
+
* 0E, 104W → 84 (single rule, cap threshold = 133)
|
|
16
22
|
* 10E, 20W → 67
|
|
17
23
|
* 5E, 0W → 85
|
|
18
24
|
* 1E, 0W → 97
|
|
@@ -22,10 +28,14 @@
|
|
|
22
28
|
const ERROR_PENALTY = 3.0;
|
|
23
29
|
/** Per-occurrence penalty for warnings on the overall score */
|
|
24
30
|
const WARNING_PENALTY = 0.15;
|
|
31
|
+
/** Max penalty any single rule's warnings can contribute to the overall score */
|
|
32
|
+
const MAX_RULE_WARNING_PENALTY = 20;
|
|
25
33
|
/** Per-occurrence penalty for errors within a category */
|
|
26
34
|
const CAT_ERROR_PENALTY = 5.0;
|
|
27
35
|
/** Per-occurrence penalty for warnings within a category */
|
|
28
36
|
const CAT_WARNING_PENALTY = 0.5;
|
|
37
|
+
/** Max penalty any single rule's warnings can contribute to a category score */
|
|
38
|
+
const MAX_RULE_CAT_PENALTY = 80;
|
|
29
39
|
/** Default pass/fail threshold */
|
|
30
40
|
const PASS_THRESHOLD = 70;
|
|
31
41
|
// ── Calculator ──────────────────────────────────────────────────────
|
|
@@ -33,31 +43,41 @@ const PASS_THRESHOLD = 70;
|
|
|
33
43
|
* Calculate health score from diagnostics.
|
|
34
44
|
*
|
|
35
45
|
* Algorithm:
|
|
36
|
-
* 1. Count total errors and warnings (info ignored)
|
|
37
|
-
* 2. Overall = 100 - (errors x 3.0) - (
|
|
38
|
-
* 3. Per category = 100 - (catErrors x 5.0) - (
|
|
46
|
+
* 1. Count total errors and per-rule warnings (info ignored)
|
|
47
|
+
* 2. Overall = 100 - (errors x 3.0) - Σ min(ruleWarnings x 0.15, 20), clamped [0,100]
|
|
48
|
+
* 3. Per category = 100 - (catErrors x 5.0) - Σ min(ruleWarnings x 0.5, 80), clamped [0,100]
|
|
39
49
|
* 4. passed = overall >= threshold
|
|
40
50
|
*/
|
|
41
51
|
export function calculateHealthScore(diagnostics, passThreshold = PASS_THRESHOLD) {
|
|
42
52
|
// Count totals
|
|
43
53
|
let totalErrors = 0;
|
|
44
|
-
|
|
54
|
+
// Per-rule warning counts (for capped overall penalty)
|
|
55
|
+
const ruleWarningCounts = new Map();
|
|
45
56
|
// Count per category
|
|
46
57
|
const catErrors = new Map();
|
|
47
|
-
|
|
58
|
+
// Per-category, per-rule warning counts (for capped category penalty)
|
|
59
|
+
const catRuleWarnings = new Map();
|
|
48
60
|
for (const d of diagnostics) {
|
|
49
61
|
if (d.severity === "error") {
|
|
50
62
|
totalErrors++;
|
|
51
63
|
catErrors.set(d.category, (catErrors.get(d.category) || 0) + 1);
|
|
52
64
|
}
|
|
53
65
|
else if (d.severity === "warning") {
|
|
54
|
-
|
|
55
|
-
|
|
66
|
+
ruleWarningCounts.set(d.rule, (ruleWarningCounts.get(d.rule) || 0) + 1);
|
|
67
|
+
if (!catRuleWarnings.has(d.category)) {
|
|
68
|
+
catRuleWarnings.set(d.category, new Map());
|
|
69
|
+
}
|
|
70
|
+
const ruleMap = catRuleWarnings.get(d.category);
|
|
71
|
+
ruleMap.set(d.rule, (ruleMap.get(d.rule) || 0) + 1);
|
|
56
72
|
}
|
|
57
73
|
// "info" diagnostics don't affect score
|
|
58
74
|
}
|
|
59
|
-
// Overall score —
|
|
60
|
-
|
|
75
|
+
// Overall score — per-rule capped warning penalty
|
|
76
|
+
let totalWarningPenalty = 0;
|
|
77
|
+
for (const count of ruleWarningCounts.values()) {
|
|
78
|
+
totalWarningPenalty += Math.min(count * WARNING_PENALTY, MAX_RULE_WARNING_PENALTY);
|
|
79
|
+
}
|
|
80
|
+
const rawTotal = 100 - totalErrors * ERROR_PENALTY - totalWarningPenalty;
|
|
61
81
|
const total = clamp(Math.round(rawTotal));
|
|
62
82
|
// Per-category scores
|
|
63
83
|
const allCategories = [
|
|
@@ -70,8 +90,15 @@ export function calculateHealthScore(diagnostics, passThreshold = PASS_THRESHOLD
|
|
|
70
90
|
const categories = {};
|
|
71
91
|
for (const cat of allCategories) {
|
|
72
92
|
const errors = catErrors.get(cat) || 0;
|
|
73
|
-
|
|
74
|
-
|
|
93
|
+
// Sum per-rule capped warning penalties for this category
|
|
94
|
+
let catWarningPenalty = 0;
|
|
95
|
+
const ruleMap = catRuleWarnings.get(cat);
|
|
96
|
+
if (ruleMap) {
|
|
97
|
+
for (const count of ruleMap.values()) {
|
|
98
|
+
catWarningPenalty += Math.min(count * CAT_WARNING_PENALTY, MAX_RULE_CAT_PENALTY);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const rawCat = 100 - errors * CAT_ERROR_PENALTY - catWarningPenalty;
|
|
75
102
|
categories[cat] = clamp(Math.round(rawCat));
|
|
76
103
|
}
|
|
77
104
|
return {
|
package/dist/doctor/score.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"score.js","sourceRoot":"","sources":["../../src/doctor/score.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"score.js","sourceRoot":"","sources":["../../src/doctor/score.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,uEAAuE;AAEvE,6DAA6D;AAC7D,MAAM,aAAa,GAAG,GAAG,CAAC;AAC1B,+DAA+D;AAC/D,MAAM,eAAe,GAAG,IAAI,CAAC;AAE7B,iFAAiF;AACjF,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAEpC,0DAA0D;AAC1D,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAC9B,4DAA4D;AAC5D,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEhC,gFAAgF;AAChF,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEhC,kCAAkC;AAClC,MAAM,cAAc,GAAG,EAAE,CAAC;AAe1B,uEAAuE;AAEvE;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAClC,WAA6B,EAC7B,aAAa,GAAG,cAAc;IAE9B,eAAe;IACf,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,uDAAuD;IACvD,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEpD,qBAAqB;IACrB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5C,sEAAsE;IACtE,MAAM,eAAe,GAAG,IAAI,GAAG,EAA+B,CAAC;IAE/D,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YAC3B,WAAW,EAAE,CAAC;YACd,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAClE,CAAC;aAAM,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACpC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACxE,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACrC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;YAC7C,CAAC;YACD,MAAM,OAAO,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAE,CAAC;YACjD,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACtD,CAAC;QACD,wCAAwC;IAC1C,CAAC;IAED,kDAAkD;IAClD,IAAI,mBAAmB,GAAG,CAAC,CAAC;IAC5B,KAAK,MAAM,KAAK,IAAI,iBAAiB,CAAC,MAAM,EAAE,EAAE,CAAC;QAC/C,mBAAmB,IAAI,IAAI,CAAC,GAAG,CAC7B,KAAK,GAAG,eAAe,EACvB,wBAAwB,CACzB,CAAC;IACJ,CAAC;IACD,MAAM,QAAQ,GAAG,GAAG,GAAG,WAAW,GAAG,aAAa,GAAG,mBAAmB,CAAC;IACzE,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;IAE1C,sBAAsB;IACtB,MAAM,aAAa,GAAG;QACpB,UAAU;QACV,SAAS;QACT,MAAM;QACN,WAAW;QACX,aAAa;KACd,CAAC;IAEF,MAAM,UAAU,GAA2B,EAAE,CAAC;IAE9C,KAAK,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAEvC,0DAA0D;QAC1D,IAAI,iBAAiB,GAAG,CAAC,CAAC;QAC1B,MAAM,OAAO,GAAG,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,OAAO,EAAE,CAAC;YACZ,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;gBACrC,iBAAiB,IAAI,IAAI,CAAC,GAAG,CAC3B,KAAK,GAAG,mBAAmB,EAC3B,oBAAoB,CACrB,CAAC;YACJ,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,GAAG,GAAG,MAAM,GAAG,iBAAiB,GAAG,iBAAiB,CAAC;QACpE,UAAU,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO;QACL,KAAK;QACL,UAAU;QACV,MAAM,EAAE,KAAK,IAAI,aAAa;QAC9B,aAAa;KACd,CAAC;AACJ,CAAC;AAED,uEAAuE;AAEvE,SAAS,KAAK,CAAC,KAAa,EAAE,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,GAAG;IAC9C,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;AAC7C,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -61,9 +61,11 @@ program
|
|
|
61
61
|
.option("-d, --dir <path>", "Directory to scan (default: current directory)")
|
|
62
62
|
.option("-f, --format <type>", "Output format: eslint, json", "eslint")
|
|
63
63
|
.option("--ci", "CI mode: exit with error code if health score below threshold")
|
|
64
|
-
.option("--report", "Upload results to Better i18n portal (requires GitHub Actions OIDC)")
|
|
64
|
+
.option("--report", "Upload results to Better i18n portal (requires GitHub Actions OIDC or --api-key)")
|
|
65
|
+
.option("--api-key <key>", "Better Auth API key for non-GitHub CI (local dev, GitLab, Jenkins)")
|
|
65
66
|
.option("--skip-code", "Skip AST code analysis (hardcoded strings)")
|
|
66
67
|
.option("--skip-health", "Skip translation file health checks")
|
|
68
|
+
.option("--skip-sync", "Skip remote CDN comparison")
|
|
67
69
|
.option("--verbose", "Show detailed output")
|
|
68
70
|
.action(doctorCommand);
|
|
69
71
|
program.parse();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO;KACJ,IAAI,CAAC,aAAa,CAAC;KACnB,WAAW,CACV,sEAAsE,CACvE;KACA,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,4CAA4C,CAAC;KACzD,MAAM,CAAC,kBAAkB,EAAE,gDAAgD,CAAC;KAC5E,MAAM,CAAC,qBAAqB,EAAE,6BAA6B,EAAE,QAAQ,CAAC;KACtE,MAAM,CACL,uBAAuB,EACvB,oDAAoD,EACpD,QAAQ,CACT;KACA,MAAM,CAAC,OAAO,EAAE,wCAAwC,CAAC;KACzD,MAAM,CAAC,MAAM,EAAE,+CAA+C,CAAC;KAC/D,MAAM,CAAC,UAAU,EAAE,4BAA4B,CAAC;KAChD,MAAM,CAAC,WAAW,EAAE,sBAAsB,CAAC;KAC3C,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,uDAAuD,CAAC;KACpE,MAAM,CAAC,kBAAkB,EAAE,gDAAgD,CAAC;KAC5E,MAAM,CAAC,qBAAqB,EAAE,6BAA6B,EAAE,QAAQ,CAAC;KACtE,MAAM,CAAC,WAAW,EAAE,0CAA0C,CAAC;KAC/D,MAAM,CAAC,WAAW,EAAE,sBAAsB,CAAC;KAC3C,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,8CAA8C;AAC9C,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,6DAA6D,CAAC;KAC1E,MAAM,CAAC,kBAAkB,EAAE,gDAAgD,CAAC;KAC5E,MAAM,CAAC,qBAAqB,EAAE,6BAA6B,EAAE,QAAQ,CAAC;KACtE,MAAM,CAAC,WAAW,EAAE,sBAAsB,CAAC;KAC3C,MAAM,CAAC,YAAY,CAAC,CAAC;AAExB,OAAO;KACJ,OAAO,CAAC,eAAe,CAAC;KACxB,WAAW,CAAC,gEAAgE,CAAC;KAC7E,MAAM,CAAC,kBAAkB,EAAE,gDAAgD,CAAC;KAC5E,MAAM,CAAC,qBAAqB,EAAE,6BAA6B,EAAE,QAAQ,CAAC;KACtE,MAAM,CAAC,WAAW,EAAE,sBAAsB,CAAC;KAC3C,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAE/B,OAAO;KACJ,OAAO,CAAC,cAAc,CAAC;KACvB,WAAW,CACV,wEAAwE,CACzE;KACA,MAAM,CAAC,kBAAkB,EAAE,gDAAgD,CAAC;KAC5E,MAAM,CAAC,qBAAqB,EAAE,6BAA6B,EAAE,QAAQ,CAAC;KACtE,MAAM,CAAC,WAAW,EAAE,sBAAsB,CAAC;KAC3C,MAAM,CAAC,kBAAkB,CAAC,CAAC;AAE9B,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,gFAAgF,CAAC;KAC7F,MAAM,CAAC,kBAAkB,EAAE,gDAAgD,CAAC;KAC5E,MAAM,CAAC,qBAAqB,EAAE,6BAA6B,EAAE,QAAQ,CAAC;KACtE,MAAM,CAAC,MAAM,EAAE,+DAA+D,CAAC;KAC/E,MAAM,CAAC,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor-eslint.d.ts","sourceRoot":"","sources":["../../src/reporters/doctor-eslint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"doctor-eslint.d.ts","sourceRoot":"","sources":["../../src/reporters/doctor-eslint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAqHvD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,UAAQ,GAAG,IAAI,CA2HxE"}
|
|
@@ -56,12 +56,21 @@ function renderCategoryLine(category, score, count) {
|
|
|
56
56
|
const countStr = count > 0 ? dim(` (${count} issues)`) : dim(" (clean)");
|
|
57
57
|
return ` ${dim(padded)} ${colorFn(scoreStr)}${countStr}`;
|
|
58
58
|
}
|
|
59
|
+
// ── Display Limits ──────────────────────────────────────────────────
|
|
60
|
+
const MAX_RULE_GROUPS = 5;
|
|
61
|
+
const MAX_ITEMS_PER_GROUP = 5;
|
|
62
|
+
const MAX_ITEMS_PER_GROUP_VERBOSE = 20;
|
|
59
63
|
// ── Diagnostic Helpers (react-doctor pattern) ───────────────────────
|
|
60
64
|
const SEVERITY_ORDER = {
|
|
61
65
|
error: 0,
|
|
62
66
|
warning: 1,
|
|
63
67
|
info: 2,
|
|
64
68
|
};
|
|
69
|
+
/** Rules that produce key-based diagnostics (namespace/key format) */
|
|
70
|
+
const KEY_BASED_RULES = new Set([
|
|
71
|
+
"missing-in-remote",
|
|
72
|
+
"unused-remote-key",
|
|
73
|
+
]);
|
|
65
74
|
function colorizeBySeverity(text, severity) {
|
|
66
75
|
if (severity === "error")
|
|
67
76
|
return red(text);
|
|
@@ -69,9 +78,13 @@ function colorizeBySeverity(text, severity) {
|
|
|
69
78
|
return yellow(text);
|
|
70
79
|
return dim(text);
|
|
71
80
|
}
|
|
72
|
-
function
|
|
81
|
+
function sortBySeverityAndCount(groups) {
|
|
73
82
|
return [...groups].sort(([, a], [, b]) => {
|
|
74
|
-
|
|
83
|
+
const sevDiff = (SEVERITY_ORDER[a[0].severity] ?? 2) -
|
|
84
|
+
(SEVERITY_ORDER[b[0].severity] ?? 2);
|
|
85
|
+
if (sevDiff !== 0)
|
|
86
|
+
return sevDiff;
|
|
87
|
+
return b.length - a.length; // more issues first
|
|
75
88
|
});
|
|
76
89
|
}
|
|
77
90
|
function buildFileLineMap(diagnostics) {
|
|
@@ -84,6 +97,16 @@ function buildFileLineMap(diagnostics) {
|
|
|
84
97
|
}
|
|
85
98
|
return fileLines;
|
|
86
99
|
}
|
|
100
|
+
function buildKeyEntries(diagnostics) {
|
|
101
|
+
const entries = [];
|
|
102
|
+
for (const d of diagnostics) {
|
|
103
|
+
if (d.key) {
|
|
104
|
+
const prefix = d.namespace ? `${d.namespace}/` : "";
|
|
105
|
+
entries.push(`${prefix}${d.key}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return entries;
|
|
109
|
+
}
|
|
87
110
|
// ── Main Reporter ───────────────────────────────────────────────────
|
|
88
111
|
/**
|
|
89
112
|
* Print ESLint-style report to stdout.
|
|
@@ -95,12 +118,15 @@ export function reportEslint(report, verbose = false) {
|
|
|
95
118
|
const { score, summary, diagnostics } = report;
|
|
96
119
|
// ── Header Box ──────────────────────────────────────────────────
|
|
97
120
|
console.log();
|
|
98
|
-
console.log(bold("
|
|
99
|
-
console.log(bold("│") + "
|
|
100
|
-
console.log(bold("
|
|
101
|
-
console.log(bold("│") + "
|
|
102
|
-
console.log(bold("│") + "
|
|
103
|
-
console.log(bold("
|
|
121
|
+
console.log(bold("╭──────────────────────────────────────────────╮"));
|
|
122
|
+
console.log(bold("│") + " " + bold("│"));
|
|
123
|
+
console.log(bold("│") + " 🌐 " + bold("better-i18n") + dim(" · i18n Doctor Report") + " " + bold("│"));
|
|
124
|
+
console.log(bold("│") + dim(" hello · hola · 你好 · こんにちは · 안녕") + " " + bold("│"));
|
|
125
|
+
console.log(bold("│") + " " + bold("│"));
|
|
126
|
+
console.log(bold("├──────────────────────────────────────────────┤"));
|
|
127
|
+
console.log(bold("│") + " " + renderScoreBar(score.total) + " " + bold("│"));
|
|
128
|
+
console.log(bold("│") + " " + (score.passed ? green("PASSED") : red("FAILED")) + dim(` (threshold: ${score.passThreshold})`) + " ".repeat(11) + bold("│"));
|
|
129
|
+
console.log(bold("╰──────────────────────────────────────────────╯"));
|
|
104
130
|
console.log();
|
|
105
131
|
// ── Category Breakdown ──────────────────────────────────────────
|
|
106
132
|
console.log(bold("Category Scores:"));
|
|
@@ -138,9 +164,12 @@ export function reportEslint(report, verbose = false) {
|
|
|
138
164
|
existing.push(d);
|
|
139
165
|
byRule.set(d.rule, existing);
|
|
140
166
|
}
|
|
141
|
-
// Sort: errors first, then
|
|
142
|
-
const sortedGroups =
|
|
143
|
-
|
|
167
|
+
// Sort: errors first, then by count descending
|
|
168
|
+
const sortedGroups = sortBySeverityAndCount([...byRule.entries()]);
|
|
169
|
+
const visibleGroups = sortedGroups.slice(0, MAX_RULE_GROUPS);
|
|
170
|
+
const hiddenGroupCount = sortedGroups.length - visibleGroups.length;
|
|
171
|
+
const maxItems = verbose ? MAX_ITEMS_PER_GROUP_VERBOSE : MAX_ITEMS_PER_GROUP;
|
|
172
|
+
for (const [rule, diags] of visibleGroups) {
|
|
144
173
|
const first = diags[0];
|
|
145
174
|
const icon = colorizeBySeverity(first.severity === "error" ? "✗" : "⚠", first.severity);
|
|
146
175
|
const count = diags.length;
|
|
@@ -153,13 +182,24 @@ export function reportEslint(report, verbose = false) {
|
|
|
153
182
|
if (first.help) {
|
|
154
183
|
console.log(dim(` ${first.help}`));
|
|
155
184
|
}
|
|
156
|
-
//
|
|
157
|
-
if (
|
|
158
|
-
const
|
|
185
|
+
// Key-based rules: show namespace/key entries
|
|
186
|
+
if (KEY_BASED_RULES.has(rule)) {
|
|
187
|
+
const keys = buildKeyEntries(diags);
|
|
188
|
+
const shown = keys.slice(0, maxItems);
|
|
189
|
+
const hiddenKeys = keys.length - shown.length;
|
|
190
|
+
for (const key of shown) {
|
|
191
|
+
console.log(dim(` ${key}`));
|
|
192
|
+
}
|
|
193
|
+
if (hiddenKeys > 0) {
|
|
194
|
+
console.log(dim(` ... and ${hiddenKeys} more`));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
// File-based rules: show file:line entries
|
|
159
199
|
const fileLines = buildFileLineMap(diags);
|
|
160
200
|
const entries = [...fileLines.entries()];
|
|
161
|
-
const shown = entries.slice(0,
|
|
162
|
-
const hiddenFiles = entries.length -
|
|
201
|
+
const shown = entries.slice(0, maxItems);
|
|
202
|
+
const hiddenFiles = entries.length - shown.length;
|
|
163
203
|
for (const [filePath, lines] of shown) {
|
|
164
204
|
const lineLabel = lines.length > 0 ? `: ${lines.join(", ")}` : "";
|
|
165
205
|
console.log(dim(` ${filePath}${lineLabel}`));
|
|
@@ -170,6 +210,10 @@ export function reportEslint(report, verbose = false) {
|
|
|
170
210
|
}
|
|
171
211
|
console.log();
|
|
172
212
|
}
|
|
213
|
+
if (hiddenGroupCount > 0) {
|
|
214
|
+
console.log(dim(` ... and ${hiddenGroupCount} more rules`));
|
|
215
|
+
console.log();
|
|
216
|
+
}
|
|
173
217
|
}
|
|
174
218
|
}
|
|
175
219
|
//# sourceMappingURL=doctor-eslint.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor-eslint.js","sourceRoot":"","sources":["../../src/reporters/doctor-eslint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAIzE,wEAAwE;AAExE,SAAS,cAAc,CAAC,KAAa;IACnC,MAAM,KAAK,GAAG,EAAE,CAAC;IACjB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAE7B,IAAI,KAA4B,CAAC;IACjC,IAAI,KAAa,CAAC;IAElB,IAAI,KAAK,IAAI,EAAE,EAAE,CAAC;QAChB,KAAK,GAAG,KAAK,CAAC;QACd,KAAK,GAAG,IAAI,CAAC;IACf,CAAC;SAAM,IAAI,KAAK,IAAI,EAAE,EAAE,CAAC;QACvB,KAAK,GAAG,KAAK,CAAC;QACd,KAAK,GAAG,GAAG,CAAC;IACd,CAAC;SAAM,IAAI,KAAK,IAAI,EAAE,EAAE,CAAC;QACvB,KAAK,GAAG,IAAI,CAAC;QACb,KAAK,GAAG,GAAG,CAAC;IACd,CAAC;SAAM,IAAI,KAAK,IAAI,EAAE,EAAE,CAAC;QACvB,KAAK,GAAG,MAAM,CAAC;QACf,KAAK,GAAG,GAAG,CAAC;IACd,CAAC;SAAM,CAAC;QACN,KAAK,GAAG,GAAG,CAAC;QACZ,KAAK,GAAG,GAAG,CAAC;IACd,CAAC;IAED,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/D,OAAO,GAAG,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;AACxE,CAAC;AAED,uEAAuE;AAEvE,SAAS,kBAAkB,CACzB,QAAgB,EAChB,KAAa,EACb,KAAa;IAEb,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAE3C,IAAI,OAA8B,CAAC;IACnC,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,GAAG,KAAK,CAAC;SAC5B,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,GAAG,IAAI,CAAC;SAChC,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,GAAG,MAAM,CAAC;;QAClC,OAAO,GAAG,GAAG,CAAC;IAEnB,MAAM,QAAQ,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACzE,OAAO,KAAK,GAAG,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,EAAE,CAAC;AAC5D,CAAC;AAED,uEAAuE;AAEvE,MAAM,cAAc,GAA2B;IAC7C,KAAK,EAAE,CAAC;IACR,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,CAAC;CACR,CAAC;AAEF,SAAS,kBAAkB,CAAC,IAAY,EAAE,QAAgB;IACxD,IAAI,QAAQ,KAAK,OAAO;QAAE,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;IAChD,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC;AACnB,CAAC;AAED,SAAS,
|
|
1
|
+
{"version":3,"file":"doctor-eslint.js","sourceRoot":"","sources":["../../src/reporters/doctor-eslint.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
* Doctor Report — API Reporter
|
|
3
3
|
*
|
|
4
4
|
* Sends a DoctorReport to the Better i18n API for storage and trend tracking.
|
|
5
|
-
* Authentication is via GitHub Actions OIDC — no API keys needed.
|
|
6
5
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* Two auth paths:
|
|
7
|
+
* 1. API key (--api-key flag) — for local dev, GitLab, Jenkins, etc.
|
|
8
|
+
* Uses Better Auth API key via x-api-key header.
|
|
9
|
+
* Reads project context from i18n.config.ts to build X-Doctor-Project header.
|
|
10
|
+
* 2. GitHub Actions OIDC (default) — no API keys needed in GitHub Actions.
|
|
11
|
+
*
|
|
12
|
+
* Graceful degradation: if auth is unavailable, it warns and returns null.
|
|
9
13
|
*/
|
|
10
14
|
import type { DoctorReport } from "../doctor/index.js";
|
|
11
15
|
interface ReportResult {
|
|
@@ -16,8 +20,9 @@ interface ReportResult {
|
|
|
16
20
|
* POST a doctor report to the Better i18n API.
|
|
17
21
|
*
|
|
18
22
|
* @param report - The DoctorReport to upload
|
|
23
|
+
* @param apiKey - Optional Better Auth API key for non-OIDC auth (--api-key flag)
|
|
19
24
|
* @returns Report ID and dashboard URL, or null if reporting failed/unavailable
|
|
20
25
|
*/
|
|
21
|
-
export declare function reportToApi(report: DoctorReport): Promise<ReportResult | null>;
|
|
26
|
+
export declare function reportToApi(report: DoctorReport, apiKey?: string): Promise<ReportResult | null>;
|
|
22
27
|
export {};
|
|
23
28
|
//# sourceMappingURL=doctor-report.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor-report.d.ts","sourceRoot":"","sources":["../../src/reporters/doctor-report.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"doctor-report.d.ts","sourceRoot":"","sources":["../../src/reporters/doctor-report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAMvD,UAAU,YAAY;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,YAAY,EACpB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAU9B"}
|
|
@@ -2,24 +2,86 @@
|
|
|
2
2
|
* Doctor Report — API Reporter
|
|
3
3
|
*
|
|
4
4
|
* Sends a DoctorReport to the Better i18n API for storage and trend tracking.
|
|
5
|
-
* Authentication is via GitHub Actions OIDC — no API keys needed.
|
|
6
5
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* Two auth paths:
|
|
7
|
+
* 1. API key (--api-key flag) — for local dev, GitLab, Jenkins, etc.
|
|
8
|
+
* Uses Better Auth API key via x-api-key header.
|
|
9
|
+
* Reads project context from i18n.config.ts to build X-Doctor-Project header.
|
|
10
|
+
* 2. GitHub Actions OIDC (default) — no API keys needed in GitHub Actions.
|
|
11
|
+
*
|
|
12
|
+
* Graceful degradation: if auth is unavailable, it warns and returns null.
|
|
9
13
|
*/
|
|
14
|
+
import { detectProjectContext } from "../context/detector.js";
|
|
10
15
|
import { fetchGitHubOidcToken, isGitHubActionsWithOidc } from "../context/oidc.js";
|
|
11
16
|
const DEFAULT_API_URL = "https://api.better-i18n.com";
|
|
12
17
|
/**
|
|
13
18
|
* POST a doctor report to the Better i18n API.
|
|
14
19
|
*
|
|
15
20
|
* @param report - The DoctorReport to upload
|
|
21
|
+
* @param apiKey - Optional Better Auth API key for non-OIDC auth (--api-key flag)
|
|
16
22
|
* @returns Report ID and dashboard URL, or null if reporting failed/unavailable
|
|
17
23
|
*/
|
|
18
|
-
export async function reportToApi(report) {
|
|
19
|
-
|
|
24
|
+
export async function reportToApi(report, apiKey) {
|
|
25
|
+
const apiUrl = process.env.BETTER_I18N_API_URL || DEFAULT_API_URL;
|
|
26
|
+
// ── API key auth path ──────────────────────────────────────────
|
|
27
|
+
if (apiKey) {
|
|
28
|
+
return reportWithApiKey(report, apiKey, apiUrl);
|
|
29
|
+
}
|
|
30
|
+
// ── OIDC auth path (GitHub Actions) ──────────────────────────
|
|
31
|
+
return reportWithOidc(report, apiUrl);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Report using Better Auth API key + X-Doctor-Project header.
|
|
35
|
+
* Reads org/project slug from i18n.config.ts.
|
|
36
|
+
*/
|
|
37
|
+
async function reportWithApiKey(report, apiKey, apiUrl) {
|
|
38
|
+
// Detect project context from i18n.config.ts
|
|
39
|
+
const context = await detectProjectContext(process.cwd(), true);
|
|
40
|
+
if (!context?.workspaceId || !context?.projectSlug) {
|
|
41
|
+
console.warn(" Warning: Could not detect project context from i18n.config.ts.\n" +
|
|
42
|
+
" Ensure your config has: project: \"orgSlug/projectSlug\"\n" +
|
|
43
|
+
" Skipping report upload.");
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const doctorProject = `${context.workspaceId}/${context.projectSlug}`;
|
|
47
|
+
try {
|
|
48
|
+
const response = await fetch(`${apiUrl}/api/doctor/report`, {
|
|
49
|
+
method: "POST",
|
|
50
|
+
headers: {
|
|
51
|
+
"Content-Type": "application/json",
|
|
52
|
+
"x-api-key": apiKey,
|
|
53
|
+
"X-Doctor-Project": doctorProject,
|
|
54
|
+
},
|
|
55
|
+
body: JSON.stringify(report),
|
|
56
|
+
});
|
|
57
|
+
if (!response.ok) {
|
|
58
|
+
const errorText = await response.text().catch(() => "Unknown error");
|
|
59
|
+
console.warn(` Warning: Report upload failed (${response.status}): ${errorText}`);
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
const data = (await response.json());
|
|
63
|
+
if (!data.reportId) {
|
|
64
|
+
console.warn(" Warning: Unexpected API response. Skipping.");
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
reportId: data.reportId,
|
|
69
|
+
url: data.url || `${apiUrl}/doctor/${data.reportId}`,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
console.warn(` Warning: Report upload failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Report using GitHub Actions OIDC token (original flow).
|
|
79
|
+
*/
|
|
80
|
+
async function reportWithOidc(report, apiUrl) {
|
|
20
81
|
if (!isGitHubActionsWithOidc()) {
|
|
21
|
-
console.warn(" Warning: --report requires GitHub Actions
|
|
22
|
-
"
|
|
82
|
+
console.warn(" Warning: --report requires GitHub Actions OIDC or --api-key flag.\n" +
|
|
83
|
+
" For GitHub Actions: add `permissions: id-token: write` to your workflow.\n" +
|
|
84
|
+
" For local/non-GitHub CI: use --api-key <your-better-auth-api-key>\n" +
|
|
23
85
|
" Skipping report upload.");
|
|
24
86
|
return null;
|
|
25
87
|
}
|
|
@@ -28,8 +90,6 @@ export async function reportToApi(report) {
|
|
|
28
90
|
console.warn(" Warning: Failed to fetch OIDC token. Skipping report upload.");
|
|
29
91
|
return null;
|
|
30
92
|
}
|
|
31
|
-
// 2. Send report to API
|
|
32
|
-
const apiUrl = process.env.BETTER_I18N_API_URL || DEFAULT_API_URL;
|
|
33
93
|
try {
|
|
34
94
|
const response = await fetch(`${apiUrl}/api/doctor/report`, {
|
|
35
95
|
method: "POST",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor-report.js","sourceRoot":"","sources":["../../src/reporters/doctor-report.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"doctor-report.js","sourceRoot":"","sources":["../../src/reporters/doctor-report.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"categories.d.ts","sourceRoot":"","sources":["../../src/rules/categories.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,
|
|
1
|
+
{"version":3,"file":"categories.d.ts","sourceRoot":"","sources":["../../src/rules/categories.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,CAoBxE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAkChD,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,CAoB5E,CAAC"}
|
package/dist/rules/categories.js
CHANGED
|
@@ -25,6 +25,9 @@ export const RULE_CATEGORY_MAP = {
|
|
|
25
25
|
"key-naming": "Structure",
|
|
26
26
|
"namespace-structure": "Structure",
|
|
27
27
|
"file-format": "Structure",
|
|
28
|
+
// ── Sync Rules (remote CDN comparison) ───────────────────────────
|
|
29
|
+
"missing-in-remote": "Coverage",
|
|
30
|
+
"unused-remote-key": "Performance",
|
|
28
31
|
// ── Code Rules (AST analysis, from existing analyzer) ─────────────
|
|
29
32
|
"jsx-text": "Code",
|
|
30
33
|
"jsx-attribute": "Code",
|
|
@@ -47,6 +50,9 @@ export const RULE_HELP_MAP = {
|
|
|
47
50
|
"key-naming": "Use consistent naming convention within each namespace (e.g., camelCase or snake_case, not mixed)",
|
|
48
51
|
"namespace-structure": "Maintain consistent namespace depth across translation files for predictable key organization",
|
|
49
52
|
"file-format": "Fix malformed JSON or encoding issues in translation files",
|
|
53
|
+
// ── Sync Rules ────────────────────────────────────────────────────
|
|
54
|
+
"missing-in-remote": "Key found in code but not in remote translations. Run sync or add the key in the editor",
|
|
55
|
+
"unused-remote-key": "Key exists in remote but not used in code. Consider removing it to reduce bundle size",
|
|
50
56
|
// ── Code Rules ────────────────────────────────────────────────────
|
|
51
57
|
"jsx-text": "Wrap hardcoded JSX text with t() function call for translation support",
|
|
52
58
|
"jsx-attribute": "Use t() for translatable attributes like title, alt, placeholder, aria-label",
|
|
@@ -70,6 +76,9 @@ export const RULE_DEFAULT_SEVERITY = {
|
|
|
70
76
|
"key-naming": "warning",
|
|
71
77
|
"namespace-structure": "info",
|
|
72
78
|
"file-format": "error",
|
|
79
|
+
// Sync rules
|
|
80
|
+
"missing-in-remote": "warning",
|
|
81
|
+
"unused-remote-key": "info",
|
|
73
82
|
// Code rules
|
|
74
83
|
"jsx-text": "warning",
|
|
75
84
|
"jsx-attribute": "warning",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"categories.js","sourceRoot":"","sources":["../../src/rules/categories.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAA+C;IAC3E,qEAAqE;IACrE,sBAAsB,EAAE,UAAU;IAClC,aAAa,EAAE,aAAa;IAC5B,sBAAsB,EAAE,SAAS;IACjC,oBAAoB,EAAE,SAAS;IAC/B,YAAY,EAAE,WAAW;IACzB,qBAAqB,EAAE,WAAW;IAClC,aAAa,EAAE,WAAW;IAE1B,qEAAqE;IACrE,UAAU,EAAE,MAAM;IAClB,eAAe,EAAE,MAAM;IACvB,gBAAgB,EAAE,MAAM;IACxB,eAAe,EAAE,MAAM;IACvB,iBAAiB,EAAE,MAAM;CAC1B,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,aAAa,GAA2B;IACnD,qEAAqE;IACrE,sBAAsB,EACpB,qFAAqF;IACvF,aAAa,EACX,sFAAsF;IACxF,sBAAsB,EACpB,2HAA2H;IAC7H,oBAAoB,EAClB,yFAAyF;IAC3F,YAAY,EACV,mGAAmG;IACrG,qBAAqB,EACnB,+FAA+F;IACjG,aAAa,EACX,4DAA4D;IAE9D,qEAAqE;IACrE,UAAU,EACR,wEAAwE;IAC1E,eAAe,EACb,8EAA8E;IAChF,gBAAgB,EACd,wFAAwF;IAC1F,eAAe,EACb,mEAAmE;IACrE,iBAAiB,EACf,sEAAsE;CACzE,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAA+C;IAC/E,oEAAoE;IACpE,sBAAsB,EAAE,OAAO;IAC/B,aAAa,EAAE,SAAS;IACxB,sBAAsB,EAAE,OAAO;IAC/B,oBAAoB,EAAE,SAAS;IAC/B,YAAY,EAAE,SAAS;IACvB,qBAAqB,EAAE,MAAM;IAC7B,aAAa,EAAE,OAAO;IAEtB,aAAa;IACb,UAAU,EAAE,SAAS;IACrB,eAAe,EAAE,SAAS;IAC1B,gBAAgB,EAAE,OAAO;IACzB,eAAe,EAAE,SAAS;IAC1B,iBAAiB,EAAE,SAAS;CAC7B,CAAC"}
|
|
1
|
+
{"version":3,"file":"categories.js","sourceRoot":"","sources":["../../src/rules/categories.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAA+C;IAC3E,qEAAqE;IACrE,sBAAsB,EAAE,UAAU;IAClC,aAAa,EAAE,aAAa;IAC5B,sBAAsB,EAAE,SAAS;IACjC,oBAAoB,EAAE,SAAS;IAC/B,YAAY,EAAE,WAAW;IACzB,qBAAqB,EAAE,WAAW;IAClC,aAAa,EAAE,WAAW;IAE1B,oEAAoE;IACpE,mBAAmB,EAAE,UAAU;IAC/B,mBAAmB,EAAE,aAAa;IAElC,qEAAqE;IACrE,UAAU,EAAE,MAAM;IAClB,eAAe,EAAE,MAAM;IACvB,gBAAgB,EAAE,MAAM;IACxB,eAAe,EAAE,MAAM;IACvB,iBAAiB,EAAE,MAAM;CAC1B,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,aAAa,GAA2B;IACnD,qEAAqE;IACrE,sBAAsB,EACpB,qFAAqF;IACvF,aAAa,EACX,sFAAsF;IACxF,sBAAsB,EACpB,2HAA2H;IAC7H,oBAAoB,EAClB,yFAAyF;IAC3F,YAAY,EACV,mGAAmG;IACrG,qBAAqB,EACnB,+FAA+F;IACjG,aAAa,EACX,4DAA4D;IAE9D,qEAAqE;IACrE,mBAAmB,EACjB,yFAAyF;IAC3F,mBAAmB,EACjB,uFAAuF;IAEzF,qEAAqE;IACrE,UAAU,EACR,wEAAwE;IAC1E,eAAe,EACb,8EAA8E;IAChF,gBAAgB,EACd,wFAAwF;IAC1F,eAAe,EACb,mEAAmE;IACrE,iBAAiB,EACf,sEAAsE;CACzE,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAA+C;IAC/E,oEAAoE;IACpE,sBAAsB,EAAE,OAAO;IAC/B,aAAa,EAAE,SAAS;IACxB,sBAAsB,EAAE,OAAO;IAC/B,oBAAoB,EAAE,SAAS;IAC/B,YAAY,EAAE,SAAS;IACvB,qBAAqB,EAAE,MAAM;IAC7B,aAAa,EAAE,OAAO;IAEtB,aAAa;IACb,mBAAmB,EAAE,SAAS;IAC9B,mBAAmB,EAAE,MAAM;IAE3B,aAAa;IACb,UAAU,EAAE,SAAS;IACrB,eAAe,EAAE,SAAS;IAC1B,gBAAgB,EAAE,OAAO;IACzB,eAAe,EAAE,SAAS;IAC1B,iBAAiB,EAAE,SAAS;CAC7B,CAAC"}
|
|
@@ -15,7 +15,7 @@ export const missingTranslationsRule = {
|
|
|
15
15
|
defaultSeverity: "error",
|
|
16
16
|
description: "Detect keys present in source locale but missing in target locales",
|
|
17
17
|
run(context) {
|
|
18
|
-
const { sourceLocale, targetLocales, translations } = context;
|
|
18
|
+
const { sourceLocale, targetLocales, translations, localeFilePaths } = context;
|
|
19
19
|
const sourceKeys = translations[sourceLocale];
|
|
20
20
|
if (!sourceKeys)
|
|
21
21
|
return [];
|
|
@@ -27,7 +27,7 @@ export const missingTranslationsRule = {
|
|
|
27
27
|
if (!(key in targetKeys)) {
|
|
28
28
|
const namespace = key.split(".")[0] || "default";
|
|
29
29
|
diagnostics.push({
|
|
30
|
-
filePath: `${targetLocale}.json`,
|
|
30
|
+
filePath: localeFilePaths?.[targetLocale] ?? `${targetLocale}.json`,
|
|
31
31
|
line: 0,
|
|
32
32
|
column: 0,
|
|
33
33
|
rule: RULE_ID,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"missing-translations.js","sourceRoot":"","sources":["../../../src/rules/health/missing-translations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAOpE,MAAM,OAAO,GAAG,sBAAsB,CAAC;AAEvC,MAAM,CAAC,MAAM,uBAAuB,GAAe;IACjD,EAAE,EAAE,OAAO;IACX,eAAe,EAAE,OAAO;IACxB,WAAW,EACT,oEAAoE;IAEtE,GAAG,CAAC,OAA0B;QAC5B,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"missing-translations.js","sourceRoot":"","sources":["../../../src/rules/health/missing-translations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAOpE,MAAM,OAAO,GAAG,sBAAsB,CAAC;AAEvC,MAAM,CAAC,MAAM,uBAAuB,GAAe;IACjD,EAAE,EAAE,OAAO;IACX,eAAe,EAAE,OAAO;IACxB,WAAW,EACT,oEAAoE;IAEtE,GAAG,CAAC,OAA0B;QAC5B,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC;QAE/E,MAAM,UAAU,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;QAC9C,IAAI,CAAC,UAAU;YAAE,OAAO,EAAE,CAAC;QAE3B,MAAM,WAAW,GAAqB,EAAE,CAAC;QACzC,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAE7C,KAAK,MAAM,YAAY,IAAI,aAAa,EAAE,CAAC;YACzC,MAAM,UAAU,GAAG,YAAY,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;YAEpD,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;gBAC/B,IAAI,CAAC,CAAC,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC;oBACzB,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;oBAEjD,WAAW,CAAC,IAAI,CAAC;wBACf,QAAQ,EAAE,eAAe,EAAE,CAAC,YAAY,CAAC,IAAI,GAAG,YAAY,OAAO;wBACnE,IAAI,EAAE,CAAC;wBACP,MAAM,EAAE,CAAC;wBACT,IAAI,EAAE,OAAO;wBACb,QAAQ,EAAE,iBAAiB,CAAC,OAAO,CAAC,IAAI,UAAU;wBAClD,QAAQ,EAAE,IAAI,CAAC,eAAe;wBAC9B,OAAO,EAAE,QAAQ,GAAG,2BAA2B,YAAY,GAAG;wBAC9D,IAAI,EAAE,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE;wBAClC,GAAG;wBACH,SAAS;wBACT,QAAQ,EAAE,YAAY;qBACvB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;CACF,CAAC"}
|
|
@@ -18,7 +18,7 @@ export const orphanKeysRule = {
|
|
|
18
18
|
defaultSeverity: "warning",
|
|
19
19
|
description: "Detect translation keys not referenced in code (dead translations)",
|
|
20
20
|
run(context) {
|
|
21
|
-
const { sourceLocale, translations, codeKeys } = context;
|
|
21
|
+
const { sourceLocale, translations, codeKeys, localeFilePaths } = context;
|
|
22
22
|
// If no code keys were collected, skip — we can't determine orphans
|
|
23
23
|
// without knowing what code actually uses.
|
|
24
24
|
if (codeKeys.size === 0)
|
|
@@ -31,7 +31,7 @@ export const orphanKeysRule = {
|
|
|
31
31
|
if (!codeKeys.has(key)) {
|
|
32
32
|
const namespace = key.split(".")[0] || "default";
|
|
33
33
|
diagnostics.push({
|
|
34
|
-
filePath: `${sourceLocale}.json`,
|
|
34
|
+
filePath: localeFilePaths?.[sourceLocale] ?? `${sourceLocale}.json`,
|
|
35
35
|
line: 0,
|
|
36
36
|
column: 0,
|
|
37
37
|
rule: RULE_ID,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orphan-keys.js","sourceRoot":"","sources":["../../../src/rules/health/orphan-keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAOpE,MAAM,OAAO,GAAG,aAAa,CAAC;AAE9B,MAAM,CAAC,MAAM,cAAc,GAAe;IACxC,EAAE,EAAE,OAAO;IACX,eAAe,EAAE,SAAS;IAC1B,WAAW,EACT,oEAAoE;IAEtE,GAAG,CAAC,OAA0B;QAC5B,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"orphan-keys.js","sourceRoot":"","sources":["../../../src/rules/health/orphan-keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAOpE,MAAM,OAAO,GAAG,aAAa,CAAC;AAE9B,MAAM,CAAC,MAAM,cAAc,GAAe;IACxC,EAAE,EAAE,OAAO;IACX,eAAe,EAAE,SAAS;IAC1B,WAAW,EACT,oEAAoE;IAEtE,GAAG,CAAC,OAA0B;QAC5B,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC;QAE1E,oEAAoE;QACpE,2CAA2C;QAC3C,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAEnC,MAAM,UAAU,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;QAC9C,IAAI,CAAC,UAAU;YAAE,OAAO,EAAE,CAAC;QAE3B,MAAM,WAAW,GAAqB,EAAE,CAAC;QAEzC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAC1C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACvB,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;gBAEjD,WAAW,CAAC,IAAI,CAAC;oBACf,QAAQ,EAAE,eAAe,EAAE,CAAC,YAAY,CAAC,IAAI,GAAG,YAAY,OAAO;oBACnE,IAAI,EAAE,CAAC;oBACP,MAAM,EAAE,CAAC;oBACT,IAAI,EAAE,OAAO;oBACb,QAAQ,EAAE,iBAAiB,CAAC,OAAO,CAAC,IAAI,aAAa;oBACrD,QAAQ,EAAE,IAAI,CAAC,eAAe;oBAC9B,OAAO,EAAE,QAAQ,GAAG,kDAAkD;oBACtE,IAAI,EAAE,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE;oBAClC,GAAG;oBACH,SAAS;iBACV,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;CACF,CAAC"}
|
|
@@ -60,7 +60,7 @@ export const placeholderMismatchRule = {
|
|
|
60
60
|
defaultSeverity: "error",
|
|
61
61
|
description: "Detect placeholder mismatches between source and target translations",
|
|
62
62
|
run(context) {
|
|
63
|
-
const { sourceLocale, targetLocales, translations } = context;
|
|
63
|
+
const { sourceLocale, targetLocales, translations, localeFilePaths } = context;
|
|
64
64
|
const sourceKeys = translations[sourceLocale];
|
|
65
65
|
if (!sourceKeys)
|
|
66
66
|
return [];
|
|
@@ -80,7 +80,7 @@ export const placeholderMismatchRule = {
|
|
|
80
80
|
for (const ph of sourcePh) {
|
|
81
81
|
if (!targetPh.includes(ph)) {
|
|
82
82
|
diagnostics.push({
|
|
83
|
-
filePath: `${targetLocale}.json`,
|
|
83
|
+
filePath: localeFilePaths?.[targetLocale] ?? `${targetLocale}.json`,
|
|
84
84
|
line: 0,
|
|
85
85
|
column: 0,
|
|
86
86
|
rule: RULE_ID,
|
|
@@ -98,7 +98,7 @@ export const placeholderMismatchRule = {
|
|
|
98
98
|
for (const ph of targetPh) {
|
|
99
99
|
if (!sourcePh.includes(ph)) {
|
|
100
100
|
diagnostics.push({
|
|
101
|
-
filePath: `${targetLocale}.json`,
|
|
101
|
+
filePath: localeFilePaths?.[targetLocale] ?? `${targetLocale}.json`,
|
|
102
102
|
line: 0,
|
|
103
103
|
column: 0,
|
|
104
104
|
rule: RULE_ID,
|