lingo.dev 0.87.0 → 0.87.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/build/cli.mjs CHANGED
@@ -621,9 +621,9 @@ function makeGitlabInitializer(spinner) {
621
621
 
622
622
  // src/cli/cmd/init.ts
623
623
  import open2 from "open";
624
- var openUrl = (path18) => {
624
+ var openUrl = (path17) => {
625
625
  const settings = getSettings(void 0);
626
- open2(`${settings.auth.webUrl}${path18}`, { wait: false });
626
+ open2(`${settings.auth.webUrl}${path17}`, { wait: false });
627
627
  };
628
628
  var throwHelpError = (option, value) => {
629
629
  if (value === "help") {
@@ -970,8 +970,8 @@ var files_default = new Command4().command("files").description("Print out the l
970
970
  } else if (type.target) {
971
971
  result.push(...targetPaths);
972
972
  }
973
- result.forEach((path18) => {
974
- console.log(path18);
973
+ result.forEach((path17) => {
974
+ console.log(path17);
975
975
  });
976
976
  }
977
977
  }
@@ -998,8 +998,8 @@ import {
998
998
  } from "@lingo.dev/_spec";
999
999
  import { Command as Command6 } from "interactive-commander";
1000
1000
  import Z3 from "zod";
1001
- import _21 from "lodash";
1002
- import * as path15 from "path";
1001
+ import _23 from "lodash";
1002
+ import * as path14 from "path";
1003
1003
  import Ora5 from "ora";
1004
1004
 
1005
1005
  // src/cli/loaders/_utils.ts
@@ -1218,7 +1218,7 @@ function createTextFileLoader(pathPattern) {
1218
1218
  const trimmedResult = result.trim();
1219
1219
  return trimmedResult;
1220
1220
  },
1221
- async push(locale, data, _24, originalLocale) {
1221
+ async push(locale, data, _26, originalLocale) {
1222
1222
  const draftPath = pathPattern.replaceAll("[locale]", locale);
1223
1223
  const finalPath = path10.resolve(draftPath);
1224
1224
  const dirPath = path10.dirname(finalPath);
@@ -1554,9 +1554,9 @@ function createHtmlLoader() {
1554
1554
  const bDepth = b.split("/").length;
1555
1555
  return aDepth - bDepth;
1556
1556
  });
1557
- paths.forEach((path18) => {
1558
- const value = data[path18];
1559
- const [nodePath, attribute] = path18.split("#");
1557
+ paths.forEach((path17) => {
1558
+ const value = data[path17];
1559
+ const [nodePath, attribute] = path17.split("#");
1560
1560
  const [rootTag, ...indices] = nodePath.split("/");
1561
1561
  let parent = rootTag === "head" ? document.head : document.body;
1562
1562
  let current = parent;
@@ -1659,7 +1659,7 @@ function createPropertiesLoader() {
1659
1659
  return result;
1660
1660
  },
1661
1661
  async push(locale, payload) {
1662
- const result = Object.entries(payload).filter(([_24, value]) => value != null).map(([key, value]) => `${key}=${value}`).join("\n");
1662
+ const result = Object.entries(payload).filter(([_26, value]) => value != null).map(([key, value]) => `${key}=${value}`).join("\n");
1663
1663
  return result;
1664
1664
  }
1665
1665
  });
@@ -1836,8 +1836,12 @@ function createXcodeXcstringsLoader(defaultLocale) {
1836
1836
  import path11 from "path";
1837
1837
  import prettier from "prettier";
1838
1838
  function createPrettierLoader(options) {
1839
+ const stage = options.stage || "both";
1839
1840
  return createLoader({
1840
1841
  async pull(locale, data) {
1842
+ if (!["pull", "both"].includes(stage)) {
1843
+ return data;
1844
+ }
1841
1845
  const draftPath = options.bucketPathPattern.replaceAll(
1842
1846
  "[locale]",
1843
1847
  locale
@@ -1846,6 +1850,9 @@ function createPrettierLoader(options) {
1846
1850
  return await formatDataWithPrettier(data, finalPath, options);
1847
1851
  },
1848
1852
  async push(locale, data) {
1853
+ if (!["push", "both"].includes(stage)) {
1854
+ return data;
1855
+ }
1849
1856
  const draftPath = options.bucketPathPattern.replaceAll(
1850
1857
  "[locale]",
1851
1858
  locale
@@ -1919,10 +1926,10 @@ function createUnlocalizableLoader(isCacheRestore = false, returnUnlocalizedKeys
1919
1926
  }
1920
1927
  }
1921
1928
  return false;
1922
- }).map(([key, _24]) => key);
1923
- const result = _10.omitBy(input2, (_24, key) => passthroughKeys.includes(key));
1929
+ }).map(([key, _26]) => key);
1930
+ const result = _10.omitBy(input2, (_26, key) => passthroughKeys.includes(key));
1924
1931
  if (returnUnlocalizedKeys) {
1925
- result.unlocalizable = _10.omitBy(input2, (_24, key) => !passthroughKeys.includes(key));
1932
+ result.unlocalizable = _10.omitBy(input2, (_26, key) => !passthroughKeys.includes(key));
1926
1933
  }
1927
1934
  return result;
1928
1935
  },
@@ -2092,10 +2099,10 @@ function createXmlLoader() {
2092
2099
  // src/cli/loaders/srt.ts
2093
2100
  import srtParser from "srt-parser-2";
2094
2101
  function createSrtLoader() {
2095
- const parser2 = new srtParser();
2102
+ const parser = new srtParser();
2096
2103
  return createLoader({
2097
2104
  async pull(locale, input2) {
2098
- const parsed = parser2.fromSrt(input2) || [];
2105
+ const parsed = parser.fromSrt(input2) || [];
2099
2106
  const result = {};
2100
2107
  parsed.forEach((entry) => {
2101
2108
  const key = `${entry.id}#${entry.startTime}-${entry.endTime}`;
@@ -2116,7 +2123,7 @@ function createSrtLoader() {
2116
2123
  text
2117
2124
  };
2118
2125
  });
2119
- const srtContent = parser2.toSrt(output).trim().replace(/\r?\n/g, "\n");
2126
+ const srtContent = parser.toSrt(output).trim().replace(/\r?\n/g, "\n");
2120
2127
  return srtContent;
2121
2128
  }
2122
2129
  });
@@ -2626,18 +2633,18 @@ function createRawDatoValue(parsedDatoValue, originalRawDatoValue, isClean = fal
2626
2633
  }
2627
2634
  function serializeStructuredText(rawStructuredText) {
2628
2635
  return serializeStructuredTextNode(rawStructuredText);
2629
- function serializeStructuredTextNode(node, path18 = [], acc = {}) {
2636
+ function serializeStructuredTextNode(node, path17 = [], acc = {}) {
2630
2637
  if ("document" in node) {
2631
- return serializeStructuredTextNode(node.document, [...path18, "document"], acc);
2638
+ return serializeStructuredTextNode(node.document, [...path17, "document"], acc);
2632
2639
  }
2633
2640
  if (!_15.isNil(node.value)) {
2634
- acc[[...path18, "value"].join(".")] = node.value;
2641
+ acc[[...path17, "value"].join(".")] = node.value;
2635
2642
  } else if (_15.get(node, "type") === "block") {
2636
- acc[[...path18, "item"].join(".")] = serializeBlock(node.item);
2643
+ acc[[...path17, "item"].join(".")] = serializeBlock(node.item);
2637
2644
  }
2638
2645
  if (node.children) {
2639
2646
  for (let i = 0; i < node.children.length; i++) {
2640
- serializeStructuredTextNode(node.children[i], [...path18, i.toString()], acc);
2647
+ serializeStructuredTextNode(node.children[i], [...path17, i.toString()], acc);
2641
2648
  }
2642
2649
  }
2643
2650
  return acc;
@@ -2696,8 +2703,8 @@ function deserializeBlockList(parsedBlockList, originalRawBlockList, isClean = f
2696
2703
  }
2697
2704
  function deserializeStructuredText(parsedStructuredText, originalRawStructuredText) {
2698
2705
  const result = _15.cloneDeep(originalRawStructuredText);
2699
- for (const [path18, value] of _15.entries(parsedStructuredText)) {
2700
- const realPath = _15.chain(path18.split(".")).flatMap((s) => !_15.isNaN(_15.toNumber(s)) ? ["children", s] : s).value();
2706
+ for (const [path17, value] of _15.entries(parsedStructuredText)) {
2707
+ const realPath = _15.chain(path17.split(".")).flatMap((s) => !_15.isNaN(_15.toNumber(s)) ? ["children", s] : s).value();
2701
2708
  const deserializedValue = createRawDatoValue(value, _15.get(originalRawStructuredText, realPath), true);
2702
2709
  _15.set(result, realPath, deserializedValue);
2703
2710
  }
@@ -3084,16 +3091,6 @@ function createMdxFrontmatterSplitLoader() {
3084
3091
  });
3085
3092
  }
3086
3093
 
3087
- // src/cli/loaders/mdx2/_utils.ts
3088
- function traverseMdast(ast, visitor) {
3089
- visitor(ast);
3090
- if ("children" in ast && Array.isArray(ast.children)) {
3091
- for (const child of ast.children) {
3092
- traverseMdast(child, visitor);
3093
- }
3094
- }
3095
- }
3096
-
3097
3094
  // src/cli/utils/md5.ts
3098
3095
  import { MD5 } from "object-hash";
3099
3096
  function md5(input2) {
@@ -3101,41 +3098,40 @@ function md5(input2) {
3101
3098
  }
3102
3099
 
3103
3100
  // src/cli/loaders/mdx2/code-placeholder.ts
3104
- import { unified } from "unified";
3105
- import remarkParse from "remark-parse";
3106
- import remarkGfm from "remark-gfm";
3107
- import { VFile } from "vfile";
3108
- import remarkMdx from "remark-mdx";
3109
- function parseMdast(content) {
3110
- const file = new VFile(content);
3111
- const parser2 = unified().use(remarkParse).use(remarkGfm).use(remarkMdx);
3112
- const result = parser2.parse(file);
3113
- return result;
3101
+ import _20 from "lodash";
3102
+ var unindentedFenceRegex = /(?<!\n\n)```([\s\S]*?)```(?!\n\n)/g;
3103
+ var indentedFenceRegex = /```([\s\S]*?)```/g;
3104
+ function ensureTrailingFenceNewline(_content) {
3105
+ let found = false;
3106
+ let content = _content;
3107
+ do {
3108
+ found = false;
3109
+ const matches = content.match(unindentedFenceRegex);
3110
+ if (matches) {
3111
+ const match = matches[0];
3112
+ content = content.replace(match, `
3113
+
3114
+ ${match}
3115
+
3116
+ `);
3117
+ found = true;
3118
+ }
3119
+ } while (found);
3120
+ content = _20.chain(content).split("\n\n").filter(Boolean).join("\n\n").value();
3121
+ return content;
3114
3122
  }
3115
3123
  function extractCodePlaceholders(content) {
3116
- const ast = parseMdast(content);
3117
- const placeholderableElements = [
3118
- "code",
3119
- "inlineCode"
3120
- ];
3121
3124
  let finalContent = content;
3125
+ finalContent = ensureTrailingFenceNewline(finalContent);
3122
3126
  const codePlaceholders = {};
3123
- traverseMdast(ast, (_node) => {
3124
- if (!placeholderableElements.includes(_node.type)) {
3125
- return;
3126
- }
3127
- const node = _node;
3128
- const nodeContent = node.value;
3129
- const nodeContentHash = md5(nodeContent);
3130
- const placeholderId = `__PLACEHOLDER_${nodeContentHash}__`;
3131
- const nodeContentStart = node.position?.start.offset;
3132
- const nodeContentEnd = node.position?.end.offset;
3133
- if (!nodeContentStart || !nodeContentEnd) {
3134
- return;
3135
- }
3136
- codePlaceholders[placeholderId] = nodeContent;
3137
- finalContent = finalContent.split(nodeContent).join(placeholderId);
3138
- });
3127
+ const codeBlockMatches = finalContent.matchAll(indentedFenceRegex);
3128
+ for (const match of codeBlockMatches) {
3129
+ const codeBlock = match[0];
3130
+ const codeBlockHash = md5(codeBlock);
3131
+ const placeholderId = `---CODE_PLACEHOLDER_${codeBlockHash}---`;
3132
+ codePlaceholders[placeholderId] = codeBlock;
3133
+ finalContent = finalContent.replace(codeBlock, placeholderId);
3134
+ }
3139
3135
  return {
3140
3136
  content: finalContent,
3141
3137
  codePlaceholders
@@ -3144,314 +3140,22 @@ function extractCodePlaceholders(content) {
3144
3140
  function createMdxCodePlaceholderLoader() {
3145
3141
  return createLoader({
3146
3142
  async pull(locale, input2) {
3147
- const { frontmatter = {}, content = "" } = input2 || {
3148
- frontmatter: {},
3149
- content: ""
3150
- };
3151
- const { content: resultContent, codePlaceholders } = extractCodePlaceholders(content);
3152
- return {
3153
- frontmatter,
3154
- content: resultContent,
3155
- codePlaceholders
3156
- };
3143
+ const response = extractCodePlaceholders(input2);
3144
+ return response.content;
3157
3145
  },
3158
3146
  async push(locale, data, originalInput) {
3159
- const { codePlaceholders } = extractCodePlaceholders(
3160
- originalInput?.content ?? ""
3161
- );
3162
- let finalContent = data.content;
3163
- for (const [placeholder, original] of Object.entries(codePlaceholders)) {
3164
- finalContent = finalContent.replaceAll(placeholder, () => original);
3147
+ const response = extractCodePlaceholders(originalInput ?? "");
3148
+ let result = data;
3149
+ for (const [placeholder, original] of Object.entries(
3150
+ response.codePlaceholders
3151
+ )) {
3152
+ result = result.replaceAll(placeholder, original);
3165
3153
  }
3166
- const result = {
3167
- frontmatter: data.frontmatter,
3168
- content: finalContent
3169
- };
3170
3154
  return result;
3171
3155
  }
3172
3156
  });
3173
3157
  }
3174
3158
 
3175
- // src/cli/loaders/mdx2/section-split.ts
3176
- import { unified as unified2 } from "unified";
3177
- import remarkParse2 from "remark-parse";
3178
- import remarkGfm2 from "remark-gfm";
3179
- import remarkMdx2 from "remark-mdx";
3180
- import { VFile as VFile2 } from "vfile";
3181
- var parser = unified2().use(remarkParse2).use(remarkGfm2).use(remarkMdx2);
3182
- var SPACING_MATRIX = [
3183
- // HEADING as previous type
3184
- ["\n\n", "\n\n", "\n\n", "\n\n", "\n\n", "\n\n"],
3185
- // JSX_OPENING_TAG as previous type
3186
- ["\n\n", "\n", "\n", "\n", "\n", "\n\n"],
3187
- // JSX_CLOSING_TAG as previous type
3188
- ["\n\n", "\n", "\n", "\n", "\n\n", "\n\n"],
3189
- // JSX_SELF_CLOSING_TAG as previous type
3190
- ["\n\n", "\n", "\n", "\n", "\n", "\n\n"],
3191
- // CONTENT as previous type
3192
- ["\n\n", "\n\n", "\n", "\n\n", "\n\n", "\n\n"],
3193
- // UNKNOWN as previous type
3194
- ["\n\n", "\n\n", "\n\n", "\n\n", "\n\n", "\n\n"]
3195
- ];
3196
- function createMdxSectionSplitLoader() {
3197
- return createLoader({
3198
- async pull(_locale, input2) {
3199
- const {
3200
- frontmatter = {},
3201
- content = "",
3202
- codePlaceholders = {}
3203
- } = input2 || {
3204
- frontmatter: {},
3205
- content: "",
3206
- codePlaceholders: {}
3207
- };
3208
- if (!content.trim()) {
3209
- return {
3210
- frontmatter,
3211
- sections: {}
3212
- };
3213
- }
3214
- const file = new VFile2(content);
3215
- const ast = parser.parse(file);
3216
- const boundaries = findSectionBoundaries(ast, content);
3217
- const sections = createSectionsFromBoundaries(boundaries, content);
3218
- return {
3219
- frontmatter,
3220
- sections
3221
- };
3222
- },
3223
- async push(_locale, data, originalInput, _originalLocale) {
3224
- const sectionsArray = Object.values(data.sections);
3225
- if (sectionsArray.length === 0) {
3226
- return {
3227
- frontmatter: data.frontmatter,
3228
- content: "",
3229
- codePlaceholders: originalInput?.codePlaceholders ?? {}
3230
- };
3231
- }
3232
- const resultParts = new Array(sectionsArray.length * 2 - 1);
3233
- const sectionTypes = new Array(sectionsArray.length);
3234
- for (let i = 0; i < sectionsArray.length; i++) {
3235
- sectionTypes[i] = determineJsxSectionType(sectionsArray[i]);
3236
- }
3237
- resultParts[0] = sectionsArray[0];
3238
- for (let i = 1, j = 1; i < sectionsArray.length; i++, j += 2) {
3239
- const prevType = sectionTypes[i - 1];
3240
- const currentType = sectionTypes[i];
3241
- resultParts[j] = SPACING_MATRIX[prevType][currentType];
3242
- resultParts[j + 1] = sectionsArray[i];
3243
- }
3244
- const content = resultParts.join("");
3245
- return {
3246
- frontmatter: data.frontmatter,
3247
- content,
3248
- codePlaceholders: originalInput?.codePlaceholders ?? {}
3249
- };
3250
- }
3251
- });
3252
- }
3253
- function determineJsxSectionType(section) {
3254
- section = section.trim();
3255
- if (!section) return 5 /* UNKNOWN */;
3256
- const firstChar = section.charAt(0);
3257
- const lastChar = section.charAt(section.length - 1);
3258
- if (firstChar === "#") {
3259
- if (/^#{1,6}\s/.test(section)) {
3260
- return 0 /* HEADING */;
3261
- }
3262
- }
3263
- if (firstChar === "<") {
3264
- if (section.endsWith("/>")) {
3265
- return 3 /* JSX_SELF_CLOSING_TAG */;
3266
- }
3267
- if (section.startsWith("</")) {
3268
- return 2 /* JSX_CLOSING_TAG */;
3269
- }
3270
- if (lastChar === ">") {
3271
- return 1 /* JSX_OPENING_TAG */;
3272
- }
3273
- }
3274
- return 4 /* CONTENT */;
3275
- }
3276
- function isJsxOrHtml(node) {
3277
- return node.type === "mdxJsxFlowElement" || node.type === "mdxJsxTextElement" || node.type === "html";
3278
- }
3279
- function findOpeningTagEnd(text) {
3280
- let depth = 0;
3281
- let inQuotes = false;
3282
- let quoteChar = "";
3283
- for (let i = 0; i < text.length; i++) {
3284
- const char = text[i];
3285
- if ((char === '"' || char === "'") && (i === 0 || text[i - 1] !== "\\")) {
3286
- if (!inQuotes) {
3287
- inQuotes = true;
3288
- quoteChar = char;
3289
- } else if (char === quoteChar) {
3290
- inQuotes = false;
3291
- }
3292
- }
3293
- if (!inQuotes) {
3294
- if (char === "<") depth++;
3295
- if (char === ">") {
3296
- depth--;
3297
- if (depth === 0) return i + 1;
3298
- }
3299
- }
3300
- }
3301
- return -1;
3302
- }
3303
- function findClosingTagStart(text) {
3304
- const openTagMatch = /<([^\s/>]+)/.exec(text);
3305
- if (!openTagMatch) return -1;
3306
- const tagName = openTagMatch[1];
3307
- const closingTagRegex = new RegExp(`</${tagName}\\s*>`, "g");
3308
- let lastMatch = null;
3309
- let match;
3310
- while ((match = closingTagRegex.exec(text)) !== null) {
3311
- lastMatch = match;
3312
- }
3313
- return lastMatch ? lastMatch.index : -1;
3314
- }
3315
- function processJsxNode(node, content, boundaries) {
3316
- if (!node.position || typeof node.position.start.offset !== "number" || typeof node.position.end.offset !== "number") {
3317
- return;
3318
- }
3319
- const nodeStart = node.position.start.offset;
3320
- const nodeEnd = node.position.end.offset;
3321
- const nodeContent = content.slice(nodeStart, nodeEnd);
3322
- if (node.type === "html") {
3323
- extractHtmlTags(nodeStart, nodeContent, boundaries);
3324
- return;
3325
- }
3326
- if (node.type === "mdxJsxFlowElement" || node.type === "mdxJsxTextElement") {
3327
- const isSelfClosing = node.selfClosing === true;
3328
- if (isSelfClosing) {
3329
- boundaries.push({
3330
- start: nodeStart,
3331
- end: nodeEnd,
3332
- isolateSelf: true
3333
- });
3334
- } else {
3335
- extractJsxTags(node, nodeContent, boundaries);
3336
- if (node.children) {
3337
- for (const child of node.children) {
3338
- if (isJsxOrHtml(child)) {
3339
- processJsxNode(child, content, boundaries);
3340
- }
3341
- }
3342
- }
3343
- }
3344
- }
3345
- }
3346
- function extractHtmlTags(nodeStart, nodeContent, boundaries) {
3347
- const tagRegex = /<\/?[a-zA-Z][a-zA-Z0-9:._-]*(?:\s+[a-zA-Z:_][a-zA-Z0-9:._-]*(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s]+))?)*\s*\/?>/g;
3348
- let match;
3349
- while ((match = tagRegex.exec(nodeContent)) !== null) {
3350
- const tagStart = nodeStart + match.index;
3351
- const tagEnd = tagStart + match[0].length;
3352
- boundaries.push({
3353
- start: tagStart,
3354
- end: tagEnd,
3355
- isolateSelf: true
3356
- });
3357
- }
3358
- }
3359
- function extractJsxTags(node, nodeContent, boundaries) {
3360
- const nodeStart = node.position.start.offset;
3361
- const nodeEnd = node.position.end.offset;
3362
- if (!nodeStart || !nodeEnd) {
3363
- return;
3364
- }
3365
- const openingTagEnd = findOpeningTagEnd(nodeContent);
3366
- if (openingTagEnd > 0) {
3367
- boundaries.push({
3368
- start: nodeStart,
3369
- end: nodeStart + openingTagEnd,
3370
- isolateSelf: true
3371
- });
3372
- }
3373
- const closingTagStart = findClosingTagStart(nodeContent);
3374
- if (closingTagStart > 0 && closingTagStart < nodeContent.length) {
3375
- boundaries.push({
3376
- start: nodeStart + closingTagStart,
3377
- end: nodeEnd,
3378
- isolateSelf: true
3379
- });
3380
- }
3381
- }
3382
- function findSectionBoundaries(ast, content) {
3383
- const boundaries = [];
3384
- const nodePositions = /* @__PURE__ */ new Map();
3385
- traverseMdast(ast, (node) => {
3386
- if (node.position && typeof node.position.start.offset === "number" && typeof node.position.end.offset === "number") {
3387
- nodePositions.set(node, {
3388
- start: node.position.start.offset,
3389
- end: node.position.end.offset
3390
- });
3391
- }
3392
- });
3393
- for (const child of ast.children) {
3394
- const position = nodePositions.get(child);
3395
- if (!position) continue;
3396
- if (child.type === "heading") {
3397
- boundaries.push({
3398
- start: position.start,
3399
- end: position.end,
3400
- isolateSelf: false
3401
- });
3402
- } else if (isJsxOrHtml(child)) {
3403
- processJsxNode(child, content, boundaries);
3404
- }
3405
- }
3406
- return boundaries.sort((a, b) => a.start - b.start);
3407
- }
3408
- function createSectionsFromBoundaries(boundaries, content) {
3409
- const sections = {};
3410
- if (!content.trim() || boundaries.length === 0) {
3411
- const trimmed = content.trim();
3412
- if (trimmed) {
3413
- sections["0"] = trimmed;
3414
- }
3415
- return sections;
3416
- }
3417
- let idx = 0;
3418
- let lastEnd = 0;
3419
- const sectionsArray = [];
3420
- for (let i = 0; i < boundaries.length; i++) {
3421
- const { start, end, isolateSelf } = boundaries[i];
3422
- if (start > lastEnd) {
3423
- const segment = content.slice(lastEnd, start).trim();
3424
- if (segment) {
3425
- sectionsArray.push(segment);
3426
- }
3427
- }
3428
- if (isolateSelf) {
3429
- const segment = content.slice(start, end).trim();
3430
- if (segment) {
3431
- sectionsArray.push(segment);
3432
- }
3433
- lastEnd = end;
3434
- } else {
3435
- const nextStart = i + 1 < boundaries.length ? boundaries[i + 1].start : content.length;
3436
- const segment = content.slice(start, nextStart).trim();
3437
- if (segment) {
3438
- sectionsArray.push(segment);
3439
- }
3440
- lastEnd = nextStart;
3441
- }
3442
- }
3443
- if (lastEnd < content.length) {
3444
- const segment = content.slice(lastEnd).trim();
3445
- if (segment) {
3446
- sectionsArray.push(segment);
3447
- }
3448
- }
3449
- sectionsArray.forEach((section, index) => {
3450
- sections[index.toString()] = section;
3451
- });
3452
- return sections;
3453
- }
3454
-
3455
3159
  // src/cli/loaders/mdx2/localizable-document.ts
3456
3160
  function createLocalizableMdxDocumentLoader() {
3457
3161
  return createLoader({
@@ -3471,14 +3175,28 @@ function createLocalizableMdxDocumentLoader() {
3471
3175
  });
3472
3176
  }
3473
3177
 
3474
- // src/cli/loaders/mdx2/index.ts
3475
- function createMdxLoader() {
3476
- return composeLoaders(
3477
- createMdxFrontmatterSplitLoader(),
3478
- createMdxCodePlaceholderLoader(),
3479
- createMdxSectionSplitLoader(),
3480
- createLocalizableMdxDocumentLoader()
3481
- );
3178
+ // src/cli/loaders/mdx2/sections-split-2.ts
3179
+ import _21 from "lodash";
3180
+ function createMdxSectionsSplit2Loader() {
3181
+ return createLoader({
3182
+ async pull(locale, input2) {
3183
+ const sections = _21.chain(input2.content).split("\n\n").filter(Boolean).map((section, index) => [index, section]).fromPairs().value();
3184
+ const result = {
3185
+ frontmatter: input2.frontmatter,
3186
+ sections
3187
+ };
3188
+ return result;
3189
+ },
3190
+ async push(locale, data, originalInput, _originalLocale, pullInput) {
3191
+ const content = _21.chain(data.sections).values().join("\n\n").value();
3192
+ const result = {
3193
+ frontmatter: data.frontmatter,
3194
+ codePlaceholders: pullInput?.codePlaceholders || {},
3195
+ content
3196
+ };
3197
+ return result;
3198
+ }
3199
+ });
3482
3200
  }
3483
3201
 
3484
3202
  // src/cli/loaders/index.ts
@@ -3547,8 +3265,14 @@ function createBucketLoader(bucketType, bucketPathPattern, options, lockedKeys)
3547
3265
  case "mdx":
3548
3266
  return composeLoaders(
3549
3267
  createTextFileLoader(bucketPathPattern),
3550
- createPrettierLoader({ parser: "mdx", bucketPathPattern }),
3551
- createMdxLoader(),
3268
+ createMdxCodePlaceholderLoader(),
3269
+ createPrettierLoader({
3270
+ parser: "mdx",
3271
+ bucketPathPattern
3272
+ }),
3273
+ createMdxFrontmatterSplitLoader(),
3274
+ createMdxSectionsSplit2Loader(),
3275
+ createLocalizableMdxDocumentLoader(),
3552
3276
  createFlatLoader(),
3553
3277
  createSyncLoader(),
3554
3278
  createUnlocalizableLoader(
@@ -3735,37 +3459,6 @@ import { createTwoFilesPatch } from "diff";
3735
3459
  import inquirer2 from "inquirer";
3736
3460
  import externalEditor from "external-editor";
3737
3461
 
3738
- // src/cli/utils/cache.ts
3739
- import path12 from "path";
3740
- import fs10 from "fs";
3741
- var cacheChunk = (targetLocale, sourceChunk, processedChunk) => {
3742
- const rows = Object.entries(sourceChunk).map(([key, source]) => ({
3743
- targetLocale,
3744
- key,
3745
- source,
3746
- processed: processedChunk[key]
3747
- }));
3748
- _appendToCache(rows);
3749
- };
3750
- function deleteCache() {
3751
- const cacheFilePath = _getCacheFilePath();
3752
- try {
3753
- fs10.unlinkSync(cacheFilePath);
3754
- } catch (e) {
3755
- }
3756
- }
3757
- function _appendToCache(rows) {
3758
- const cacheFilePath = _getCacheFilePath();
3759
- const lines = _buildJSONLines(rows);
3760
- fs10.appendFileSync(cacheFilePath, lines);
3761
- }
3762
- function _getCacheFilePath() {
3763
- return path12.join(process.cwd(), "i18n.cache");
3764
- }
3765
- function _buildJSONLines(rows) {
3766
- return rows.map((row) => JSON.stringify(row)).join("\n") + "\n";
3767
- }
3768
-
3769
3462
  // src/cli/processor/lingo.ts
3770
3463
  import { LingoDotDevEngine } from "@lingo.dev/_sdk";
3771
3464
  function createLingoLocalizer(params) {
@@ -3931,33 +3624,33 @@ async function trackEvent(distinctId, event, properties) {
3931
3624
  }
3932
3625
 
3933
3626
  // src/cli/utils/delta.ts
3934
- import _20 from "lodash";
3627
+ import _22 from "lodash";
3935
3628
  import z from "zod";
3936
3629
 
3937
3630
  // src/cli/utils/fs.ts
3938
- import * as fs11 from "fs";
3939
- import * as path13 from "path";
3631
+ import * as fs10 from "fs";
3632
+ import * as path12 from "path";
3940
3633
  function tryReadFile(filePath, defaultValue = null) {
3941
3634
  try {
3942
- const content = fs11.readFileSync(filePath, "utf-8");
3635
+ const content = fs10.readFileSync(filePath, "utf-8");
3943
3636
  return content;
3944
3637
  } catch (error) {
3945
3638
  return defaultValue;
3946
3639
  }
3947
3640
  }
3948
3641
  function writeFile(filePath, content) {
3949
- const dir = path13.dirname(filePath);
3950
- if (!fs11.existsSync(dir)) {
3951
- fs11.mkdirSync(dir, { recursive: true });
3642
+ const dir = path12.dirname(filePath);
3643
+ if (!fs10.existsSync(dir)) {
3644
+ fs10.mkdirSync(dir, { recursive: true });
3952
3645
  }
3953
- fs11.writeFileSync(filePath, content);
3646
+ fs10.writeFileSync(filePath, content);
3954
3647
  }
3955
3648
  function checkIfFileExists(filePath) {
3956
- return fs11.existsSync(filePath);
3649
+ return fs10.existsSync(filePath);
3957
3650
  }
3958
3651
 
3959
3652
  // src/cli/utils/delta.ts
3960
- import * as path14 from "path";
3653
+ import * as path13 from "path";
3961
3654
  import YAML3 from "yaml";
3962
3655
  var LockSchema = z.object({
3963
3656
  version: z.literal(1).default(1),
@@ -3974,15 +3667,15 @@ var LockSchema = z.object({
3974
3667
  ).default({})
3975
3668
  });
3976
3669
  function createDeltaProcessor(fileKey) {
3977
- const lockfilePath = path14.join(process.cwd(), "i18n.lock");
3670
+ const lockfilePath = path13.join(process.cwd(), "i18n.lock");
3978
3671
  return {
3979
3672
  async checkIfLockExists() {
3980
3673
  return checkIfFileExists(lockfilePath);
3981
3674
  },
3982
3675
  async calculateDelta(params) {
3983
- let added = _20.difference(Object.keys(params.sourceData), Object.keys(params.targetData));
3984
- let removed = _20.difference(Object.keys(params.targetData), Object.keys(params.sourceData));
3985
- const updated = _20.filter(Object.keys(params.sourceData), (key) => {
3676
+ let added = _22.difference(Object.keys(params.sourceData), Object.keys(params.targetData));
3677
+ let removed = _22.difference(Object.keys(params.targetData), Object.keys(params.sourceData));
3678
+ const updated = _22.filter(Object.keys(params.sourceData), (key) => {
3986
3679
  return md5(params.sourceData[key]) !== params.checksums[key] && params.checksums[key];
3987
3680
  });
3988
3681
  const renamed = [];
@@ -4031,7 +3724,7 @@ function createDeltaProcessor(fileKey) {
4031
3724
  await this.saveLock(lockfileData);
4032
3725
  },
4033
3726
  async createChecksums(sourceData) {
4034
- const checksums = _20.mapValues(sourceData, (value) => md5(value));
3727
+ const checksums = _22.mapValues(sourceData, (value) => md5(value));
4035
3728
  return checksums;
4036
3729
  }
4037
3730
  };
@@ -4115,7 +3808,7 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
4115
3808
  if (flags.file?.length) {
4116
3809
  buckets = buckets.map((bucket) => {
4117
3810
  const paths = bucket.paths.filter(
4118
- (path18) => flags.file.find((file) => path18.pathPattern?.includes(file))
3811
+ (path17) => flags.file.find((file) => path17.pathPattern?.includes(file))
4119
3812
  );
4120
3813
  return { ...bucket, paths };
4121
3814
  }).filter((bucket) => bucket.paths.length > 0);
@@ -4128,8 +3821,8 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
4128
3821
  ora.info(`\x1B[36mProcessing only filtered buckets:\x1B[0m`);
4129
3822
  buckets.map((bucket) => {
4130
3823
  ora.info(` ${bucket.type}:`);
4131
- bucket.paths.forEach((path18) => {
4132
- ora.info(` - ${path18.pathPattern}`);
3824
+ bucket.paths.forEach((path17) => {
3825
+ ora.info(` - ${path17.pathPattern}`);
4133
3826
  });
4134
3827
  });
4135
3828
  }
@@ -4181,7 +3874,7 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
4181
3874
  bucketPath.delimiter
4182
3875
  );
4183
3876
  const deltaProcessor = createDeltaProcessor(bucketPath.pathPattern);
4184
- const sourcePath = path15.join(
3877
+ const sourcePath = path14.join(
4185
3878
  process.cwd(),
4186
3879
  bucketPath.pathPattern.replace("[locale]", sourceLocale)
4187
3880
  );
@@ -4198,7 +3891,7 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
4198
3891
  _targetLocale,
4199
3892
  bucketPath.delimiter
4200
3893
  );
4201
- const targetPath = path15.join(
3894
+ const targetPath = path14.join(
4202
3895
  process.cwd(),
4203
3896
  bucketPath.pathPattern.replace("[locale]", targetLocale)
4204
3897
  );
@@ -4263,7 +3956,7 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
4263
3956
  const deltaProcessor = createDeltaProcessor(bucketPath.pathPattern);
4264
3957
  const sourceChecksums = await deltaProcessor.createChecksums(sourceData);
4265
3958
  const savedChecksums = await deltaProcessor.loadChecksums();
4266
- const updatedSourceData = _21.pickBy(
3959
+ const updatedSourceData = _23.pickBy(
4267
3960
  sourceData,
4268
3961
  (value, key) => sourceChecksums[key] !== savedChecksums[key]
4269
3962
  );
@@ -4277,15 +3970,15 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
4277
3970
  bucketPath.delimiter
4278
3971
  );
4279
3972
  const { unlocalizable: targetUnlocalizable, ...targetData } = await bucketLoader.pull(targetLocale);
4280
- const missingKeys = _21.difference(
3973
+ const missingKeys = _23.difference(
4281
3974
  Object.keys(sourceData),
4282
3975
  Object.keys(targetData)
4283
3976
  );
4284
- const extraKeys = _21.difference(
3977
+ const extraKeys = _23.difference(
4285
3978
  Object.keys(targetData),
4286
3979
  Object.keys(sourceData)
4287
3980
  );
4288
- const unlocalizableDataDiff = !_21.isEqual(
3981
+ const unlocalizableDataDiff = !_23.isEqual(
4289
3982
  sourceUnlocalizable,
4290
3983
  targetUnlocalizable
4291
3984
  );
@@ -4365,13 +4058,13 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
4365
4058
  targetData,
4366
4059
  checksums: checksums2
4367
4060
  });
4368
- let processableData = _21.chain(sourceData).entries().filter(
4061
+ let processableData = _23.chain(sourceData).entries().filter(
4369
4062
  ([key, value]) => delta.added.includes(key) || delta.updated.includes(key) || !!flags.force
4370
4063
  ).fromPairs().value();
4371
4064
  if (flags.key) {
4372
- processableData = _21.pickBy(
4065
+ processableData = _23.pickBy(
4373
4066
  processableData,
4374
- (_24, key) => key === flags.key
4067
+ (_26, key) => key === flags.key
4375
4068
  );
4376
4069
  }
4377
4070
  if (flags.verbose) {
@@ -4398,7 +4091,6 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
4398
4091
  targetData
4399
4092
  },
4400
4093
  (progress, sourceChunk, processedChunk) => {
4401
- cacheChunk(targetLocale, sourceChunk, processedChunk);
4402
4094
  const progressLog = `[${sourceLocale} -> ${targetLocale}] [${Object.keys(processableData).length} entries] (${progress}%) AI localization in progress...`;
4403
4095
  if (flags.verbose) {
4404
4096
  bucketOra.info(progressLog);
@@ -4413,7 +4105,7 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
4413
4105
  if (flags.verbose) {
4414
4106
  bucketOra.info(JSON.stringify(processedTargetData, null, 2));
4415
4107
  }
4416
- let finalTargetData = _21.merge(
4108
+ let finalTargetData = _23.merge(
4417
4109
  {},
4418
4110
  sourceData,
4419
4111
  targetData,
@@ -4434,7 +4126,7 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
4434
4126
  `Applying changes to ${bucketPath} (${targetLocale})`
4435
4127
  );
4436
4128
  }
4437
- const finalDiffSize = _21.chain(finalTargetData).omitBy((value, key) => value === targetData[key]).size().value();
4129
+ const finalDiffSize = _23.chain(finalTargetData).omitBy((value, key) => value === targetData[key]).size().value();
4438
4130
  await bucketLoader.push(targetLocale, finalTargetData);
4439
4131
  if (finalDiffSize > 0 || flags.force) {
4440
4132
  bucketOra.succeed(
@@ -4476,10 +4168,6 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
4476
4168
  console.log();
4477
4169
  if (!hasErrors) {
4478
4170
  ora.succeed("Localization completed.");
4479
- deleteCache();
4480
- if (flags.verbose) {
4481
- ora.info("Cache file deleted.");
4482
- }
4483
4171
  trackEvent(auth.id, "cmd.i18n.success", {
4484
4172
  i18nConfig,
4485
4173
  flags
@@ -4606,7 +4294,7 @@ Reviewing changes for ${chalk.blue(args.pathPattern)} (${chalk.yellow(args.targe
4606
4294
  return args.currentData;
4607
4295
  }
4608
4296
  const customData = { ...args.currentData };
4609
- const changes = _21.reduce(
4297
+ const changes = _23.reduce(
4610
4298
  args.proposedData,
4611
4299
  (result, value, key) => {
4612
4300
  if (args.currentData[key] !== value) {
@@ -4674,57 +4362,57 @@ import Z5 from "zod";
4674
4362
  import Ora6 from "ora";
4675
4363
 
4676
4364
  // src/cli/utils/lockfile.ts
4677
- import fs12 from "fs";
4678
- import path16 from "path";
4365
+ import fs11 from "fs";
4366
+ import path15 from "path";
4679
4367
  import Z4 from "zod";
4680
4368
  import YAML4 from "yaml";
4681
4369
  import { MD5 as MD52 } from "object-hash";
4682
- import _22 from "lodash";
4370
+ import _24 from "lodash";
4683
4371
  function createLockfileHelper() {
4684
4372
  return {
4685
4373
  isLockfileExists: () => {
4686
4374
  const lockfilePath = _getLockfilePath();
4687
- return fs12.existsSync(lockfilePath);
4375
+ return fs11.existsSync(lockfilePath);
4688
4376
  },
4689
4377
  registerSourceData: (pathPattern, sourceData) => {
4690
4378
  const lockfile = _loadLockfile();
4691
4379
  const sectionKey = MD52(pathPattern);
4692
- const sectionChecksums = _22.mapValues(sourceData, (value) => MD52(value));
4380
+ const sectionChecksums = _24.mapValues(sourceData, (value) => MD52(value));
4693
4381
  lockfile.checksums[sectionKey] = sectionChecksums;
4694
4382
  _saveLockfile(lockfile);
4695
4383
  },
4696
4384
  registerPartialSourceData: (pathPattern, partialSourceData) => {
4697
4385
  const lockfile = _loadLockfile();
4698
4386
  const sectionKey = MD52(pathPattern);
4699
- const sectionChecksums = _22.mapValues(partialSourceData, (value) => MD52(value));
4700
- lockfile.checksums[sectionKey] = _22.merge({}, lockfile.checksums[sectionKey] ?? {}, sectionChecksums);
4387
+ const sectionChecksums = _24.mapValues(partialSourceData, (value) => MD52(value));
4388
+ lockfile.checksums[sectionKey] = _24.merge({}, lockfile.checksums[sectionKey] ?? {}, sectionChecksums);
4701
4389
  _saveLockfile(lockfile);
4702
4390
  },
4703
4391
  extractUpdatedData: (pathPattern, sourceData) => {
4704
4392
  const lockfile = _loadLockfile();
4705
4393
  const sectionKey = MD52(pathPattern);
4706
- const currentChecksums = _22.mapValues(sourceData, (value) => MD52(value));
4394
+ const currentChecksums = _24.mapValues(sourceData, (value) => MD52(value));
4707
4395
  const savedChecksums = lockfile.checksums[sectionKey] || {};
4708
- const updatedData = _22.pickBy(sourceData, (value, key) => savedChecksums[key] !== currentChecksums[key]);
4396
+ const updatedData = _24.pickBy(sourceData, (value, key) => savedChecksums[key] !== currentChecksums[key]);
4709
4397
  return updatedData;
4710
4398
  }
4711
4399
  };
4712
4400
  function _loadLockfile() {
4713
4401
  const lockfilePath = _getLockfilePath();
4714
- if (!fs12.existsSync(lockfilePath)) {
4402
+ if (!fs11.existsSync(lockfilePath)) {
4715
4403
  return LockfileSchema.parse({});
4716
4404
  }
4717
- const content = fs12.readFileSync(lockfilePath, "utf-8");
4405
+ const content = fs11.readFileSync(lockfilePath, "utf-8");
4718
4406
  const result = LockfileSchema.parse(YAML4.parse(content));
4719
4407
  return result;
4720
4408
  }
4721
4409
  function _saveLockfile(lockfile) {
4722
4410
  const lockfilePath = _getLockfilePath();
4723
4411
  const content = YAML4.stringify(lockfile);
4724
- fs12.writeFileSync(lockfilePath, content);
4412
+ fs11.writeFileSync(lockfilePath, content);
4725
4413
  }
4726
4414
  function _getLockfilePath() {
4727
- return path16.join(process.cwd(), "i18n.lock");
4415
+ return path15.join(process.cwd(), "i18n.lock");
4728
4416
  }
4729
4417
  }
4730
4418
  var LockfileSchema = Z4.object({
@@ -4775,7 +4463,7 @@ var flagsSchema = Z5.object({
4775
4463
  // src/cli/cmd/cleanup.ts
4776
4464
  import { resolveOverriddenLocale as resolveOverriddenLocale5 } from "@lingo.dev/_spec";
4777
4465
  import { Command as Command8 } from "interactive-commander";
4778
- import _23 from "lodash";
4466
+ import _25 from "lodash";
4779
4467
  import Ora7 from "ora";
4780
4468
  var cleanup_default = new Command8().command("cleanup").description("Remove keys from target files that do not exist in the source file").helpOption("-h, --help", "Show help").option("--locale <locale>", "Specific locale to cleanup").option("--bucket <bucket>", "Specific bucket to cleanup").option("--dry-run", "Show what would be removed without making changes").option(
4781
4469
  "--verbose",
@@ -4811,7 +4499,7 @@ var cleanup_default = new Command8().command("cleanup").description("Remove keys
4811
4499
  try {
4812
4500
  const targetData = await bucketLoader.pull(targetLocale);
4813
4501
  const targetKeys = Object.keys(targetData);
4814
- const keysToRemove = _23.difference(targetKeys, sourceKeys);
4502
+ const keysToRemove = _25.difference(targetKeys, sourceKeys);
4815
4503
  if (keysToRemove.length === 0) {
4816
4504
  bucketOra.succeed(`[${targetLocale}] No keys to remove`);
4817
4505
  continue;
@@ -4820,7 +4508,7 @@ var cleanup_default = new Command8().command("cleanup").description("Remove keys
4820
4508
  bucketOra.info(`[${targetLocale}] Keys to remove: ${JSON.stringify(keysToRemove, null, 2)}`);
4821
4509
  }
4822
4510
  if (!options.dryRun) {
4823
- const cleanedData = _23.pick(targetData, sourceKeys);
4511
+ const cleanedData = _25.pick(targetData, sourceKeys);
4824
4512
  await bucketLoader.push(targetLocale, cleanedData);
4825
4513
  bucketOra.succeed(`[${targetLocale}] Removed ${keysToRemove.length} keys`);
4826
4514
  } else {
@@ -4875,7 +4563,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
4875
4563
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4876
4564
  import Z6 from "zod";
4877
4565
  import { ReplexicaEngine } from "@lingo.dev/_sdk";
4878
- var mcp_default = new Command9().command("mcp").description("Use Lingo.dev model context provider with your AI agent").helpOption("-h, --help", "Show help").action(async (_24, program) => {
4566
+ var mcp_default = new Command9().command("mcp").description("Use Lingo.dev model context provider with your AI agent").helpOption("-h, --help", "Show help").action(async (_26, program) => {
4879
4567
  const apiKey = program.args[0];
4880
4568
  const settings = getSettings(apiKey);
4881
4569
  if (!settings.auth.apiKey) {
@@ -4933,7 +4621,7 @@ import { execSync as execSync2 } from "child_process";
4933
4621
 
4934
4622
  // ../../action/src/flows/in-branch.ts
4935
4623
  import { execSync } from "child_process";
4936
- import path17 from "path";
4624
+ import path16 from "path";
4937
4625
 
4938
4626
  // ../../action/src/flows/_base.ts
4939
4627
  var IntegrationFlow = class {
@@ -5011,7 +4699,7 @@ var InBranchFlow = class extends IntegrationFlow {
5011
4699
  return false;
5012
4700
  }
5013
4701
  }
5014
- const workingDir = path17.resolve(process.cwd(), this.platformKit.config.workingDir);
4702
+ const workingDir = path16.resolve(process.cwd(), this.platformKit.config.workingDir);
5015
4703
  if (workingDir !== process.cwd()) {
5016
4704
  this.ora.info(`Changing to working directory: ${this.platformKit.config.workingDir}`);
5017
4705
  process.chdir(workingDir);
@@ -5583,7 +5271,7 @@ var status_default = new Command11().command("status").description("Show the sta
5583
5271
  ora.succeed("Buckets retrieved");
5584
5272
  if (flags.file?.length) {
5585
5273
  buckets = buckets.map((bucket) => {
5586
- const paths = bucket.paths.filter((path18) => flags.file.find((file) => path18.pathPattern?.match(file)));
5274
+ const paths = bucket.paths.filter((path17) => flags.file.find((file) => path17.pathPattern?.match(file)));
5587
5275
  return { ...bucket, paths };
5588
5276
  }).filter((bucket) => bucket.paths.length > 0);
5589
5277
  if (buckets.length === 0) {
@@ -5593,8 +5281,8 @@ var status_default = new Command11().command("status").description("Show the sta
5593
5281
  ora.info(`\x1B[36mProcessing only filtered buckets:\x1B[0m`);
5594
5282
  buckets.map((bucket) => {
5595
5283
  ora.info(` ${bucket.type}:`);
5596
- bucket.paths.forEach((path18) => {
5597
- ora.info(` - ${path18.pathPattern}`);
5284
+ bucket.paths.forEach((path17) => {
5285
+ ora.info(` - ${path17.pathPattern}`);
5598
5286
  });
5599
5287
  });
5600
5288
  }
@@ -5823,10 +5511,10 @@ var status_default = new Command11().command("status").description("Show the sta
5823
5511
  if (flags.confirm && Object.keys(fileStats).length > 0) {
5824
5512
  console.log(chalk2.bold(`
5825
5513
  \u{1F4D1} BREAKDOWN BY FILE:`));
5826
- Object.entries(fileStats).sort((a, b) => b[1].wordCount - a[1].wordCount).forEach(([path18, stats]) => {
5514
+ Object.entries(fileStats).sort((a, b) => b[1].wordCount - a[1].wordCount).forEach(([path17, stats]) => {
5827
5515
  if (stats.sourceKeys === 0) return;
5828
5516
  console.log(chalk2.bold(`
5829
- \u2022 ${path18}:`));
5517
+ \u2022 ${path17}:`));
5830
5518
  console.log(` ${stats.sourceKeys} source keys, ~${stats.wordCount.toLocaleString()} source words`);
5831
5519
  const fileTable = new Table({
5832
5520
  head: ["Language", "Status", "Details"],
@@ -5956,7 +5644,7 @@ function validateParams2(i18nConfig, flags) {
5956
5644
  // package.json
5957
5645
  var package_default = {
5958
5646
  name: "lingo.dev",
5959
- version: "0.87.0",
5647
+ version: "0.87.2",
5960
5648
  description: "Lingo.dev CLI",
5961
5649
  private: false,
5962
5650
  publishConfig: {