@let-value/translate-extract 1.0.19 → 1.0.22

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.
@@ -1,4 +1,6 @@
1
1
  const require_run = require('../run-BonabcP6.cjs');
2
+ let node_util = require("node:util");
3
+ node_util = require_run.__toESM(node_util);
2
4
  let node_path = require("node:path");
3
5
  node_path = require_run.__toESM(node_path);
4
6
  let node_fs_promises = require("node:fs/promises");
@@ -59,15 +61,12 @@ function cleanup() {
59
61
  const files = await node_fs_promises.default.readdir(path$1).catch(() => []);
60
62
  for (const f of files.filter((p) => p.endsWith(".po"))) {
61
63
  const full = (0, node_path.join)(path$1, f);
62
- if (generated.has(full)) continue;
63
64
  const contents = await node_fs_promises.default.readFile(full).catch(() => void 0);
64
65
  if (!contents) continue;
65
66
  const parsed = gettext_parser.po.parse(contents);
66
- if (Object.entries(parsed.translations || {}).some(([ctx, msgs]) => Object.keys(msgs).some((id) => !(ctx === "" && id === "")))) build.context.logger?.warn({ path: full }, "stray translation file");
67
- else {
68
- await node_fs_promises.default.unlink(full);
69
- build.context.logger?.info({ path: full }, "removed empty translation file");
70
- }
67
+ const hasTranslations = Object.entries(parsed.translations || {}).some(([ctx, msgs]) => Object.keys(msgs).some((id) => !(ctx === "" && id === "")));
68
+ if (!hasTranslations && generated.has(full)) await node_fs_promises.default.unlink(full);
69
+ if (hasTranslations && !generated.has(full)) build.context.logger?.warn({ path: full }, "stray translation file");
71
70
  }
72
71
  });
73
72
  }
@@ -659,20 +658,7 @@ function core() {
659
658
  }
660
659
 
661
660
  //#endregion
662
- //#region src/plugins/po/po.ts
663
- function formatDate(date) {
664
- const pad = (n) => n.toString().padStart(2, "0");
665
- const year = date.getFullYear();
666
- const month = pad(date.getMonth() + 1);
667
- const day = pad(date.getDate());
668
- const hours = pad(date.getHours());
669
- const minutes = pad(date.getMinutes());
670
- const tzo = -date.getTimezoneOffset();
671
- const sign = tzo >= 0 ? "+" : "-";
672
- const offsetHours = pad(Math.floor(Math.abs(tzo) / 60));
673
- const offsetMinutes = pad(Math.abs(tzo) % 60);
674
- return `${year}-${month}-${day} ${hours}:${minutes}${sign}${offsetHours}${offsetMinutes}`;
675
- }
661
+ //#region src/plugins/po/collect.ts
676
662
  function collect(source, locale) {
677
663
  const translations = { "": {} };
678
664
  const nplurals = locale ? (0, plural_forms.getNPlurals)(locale) : void 0;
@@ -705,25 +691,60 @@ function collect(source, locale) {
705
691
  }
706
692
  return translations;
707
693
  }
