@intl-party/eslint-plugin 1.0.2 → 1.1.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 +2 -0
- package/dist/index.js +380 -8
- package/package.json +12 -4
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,15 @@ 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"
|
|
491
|
+
},
|
|
492
|
+
cacheTimeout: {
|
|
493
|
+
type: "number",
|
|
494
|
+
default: 3e5,
|
|
495
|
+
description: "Cache timeout in milliseconds (default: 5 minutes)"
|
|
188
496
|
}
|
|
189
497
|
},
|
|
190
498
|
additionalProperties: false
|
|
@@ -197,12 +505,23 @@ var noMissingKeys = import_utils2.ESLintUtils.RuleCreator(
|
|
|
197
505
|
},
|
|
198
506
|
defaultOptions: [{}],
|
|
199
507
|
create(context, [options]) {
|
|
200
|
-
const {
|
|
201
|
-
|
|
508
|
+
const {
|
|
509
|
+
translationFiles = [],
|
|
510
|
+
defaultLocale = "en",
|
|
511
|
+
configPath,
|
|
512
|
+
cacheTimeout = 3e5
|
|
513
|
+
} = options || {};
|
|
514
|
+
const translationUtils = new TranslationUtils({
|
|
515
|
+
translationFiles,
|
|
516
|
+
defaultLocale,
|
|
517
|
+
configPath,
|
|
518
|
+
cacheTimeout
|
|
519
|
+
});
|
|
520
|
+
const fileTranslationCache = /* @__PURE__ */ new Map();
|
|
202
521
|
function isValidTranslationKey(key) {
|
|
203
|
-
return
|
|
522
|
+
return translationUtils.isValidTranslationKey(key);
|
|
204
523
|
}
|
|
205
|
-
function checkTranslationCall(node) {
|
|
524
|
+
async function checkTranslationCall(node) {
|
|
206
525
|
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
526
|
const key = node.arguments[0].value;
|
|
208
527
|
if (!isValidTranslationKey(key)) {
|
|
@@ -213,16 +532,69 @@ var noMissingKeys = import_utils2.ESLintUtils.RuleCreator(
|
|
|
213
532
|
});
|
|
214
533
|
return;
|
|
215
534
|
}
|
|
535
|
+
try {
|
|
536
|
+
const namespace = translationUtils.extractNamespace(key);
|
|
537
|
+
const baseKey = translationUtils.getBaseKey(key);
|
|
538
|
+
const hasKey = await translationUtils.hasTranslationKey(
|
|
539
|
+
defaultLocale,
|
|
540
|
+
namespace ? baseKey : key,
|
|
541
|
+
namespace || void 0
|
|
542
|
+
);
|
|
543
|
+
if (!hasKey) {
|
|
544
|
+
context.report({
|
|
545
|
+
node: node.arguments[0],
|
|
546
|
+
messageId: "missingTranslationKey",
|
|
547
|
+
data: { key }
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
} catch (error) {
|
|
551
|
+
}
|
|
216
552
|
}
|
|
217
553
|
}
|
|
218
554
|
function checkUseTranslationsCall(node) {
|
|
219
|
-
if (node.callee.type === "Identifier" && node.callee.name === "useTranslations") {
|
|
555
|
+
if (node.callee.type === "Identifier" && node.callee.name === "useTranslations" && node.arguments.length > 0 && node.arguments[0].type === "Literal" && typeof node.arguments[0].value === "string") {
|
|
556
|
+
const namespace = node.arguments[0].value;
|
|
557
|
+
translationUtils.getNamespaces(defaultLocale).then((namespaces) => {
|
|
558
|
+
if (!namespaces.includes(namespace)) {
|
|
559
|
+
context.report({
|
|
560
|
+
node: node.arguments[0],
|
|
561
|
+
messageId: "missingTranslationKey",
|
|
562
|
+
data: { key: namespace }
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
}).catch(() => {
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
function checkTemplateLiteral(node) {
|
|
570
|
+
for (const quasi of node.quasis) {
|
|
571
|
+
const text = quasi.value.raw;
|
|
572
|
+
const keyMatches = text.match(/[a-zA-Z][a-zA-Z0-9._-]*/g);
|
|
573
|
+
if (keyMatches) {
|
|
574
|
+
for (const potentialKey of keyMatches) {
|
|
575
|
+
if (isValidTranslationKey(potentialKey)) {
|
|
576
|
+
translationUtils.hasTranslationKey(defaultLocale, potentialKey).then((hasKey) => {
|
|
577
|
+
if (!hasKey) {
|
|
578
|
+
context.report({
|
|
579
|
+
node: quasi,
|
|
580
|
+
messageId: "missingTranslationKey",
|
|
581
|
+
data: { key: potentialKey }
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
}).catch(() => {
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
220
589
|
}
|
|
221
590
|
}
|
|
222
591
|
return {
|
|
223
592
|
CallExpression(node) {
|
|
224
593
|
checkTranslationCall(node);
|
|
225
594
|
checkUseTranslationsCall(node);
|
|
595
|
+
},
|
|
596
|
+
TemplateLiteral(node) {
|
|
597
|
+
checkTemplateLiteral(node);
|
|
226
598
|
}
|
|
227
599
|
};
|
|
228
600
|
}
|
|
@@ -231,7 +603,7 @@ var noMissingKeys = import_utils2.ESLintUtils.RuleCreator(
|
|
|
231
603
|
// src/rules/prefer-translation-hooks.ts
|
|
232
604
|
var import_utils3 = require("@typescript-eslint/utils");
|
|
233
605
|
var preferTranslationHooks = import_utils3.ESLintUtils.RuleCreator(
|
|
234
|
-
(name) => `https://github.com/
|
|
606
|
+
(name) => `https://github.com/RodrigoEspinosa/intl-party/blob/main/packages/eslint-plugin/docs/rules/${name}.md`
|
|
235
607
|
)({
|
|
236
608
|
name: "prefer-translation-hooks",
|
|
237
609
|
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.1.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.2.0"
|
|
22
27
|
},
|
|
23
28
|
"devDependencies": {
|
|
24
29
|
"@types/eslint": "^8.56.0",
|
|
@@ -37,9 +42,12 @@
|
|
|
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",
|