@saasmakers/eslint 0.1.3 → 0.1.4
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/dist/eslint.config.cjs +13 -0
- package/dist/eslint.config.d.cts +13 -0
- package/dist/eslint.config.d.mts +13 -0
- package/dist/eslint.config.d.ts +13 -0
- package/dist/eslint.config.mjs +13 -0
- package/dist/index.cjs +377 -10
- package/dist/index.d.cts +4 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.mjs +377 -10
- package/package.json +1 -1
package/dist/eslint.config.cjs
CHANGED
|
@@ -183,6 +183,19 @@ const eslint_config = antfu__default(
|
|
|
183
183
|
"saasmakers/ts-multiline-ternary": "error",
|
|
184
184
|
"saasmakers/ts-multiline-union": "error",
|
|
185
185
|
"saasmakers/ts-sort-tests": "error",
|
|
186
|
+
"saasmakers/vue-i18n-consistent-locales": [
|
|
187
|
+
"error",
|
|
188
|
+
{
|
|
189
|
+
locales: [
|
|
190
|
+
"en",
|
|
191
|
+
"fr",
|
|
192
|
+
"ja"
|
|
193
|
+
]
|
|
194
|
+
}
|
|
195
|
+
],
|
|
196
|
+
"saasmakers/vue-i18n-consistent-t": "error",
|
|
197
|
+
"saasmakers/vue-i18n-sort-keys": "error",
|
|
198
|
+
"saasmakers/vue-i18n-unused-strings": "error",
|
|
186
199
|
"sort-imports": "off",
|
|
187
200
|
"ts/ban-ts-comment": "off",
|
|
188
201
|
"ts/ban-ts-ignore": "off",
|
package/dist/eslint.config.d.cts
CHANGED
|
@@ -175,6 +175,19 @@ var eslint_config = antfu(
|
|
|
175
175
|
"saasmakers/ts-multiline-ternary": "error",
|
|
176
176
|
"saasmakers/ts-multiline-union": "error",
|
|
177
177
|
"saasmakers/ts-sort-tests": "error",
|
|
178
|
+
"saasmakers/vue-i18n-consistent-locales": [
|
|
179
|
+
"error",
|
|
180
|
+
{
|
|
181
|
+
locales: [
|
|
182
|
+
"en",
|
|
183
|
+
"fr",
|
|
184
|
+
"ja"
|
|
185
|
+
]
|
|
186
|
+
}
|
|
187
|
+
],
|
|
188
|
+
"saasmakers/vue-i18n-consistent-t": "error",
|
|
189
|
+
"saasmakers/vue-i18n-sort-keys": "error",
|
|
190
|
+
"saasmakers/vue-i18n-unused-strings": "error",
|
|
178
191
|
"sort-imports": "off",
|
|
179
192
|
"ts/ban-ts-comment": "off",
|
|
180
193
|
"ts/ban-ts-ignore": "off",
|
package/dist/eslint.config.d.mts
CHANGED
|
@@ -175,6 +175,19 @@ var eslint_config = antfu(
|
|
|
175
175
|
"saasmakers/ts-multiline-ternary": "error",
|
|
176
176
|
"saasmakers/ts-multiline-union": "error",
|
|
177
177
|
"saasmakers/ts-sort-tests": "error",
|
|
178
|
+
"saasmakers/vue-i18n-consistent-locales": [
|
|
179
|
+
"error",
|
|
180
|
+
{
|
|
181
|
+
locales: [
|
|
182
|
+
"en",
|
|
183
|
+
"fr",
|
|
184
|
+
"ja"
|
|
185
|
+
]
|
|
186
|
+
}
|
|
187
|
+
],
|
|
188
|
+
"saasmakers/vue-i18n-consistent-t": "error",
|
|
189
|
+
"saasmakers/vue-i18n-sort-keys": "error",
|
|
190
|
+
"saasmakers/vue-i18n-unused-strings": "error",
|
|
178
191
|
"sort-imports": "off",
|
|
179
192
|
"ts/ban-ts-comment": "off",
|
|
180
193
|
"ts/ban-ts-ignore": "off",
|
package/dist/eslint.config.d.ts
CHANGED
|
@@ -175,6 +175,19 @@ var eslint_config = antfu(
|
|
|
175
175
|
"saasmakers/ts-multiline-ternary": "error",
|
|
176
176
|
"saasmakers/ts-multiline-union": "error",
|
|
177
177
|
"saasmakers/ts-sort-tests": "error",
|
|
178
|
+
"saasmakers/vue-i18n-consistent-locales": [
|
|
179
|
+
"error",
|
|
180
|
+
{
|
|
181
|
+
locales: [
|
|
182
|
+
"en",
|
|
183
|
+
"fr",
|
|
184
|
+
"ja"
|
|
185
|
+
]
|
|
186
|
+
}
|
|
187
|
+
],
|
|
188
|
+
"saasmakers/vue-i18n-consistent-t": "error",
|
|
189
|
+
"saasmakers/vue-i18n-sort-keys": "error",
|
|
190
|
+
"saasmakers/vue-i18n-unused-strings": "error",
|
|
178
191
|
"sort-imports": "off",
|
|
179
192
|
"ts/ban-ts-comment": "off",
|
|
180
193
|
"ts/ban-ts-ignore": "off",
|
package/dist/eslint.config.mjs
CHANGED
|
@@ -175,6 +175,19 @@ const eslint_config = antfu(
|
|
|
175
175
|
"saasmakers/ts-multiline-ternary": "error",
|
|
176
176
|
"saasmakers/ts-multiline-union": "error",
|
|
177
177
|
"saasmakers/ts-sort-tests": "error",
|
|
178
|
+
"saasmakers/vue-i18n-consistent-locales": [
|
|
179
|
+
"error",
|
|
180
|
+
{
|
|
181
|
+
locales: [
|
|
182
|
+
"en",
|
|
183
|
+
"fr",
|
|
184
|
+
"ja"
|
|
185
|
+
]
|
|
186
|
+
}
|
|
187
|
+
],
|
|
188
|
+
"saasmakers/vue-i18n-consistent-t": "error",
|
|
189
|
+
"saasmakers/vue-i18n-sort-keys": "error",
|
|
190
|
+
"saasmakers/vue-i18n-unused-strings": "error",
|
|
178
191
|
"sort-imports": "off",
|
|
179
192
|
"ts/ban-ts-comment": "off",
|
|
180
193
|
"ts/ban-ts-ignore": "off",
|
package/dist/index.cjs
CHANGED
|
@@ -14084,7 +14084,7 @@ function requireDist () {
|
|
|
14084
14084
|
|
|
14085
14085
|
var distExports = requireDist();
|
|
14086
14086
|
|
|
14087
|
-
const rule$
|
|
14087
|
+
const rule$6 = {
|
|
14088
14088
|
meta: {
|
|
14089
14089
|
docs: {
|
|
14090
14090
|
category: "Stylistic Issues",
|
|
@@ -14147,7 +14147,7 @@ const rule$2 = {
|
|
|
14147
14147
|
}
|
|
14148
14148
|
};
|
|
14149
14149
|
|
|
14150
|
-
const rule$
|
|
14150
|
+
const rule$5 = {
|
|
14151
14151
|
meta: {
|
|
14152
14152
|
docs: {
|
|
14153
14153
|
category: "Stylistic Issues",
|
|
@@ -14213,7 +14213,7 @@ const rule$1 = {
|
|
|
14213
14213
|
}
|
|
14214
14214
|
};
|
|
14215
14215
|
|
|
14216
|
-
const rule = {
|
|
14216
|
+
const rule$4 = {
|
|
14217
14217
|
meta: {
|
|
14218
14218
|
docs: {
|
|
14219
14219
|
category: "Best Practices",
|
|
@@ -14328,15 +14328,382 @@ const rule = {
|
|
|
14328
14328
|
}
|
|
14329
14329
|
};
|
|
14330
14330
|
|
|
14331
|
+
const rule$3 = {
|
|
14332
|
+
meta: {
|
|
14333
|
+
docs: {
|
|
14334
|
+
category: "Possible Errors",
|
|
14335
|
+
description: "Enforce consistent i18n locale keys across translations",
|
|
14336
|
+
recommended: true
|
|
14337
|
+
},
|
|
14338
|
+
messages: {
|
|
14339
|
+
invalidJson: "Invalid JSON in i18n block: {{error}}",
|
|
14340
|
+
invalidLocale: "Invalid locale: {{locale}}. Allowed locales are: {{allowed}}",
|
|
14341
|
+
missingLocale: "Missing required locale: {{locale}}",
|
|
14342
|
+
missingTranslations: 'Missing translations in "{{locale}}" locale: {{missing}}'
|
|
14343
|
+
},
|
|
14344
|
+
schema: [
|
|
14345
|
+
{
|
|
14346
|
+
additionalProperties: false,
|
|
14347
|
+
properties: {
|
|
14348
|
+
locales: {
|
|
14349
|
+
items: { type: "string" },
|
|
14350
|
+
type: "array"
|
|
14351
|
+
}
|
|
14352
|
+
},
|
|
14353
|
+
type: "object"
|
|
14354
|
+
}
|
|
14355
|
+
],
|
|
14356
|
+
type: "problem"
|
|
14357
|
+
},
|
|
14358
|
+
create(context) {
|
|
14359
|
+
if (!context.filename.endsWith(".vue")) {
|
|
14360
|
+
return {};
|
|
14361
|
+
}
|
|
14362
|
+
const locales = context.options[0]?.locales || ["en", "fr"];
|
|
14363
|
+
return {
|
|
14364
|
+
Program() {
|
|
14365
|
+
const source = context.sourceCode.getText();
|
|
14366
|
+
const i18nMatch = source.match(/(<i18n\s+lang=["']json["']>)([\s\S]*?)(<\/i18n>)/i);
|
|
14367
|
+
if (i18nMatch) {
|
|
14368
|
+
const startOffset = i18nMatch.index + i18nMatch[1].length;
|
|
14369
|
+
const i18nContent = i18nMatch[2].trim();
|
|
14370
|
+
try {
|
|
14371
|
+
const parsed = JSON.parse(i18nContent);
|
|
14372
|
+
for (const locale of locales) {
|
|
14373
|
+
if (!parsed[locale]) {
|
|
14374
|
+
context.report({
|
|
14375
|
+
data: { locale },
|
|
14376
|
+
loc: {
|
|
14377
|
+
end: context.sourceCode.getLocFromIndex(startOffset + i18nContent.length),
|
|
14378
|
+
start: context.sourceCode.getLocFromIndex(startOffset)
|
|
14379
|
+
},
|
|
14380
|
+
messageId: "missingLocale"
|
|
14381
|
+
});
|
|
14382
|
+
}
|
|
14383
|
+
}
|
|
14384
|
+
for (const locale of Object.keys(parsed)) {
|
|
14385
|
+
if (!locales.includes(locale)) {
|
|
14386
|
+
const localeMatch = new RegExp(`"${locale}"\\s*:`, "g").exec(i18nContent);
|
|
14387
|
+
if (localeMatch) {
|
|
14388
|
+
const localeOffset = startOffset + localeMatch.index;
|
|
14389
|
+
context.report({
|
|
14390
|
+
data: {
|
|
14391
|
+
allowed: locales.join(", "),
|
|
14392
|
+
locale
|
|
14393
|
+
},
|
|
14394
|
+
loc: {
|
|
14395
|
+
end: context.sourceCode.getLocFromIndex(localeOffset + locale.length + 2),
|
|
14396
|
+
start: context.sourceCode.getLocFromIndex(localeOffset)
|
|
14397
|
+
},
|
|
14398
|
+
messageId: "invalidLocale"
|
|
14399
|
+
});
|
|
14400
|
+
}
|
|
14401
|
+
}
|
|
14402
|
+
}
|
|
14403
|
+
const allKeys = /* @__PURE__ */ new Set();
|
|
14404
|
+
for (const locale of locales) {
|
|
14405
|
+
if (parsed[locale]) {
|
|
14406
|
+
const keys = getAllKeys(parsed[locale]);
|
|
14407
|
+
keys.forEach((key) => allKeys.add(key));
|
|
14408
|
+
}
|
|
14409
|
+
}
|
|
14410
|
+
for (const locale of locales) {
|
|
14411
|
+
if (parsed[locale]) {
|
|
14412
|
+
const localeKeys = getAllKeys(parsed[locale]);
|
|
14413
|
+
const missingKeys = [...allKeys].filter((key) => !localeKeys.includes(key));
|
|
14414
|
+
if (missingKeys.length > 0) {
|
|
14415
|
+
const localeMatch = new RegExp(`"${locale}"\\s*:\\s*{`, "g").exec(i18nContent);
|
|
14416
|
+
if (localeMatch) {
|
|
14417
|
+
const localeOffset = startOffset + localeMatch.index;
|
|
14418
|
+
context.report({
|
|
14419
|
+
data: {
|
|
14420
|
+
locale,
|
|
14421
|
+
missing: missingKeys.join(", ")
|
|
14422
|
+
},
|
|
14423
|
+
loc: {
|
|
14424
|
+
end: context.sourceCode.getLocFromIndex(localeOffset + locale.length + 2),
|
|
14425
|
+
start: context.sourceCode.getLocFromIndex(localeOffset)
|
|
14426
|
+
},
|
|
14427
|
+
messageId: "missingTranslations"
|
|
14428
|
+
});
|
|
14429
|
+
}
|
|
14430
|
+
}
|
|
14431
|
+
}
|
|
14432
|
+
}
|
|
14433
|
+
} catch (error) {
|
|
14434
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
14435
|
+
context.report({
|
|
14436
|
+
data: { error: errorMessage },
|
|
14437
|
+
loc: {
|
|
14438
|
+
end: context.sourceCode.getLocFromIndex(startOffset + i18nContent.length),
|
|
14439
|
+
start: context.sourceCode.getLocFromIndex(startOffset)
|
|
14440
|
+
},
|
|
14441
|
+
messageId: "invalidJson"
|
|
14442
|
+
});
|
|
14443
|
+
}
|
|
14444
|
+
}
|
|
14445
|
+
function getAllKeys(object, prefix = "") {
|
|
14446
|
+
let keys = [];
|
|
14447
|
+
for (const key in object) {
|
|
14448
|
+
const newPrefix = prefix ? `${prefix}.${key}` : key;
|
|
14449
|
+
if (typeof object[key] === "object" && object[key] !== null) {
|
|
14450
|
+
keys = [...keys, ...getAllKeys(object[key], newPrefix)];
|
|
14451
|
+
} else {
|
|
14452
|
+
keys.push(newPrefix);
|
|
14453
|
+
}
|
|
14454
|
+
}
|
|
14455
|
+
return keys;
|
|
14456
|
+
}
|
|
14457
|
+
}
|
|
14458
|
+
};
|
|
14459
|
+
}
|
|
14460
|
+
};
|
|
14461
|
+
|
|
14462
|
+
const rule$2 = {
|
|
14463
|
+
meta: {
|
|
14464
|
+
docs: {
|
|
14465
|
+
category: "Best Practices",
|
|
14466
|
+
description: "Enforce using t() instead of $t() in Vue templates",
|
|
14467
|
+
recommended: true
|
|
14468
|
+
},
|
|
14469
|
+
fixable: "code",
|
|
14470
|
+
messages: { useT: "Use t() instead of $t() in Vue templates as it does not work with <i18n> tags." },
|
|
14471
|
+
schema: [],
|
|
14472
|
+
type: "problem"
|
|
14473
|
+
},
|
|
14474
|
+
create(context) {
|
|
14475
|
+
if (!context.filename.endsWith(".vue")) {
|
|
14476
|
+
return {};
|
|
14477
|
+
}
|
|
14478
|
+
return {
|
|
14479
|
+
Program() {
|
|
14480
|
+
const sourceCode = context.sourceCode;
|
|
14481
|
+
const source = sourceCode.getText();
|
|
14482
|
+
const templateMatch = source.match(/<template>([\s\S]*)<\/template>/i);
|
|
14483
|
+
if (!templateMatch || templateMatch.index === void 0) {
|
|
14484
|
+
return;
|
|
14485
|
+
}
|
|
14486
|
+
const templateContent = templateMatch[1];
|
|
14487
|
+
const tPatterns = [
|
|
14488
|
+
{
|
|
14489
|
+
pattern: / \$t\(/g,
|
|
14490
|
+
quote: " "
|
|
14491
|
+
},
|
|
14492
|
+
{
|
|
14493
|
+
pattern: /"\$t\(/g,
|
|
14494
|
+
quote: '"'
|
|
14495
|
+
},
|
|
14496
|
+
{
|
|
14497
|
+
pattern: /`\$t\(/g,
|
|
14498
|
+
quote: "`"
|
|
14499
|
+
},
|
|
14500
|
+
{
|
|
14501
|
+
pattern: /\{\$t\(/g,
|
|
14502
|
+
quote: "{"
|
|
14503
|
+
},
|
|
14504
|
+
{
|
|
14505
|
+
pattern: /\[\$t\(/g,
|
|
14506
|
+
quote: "["
|
|
14507
|
+
}
|
|
14508
|
+
];
|
|
14509
|
+
for (const { pattern, quote } of tPatterns) {
|
|
14510
|
+
let match;
|
|
14511
|
+
while ((match = pattern.exec(templateContent)) !== null) {
|
|
14512
|
+
const templateStart = templateMatch.index + templateMatch[0].indexOf(templateContent);
|
|
14513
|
+
const start = templateStart + match.index;
|
|
14514
|
+
const end = start + 4;
|
|
14515
|
+
context.report({
|
|
14516
|
+
fix(fixer) {
|
|
14517
|
+
return fixer.replaceTextRange([start, end], `${quote}t(`);
|
|
14518
|
+
},
|
|
14519
|
+
loc: {
|
|
14520
|
+
end: sourceCode.getLocFromIndex(end),
|
|
14521
|
+
start: sourceCode.getLocFromIndex(start)
|
|
14522
|
+
},
|
|
14523
|
+
messageId: "useT"
|
|
14524
|
+
});
|
|
14525
|
+
}
|
|
14526
|
+
}
|
|
14527
|
+
}
|
|
14528
|
+
};
|
|
14529
|
+
}
|
|
14530
|
+
};
|
|
14531
|
+
|
|
14532
|
+
const rule$1 = {
|
|
14533
|
+
meta: {
|
|
14534
|
+
docs: {
|
|
14535
|
+
category: "Best Practices",
|
|
14536
|
+
description: "Enforce consistent indentation and sorted keys in i18n blocks",
|
|
14537
|
+
recommended: true
|
|
14538
|
+
},
|
|
14539
|
+
fixable: "whitespace",
|
|
14540
|
+
messages: {
|
|
14541
|
+
indentError: "Invalid indentation for i18n content. Expected {{expected}} spaces.",
|
|
14542
|
+
invalidJson: "Invalid JSON in i18n block: {{error}}",
|
|
14543
|
+
sortError: "Keys in i18n block should be sorted alphabetically."
|
|
14544
|
+
},
|
|
14545
|
+
schema: [],
|
|
14546
|
+
type: "problem"
|
|
14547
|
+
},
|
|
14548
|
+
create(context) {
|
|
14549
|
+
if (!context.filename.endsWith(".vue")) {
|
|
14550
|
+
return {};
|
|
14551
|
+
}
|
|
14552
|
+
function sortObjectKeys(object) {
|
|
14553
|
+
if (Array.isArray(object)) {
|
|
14554
|
+
return object.map(sortObjectKeys);
|
|
14555
|
+
}
|
|
14556
|
+
if (object && typeof object === "object") {
|
|
14557
|
+
const sortedKeys = Object.keys(object).sort();
|
|
14558
|
+
const result = {};
|
|
14559
|
+
const obj = object;
|
|
14560
|
+
for (const key of sortedKeys) {
|
|
14561
|
+
result[key] = sortObjectKeys(obj[key]);
|
|
14562
|
+
}
|
|
14563
|
+
return result;
|
|
14564
|
+
}
|
|
14565
|
+
return object;
|
|
14566
|
+
}
|
|
14567
|
+
return {
|
|
14568
|
+
Program() {
|
|
14569
|
+
const source = context.sourceCode.getText();
|
|
14570
|
+
const i18nMatch = source.match(/(<i18n\s+lang=["']json["']>)([\s\S]*?)(<\/i18n>)/i);
|
|
14571
|
+
if (i18nMatch) {
|
|
14572
|
+
const startOffset = i18nMatch.index + i18nMatch[1].length;
|
|
14573
|
+
const i18nContent = i18nMatch[2];
|
|
14574
|
+
try {
|
|
14575
|
+
const parsed = JSON.parse(i18nContent.trim());
|
|
14576
|
+
const totalSpaces = 2;
|
|
14577
|
+
const sortedParsed = sortObjectKeys(parsed);
|
|
14578
|
+
const formattedContent = `
|
|
14579
|
+
${JSON.stringify(sortedParsed, null, totalSpaces).replace(/\n\n+/g, "\n")}
|
|
14580
|
+
`;
|
|
14581
|
+
if (formattedContent.trim() !== i18nContent.trim()) {
|
|
14582
|
+
const currentKeys = JSON.stringify(parsed, null, totalSpaces).trim();
|
|
14583
|
+
const sortedKeys = JSON.stringify(sortedParsed, null, totalSpaces).trim();
|
|
14584
|
+
context.report({
|
|
14585
|
+
data: { expected: String(totalSpaces) },
|
|
14586
|
+
fix(fixer) {
|
|
14587
|
+
return fixer.replaceTextRange(
|
|
14588
|
+
[startOffset, startOffset + i18nContent.length],
|
|
14589
|
+
formattedContent
|
|
14590
|
+
);
|
|
14591
|
+
},
|
|
14592
|
+
loc: {
|
|
14593
|
+
end: context.sourceCode.getLocFromIndex(startOffset + i18nContent.length),
|
|
14594
|
+
start: context.sourceCode.getLocFromIndex(startOffset)
|
|
14595
|
+
},
|
|
14596
|
+
messageId: currentKeys !== sortedKeys ? "sortError" : "indentError"
|
|
14597
|
+
});
|
|
14598
|
+
}
|
|
14599
|
+
} catch (error) {
|
|
14600
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
14601
|
+
context.report({
|
|
14602
|
+
data: { error: errorMessage },
|
|
14603
|
+
loc: {
|
|
14604
|
+
end: context.sourceCode.getLocFromIndex(startOffset + i18nContent.length),
|
|
14605
|
+
start: context.sourceCode.getLocFromIndex(startOffset)
|
|
14606
|
+
},
|
|
14607
|
+
messageId: "invalidJson"
|
|
14608
|
+
});
|
|
14609
|
+
}
|
|
14610
|
+
}
|
|
14611
|
+
}
|
|
14612
|
+
};
|
|
14613
|
+
}
|
|
14614
|
+
};
|
|
14615
|
+
|
|
14616
|
+
const rule = {
|
|
14617
|
+
meta: {
|
|
14618
|
+
docs: {
|
|
14619
|
+
category: "Best Practices",
|
|
14620
|
+
description: "Detect unused strings in the English locale",
|
|
14621
|
+
recommended: true
|
|
14622
|
+
},
|
|
14623
|
+
messages: {
|
|
14624
|
+
invalidJson: "Invalid JSON in i18n block: {{error}}",
|
|
14625
|
+
unusedString: 'Unused string in English locale: "{{key}}"'
|
|
14626
|
+
},
|
|
14627
|
+
schema: [],
|
|
14628
|
+
type: "problem"
|
|
14629
|
+
},
|
|
14630
|
+
create(context) {
|
|
14631
|
+
if (!context.filename.endsWith(".vue")) {
|
|
14632
|
+
return {};
|
|
14633
|
+
}
|
|
14634
|
+
return {
|
|
14635
|
+
Program() {
|
|
14636
|
+
const source = context.sourceCode.getText();
|
|
14637
|
+
const i18nMatch = source.match(/(<i18n\s+lang=["']json["']>)([\s\S]*?)(<\/i18n>)/i);
|
|
14638
|
+
if (!i18nMatch) {
|
|
14639
|
+
return;
|
|
14640
|
+
}
|
|
14641
|
+
const startOffset = i18nMatch.index + i18nMatch[1].length;
|
|
14642
|
+
const i18nContent = i18nMatch[2].trim();
|
|
14643
|
+
try {
|
|
14644
|
+
const parsed = JSON.parse(i18nContent);
|
|
14645
|
+
if (!parsed.en) {
|
|
14646
|
+
return;
|
|
14647
|
+
}
|
|
14648
|
+
const templateMatch = source.match(/<template>([\s\S]*)<\/template>/i);
|
|
14649
|
+
const templateContent = templateMatch ? templateMatch[1] : "";
|
|
14650
|
+
const scriptMatch = source.match(/<script[^>]*>([\s\S]*?)<\/script>/i);
|
|
14651
|
+
const scriptContent = scriptMatch ? scriptMatch[1] : "";
|
|
14652
|
+
const enKeys = getAllKeys(parsed.en);
|
|
14653
|
+
for (const key of enKeys) {
|
|
14654
|
+
const isUsed = templateContent.includes(key) || scriptContent.includes(key);
|
|
14655
|
+
if (!isUsed) {
|
|
14656
|
+
const keyMatch = new RegExp(`"${key}"\\s*:`, "g").exec(i18nContent);
|
|
14657
|
+
if (keyMatch) {
|
|
14658
|
+
const keyOffset = startOffset + keyMatch.index;
|
|
14659
|
+
context.report({
|
|
14660
|
+
data: { key },
|
|
14661
|
+
loc: {
|
|
14662
|
+
end: context.sourceCode.getLocFromIndex(keyOffset + key.length + 2),
|
|
14663
|
+
start: context.sourceCode.getLocFromIndex(keyOffset)
|
|
14664
|
+
},
|
|
14665
|
+
messageId: "unusedString"
|
|
14666
|
+
});
|
|
14667
|
+
}
|
|
14668
|
+
}
|
|
14669
|
+
}
|
|
14670
|
+
} catch (error) {
|
|
14671
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
14672
|
+
context.report({
|
|
14673
|
+
data: { error: errorMessage },
|
|
14674
|
+
loc: {
|
|
14675
|
+
end: context.sourceCode.getLocFromIndex(startOffset + i18nContent.length),
|
|
14676
|
+
start: context.sourceCode.getLocFromIndex(startOffset)
|
|
14677
|
+
},
|
|
14678
|
+
messageId: "invalidJson"
|
|
14679
|
+
});
|
|
14680
|
+
}
|
|
14681
|
+
}
|
|
14682
|
+
};
|
|
14683
|
+
function getAllKeys(object, prefix = "") {
|
|
14684
|
+
let keys = [];
|
|
14685
|
+
for (const key in object) {
|
|
14686
|
+
const newPrefix = prefix ? `${prefix}.${key}` : key;
|
|
14687
|
+
if (typeof object[key] === "object" && object[key] !== null) {
|
|
14688
|
+
keys = [...keys, ...getAllKeys(object[key], newPrefix)];
|
|
14689
|
+
} else {
|
|
14690
|
+
keys.push(newPrefix);
|
|
14691
|
+
}
|
|
14692
|
+
}
|
|
14693
|
+
return keys;
|
|
14694
|
+
}
|
|
14695
|
+
}
|
|
14696
|
+
};
|
|
14697
|
+
|
|
14331
14698
|
const index = {
|
|
14332
14699
|
rules: {
|
|
14333
|
-
"ts-multiline-ternary": rule$
|
|
14334
|
-
"ts-multiline-union": rule$
|
|
14335
|
-
"ts-sort-tests": rule
|
|
14336
|
-
|
|
14337
|
-
|
|
14338
|
-
|
|
14339
|
-
|
|
14700
|
+
"ts-multiline-ternary": rule$6,
|
|
14701
|
+
"ts-multiline-union": rule$5,
|
|
14702
|
+
"ts-sort-tests": rule$4,
|
|
14703
|
+
"vue-i18n-consistent-locales": rule$3,
|
|
14704
|
+
"vue-i18n-consistent-t": rule$2,
|
|
14705
|
+
"vue-i18n-sort-keys": rule$1,
|
|
14706
|
+
"vue-i18n-unused-strings": rule
|
|
14340
14707
|
// 'vue-script-format-computed': vueScriptFormatComputed,
|
|
14341
14708
|
// 'vue-script-format-emits': vueScriptFormatEmits,
|
|
14342
14709
|
// 'vue-script-format-props': vueScriptFormatProps,
|
package/dist/index.d.cts
CHANGED
|
@@ -5,6 +5,10 @@ declare const _default: {
|
|
|
5
5
|
'ts-multiline-ternary': eslint.Rule.RuleModule;
|
|
6
6
|
'ts-multiline-union': eslint.Rule.RuleModule;
|
|
7
7
|
'ts-sort-tests': eslint.Rule.RuleModule;
|
|
8
|
+
'vue-i18n-consistent-locales': eslint.Rule.RuleModule;
|
|
9
|
+
'vue-i18n-consistent-t': eslint.Rule.RuleModule;
|
|
10
|
+
'vue-i18n-sort-keys': eslint.Rule.RuleModule;
|
|
11
|
+
'vue-i18n-unused-strings': eslint.Rule.RuleModule;
|
|
8
12
|
};
|
|
9
13
|
};
|
|
10
14
|
|
package/dist/index.d.mts
CHANGED
|
@@ -5,6 +5,10 @@ declare const _default: {
|
|
|
5
5
|
'ts-multiline-ternary': eslint.Rule.RuleModule;
|
|
6
6
|
'ts-multiline-union': eslint.Rule.RuleModule;
|
|
7
7
|
'ts-sort-tests': eslint.Rule.RuleModule;
|
|
8
|
+
'vue-i18n-consistent-locales': eslint.Rule.RuleModule;
|
|
9
|
+
'vue-i18n-consistent-t': eslint.Rule.RuleModule;
|
|
10
|
+
'vue-i18n-sort-keys': eslint.Rule.RuleModule;
|
|
11
|
+
'vue-i18n-unused-strings': eslint.Rule.RuleModule;
|
|
8
12
|
};
|
|
9
13
|
};
|
|
10
14
|
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,10 @@ declare const _default: {
|
|
|
5
5
|
'ts-multiline-ternary': eslint.Rule.RuleModule;
|
|
6
6
|
'ts-multiline-union': eslint.Rule.RuleModule;
|
|
7
7
|
'ts-sort-tests': eslint.Rule.RuleModule;
|
|
8
|
+
'vue-i18n-consistent-locales': eslint.Rule.RuleModule;
|
|
9
|
+
'vue-i18n-consistent-t': eslint.Rule.RuleModule;
|
|
10
|
+
'vue-i18n-sort-keys': eslint.Rule.RuleModule;
|
|
11
|
+
'vue-i18n-unused-strings': eslint.Rule.RuleModule;
|
|
8
12
|
};
|
|
9
13
|
};
|
|
10
14
|
|
package/dist/index.mjs
CHANGED
|
@@ -14077,7 +14077,7 @@ function requireDist () {
|
|
|
14077
14077
|
|
|
14078
14078
|
var distExports = requireDist();
|
|
14079
14079
|
|
|
14080
|
-
const rule$
|
|
14080
|
+
const rule$6 = {
|
|
14081
14081
|
meta: {
|
|
14082
14082
|
docs: {
|
|
14083
14083
|
category: "Stylistic Issues",
|
|
@@ -14140,7 +14140,7 @@ const rule$2 = {
|
|
|
14140
14140
|
}
|
|
14141
14141
|
};
|
|
14142
14142
|
|
|
14143
|
-
const rule$
|
|
14143
|
+
const rule$5 = {
|
|
14144
14144
|
meta: {
|
|
14145
14145
|
docs: {
|
|
14146
14146
|
category: "Stylistic Issues",
|
|
@@ -14206,7 +14206,7 @@ const rule$1 = {
|
|
|
14206
14206
|
}
|
|
14207
14207
|
};
|
|
14208
14208
|
|
|
14209
|
-
const rule = {
|
|
14209
|
+
const rule$4 = {
|
|
14210
14210
|
meta: {
|
|
14211
14211
|
docs: {
|
|
14212
14212
|
category: "Best Practices",
|
|
@@ -14321,15 +14321,382 @@ const rule = {
|
|
|
14321
14321
|
}
|
|
14322
14322
|
};
|
|
14323
14323
|
|
|
14324
|
+
const rule$3 = {
|
|
14325
|
+
meta: {
|
|
14326
|
+
docs: {
|
|
14327
|
+
category: "Possible Errors",
|
|
14328
|
+
description: "Enforce consistent i18n locale keys across translations",
|
|
14329
|
+
recommended: true
|
|
14330
|
+
},
|
|
14331
|
+
messages: {
|
|
14332
|
+
invalidJson: "Invalid JSON in i18n block: {{error}}",
|
|
14333
|
+
invalidLocale: "Invalid locale: {{locale}}. Allowed locales are: {{allowed}}",
|
|
14334
|
+
missingLocale: "Missing required locale: {{locale}}",
|
|
14335
|
+
missingTranslations: 'Missing translations in "{{locale}}" locale: {{missing}}'
|
|
14336
|
+
},
|
|
14337
|
+
schema: [
|
|
14338
|
+
{
|
|
14339
|
+
additionalProperties: false,
|
|
14340
|
+
properties: {
|
|
14341
|
+
locales: {
|
|
14342
|
+
items: { type: "string" },
|
|
14343
|
+
type: "array"
|
|
14344
|
+
}
|
|
14345
|
+
},
|
|
14346
|
+
type: "object"
|
|
14347
|
+
}
|
|
14348
|
+
],
|
|
14349
|
+
type: "problem"
|
|
14350
|
+
},
|
|
14351
|
+
create(context) {
|
|
14352
|
+
if (!context.filename.endsWith(".vue")) {
|
|
14353
|
+
return {};
|
|
14354
|
+
}
|
|
14355
|
+
const locales = context.options[0]?.locales || ["en", "fr"];
|
|
14356
|
+
return {
|
|
14357
|
+
Program() {
|
|
14358
|
+
const source = context.sourceCode.getText();
|
|
14359
|
+
const i18nMatch = source.match(/(<i18n\s+lang=["']json["']>)([\s\S]*?)(<\/i18n>)/i);
|
|
14360
|
+
if (i18nMatch) {
|
|
14361
|
+
const startOffset = i18nMatch.index + i18nMatch[1].length;
|
|
14362
|
+
const i18nContent = i18nMatch[2].trim();
|
|
14363
|
+
try {
|
|
14364
|
+
const parsed = JSON.parse(i18nContent);
|
|
14365
|
+
for (const locale of locales) {
|
|
14366
|
+
if (!parsed[locale]) {
|
|
14367
|
+
context.report({
|
|
14368
|
+
data: { locale },
|
|
14369
|
+
loc: {
|
|
14370
|
+
end: context.sourceCode.getLocFromIndex(startOffset + i18nContent.length),
|
|
14371
|
+
start: context.sourceCode.getLocFromIndex(startOffset)
|
|
14372
|
+
},
|
|
14373
|
+
messageId: "missingLocale"
|
|
14374
|
+
});
|
|
14375
|
+
}
|
|
14376
|
+
}
|
|
14377
|
+
for (const locale of Object.keys(parsed)) {
|
|
14378
|
+
if (!locales.includes(locale)) {
|
|
14379
|
+
const localeMatch = new RegExp(`"${locale}"\\s*:`, "g").exec(i18nContent);
|
|
14380
|
+
if (localeMatch) {
|
|
14381
|
+
const localeOffset = startOffset + localeMatch.index;
|
|
14382
|
+
context.report({
|
|
14383
|
+
data: {
|
|
14384
|
+
allowed: locales.join(", "),
|
|
14385
|
+
locale
|
|
14386
|
+
},
|
|
14387
|
+
loc: {
|
|
14388
|
+
end: context.sourceCode.getLocFromIndex(localeOffset + locale.length + 2),
|
|
14389
|
+
start: context.sourceCode.getLocFromIndex(localeOffset)
|
|
14390
|
+
},
|
|
14391
|
+
messageId: "invalidLocale"
|
|
14392
|
+
});
|
|
14393
|
+
}
|
|
14394
|
+
}
|
|
14395
|
+
}
|
|
14396
|
+
const allKeys = /* @__PURE__ */ new Set();
|
|
14397
|
+
for (const locale of locales) {
|
|
14398
|
+
if (parsed[locale]) {
|
|
14399
|
+
const keys = getAllKeys(parsed[locale]);
|
|
14400
|
+
keys.forEach((key) => allKeys.add(key));
|
|
14401
|
+
}
|
|
14402
|
+
}
|
|
14403
|
+
for (const locale of locales) {
|
|
14404
|
+
if (parsed[locale]) {
|
|
14405
|
+
const localeKeys = getAllKeys(parsed[locale]);
|
|
14406
|
+
const missingKeys = [...allKeys].filter((key) => !localeKeys.includes(key));
|
|
14407
|
+
if (missingKeys.length > 0) {
|
|
14408
|
+
const localeMatch = new RegExp(`"${locale}"\\s*:\\s*{`, "g").exec(i18nContent);
|
|
14409
|
+
if (localeMatch) {
|
|
14410
|
+
const localeOffset = startOffset + localeMatch.index;
|
|
14411
|
+
context.report({
|
|
14412
|
+
data: {
|
|
14413
|
+
locale,
|
|
14414
|
+
missing: missingKeys.join(", ")
|
|
14415
|
+
},
|
|
14416
|
+
loc: {
|
|
14417
|
+
end: context.sourceCode.getLocFromIndex(localeOffset + locale.length + 2),
|
|
14418
|
+
start: context.sourceCode.getLocFromIndex(localeOffset)
|
|
14419
|
+
},
|
|
14420
|
+
messageId: "missingTranslations"
|
|
14421
|
+
});
|
|
14422
|
+
}
|
|
14423
|
+
}
|
|
14424
|
+
}
|
|
14425
|
+
}
|
|
14426
|
+
} catch (error) {
|
|
14427
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
14428
|
+
context.report({
|
|
14429
|
+
data: { error: errorMessage },
|
|
14430
|
+
loc: {
|
|
14431
|
+
end: context.sourceCode.getLocFromIndex(startOffset + i18nContent.length),
|
|
14432
|
+
start: context.sourceCode.getLocFromIndex(startOffset)
|
|
14433
|
+
},
|
|
14434
|
+
messageId: "invalidJson"
|
|
14435
|
+
});
|
|
14436
|
+
}
|
|
14437
|
+
}
|
|
14438
|
+
function getAllKeys(object, prefix = "") {
|
|
14439
|
+
let keys = [];
|
|
14440
|
+
for (const key in object) {
|
|
14441
|
+
const newPrefix = prefix ? `${prefix}.${key}` : key;
|
|
14442
|
+
if (typeof object[key] === "object" && object[key] !== null) {
|
|
14443
|
+
keys = [...keys, ...getAllKeys(object[key], newPrefix)];
|
|
14444
|
+
} else {
|
|
14445
|
+
keys.push(newPrefix);
|
|
14446
|
+
}
|
|
14447
|
+
}
|
|
14448
|
+
return keys;
|
|
14449
|
+
}
|
|
14450
|
+
}
|
|
14451
|
+
};
|
|
14452
|
+
}
|
|
14453
|
+
};
|
|
14454
|
+
|
|
14455
|
+
const rule$2 = {
|
|
14456
|
+
meta: {
|
|
14457
|
+
docs: {
|
|
14458
|
+
category: "Best Practices",
|
|
14459
|
+
description: "Enforce using t() instead of $t() in Vue templates",
|
|
14460
|
+
recommended: true
|
|
14461
|
+
},
|
|
14462
|
+
fixable: "code",
|
|
14463
|
+
messages: { useT: "Use t() instead of $t() in Vue templates as it does not work with <i18n> tags." },
|
|
14464
|
+
schema: [],
|
|
14465
|
+
type: "problem"
|
|
14466
|
+
},
|
|
14467
|
+
create(context) {
|
|
14468
|
+
if (!context.filename.endsWith(".vue")) {
|
|
14469
|
+
return {};
|
|
14470
|
+
}
|
|
14471
|
+
return {
|
|
14472
|
+
Program() {
|
|
14473
|
+
const sourceCode = context.sourceCode;
|
|
14474
|
+
const source = sourceCode.getText();
|
|
14475
|
+
const templateMatch = source.match(/<template>([\s\S]*)<\/template>/i);
|
|
14476
|
+
if (!templateMatch || templateMatch.index === void 0) {
|
|
14477
|
+
return;
|
|
14478
|
+
}
|
|
14479
|
+
const templateContent = templateMatch[1];
|
|
14480
|
+
const tPatterns = [
|
|
14481
|
+
{
|
|
14482
|
+
pattern: / \$t\(/g,
|
|
14483
|
+
quote: " "
|
|
14484
|
+
},
|
|
14485
|
+
{
|
|
14486
|
+
pattern: /"\$t\(/g,
|
|
14487
|
+
quote: '"'
|
|
14488
|
+
},
|
|
14489
|
+
{
|
|
14490
|
+
pattern: /`\$t\(/g,
|
|
14491
|
+
quote: "`"
|
|
14492
|
+
},
|
|
14493
|
+
{
|
|
14494
|
+
pattern: /\{\$t\(/g,
|
|
14495
|
+
quote: "{"
|
|
14496
|
+
},
|
|
14497
|
+
{
|
|
14498
|
+
pattern: /\[\$t\(/g,
|
|
14499
|
+
quote: "["
|
|
14500
|
+
}
|
|
14501
|
+
];
|
|
14502
|
+
for (const { pattern, quote } of tPatterns) {
|
|
14503
|
+
let match;
|
|
14504
|
+
while ((match = pattern.exec(templateContent)) !== null) {
|
|
14505
|
+
const templateStart = templateMatch.index + templateMatch[0].indexOf(templateContent);
|
|
14506
|
+
const start = templateStart + match.index;
|
|
14507
|
+
const end = start + 4;
|
|
14508
|
+
context.report({
|
|
14509
|
+
fix(fixer) {
|
|
14510
|
+
return fixer.replaceTextRange([start, end], `${quote}t(`);
|
|
14511
|
+
},
|
|
14512
|
+
loc: {
|
|
14513
|
+
end: sourceCode.getLocFromIndex(end),
|
|
14514
|
+
start: sourceCode.getLocFromIndex(start)
|
|
14515
|
+
},
|
|
14516
|
+
messageId: "useT"
|
|
14517
|
+
});
|
|
14518
|
+
}
|
|
14519
|
+
}
|
|
14520
|
+
}
|
|
14521
|
+
};
|
|
14522
|
+
}
|
|
14523
|
+
};
|
|
14524
|
+
|
|
14525
|
+
const rule$1 = {
|
|
14526
|
+
meta: {
|
|
14527
|
+
docs: {
|
|
14528
|
+
category: "Best Practices",
|
|
14529
|
+
description: "Enforce consistent indentation and sorted keys in i18n blocks",
|
|
14530
|
+
recommended: true
|
|
14531
|
+
},
|
|
14532
|
+
fixable: "whitespace",
|
|
14533
|
+
messages: {
|
|
14534
|
+
indentError: "Invalid indentation for i18n content. Expected {{expected}} spaces.",
|
|
14535
|
+
invalidJson: "Invalid JSON in i18n block: {{error}}",
|
|
14536
|
+
sortError: "Keys in i18n block should be sorted alphabetically."
|
|
14537
|
+
},
|
|
14538
|
+
schema: [],
|
|
14539
|
+
type: "problem"
|
|
14540
|
+
},
|
|
14541
|
+
create(context) {
|
|
14542
|
+
if (!context.filename.endsWith(".vue")) {
|
|
14543
|
+
return {};
|
|
14544
|
+
}
|
|
14545
|
+
function sortObjectKeys(object) {
|
|
14546
|
+
if (Array.isArray(object)) {
|
|
14547
|
+
return object.map(sortObjectKeys);
|
|
14548
|
+
}
|
|
14549
|
+
if (object && typeof object === "object") {
|
|
14550
|
+
const sortedKeys = Object.keys(object).sort();
|
|
14551
|
+
const result = {};
|
|
14552
|
+
const obj = object;
|
|
14553
|
+
for (const key of sortedKeys) {
|
|
14554
|
+
result[key] = sortObjectKeys(obj[key]);
|
|
14555
|
+
}
|
|
14556
|
+
return result;
|
|
14557
|
+
}
|
|
14558
|
+
return object;
|
|
14559
|
+
}
|
|
14560
|
+
return {
|
|
14561
|
+
Program() {
|
|
14562
|
+
const source = context.sourceCode.getText();
|
|
14563
|
+
const i18nMatch = source.match(/(<i18n\s+lang=["']json["']>)([\s\S]*?)(<\/i18n>)/i);
|
|
14564
|
+
if (i18nMatch) {
|
|
14565
|
+
const startOffset = i18nMatch.index + i18nMatch[1].length;
|
|
14566
|
+
const i18nContent = i18nMatch[2];
|
|
14567
|
+
try {
|
|
14568
|
+
const parsed = JSON.parse(i18nContent.trim());
|
|
14569
|
+
const totalSpaces = 2;
|
|
14570
|
+
const sortedParsed = sortObjectKeys(parsed);
|
|
14571
|
+
const formattedContent = `
|
|
14572
|
+
${JSON.stringify(sortedParsed, null, totalSpaces).replace(/\n\n+/g, "\n")}
|
|
14573
|
+
`;
|
|
14574
|
+
if (formattedContent.trim() !== i18nContent.trim()) {
|
|
14575
|
+
const currentKeys = JSON.stringify(parsed, null, totalSpaces).trim();
|
|
14576
|
+
const sortedKeys = JSON.stringify(sortedParsed, null, totalSpaces).trim();
|
|
14577
|
+
context.report({
|
|
14578
|
+
data: { expected: String(totalSpaces) },
|
|
14579
|
+
fix(fixer) {
|
|
14580
|
+
return fixer.replaceTextRange(
|
|
14581
|
+
[startOffset, startOffset + i18nContent.length],
|
|
14582
|
+
formattedContent
|
|
14583
|
+
);
|
|
14584
|
+
},
|
|
14585
|
+
loc: {
|
|
14586
|
+
end: context.sourceCode.getLocFromIndex(startOffset + i18nContent.length),
|
|
14587
|
+
start: context.sourceCode.getLocFromIndex(startOffset)
|
|
14588
|
+
},
|
|
14589
|
+
messageId: currentKeys !== sortedKeys ? "sortError" : "indentError"
|
|
14590
|
+
});
|
|
14591
|
+
}
|
|
14592
|
+
} catch (error) {
|
|
14593
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
14594
|
+
context.report({
|
|
14595
|
+
data: { error: errorMessage },
|
|
14596
|
+
loc: {
|
|
14597
|
+
end: context.sourceCode.getLocFromIndex(startOffset + i18nContent.length),
|
|
14598
|
+
start: context.sourceCode.getLocFromIndex(startOffset)
|
|
14599
|
+
},
|
|
14600
|
+
messageId: "invalidJson"
|
|
14601
|
+
});
|
|
14602
|
+
}
|
|
14603
|
+
}
|
|
14604
|
+
}
|
|
14605
|
+
};
|
|
14606
|
+
}
|
|
14607
|
+
};
|
|
14608
|
+
|
|
14609
|
+
const rule = {
|
|
14610
|
+
meta: {
|
|
14611
|
+
docs: {
|
|
14612
|
+
category: "Best Practices",
|
|
14613
|
+
description: "Detect unused strings in the English locale",
|
|
14614
|
+
recommended: true
|
|
14615
|
+
},
|
|
14616
|
+
messages: {
|
|
14617
|
+
invalidJson: "Invalid JSON in i18n block: {{error}}",
|
|
14618
|
+
unusedString: 'Unused string in English locale: "{{key}}"'
|
|
14619
|
+
},
|
|
14620
|
+
schema: [],
|
|
14621
|
+
type: "problem"
|
|
14622
|
+
},
|
|
14623
|
+
create(context) {
|
|
14624
|
+
if (!context.filename.endsWith(".vue")) {
|
|
14625
|
+
return {};
|
|
14626
|
+
}
|
|
14627
|
+
return {
|
|
14628
|
+
Program() {
|
|
14629
|
+
const source = context.sourceCode.getText();
|
|
14630
|
+
const i18nMatch = source.match(/(<i18n\s+lang=["']json["']>)([\s\S]*?)(<\/i18n>)/i);
|
|
14631
|
+
if (!i18nMatch) {
|
|
14632
|
+
return;
|
|
14633
|
+
}
|
|
14634
|
+
const startOffset = i18nMatch.index + i18nMatch[1].length;
|
|
14635
|
+
const i18nContent = i18nMatch[2].trim();
|
|
14636
|
+
try {
|
|
14637
|
+
const parsed = JSON.parse(i18nContent);
|
|
14638
|
+
if (!parsed.en) {
|
|
14639
|
+
return;
|
|
14640
|
+
}
|
|
14641
|
+
const templateMatch = source.match(/<template>([\s\S]*)<\/template>/i);
|
|
14642
|
+
const templateContent = templateMatch ? templateMatch[1] : "";
|
|
14643
|
+
const scriptMatch = source.match(/<script[^>]*>([\s\S]*?)<\/script>/i);
|
|
14644
|
+
const scriptContent = scriptMatch ? scriptMatch[1] : "";
|
|
14645
|
+
const enKeys = getAllKeys(parsed.en);
|
|
14646
|
+
for (const key of enKeys) {
|
|
14647
|
+
const isUsed = templateContent.includes(key) || scriptContent.includes(key);
|
|
14648
|
+
if (!isUsed) {
|
|
14649
|
+
const keyMatch = new RegExp(`"${key}"\\s*:`, "g").exec(i18nContent);
|
|
14650
|
+
if (keyMatch) {
|
|
14651
|
+
const keyOffset = startOffset + keyMatch.index;
|
|
14652
|
+
context.report({
|
|
14653
|
+
data: { key },
|
|
14654
|
+
loc: {
|
|
14655
|
+
end: context.sourceCode.getLocFromIndex(keyOffset + key.length + 2),
|
|
14656
|
+
start: context.sourceCode.getLocFromIndex(keyOffset)
|
|
14657
|
+
},
|
|
14658
|
+
messageId: "unusedString"
|
|
14659
|
+
});
|
|
14660
|
+
}
|
|
14661
|
+
}
|
|
14662
|
+
}
|
|
14663
|
+
} catch (error) {
|
|
14664
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
14665
|
+
context.report({
|
|
14666
|
+
data: { error: errorMessage },
|
|
14667
|
+
loc: {
|
|
14668
|
+
end: context.sourceCode.getLocFromIndex(startOffset + i18nContent.length),
|
|
14669
|
+
start: context.sourceCode.getLocFromIndex(startOffset)
|
|
14670
|
+
},
|
|
14671
|
+
messageId: "invalidJson"
|
|
14672
|
+
});
|
|
14673
|
+
}
|
|
14674
|
+
}
|
|
14675
|
+
};
|
|
14676
|
+
function getAllKeys(object, prefix = "") {
|
|
14677
|
+
let keys = [];
|
|
14678
|
+
for (const key in object) {
|
|
14679
|
+
const newPrefix = prefix ? `${prefix}.${key}` : key;
|
|
14680
|
+
if (typeof object[key] === "object" && object[key] !== null) {
|
|
14681
|
+
keys = [...keys, ...getAllKeys(object[key], newPrefix)];
|
|
14682
|
+
} else {
|
|
14683
|
+
keys.push(newPrefix);
|
|
14684
|
+
}
|
|
14685
|
+
}
|
|
14686
|
+
return keys;
|
|
14687
|
+
}
|
|
14688
|
+
}
|
|
14689
|
+
};
|
|
14690
|
+
|
|
14324
14691
|
const index = {
|
|
14325
14692
|
rules: {
|
|
14326
|
-
"ts-multiline-ternary": rule$
|
|
14327
|
-
"ts-multiline-union": rule$
|
|
14328
|
-
"ts-sort-tests": rule
|
|
14329
|
-
|
|
14330
|
-
|
|
14331
|
-
|
|
14332
|
-
|
|
14693
|
+
"ts-multiline-ternary": rule$6,
|
|
14694
|
+
"ts-multiline-union": rule$5,
|
|
14695
|
+
"ts-sort-tests": rule$4,
|
|
14696
|
+
"vue-i18n-consistent-locales": rule$3,
|
|
14697
|
+
"vue-i18n-consistent-t": rule$2,
|
|
14698
|
+
"vue-i18n-sort-keys": rule$1,
|
|
14699
|
+
"vue-i18n-unused-strings": rule
|
|
14333
14700
|
// 'vue-script-format-computed': vueScriptFormatComputed,
|
|
14334
14701
|
// 'vue-script-format-emits': vueScriptFormatEmits,
|
|
14335
14702
|
// 'vue-script-format-props': vueScriptFormatProps,
|