@let-value/translate-extract 1.2.3 → 1.2.4

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.
@@ -582,6 +582,16 @@ function isBuiltin(spec) {
582
582
  const [base, subpath] = (spec.startsWith("node:") ? spec.slice(5) : spec).split("/", 2);
583
583
  return subpath !== void 0 && builtins.has(base);
584
584
  }
585
+ const schemePattern = /^[a-z][a-z\d+\-.]+:/i;
586
+ /**
587
+ * Specifiers that exist only inside a bundler's plugin pipeline — Vite virtual
588
+ * modules (`virtual:pwa-register`), their resolved `\0` form, and URL schemes.
589
+ * Extraction runs without that pipeline, so they can never resolve on disk and
590
+ * reporting them as unresolved is noise.
591
+ */
592
+ function isExternal(spec) {
593
+ return spec.startsWith("\0") || schemePattern.test(spec);
594
+ }
585
595
  function getResolver(dir) {
586
596
  const tsconfig = findTsconfig(dir);
587
597
  const key = tsconfig ?? "__default__";
@@ -621,10 +631,15 @@ function resolveImportResults(file, imports) {
621
631
  const resolver = getResolver(dir);
622
632
  const resolved = [];
623
633
  const unresolved = [];
634
+ const external = [];
624
635
  for (const imp of imports) {
625
636
  const ref = normalizeImportReference(imp);
626
637
  const { spec } = ref;
627
638
  if (isBuiltin(spec)) continue;
639
+ if (isExternal(spec)) {
640
+ external.push(spec);
641
+ continue;
642
+ }
628
643
  try {
629
644
  const res = resolver.sync(dir, spec);
630
645
  if (res.path) resolved.push({
@@ -647,7 +662,8 @@ function resolveImportResults(file, imports) {
647
662
  }
648
663
  return {
649
664
  resolved,
650
- unresolved
665
+ unresolved,
666
+ external
651
667
  };
652
668
  }
653
669
  //#endregion
@@ -658,6 +674,12 @@ function core() {
658
674
  name: "core",
659
675
  setup(build) {
660
676
  build.context.logger?.debug("core plugin initialized");
677
+ const reported = /* @__PURE__ */ new Set();
678
+ const warnOnce = (message) => {
679
+ if (reported.has(message)) return;
680
+ reported.add(message);
681
+ build.context.logger?.warn(message);
682
+ };
661
683
  build.onLoad(filter$1, ({ path }) => (0, node_fs_promises.readFile)(path, "utf8"));
662
684
  build.onProcess(filter$1, ({ entrypoint, path, contents, emit }) => {
663
685
  const result = parseSource$1(contents, path);
@@ -670,7 +692,11 @@ function core() {
670
692
  }
671
693
  const { translations, imports, warnings } = result;
672
694
  if (build.context.config.walk) {
673
- const { resolved, unresolved } = resolveImportResults(path, imports);
695
+ const { resolved, unresolved, external } = resolveImportResults(path, imports);
696
+ for (const spec of external) build.context.logger?.debug({
697
+ path,
698
+ spec
699
+ }, "skipping external import");
674
700
  for (const result of resolved) {
675
701
  if (build.context.paths.has(result.path)) continue;
676
702
  build.source({
@@ -687,16 +713,57 @@ function core() {
687
713
  namespace: "source",
688
714
  import: imp
689
715
  }, build.context.config.exclude)) continue;
690
- build.context.logger?.warn(`Unable to resolve import "${spec}" from ${path}${error ? `: ${error}` : ""}`);
716
+ warnOnce(`Unable to resolve import "${spec}" from ${path}${error ? `: ${error}` : ""}`);
691
717
  }
692
718
  }
693
- for (const warning of warnings) build.context.logger?.warn(`${warning.error} at ${warning.reference}`);
719
+ for (const warning of warnings) warnOnce(`${warning.error} at ${warning.reference}`);
694
720
  emit(translations);
695
721
  });
696
722
  }
697
723
  };
698
724
  }
699
725
  //#endregion
726
+ //#region src/plugins/po/references.ts
727
+ const referencePattern = /^(.*?):(\d+)(?::(\d+))?$/;
728
+ function parseReference(reference) {
729
+ const match = referencePattern.exec(reference);
730
+ if (!match) return {
731
+ path: reference,
732
+ line: -1,
733
+ column: -1
734
+ };
735
+ return {
736
+ path: match[1],
737
+ line: Number(match[2]),
738
+ column: match[3] ? Number(match[3]) : -1
739
+ };
740
+ }
741
+ function comparePaths(left, right) {
742
+ if (left === right) return 0;
743
+ return left < right ? -1 : 1;
744
+ }
745
+ /**
746
+ * Orders reference comments canonically — by file path, then line, then column —
747
+ * so that a catalog does not record the order in which the module graph happened
748
+ * to be walked.
749
+ */
750
+ function sortReferences(references) {
751
+ return [...references].map((reference) => ({
752
+ reference,
753
+ parsed: parseReference(reference)
754
+ })).sort((left, right) => {
755
+ const byPath = comparePaths(left.parsed.path, right.parsed.path);
756
+ if (byPath !== 0) return byPath;
757
+ if (left.parsed.line !== right.parsed.line) return left.parsed.line - right.parsed.line;
758
+ if (left.parsed.column !== right.parsed.column) return left.parsed.column - right.parsed.column;
759
+ return comparePaths(left.reference, right.reference);
760
+ }).map(({ reference }) => reference);
761
+ }
762
+ /** Orders message keys (contexts and msgids) canonically. */
763
+ function sortKeys(keys) {
764
+ return [...keys].sort(comparePaths);
765
+ }
766
+ //#endregion
700
767
  //#region src/plugins/po/collect.ts
701
768
  function collect(source, locale) {
702
769
  const translations = { "": {} };
@@ -723,7 +790,7 @@ function collect(source, locale) {
723
790
  comments: {
724
791
  ...existing?.comments,
725
792
  ...comments,
726
- reference: refs.size ? Array.from(refs).join("\n") : void 0
793
+ reference: refs.size ? sortReferences(refs).join("\n") : void 0
727
794
  },
728
795
  obsolete: existing?.obsolete ?? obsolete
729
796
  };
@@ -810,14 +877,16 @@ function merge(sources, existing, obsolete, locale, generatedAt) {
810
877
  comments: {
811
878
  ...existing?.comments,
812
879
  ...entry.comments,
813
- reference: refs.size ? Array.from(refs).join("\n") : void 0
880
+ reference: refs.size ? sortReferences(refs).join("\n") : void 0
814
881
  }
815
882
  };
816
883
  }
817
884
  }
818
- for (const [ctx, msgs] of Object.entries(collected)) {
885
+ for (const ctx of sortKeys(Object.keys(collected))) {
886
+ const msgs = collected[ctx];
819
887
  if (!translations[ctx]) translations[ctx] = {};
820
- for (const [id, entry] of Object.entries(msgs)) {
888
+ for (const id of sortKeys(Object.keys(msgs))) {
889
+ const entry = msgs[id];
821
890
  const existingEntry = translations[ctx][id] ?? obsoleteTranslations[ctx]?.[id];
822
891
  if (existingEntry) {
823
892
  entry.msgstr = existingEntry.msgstr;
@@ -1194,9 +1263,15 @@ function react() {
1194
1263
  name: "react",
1195
1264
  setup(build) {
1196
1265
  build.context.logger?.debug("react plugin initialized");
1266
+ const reported = /* @__PURE__ */ new Set();
1197
1267
  build.onProcess(filter, ({ path, contents, emit }) => {
1198
1268
  const { translations, warnings } = parseSource(contents, path);
1199
- for (const warning of warnings) build.context.logger?.warn(`${warning.error} at ${warning.reference}`);
1269
+ for (const warning of warnings) {
1270
+ const message = `${warning.error} at ${warning.reference}`;
1271
+ if (reported.has(message)) continue;
1272
+ reported.add(message);
1273
+ build.context.logger?.warn(message);
1274
+ }
1200
1275
  emit(translations);
1201
1276
  });
1202
1277
  }
@@ -1,2 +1,2 @@
1
- import { C as ProcessHook, E as UniversalPlugin, S as ProcessArgs, T as SourceArgs, _ as LoadArgs, a as ExcludeFn, b as OutputsHook, c as ResolvedEntrypoint, d as Build, f as CollectedArgs, g as ImportReference, h as FileTranslations, i as ExcludeConfig, l as UserConfig, m as Context, n as EntrypointConfig, o as ObsoleteStrategy, p as CollectedHook, r as Exclude, s as ResolvedConfig, t as DestinationFn, u as defineConfig, v as LoadHook, w as ResolveArgs, x as Plugin, y as OutputsArgs } from "../configuration-DLSMbmU5.cjs";
1
+ import { C as ProcessHook, E as UniversalPlugin, S as ProcessArgs, T as SourceArgs, _ as LoadArgs, a as ExcludeFn, b as OutputsHook, c as ResolvedEntrypoint, d as Build, f as CollectedArgs, g as ImportReference, h as FileTranslations, i as ExcludeConfig, l as UserConfig, m as Context, n as EntrypointConfig, o as ObsoleteStrategy, p as CollectedHook, r as Exclude, s as ResolvedConfig, t as DestinationFn, u as defineConfig, v as LoadHook, w as ResolveArgs, x as Plugin, y as OutputsArgs } from "../configuration-CoElcSHz.cjs";
2
2
  export { Build, CollectedArgs, CollectedHook, Context, DestinationFn, EntrypointConfig, Exclude, ExcludeConfig, ExcludeFn, FileTranslations, ImportReference, LoadArgs, LoadHook, ObsoleteStrategy, OutputsArgs, OutputsHook, Plugin, ProcessArgs, ProcessHook, ResolveArgs, ResolvedConfig, ResolvedEntrypoint, SourceArgs, UniversalPlugin, UserConfig, defineConfig };
@@ -1,2 +1,2 @@
1
- import { C as ProcessHook, E as UniversalPlugin, S as ProcessArgs, T as SourceArgs, _ as LoadArgs, a as ExcludeFn, b as OutputsHook, c as ResolvedEntrypoint, d as Build, f as CollectedArgs, g as ImportReference, h as FileTranslations, i as ExcludeConfig, l as UserConfig, m as Context, n as EntrypointConfig, o as ObsoleteStrategy, p as CollectedHook, r as Exclude, s as ResolvedConfig, t as DestinationFn, u as defineConfig, v as LoadHook, w as ResolveArgs, x as Plugin, y as OutputsArgs } from "../configuration-Bwtek7Fh.mjs";
1
+ import { C as ProcessHook, E as UniversalPlugin, S as ProcessArgs, T as SourceArgs, _ as LoadArgs, a as ExcludeFn, b as OutputsHook, c as ResolvedEntrypoint, d as Build, f as CollectedArgs, g as ImportReference, h as FileTranslations, i as ExcludeConfig, l as UserConfig, m as Context, n as EntrypointConfig, o as ObsoleteStrategy, p as CollectedHook, r as Exclude, s as ResolvedConfig, t as DestinationFn, u as defineConfig, v as LoadHook, w as ResolveArgs, x as Plugin, y as OutputsArgs } from "../configuration-s7zv58Wf.mjs";
2
2
  export { Build, CollectedArgs, CollectedHook, Context, DestinationFn, EntrypointConfig, Exclude, ExcludeConfig, ExcludeFn, FileTranslations, ImportReference, LoadArgs, LoadHook, ObsoleteStrategy, OutputsArgs, OutputsHook, Plugin, ProcessArgs, ProcessHook, ResolveArgs, ResolvedConfig, ResolvedEntrypoint, SourceArgs, UniversalPlugin, UserConfig, defineConfig };
@@ -1 +1 @@
1
- {"version":3,"file":"core.mjs","names":[],"sources":["../../src/configuration.ts"],"sourcesContent":["import { basename, dirname, extname, join } from \"node:path\";\nimport type { PluralFormsLocale } from \"@let-value/translate\";\nimport { type DefaultExclude, defaultExclude, defaultExcludes } from \"./exclude.ts\";\nimport type { LogLevel } from \"./logger.ts\";\n\nimport type { ResolveArgs, UniversalPlugin } from \"./plugin.ts\";\nimport { cleanup, core, po } from \"./static.ts\";\n\nexport type DestinationFn = (args: { locale: string; entrypoint: string; path: string }) => string;\nexport type ExcludeFn = (args: ResolveArgs) => boolean;\nexport type Exclude = RegExp | ExcludeFn;\nexport type ExcludeConfig = RegExp | Exclude[] | ((defaultExclude: DefaultExclude) => Exclude[]);\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?: ExcludeConfig;\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?: UniversalPlugin[] | ((defaultPlugins: DefaultPlugins) => UniversalPlugin[]);\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?: ExcludeConfig;\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: UniversalPlugin[];\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\nfunction normalizeExclude(exclude?: RegExp | Exclude[]): Exclude[] {\n if (!exclude) return [];\n return Array.isArray(exclude) ? exclude : [exclude];\n}\n\nfunction resolveExcludes(exclude?: ExcludeConfig): Exclude[] {\n if (typeof exclude === \"function\") {\n return exclude(defaultExclude);\n }\n\n return [...defaultExcludes, ...normalizeExclude(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 {\n entrypoint,\n destination,\n obsolete,\n walk,\n exclude: exclude ? resolveExcludes(exclude) : undefined,\n };\n}\n\nfunction resolvePlugins(user?: UserConfig[\"plugins\"]): UniversalPlugin[] {\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: resolveExcludes(config.exclude),\n };\n}\n"],"mappings":";;;;AAaA,MAAM,iBAAiB;CAAE;CAAM;CAAI;AAAQ;AA8F3C,MAAM,sBAAqC,EAAE,YAAY,aACrD,KAAK,QAAQ,UAAU,GAAG,gBAAgB,GAAG,SAAS,YAAY,QAAQ,UAAU,CAAC,EAAE,GAAG,OAAO,IAAI;AAEzG,SAAS,iBAAiB,SAAyC;CAC/D,IAAI,CAAC,SAAS,OAAO,CAAC;CACtB,OAAO,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO;AACtD;AAEA,SAAS,gBAAgB,SAAoC;CACzD,IAAI,OAAO,YAAY,YACnB,OAAO,QAAQ,cAAc;CAGjC,OAAO,CAAC,GAAG,iBAAiB,GAAG,iBAAiB,OAAO,CAAC;AAC5D;AAEA,SAAS,kBAAkB,IAAmD;CAC1E,IAAI,OAAO,OAAO,UACd,OAAO,EAAE,YAAY,GAAG;CAE5B,MAAM,EAAE,YAAY,aAAa,UAAU,MAAM,YAAY;CAC7D,OAAO;EACH;EACA;EACA;EACA;EACA,SAAS,UAAU,gBAAgB,OAAO,IAAI,KAAA;CAClD;AACJ;AAEA,SAAS,eAAe,MAAiD;CACrE,IAAI,OAAO,SAAS,YAChB,OAAO,KAAK,cAAc;CAE9B,IAAI,MAAM,QAAQ,IAAI,GAClB,OAAO,CAAC,GAAG,OAAO,OAAO,cAAc,CAAC,CAAC,KAAK,WAAW,OAAO,CAAC,GAAG,GAAG,IAAI;CAE/E,OAAO,OAAO,OAAO,cAAc,CAAC,CAAC,KAAK,WAAW,OAAO,CAAC;AACjE;;;;;AAMA,SAAgB,aAAa,QAAoC;CAC7D,MAAM,gBAAgB,OAAO,iBAAiB;CAO9C,OAAO;EACH,SANY,eAAe,OAAO,OAM5B;EACN,cALQ,MAAM,QAAQ,OAAO,WAAW,IAAI,OAAO,cAAc,CAAC,OAAO,WAAW,EAAA,CAChE,IAAI,iBAId;EACV;EACA,SAAS,OAAO,WAAW,CAAC,aAAa;EACzC,aAAa,OAAO,eAAe;EACnC,UAAU,OAAO,YAAY;EAC7B,MAAM,OAAO,QAAQ;EACrB,UAAU,OAAO,YAAY;EAC7B,SAAS,gBAAgB,OAAO,OAAO;CAC3C;AACJ"}
1
+ {"version":3,"file":"core.mjs","names":[],"sources":["../../src/configuration.ts"],"sourcesContent":["import { basename, dirname, extname, join } from \"node:path\";\nimport type { PluralFormsLocale } from \"@let-value/translate\";\nimport { type DefaultExclude, defaultExclude, defaultExcludes } from \"./exclude.ts\";\nimport type { LogLevel } from \"./logger.ts\";\n\nimport type { ResolveArgs, UniversalPlugin } from \"./plugin.ts\";\nimport { cleanup, core, po } from \"./static.ts\";\n\nexport type DestinationFn = (args: { locale: string; entrypoint: string; path: string }) => string;\nexport type ExcludeFn = (args: ResolveArgs) => boolean;\nexport type Exclude = RegExp | ExcludeFn;\nexport type ExcludeConfig = RegExp | Exclude[] | ((defaultExclude: DefaultExclude) => Exclude[]);\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?: ExcludeConfig;\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?: UniversalPlugin[] | ((defaultPlugins: DefaultPlugins) => UniversalPlugin[]);\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 * Also matched against the specifier of an import that could not be\n * resolved, so it doubles as an ignore list for such imports — a matching\n * specifier is skipped without a warning. Bundler-virtual specifiers\n * (`virtual:…`, `\\0…`, URL schemes) are skipped without configuration.\n * @default [/node_modules/, /dist/, /build/]\n * @see Can be overridden per entrypoint via `exclude` in {@link EntrypointConfig}.\n */\n exclude?: ExcludeConfig;\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: UniversalPlugin[];\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\nfunction normalizeExclude(exclude?: RegExp | Exclude[]): Exclude[] {\n if (!exclude) return [];\n return Array.isArray(exclude) ? exclude : [exclude];\n}\n\nfunction resolveExcludes(exclude?: ExcludeConfig): Exclude[] {\n if (typeof exclude === \"function\") {\n return exclude(defaultExclude);\n }\n\n return [...defaultExcludes, ...normalizeExclude(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 {\n entrypoint,\n destination,\n obsolete,\n walk,\n exclude: exclude ? resolveExcludes(exclude) : undefined,\n };\n}\n\nfunction resolvePlugins(user?: UserConfig[\"plugins\"]): UniversalPlugin[] {\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: resolveExcludes(config.exclude),\n };\n}\n"],"mappings":";;;;AAaA,MAAM,iBAAiB;CAAE;CAAM;CAAI;AAAQ;AAkG3C,MAAM,sBAAqC,EAAE,YAAY,aACrD,KAAK,QAAQ,UAAU,GAAG,gBAAgB,GAAG,SAAS,YAAY,QAAQ,UAAU,CAAC,EAAE,GAAG,OAAO,IAAI;AAEzG,SAAS,iBAAiB,SAAyC;CAC/D,IAAI,CAAC,SAAS,OAAO,CAAC;CACtB,OAAO,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO;AACtD;AAEA,SAAS,gBAAgB,SAAoC;CACzD,IAAI,OAAO,YAAY,YACnB,OAAO,QAAQ,cAAc;CAGjC,OAAO,CAAC,GAAG,iBAAiB,GAAG,iBAAiB,OAAO,CAAC;AAC5D;AAEA,SAAS,kBAAkB,IAAmD;CAC1E,IAAI,OAAO,OAAO,UACd,OAAO,EAAE,YAAY,GAAG;CAE5B,MAAM,EAAE,YAAY,aAAa,UAAU,MAAM,YAAY;CAC7D,OAAO;EACH;EACA;EACA;EACA;EACA,SAAS,UAAU,gBAAgB,OAAO,IAAI,KAAA;CAClD;AACJ;AAEA,SAAS,eAAe,MAAiD;CACrE,IAAI,OAAO,SAAS,YAChB,OAAO,KAAK,cAAc;CAE9B,IAAI,MAAM,QAAQ,IAAI,GAClB,OAAO,CAAC,GAAG,OAAO,OAAO,cAAc,CAAC,CAAC,KAAK,WAAW,OAAO,CAAC,GAAG,GAAG,IAAI;CAE/E,OAAO,OAAO,OAAO,cAAc,CAAC,CAAC,KAAK,WAAW,OAAO,CAAC;AACjE;;;;;AAMA,SAAgB,aAAa,QAAoC;CAC7D,MAAM,gBAAgB,OAAO,iBAAiB;CAO9C,OAAO;EACH,SANY,eAAe,OAAO,OAM5B;EACN,cALQ,MAAM,QAAQ,OAAO,WAAW,IAAI,OAAO,cAAc,CAAC,OAAO,WAAW,EAAA,CAChE,IAAI,iBAId;EACV;EACA,SAAS,OAAO,WAAW,CAAC,aAAa;EACzC,aAAa,OAAO,eAAe;EACnC,UAAU,OAAO,YAAY;EAC7B,MAAM,OAAO,QAAQ;EACrB,UAAU,OAAO,YAAY;EAC7B,SAAS,gBAAgB,OAAO,OAAO;CAC3C;AACJ"}
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_run = require("../run-Bcz92fEY.cjs");
2
+ const require_run = require("../run-E1x_uibM.cjs");
3
3
  const require_src_core = require("./core.cjs");
4
4
  exports.cleanup = require_run.cleanup;
5
5
  exports.core = require_run.core;
@@ -1,4 +1,4 @@
1
- import { C as ProcessHook, E as UniversalPlugin, F as cleanup, I as Logger, M as react, N as po, P as core, S as ProcessArgs, T as SourceArgs, _ as LoadArgs, a as ExcludeFn, b as OutputsHook, c as ResolvedEntrypoint, d as Build, f as CollectedArgs, g as ImportReference, h as FileTranslations, i as ExcludeConfig, l as UserConfig, m as Context, n as EntrypointConfig, o as ObsoleteStrategy, p as CollectedHook, r as Exclude, s as ResolvedConfig, t as DestinationFn, u as defineConfig, v as LoadHook, w as ResolveArgs, x as Plugin, y as OutputsArgs } from "../configuration-DLSMbmU5.cjs";
1
+ import { C as ProcessHook, E as UniversalPlugin, F as cleanup, I as Logger, M as react, N as po, P as core, S as ProcessArgs, T as SourceArgs, _ as LoadArgs, a as ExcludeFn, b as OutputsHook, c as ResolvedEntrypoint, d as Build, f as CollectedArgs, g as ImportReference, h as FileTranslations, i as ExcludeConfig, l as UserConfig, m as Context, n as EntrypointConfig, o as ObsoleteStrategy, p as CollectedHook, r as Exclude, s as ResolvedConfig, t as DestinationFn, u as defineConfig, v as LoadHook, w as ResolveArgs, x as Plugin, y as OutputsArgs } from "../configuration-CoElcSHz.cjs";
2
2
  import "./core.cjs";
3
3
  //#region src/run.d.ts
4
4
  declare function run(entrypoint: ResolvedEntrypoint, { config, logger }: {
@@ -1,4 +1,4 @@
1
- import { C as ProcessHook, E as UniversalPlugin, F as cleanup, I as Logger, M as react, N as po, P as core, S as ProcessArgs, T as SourceArgs, _ as LoadArgs, a as ExcludeFn, b as OutputsHook, c as ResolvedEntrypoint, d as Build, f as CollectedArgs, g as ImportReference, h as FileTranslations, i as ExcludeConfig, l as UserConfig, m as Context, n as EntrypointConfig, o as ObsoleteStrategy, p as CollectedHook, r as Exclude, s as ResolvedConfig, t as DestinationFn, u as defineConfig, v as LoadHook, w as ResolveArgs, x as Plugin, y as OutputsArgs } from "../configuration-Bwtek7Fh.mjs";
1
+ import { C as ProcessHook, E as UniversalPlugin, F as cleanup, I as Logger, M as react, N as po, P as core, S as ProcessArgs, T as SourceArgs, _ as LoadArgs, a as ExcludeFn, b as OutputsHook, c as ResolvedEntrypoint, d as Build, f as CollectedArgs, g as ImportReference, h as FileTranslations, i as ExcludeConfig, l as UserConfig, m as Context, n as EntrypointConfig, o as ObsoleteStrategy, p as CollectedHook, r as Exclude, s as ResolvedConfig, t as DestinationFn, u as defineConfig, v as LoadHook, w as ResolveArgs, x as Plugin, y as OutputsArgs } from "../configuration-s7zv58Wf.mjs";
2
2
  import "./core.mjs";
3
3
  //#region src/run.d.ts
4
4
  declare function run(entrypoint: ResolvedEntrypoint, { config, logger }: {
@@ -1,3 +1,3 @@
1
1
  import { defineConfig } from "./core.mjs";
2
- import { a as cleanup, i as core, n as react, r as po, t as run } from "../run-CzeTVOug.mjs";
2
+ import { a as cleanup, i as core, n as react, r as po, t as run } from "../run-Bv_HcDXZ.mjs";
3
3
  export { cleanup, core, defineConfig, po, react, run };
@@ -1,2 +1,2 @@
1
- import { A as po, D as StaticPlugin, O as cleanup, j as react, k as core } from "../configuration-DLSMbmU5.cjs";
1
+ import { A as po, D as StaticPlugin, O as cleanup, j as react, k as core } from "../configuration-CoElcSHz.cjs";
2
2
  export { StaticPlugin, cleanup, core, po, react };
@@ -1,2 +1,2 @@
1
- import { A as po, D as StaticPlugin, O as cleanup, j as react, k as core } from "../configuration-Bwtek7Fh.mjs";
1
+ import { A as po, D as StaticPlugin, O as cleanup, j as react, k as core } from "../configuration-s7zv58Wf.mjs";
2
2
  export { StaticPlugin, cleanup, core, po, react };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@let-value/translate-extract",
3
- "version": "1.2.3",
3
+ "version": "1.2.4",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/let-value/translate"
@@ -50,13 +50,13 @@
50
50
  "plural-forms": "0.5.5",
51
51
  "tree-sitter-javascript": "0.25.0",
52
52
  "tree-sitter-typescript": "0.23.2",
53
- "@let-value/translate": "1.2.3"
53
+ "@let-value/translate": "1.2.4"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@types/gettext-parser": "9.0.0",
57
57
  "typescript": "6.0.3",
58
58
  "vite-plus": "latest",
59
- "@let-value/graph": "1.2.3"
59
+ "@let-value/graph": "1.2.4"
60
60
  },
61
61
  "scripts": {
62
62
  "build": "vp pack",