@intl-party/eslint-plugin 1.0.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +372 -8
- package/package.json +14 -6
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2025-2026 IntlParty Team
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -27,7 +37,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
27
37
|
// src/rules/no-hardcoded-strings.ts
|
|
28
38
|
var import_utils = require("@typescript-eslint/utils");
|
|
29
39
|
var noHardcodedStrings = import_utils.ESLintUtils.RuleCreator(
|
|
30
|
-
(name) => `https://github.com/
|
|
40
|
+
(name) => `https://github.com/RodrigoEspinosa/intl-party/blob/main/packages/eslint-plugin/docs/rules/${name}.md`
|
|
31
41
|
)({
|
|
32
42
|
name: "no-hardcoded-strings",
|
|
33
43
|
meta: {
|
|
@@ -162,8 +172,297 @@ var noHardcodedStrings = import_utils.ESLintUtils.RuleCreator(
|
|
|
162
172
|
|
|
163
173
|
// src/rules/no-missing-keys.ts
|
|
164
174
|
var import_utils2 = require("@typescript-eslint/utils");
|
|
175
|
+
|
|
176
|
+
// src/utils/translation-utils.ts
|
|
177
|
+
var import_promises = __toESM(require("fs/promises"));
|
|
178
|
+
var import_node_path = __toESM(require("path"));
|
|
179
|
+
var translationCache = /* @__PURE__ */ new Map();
|
|
180
|
+
var TranslationUtils = class {
|
|
181
|
+
constructor(options = {}) {
|
|
182
|
+
this.options = {
|
|
183
|
+
defaultLocale: "en",
|
|
184
|
+
cacheTimeout: 5 * 60 * 1e3,
|
|
185
|
+
// 5 minutes
|
|
186
|
+
...options
|
|
187
|
+
};
|
|
188
|
+
this.cacheTimeout = this.options.cacheTimeout;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Load translations from configuration or provided files
|
|
192
|
+
*/
|
|
193
|
+
async loadTranslations() {
|
|
194
|
+
const cacheKey = this.getCacheKey();
|
|
195
|
+
const now = Date.now();
|
|
196
|
+
const cached = translationCache.get(cacheKey);
|
|
197
|
+
if (cached && now - cached.timestamp < this.cacheTimeout) {
|
|
198
|
+
return cached.translations;
|
|
199
|
+
}
|
|
200
|
+
let translations;
|
|
201
|
+
try {
|
|
202
|
+
translations = await this.loadFromConfig();
|
|
203
|
+
} catch {
|
|
204
|
+
translations = await this.loadFromFiles();
|
|
205
|
+
}
|
|
206
|
+
translationCache.set(cacheKey, {
|
|
207
|
+
translations,
|
|
208
|
+
timestamp: now,
|
|
209
|
+
locales: Object.keys(translations),
|
|
210
|
+
namespaces: this.extractNamespaces(translations)
|
|
211
|
+
});
|
|
212
|
+
return translations;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Get all available translation keys for a specific locale and namespace
|
|
216
|
+
*/
|
|
217
|
+
async getTranslationKeys(locale, namespace) {
|
|
218
|
+
const translations = await this.loadTranslations();
|
|
219
|
+
const keys = /* @__PURE__ */ new Set();
|
|
220
|
+
if (namespace) {
|
|
221
|
+
const namespaceTranslations = translations[locale]?.[namespace] || {};
|
|
222
|
+
this.collectKeys(namespaceTranslations, "", keys);
|
|
223
|
+
} else {
|
|
224
|
+
const localeTranslations = translations[locale] || {};
|
|
225
|
+
for (const nsTranslations of Object.values(localeTranslations)) {
|
|
226
|
+
this.collectKeys(nsTranslations, "", keys);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return keys;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Check if a translation key exists
|
|
233
|
+
*/
|
|
234
|
+
async hasTranslationKey(locale, key, namespace) {
|
|
235
|
+
const keys = await this.getTranslationKeys(locale, namespace);
|
|
236
|
+
return keys.has(key);
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Get all available locales
|
|
240
|
+
*/
|
|
241
|
+
async getLocales() {
|
|
242
|
+
const translations = await this.loadTranslations();
|
|
243
|
+
return Object.keys(translations);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Get all available namespaces for a locale
|
|
247
|
+
*/
|
|
248
|
+
async getNamespaces(locale) {
|
|
249
|
+
const translations = await this.loadTranslations();
|
|
250
|
+
return Object.keys(translations[locale] || {});
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Validate translation key format
|
|
254
|
+
*/
|
|
255
|
+
isValidTranslationKey(key) {
|
|
256
|
+
return /^[a-zA-Z][a-zA-Z0-9._-]*$/.test(key);
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Extract namespace from a translation key
|
|
260
|
+
*/
|
|
261
|
+
extractNamespace(key) {
|
|
262
|
+
if (key.includes(".")) {
|
|
263
|
+
return key.split(".")[0];
|
|
264
|
+
}
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Get the base key (without namespace) from a translation key
|
|
269
|
+
*/
|
|
270
|
+
getBaseKey(key) {
|
|
271
|
+
if (key.includes(".")) {
|
|
272
|
+
return key.split(".").slice(1).join(".");
|
|
273
|
+
}
|
|
274
|
+
return key;
|
|
275
|
+
}
|
|
276
|
+
getCacheKey() {
|
|
277
|
+
return `${this.options.configPath || "default"}-${this.options.defaultLocale}`;
|
|
278
|
+
}
|
|
279
|
+
async loadFromConfig() {
|
|
280
|
+
const configFiles = [
|
|
281
|
+
this.options.configPath,
|
|
282
|
+
"intl-party.config.js",
|
|
283
|
+
"intl-party.config.ts",
|
|
284
|
+
"intl-party.config.json"
|
|
285
|
+
].filter(Boolean);
|
|
286
|
+
for (const configFile of configFiles) {
|
|
287
|
+
if (configFile && await this.pathExists(configFile)) {
|
|
288
|
+
try {
|
|
289
|
+
let config;
|
|
290
|
+
if (configFile.endsWith(".json")) {
|
|
291
|
+
const content = await import_promises.default.readFile(configFile, "utf-8");
|
|
292
|
+
config = JSON.parse(content);
|
|
293
|
+
} else {
|
|
294
|
+
delete require.cache[import_node_path.default.resolve(configFile)];
|
|
295
|
+
config = require(import_node_path.default.resolve(configFile));
|
|
296
|
+
if (config.default) {
|
|
297
|
+
config = config.default;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return await this.loadFromConfigObject(config);
|
|
301
|
+
} catch (error) {
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
throw new Error("No valid configuration found");
|
|
307
|
+
}
|
|
308
|
+
async loadFromConfigObject(config) {
|
|
309
|
+
const {
|
|
310
|
+
locales = ["en"],
|
|
311
|
+
defaultLocale = "en",
|
|
312
|
+
messages = "./messages"
|
|
313
|
+
} = config;
|
|
314
|
+
const translations = {};
|
|
315
|
+
for (const locale of locales) {
|
|
316
|
+
translations[locale] = {};
|
|
317
|
+
const messagesPath = typeof messages === "string" ? messages : "./messages";
|
|
318
|
+
if (await this.pathExists(messagesPath)) {
|
|
319
|
+
const localePath = import_node_path.default.join(messagesPath, locale);
|
|
320
|
+
if (await this.pathExists(localePath)) {
|
|
321
|
+
const files = await import_promises.default.readdir(localePath);
|
|
322
|
+
for (const file of files) {
|
|
323
|
+
if (file.endsWith(".json")) {
|
|
324
|
+
const namespace = import_node_path.default.basename(file, ".json");
|
|
325
|
+
const filePath = import_node_path.default.join(localePath, file);
|
|
326
|
+
try {
|
|
327
|
+
const content = await this.readJson(filePath);
|
|
328
|
+
translations[locale][namespace] = content;
|
|
329
|
+
} catch {
|
|
330
|
+
translations[locale][namespace] = {};
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return translations;
|
|
338
|
+
}
|
|
339
|
+
async loadFromFiles() {
|
|
340
|
+
const { translationFiles = [], defaultLocale = "en" } = this.options;
|
|
341
|
+
if (translationFiles.length === 0) {
|
|
342
|
+
return await this.autoDetectTranslations();
|
|
343
|
+
}
|
|
344
|
+
const translations = {};
|
|
345
|
+
for (const filePath of translationFiles) {
|
|
346
|
+
try {
|
|
347
|
+
const content = await this.readJson(filePath);
|
|
348
|
+
const { locale, namespace } = this.parseFilePath(filePath);
|
|
349
|
+
if (!translations[locale]) {
|
|
350
|
+
translations[locale] = {};
|
|
351
|
+
}
|
|
352
|
+
translations[locale][namespace] = content;
|
|
353
|
+
} catch {
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return translations;
|
|
358
|
+
}
|
|
359
|
+
async autoDetectTranslations() {
|
|
360
|
+
const translations = {};
|
|
361
|
+
const commonPaths = [
|
|
362
|
+
"messages",
|
|
363
|
+
"locales",
|
|
364
|
+
"i18n",
|
|
365
|
+
"public/locales",
|
|
366
|
+
"src/locales",
|
|
367
|
+
"src/translations"
|
|
368
|
+
];
|
|
369
|
+
for (const basePath of commonPaths) {
|
|
370
|
+
if (await this.pathExists(basePath)) {
|
|
371
|
+
try {
|
|
372
|
+
const entries = await import_promises.default.readdir(basePath);
|
|
373
|
+
for (const entry of entries) {
|
|
374
|
+
const entryPath = import_node_path.default.join(basePath, entry);
|
|
375
|
+
const stat = await import_promises.default.stat(entryPath);
|
|
376
|
+
if (stat.isDirectory()) {
|
|
377
|
+
const locale = entry;
|
|
378
|
+
translations[locale] = {};
|
|
379
|
+
const files = await import_promises.default.readdir(entryPath);
|
|
380
|
+
for (const file of files) {
|
|
381
|
+
if (file.endsWith(".json")) {
|
|
382
|
+
const namespace = import_node_path.default.basename(file, ".json");
|
|
383
|
+
const filePath = import_node_path.default.join(entryPath, file);
|
|
384
|
+
try {
|
|
385
|
+
const content = await this.readJson(filePath);
|
|
386
|
+
translations[locale][namespace] = content;
|
|
387
|
+
} catch {
|
|
388
|
+
translations[locale][namespace] = {};
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
if (Object.keys(translations).length > 0) {
|
|
395
|
+
break;
|
|
396
|
+
}
|
|
397
|
+
} catch {
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return translations;
|
|
403
|
+
}
|
|
404
|
+
parseFilePath(filePath) {
|
|
405
|
+
const parts = filePath.split(import_node_path.default.sep);
|
|
406
|
+
const fileName = parts[parts.length - 1];
|
|
407
|
+
const namespace = import_node_path.default.basename(fileName, ".json");
|
|
408
|
+
let locale = this.options.defaultLocale;
|
|
409
|
+
for (let i = parts.length - 2; i >= 0; i--) {
|
|
410
|
+
const part = parts[i];
|
|
411
|
+
if (/^[a-z]{2}(-[A-Z]{2})?$/.test(part)) {
|
|
412
|
+
locale = part;
|
|
413
|
+
break;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return { locale, namespace };
|
|
417
|
+
}
|
|
418
|
+
collectKeys(obj, prefix, keys) {
|
|
419
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
420
|
+
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
421
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
422
|
+
this.collectKeys(value, fullKey, keys);
|
|
423
|
+
} else {
|
|
424
|
+
keys.add(fullKey);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
extractNamespaces(translations) {
|
|
429
|
+
const namespaces = /* @__PURE__ */ new Set();
|
|
430
|
+
for (const localeTranslations of Object.values(translations)) {
|
|
431
|
+
for (const namespace of Object.keys(localeTranslations)) {
|
|
432
|
+
namespaces.add(namespace);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
return Array.from(namespaces);
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Clear the translation cache
|
|
439
|
+
*/
|
|
440
|
+
clearCache() {
|
|
441
|
+
translationCache.clear();
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Check if a path exists (replacement for fs-extra's pathExists)
|
|
445
|
+
*/
|
|
446
|
+
async pathExists(filePath) {
|
|
447
|
+
try {
|
|
448
|
+
await import_promises.default.access(filePath);
|
|
449
|
+
return true;
|
|
450
|
+
} catch {
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Read and parse JSON file (replacement for fs-extra's readJson)
|
|
456
|
+
*/
|
|
457
|
+
async readJson(filePath) {
|
|
458
|
+
const content = await import_promises.default.readFile(filePath, "utf-8");
|
|
459
|
+
return JSON.parse(content);
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
// src/rules/no-missing-keys.ts
|
|
165
464
|
var noMissingKeys = import_utils2.ESLintUtils.RuleCreator(
|
|
166
|
-
(name) => `https://github.com/
|
|
465
|
+
(name) => `https://github.com/RodrigoEspinosa/intl-party/blob/main/packages/eslint-plugin/docs/rules/${name}.md`
|
|
167
466
|
)({
|
|
168
467
|
name: "no-missing-keys",
|
|
169
468
|
meta: {
|
|
@@ -185,6 +484,10 @@ var noMissingKeys = import_utils2.ESLintUtils.RuleCreator(
|
|
|
185
484
|
type: "string",
|
|
186
485
|
default: "en",
|
|
187
486
|
description: "Default locale to check keys against"
|
|
487
|
+
},
|
|
488
|
+
configPath: {
|
|
489
|
+
type: "string",
|
|
490
|
+
description: "Path to intl-party configuration file"
|
|
188
491
|
}
|
|
189
492
|
},
|
|
190
493
|
additionalProperties: false
|
|
@@ -197,12 +500,20 @@ var noMissingKeys = import_utils2.ESLintUtils.RuleCreator(
|
|
|
197
500
|
},
|
|
198
501
|
defaultOptions: [{}],
|
|
199
502
|
create(context, [options]) {
|
|
200
|
-
const {
|
|
201
|
-
|
|
503
|
+
const {
|
|
504
|
+
translationFiles = [],
|
|
505
|
+
defaultLocale = "en",
|
|
506
|
+
configPath
|
|
507
|
+
} = options || {};
|
|
508
|
+
const translationUtils = new TranslationUtils({
|
|
509
|
+
translationFiles,
|
|
510
|
+
defaultLocale,
|
|
511
|
+
configPath
|
|
512
|
+
});
|
|
202
513
|
function isValidTranslationKey(key) {
|
|
203
|
-
return
|
|
514
|
+
return translationUtils.isValidTranslationKey(key);
|
|
204
515
|
}
|
|
205
|
-
function checkTranslationCall(node) {
|
|
516
|
+
async function checkTranslationCall(node) {
|
|
206
517
|
if (node.callee.type === "Identifier" && node.callee.name === "t" && node.arguments.length > 0 && node.arguments[0].type === "Literal" && typeof node.arguments[0].value === "string") {
|
|
207
518
|
const key = node.arguments[0].value;
|
|
208
519
|
if (!isValidTranslationKey(key)) {
|
|
@@ -213,16 +524,69 @@ var noMissingKeys = import_utils2.ESLintUtils.RuleCreator(
|
|
|
213
524
|
});
|
|
214
525
|
return;
|
|
215
526
|
}
|
|
527
|
+
try {
|
|
528
|
+
const namespace = translationUtils.extractNamespace(key);
|
|
529
|
+
const baseKey = translationUtils.getBaseKey(key);
|
|
530
|
+
const hasKey = await translationUtils.hasTranslationKey(
|
|
531
|
+
defaultLocale,
|
|
532
|
+
namespace ? baseKey : key,
|
|
533
|
+
namespace || void 0
|
|
534
|
+
);
|
|
535
|
+
if (!hasKey) {
|
|
536
|
+
context.report({
|
|
537
|
+
node: node.arguments[0],
|
|
538
|
+
messageId: "missingTranslationKey",
|
|
539
|
+
data: { key }
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
} catch (error) {
|
|
543
|
+
}
|
|
216
544
|
}
|
|
217
545
|
}
|
|
218
546
|
function checkUseTranslationsCall(node) {
|
|
219
|
-
if (node.callee.type === "Identifier" && node.callee.name === "useTranslations") {
|
|
547
|
+
if (node.callee.type === "Identifier" && node.callee.name === "useTranslations" && node.arguments.length > 0 && node.arguments[0].type === "Literal" && typeof node.arguments[0].value === "string") {
|
|
548
|
+
const namespace = node.arguments[0].value;
|
|
549
|
+
translationUtils.getNamespaces(defaultLocale).then((namespaces) => {
|
|
550
|
+
if (!namespaces.includes(namespace)) {
|
|
551
|
+
context.report({
|
|
552
|
+
node: node.arguments[0],
|
|
553
|
+
messageId: "missingTranslationKey",
|
|
554
|
+
data: { key: namespace }
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
}).catch(() => {
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
function checkTemplateLiteral(node) {
|
|
562
|
+
for (const quasi of node.quasis) {
|
|
563
|
+
const text = quasi.value.raw;
|
|
564
|
+
const keyMatches = text.match(/[a-zA-Z][a-zA-Z0-9._-]*/g);
|
|
565
|
+
if (keyMatches) {
|
|
566
|
+
for (const potentialKey of keyMatches) {
|
|
567
|
+
if (isValidTranslationKey(potentialKey)) {
|
|
568
|
+
translationUtils.hasTranslationKey(defaultLocale, potentialKey).then((hasKey) => {
|
|
569
|
+
if (!hasKey) {
|
|
570
|
+
context.report({
|
|
571
|
+
node: quasi,
|
|
572
|
+
messageId: "missingTranslationKey",
|
|
573
|
+
data: { key: potentialKey }
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
}).catch(() => {
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
220
581
|
}
|
|
221
582
|
}
|
|
222
583
|
return {
|
|
223
584
|
CallExpression(node) {
|
|
224
585
|
checkTranslationCall(node);
|
|
225
586
|
checkUseTranslationsCall(node);
|
|
587
|
+
},
|
|
588
|
+
TemplateLiteral(node) {
|
|
589
|
+
checkTemplateLiteral(node);
|
|
226
590
|
}
|
|
227
591
|
};
|
|
228
592
|
}
|
|
@@ -231,7 +595,7 @@ var noMissingKeys = import_utils2.ESLintUtils.RuleCreator(
|
|
|
231
595
|
// src/rules/prefer-translation-hooks.ts
|
|
232
596
|
var import_utils3 = require("@typescript-eslint/utils");
|
|
233
597
|
var preferTranslationHooks = import_utils3.ESLintUtils.RuleCreator(
|
|
234
|
-
(name) => `https://github.com/
|
|
598
|
+
(name) => `https://github.com/RodrigoEspinosa/intl-party/blob/main/packages/eslint-plugin/docs/rules/${name}.md`
|
|
235
599
|
)({
|
|
236
600
|
name: "prefer-translation-hooks",
|
|
237
601
|
meta: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intl-party/eslint-plugin",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "ESLint plugin for IntlParty - detect hardcoded strings and enforce i18n best practices",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -15,10 +15,15 @@
|
|
|
15
15
|
"typescript",
|
|
16
16
|
"hardcoded-strings"
|
|
17
17
|
],
|
|
18
|
-
"author": "
|
|
18
|
+
"author": "RodrigoEspinosa",
|
|
19
19
|
"license": "MIT",
|
|
20
|
+
"homepage": "https://github.com/RodrigoEspinosa/intl-party#readme",
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/RodrigoEspinosa/intl-party/issues"
|
|
23
|
+
},
|
|
20
24
|
"dependencies": {
|
|
21
|
-
"@typescript-eslint/utils": "^6.15.0"
|
|
25
|
+
"@typescript-eslint/utils": "^6.15.0",
|
|
26
|
+
"fs-extra": "^11.3.4"
|
|
22
27
|
},
|
|
23
28
|
"devDependencies": {
|
|
24
29
|
"@types/eslint": "^8.56.0",
|
|
@@ -28,18 +33,21 @@
|
|
|
28
33
|
"@typescript-eslint/rule-tester": "^6.15.0",
|
|
29
34
|
"eslint": "^8.55.0",
|
|
30
35
|
"jsdom": "^23.0.1",
|
|
31
|
-
"tsup": "^8.
|
|
36
|
+
"tsup": "^8.5.1",
|
|
32
37
|
"typescript": "^5.3.0",
|
|
33
|
-
"vitest": "^
|
|
38
|
+
"vitest": "^3.2.4"
|
|
34
39
|
},
|
|
35
40
|
"peerDependencies": {
|
|
36
41
|
"eslint": ">=8.0.0"
|
|
37
42
|
},
|
|
38
43
|
"repository": {
|
|
39
44
|
"type": "git",
|
|
40
|
-
"url": "https://github.com/
|
|
45
|
+
"url": "https://github.com/RodrigoEspinosa/intl-party.git",
|
|
41
46
|
"directory": "packages/eslint-plugin"
|
|
42
47
|
},
|
|
48
|
+
"engines": {
|
|
49
|
+
"node": ">=18.0.0"
|
|
50
|
+
},
|
|
43
51
|
"scripts": {
|
|
44
52
|
"build": "tsup src/index.ts --format cjs --dts",
|
|
45
53
|
"dev": "tsup src/index.ts --format cjs --dts --watch",
|