i18next-cli 1.58.0 → 1.58.2

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/cjs/cli.js CHANGED
@@ -32,7 +32,7 @@ const program = new commander.Command();
32
32
  program
33
33
  .name('i18next-cli')
34
34
  .description('A unified, high-performance i18next CLI.')
35
- .version('1.58.0'); // This string is replaced with the actual version at build time by rollup
35
+ .version('1.58.2'); // This string is replaced with the actual version at build time by rollup
36
36
  // new: global config override option
37
37
  program.option('-c, --config <path>', 'Path to i18next-cli config file (overrides detection)');
38
38
  program
@@ -328,18 +328,62 @@ function addImportStatements(s, content, needs) {
328
328
  if (content.startsWith('#!')) {
329
329
  insertPos = content.indexOf('\n') + 1;
330
330
  }
331
- // Find the end of the last import statement
332
- const importRegex = /^import\s.+$/gm;
331
+ // Find the end of the last import statement. Imports may span multiple lines
332
+ // (e.g. `import {\n CCol,\n} from '...'`), so we can't treat each `import`
333
+ // line as a complete statement — we scan to the real end of each declaration.
334
+ const importStartRegex = /^import\b/gm;
333
335
  let match;
334
- while ((match = importRegex.exec(content)) !== null) {
335
- const endOfImport = match.index + match[0].length;
336
- if (endOfImport > insertPos) {
337
- const nextNewline = content.indexOf('\n', endOfImport);
338
- insertPos = nextNewline !== -1 ? nextNewline + 1 : endOfImport;
339
- }
336
+ while ((match = importStartRegex.exec(content)) !== null) {
337
+ const endOfImport = findImportStatementEnd(content, match.index);
338
+ if (endOfImport > insertPos)
339
+ insertPos = endOfImport;
340
+ // Skip past this statement so we don't match `import` lines inside it.
341
+ importStartRegex.lastIndex = endOfImport;
340
342
  }
341
343
  s.appendRight(insertPos, importStatement);
342
344
  }
345
+ /**
346
+ * Returns the offset just past the end of the import statement that begins at
347
+ * `start`, handling multi-line imports with `{ ... }` clauses. The statement
348
+ * ends at the first newline or `;` at brace depth 0, after its module-specifier
349
+ * string has been closed.
350
+ */
351
+ function findImportStatementEnd(content, start) {
352
+ let depth = 0;
353
+ let stringChar = null;
354
+ let sawString = false;
355
+ for (let i = start; i < content.length; i++) {
356
+ const ch = content[i];
357
+ if (stringChar !== null) {
358
+ if (ch === '\\') {
359
+ i++;
360
+ continue;
361
+ }
362
+ if (ch === stringChar) {
363
+ stringChar = null;
364
+ if (depth === 0)
365
+ sawString = true;
366
+ }
367
+ continue;
368
+ }
369
+ if (ch === '\'' || ch === '"' || ch === '`') {
370
+ stringChar = ch;
371
+ continue;
372
+ }
373
+ if (ch === '{' || ch === '(' || ch === '[') {
374
+ depth++;
375
+ continue;
376
+ }
377
+ if (ch === '}' || ch === ')' || ch === ']') {
378
+ depth--;
379
+ continue;
380
+ }
381
+ if (depth === 0 && sawString && (ch === '\n' || ch === ';')) {
382
+ return i + 1;
383
+ }
384
+ }
385
+ return content.length;
386
+ }
343
387
  /**
344
388
  * Augments an existing `import { ... } from 'react-i18next'` with any missing
345
389
  * named exports (e.g. adds `Trans` when only `useTranslation` is imported).
@@ -9,6 +9,8 @@ var promises = require('node:fs/promises');
9
9
  var node_path = require('node:path');
10
10
  var core = require('@swc/core');
11
11
  var fileUtils = require('./utils/file-utils.js');
12
+ var json5Parser = require('@croct/json5-parser');
13
+ var yaml = require('yaml');
12
14
  var vm = require('node:vm');
13
15
 
14
16
  async function loadFile(file) {
@@ -27,10 +29,10 @@ async function loadFile(file) {
27
29
  type: 'commonjs'
28
30
  }
29
31
  });
30
- const exports$1 = {};
31
- const module = { exports: exports$1 };
32
+ const exports = {};
33
+ const module = { exports };
32
34
  const context = vm.createContext({
33
- exports: exports$1,
35
+ exports,
34
36
  module,
35
37
  require: (id) => require(id),
36
38
  console,
@@ -43,6 +45,12 @@ async function loadFile(file) {
43
45
  return exported;
44
46
  }
45
47
  const content = await promises.readFile(file, 'utf-8');
48
+ if (ext === '.yaml' || ext === '.yml') {
49
+ return yaml.parse(content);
50
+ }
51
+ if (ext === '.json5') {
52
+ return json5Parser.JsonParser.parse(content, json5Parser.JsonObjectNode).toJSON();
53
+ }
46
54
  return JSON.parse(content);
47
55
  }
48
56
  /**
package/dist/esm/cli.js CHANGED
@@ -30,7 +30,7 @@ const program = new Command();
30
30
  program
31
31
  .name('i18next-cli')
32
32
  .description('A unified, high-performance i18next CLI.')
33
- .version('1.58.0'); // This string is replaced with the actual version at build time by rollup
33
+ .version('1.58.2'); // This string is replaced with the actual version at build time by rollup
34
34
  // new: global config override option
35
35
  program.option('-c, --config <path>', 'Path to i18next-cli config file (overrides detection)');
36
36
  program
@@ -326,18 +326,62 @@ function addImportStatements(s, content, needs) {
326
326
  if (content.startsWith('#!')) {
327
327
  insertPos = content.indexOf('\n') + 1;
328
328
  }
329
- // Find the end of the last import statement
330
- const importRegex = /^import\s.+$/gm;
329
+ // Find the end of the last import statement. Imports may span multiple lines
330
+ // (e.g. `import {\n CCol,\n} from '...'`), so we can't treat each `import`
331
+ // line as a complete statement — we scan to the real end of each declaration.
332
+ const importStartRegex = /^import\b/gm;
331
333
  let match;
332
- while ((match = importRegex.exec(content)) !== null) {
333
- const endOfImport = match.index + match[0].length;
334
- if (endOfImport > insertPos) {
335
- const nextNewline = content.indexOf('\n', endOfImport);
336
- insertPos = nextNewline !== -1 ? nextNewline + 1 : endOfImport;
337
- }
334
+ while ((match = importStartRegex.exec(content)) !== null) {
335
+ const endOfImport = findImportStatementEnd(content, match.index);
336
+ if (endOfImport > insertPos)
337
+ insertPos = endOfImport;
338
+ // Skip past this statement so we don't match `import` lines inside it.
339
+ importStartRegex.lastIndex = endOfImport;
338
340
  }
339
341
  s.appendRight(insertPos, importStatement);
340
342
  }
343
+ /**
344
+ * Returns the offset just past the end of the import statement that begins at
345
+ * `start`, handling multi-line imports with `{ ... }` clauses. The statement
346
+ * ends at the first newline or `;` at brace depth 0, after its module-specifier
347
+ * string has been closed.
348
+ */
349
+ function findImportStatementEnd(content, start) {
350
+ let depth = 0;
351
+ let stringChar = null;
352
+ let sawString = false;
353
+ for (let i = start; i < content.length; i++) {
354
+ const ch = content[i];
355
+ if (stringChar !== null) {
356
+ if (ch === '\\') {
357
+ i++;
358
+ continue;
359
+ }
360
+ if (ch === stringChar) {
361
+ stringChar = null;
362
+ if (depth === 0)
363
+ sawString = true;
364
+ }
365
+ continue;
366
+ }
367
+ if (ch === '\'' || ch === '"' || ch === '`') {
368
+ stringChar = ch;
369
+ continue;
370
+ }
371
+ if (ch === '{' || ch === '(' || ch === '[') {
372
+ depth++;
373
+ continue;
374
+ }
375
+ if (ch === '}' || ch === ')' || ch === ']') {
376
+ depth--;
377
+ continue;
378
+ }
379
+ if (depth === 0 && sawString && (ch === '\n' || ch === ';')) {
380
+ return i + 1;
381
+ }
382
+ }
383
+ return content.length;
384
+ }
341
385
  /**
342
386
  * Augments an existing `import { ... } from 'react-i18next'` with any missing
343
387
  * named exports (e.g. adds `Trans` when only `useTranslation` is imported).
@@ -7,6 +7,8 @@ import { mkdir, writeFile, access, readFile } from 'node:fs/promises';
7
7
  import { join, dirname, basename, extname, resolve, relative } from 'node:path';
8
8
  import { transform } from '@swc/core';
9
9
  import { getOutputPath } from './utils/file-utils.js';
10
+ import { JsonParser, JsonObjectNode } from '@croct/json5-parser';
11
+ import yaml from 'yaml';
10
12
  import vm from 'node:vm';
11
13
 
12
14
  async function loadFile(file) {
@@ -25,10 +27,10 @@ async function loadFile(file) {
25
27
  type: 'commonjs'
26
28
  }
27
29
  });
28
- const exports$1 = {};
29
- const module = { exports: exports$1 };
30
+ const exports = {};
31
+ const module = { exports };
30
32
  const context = vm.createContext({
31
- exports: exports$1,
33
+ exports,
32
34
  module,
33
35
  require: (id) => require(id),
34
36
  console,
@@ -41,6 +43,12 @@ async function loadFile(file) {
41
43
  return exported;
42
44
  }
43
45
  const content = await readFile(file, 'utf-8');
46
+ if (ext === '.yaml' || ext === '.yml') {
47
+ return yaml.parse(content);
48
+ }
49
+ if (ext === '.json5') {
50
+ return JsonParser.parse(content, JsonObjectNode).toJSON();
51
+ }
44
52
  return JSON.parse(content);
45
53
  }
46
54
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i18next-cli",
3
- "version": "1.58.0",
3
+ "version": "1.58.2",
4
4
  "description": "A unified, high-performance i18next CLI.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -56,36 +56,36 @@
56
56
  "@rollup/plugin-terser": "^1.0.0",
57
57
  "@rollup/plugin-typescript": "^12.3.0",
58
58
  "@types/inquirer": "^9.0.9",
59
- "@types/node": "^25.6.0",
60
- "@types/react": "^19.2.14",
61
- "@typescript-eslint/parser": "^8.58.2",
62
- "@vitest/coverage-v8": "^4.1.4",
59
+ "@types/node": "^25.9.1",
60
+ "@types/react": "^19.2.15",
61
+ "@typescript-eslint/parser": "^8.60.0",
62
+ "@vitest/coverage-v8": "^4.1.7",
63
63
  "eslint": "^9.39.4",
64
64
  "eslint-import-resolver-typescript": "^4.4.4",
65
65
  "eslint-plugin-import": "^2.32.0",
66
- "memfs": "^4.57.2",
66
+ "memfs": "^4.57.3",
67
67
  "neostandard": "^0.13.0",
68
- "rollup": "^4.60.1",
68
+ "rollup": "^4.60.4",
69
69
  "typescript": "^6.0.3",
70
70
  "unplugin-swc": "^1.5.9",
71
- "vitest": "^4.1.4"
71
+ "vitest": "^4.1.7"
72
72
  },
73
73
  "dependencies": {
74
74
  "@croct/json5-parser": "^0.2.2",
75
- "@swc/core": "^1.15.26",
75
+ "@swc/core": "^1.15.40",
76
76
  "chokidar": "^5.0.0",
77
77
  "commander": "^14.0.3",
78
78
  "execa": "^9.6.1",
79
79
  "glob": "^13.0.6",
80
80
  "i18next-resources-for-ts": "^2.1.0",
81
- "inquirer": "^13.4.1",
82
- "jiti": "^2.6.1",
81
+ "inquirer": "^13.4.3",
82
+ "jiti": "^2.7.0",
83
83
  "jsonc-parser": "^3.3.1",
84
84
  "magic-string": "^0.30.21",
85
85
  "minimatch": "^10.2.5",
86
- "ora": "^9.3.0",
87
- "react": "^19.2.5",
88
- "react-i18next": "^17.0.7",
89
- "yaml": "^2.8.3"
86
+ "ora": "^9.4.0",
87
+ "react": "^19.2.6",
88
+ "react-i18next": "^17.0.8",
89
+ "yaml": "^2.9.0"
90
90
  }
91
91
  }
package/tsconfig.json CHANGED
@@ -46,7 +46,7 @@
46
46
  // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
47
47
  // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
48
48
  // "typeRoots": [], /* List of folders to include type definitions from. */
49
- // "types": [], /* Type declaration files to be included in compilation. */
49
+ "types": ["node"], /* Type declaration files to be included in compilation. */
50
50
  // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
51
51
  "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
52
52
  // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
@@ -1 +1 @@
1
- {"version":3,"file":"transformer.d.ts","sourceRoot":"","sources":["../../../src/instrumenter/core/transformer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,eAAe,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAGnI,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,OAAO,CAAA;IACjB,qBAAqB,EAAE,OAAO,CAAA;IAC9B,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,CAAA;IAC7C,6EAA6E;IAC7E,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAA;IAChC,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gFAAgF;IAChF,mBAAmB,CAAC,EAAE,kBAAkB,EAAE,CAAA;CAC3C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,eAAe,EAAE,EAC7B,OAAO,EAAE,kBAAkB,GAC1B,eAAe,CAyLjB;AAmND;;GAEG;AACH,wBAAgB,YAAY,CAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAwB1F"}
1
+ {"version":3,"file":"transformer.d.ts","sourceRoot":"","sources":["../../../src/instrumenter/core/transformer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,eAAe,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAGnI,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,OAAO,CAAA;IACjB,qBAAqB,EAAE,OAAO,CAAA;IAC9B,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,CAAA;IAC7C,6EAA6E;IAC7E,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAA;IAChC,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gFAAgF;IAChF,mBAAmB,CAAC,EAAE,kBAAkB,EAAE,CAAA;CAC3C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,eAAe,EAAE,EAC7B,OAAO,EAAE,kBAAkB,GAC1B,eAAe,CAyLjB;AAkPD;;GAEG;AACH,wBAAgB,YAAY,CAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAwB1F"}
@@ -1 +1 @@
1
- {"version":3,"file":"types-generator.d.ts","sourceRoot":"","sources":["../src/types-generator.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAqE9D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,oBAAoB,EAC5B,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,iBA+GnD"}
1
+ {"version":3,"file":"types-generator.d.ts","sourceRoot":"","sources":["../src/types-generator.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AA6E9D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,oBAAoB,EAC5B,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,iBA+GnD"}