708
- function hasChanges(left, right) {
709
- const ignoredKeys = new Set(["pot-creation-date", "po-revision-date"]);
710
- function deepEqual(left$1, right$1) {
711
- if (left$1 === right$1) return true;
712
- if (left$1 == null || right$1 == null) return false;
713
- if (typeof left$1 !== typeof right$1) return false;
714
- if (Array.isArray(left$1)) {
715
- if (!Array.isArray(right$1) || left$1.length !== right$1.length) return false;
716
- return left$1.every((item, index) => deepEqual(item, right$1[index]));
717
- }
718
- if (typeof left$1 === "object") {
719
- const keys1 = Object.keys(left$1).filter((key) => !ignoredKeys.has(key));
720
- const keys2 = Object.keys(right$1).filter((key) => !ignoredKeys.has(key));
721
- if (keys1.length !== keys2.length) return false;
722
- return keys1.every((key) => deepEqual(left$1[key], right$1[key]));
723
- }
724
- return false;
694
+
695
+ //#endregion
696
+ //#region src/plugins/po/hasChanges.ts
697
+ const IGNORED_HEADER_KEYS = new Set(["pot-creation-date", "po-revision-date"]);
698
+ const IGNORED_HEADER_LINE_PREFIXES = ["pot-creation-date:", "po-revision-date:"];
699
+ function normalizeHeaderString(value) {
700
+ const lines = value.split("\n");
701
+ const hadTrailingNewline = value.endsWith("\n");
702
+ const filtered = lines.filter((line) => {
703
+ const trimmed = line.trimStart().toLowerCase();
704
+ return !IGNORED_HEADER_LINE_PREFIXES.some((prefix) => trimmed.startsWith(prefix));
705
+ }).map((line) => {
706
+ const separatorIndex = line.indexOf(":");
707
+ if (separatorIndex === -1) return line;
708
+ const key = line.slice(0, separatorIndex).trim().toLowerCase();
709
+ const value$1 = line.slice(separatorIndex + 1);
710
+ return `${key}:${value$1}`;
711
+ });
712
+ if (hadTrailingNewline && filtered[filtered.length - 1] !== "") filtered.push("");
713
+ return filtered.join("\n");
714
+ }
715
+ function normalize(translations) {
716
+ const compiled = gettext_parser.po.compile(translations);
717
+ const parsed = gettext_parser.po.parse(compiled);
718
+ if (parsed.headers) {
719
+ const normalizedHeaders = {};
720
+ for (const [key, value] of Object.entries(parsed.headers)) if (!IGNORED_HEADER_KEYS.has(key.toLowerCase())) normalizedHeaders[key.toLowerCase()] = value;
721
+ parsed.headers = normalizedHeaders;
725
722
  }
726
- return !deepEqual(left, right);
723
+ const headerMessage = parsed.translations?.[""]?.[""];
724
+ if (headerMessage?.msgstr) headerMessage.msgstr = headerMessage.msgstr.map((item) => normalizeHeaderString(item));
725
+ return parsed;
726
+ }
727
+ function hasChanges(left, right) {
728
+ if (!right) return true;
729
+ const normalizedLeft = normalize(left);
730
+ const normalizedRight = normalize(right);
731
+ return !(0, node_util.isDeepStrictEqual)(normalizedLeft, normalizedRight);
732
+ }
733
+
734
+ //#endregion
735
+ //#region src/plugins/po/merge.ts
736
+ function formatDate(date) {
737
+ const pad = (n) => n.toString().padStart(2, "0");
738
+ const year = date.getFullYear();
739
+ const month = pad(date.getMonth() + 1);
740
+ const day = pad(date.getDate());
741
+ const hours = pad(date.getHours());
742
+ const minutes = pad(date.getMinutes());
743
+ const tzo = -date.getTimezoneOffset();
744
+ const sign = tzo >= 0 ? "+" : "-";
745
+ const offsetHours = pad(Math.floor(Math.abs(tzo) / 60));
746
+ const offsetMinutes = pad(Math.abs(tzo) % 60);
747
+ return `${year}-${month}-${day} ${hours}:${minutes}${sign}${offsetHours}${offsetMinutes}`;
727
748
  }
728
749
  function merge(sources, existing, obsolete, locale, generatedAt) {
729
750
  let headers = {};
@@ -803,6 +824,9 @@ function merge(sources, existing, obsolete, locale, generatedAt) {
803
824
  ...obsolete === "mark" && Object.keys(obsoleteTranslations).length ? { obsolete: obsoleteTranslations } : {}
804
825
  };
805
826
  }
827
+
828
+ //#endregion
829
+ //#region src/plugins/po/po.ts
806
830
  const namespace = "translate";
807
831
  function po() {
808
832
  return {
@@ -1275,12 +1299,8 @@ function react() {
1275
1299
 
1276
1300
  //#endregion
1277
1301
  exports.cleanup = cleanup;
1278
- exports.collect = collect;
1279
1302
  exports.core = core;
1280
1303
  exports.defineConfig = defineConfig;
1281
- exports.formatDate = formatDate;
1282
- exports.hasChanges = hasChanges;
1283
- exports.merge = merge;
1284
1304
  exports.po = po;
1285
1305
  exports.react = react;
1286
1306
  exports.run = require_run.run;
@@ -1,6 +1,5 @@
1
1
  import { PluralFormsLocale } from "@let-value/translate";
2
2
  import { LogLevelNames, Logger } from "loglevel";
3
- import { GetTextTranslationRecord, GetTextTranslations } from "gettext-parser";
4
3
 
5
4
  //#region src/logger.d.ts
6
5
  type LogLevel = LogLevelNames;
@@ -94,13 +93,6 @@ interface Translation {
94
93
  declare function core(): Plugin<string, Translation[]>;
95
94
  //#endregion
96
95
  //#region src/plugins/po/po.d.ts
97
- interface Collected {
98
- translations: GetTextTranslationRecord;
99
- }
100
- declare function formatDate(date: Date): string;
101
- declare function collect(source: Translation[], locale?: string): GetTextTranslationRecord;
102
- declare function hasChanges(left: GetTextTranslations, right?: GetTextTranslations): boolean;
103
- declare function merge(sources: Collected[], existing: GetTextTranslations | undefined, obsolete: ObsoleteStrategy, locale: string, generatedAt: Date): GetTextTranslations;
104
96
  declare function po(): Plugin;
105
97
  //#endregion
106
98
  //#region src/configuration.d.ts
@@ -234,5 +226,5 @@ declare function run(entrypoint: ResolvedEntrypoint, {
234
226
  logger?: Logger;
235
227
  }): Promise<void>;
236
228
  //#endregion
237
- export { Build, Collected, Context, DestinationFn, EntrypointConfig, Exclude, ExcludeFn, Filter, LoadArgs, LoadHook, LoadResult, ObsoleteStrategy, Plugin, ProcessArgs, ProcessHook, ProcessResult, ResolveArgs, ResolveHook, ResolveResult, ResolvedConfig, ResolvedEntrypoint, Task, UserConfig, cleanup, collect, core, defineConfig, formatDate, hasChanges, merge, po, react, run };
229
+ export { Build, Context, DestinationFn, EntrypointConfig, Exclude, ExcludeFn, Filter, LoadArgs, LoadHook, LoadResult, ObsoleteStrategy, Plugin, ProcessArgs, ProcessHook, ProcessResult, ResolveArgs, ResolveHook, ResolveResult, ResolvedConfig, ResolvedEntrypoint, Task, UserConfig, cleanup, core, defineConfig, po, react, run };
238
230
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/logger.ts","../../src/plugin.ts","../../src/plugins/cleanup/cleanup.ts","../../src/plugins/core/queries/types.ts","../../src/plugins/core/core.ts","../../src/plugins/po/po.ts","../../src/configuration.ts","../../src/plugins/react/react.ts","../../src/run.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/logger.ts","../../src/plugin.ts","../../src/plugins/cleanup/cleanup.ts","../../src/plugins/core/queries/types.ts","../../src/plugins/core/core.ts","../../src/plugins/po/po.ts","../../src/configuration.ts","../../src/plugins/react/react.ts","../../src/run.ts"],"sourcesContent":[],"mappings":"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"}
@@ -1,5 +1,4 @@
1
1
  import log, { LogLevelNames, Logger } from "loglevel";
2
- import { GetTextTranslationRecord, GetTextTranslations } from "gettext-parser";
3
2
  import Parser from "tree-sitter";
4
3
  import { PluralFormsLocale } from "@let-value/translate";
5
4
 
@@ -95,13 +94,6 @@ interface Translation {
95
94
  declare function core(): Plugin<string, Translation[]>;
96
95
  //#endregion
97
96
  //#region src/plugins/po/po.d.ts
98
- interface Collected {
99
- translations: GetTextTranslationRecord;
100
- }
101
- declare function formatDate(date: Date): string;
102
- declare function collect(source: Translation[], locale?: string): GetTextTranslationRecord;
103
- declare function hasChanges(left: GetTextTranslations, right?: GetTextTranslations): boolean;
104
- declare function merge(sources: Collected[], existing: GetTextTranslations | undefined, obsolete: ObsoleteStrategy, locale: string, generatedAt: Date): GetTextTranslations;
105
97
  declare function po(): Plugin;
106
98
  //#endregion
107
99
  //#region src/configuration.d.ts
@@ -235,5 +227,5 @@ declare function run(entrypoint: ResolvedEntrypoint, {
235
227
  logger?: Logger;
236
228
  }): Promise<void>;
237
229
  //#endregion
238
- export { Build, Collected, Context, DestinationFn, EntrypointConfig, Exclude, ExcludeFn, Filter, LoadArgs, LoadHook, LoadResult, ObsoleteStrategy, Plugin, ProcessArgs, ProcessHook, ProcessResult, ResolveArgs, ResolveHook, ResolveResult, ResolvedConfig, ResolvedEntrypoint, Task, UserConfig, cleanup, collect, core, defineConfig, formatDate, hasChanges, merge, po, react, run };
230
+ export { Build, Context, DestinationFn, EntrypointConfig, Exclude, ExcludeFn, Filter, LoadArgs, LoadHook, LoadResult, ObsoleteStrategy, Plugin, ProcessArgs, ProcessHook, ProcessResult, ResolveArgs, ResolveHook, ResolveResult, ResolvedConfig, ResolvedEntrypoint, Task, UserConfig, cleanup, core, defineConfig, po, react, run };
239
231
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/logger.ts","../../src/plugin.ts","../../src/plugins/cleanup/cleanup.ts","../../src/plugins/core/queries/types.ts","../../src/plugins/core/core.ts","../../src/plugins/po/po.ts","../../src/configuration.ts","../../src/plugins/react/react.ts","../../src/run.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/logger.ts","../../src/plugin.ts","../../src/plugins/cleanup/cleanup.ts","../../src/plugins/core/queries/types.ts","../../src/plugins/core/core.ts","../../src/plugins/po/po.ts","../../src/configuration.ts","../../src/plugins/react/react.ts","../../src/run.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/src/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { run } from "../run-C_bYec-q.js";
2
+ import { isDeepStrictEqual } from "node:util";
2
3
  import path, { basename, dirname, extname, join, relative, resolve } from "node:path";
3
4
  import fs, { readFile } from "node:fs/promises";
4
5
  import * as gettextParser from "gettext-parser";
@@ -50,15 +51,12 @@ function cleanup() {
50
51
  const files = await fs.readdir(path$1).catch(() => []);
51
52
  for (const f of files.filter((p) => p.endsWith(".po"))) {
52
53
  const full = join(path$1, f);
53
- if (generated.has(full)) continue;
54
54
  const contents = await fs.readFile(full).catch(() => void 0);
55
55
  if (!contents) continue;
56
56
  const parsed = gettextParser.po.parse(contents);
57
- if (Object.entries(parsed.translations || {}).some(([ctx, msgs]) => Object.keys(msgs).some((id) => !(ctx === "" && id === "")))) build.context.logger?.warn({ path: full }, "stray translation file");
58
- else {
59
- await fs.unlink(full);
60
- build.context.logger?.info({ path: full }, "removed empty translation file");
61
- }
57
+ const hasTranslations = Object.entries(parsed.translations || {}).some(([ctx, msgs]) => Object.keys(msgs).some((id) => !(ctx === "" && id === "")));
58
+ if (!hasTranslations && generated.has(full)) await fs.unlink(full);
59
+ if (hasTranslations && !generated.has(full)) build.context.logger?.warn({ path: full }, "stray translation file");
62
60
  }
63
61
  });
64
62
  }
@@ -650,20 +648,7 @@ function core() {
650
648
  }
651
649
 
652
650
  //#endregion
653
- //#region src/plugins/po/po.ts
654
- function formatDate(date) {
655
- const pad = (n) => n.toString().padStart(2, "0");
656
- const year = date.getFullYear();
657
- const month = pad(date.getMonth() + 1);
658
- const day = pad(date.getDate());
659
- const hours = pad(date.getHours());
660
- const minutes = pad(date.getMinutes());
661
- const tzo = -date.getTimezoneOffset();
662
- const sign = tzo >= 0 ? "+" : "-";
663
- const offsetHours = pad(Math.floor(Math.abs(tzo) / 60));
664
- const offsetMinutes = pad(Math.abs(tzo) % 60);
665
- return `${year}-${month}-${day} ${hours}:${minutes}${sign}${offsetHours}${offsetMinutes}`;
666
- }
651
+ //#region src/plugins/po/collect.ts
667
652
  function collect(source, locale) {
668
653
  const translations = { "": {} };
669
654
  const nplurals = locale ? getNPlurals(locale) : void 0;
@@ -696,25 +681,60 @@ function collect(source, locale) {
696
681
  }
697
682
  return translations;
698
683
  }
699
- function hasChanges(left, right) {
700
- const ignoredKeys = new Set(["pot-creation-date", "po-revision-date"]);
701
- function deepEqual(left$1, right$1) {
702
- if (left$1 === right$1) return true;
703
- if (left$1 == null || right$1 == null) return false;
704
- if (typeof left$1 !== typeof right$1) return false;
705
- if (Array.isArray(left$1)) {
706
- if (!Array.isArray(right$1) || left$1.length !== right$1.length) return false;
707
- return left$1.every((item, index) => deepEqual(item, right$1[index]));
708
- }
709
- if (typeof left$1 === "object") {
710
- const keys1 = Object.keys(left$1).filter((key) => !ignoredKeys.has(key));
711
- const keys2 = Object.keys(right$1).filter((key) => !ignoredKeys.has(key));
712
- if (keys1.length !== keys2.length) return false;
713
- return keys1.every((key) => deepEqual(left$1[key], right$1[key]));
714
- }
715
- return false;
684
+
685
+ //#endregion
686
+ //#region src/plugins/po/hasChanges.ts
687
+ const IGNORED_HEADER_KEYS = new Set(["pot-creation-date", "po-revision-date"]);
688
+ const IGNORED_HEADER_LINE_PREFIXES = ["pot-creation-date:", "po-revision-date:"];
689
+ function normalizeHeaderString(value) {
690
+ const lines = value.split("\n");
691
+ const hadTrailingNewline = value.endsWith("\n");
692
+ const filtered = lines.filter((line) => {
693
+ const trimmed = line.trimStart().toLowerCase();
694
+ return !IGNORED_HEADER_LINE_PREFIXES.some((prefix) => trimmed.startsWith(prefix));
695
+ }).map((line) => {
696
+ const separatorIndex = line.indexOf(":");
697
+ if (separatorIndex === -1) return line;
698
+ const key = line.slice(0, separatorIndex).trim().toLowerCase();
699
+ const value$1 = line.slice(separatorIndex + 1);
700
+ return `${key}:${value$1}`;
701
+ });
702
+ if (hadTrailingNewline && filtered[filtered.length - 1] !== "") filtered.push("");
703
+ return filtered.join("\n");
704
+ }
705
+ function normalize(translations) {
706
+ const compiled = gettextParser.po.compile(translations);
707
+ const parsed = gettextParser.po.parse(compiled);
708
+ if (parsed.headers) {
709
+ const normalizedHeaders = {};
710
+ for (const [key, value] of Object.entries(parsed.headers)) if (!IGNORED_HEADER_KEYS.has(key.toLowerCase())) normalizedHeaders[key.toLowerCase()] = value;
711
+ parsed.headers = normalizedHeaders;
716
712
  }
717
- return !deepEqual(left, right);
713
+ const headerMessage = parsed.translations?.[""]?.[""];
714
+ if (headerMessage?.msgstr) headerMessage.msgstr = headerMessage.msgstr.map((item) => normalizeHeaderString(item));
715
+ return parsed;
716
+ }
717
+ function hasChanges(left, right) {
718
+ if (!right) return true;
719
+ const normalizedLeft = normalize(left);
720
+ const normalizedRight = normalize(right);
721
+ return !isDeepStrictEqual(normalizedLeft, normalizedRight);
722
+ }
723
+
724
+ //#endregion
725
+ //#region src/plugins/po/merge.ts
726
+ function formatDate(date) {
727
+ const pad = (n) => n.toString().padStart(2, "0");
728
+ const year = date.getFullYear();
729
+ const month = pad(date.getMonth() + 1);
730
+ const day = pad(date.getDate());
731
+ const hours = pad(date.getHours());
732
+ const minutes = pad(date.getMinutes());
733
+ const tzo = -date.getTimezoneOffset();
734
+ const sign = tzo >= 0 ? "+" : "-";
735
+ const offsetHours = pad(Math.floor(Math.abs(tzo) / 60));
736
+ const offsetMinutes = pad(Math.abs(tzo) % 60);
737
+ return `${year}-${month}-${day} ${hours}:${minutes}${sign}${offsetHours}${offsetMinutes}`;
718
738
  }
719
739
  function merge(sources, existing, obsolete, locale, generatedAt) {
720
740
  let headers = {};
@@ -794,6 +814,9 @@ function merge(sources, existing, obsolete, locale, generatedAt) {
794
814
  ...obsolete === "mark" && Object.keys(obsoleteTranslations).length ? { obsolete: obsoleteTranslations } : {}
795
815
  };
796
816
  }
817
+
818
+ //#endregion
819
+ //#region src/plugins/po/po.ts
797
820
  const namespace = "translate";
798
821
  function po() {
799
822
  return {
@@ -1265,5 +1288,5 @@ function react() {
1265
1288
  }
1266
1289
 
1267
1290
  //#endregion
1268
- export { cleanup, collect, core, defineConfig, formatDate, hasChanges, merge, po, react, run };
1291
+ export { cleanup, core, defineConfig, po, react, run };
1269
1292
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["namespace","path","path","importQuery: ImportQuerySpec","current: Parser.SyntaxNode | null","messageQuery: QuerySpec","allowed","messageInvalidQuery: QuerySpec","ids: string[]","strs: string[]","subMatch: Parser.QueryMatch","translation: Translation","contextMsgQuery: QuerySpec","msgCall","contextPluralQuery: QuerySpec","contextInvalidQuery: QuerySpec","gettextQuery: QuerySpec","gettextInvalidQuery: QuerySpec","msgCall","plainMsg","msgArg","ngettextQuery: QuerySpec","msgCall","npgettextQuery: QuerySpec","pgettextQuery: QuerySpec","pluralQuery: QuerySpec","queries: QuerySpec[]","messageQuery","pluralQuery","path","parseSource","context: Context","translations: Translation[]","warnings: Warning[]","imports: string[]","queries","fs","resolved: string[]","filter","namespace","path","parseSource","translations: GetTextTranslationRecord","left","right","headers: Record<string, string>","obsoleteTranslations: GetTextTranslationRecord","collected: GetTextTranslationRecord","translations","existing","path","defaultDestination: DestinationFn","defaultExclude: Exclude[]","parts: Part[]","text","strings: string[]","values: string[]","messageQuery: QuerySpec","attrs: Parser.SyntaxNode[]","msgctxt: string | undefined","childValue: Parser.SyntaxNode | undefined","error: string | undefined","translation: Translation","forms: string[]","pluralQuery: QuerySpec","attrs: Parser.SyntaxNode[]","msgctxt: string | undefined","formsNode: Parser.SyntaxNode | null | undefined","translation: Translation","queries: QuerySpec[]","context: Context","path","translations: Translation[]","warnings: Warning[]","path"],"sources":["../../src/plugins/cleanup/cleanup.ts","../../src/plugins/core/queries/comment.ts","../../src/plugins/core/queries/import.ts","../../src/plugins/core/queries/utils.ts","../../src/plugins/core/queries/message.ts","../../src/plugins/core/queries/plural-utils.ts","../../src/plugins/core/queries/context.ts","../../src/plugins/core/queries/gettext.ts","../../src/plugins/core/queries/ngettext.ts","../../src/plugins/core/queries/npgettext.ts","../../src/plugins/core/queries/pgettext.ts","../../src/plugins/core/queries/plural.ts","../../src/plugins/core/queries/index.ts","../../src/plugins/core/parse.ts","../../src/plugins/core/resolve.ts","../../src/plugins/core/core.ts","../../src/plugins/po/po.ts","../../src/configuration.ts","../../src/plugins/react/queries/utils.ts","../../src/plugins/react/queries/message.ts","../../src/plugins/react/queries/plural.ts","../../src/plugins/react/queries/index.ts","../../src/plugins/react/parse.ts","../../src/plugins/react/react.ts"],"sourcesContent":["import fs from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport * as gettextParser from \"gettext-parser\";\n\nimport type { Plugin } from \"../../plugin.ts\";\n\nconst namespace = \"cleanup\";\n\nexport function cleanup(): Plugin {\n return {\n name: \"cleanup\",\n setup(build) {\n build.context.logger?.debug(\"cleanup plugin initialized\");\n const processed = new Set<string>();\n const generated = new Set<string>();\n const dirs = new Set<string>();\n let dispatched = false;\n\n build.onResolve({ namespace, filter: /.*/ }, ({ path }) => {\n generated.add(path);\n dirs.add(dirname(path));\n\n Promise.all([build.defer(\"source\"), build.defer(\"translate\"), build.defer(namespace)]).then(() => {\n if (dispatched) {\n return;\n }\n dispatched = true;\n\n for (const path of dirs.values()) {\n build.process({ entrypoint: path, path, namespace, data: undefined });\n }\n });\n\n return undefined;\n });\n\n build.onProcess({ namespace, filter: /.*/ }, async ({ path }) => {\n if (processed.has(path)) {\n return undefined;\n }\n processed.add(path);\n const files = await fs.readdir(path).catch(() => []);\n for (const f of files.filter((p) => p.endsWith(\".po\"))) {\n const full = join(path, f);\n if (generated.has(full)) {\n continue;\n }\n const contents = await fs.readFile(full).catch(() => undefined);\n if (!contents) {\n continue;\n }\n const parsed = gettextParser.po.parse(contents);\n const hasTranslations = Object.entries(parsed.translations || {}).some(([ctx, msgs]) =>\n Object.keys(msgs).some((id) => !(ctx === \"\" && id === \"\")),\n );\n if (hasTranslations) {\n build.context.logger?.warn({ path: full }, \"stray translation file\");\n } else {\n await fs.unlink(full);\n build.context.logger?.info({ path: full }, \"removed empty translation file\");\n }\n }\n return undefined;\n });\n },\n };\n}\n","import { relative } from \"node:path\";\nimport type Parser from \"tree-sitter\";\n\nimport type { Context, QuerySpec } from \"./types.ts\";\n\nexport function getReference(node: Parser.SyntaxNode, { path }: Context) {\n const line = node.startPosition.row + 1;\n const rel = relative(process.cwd(), path).replace(/\\\\+/g, \"/\");\n return `${rel}:${line}`;\n}\n\nfunction getComment(node: Parser.SyntaxNode): string {\n const text = node.text;\n if (text.startsWith(\"/*\")) {\n return text\n .slice(2, -2)\n .replace(/^\\s*\\*?\\s*/gm, \"\")\n .trim();\n }\n return text.replace(/^\\/\\/\\s?/, \"\").trim();\n}\n\nexport const withComment = (query: QuerySpec): QuerySpec => ({\n pattern: `(\n\t((comment) @comment)?\n .\n\t(_ ${query.pattern})\n)`,\n extract(match) {\n const result = query.extract(match);\n if (!result?.translation) {\n return result;\n }\n\n const comment = match.captures.find((c) => c.name === \"comment\")?.node;\n if (!comment) {\n return result;\n }\n\n if (comment) {\n result.translation.comments = {\n ...result.translation.comments,\n extracted: getComment(comment),\n };\n }\n\n return result;\n },\n});\n","import type Parser from \"tree-sitter\";\nimport type { ImportQuerySpec } from \"./types.ts\";\n\nexport const importQuery: ImportQuerySpec = {\n pattern: `\n [\n (import_statement\n source: (string (string_fragment) @import))\n (export_statement\n source: (string (string_fragment) @import))\n (call_expression\n function: (identifier) @func\n arguments: (arguments (string (string_fragment) @import))\n (#eq? @func \"require\"))\n (call_expression\n function: (member_expression\n object: (identifier) @obj\n property: (property_identifier) @method)\n arguments: (arguments (string (string_fragment) @import))\n (#eq? @obj \"require\")\n (#eq? @method \"resolve\"))\n (call_expression\n function: (import)\n arguments: (arguments (string (string_fragment) @import)))\n ]\n `,\n extract(match: Parser.QueryMatch): string | undefined {\n const node = match.captures.find((c) => c.name === \"import\")?.node;\n return node?.text;\n },\n};\n","import type Parser from \"tree-sitter\";\n\nexport const callPattern = (fnName: string, args: string, allowMember = true): string => `(\n (call_expression\n function: ${\n allowMember\n ? `[\n (identifier) @func\n (member_expression property: (property_identifier) @func)\n ]`\n : `(identifier) @func`\n }\n arguments: ${args}\n ) @call\n (#eq? @func \"${fnName}\")\n)`;\n\nexport function isDescendant(node: Parser.SyntaxNode, ancestor: Parser.SyntaxNode): boolean {\n let current: Parser.SyntaxNode | null = node;\n while (current) {\n if (current.id === ancestor.id) return true;\n current = current.parent;\n }\n return false;\n}\n","import type Parser from \"tree-sitter\";\nimport { withComment } from \"./comment.ts\";\nimport type { MessageMatch, QuerySpec } from \"./types.ts\";\nimport { callPattern } from \"./utils.ts\";\n\nconst notInPlural = (query: QuerySpec): QuerySpec => ({\n pattern: query.pattern,\n extract(match) {\n const result = query.extract(match);\n if (!result?.node) {\n return result;\n }\n\n let parent = result.node.parent;\n\n if (parent && parent.type === \"arguments\") {\n parent = parent.parent;\n }\n\n if (parent && parent.type === \"call_expression\") {\n const fn = parent.childForFieldName(\"function\");\n if (fn) {\n if (\n (fn.type === \"identifier\" &&\n (fn.text === \"plural\" ||\n fn.text === \"ngettext\" ||\n fn.text === \"pgettext\" ||\n fn.text === \"npgettext\")) ||\n (fn.type === \"member_expression\" &&\n [\"plural\", \"ngettext\", \"pgettext\", \"npgettext\"].includes(\n fn.childForFieldName(\"property\")?.text ?? \"\",\n ))\n ) {\n return undefined;\n }\n }\n }\n\n return result;\n },\n});\n\nexport const messageArg = `[\n (string (string_fragment) @msgid)\n (object\n (_)*\n (pair\n key: (property_identifier) @id_key\n value: (string (string_fragment) @id)\n (#eq? @id_key \"id\")\n )?\n (_)*\n (pair\n key: (property_identifier) @msg_key\n value: (string (string_fragment) @message)\n (#eq? @msg_key \"message\")\n )?\n (_)*\n )\n (template_string) @tpl\n]`;\n\nexport const messageArgs = `[ (arguments ${messageArg}) (template_string) @tpl ]`;\n\nexport const extractMessage =\n (name: string) =>\n (match: Parser.QueryMatch): MessageMatch | undefined => {\n const node = match.captures.find((c) => c.name === \"call\")?.node;\n if (!node) {\n return undefined;\n }\n\n const msgid = match.captures.find((c) => c.name === \"msgid\")?.node.text;\n if (msgid) {\n return {\n node,\n translation: {\n id: msgid,\n message: [msgid],\n },\n };\n }\n\n const tpl = match.captures.find((c) => c.name === \"tpl\")?.node;\n if (tpl) {\n for (const child of tpl.children) {\n if (child.type !== \"template_substitution\") {\n continue;\n }\n\n const expr = child.namedChildren[0];\n if (!expr || expr.type !== \"identifier\") {\n return {\n node,\n error: `${name}() template expressions must be simple identifiers`,\n };\n }\n }\n\n const text = tpl.text.slice(1, -1);\n\n return {\n node,\n translation: { id: text, message: [text] },\n };\n }\n\n const id = match.captures.find((c) => c.name === \"id\")?.node.text;\n const message = match.captures.find((c) => c.name === \"message\")?.node.text;\n const msgId = id ?? message;\n if (!msgId) {\n return undefined;\n }\n\n const msgstr = message ?? id ?? \"\";\n\n return {\n node,\n translation: {\n id: msgId,\n message: [msgstr],\n },\n };\n };\n\nexport const messageQuery: QuerySpec = notInPlural(\n withComment({\n pattern: callPattern(\"message\", messageArgs),\n extract: extractMessage(\"message\"),\n }),\n);\n\nconst allowed = new Set([\"string\", \"object\", \"template_string\"]);\n\nexport const messageInvalidQuery: QuerySpec = notInPlural({\n pattern: callPattern(\"message\", \"(arguments (_) @arg)\"),\n extract(match) {\n const call = match.captures.find((c) => c.name === \"call\")?.node;\n const node = match.captures.find((c) => c.name === \"arg\")?.node;\n\n if (!call || !node) {\n return undefined;\n }\n\n if (allowed.has(node.type)) {\n return undefined;\n }\n\n return {\n node,\n error: \"message() argument must be a string literal, object literal, or template literal\",\n };\n },\n});\n","import type Parser from \"tree-sitter\";\nimport { extractMessage } from \"./message.ts\";\nimport type { MessageMatch, Translation } from \"./types.ts\";\nimport { isDescendant } from \"./utils.ts\";\n\nexport const extractPluralForms =\n (name: string) =>\n (match: Parser.QueryMatch): MessageMatch | undefined => {\n const call = match.captures.find((c) => c.name === \"call\")?.node;\n const n = match.captures.find((c) => c.name === \"n\")?.node;\n if (!call || !n || n.nextNamedSibling) {\n return undefined;\n }\n\n const msgctxt = match.captures.find((c) => c.name === \"msgctxt\")?.node?.text;\n const msgNodes = match.captures.filter((c) => c.name === \"msg\").map((c) => c.node);\n\n const ids: string[] = [];\n const strs: string[] = [];\n\n for (const node of msgNodes) {\n const relevant = match.captures.filter(\n (c) => [\"msgid\", \"id\", \"message\", \"tpl\"].includes(c.name) && isDescendant(c.node, node),\n );\n\n const subMatch: Parser.QueryMatch = {\n pattern: 0,\n captures: [{ name: \"call\", node }, ...relevant],\n };\n\n const result = extractMessage(name)(subMatch);\n if (!result) continue;\n if (result.error) {\n return { node: call, error: result.error };\n }\n if (result.translation) {\n ids.push(result.translation.id);\n strs.push(result.translation.message[0] ?? \"\");\n }\n }\n\n if (ids.length === 0) {\n return undefined;\n }\n\n const translation: Translation = {\n id: ids[0],\n plural: ids[1],\n message: strs,\n };\n if (msgctxt) translation.context = msgctxt;\n\n return { node: call, translation };\n };\n","import { withComment } from \"./comment.ts\";\nimport { extractMessage, messageArgs } from \"./message.ts\";\nimport { extractPluralForms } from \"./plural-utils.ts\";\nimport type { QuerySpec } from \"./types.ts\";\nimport { callPattern } from \"./utils.ts\";\n\nconst ctxCall = callPattern(\"context\", `(arguments (string (string_fragment) @msgctxt))`)\n .replace(/@call/g, \"@ctx\")\n .replace(/@func/g, \"@ctxfn\");\n\nexport const contextMsgQuery: QuerySpec = withComment({\n pattern: `(\n (call_expression\n function: (member_expression\n object: ${ctxCall}\n property: (property_identifier) @func\n )\n arguments: ${messageArgs}\n ) @call\n (#eq? @func \"message\")\n)`,\n extract(match) {\n const result = extractMessage(\"context.message\")(match);\n const contextNode = match.captures.find((c) => c.name === \"msgctxt\")?.node;\n if (!result || !result.translation || !contextNode) {\n return result;\n }\n return {\n node: result.node,\n translation: {\n ...result.translation,\n context: contextNode.text,\n },\n };\n },\n});\n\nconst msgCall = callPattern(\"message\", messageArgs, false).replace(/@call/g, \"@msg\").replace(/@func/g, \"@msgfn\");\n\nexport const contextPluralQuery: QuerySpec = withComment({\n pattern: `(\n (call_expression\n function: (member_expression\n object: ${ctxCall}\n property: (property_identifier) @func\n )\n arguments: (arguments (\n (${msgCall} (\",\" )?)+\n (number) @n\n ))\n ) @call\n (#eq? @func \"plural\")\n)`,\n extract: extractPluralForms(\"context.plural\"),\n});\n\nexport const contextInvalidQuery: QuerySpec = withComment({\n pattern: ctxCall,\n extract(match) {\n const call = match.captures.find((c) => c.name === \"ctx\")?.node;\n if (!call) {\n return undefined;\n }\n\n const parent = call.parent;\n if (parent && parent.type === \"member_expression\" && parent.childForFieldName(\"object\")?.id === call.id) {\n const property = parent.childForFieldName(\"property\")?.text;\n const grandparent = parent.parent;\n if (\n grandparent &&\n grandparent.type === \"call_expression\" &&\n grandparent.childForFieldName(\"function\")?.id === parent.id &&\n (property === \"message\" || property === \"plural\")\n ) {\n return undefined;\n }\n }\n\n return {\n node: call,\n error: \"context() must be used with message() or plural() in the same expression\",\n };\n },\n});\n","import { withComment } from \"./comment.ts\";\nimport { extractMessage, messageArgs } from \"./message.ts\";\nimport type { QuerySpec } from \"./types.ts\";\nimport { callPattern } from \"./utils.ts\";\n\nexport const gettextQuery: QuerySpec = withComment({\n pattern: callPattern(\"gettext\", messageArgs),\n extract: extractMessage(\"gettext\"),\n});\n\nconst allowed = new Set([\"string\", \"object\", \"template_string\", \"identifier\", \"call_expression\"]);\n\nexport const gettextInvalidQuery: QuerySpec = {\n pattern: callPattern(\"gettext\", \"(arguments (_) @arg)\"),\n extract(match) {\n const call = match.captures.find((c) => c.name === \"call\")?.node;\n const node = match.captures.find((c) => c.name === \"arg\")?.node;\n\n if (!call || !node) {\n return undefined;\n }\n\n if (allowed.has(node.type)) {\n return undefined;\n }\n\n return {\n node,\n error: \"gettext() argument must be a string literal, object literal, or template literal\",\n };\n },\n};\n","import { withComment } from \"./comment.ts\";\nimport { messageArg, messageArgs } from \"./message.ts\";\nimport { extractPluralForms } from \"./plural-utils.ts\";\nimport type { QuerySpec } from \"./types.ts\";\nimport { callPattern } from \"./utils.ts\";\n\nconst msgCall = callPattern(\"message\", messageArgs).replace(/@call/g, \"@msg\").replace(/@func/g, \"@msgfn\");\nconst plainMsg = `(${messageArg}) @msg`;\nconst msgArg = `[${msgCall} ${plainMsg}]`;\n\nexport const ngettextQuery: QuerySpec = withComment({\n pattern: callPattern(\"ngettext\", `(arguments ${msgArg} \",\" ${msgArg} (\",\" ${msgArg})* \",\" (_) @n)`),\n extract: extractPluralForms(\"ngettext\"),\n});\n","import { withComment } from \"./comment.ts\";\nimport { messageArg, messageArgs } from \"./message.ts\";\nimport { extractPluralForms } from \"./plural-utils.ts\";\nimport type { QuerySpec } from \"./types.ts\";\nimport { callPattern } from \"./utils.ts\";\n\nconst msgCall = callPattern(\"message\", messageArgs).replace(/@call/g, \"@msg\").replace(/@func/g, \"@msgfn\");\nconst plainMsg = `(${messageArg}) @msg`;\nconst msgArg = `[${msgCall} ${plainMsg}]`;\n\nexport const npgettextQuery: QuerySpec = withComment({\n pattern: callPattern(\n \"npgettext\",\n `(arguments (string (string_fragment) @msgctxt) \",\" ${msgArg} \",\" ${msgArg} (\",\" ${msgArg})* \",\" (_) @n)`,\n ),\n extract: extractPluralForms(\"npgettext\"),\n});\n","import { withComment } from \"./comment.ts\";\nimport { extractMessage, messageArg } from \"./message.ts\";\nimport type { QuerySpec } from \"./types.ts\";\nimport { callPattern } from \"./utils.ts\";\n\nexport const pgettextQuery: QuerySpec = withComment({\n pattern: callPattern(\"pgettext\", `(arguments (string (string_fragment) @msgctxt) \",\" ${messageArg})`),\n extract(match) {\n const result = extractMessage(\"pgettext\")(match);\n const contextNode = match.captures.find((c) => c.name === \"msgctxt\")?.node;\n if (!result || !contextNode || !result.translation) {\n return result;\n }\n return {\n node: result.node,\n translation: {\n ...result.translation,\n context: contextNode.text,\n },\n };\n },\n});\n","import { withComment } from \"./comment.ts\";\nimport { messageArgs } from \"./message.ts\";\nimport { extractPluralForms } from \"./plural-utils.ts\";\nimport type { QuerySpec } from \"./types.ts\";\nimport { callPattern } from \"./utils.ts\";\n\nconst msgCall = callPattern(\"message\", messageArgs, false).replace(/@call/g, \"@msg\").replace(/@func/g, \"@msgfn\");\n\nexport const pluralQuery: QuerySpec = withComment({\n pattern: callPattern(\n \"plural\",\n `(arguments (\n (${msgCall} (\",\" )?)+\n (number) @n\n ))`,\n false,\n ),\n extract: extractPluralForms(\"plural\"),\n});\n","import { contextInvalidQuery, contextMsgQuery, contextPluralQuery } from \"./context.ts\";\nimport { gettextInvalidQuery, gettextQuery } from \"./gettext.ts\";\nimport { messageInvalidQuery, messageQuery } from \"./message.ts\";\nimport { ngettextQuery } from \"./ngettext.ts\";\nimport { npgettextQuery } from \"./npgettext.ts\";\nimport { pgettextQuery } from \"./pgettext.ts\";\nimport { pluralQuery } from \"./plural.ts\";\nimport type { QuerySpec } from \"./types.ts\";\n\nexport type { MessageMatch, QuerySpec } from \"./types.ts\";\n\nexport const queries: QuerySpec[] = [\n messageQuery,\n messageInvalidQuery,\n gettextQuery,\n gettextInvalidQuery,\n pluralQuery,\n ngettextQuery,\n pgettextQuery,\n npgettextQuery,\n contextMsgQuery,\n contextPluralQuery,\n contextInvalidQuery,\n];\n","import fs from \"node:fs\";\nimport { extname, resolve } from \"node:path\";\n\nimport Parser from \"tree-sitter\";\nimport JavaScript from \"tree-sitter-javascript\";\nimport TS from \"tree-sitter-typescript\";\n\nimport { getReference } from \"./queries/comment.ts\";\nimport { importQuery } from \"./queries/import.ts\";\nimport { queries } from \"./queries/index.ts\";\nimport type { Context, Translation, Warning } from \"./queries/types.ts\";\n\nexport interface ParseResult {\n translations: Translation[];\n imports: string[];\n warnings: Warning[];\n}\n\nfunction getLanguage(ext: string) {\n switch (ext) {\n case \".ts\":\n return TS.typescript;\n case \".tsx\":\n return TS.tsx;\n default:\n return JavaScript;\n }\n}\n\nconst parserCache = new Map<string, { parser: Parser; language: Parser.Language }>();\nconst queryCache = new WeakMap<Parser.Language, Map<string, Parser.Query>>();\n\nfunction getCachedParser(ext: string) {\n let cached = parserCache.get(ext);\n if (!cached) {\n const parser = new Parser();\n const language = getLanguage(ext) as Parser.Language;\n parser.setLanguage(language);\n cached = { parser, language };\n parserCache.set(ext, cached);\n }\n return cached;\n}\n\nfunction getCachedQuery(language: Parser.Language, pattern: string) {\n let cache = queryCache.get(language);\n if (!cache) {\n cache = new Map();\n queryCache.set(language, cache);\n }\n\n let query = cache.get(pattern);\n if (!query) {\n query = new Parser.Query(language, pattern);\n cache.set(pattern, query);\n }\n\n return query;\n}\n\nexport function getParser(path: string) {\n const ext = extname(path);\n return getCachedParser(ext);\n}\n\nexport function getQuery(language: Parser.Language, pattern: string) {\n return getCachedQuery(language, pattern);\n}\n\nexport function parseFile(filePath: string): ParseResult {\n const path = resolve(filePath);\n const source = fs.readFileSync(path, \"utf8\");\n return parseSource(source, path);\n}\n\nexport function parseSource(source: string, path: string): ParseResult {\n const context: Context = {\n path,\n };\n\n const { parser, language } = getParser(path);\n const tree = parser.parse(source);\n\n const translations: Translation[] = [];\n const warnings: Warning[] = [];\n const imports: string[] = [];\n\n const seen = new Set<number>();\n\n for (const spec of queries) {\n const query = getCachedQuery(language, spec.pattern);\n for (const match of query.matches(tree.rootNode)) {\n const message = spec.extract(match);\n if (!message) {\n continue;\n }\n\n const { node, translation, error } = message;\n if (seen.has(node.id)) {\n continue;\n }\n seen.add(node.id);\n const reference = getReference(node, context);\n\n if (translation) {\n translations.push({\n ...translation,\n comments: {\n ...translation.comments,\n reference,\n },\n });\n }\n\n if (error) {\n warnings.push({\n error,\n reference,\n });\n }\n }\n }\n\n const importTreeQuery = getCachedQuery(language, importQuery.pattern);\n for (const match of importTreeQuery.matches(tree.rootNode)) {\n const imp = importQuery.extract(match);\n if (imp) {\n imports.push(imp);\n }\n }\n\n return { translations, imports, warnings };\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { ResolverFactory } from \"oxc-resolver\";\n\nfunction findTsconfig(dir: string): string | undefined {\n let current = dir;\n while (true) {\n const config = path.join(current, \"tsconfig.json\");\n if (fs.existsSync(config)) {\n return config;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n return undefined;\n }\n current = parent;\n }\n}\n\nconst resolverCache = new Map<string, ResolverFactory>();\n\nfunction getResolver(dir: string) {\n const tsconfig = findTsconfig(dir);\n const key = tsconfig ?? \"__default__\";\n let resolver = resolverCache.get(key);\n if (!resolver) {\n resolver = new ResolverFactory({\n extensions: [\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\", \".cjs\", \".json\"],\n conditionNames: [\"import\", \"require\", \"node\"],\n ...(tsconfig ? { tsconfig: { configFile: tsconfig } } : {}),\n });\n resolverCache.set(key, resolver);\n }\n return resolver;\n}\n\nfunction resolveFromDir(dir: string, spec: string): string | undefined {\n const resolver = getResolver(dir);\n const res = resolver.sync(dir, spec) as { path?: string };\n return res.path;\n}\n\nexport function resolveImport(file: string, spec: string): string | undefined {\n const dir = path.dirname(path.resolve(file));\n return resolveFromDir(dir, spec);\n}\n\nexport function resolveImports(file: string, imports: string[]): string[] {\n const dir = path.dirname(path.resolve(file));\n const resolver = getResolver(dir);\n const resolved: string[] = [];\n for (const spec of imports) {\n const res = resolver.sync(dir, spec) as { path?: string };\n if (res.path) {\n resolved.push(res.path);\n }\n }\n return resolved;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nimport type { Plugin } from \"../../plugin.ts\";\nimport { parseSource } from \"./parse.ts\";\nimport type { Translation } from \"./queries/types.ts\";\nimport { resolveImports } from \"./resolve.ts\";\n\nconst filter = /\\.([cm]?tsx?|jsx?)$/;\nconst namespace = \"source\";\n\nexport function core(): Plugin<string, Translation[]> {\n return {\n name: \"core\",\n setup(build) {\n build.context.logger?.debug(\"core plugin initialized\");\n build.onResolve({ filter, namespace }, ({ entrypoint, path }) => {\n return {\n entrypoint,\n namespace,\n path: resolve(path),\n };\n });\n\n build.onLoad({ filter, namespace }, async ({ entrypoint, path }) => {\n const data = await readFile(path, \"utf8\");\n return {\n entrypoint,\n path,\n namespace,\n data,\n };\n });\n\n build.onProcess({ filter, namespace }, ({ entrypoint, path, data }) => {\n const { translations, imports, warnings } = parseSource(data, path);\n\n if (build.context.config.walk) {\n const paths = resolveImports(path, imports);\n for (const path of paths) {\n build.resolve({ entrypoint, path, namespace });\n }\n }\n\n for (const warning of warnings) {\n build.context.logger?.warn(`${warning.error} at ${warning.reference}`);\n }\n\n build.resolve({\n entrypoint,\n path,\n namespace: \"translate\",\n data: translations,\n });\n\n return undefined;\n });\n },\n };\n}\n","import fs from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n\nimport type { GetTextTranslationRecord, GetTextTranslations } from \"gettext-parser\";\nimport * as gettextParser from \"gettext-parser\";\nimport { getFormula, getNPlurals } from \"plural-forms\";\n\nimport type { ObsoleteStrategy } from \"../../configuration.ts\";\nimport type { Plugin } from \"../../plugin.ts\";\nimport type { Translation } from \"../core/queries/types.ts\";\n\nexport interface Collected {\n translations: GetTextTranslationRecord;\n}\n\nexport function formatDate(date: Date): string {\n const pad = (n: number) => n.toString().padStart(2, \"0\");\n const year = date.getFullYear();\n const month = pad(date.getMonth() + 1);\n const day = pad(date.getDate());\n const hours = pad(date.getHours());\n const minutes = pad(date.getMinutes());\n const tzo = -date.getTimezoneOffset();\n const sign = tzo >= 0 ? \"+\" : \"-\";\n const offsetHours = pad(Math.floor(Math.abs(tzo) / 60));\n const offsetMinutes = pad(Math.abs(tzo) % 60);\n return `${year}-${month}-${day} ${hours}:${minutes}${sign}${offsetHours}${offsetMinutes}`;\n}\n\nexport function collect(source: Translation[], locale?: string): GetTextTranslationRecord {\n const translations: GetTextTranslationRecord = { \"\": {} };\n const nplurals = locale ? getNPlurals(locale) : undefined;\n\n for (const { context, id, message, comments, obsolete, plural } of source) {\n const ctx = context || \"\";\n if (!translations[ctx]) {\n translations[ctx] = {};\n }\n\n const length = plural ? (nplurals ?? message.length) : 1;\n\n const existing = translations[ctx][id];\n const refs = new Set<string>();\n if (existing?.comments?.reference) {\n existing.comments.reference.split(/\\r?\\n|\\r/).forEach((r) => {\n refs.add(r);\n });\n }\n if (comments?.reference) {\n comments.reference.split(/\\r?\\n|\\r/).forEach((r) => {\n refs.add(r);\n });\n }\n\n const msgstr = existing?.msgstr ? existing.msgstr.slice(0, length) : Array.from({ length }, () => \"\");\n while (msgstr.length < length) msgstr.push(\"\");\n\n translations[ctx][id] = {\n msgctxt: context || undefined,\n msgid: id,\n msgid_plural: plural,\n msgstr,\n comments: {\n ...existing?.comments,\n ...comments,\n reference: refs.size ? Array.from(refs).join(\"\\n\") : undefined,\n },\n obsolete: existing?.obsolete ?? obsolete,\n };\n }\n\n return translations;\n}\n\nexport function hasChanges(left: GetTextTranslations, right?: GetTextTranslations): boolean {\n const ignoredKeys = new Set([\"pot-creation-date\", \"po-revision-date\"]);\n\n function deepEqual(left: unknown, right: unknown): boolean {\n if (left === right) {\n return true;\n }\n\n if (left == null || right == null) {\n return false;\n }\n\n if (typeof left !== typeof right) {\n return false;\n }\n\n if (Array.isArray(left)) {\n if (!Array.isArray(right) || left.length !== right.length) {\n return false;\n }\n\n return left.every((item, index) => deepEqual(item, right[index]));\n }\n\n if (typeof left === \"object\") {\n const keys1 = Object.keys(left).filter((key) => !ignoredKeys.has(key));\n const keys2 = Object.keys(right).filter((key) => !ignoredKeys.has(key));\n\n if (keys1.length !== keys2.length) {\n return false;\n }\n\n return keys1.every((key) => deepEqual(left[key as never], right[key as never]));\n }\n\n return false;\n }\n\n return !deepEqual(left, right);\n}\n\nexport function merge(\n sources: Collected[],\n existing: GetTextTranslations | undefined,\n obsolete: ObsoleteStrategy,\n locale: string,\n generatedAt: Date,\n): GetTextTranslations {\n let headers: Record<string, string> = {};\n let translations: GetTextTranslationRecord = { \"\": {} };\n let obsoleteTranslations: GetTextTranslationRecord = {};\n const nplurals = getNPlurals(locale);\n\n if (existing) {\n translations = existing.translations || { \"\": {} };\n obsoleteTranslations = existing.obsolete || {};\n for (const ctx of Object.keys(translations)) {\n for (const id of Object.keys(translations[ctx])) {\n if (ctx === \"\" && id === \"\") continue;\n translations[ctx][id].obsolete = true;\n }\n }\n }\n\n const collected: GetTextTranslationRecord = { \"\": {} };\n for (const { translations } of sources) {\n for (const [ctx, msgs] of Object.entries(translations)) {\n if (!collected[ctx]) collected[ctx] = {};\n for (const [id, entry] of Object.entries(msgs)) {\n const existing = collected[ctx][id];\n const refs = new Set<string>();\n if (existing?.comments?.reference) {\n existing.comments.reference.split(/\\r?\\n|\\r/).forEach((r) => {\n refs.add(r);\n });\n }\n if (entry.comments?.reference) {\n entry.comments.reference.split(/\\r?\\n|\\r/).forEach((r) => {\n refs.add(r);\n });\n }\n collected[ctx][id] = {\n ...existing,\n ...entry,\n comments: {\n ...existing?.comments,\n ...entry.comments,\n reference: refs.size ? Array.from(refs).join(\"\\n\") : undefined,\n },\n };\n }\n }\n }\n\n for (const [ctx, msgs] of Object.entries(collected)) {\n if (!translations[ctx]) translations[ctx] = {};\n for (const [id, entry] of Object.entries(msgs)) {\n const existingEntry = translations[ctx][id] ?? obsoleteTranslations[ctx]?.[id];\n if (existingEntry) {\n entry.msgstr = existingEntry.msgstr;\n entry.comments = {\n ...entry.comments,\n translator: existingEntry.comments?.translator,\n };\n }\n delete entry.obsolete;\n entry.msgstr = entry.msgstr.slice(0, nplurals);\n while (entry.msgstr.length < nplurals) {\n entry.msgstr.push(\"\");\n }\n translations[ctx][id] = entry;\n if (obsoleteTranslations[ctx]) {\n delete obsoleteTranslations[ctx][id];\n }\n }\n }\n\n for (const ctx of Object.keys(translations)) {\n for (const id of Object.keys(translations[ctx])) {\n if (ctx === \"\" && id === \"\") {\n continue;\n }\n const entry = translations[ctx][id];\n if (entry.obsolete) {\n if (!obsoleteTranslations[ctx]) {\n obsoleteTranslations[ctx] = {};\n }\n obsoleteTranslations[ctx][id] = entry;\n delete translations[ctx][id];\n }\n }\n }\n\n headers = {\n ...headers,\n \"content-type\": headers[\"content-type\"] || \"text/plain; charset=UTF-8\",\n \"plural-forms\": `nplurals=${nplurals}; plural=${getFormula(locale)};`,\n language: locale,\n \"pot-creation-date\": formatDate(generatedAt),\n \"x-generator\": \"@let-value/translate-extract\",\n };\n\n return {\n charset: \"utf-8\",\n headers,\n translations,\n ...(obsolete === \"mark\" && Object.keys(obsoleteTranslations).length ? { obsolete: obsoleteTranslations } : {}),\n };\n}\n\nconst namespace = \"translate\";\n\nexport function po(): Plugin {\n return {\n name: \"po\",\n setup(build) {\n build.context.logger?.debug(\"po plugin initialized\");\n const collections = new Map<\n string,\n {\n locale: string;\n translations: Translation[];\n }\n >();\n let dispatched = false;\n\n build.onResolve({ filter: /.*/, namespace }, async ({ entrypoint, path, data }) => {\n if (!data || !Array.isArray(data)) {\n return undefined;\n }\n\n for (const locale of build.context.config.locales) {\n const destination = build.context.config.destination({ entrypoint, locale, path });\n if (!collections.has(destination)) {\n collections.set(destination, { locale, translations: [] });\n }\n\n collections.get(destination)?.translations.push(...data);\n }\n\n Promise.all([build.defer(\"source\"), build.defer(namespace)]).then(() => {\n if (dispatched) {\n return;\n }\n dispatched = true;\n\n for (const path of collections.keys()) {\n build.load({ entrypoint, path, namespace });\n }\n });\n\n return undefined;\n });\n\n build.onLoad({ filter: /.*\\.po$/, namespace }, async ({ entrypoint, path }) => {\n const contents = await fs.readFile(path).catch(() => undefined);\n const data = contents ? gettextParser.po.parse(contents) : undefined;\n return {\n entrypoint,\n path,\n namespace,\n data,\n };\n });\n\n build.onProcess({ filter: /.*\\.po$/, namespace }, async ({ entrypoint, path, data }) => {\n const collected = collections.get(path);\n if (!collected) {\n build.context.logger?.warn({ path }, \"no translations collected for this path\");\n return undefined;\n }\n\n const { locale, translations } = collected;\n\n const record = collect(translations, locale);\n\n const out = merge(\n [{ translations: record }],\n data as never,\n build.context.config.obsolete,\n locale,\n build.context.generatedAt,\n );\n\n if (hasChanges(out, data as never)) {\n await fs.mkdir(dirname(path), { recursive: true });\n await fs.writeFile(path, gettextParser.po.compile(out));\n }\n\n build.resolve({\n entrypoint,\n path,\n namespace: \"cleanup\",\n data: translations,\n });\n });\n },\n };\n}\n","import { basename, dirname, extname, join } from \"node:path\";\nimport type { PluralFormsLocale } from \"@let-value/translate\";\nimport type { LogLevel } from \"./logger.ts\";\n\nimport type { Plugin } from \"./plugin.ts\";\nimport { cleanup } from \"./plugins/cleanup/cleanup.ts\";\nimport { core } from \"./plugins/core/core.ts\";\nimport { po } from \"./plugins/po/po.ts\";\n\nexport type DestinationFn = (args: { locale: string; entrypoint: string; path: string }) => string;\nexport type ExcludeFn = (args: { entrypoint: string; path: string }) => boolean;\nexport type Exclude = RegExp | ExcludeFn;\n\nconst defaultPlugins = { core, po, cleanup };\ntype DefaultPlugins = typeof defaultPlugins;\n\n/**\n * Strategy to handle obsolete translations in existing locale files:\n * - \"mark\": keep obsolete entries in the locale file but mark them as obsolete\n * - \"remove\": remove obsolete entries from the locale file\n */\nexport type ObsoleteStrategy = \"mark\" | \"remove\";\n\nexport interface EntrypointConfig {\n entrypoint: string;\n destination?: DestinationFn;\n obsolete?: ObsoleteStrategy;\n walk?: boolean;\n exclude?: Exclude | Exclude[];\n}\n\nexport interface UserConfig {\n /**\n * Default locale to use as the base for extraction\n * @default \"en\"\n * @see {@link PluralFormsLocale} for available locales\n */\n defaultLocale?: PluralFormsLocale;\n /**\n * Array of locales to extract translations for\n * @default [defaultLocale]\n * @see {@link PluralFormsLocale} for available locales\n */\n locales?: PluralFormsLocale[];\n /**\n * Array of plugins to use or a function to override the default plugins\n * @default DefaultPlugins\n * @see {@link DefaultPlugins} for available plugins\n */\n plugins?: Plugin[] | ((defaultPlugins: DefaultPlugins) => Plugin[]);\n /**\n * One or more entrypoints to extract translations from, could be:\n * - file path, will be treated as a single file entrypoint\n * - glob pattern will be expanded to match files, each treated as a separate entrypoint\n * - configuration object with options for the entrypoint\n * @see {@link EntrypointConfig} for configuration options\n */\n entrypoints: string | EntrypointConfig | Array<string | EntrypointConfig>;\n /**\n * Function to determine the destination path for each extracted locale file\n * @default `./translations/entrypoint.locale.po`\n * @see {@link DestinationFn}\n * @see Can be overridden per entrypoint via `destination` in {@link EntrypointConfig\n */\n destination?: DestinationFn;\n /**\n * Strategy to handle obsolete translations in existing locale files\n * @default \"mark\"\n * @see {@link ObsoleteStrategy} for available strategies\n * @see Can be overridden per entrypoint via `obsolete` in {@link EntrypointConfig\n */\n obsolete?: ObsoleteStrategy;\n /**\n * Whether to recursively walk dependencies of the entrypoints\n * @default true\n * @see Can be overridden per entrypoint via `walk` in {@link EntrypointConfig}.\n */\n walk?: boolean;\n /**\n * Paths or patterns to exclude from extraction, applied to all entrypoints\n * @default [/node_modules/, /dist/, /build/]\n * @see Can be overridden per entrypoint via `exclude` in {@link EntrypointConfig}.\n */\n exclude?: Exclude | Exclude[];\n /**\n * Log level for the extraction process\n * @default \"info\"\n */\n logLevel?: LogLevel;\n}\n\nexport interface ResolvedEntrypoint extends Omit<EntrypointConfig, \"exclude\"> {\n exclude?: Exclude[];\n}\n\nexport interface ResolvedConfig {\n plugins: Plugin[];\n entrypoints: ResolvedEntrypoint[];\n defaultLocale: string;\n locales: string[];\n destination: DestinationFn;\n obsolete: ObsoleteStrategy;\n walk: boolean;\n logLevel: LogLevel;\n exclude: Exclude[];\n}\n\nconst defaultDestination: DestinationFn = ({ entrypoint, locale }) =>\n join(dirname(entrypoint), \"translations\", `${basename(entrypoint, extname(entrypoint))}.${locale}.po`);\n\nconst defaultExclude: Exclude[] = [\n /(?:^|[\\\\/])node_modules(?:[\\\\/]|$)/,\n /(?:^|[\\\\/])dist(?:[\\\\/]|$)/,\n /(?:^|[\\\\/])build(?:[\\\\/]|$)/,\n];\n\nfunction normalizeExclude(exclude?: Exclude | Exclude[]): Exclude[] {\n if (!exclude) return [];\n return Array.isArray(exclude) ? exclude : [exclude];\n}\n\nfunction resolveEntrypoint(ep: string | EntrypointConfig): ResolvedEntrypoint {\n if (typeof ep === \"string\") {\n return { entrypoint: ep };\n }\n const { entrypoint, destination, obsolete, walk, exclude } = ep;\n return { entrypoint, destination, obsolete, walk, exclude: exclude ? normalizeExclude(exclude) : undefined };\n}\n\nfunction resolvePlugins(user?: UserConfig[\"plugins\"]): Plugin[] {\n if (typeof user === \"function\") {\n return user(defaultPlugins);\n }\n if (Array.isArray(user)) {\n return [...Object.values(defaultPlugins).map((plugin) => plugin()), ...user];\n }\n return Object.values(defaultPlugins).map((plugin) => plugin());\n}\n\n/**\n * Type helper to make it easier to use translate.config.ts\n * @param config - {@link UserConfig}.\n */\nexport function defineConfig(config: UserConfig): ResolvedConfig {\n const defaultLocale = config.defaultLocale ?? \"en\";\n\n const plugins = resolvePlugins(config.plugins);\n\n const raw = Array.isArray(config.entrypoints) ? config.entrypoints : [config.entrypoints];\n const entrypoints = raw.map(resolveEntrypoint);\n\n return {\n plugins,\n entrypoints,\n defaultLocale,\n locales: config.locales ?? [defaultLocale],\n destination: config.destination ?? defaultDestination,\n obsolete: config.obsolete ?? \"mark\",\n walk: config.walk ?? true,\n logLevel: config.logLevel ?? \"info\",\n exclude: config.exclude ? normalizeExclude(config.exclude) : defaultExclude,\n };\n}\n","import type Parser from \"tree-sitter\";\n\nexport function buildTemplate(node: Parser.SyntaxNode): { text: string; error?: string } {\n const source = node.tree.rootNode.text;\n const open = node.childForFieldName(\"open_tag\");\n const close = node.childForFieldName(\"close_tag\");\n const contentStart = open?.endIndex ?? node.startIndex;\n const contentEnd = close?.startIndex ?? node.endIndex;\n\n type Part = { kind: \"text\"; text: string; raw: boolean } | { kind: \"expr\"; value: string };\n\n const parts: Part[] = [];\n let segmentStart = contentStart;\n\n const pushRawText = (endIndex: number) => {\n if (endIndex <= segmentStart) {\n segmentStart = Math.max(segmentStart, endIndex);\n return;\n }\n const text = source.slice(segmentStart, endIndex);\n if (text) {\n parts.push({ kind: \"text\", text, raw: true });\n }\n segmentStart = endIndex;\n };\n\n const children = node.namedChildren.slice(1, -1);\n for (const child of children) {\n if (child.type === \"jsx_expression\") {\n pushRawText(child.startIndex);\n const expr = child.namedChildren[0];\n if (!expr) {\n return { text: \"\", error: \"Empty JSX expression\" };\n }\n\n if (expr.type === \"identifier\") {\n parts.push({ kind: \"expr\", value: expr.text });\n } else if (expr.type === \"string\") {\n parts.push({ kind: \"text\", text: expr.text.slice(1, -1), raw: false });\n } else if (expr.type === \"template_string\") {\n const hasSubstitutions = expr.children.some((c) => c.type === \"template_substitution\");\n if (hasSubstitutions) {\n return { text: \"\", error: \"JSX expressions with template substitutions are not supported\" };\n }\n parts.push({ kind: \"text\", text: expr.text.slice(1, -1), raw: false });\n } else {\n return { text: \"\", error: \"JSX expressions must be simple identifiers, strings, or template literals\" };\n }\n segmentStart = child.endIndex;\n } else if (child.type === \"string\") {\n pushRawText(child.startIndex);\n parts.push({ kind: \"text\", text: child.text.slice(1, -1), raw: false });\n segmentStart = child.endIndex;\n } else if (child.type === \"jsx_text\" || child.type === \"html_character_reference\" || child.isError) {\n } else {\n return { text: \"\", error: \"Unsupported JSX child\" };\n }\n }\n\n pushRawText(contentEnd);\n\n const firstRawIndex = parts.findIndex((part) => part.kind === \"text\" && part.raw);\n if (firstRawIndex === 0) {\n const part = parts[firstRawIndex] as Extract<Part, { kind: \"text\" }>;\n part.text = part.text.replace(/^\\s+/, \"\");\n }\n\n let lastRawIndex = -1;\n for (let i = parts.length - 1; i >= 0; i--) {\n const part = parts[i];\n if (part.kind === \"text\" && part.raw) {\n lastRawIndex = i;\n break;\n }\n }\n if (lastRawIndex !== -1 && lastRawIndex === parts.length - 1) {\n const part = parts[lastRawIndex] as Extract<Part, { kind: \"text\" }>;\n part.text = part.text.replace(/\\s+$/, \"\");\n }\n\n const strings: string[] = [\"\"];\n const values: string[] = [];\n for (const part of parts) {\n if (part.kind === \"text\") {\n if (part.text) {\n strings[strings.length - 1] += part.text;\n }\n } else {\n values.push(part.value);\n strings.push(\"\");\n }\n }\n\n let text = \"\";\n for (let i = 0; i < strings.length; i++) {\n text += strings[i];\n if (values[i]) {\n text += `\\${${values[i]}}`;\n }\n }\n return { text };\n}\n\nexport function buildAttrValue(node: Parser.SyntaxNode): { text: string; error?: string } {\n if (node.type === \"string\") {\n return { text: node.text.slice(1, -1) };\n }\n if (node.type === \"jsx_expression\") {\n const expr = node.namedChildren[0];\n if (!expr) {\n return { text: \"\", error: \"Empty JSX expression\" };\n }\n\n if (expr.type === \"identifier\") {\n return { text: `\\${${expr.text}}` };\n } else if (expr.type === \"string\") {\n return { text: expr.text.slice(1, -1) };\n } else if (expr.type === \"template_string\") {\n // Check if it's a simple template string with no substitutions\n const hasSubstitutions = expr.children.some((c) => c.type === \"template_substitution\");\n if (hasSubstitutions) {\n return { text: \"\", error: \"JSX expressions with template substitutions are not supported\" };\n }\n // Extract the text content from the template string\n const content = expr.text.slice(1, -1); // Remove backticks\n return { text: content };\n } else {\n return { text: \"\", error: \"JSX expressions must be simple identifiers, strings, or template literals\" };\n }\n }\n return { text: \"\", error: \"Unsupported JSX child\" };\n}\n","import type Parser from \"tree-sitter\";\n\nimport { withComment } from \"../../core/queries/comment.ts\";\nimport type { MessageMatch, QuerySpec, Translation } from \"../../core/queries/types.ts\";\nimport { buildAttrValue, buildTemplate } from \"./utils.ts\";\n\nexport const messageQuery: QuerySpec = withComment({\n pattern: `(\n [\n (jsx_element (jsx_opening_element name: (identifier) @name)) @call\n (jsx_self_closing_element name: (identifier) @name) @call\n (lexical_declaration \n (variable_declarator \n value: [\n (jsx_element (jsx_opening_element name: (identifier) @name)) @call\n (jsx_self_closing_element name: (identifier) @name) @call\n ]\n )\n )\n ]\n (#eq? @name \"Message\")\n )`,\n extract(match: Parser.QueryMatch): MessageMatch | undefined {\n const node = match.captures.find((c) => c.name === \"call\")?.node;\n if (!node) return undefined;\n let attrs: Parser.SyntaxNode[] = [];\n if (node.type === \"jsx_element\") {\n const open = node.childForFieldName(\"open_tag\");\n if (open) attrs = open.namedChildren;\n } else if (node.type === \"jsx_self_closing_element\") {\n attrs = node.namedChildren.slice(1);\n }\n let msgctxt: string | undefined;\n let childValue: Parser.SyntaxNode | undefined;\n for (const child of attrs) {\n if (child.type !== \"jsx_attribute\") continue;\n const name = child.child(0);\n const value = child.child(child.childCount - 1);\n if (name?.text === \"context\" && value?.type === \"string\") {\n msgctxt = value.text.slice(1, -1);\n } else if (name?.text === \"children\" && value) {\n childValue = value;\n }\n }\n let text = \"\";\n let error: string | undefined;\n if (node.type === \"jsx_element\") {\n ({ text, error } = buildTemplate(node));\n } else if (childValue) {\n ({ text, error } = buildAttrValue(childValue));\n }\n if (error) {\n return { node, error };\n }\n if (!text) return undefined;\n const translation: Translation = {\n id: text,\n message: [text],\n };\n if (msgctxt) translation.context = msgctxt;\n return { node, translation };\n },\n});\n","import type Parser from \"tree-sitter\";\n\nimport { withComment } from \"../../core/queries/comment.ts\";\nimport type { MessageMatch, QuerySpec, Translation } from \"../../core/queries/types.ts\";\nimport { buildTemplate } from \"./utils.ts\";\n\nfunction parseForms(node: Parser.SyntaxNode): { forms: string[]; error?: string } {\n const forms: string[] = [];\n if (node.type === \"jsx_expression\") {\n const arr = node.namedChildren[0];\n if (!arr || arr.type !== \"array\") {\n return { forms: [], error: \"Plural forms must be an array\" };\n }\n for (const el of arr.namedChildren) {\n if (el.type === \"jsx_element\" || el.type === \"jsx_fragment\") {\n const { text, error } = buildTemplate(el);\n if (error) return { forms: [], error };\n forms.push(text);\n } else if (el.type === \"string\") {\n forms.push(el.text.slice(1, -1));\n } else {\n return { forms: [], error: \"Unsupported plural form\" };\n }\n }\n }\n return { forms };\n}\n\nexport const pluralQuery: QuerySpec = withComment({\n pattern: `(\n [\n (jsx_element (jsx_opening_element name: (identifier) @name))\n (jsx_self_closing_element name: (identifier) @name)\n ] @call\n (#eq? @name \"Plural\")\n )`,\n extract(match: Parser.QueryMatch): MessageMatch | undefined {\n const node = match.captures.find((c) => c.name === \"call\")?.node;\n if (!node) return undefined;\n let attrs: Parser.SyntaxNode[] = [];\n if (node.type === \"jsx_element\") {\n const open = node.childForFieldName(\"open_tag\");\n if (open) attrs = open.namedChildren;\n } else if (node.type === \"jsx_self_closing_element\") {\n attrs = node.namedChildren.slice(1);\n }\n let msgctxt: string | undefined;\n let formsNode: Parser.SyntaxNode | null | undefined;\n for (const child of attrs) {\n if (child.type !== \"jsx_attribute\") continue;\n const name = child.child(0);\n const value = child.child(child.childCount - 1);\n if (name?.text === \"context\" && value?.type === \"string\") {\n msgctxt = value.text.slice(1, -1);\n } else if (name?.text === \"forms\" && value) {\n formsNode = value;\n }\n }\n if (!formsNode) return undefined;\n const { forms, error } = parseForms(formsNode);\n if (error) {\n return { node, error };\n }\n if (forms.length === 0) return undefined;\n const translation: Translation = {\n id: forms[0],\n plural: forms[1],\n message: forms,\n };\n if (msgctxt) translation.context = msgctxt;\n return { node, translation };\n },\n});\n","import type { QuerySpec } from \"../../core/queries/types.ts\";\nimport { messageQuery } from \"./message.ts\";\nimport { pluralQuery } from \"./plural.ts\";\n\nexport const queries: QuerySpec[] = [messageQuery, pluralQuery];\n","import fs from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { getParser, getQuery } from \"../core/parse.ts\";\nimport { getReference } from \"../core/queries/comment.ts\";\n\nimport type { Context, Translation, Warning } from \"../core/queries/types.ts\";\nimport { queries } from \"./queries/index.ts\";\n\nexport interface ParseResult {\n translations: Translation[];\n warnings: Warning[];\n}\n\nexport function parseFile(filePath: string): ParseResult {\n const path = resolve(filePath);\n const source = fs.readFileSync(path, \"utf8\");\n return parseSource(source, path);\n}\n\nexport function parseSource(source: string, path: string): ParseResult {\n const context: Context = { path };\n const { parser, language } = getParser(path);\n const tree = parser.parse(source);\n\n const translations: Translation[] = [];\n const warnings: Warning[] = [];\n const seen = new Set<number>();\n\n for (const spec of queries) {\n const query = getQuery(language, spec.pattern);\n for (const match of query.matches(tree.rootNode)) {\n const message = spec.extract(match);\n if (!message) continue;\n const { node, translation, error } = message;\n if (seen.has(node.id)) continue;\n seen.add(node.id);\n const reference = getReference(node, context);\n if (translation) {\n translations.push({\n ...translation,\n comments: {\n ...translation.comments,\n reference,\n },\n });\n }\n if (error) {\n warnings.push({\n error,\n reference,\n });\n }\n }\n }\n\n return { translations, warnings };\n}\n","import { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nimport type { Plugin } from \"../../plugin.ts\";\nimport type { Translation } from \"../core/queries/types.ts\";\nimport { parseSource } from \"./parse.ts\";\n\nconst filter = /\\.[cm]?[jt]sx$/;\n\nexport function react(): Plugin<string, Translation[]> {\n return {\n name: \"react\",\n setup(build) {\n build.context.logger?.debug(\"react plugin initialized\");\n build.onResolve({ filter: /.*/, namespace: \"source\" }, ({ entrypoint, path, namespace }) => {\n return {\n entrypoint,\n namespace,\n path: resolve(path),\n };\n });\n build.onLoad({ filter, namespace: \"source\" }, async ({ entrypoint, path, namespace }) => {\n const data = await readFile(path, \"utf8\");\n return {\n entrypoint,\n path,\n namespace,\n data,\n };\n });\n build.onProcess({ filter, namespace: \"source\" }, ({ entrypoint, path, data }) => {\n const { translations, warnings } = parseSource(data, path);\n\n for (const warning of warnings) {\n build.context.logger?.warn(`${warning.error} at ${warning.reference}`);\n }\n\n build.resolve({\n entrypoint,\n path,\n namespace: \"translate\",\n data: translations,\n });\n\n return undefined;\n });\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["namespace","path","path","importQuery: ImportQuerySpec","current: Parser.SyntaxNode | null","messageQuery: QuerySpec","allowed","messageInvalidQuery: QuerySpec","ids: string[]","strs: string[]","subMatch: Parser.QueryMatch","translation: Translation","contextMsgQuery: QuerySpec","msgCall","contextPluralQuery: QuerySpec","contextInvalidQuery: QuerySpec","gettextQuery: QuerySpec","gettextInvalidQuery: QuerySpec","msgCall","plainMsg","msgArg","ngettextQuery: QuerySpec","msgCall","npgettextQuery: QuerySpec","pgettextQuery: QuerySpec","pluralQuery: QuerySpec","queries: QuerySpec[]","messageQuery","pluralQuery","path","parseSource","context: Context","translations: Translation[]","warnings: Warning[]","imports: string[]","queries","fs","resolved: string[]","filter","namespace","path","parseSource","translations: GetTextTranslationRecord","value","normalizedHeaders: Record<string, string>","headers: Record<string, string>","translations: GetTextTranslationRecord","obsoleteTranslations: GetTextTranslationRecord","collected: GetTextTranslationRecord","translations","existing","path","defaultDestination: DestinationFn","defaultExclude: Exclude[]","parts: Part[]","text","strings: string[]","values: string[]","messageQuery: QuerySpec","attrs: Parser.SyntaxNode[]","msgctxt: string | undefined","childValue: Parser.SyntaxNode | undefined","error: string | undefined","translation: Translation","forms: string[]","pluralQuery: QuerySpec","attrs: Parser.SyntaxNode[]","msgctxt: string | undefined","formsNode: Parser.SyntaxNode | null | undefined","translation: Translation","queries: QuerySpec[]","context: Context","path","translations: Translation[]","warnings: Warning[]","path"],"sources":["../../src/plugins/cleanup/cleanup.ts","../../src/plugins/core/queries/comment.ts","../../src/plugins/core/queries/import.ts","../../src/plugins/core/queries/utils.ts","../../src/plugins/core/queries/message.ts","../../src/plugins/core/queries/plural-utils.ts","../../src/plugins/core/queries/context.ts","../../src/plugins/core/queries/gettext.ts","../../src/plugins/core/queries/ngettext.ts","../../src/plugins/core/queries/npgettext.ts","../../src/plugins/core/queries/pgettext.ts","../../src/plugins/core/queries/plural.ts","../../src/plugins/core/queries/index.ts","../../src/plugins/core/parse.ts","../../src/plugins/core/resolve.ts","../../src/plugins/core/core.ts","../../src/plugins/po/collect.ts","../../src/plugins/po/hasChanges.ts","../../src/plugins/po/merge.ts","../../src/plugins/po/po.ts","../../src/configuration.ts","../../src/plugins/react/queries/utils.ts","../../src/plugins/react/queries/message.ts","../../src/plugins/react/queries/plural.ts","../../src/plugins/react/queries/index.ts","../../src/plugins/react/parse.ts","../../src/plugins/react/react.ts"],"sourcesContent":["import fs from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport * as gettextParser from \"gettext-parser\";\n\nimport type { Plugin } from \"../../plugin.ts\";\n\nconst namespace = \"cleanup\";\n\nexport function cleanup(): Plugin {\n return {\n name: \"cleanup\",\n setup(build) {\n build.context.logger?.debug(\"cleanup plugin initialized\");\n const processed = new Set<string>();\n const generated = new Set<string>();\n const dirs = new Set<string>();\n let dispatched = false;\n\n build.onResolve({ namespace, filter: /.*/ }, ({ path }) => {\n generated.add(path);\n dirs.add(dirname(path));\n\n Promise.all([build.defer(\"source\"), build.defer(\"translate\"), build.defer(namespace)]).then(() => {\n if (dispatched) {\n return;\n }\n dispatched = true;\n\n for (const path of dirs.values()) {\n build.process({ entrypoint: path, path, namespace, data: undefined });\n }\n });\n\n return undefined;\n });\n\n build.onProcess({ namespace, filter: /.*/ }, async ({ path }) => {\n if (processed.has(path)) {\n return undefined;\n }\n processed.add(path);\n const files = await fs.readdir(path).catch(() => []);\n for (const f of files.filter((p) => p.endsWith(\".po\"))) {\n const full = join(path, f);\n const contents = await fs.readFile(full).catch(() => undefined);\n if (!contents) {\n continue;\n }\n const parsed = gettextParser.po.parse(contents);\n const hasTranslations = Object.entries(parsed.translations || {}).some(([ctx, msgs]) =>\n Object.keys(msgs).some((id) => !(ctx === \"\" && id === \"\")),\n );\n if (!hasTranslations && generated.has(full)) {\n await fs.unlink(full);\n }\n if (hasTranslations && !generated.has(full)) {\n build.context.logger?.warn({ path: full }, \"stray translation file\");\n }\n }\n return undefined;\n });\n },\n };\n}\n","import { relative } from \"node:path\";\nimport type Parser from \"tree-sitter\";\n\nimport type { Context, QuerySpec } from \"./types.ts\";\n\nexport function getReference(node: Parser.SyntaxNode, { path }: Context) {\n const line = node.startPosition.row + 1;\n const rel = relative(process.cwd(), path).replace(/\\\\+/g, \"/\");\n return `${rel}:${line}`;\n}\n\nfunction getComment(node: Parser.SyntaxNode): string {\n const text = node.text;\n if (text.startsWith(\"/*\")) {\n return text\n .slice(2, -2)\n .replace(/^\\s*\\*?\\s*/gm, \"\")\n .trim();\n }\n return text.replace(/^\\/\\/\\s?/, \"\").trim();\n}\n\nexport const withComment = (query: QuerySpec): QuerySpec => ({\n pattern: `(\n\t((comment) @comment)?\n .\n\t(_ ${query.pattern})\n)`,\n extract(match) {\n const result = query.extract(match);\n if (!result?.translation) {\n return result;\n }\n\n const comment = match.captures.find((c) => c.name === \"comment\")?.node;\n if (!comment) {\n return result;\n }\n\n if (comment) {\n result.translation.comments = {\n ...result.translation.comments,\n extracted: getComment(comment),\n };\n }\n\n return result;\n },\n});\n","import type Parser from \"tree-sitter\";\nimport type { ImportQuerySpec } from \"./types.ts\";\n\nexport const importQuery: ImportQuerySpec = {\n pattern: `\n [\n (import_statement\n source: (string (string_fragment) @import))\n (export_statement\n source: (string (string_fragment) @import))\n (call_expression\n function: (identifier) @func\n arguments: (arguments (string (string_fragment) @import))\n (#eq? @func \"require\"))\n (call_expression\n function: (member_expression\n object: (identifier) @obj\n property: (property_identifier) @method)\n arguments: (arguments (string (string_fragment) @import))\n (#eq? @obj \"require\")\n (#eq? @method \"resolve\"))\n (call_expression\n function: (import)\n arguments: (arguments (string (string_fragment) @import)))\n ]\n `,\n extract(match: Parser.QueryMatch): string | undefined {\n const node = match.captures.find((c) => c.name === \"import\")?.node;\n return node?.text;\n },\n};\n","import type Parser from \"tree-sitter\";\n\nexport const callPattern = (fnName: string, args: string, allowMember = true): string => `(\n (call_expression\n function: ${\n allowMember\n ? `[\n (identifier) @func\n (member_expression property: (property_identifier) @func)\n ]`\n : `(identifier) @func`\n }\n arguments: ${args}\n ) @call\n (#eq? @func \"${fnName}\")\n)`;\n\nexport function isDescendant(node: Parser.SyntaxNode, ancestor: Parser.SyntaxNode): boolean {\n let current: Parser.SyntaxNode | null = node;\n while (current) {\n if (current.id === ancestor.id) return true;\n current = current.parent;\n }\n return false;\n}\n","import type Parser from \"tree-sitter\";\nimport { withComment } from \"./comment.ts\";\nimport type { MessageMatch, QuerySpec } from \"./types.ts\";\nimport { callPattern } from \"./utils.ts\";\n\nconst notInPlural = (query: QuerySpec): QuerySpec => ({\n pattern: query.pattern,\n extract(match) {\n const result = query.extract(match);\n if (!result?.node) {\n return result;\n }\n\n let parent = result.node.parent;\n\n if (parent && parent.type === \"arguments\") {\n parent = parent.parent;\n }\n\n if (parent && parent.type === \"call_expression\") {\n const fn = parent.childForFieldName(\"function\");\n if (fn) {\n if (\n (fn.type === \"identifier\" &&\n (fn.text === \"plural\" ||\n fn.text === \"ngettext\" ||\n fn.text === \"pgettext\" ||\n fn.text === \"npgettext\")) ||\n (fn.type === \"member_expression\" &&\n [\"plural\", \"ngettext\", \"pgettext\", \"npgettext\"].includes(\n fn.childForFieldName(\"property\")?.text ?? \"\",\n ))\n ) {\n return undefined;\n }\n }\n }\n\n return result;\n },\n});\n\nexport const messageArg = `[\n (string (string_fragment) @msgid)\n (object\n (_)*\n (pair\n key: (property_identifier) @id_key\n value: (string (string_fragment) @id)\n (#eq? @id_key \"id\")\n )?\n (_)*\n (pair\n key: (property_identifier) @msg_key\n value: (string (string_fragment) @message)\n (#eq? @msg_key \"message\")\n )?\n (_)*\n )\n (template_string) @tpl\n]`;\n\nexport const messageArgs = `[ (arguments ${messageArg}) (template_string) @tpl ]`;\n\nexport const extractMessage =\n (name: string) =>\n (match: Parser.QueryMatch): MessageMatch | undefined => {\n const node = match.captures.find((c) => c.name === \"call\")?.node;\n if (!node) {\n return undefined;\n }\n\n const msgid = match.captures.find((c) => c.name === \"msgid\")?.node.text;\n if (msgid) {\n return {\n node,\n translation: {\n id: msgid,\n message: [msgid],\n },\n };\n }\n\n const tpl = match.captures.find((c) => c.name === \"tpl\")?.node;\n if (tpl) {\n for (const child of tpl.children) {\n if (child.type !== \"template_substitution\") {\n continue;\n }\n\n const expr = child.namedChildren[0];\n if (!expr || expr.type !== \"identifier\") {\n return {\n node,\n error: `${name}() template expressions must be simple identifiers`,\n };\n }\n }\n\n const text = tpl.text.slice(1, -1);\n\n return {\n node,\n translation: { id: text, message: [text] },\n };\n }\n\n const id = match.captures.find((c) => c.name === \"id\")?.node.text;\n const message = match.captures.find((c) => c.name === \"message\")?.node.text;\n const msgId = id ?? message;\n if (!msgId) {\n return undefined;\n }\n\n const msgstr = message ?? id ?? \"\";\n\n return {\n node,\n translation: {\n id: msgId,\n message: [msgstr],\n },\n };\n };\n\nexport const messageQuery: QuerySpec = notInPlural(\n withComment({\n pattern: callPattern(\"message\", messageArgs),\n extract: extractMessage(\"message\"),\n }),\n);\n\nconst allowed = new Set([\"string\", \"object\", \"template_string\"]);\n\nexport const messageInvalidQuery: QuerySpec = notInPlural({\n pattern: callPattern(\"message\", \"(arguments (_) @arg)\"),\n extract(match) {\n const call = match.captures.find((c) => c.name === \"call\")?.node;\n const node = match.captures.find((c) => c.name === \"arg\")?.node;\n\n if (!call || !node) {\n return undefined;\n }\n\n if (allowed.has(node.type)) {\n return undefined;\n }\n\n return {\n node,\n error: \"message() argument must be a string literal, object literal, or template literal\",\n };\n },\n});\n","import type Parser from \"tree-sitter\";\nimport { extractMessage } from \"./message.ts\";\nimport type { MessageMatch, Translation } from \"./types.ts\";\nimport { isDescendant } from \"./utils.ts\";\n\nexport const extractPluralForms =\n (name: string) =>\n (match: Parser.QueryMatch): MessageMatch | undefined => {\n const call = match.captures.find((c) => c.name === \"call\")?.node;\n const n = match.captures.find((c) => c.name === \"n\")?.node;\n if (!call || !n || n.nextNamedSibling) {\n return undefined;\n }\n\n const msgctxt = match.captures.find((c) => c.name === \"msgctxt\")?.node?.text;\n const msgNodes = match.captures.filter((c) => c.name === \"msg\").map((c) => c.node);\n\n const ids: string[] = [];\n const strs: string[] = [];\n\n for (const node of msgNodes) {\n const relevant = match.captures.filter(\n (c) => [\"msgid\", \"id\", \"message\", \"tpl\"].includes(c.name) && isDescendant(c.node, node),\n );\n\n const subMatch: Parser.QueryMatch = {\n pattern: 0,\n captures: [{ name: \"call\", node }, ...relevant],\n };\n\n const result = extractMessage(name)(subMatch);\n if (!result) continue;\n if (result.error) {\n return { node: call, error: result.error };\n }\n if (result.translation) {\n ids.push(result.translation.id);\n strs.push(result.translation.message[0] ?? \"\");\n }\n }\n\n if (ids.length === 0) {\n return undefined;\n }\n\n const translation: Translation = {\n id: ids[0],\n plural: ids[1],\n message: strs,\n };\n if (msgctxt) translation.context = msgctxt;\n\n return { node: call, translation };\n };\n","import { withComment } from \"./comment.ts\";\nimport { extractMessage, messageArgs } from \"./message.ts\";\nimport { extractPluralForms } from \"./plural-utils.ts\";\nimport type { QuerySpec } from \"./types.ts\";\nimport { callPattern } from \"./utils.ts\";\n\nconst ctxCall = callPattern(\"context\", `(arguments (string (string_fragment) @msgctxt))`)\n .replace(/@call/g, \"@ctx\")\n .replace(/@func/g, \"@ctxfn\");\n\nexport const contextMsgQuery: QuerySpec = withComment({\n pattern: `(\n (call_expression\n function: (member_expression\n object: ${ctxCall}\n property: (property_identifier) @func\n )\n arguments: ${messageArgs}\n ) @call\n (#eq? @func \"message\")\n)`,\n extract(match) {\n const result = extractMessage(\"context.message\")(match);\n const contextNode = match.captures.find((c) => c.name === \"msgctxt\")?.node;\n if (!result || !result.translation || !contextNode) {\n return result;\n }\n return {\n node: result.node,\n translation: {\n ...result.translation,\n context: contextNode.text,\n },\n };\n },\n});\n\nconst msgCall = callPattern(\"message\", messageArgs, false).replace(/@call/g, \"@msg\").replace(/@func/g, \"@msgfn\");\n\nexport const contextPluralQuery: QuerySpec = withComment({\n pattern: `(\n (call_expression\n function: (member_expression\n object: ${ctxCall}\n property: (property_identifier) @func\n )\n arguments: (arguments (\n (${msgCall} (\",\" )?)+\n (number) @n\n ))\n ) @call\n (#eq? @func \"plural\")\n)`,\n extract: extractPluralForms(\"context.plural\"),\n});\n\nexport const contextInvalidQuery: QuerySpec = withComment({\n pattern: ctxCall,\n extract(match) {\n const call = match.captures.find((c) => c.name === \"ctx\")?.node;\n if (!call) {\n return undefined;\n }\n\n const parent = call.parent;\n if (parent && parent.type === \"member_expression\" && parent.childForFieldName(\"object\")?.id === call.id) {\n const property = parent.childForFieldName(\"property\")?.text;\n const grandparent = parent.parent;\n if (\n grandparent &&\n grandparent.type === \"call_expression\" &&\n grandparent.childForFieldName(\"function\")?.id === parent.id &&\n (property === \"message\" || property === \"plural\")\n ) {\n return undefined;\n }\n }\n\n return {\n node: call,\n error: \"context() must be used with message() or plural() in the same expression\",\n };\n },\n});\n","import { withComment } from \"./comment.ts\";\nimport { extractMessage, messageArgs } from \"./message.ts\";\nimport type { QuerySpec } from \"./types.ts\";\nimport { callPattern } from \"./utils.ts\";\n\nexport const gettextQuery: QuerySpec = withComment({\n pattern: callPattern(\"gettext\", messageArgs),\n extract: extractMessage(\"gettext\"),\n});\n\nconst allowed = new Set([\"string\", \"object\", \"template_string\", \"identifier\", \"call_expression\"]);\n\nexport const gettextInvalidQuery: QuerySpec = {\n pattern: callPattern(\"gettext\", \"(arguments (_) @arg)\"),\n extract(match) {\n const call = match.captures.find((c) => c.name === \"call\")?.node;\n const node = match.captures.find((c) => c.name === \"arg\")?.node;\n\n if (!call || !node) {\n return undefined;\n }\n\n if (allowed.has(node.type)) {\n return undefined;\n }\n\n return {\n node,\n error: \"gettext() argument must be a string literal, object literal, or template literal\",\n };\n },\n};\n","import { withComment } from \"./comment.ts\";\nimport { messageArg, messageArgs } from \"./message.ts\";\nimport { extractPluralForms } from \"./plural-utils.ts\";\nimport type { QuerySpec } from \"./types.ts\";\nimport { callPattern } from \"./utils.ts\";\n\nconst msgCall = callPattern(\"message\", messageArgs).replace(/@call/g, \"@msg\").replace(/@func/g, \"@msgfn\");\nconst plainMsg = `(${messageArg}) @msg`;\nconst msgArg = `[${msgCall} ${plainMsg}]`;\n\nexport const ngettextQuery: QuerySpec = withComment({\n pattern: callPattern(\"ngettext\", `(arguments ${msgArg} \",\" ${msgArg} (\",\" ${msgArg})* \",\" (_) @n)`),\n extract: extractPluralForms(\"ngettext\"),\n});\n","import { withComment } from \"./comment.ts\";\nimport { messageArg, messageArgs } from \"./message.ts\";\nimport { extractPluralForms } from \"./plural-utils.ts\";\nimport type { QuerySpec } from \"./types.ts\";\nimport { callPattern } from \"./utils.ts\";\n\nconst msgCall = callPattern(\"message\", messageArgs).replace(/@call/g, \"@msg\").replace(/@func/g, \"@msgfn\");\nconst plainMsg = `(${messageArg}) @msg`;\nconst msgArg = `[${msgCall} ${plainMsg}]`;\n\nexport const npgettextQuery: QuerySpec = withComment({\n pattern: callPattern(\n \"npgettext\",\n `(arguments (string (string_fragment) @msgctxt) \",\" ${msgArg} \",\" ${msgArg} (\",\" ${msgArg})* \",\" (_) @n)`,\n ),\n extract: extractPluralForms(\"npgettext\"),\n});\n","import { withComment } from \"./comment.ts\";\nimport { extractMessage, messageArg } from \"./message.ts\";\nimport type { QuerySpec } from \"./types.ts\";\nimport { callPattern } from \"./utils.ts\";\n\nexport const pgettextQuery: QuerySpec = withComment({\n pattern: callPattern(\"pgettext\", `(arguments (string (string_fragment) @msgctxt) \",\" ${messageArg})`),\n extract(match) {\n const result = extractMessage(\"pgettext\")(match);\n const contextNode = match.captures.find((c) => c.name === \"msgctxt\")?.node;\n if (!result || !contextNode || !result.translation) {\n return result;\n }\n return {\n node: result.node,\n translation: {\n ...result.translation,\n context: contextNode.text,\n },\n };\n },\n});\n","import { withComment } from \"./comment.ts\";\nimport { messageArgs } from \"./message.ts\";\nimport { extractPluralForms } from \"./plural-utils.ts\";\nimport type { QuerySpec } from \"./types.ts\";\nimport { callPattern } from \"./utils.ts\";\n\nconst msgCall = callPattern(\"message\", messageArgs, false).replace(/@call/g, \"@msg\").replace(/@func/g, \"@msgfn\");\n\nexport const pluralQuery: QuerySpec = withComment({\n pattern: callPattern(\n \"plural\",\n `(arguments (\n (${msgCall} (\",\" )?)+\n (number) @n\n ))`,\n false,\n ),\n extract: extractPluralForms(\"plural\"),\n});\n","import { contextInvalidQuery, contextMsgQuery, contextPluralQuery } from \"./context.ts\";\nimport { gettextInvalidQuery, gettextQuery } from \"./gettext.ts\";\nimport { messageInvalidQuery, messageQuery } from \"./message.ts\";\nimport { ngettextQuery } from \"./ngettext.ts\";\nimport { npgettextQuery } from \"./npgettext.ts\";\nimport { pgettextQuery } from \"./pgettext.ts\";\nimport { pluralQuery } from \"./plural.ts\";\nimport type { QuerySpec } from \"./types.ts\";\n\nexport type { MessageMatch, QuerySpec } from \"./types.ts\";\n\nexport const queries: QuerySpec[] = [\n messageQuery,\n messageInvalidQuery,\n gettextQuery,\n gettextInvalidQuery,\n pluralQuery,\n ngettextQuery,\n pgettextQuery,\n npgettextQuery,\n contextMsgQuery,\n contextPluralQuery,\n contextInvalidQuery,\n];\n","import fs from \"node:fs\";\nimport { extname, resolve } from \"node:path\";\n\nimport Parser from \"tree-sitter\";\nimport JavaScript from \"tree-sitter-javascript\";\nimport TS from \"tree-sitter-typescript\";\n\nimport { getReference } from \"./queries/comment.ts\";\nimport { importQuery } from \"./queries/import.ts\";\nimport { queries } from \"./queries/index.ts\";\nimport type { Context, Translation, Warning } from \"./queries/types.ts\";\n\nexport interface ParseResult {\n translations: Translation[];\n imports: string[];\n warnings: Warning[];\n}\n\nfunction getLanguage(ext: string) {\n switch (ext) {\n case \".ts\":\n return TS.typescript;\n case \".tsx\":\n return TS.tsx;\n default:\n return JavaScript;\n }\n}\n\nconst parserCache = new Map<string, { parser: Parser; language: Parser.Language }>();\nconst queryCache = new WeakMap<Parser.Language, Map<string, Parser.Query>>();\n\nfunction getCachedParser(ext: string) {\n let cached = parserCache.get(ext);\n if (!cached) {\n const parser = new Parser();\n const language = getLanguage(ext) as Parser.Language;\n parser.setLanguage(language);\n cached = { parser, language };\n parserCache.set(ext, cached);\n }\n return cached;\n}\n\nfunction getCachedQuery(language: Parser.Language, pattern: string) {\n let cache = queryCache.get(language);\n if (!cache) {\n cache = new Map();\n queryCache.set(language, cache);\n }\n\n let query = cache.get(pattern);\n if (!query) {\n query = new Parser.Query(language, pattern);\n cache.set(pattern, query);\n }\n\n return query;\n}\n\nexport function getParser(path: string) {\n const ext = extname(path);\n return getCachedParser(ext);\n}\n\nexport function getQuery(language: Parser.Language, pattern: string) {\n return getCachedQuery(language, pattern);\n}\n\nexport function parseFile(filePath: string): ParseResult {\n const path = resolve(filePath);\n const source = fs.readFileSync(path, \"utf8\");\n return parseSource(source, path);\n}\n\nexport function parseSource(source: string, path: string): ParseResult {\n const context: Context = {\n path,\n };\n\n const { parser, language } = getParser(path);\n const tree = parser.parse(source);\n\n const translations: Translation[] = [];\n const warnings: Warning[] = [];\n const imports: string[] = [];\n\n const seen = new Set<number>();\n\n for (const spec of queries) {\n const query = getCachedQuery(language, spec.pattern);\n for (const match of query.matches(tree.rootNode)) {\n const message = spec.extract(match);\n if (!message) {\n continue;\n }\n\n const { node, translation, error } = message;\n if (seen.has(node.id)) {\n continue;\n }\n seen.add(node.id);\n const reference = getReference(node, context);\n\n if (translation) {\n translations.push({\n ...translation,\n comments: {\n ...translation.comments,\n reference,\n },\n });\n }\n\n if (error) {\n warnings.push({\n error,\n reference,\n });\n }\n }\n }\n\n const importTreeQuery = getCachedQuery(language, importQuery.pattern);\n for (const match of importTreeQuery.matches(tree.rootNode)) {\n const imp = importQuery.extract(match);\n if (imp) {\n imports.push(imp);\n }\n }\n\n return { translations, imports, warnings };\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { ResolverFactory } from \"oxc-resolver\";\n\nfunction findTsconfig(dir: string): string | undefined {\n let current = dir;\n while (true) {\n const config = path.join(current, \"tsconfig.json\");\n if (fs.existsSync(config)) {\n return config;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n return undefined;\n }\n current = parent;\n }\n}\n\nconst resolverCache = new Map<string, ResolverFactory>();\n\nfunction getResolver(dir: string) {\n const tsconfig = findTsconfig(dir);\n const key = tsconfig ?? \"__default__\";\n let resolver = resolverCache.get(key);\n if (!resolver) {\n resolver = new ResolverFactory({\n extensions: [\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\", \".cjs\", \".json\"],\n conditionNames: [\"import\", \"require\", \"node\"],\n ...(tsconfig ? { tsconfig: { configFile: tsconfig } } : {}),\n });\n resolverCache.set(key, resolver);\n }\n return resolver;\n}\n\nfunction resolveFromDir(dir: string, spec: string): string | undefined {\n const resolver = getResolver(dir);\n const res = resolver.sync(dir, spec) as { path?: string };\n return res.path;\n}\n\nexport function resolveImport(file: string, spec: string): string | undefined {\n const dir = path.dirname(path.resolve(file));\n return resolveFromDir(dir, spec);\n}\n\nexport function resolveImports(file: string, imports: string[]): string[] {\n const dir = path.dirname(path.resolve(file));\n const resolver = getResolver(dir);\n const resolved: string[] = [];\n for (const spec of imports) {\n const res = resolver.sync(dir, spec) as { path?: string };\n if (res.path) {\n resolved.push(res.path);\n }\n }\n return resolved;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nimport type { Plugin } from \"../../plugin.ts\";\nimport { parseSource } from \"./parse.ts\";\nimport type { Translation } from \"./queries/types.ts\";\nimport { resolveImports } from \"./resolve.ts\";\n\nconst filter = /\\.([cm]?tsx?|jsx?)$/;\nconst namespace = \"source\";\n\nexport function core(): Plugin<string, Translation[]> {\n return {\n name: \"core\",\n setup(build) {\n build.context.logger?.debug(\"core plugin initialized\");\n build.onResolve({ filter, namespace }, ({ entrypoint, path }) => {\n return {\n entrypoint,\n namespace,\n path: resolve(path),\n };\n });\n\n build.onLoad({ filter, namespace }, async ({ entrypoint, path }) => {\n const data = await readFile(path, \"utf8\");\n return {\n entrypoint,\n path,\n namespace,\n data,\n };\n });\n\n build.onProcess({ filter, namespace }, ({ entrypoint, path, data }) => {\n const { translations, imports, warnings } = parseSource(data, path);\n\n if (build.context.config.walk) {\n const paths = resolveImports(path, imports);\n for (const path of paths) {\n build.resolve({ entrypoint, path, namespace });\n }\n }\n\n for (const warning of warnings) {\n build.context.logger?.warn(`${warning.error} at ${warning.reference}`);\n }\n\n build.resolve({\n entrypoint,\n path,\n namespace: \"translate\",\n data: translations,\n });\n\n return undefined;\n });\n },\n };\n}\n","import type { GetTextTranslationRecord } from \"gettext-parser\";\nimport { getNPlurals } from \"plural-forms\";\n\nimport type { Translation } from \"../core/queries/types.ts\";\n\nexport function collect(source: Translation[], locale?: string): GetTextTranslationRecord {\n const translations: GetTextTranslationRecord = { \"\": {} };\n const nplurals = locale ? getNPlurals(locale) : undefined;\n\n for (const { context, id, message, comments, obsolete, plural } of source) {\n const ctx = context || \"\";\n if (!translations[ctx]) {\n translations[ctx] = {};\n }\n\n const length = plural ? (nplurals ?? message.length) : 1;\n\n const existing = translations[ctx][id];\n const refs = new Set<string>();\n if (existing?.comments?.reference) {\n existing.comments.reference.split(/\\r?\\n|\\r/).forEach((r) => {\n refs.add(r);\n });\n }\n if (comments?.reference) {\n comments.reference.split(/\\r?\\n|\\r/).forEach((r) => {\n refs.add(r);\n });\n }\n\n const msgstr = existing?.msgstr ? existing.msgstr.slice(0, length) : Array.from({ length }, () => \"\");\n while (msgstr.length < length) msgstr.push(\"\");\n\n translations[ctx][id] = {\n msgctxt: context || undefined,\n msgid: id,\n msgid_plural: plural,\n msgstr,\n comments: {\n ...existing?.comments,\n ...comments,\n reference: refs.size ? Array.from(refs).join(\"\\n\") : undefined,\n },\n obsolete: existing?.obsolete ?? obsolete,\n };\n }\n\n return translations;\n}\n","import { isDeepStrictEqual } from \"node:util\";\nimport type { GetTextTranslations } from \"gettext-parser\";\nimport * as gettextParser from \"gettext-parser\";\n\nconst IGNORED_HEADER_KEYS = new Set([\"pot-creation-date\", \"po-revision-date\"]);\nconst IGNORED_HEADER_LINE_PREFIXES = [\"pot-creation-date:\", \"po-revision-date:\"];\n\nfunction normalizeHeaderString(value: string): string {\n const lines = value.split(\"\\n\");\n const hadTrailingNewline = value.endsWith(\"\\n\");\n\n const filtered = lines\n .filter((line) => {\n const trimmed = line.trimStart().toLowerCase();\n return !IGNORED_HEADER_LINE_PREFIXES.some((prefix) => trimmed.startsWith(prefix));\n })\n .map((line) => {\n const separatorIndex = line.indexOf(\":\");\n if (separatorIndex === -1) {\n return line;\n }\n\n const key = line.slice(0, separatorIndex).trim().toLowerCase();\n const value = line.slice(separatorIndex + 1);\n return `${key}:${value}`;\n });\n\n if (hadTrailingNewline && filtered[filtered.length - 1] !== \"\") {\n filtered.push(\"\");\n }\n\n return filtered.join(\"\\n\");\n}\n\nfunction normalize(translations: GetTextTranslations): GetTextTranslations {\n const compiled = gettextParser.po.compile(translations);\n const parsed = gettextParser.po.parse(compiled);\n\n if (parsed.headers) {\n const normalizedHeaders: Record<string, string> = {};\n for (const [key, value] of Object.entries(parsed.headers)) {\n if (!IGNORED_HEADER_KEYS.has(key.toLowerCase())) {\n normalizedHeaders[key.toLowerCase()] = value as string;\n }\n }\n parsed.headers = normalizedHeaders;\n }\n\n const headerMessage = parsed.translations?.[\"\"]?.[\"\"];\n if (headerMessage?.msgstr) {\n headerMessage.msgstr = headerMessage.msgstr.map((item) => normalizeHeaderString(item));\n }\n\n return parsed;\n}\n\nexport function hasChanges(left: GetTextTranslations, right?: GetTextTranslations): boolean {\n if (!right) {\n return true;\n }\n\n const normalizedLeft = normalize(left);\n const normalizedRight = normalize(right);\n\n return !isDeepStrictEqual(normalizedLeft, normalizedRight);\n}\n","import type { GetTextTranslationRecord, GetTextTranslations } from \"gettext-parser\";\nimport { getFormula, getNPlurals } from \"plural-forms\";\n\nimport type { ObsoleteStrategy } from \"../../configuration.ts\";\n\nexport interface Collected {\n translations: GetTextTranslationRecord;\n}\n\nexport function formatDate(date: Date): string {\n const pad = (n: number) => n.toString().padStart(2, \"0\");\n const year = date.getFullYear();\n const month = pad(date.getMonth() + 1);\n const day = pad(date.getDate());\n const hours = pad(date.getHours());\n const minutes = pad(date.getMinutes());\n const tzo = -date.getTimezoneOffset();\n const sign = tzo >= 0 ? \"+\" : \"-\";\n const offsetHours = pad(Math.floor(Math.abs(tzo) / 60));\n const offsetMinutes = pad(Math.abs(tzo) % 60);\n return `${year}-${month}-${day} ${hours}:${minutes}${sign}${offsetHours}${offsetMinutes}`;\n}\n\nexport function merge(\n sources: Collected[],\n existing: GetTextTranslations | undefined,\n obsolete: ObsoleteStrategy,\n locale: string,\n generatedAt: Date,\n): GetTextTranslations {\n let headers: Record<string, string> = {};\n let translations: GetTextTranslationRecord = { \"\": {} };\n let obsoleteTranslations: GetTextTranslationRecord = {};\n const nplurals = getNPlurals(locale);\n\n if (existing) {\n translations = existing.translations || { \"\": {} };\n obsoleteTranslations = existing.obsolete || {};\n for (const ctx of Object.keys(translations)) {\n for (const id of Object.keys(translations[ctx])) {\n if (ctx === \"\" && id === \"\") continue;\n translations[ctx][id].obsolete = true;\n }\n }\n }\n\n const collected: GetTextTranslationRecord = { \"\": {} };\n for (const { translations } of sources) {\n for (const [ctx, msgs] of Object.entries(translations)) {\n if (!collected[ctx]) collected[ctx] = {};\n for (const [id, entry] of Object.entries(msgs)) {\n const existing = collected[ctx][id];\n const refs = new Set<string>();\n if (existing?.comments?.reference) {\n existing.comments.reference.split(/\\r?\\n|\\r/).forEach((r) => {\n refs.add(r);\n });\n }\n if (entry.comments?.reference) {\n entry.comments.reference.split(/\\r?\\n|\\r/).forEach((r) => {\n refs.add(r);\n });\n }\n collected[ctx][id] = {\n ...existing,\n ...entry,\n comments: {\n ...existing?.comments,\n ...entry.comments,\n reference: refs.size ? Array.from(refs).join(\"\\n\") : undefined,\n },\n };\n }\n }\n }\n\n for (const [ctx, msgs] of Object.entries(collected)) {\n if (!translations[ctx]) translations[ctx] = {};\n for (const [id, entry] of Object.entries(msgs)) {\n const existingEntry = translations[ctx][id] ?? obsoleteTranslations[ctx]?.[id];\n if (existingEntry) {\n entry.msgstr = existingEntry.msgstr;\n entry.comments = {\n ...entry.comments,\n translator: existingEntry.comments?.translator,\n };\n }\n delete entry.obsolete;\n entry.msgstr = entry.msgstr.slice(0, nplurals);\n while (entry.msgstr.length < nplurals) {\n entry.msgstr.push(\"\");\n }\n translations[ctx][id] = entry;\n if (obsoleteTranslations[ctx]) {\n delete obsoleteTranslations[ctx][id];\n }\n }\n }\n\n for (const ctx of Object.keys(translations)) {\n for (const id of Object.keys(translations[ctx])) {\n if (ctx === \"\" && id === \"\") {\n continue;\n }\n const entry = translations[ctx][id];\n if (entry.obsolete) {\n if (!obsoleteTranslations[ctx]) {\n obsoleteTranslations[ctx] = {};\n }\n obsoleteTranslations[ctx][id] = entry;\n delete translations[ctx][id];\n }\n }\n }\n\n headers = {\n ...headers,\n \"content-type\": headers[\"content-type\"] || \"text/plain; charset=UTF-8\",\n \"plural-forms\": `nplurals=${nplurals}; plural=${getFormula(locale)};`,\n language: locale,\n \"pot-creation-date\": formatDate(generatedAt),\n \"x-generator\": \"@let-value/translate-extract\",\n };\n\n return {\n charset: \"utf-8\",\n headers,\n translations,\n ...(obsolete === \"mark\" && Object.keys(obsoleteTranslations).length ? { obsolete: obsoleteTranslations } : {}),\n };\n}\n","import fs from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport * as gettextParser from \"gettext-parser\";\n\nimport type { Plugin } from \"../../plugin.ts\";\nimport type { Translation } from \"../core/queries/types.ts\";\nimport { collect } from \"./collect.ts\";\nimport { hasChanges } from \"./hasChanges.ts\";\nimport { merge } from \"./merge.ts\";\n\nconst namespace = \"translate\";\n\nexport function po(): Plugin {\n return {\n name: \"po\",\n setup(build) {\n build.context.logger?.debug(\"po plugin initialized\");\n const collections = new Map<\n string,\n {\n locale: string;\n translations: Translation[];\n }\n >();\n let dispatched = false;\n\n build.onResolve({ filter: /.*/, namespace }, async ({ entrypoint, path, data }) => {\n if (!data || !Array.isArray(data)) {\n return undefined;\n }\n\n for (const locale of build.context.config.locales) {\n const destination = build.context.config.destination({ entrypoint, locale, path });\n if (!collections.has(destination)) {\n collections.set(destination, { locale, translations: [] });\n }\n\n collections.get(destination)?.translations.push(...data);\n }\n\n Promise.all([build.defer(\"source\"), build.defer(namespace)]).then(() => {\n if (dispatched) {\n return;\n }\n dispatched = true;\n\n for (const path of collections.keys()) {\n build.load({ entrypoint, path, namespace });\n }\n });\n\n return undefined;\n });\n\n build.onLoad({ filter: /.*\\.po$/, namespace }, async ({ entrypoint, path }) => {\n const contents = await fs.readFile(path).catch(() => undefined);\n const data = contents ? gettextParser.po.parse(contents) : undefined;\n return {\n entrypoint,\n path,\n namespace,\n data,\n };\n });\n\n build.onProcess({ filter: /.*\\.po$/, namespace }, async ({ entrypoint, path, data }) => {\n const collected = collections.get(path);\n if (!collected) {\n build.context.logger?.warn({ path }, \"no translations collected for this path\");\n return undefined;\n }\n\n const { locale, translations } = collected;\n\n const record = collect(translations, locale);\n\n const out = merge(\n [{ translations: record }],\n data as never,\n build.context.config.obsolete,\n locale,\n build.context.generatedAt,\n );\n\n if (hasChanges(out, data as never)) {\n await fs.mkdir(dirname(path), { recursive: true });\n await fs.writeFile(path, gettextParser.po.compile(out));\n }\n\n build.resolve({\n entrypoint,\n path,\n namespace: \"cleanup\",\n data: translations,\n });\n });\n },\n };\n}\n","import { basename, dirname, extname, join } from \"node:path\";\nimport type { PluralFormsLocale } from \"@let-value/translate\";\nimport type { LogLevel } from \"./logger.ts\";\n\nimport type { Plugin } from \"./plugin.ts\";\nimport { cleanup } from \"./plugins/cleanup/cleanup.ts\";\nimport { core } from \"./plugins/core/core.ts\";\nimport { po } from \"./plugins/po/po.ts\";\n\nexport type DestinationFn = (args: { locale: string; entrypoint: string; path: string }) => string;\nexport type ExcludeFn = (args: { entrypoint: string; path: string }) => boolean;\nexport type Exclude = RegExp | ExcludeFn;\n\nconst defaultPlugins = { core, po, cleanup };\ntype DefaultPlugins = typeof defaultPlugins;\n\n/**\n * Strategy to handle obsolete translations in existing locale files:\n * - \"mark\": keep obsolete entries in the locale file but mark them as obsolete\n * - \"remove\": remove obsolete entries from the locale file\n */\nexport type ObsoleteStrategy = \"mark\" | \"remove\";\n\nexport interface EntrypointConfig {\n entrypoint: string;\n destination?: DestinationFn;\n obsolete?: ObsoleteStrategy;\n walk?: boolean;\n exclude?: Exclude | Exclude[];\n}\n\nexport interface UserConfig {\n /**\n * Default locale to use as the base for extraction\n * @default \"en\"\n * @see {@link PluralFormsLocale} for available locales\n */\n defaultLocale?: PluralFormsLocale;\n /**\n * Array of locales to extract translations for\n * @default [defaultLocale]\n * @see {@link PluralFormsLocale} for available locales\n */\n locales?: PluralFormsLocale[];\n /**\n * Array of plugins to use or a function to override the default plugins\n * @default DefaultPlugins\n * @see {@link DefaultPlugins} for available plugins\n */\n plugins?: Plugin[] | ((defaultPlugins: DefaultPlugins) => Plugin[]);\n /**\n * One or more entrypoints to extract translations from, could be:\n * - file path, will be treated as a single file entrypoint\n * - glob pattern will be expanded to match files, each treated as a separate entrypoint\n * - configuration object with options for the entrypoint\n * @see {@link EntrypointConfig} for configuration options\n */\n entrypoints: string | EntrypointConfig | Array<string | EntrypointConfig>;\n /**\n * Function to determine the destination path for each extracted locale file\n * @default `./translations/entrypoint.locale.po`\n * @see {@link DestinationFn}\n * @see Can be overridden per entrypoint via `destination` in {@link EntrypointConfig\n */\n destination?: DestinationFn;\n /**\n * Strategy to handle obsolete translations in existing locale files\n * @default \"mark\"\n * @see {@link ObsoleteStrategy} for available strategies\n * @see Can be overridden per entrypoint via `obsolete` in {@link EntrypointConfig\n */\n obsolete?: ObsoleteStrategy;\n /**\n * Whether to recursively walk dependencies of the entrypoints\n * @default true\n * @see Can be overridden per entrypoint via `walk` in {@link EntrypointConfig}.\n */\n walk?: boolean;\n /**\n * Paths or patterns to exclude from extraction, applied to all entrypoints\n * @default [/node_modules/, /dist/, /build/]\n * @see Can be overridden per entrypoint via `exclude` in {@link EntrypointConfig}.\n */\n exclude?: Exclude | Exclude[];\n /**\n * Log level for the extraction process\n * @default \"info\"\n */\n logLevel?: LogLevel;\n}\n\nexport interface ResolvedEntrypoint extends Omit<EntrypointConfig, \"exclude\"> {\n exclude?: Exclude[];\n}\n\nexport interface ResolvedConfig {\n plugins: Plugin[];\n entrypoints: ResolvedEntrypoint[];\n defaultLocale: string;\n locales: string[];\n destination: DestinationFn;\n obsolete: ObsoleteStrategy;\n walk: boolean;\n logLevel: LogLevel;\n exclude: Exclude[];\n}\n\nconst defaultDestination: DestinationFn = ({ entrypoint, locale }) =>\n join(dirname(entrypoint), \"translations\", `${basename(entrypoint, extname(entrypoint))}.${locale}.po`);\n\nconst defaultExclude: Exclude[] = [\n /(?:^|[\\\\/])node_modules(?:[\\\\/]|$)/,\n /(?:^|[\\\\/])dist(?:[\\\\/]|$)/,\n /(?:^|[\\\\/])build(?:[\\\\/]|$)/,\n];\n\nfunction normalizeExclude(exclude?: Exclude | Exclude[]): Exclude[] {\n if (!exclude) return [];\n return Array.isArray(exclude) ? exclude : [exclude];\n}\n\nfunction resolveEntrypoint(ep: string | EntrypointConfig): ResolvedEntrypoint {\n if (typeof ep === \"string\") {\n return { entrypoint: ep };\n }\n const { entrypoint, destination, obsolete, walk, exclude } = ep;\n return { entrypoint, destination, obsolete, walk, exclude: exclude ? normalizeExclude(exclude) : undefined };\n}\n\nfunction resolvePlugins(user?: UserConfig[\"plugins\"]): Plugin[] {\n if (typeof user === \"function\") {\n return user(defaultPlugins);\n }\n if (Array.isArray(user)) {\n return [...Object.values(defaultPlugins).map((plugin) => plugin()), ...user];\n }\n return Object.values(defaultPlugins).map((plugin) => plugin());\n}\n\n/**\n * Type helper to make it easier to use translate.config.ts\n * @param config - {@link UserConfig}.\n */\nexport function defineConfig(config: UserConfig): ResolvedConfig {\n const defaultLocale = config.defaultLocale ?? \"en\";\n\n const plugins = resolvePlugins(config.plugins);\n\n const raw = Array.isArray(config.entrypoints) ? config.entrypoints : [config.entrypoints];\n const entrypoints = raw.map(resolveEntrypoint);\n\n return {\n plugins,\n entrypoints,\n defaultLocale,\n locales: config.locales ?? [defaultLocale],\n destination: config.destination ?? defaultDestination,\n obsolete: config.obsolete ?? \"mark\",\n walk: config.walk ?? true,\n logLevel: config.logLevel ?? \"info\",\n exclude: config.exclude ? normalizeExclude(config.exclude) : defaultExclude,\n };\n}\n","import type Parser from \"tree-sitter\";\n\nexport function buildTemplate(node: Parser.SyntaxNode): { text: string; error?: string } {\n const source = node.tree.rootNode.text;\n const open = node.childForFieldName(\"open_tag\");\n const close = node.childForFieldName(\"close_tag\");\n const contentStart = open?.endIndex ?? node.startIndex;\n const contentEnd = close?.startIndex ?? node.endIndex;\n\n type Part = { kind: \"text\"; text: string; raw: boolean } | { kind: \"expr\"; value: string };\n\n const parts: Part[] = [];\n let segmentStart = contentStart;\n\n const pushRawText = (endIndex: number) => {\n if (endIndex <= segmentStart) {\n segmentStart = Math.max(segmentStart, endIndex);\n return;\n }\n const text = source.slice(segmentStart, endIndex);\n if (text) {\n parts.push({ kind: \"text\", text, raw: true });\n }\n segmentStart = endIndex;\n };\n\n const children = node.namedChildren.slice(1, -1);\n for (const child of children) {\n if (child.type === \"jsx_expression\") {\n pushRawText(child.startIndex);\n const expr = child.namedChildren[0];\n if (!expr) {\n return { text: \"\", error: \"Empty JSX expression\" };\n }\n\n if (expr.type === \"identifier\") {\n parts.push({ kind: \"expr\", value: expr.text });\n } else if (expr.type === \"string\") {\n parts.push({ kind: \"text\", text: expr.text.slice(1, -1), raw: false });\n } else if (expr.type === \"template_string\") {\n const hasSubstitutions = expr.children.some((c) => c.type === \"template_substitution\");\n if (hasSubstitutions) {\n return { text: \"\", error: \"JSX expressions with template substitutions are not supported\" };\n }\n parts.push({ kind: \"text\", text: expr.text.slice(1, -1), raw: false });\n } else {\n return { text: \"\", error: \"JSX expressions must be simple identifiers, strings, or template literals\" };\n }\n segmentStart = child.endIndex;\n } else if (child.type === \"string\") {\n pushRawText(child.startIndex);\n parts.push({ kind: \"text\", text: child.text.slice(1, -1), raw: false });\n segmentStart = child.endIndex;\n } else if (child.type === \"jsx_text\" || child.type === \"html_character_reference\" || child.isError) {\n } else {\n return { text: \"\", error: \"Unsupported JSX child\" };\n }\n }\n\n pushRawText(contentEnd);\n\n const firstRawIndex = parts.findIndex((part) => part.kind === \"text\" && part.raw);\n if (firstRawIndex === 0) {\n const part = parts[firstRawIndex] as Extract<Part, { kind: \"text\" }>;\n part.text = part.text.replace(/^\\s+/, \"\");\n }\n\n let lastRawIndex = -1;\n for (let i = parts.length - 1; i >= 0; i--) {\n const part = parts[i];\n if (part.kind === \"text\" && part.raw) {\n lastRawIndex = i;\n break;\n }\n }\n if (lastRawIndex !== -1 && lastRawIndex === parts.length - 1) {\n const part = parts[lastRawIndex] as Extract<Part, { kind: \"text\" }>;\n part.text = part.text.replace(/\\s+$/, \"\");\n }\n\n const strings: string[] = [\"\"];\n const values: string[] = [];\n for (const part of parts) {\n if (part.kind === \"text\") {\n if (part.text) {\n strings[strings.length - 1] += part.text;\n }\n } else {\n values.push(part.value);\n strings.push(\"\");\n }\n }\n\n let text = \"\";\n for (let i = 0; i < strings.length; i++) {\n text += strings[i];\n if (values[i]) {\n text += `\\${${values[i]}}`;\n }\n }\n return { text };\n}\n\nexport function buildAttrValue(node: Parser.SyntaxNode): { text: string; error?: string } {\n if (node.type === \"string\") {\n return { text: node.text.slice(1, -1) };\n }\n if (node.type === \"jsx_expression\") {\n const expr = node.namedChildren[0];\n if (!expr) {\n return { text: \"\", error: \"Empty JSX expression\" };\n }\n\n if (expr.type === \"identifier\") {\n return { text: `\\${${expr.text}}` };\n } else if (expr.type === \"string\") {\n return { text: expr.text.slice(1, -1) };\n } else if (expr.type === \"template_string\") {\n // Check if it's a simple template string with no substitutions\n const hasSubstitutions = expr.children.some((c) => c.type === \"template_substitution\");\n if (hasSubstitutions) {\n return { text: \"\", error: \"JSX expressions with template substitutions are not supported\" };\n }\n // Extract the text content from the template string\n const content = expr.text.slice(1, -1); // Remove backticks\n return { text: content };\n } else {\n return { text: \"\", error: \"JSX expressions must be simple identifiers, strings, or template literals\" };\n }\n }\n return { text: \"\", error: \"Unsupported JSX child\" };\n}\n","import type Parser from \"tree-sitter\";\n\nimport { withComment } from \"../../core/queries/comment.ts\";\nimport type { MessageMatch, QuerySpec, Translation } from \"../../core/queries/types.ts\";\nimport { buildAttrValue, buildTemplate } from \"./utils.ts\";\n\nexport const messageQuery: QuerySpec = withComment({\n pattern: `(\n [\n (jsx_element (jsx_opening_element name: (identifier) @name)) @call\n (jsx_self_closing_element name: (identifier) @name) @call\n (lexical_declaration \n (variable_declarator \n value: [\n (jsx_element (jsx_opening_element name: (identifier) @name)) @call\n (jsx_self_closing_element name: (identifier) @name) @call\n ]\n )\n )\n ]\n (#eq? @name \"Message\")\n )`,\n extract(match: Parser.QueryMatch): MessageMatch | undefined {\n const node = match.captures.find((c) => c.name === \"call\")?.node;\n if (!node) return undefined;\n let attrs: Parser.SyntaxNode[] = [];\n if (node.type === \"jsx_element\") {\n const open = node.childForFieldName(\"open_tag\");\n if (open) attrs = open.namedChildren;\n } else if (node.type === \"jsx_self_closing_element\") {\n attrs = node.namedChildren.slice(1);\n }\n let msgctxt: string | undefined;\n let childValue: Parser.SyntaxNode | undefined;\n for (const child of attrs) {\n if (child.type !== \"jsx_attribute\") continue;\n const name = child.child(0);\n const value = child.child(child.childCount - 1);\n if (name?.text === \"context\" && value?.type === \"string\") {\n msgctxt = value.text.slice(1, -1);\n } else if (name?.text === \"children\" && value) {\n childValue = value;\n }\n }\n let text = \"\";\n let error: string | undefined;\n if (node.type === \"jsx_element\") {\n ({ text, error } = buildTemplate(node));\n } else if (childValue) {\n ({ text, error } = buildAttrValue(childValue));\n }\n if (error) {\n return { node, error };\n }\n if (!text) return undefined;\n const translation: Translation = {\n id: text,\n message: [text],\n };\n if (msgctxt) translation.context = msgctxt;\n return { node, translation };\n },\n});\n","import type Parser from \"tree-sitter\";\n\nimport { withComment } from \"../../core/queries/comment.ts\";\nimport type { MessageMatch, QuerySpec, Translation } from \"../../core/queries/types.ts\";\nimport { buildTemplate } from \"./utils.ts\";\n\nfunction parseForms(node: Parser.SyntaxNode): { forms: string[]; error?: string } {\n const forms: string[] = [];\n if (node.type === \"jsx_expression\") {\n const arr = node.namedChildren[0];\n if (!arr || arr.type !== \"array\") {\n return { forms: [], error: \"Plural forms must be an array\" };\n }\n for (const el of arr.namedChildren) {\n if (el.type === \"jsx_element\" || el.type === \"jsx_fragment\") {\n const { text, error } = buildTemplate(el);\n if (error) return { forms: [], error };\n forms.push(text);\n } else if (el.type === \"string\") {\n forms.push(el.text.slice(1, -1));\n } else {\n return { forms: [], error: \"Unsupported plural form\" };\n }\n }\n }\n return { forms };\n}\n\nexport const pluralQuery: QuerySpec = withComment({\n pattern: `(\n [\n (jsx_element (jsx_opening_element name: (identifier) @name))\n (jsx_self_closing_element name: (identifier) @name)\n ] @call\n (#eq? @name \"Plural\")\n )`,\n extract(match: Parser.QueryMatch): MessageMatch | undefined {\n const node = match.captures.find((c) => c.name === \"call\")?.node;\n if (!node) return undefined;\n let attrs: Parser.SyntaxNode[] = [];\n if (node.type === \"jsx_element\") {\n const open = node.childForFieldName(\"open_tag\");\n if (open) attrs = open.namedChildren;\n } else if (node.type === \"jsx_self_closing_element\") {\n attrs = node.namedChildren.slice(1);\n }\n let msgctxt: string | undefined;\n let formsNode: Parser.SyntaxNode | null | undefined;\n for (const child of attrs) {\n if (child.type !== \"jsx_attribute\") continue;\n const name = child.child(0);\n const value = child.child(child.childCount - 1);\n if (name?.text === \"context\" && value?.type === \"string\") {\n msgctxt = value.text.slice(1, -1);\n } else if (name?.text === \"forms\" && value) {\n formsNode = value;\n }\n }\n if (!formsNode) return undefined;\n const { forms, error } = parseForms(formsNode);\n if (error) {\n return { node, error };\n }\n if (forms.length === 0) return undefined;\n const translation: Translation = {\n id: forms[0],\n plural: forms[1],\n message: forms,\n };\n if (msgctxt) translation.context = msgctxt;\n return { node, translation };\n },\n});\n","import type { QuerySpec } from \"../../core/queries/types.ts\";\nimport { messageQuery } from \"./message.ts\";\nimport { pluralQuery } from \"./plural.ts\";\n\nexport const queries: QuerySpec[] = [messageQuery, pluralQuery];\n","import fs from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { getParser, getQuery } from \"../core/parse.ts\";\nimport { getReference } from \"../core/queries/comment.ts\";\n\nimport type { Context, Translation, Warning } from \"../core/queries/types.ts\";\nimport { queries } from \"./queries/index.ts\";\n\nexport interface ParseResult {\n translations: Translation[];\n warnings: Warning[];\n}\n\nexport function parseFile(filePath: string): ParseResult {\n const path = resolve(filePath);\n const source = fs.readFileSync(path, \"utf8\");\n return parseSource(source, path);\n}\n\nexport function parseSource(source: string, path: string): ParseResult {\n const context: Context = { path };\n const { parser, language } = getParser(path);\n const tree = parser.parse(source);\n\n const translations: Translation[] = [];\n const warnings: Warning[] = [];\n const seen = new Set<number>();\n\n for (const spec of queries) {\n const query = getQuery(language, spec.pattern);\n for (const match of query.matches(tree.rootNode)) {\n const message = spec.extract(match);\n if (!message) continue;\n const { node, translation, error } = message;\n if (seen.has(node.id)) continue;\n seen.add(node.id);\n const reference = getReference(node, context);\n if (translation) {\n translations.push({\n ...translation,\n comments: {\n ...translation.comments,\n reference,\n },\n });\n }\n if (error) {\n warnings.push({\n error,\n reference,\n });\n }\n }\n }\n\n return { translations, warnings };\n}\n","import { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nimport type { Plugin } from \"../../plugin.ts\";\nimport type { Translation } from \"../core/queries/types.ts\";\nimport { parseSource } from \"./parse.ts\";\n\nconst filter = /\\.[cm]?[jt]sx$/;\n\nexport function react(): Plugin<string, Translation[]> {\n return {\n name: \"react\",\n setup(build) {\n build.context.logger?.debug(\"react plugin initialized\");\n build.onResolve({ filter: /.*/, namespace: \"source\" }, ({ entrypoint, path, namespace }) => {\n return {\n entrypoint,\n namespace,\n path: resolve(path),\n };\n });\n build.onLoad({ filter, namespace: \"source\" }, async ({ entrypoint, path, namespace }) => {\n const data = await readFile(path, \"utf8\");\n return {\n entrypoint,\n path,\n namespace,\n data,\n };\n });\n build.onProcess({ filter, namespace: \"source\" }, ({ entrypoint, path, data }) => {\n const { translations, warnings } = parseSource(data, path);\n\n for (const warning of warnings) {\n build.context.logger?.warn(`${warning.error} at ${warning.reference}`);\n }\n\n build.resolve({\n entrypoint,\n path,\n namespace: \"translate\",\n data: translations,\n });\n\n return undefined;\n });\n },\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@let-value/translate-extract",
3
- "version": "1.0.19",
3
+ "version": "1.0.22",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -20,7 +20,7 @@
20
20
  "dist"
21
21
  ],
22
22
  "dependencies": {
23
- "@let-value/translate": "1.0.19",
23
+ "@let-value/translate": "1.0.22",
24
24
  "chalk": "5.3.0",
25
25
  "cosmiconfig": "9.0.0",
26
26
  "gettext-parser": "8.0.0",