@let-value/translate-extract 1.0.7 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/cli.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const require_run = require('../run-DmgUA6g-.cjs');
2
+ const require_run = require('../run-BbCR8HKr.cjs');
3
3
  let node_util = require("node:util");
4
4
  node_util = require_run.__toESM(node_util);
5
5
  let cosmiconfig = require("cosmiconfig");
package/dist/bin/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { run } from "../run-CDoyE55S.js";
2
+ import { run } from "../run-B5wkuAcc.js";
3
3
  import { parseArgs } from "node:util";
4
4
  import { cosmiconfig } from "cosmiconfig";
5
5
  import pino from "pino";
@@ -13,7 +13,7 @@ async function run(entrypoint, { locale, config, logger }) {
13
13
  locale
14
14
  }, "starting extraction");
15
15
  const context = {
16
- entry: entrypoint,
16
+ entrypoint,
17
17
  config: {
18
18
  ...config,
19
19
  destination,
@@ -80,10 +80,7 @@ async function run(entrypoint, { locale, config, logger }) {
80
80
  entrypoint: entrypoint$1,
81
81
  path
82
82
  }, context);
83
- if (result$1) logger?.debug({
84
- entrypoint: entrypoint$1,
85
- path
86
- }, "resolved");
83
+ if (result$1) logger?.debug(result$1, "resolved");
87
84
  if (result$1) return result$1;
88
85
  }
89
86
  return void 0;
@@ -179,4 +176,4 @@ async function run(entrypoint, { locale, config, logger }) {
179
176
 
180
177
  //#endregion
181
178
  export { run };
182
- //# sourceMappingURL=run-CDoyE55S.js.map
179
+ //# sourceMappingURL=run-B5wkuAcc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-B5wkuAcc.js","names":["queue: ResolveArgs[]","context: ExtractContext","resolves: { filter: RegExp; hook: ResolveHook }[]","loads: { filter: RegExp; hook: LoadHook }[]","extracts: { filter: RegExp; hook: ExtractHook }[]","collects: { filter: RegExp; hook: CollectHook }[]","generates: { filter: RegExp; hook: GenerateHook }[]","build: ExtractBuild","results: ExtractResult[]","result","destination","result: Record<string, CollectResult[]>"],"sources":["../src/run.ts"],"sourcesContent":["import type { ResolvedConfig } from \"./configuration.ts\";\nimport type { Logger } from \"./logger.ts\";\nimport type {\n CollectArgs,\n CollectHook,\n CollectResult,\n ExtractArgs,\n ExtractBuild,\n ExtractContext,\n ExtractHook,\n ExtractResult,\n GenerateHook,\n LoadArgs,\n LoadHook,\n LoadResult,\n ResolveArgs,\n ResolveHook,\n ResolveResult,\n} from \"./plugin.ts\";\n\nexport async function run(\n entrypoint: string,\n { locale, config, logger }: { locale: string; config: ResolvedConfig; logger?: Logger },\n) {\n const entryConfig = config.entrypoints.find((e) => e.entrypoint === entrypoint);\n const destination = entryConfig?.destination ?? config.destination;\n const obsolete = entryConfig?.obsolete ?? config.obsolete;\n const exclude = entryConfig?.exclude ?? config.exclude;\n\n const queue: ResolveArgs[] = [{ entrypoint, path: entrypoint }];\n\n logger?.info({ entrypoint, locale }, \"starting extraction\");\n\n const context: ExtractContext = {\n entrypoint,\n config: { ...config, destination, obsolete, exclude },\n generatedAt: new Date(),\n locale,\n logger,\n };\n\n const resolves: { filter: RegExp; hook: ResolveHook }[] = [];\n const loads: { filter: RegExp; hook: LoadHook }[] = [];\n const extracts: { filter: RegExp; hook: ExtractHook }[] = [];\n const collects: { filter: RegExp; hook: CollectHook }[] = [];\n const generates: { filter: RegExp; hook: GenerateHook }[] = [];\n\n function resolvePath(args: ResolveArgs) {\n for (const ex of context.config.exclude) {\n if (ex instanceof RegExp ? ex.test(args.path) : ex(args.path)) {\n return;\n }\n }\n if (context.config.walk) {\n queue.push(args);\n }\n }\n\n const build: ExtractBuild = {\n onResolve({ filter }, hook) {\n resolves.push({ filter, hook });\n },\n onLoad({ filter }, hook) {\n loads.push({ filter, hook });\n },\n onExtract({ filter }, hook) {\n extracts.push({ filter, hook });\n },\n onCollect({ filter }, hook) {\n collects.push({ filter, hook });\n },\n onGenerate({ filter }, hook) {\n generates.push({ filter, hook });\n },\n resolvePath,\n context,\n };\n\n for (const plugin of config.plugins) {\n logger?.debug({ plugin: plugin.name }, \"setting up plugin\");\n plugin.setup(build);\n }\n\n const visited = new Set<string>();\n const results: ExtractResult[] = [];\n\n async function applyResolve({ entrypoint, path }: ResolveArgs): Promise<ResolveResult | undefined> {\n for (const { filter, hook } of resolves) {\n if (!filter.test(path)) continue;\n const result = await hook({ entrypoint, path }, context);\n if (result) {\n logger?.debug(result, \"resolved\");\n }\n if (result) return result;\n }\n return undefined;\n }\n\n async function applyLoad({ entrypoint, path }: LoadArgs): Promise<LoadResult | undefined> {\n for (const { filter, hook } of loads) {\n if (!filter.test(path)) continue;\n const result = await hook({ entrypoint, path }, context);\n if (result) {\n logger?.debug({ entrypoint, path }, \"loaded\");\n }\n if (result) return result;\n }\n return undefined;\n }\n\n async function applyExtract({ entrypoint, path, contents }: ExtractArgs): Promise<ExtractResult | undefined> {\n for (const { filter, hook } of extracts) {\n if (!filter.test(path)) continue;\n const result = await hook({ entrypoint, path, contents }, context);\n if (result) {\n logger?.debug({ entrypoint, path }, \"extracted\");\n }\n if (result) return result;\n }\n return undefined;\n }\n\n async function applyCollect({\n entrypoint,\n path,\n translations,\n destination,\n }: CollectArgs): Promise<CollectResult | undefined> {\n for (const { filter, hook } of collects) {\n if (!filter.test(path)) continue;\n const result = await hook({ entrypoint, path, translations, destination }, context);\n if (result) {\n logger?.debug(\n {\n entrypoint,\n path,\n destination,\n ...(destination !== result.destination && { redirected: result.destination }),\n },\n \"collected\",\n );\n }\n if (result) return result;\n }\n return undefined;\n }\n\n const result: Record<string, CollectResult[]> = {};\n\n while (queue.length) {\n // biome-ignore lint/style/noNonNullAssertion: queue is checked above\n const args = queue.shift()!;\n const resolved = await applyResolve(args);\n if (!resolved || visited.has(resolved.path)) continue;\n visited.add(resolved.path);\n\n const loaded = await applyLoad(resolved);\n if (!loaded) continue;\n\n const extracted = await applyExtract(loaded);\n if (!extracted) continue;\n\n const destination = context.config.destination({ entrypoint, locale, path: resolved.path });\n const collected = await applyCollect({ ...extracted, destination });\n if (!collected) continue;\n\n if (!result[collected.destination]) {\n result[collected.destination] = [];\n }\n\n result[collected.destination].push(collected);\n }\n\n for (const [path, collected] of Object.entries(result)) {\n for (const { filter, hook } of generates) {\n if (!filter.test(path)) continue;\n logger?.info({ path }, \"generating output\");\n await hook({ entrypoint, path, collected }, context);\n }\n }\n\n logger?.info({ entrypoint, locale }, \"extraction completed\");\n return results;\n}\n"],"mappings":"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"}
@@ -37,7 +37,7 @@ async function run(entrypoint, { locale, config, logger }) {
37
37
  locale
38
38
  }, "starting extraction");
39
39
  const context = {
40
- entry: entrypoint,
40
+ entrypoint,
41
41
  config: {
42
42
  ...config,
43
43
  destination,
@@ -104,10 +104,7 @@ async function run(entrypoint, { locale, config, logger }) {
104
104
  entrypoint: entrypoint$1,
105
105
  path
106
106
  }, context);
107
- if (result$1) logger?.debug({
108
- entrypoint: entrypoint$1,
109
- path
110
- }, "resolved");
107
+ if (result$1) logger?.debug(result$1, "resolved");
111
108
  if (result$1) return result$1;
112
109
  }
113
110
  return void 0;
@@ -1,4 +1,4 @@
1
- const require_run = require('../run-DmgUA6g-.cjs');
1
+ const require_run = require('../run-BbCR8HKr.cjs');
2
2
  let node_path = require("node:path");
3
3
  node_path = require_run.__toESM(node_path);
4
4
  let glob = require("glob");
@@ -663,7 +663,7 @@ function po() {
663
663
  translations: record
664
664
  };
665
665
  });
666
- build.onGenerate({ filter: /.*\/po$/ }, async ({ path: path$1, collected }, ctx) => {
666
+ build.onGenerate({ filter: /\.po$/ }, async ({ path: path$1, collected }, ctx) => {
667
667
  const existing = await node_fs_promises.default.readFile(path$1).catch(() => void 0);
668
668
  const out = merge(collected, existing, ctx.config.obsolete, ctx.locale, ctx.generatedAt);
669
669
  await node_fs_promises.default.mkdir((0, node_path.dirname)(path$1), { recursive: true });
@@ -4,7 +4,7 @@ import { GetTextTranslationRecord } from "gettext-parser";
4
4
  //#region src/plugin.d.ts
5
5
  type MaybePromise<T> = T | Promise<T>;
6
6
  interface ExtractContext {
7
- entry: string;
7
+ entrypoint: string;
8
8
  config: ResolvedConfig;
9
9
  generatedAt: Date;
10
10
  locale: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../../../../src/plugin.ts","../../../../src/plugins/core/core.ts","../../../../src/plugins/core/queries/types.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/plugin.ts","../../../../src/plugins/core/core.ts","../../../../src/plugins/core/queries/types.ts","../../../../src/plugins/po/po.ts","../../../../src/configuration.ts","../../../../src/plugins/react/react.ts","../../../../src/run.ts"],"sourcesContent":[],"mappings":"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"}
@@ -5,7 +5,7 @@ import { GetTextTranslationRecord } from "gettext-parser";
5
5
  //#region src/plugin.d.ts
6
6
  type MaybePromise<T> = T | Promise<T>;
7
7
  interface ExtractContext {
8
- entry: string;
8
+ entrypoint: string;
9
9
  config: ResolvedConfig;
10
10
  generatedAt: Date;
11
11
  locale: string;
package/dist/src/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { run } from "../run-CDoyE55S.js";
1
+ import { run } from "../run-B5wkuAcc.js";
2
2
  import path, { basename, dirname, extname, join, relative, resolve } from "node:path";
3
3
  import { globSync } from "glob";
4
4
  import fs, { readFile } from "node:fs/promises";
@@ -652,7 +652,7 @@ function po() {
652
652
  translations: record
653
653
  };
654
654
  });
655
- build.onGenerate({ filter: /.*\/po$/ }, async ({ path: path$1, collected }, ctx) => {
655
+ build.onGenerate({ filter: /\.po$/ }, async ({ path: path$1, collected }, ctx) => {
656
656
  const existing = await fs.readFile(path$1).catch(() => void 0);
657
657
  const out = merge(collected, existing, ctx.config.obsolete, ctx.locale, ctx.generatedAt);
658
658
  await fs.mkdir(dirname(path$1), { recursive: true });
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["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","getCachedParser","path","parseSource","context: Context","translations: Translation[]","imports: string[]","fs","resolved: string[]","filter","path","parseSource","translations: GetTextTranslationRecord","headers: Record<string, string>","translations","poObj: GetTextTranslations","path","defaultDestination: DestinationFn","defaultExclude: Exclude[]","plugins: ExtractorPlugin[]","entrypoints: ResolvedEntrypoint[]","path","exclude","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[]","imports: string[]","coreQueries","reactQueries","path"],"sources":["../../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 { 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 col = node.startPosition.column + 1;\n const rel = relative(process.cwd(), path);\n return `${rel}:${line}:${col}`;\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 { memo } from \"radash\";\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 } from \"./queries/types.ts\";\n\nexport interface ParseResult {\n translations: Translation[];\n imports: string[];\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 getCachedParser = memo(function getCachedParser(ext: string) {\n const parser = new Parser();\n const language = getLanguage(ext) as Parser.Language;\n parser.setLanguage(language);\n\n return { parser, language };\n});\n\nexport function getParser(path: string) {\n const ext = extname(path);\n return getCachedParser(ext);\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 imports: string[] = [];\n\n const seen = new Set<number>();\n\n for (const spec of queries) {\n const query = new Parser.Query(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 console.warn(`Parsing error at ${reference}: ${error}`);\n }\n }\n }\n\n const importTreeQuery = new Parser.Query(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 };\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\";\nimport type { ExtractorPlugin } from \"../../plugin.ts\";\nimport { parseSource } from \"./parse.ts\";\nimport { resolveImports } from \"./resolve.ts\";\n\nconst filter = /\\.([cm]?tsx?|jsx?)$/;\n\nexport function core(): ExtractorPlugin {\n return {\n name: \"core\",\n setup(build) {\n build.context.logger?.debug(\"core plugin initialized\");\n build.onResolve({ filter: /.*/ }, ({ entrypoint, path }) => {\n return {\n entrypoint,\n path: resolve(path),\n };\n });\n build.onLoad({ filter }, async ({ entrypoint, path }) => {\n const contents = await readFile(path, \"utf8\");\n return { entrypoint, path, contents };\n });\n build.onExtract({ filter }, ({ entrypoint, path, contents }) => {\n const { translations, imports } = parseSource(contents, path);\n if (build.context.config.walk) {\n const paths = resolveImports(path, imports);\n for (const path of paths) {\n build.resolvePath({\n entrypoint,\n path,\n });\n }\n }\n return {\n entrypoint,\n path,\n translations,\n };\n });\n },\n } satisfies ExtractorPlugin;\n}\n","import fs from \"node:fs/promises\";\nimport { basename, dirname, extname, join } from \"node:path\";\nimport type { GetTextTranslationRecord, GetTextTranslations } from \"gettext-parser\";\nimport * as gettextParser from \"gettext-parser\";\nimport { getFormula, getNPlurals } from \"plural-forms\";\nimport { assign } from \"radash\";\nimport type { ObsoleteStrategy } from \"../../configuration.ts\";\nimport type { CollectResult, ExtractContext, ExtractorPlugin, GenerateArgs } from \"../../plugin.ts\";\nimport type { Translation } from \"../core/queries/types.ts\";\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 translations[ctx][id] = {\n msgctxt: context || undefined,\n msgid: id,\n msgid_plural: plural,\n msgstr: Array.from({ length }, () => \"\"),\n comments: comments,\n obsolete: obsolete,\n };\n }\n\n return translations;\n}\n\nexport function merge(\n sources: CollectResult[],\n existing: string | Buffer | undefined,\n obsolete: ObsoleteStrategy,\n locale: string,\n generatedAt: Date,\n): string {\n let headers: Record<string, string> = {};\n let translations: GetTextTranslationRecord = { \"\": {} };\n const nplurals = getNPlurals(locale);\n\n if (existing) {\n const parsed = gettextParser.po.parse(existing);\n headers = parsed.headers || {};\n translations = parsed.translations || { \"\": {} };\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 = sources.reduce((acc, { translations }) => assign(acc, translations as GetTextTranslationRecord), {\n \"\": {},\n } as GetTextTranslationRecord);\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];\n if (existingEntry) {\n entry.msgstr = existingEntry.msgstr;\n entry.comments = {\n ...entry.comments,\n translator: existingEntry.comments?.translator,\n };\n }\n entry.obsolete = false;\n entry.msgstr = entry.msgstr.slice(0, nplurals);\n while (entry.msgstr.length < nplurals) entry.msgstr.push(\"\");\n translations[ctx][id] = entry;\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 if (obsolete === \"remove\") {\n for (const ctx of Object.keys(translations)) {\n for (const id of Object.keys(translations[ctx])) {\n if (translations[ctx][id].obsolete) {\n delete translations[ctx][id];\n }\n }\n }\n }\n\n const poObj: GetTextTranslations = {\n charset: \"utf-8\",\n headers,\n translations,\n };\n\n return gettextParser.po.compile(poObj).toString();\n}\n\nexport function po(): ExtractorPlugin {\n return {\n name: \"po\",\n setup(build) {\n build.context.logger?.debug(\"po plugin initialized\");\n build.onCollect({ filter: /.*/ }, ({ entrypoint, translations, destination, ...rest }, ctx) => {\n const record = collect(translations as Translation[], ctx.locale);\n const redirected = join(dirname(destination), `${basename(destination, extname(destination))}.po`);\n\n return {\n ...rest,\n entrypoint,\n destination: redirected,\n translations: record,\n };\n });\n build.onGenerate({ filter: /.*\\/po$/ }, async ({ path, collected }: GenerateArgs, ctx: ExtractContext) => {\n const existing = await fs.readFile(path).catch(() => undefined);\n const out = merge(collected, existing, ctx.config.obsolete, ctx.locale, ctx.generatedAt);\n await fs.mkdir(dirname(path), { recursive: true });\n await fs.writeFile(path, out);\n });\n },\n };\n}\n","import { basename, dirname, extname, join } from \"node:path\";\nimport { globSync } from \"glob\";\nimport type { LevelWithSilent } from \"pino\";\nimport type { ExtractorPlugin } from \"./plugin.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 = (path: string) => boolean;\nexport type Exclude = RegExp | ExcludeFn;\n\nconst defaultPlugins = { core, po };\ntype DefaultPlugins = typeof defaultPlugins;\n\nexport type ObsoleteStrategy = \"mark\" | \"remove\";\n\nexport interface EntrypointConfig {\n entrypoint: string;\n destination?: DestinationFn;\n obsolete?: ObsoleteStrategy;\n exclude?: Exclude | Exclude[];\n}\n\nexport interface UserConfig {\n plugins?: ExtractorPlugin[] | ((defaultPlugins: DefaultPlugins) => ExtractorPlugin[]);\n entrypoints: string | EntrypointConfig | Array<string | EntrypointConfig>;\n defaultLocale?: string;\n locales?: string[];\n destination?: DestinationFn;\n obsolete?: ObsoleteStrategy;\n walk?: boolean;\n logLevel?: LevelWithSilent;\n exclude?: Exclude | Exclude[];\n}\n\nexport interface ResolvedEntrypoint extends Omit<EntrypointConfig, \"exclude\"> {\n exclude?: Exclude[];\n}\n\nexport interface ResolvedConfig {\n plugins: ExtractorPlugin[];\n entrypoints: ResolvedEntrypoint[];\n defaultLocale: string;\n locales: string[];\n destination: DestinationFn;\n obsolete: ObsoleteStrategy;\n walk: boolean;\n logLevel: LevelWithSilent;\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\nexport function defineConfig(config: UserConfig): ResolvedConfig {\n let plugins: ExtractorPlugin[];\n const user = config.plugins;\n if (typeof user === \"function\") {\n plugins = user(defaultPlugins);\n } else if (Array.isArray(user)) {\n plugins = [...Object.values(defaultPlugins).map((plugin) => plugin()), ...user];\n } else {\n plugins = Object.values(defaultPlugins).map((plugin) => plugin());\n }\n\n const raw = Array.isArray(config.entrypoints) ? config.entrypoints : [config.entrypoints];\n const entrypoints: ResolvedEntrypoint[] = [];\n for (const ep of raw) {\n if (typeof ep === \"string\") {\n const paths = globSync(ep, { nodir: true });\n if (paths.length === 0) {\n entrypoints.push({ entrypoint: ep });\n } else {\n for (const path of paths) entrypoints.push({ entrypoint: path });\n }\n } else {\n const { entrypoint, destination, obsolete, exclude } = ep;\n const paths = globSync(entrypoint, { nodir: true });\n const epExclude = exclude ? [...defaultExclude, ...normalizeExclude(exclude)] : undefined;\n if (paths.length === 0) {\n entrypoints.push({ entrypoint, destination, obsolete, exclude: epExclude });\n } else {\n for (const path of paths)\n entrypoints.push({ entrypoint: path, destination, obsolete, exclude: epExclude });\n }\n }\n }\n\n const defaultLocale = config.defaultLocale ?? \"en\";\n const locales = config.locales ?? [defaultLocale];\n const destination = config.destination ?? defaultDestination;\n const obsolete = config.obsolete ?? \"mark\";\n const walk = config.walk ?? true;\n const logLevel = config.logLevel ?? \"info\";\n const exclude = [...defaultExclude, ...normalizeExclude(config.exclude)];\n return { plugins, entrypoints, defaultLocale, locales, destination, obsolete, walk, logLevel, exclude };\n}\n","import type Parser from \"tree-sitter\";\n\nexport function buildTemplate(node: Parser.SyntaxNode): { text: string; error?: string } {\n const children = node.namedChildren.slice(1, -1);\n const strings: string[] = [\"\"];\n const values: string[] = [];\n for (const child of children) {\n if (child.type === \"jsx_text\") {\n strings[strings.length - 1] += child.text;\n } else if (child.type === \"jsx_expression\") {\n const expr = child.namedChildren[0];\n if (!expr || expr.type !== \"identifier\") {\n return { text: \"\", error: \"JSX expressions must be simple identifiers\" };\n }\n values.push(expr.text);\n strings.push(\"\");\n } else if (child.type === \"string\") {\n strings[strings.length - 1] += child.text.slice(1, -1);\n } else {\n return { text: \"\", error: \"Unsupported JSX child\" };\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 || expr.type !== \"identifier\") {\n return { text: \"\", error: \"JSX expressions must be simple identifiers\" };\n }\n return { text: `\\${${expr.text}}` };\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))\n (jsx_self_closing_element name: (identifier) @name)\n ] @call\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 Parser from \"tree-sitter\";\n\nimport { getParser } from \"../core/parse.ts\";\nimport { getReference } from \"../core/queries/comment.ts\";\nimport { importQuery } from \"../core/queries/import.ts\";\nimport { queries as coreQueries } from \"../core/queries/index.ts\";\nimport type { Context, Translation } from \"../core/queries/types.ts\";\nimport { queries as reactQueries } from \"./queries/index.ts\";\n\nexport interface ParseResult {\n translations: Translation[];\n imports: string[];\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 imports: string[] = [];\n const seen = new Set<number>();\n\n for (const spec of [...coreQueries, ...reactQueries]) {\n const query = new Parser.Query(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 console.warn(`Parsing error at ${reference}: ${error}`);\n }\n }\n }\n\n const importTreeQuery = new Parser.Query(language, importQuery.pattern);\n for (const match of importTreeQuery.matches(tree.rootNode)) {\n const imp = importQuery.extract(match);\n if (imp) imports.push(imp);\n }\n\n return { translations, imports };\n}\n","import { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nimport type { ExtractorPlugin } from \"../../plugin.ts\";\nimport { resolveImports } from \"../core/resolve.ts\";\nimport { parseSource } from \"./parse.ts\";\n\nconst filter = /\\.[cm]?[jt]sx$/;\n\nexport function react(): ExtractorPlugin {\n return {\n name: \"react\",\n setup(build) {\n build.context.logger?.debug(\"react plugin initialized\");\n build.onResolve({ filter: /.*/ }, ({ entrypoint, path }) => {\n return {\n entrypoint,\n path: resolve(path),\n };\n });\n build.onLoad({ filter }, async ({ entrypoint, path }) => {\n const contents = await readFile(path, \"utf8\");\n return { entrypoint, path, contents };\n });\n build.onExtract({ filter }, ({ entrypoint, path, contents }) => {\n const { translations, imports } = parseSource(contents, path);\n if (build.context.config.walk) {\n const paths = resolveImports(path, imports);\n for (const p of paths) {\n build.resolvePath({ entrypoint, path: p });\n }\n }\n return {\n entrypoint,\n path,\n translations,\n };\n });\n },\n } satisfies ExtractorPlugin;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["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","getCachedParser","path","parseSource","context: Context","translations: Translation[]","imports: string[]","fs","resolved: string[]","filter","path","parseSource","translations: GetTextTranslationRecord","headers: Record<string, string>","translations","poObj: GetTextTranslations","path","defaultDestination: DestinationFn","defaultExclude: Exclude[]","plugins: ExtractorPlugin[]","entrypoints: ResolvedEntrypoint[]","path","exclude","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[]","imports: string[]","coreQueries","reactQueries","path"],"sources":["../../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 { 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 col = node.startPosition.column + 1;\n const rel = relative(process.cwd(), path);\n return `${rel}:${line}:${col}`;\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 { memo } from \"radash\";\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 } from \"./queries/types.ts\";\n\nexport interface ParseResult {\n translations: Translation[];\n imports: string[];\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 getCachedParser = memo(function getCachedParser(ext: string) {\n const parser = new Parser();\n const language = getLanguage(ext) as Parser.Language;\n parser.setLanguage(language);\n\n return { parser, language };\n});\n\nexport function getParser(path: string) {\n const ext = extname(path);\n return getCachedParser(ext);\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 imports: string[] = [];\n\n const seen = new Set<number>();\n\n for (const spec of queries) {\n const query = new Parser.Query(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 console.warn(`Parsing error at ${reference}: ${error}`);\n }\n }\n }\n\n const importTreeQuery = new Parser.Query(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 };\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\";\nimport type { ExtractorPlugin } from \"../../plugin.ts\";\nimport { parseSource } from \"./parse.ts\";\nimport { resolveImports } from \"./resolve.ts\";\n\nconst filter = /\\.([cm]?tsx?|jsx?)$/;\n\nexport function core(): ExtractorPlugin {\n return {\n name: \"core\",\n setup(build) {\n build.context.logger?.debug(\"core plugin initialized\");\n build.onResolve({ filter: /.*/ }, ({ entrypoint, path }) => {\n return {\n entrypoint,\n path: resolve(path),\n };\n });\n build.onLoad({ filter }, async ({ entrypoint, path }) => {\n const contents = await readFile(path, \"utf8\");\n return { entrypoint, path, contents };\n });\n build.onExtract({ filter }, ({ entrypoint, path, contents }) => {\n const { translations, imports } = parseSource(contents, path);\n if (build.context.config.walk) {\n const paths = resolveImports(path, imports);\n for (const path of paths) {\n build.resolvePath({\n entrypoint,\n path,\n });\n }\n }\n return {\n entrypoint,\n path,\n translations,\n };\n });\n },\n } satisfies ExtractorPlugin;\n}\n","import fs from \"node:fs/promises\";\nimport { basename, dirname, extname, join } from \"node:path\";\nimport type { GetTextTranslationRecord, GetTextTranslations } from \"gettext-parser\";\nimport * as gettextParser from \"gettext-parser\";\nimport { getFormula, getNPlurals } from \"plural-forms\";\nimport { assign } from \"radash\";\nimport type { ObsoleteStrategy } from \"../../configuration.ts\";\nimport type { CollectResult, ExtractContext, ExtractorPlugin, GenerateArgs } from \"../../plugin.ts\";\nimport type { Translation } from \"../core/queries/types.ts\";\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 translations[ctx][id] = {\n msgctxt: context || undefined,\n msgid: id,\n msgid_plural: plural,\n msgstr: Array.from({ length }, () => \"\"),\n comments: comments,\n obsolete: obsolete,\n };\n }\n\n return translations;\n}\n\nexport function merge(\n sources: CollectResult[],\n existing: string | Buffer | undefined,\n obsolete: ObsoleteStrategy,\n locale: string,\n generatedAt: Date,\n): string {\n let headers: Record<string, string> = {};\n let translations: GetTextTranslationRecord = { \"\": {} };\n const nplurals = getNPlurals(locale);\n\n if (existing) {\n const parsed = gettextParser.po.parse(existing);\n headers = parsed.headers || {};\n translations = parsed.translations || { \"\": {} };\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 = sources.reduce((acc, { translations }) => assign(acc, translations as GetTextTranslationRecord), {\n \"\": {},\n } as GetTextTranslationRecord);\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];\n if (existingEntry) {\n entry.msgstr = existingEntry.msgstr;\n entry.comments = {\n ...entry.comments,\n translator: existingEntry.comments?.translator,\n };\n }\n entry.obsolete = false;\n entry.msgstr = entry.msgstr.slice(0, nplurals);\n while (entry.msgstr.length < nplurals) entry.msgstr.push(\"\");\n translations[ctx][id] = entry;\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 if (obsolete === \"remove\") {\n for (const ctx of Object.keys(translations)) {\n for (const id of Object.keys(translations[ctx])) {\n if (translations[ctx][id].obsolete) {\n delete translations[ctx][id];\n }\n }\n }\n }\n\n const poObj: GetTextTranslations = {\n charset: \"utf-8\",\n headers,\n translations,\n };\n\n return gettextParser.po.compile(poObj).toString();\n}\n\nexport function po(): ExtractorPlugin {\n return {\n name: \"po\",\n setup(build) {\n build.context.logger?.debug(\"po plugin initialized\");\n build.onCollect({ filter: /.*/ }, ({ entrypoint, translations, destination, ...rest }, ctx) => {\n const record = collect(translations as Translation[], ctx.locale);\n const redirected = join(dirname(destination), `${basename(destination, extname(destination))}.po`);\n\n return {\n ...rest,\n entrypoint,\n destination: redirected,\n translations: record,\n };\n });\n build.onGenerate({ filter: /\\.po$/ }, async ({ path, collected }: GenerateArgs, ctx: ExtractContext) => {\n const existing = await fs.readFile(path).catch(() => undefined);\n const out = merge(collected, existing, ctx.config.obsolete, ctx.locale, ctx.generatedAt);\n await fs.mkdir(dirname(path), { recursive: true });\n await fs.writeFile(path, out);\n });\n },\n };\n}\n","import { basename, dirname, extname, join } from \"node:path\";\nimport { globSync } from \"glob\";\nimport type { LevelWithSilent } from \"pino\";\nimport type { ExtractorPlugin } from \"./plugin.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 = (path: string) => boolean;\nexport type Exclude = RegExp | ExcludeFn;\n\nconst defaultPlugins = { core, po };\ntype DefaultPlugins = typeof defaultPlugins;\n\nexport type ObsoleteStrategy = \"mark\" | \"remove\";\n\nexport interface EntrypointConfig {\n entrypoint: string;\n destination?: DestinationFn;\n obsolete?: ObsoleteStrategy;\n exclude?: Exclude | Exclude[];\n}\n\nexport interface UserConfig {\n plugins?: ExtractorPlugin[] | ((defaultPlugins: DefaultPlugins) => ExtractorPlugin[]);\n entrypoints: string | EntrypointConfig | Array<string | EntrypointConfig>;\n defaultLocale?: string;\n locales?: string[];\n destination?: DestinationFn;\n obsolete?: ObsoleteStrategy;\n walk?: boolean;\n logLevel?: LevelWithSilent;\n exclude?: Exclude | Exclude[];\n}\n\nexport interface ResolvedEntrypoint extends Omit<EntrypointConfig, \"exclude\"> {\n exclude?: Exclude[];\n}\n\nexport interface ResolvedConfig {\n plugins: ExtractorPlugin[];\n entrypoints: ResolvedEntrypoint[];\n defaultLocale: string;\n locales: string[];\n destination: DestinationFn;\n obsolete: ObsoleteStrategy;\n walk: boolean;\n logLevel: LevelWithSilent;\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\nexport function defineConfig(config: UserConfig): ResolvedConfig {\n let plugins: ExtractorPlugin[];\n const user = config.plugins;\n if (typeof user === \"function\") {\n plugins = user(defaultPlugins);\n } else if (Array.isArray(user)) {\n plugins = [...Object.values(defaultPlugins).map((plugin) => plugin()), ...user];\n } else {\n plugins = Object.values(defaultPlugins).map((plugin) => plugin());\n }\n\n const raw = Array.isArray(config.entrypoints) ? config.entrypoints : [config.entrypoints];\n const entrypoints: ResolvedEntrypoint[] = [];\n for (const ep of raw) {\n if (typeof ep === \"string\") {\n const paths = globSync(ep, { nodir: true });\n if (paths.length === 0) {\n entrypoints.push({ entrypoint: ep });\n } else {\n for (const path of paths) entrypoints.push({ entrypoint: path });\n }\n } else {\n const { entrypoint, destination, obsolete, exclude } = ep;\n const paths = globSync(entrypoint, { nodir: true });\n const epExclude = exclude ? [...defaultExclude, ...normalizeExclude(exclude)] : undefined;\n if (paths.length === 0) {\n entrypoints.push({ entrypoint, destination, obsolete, exclude: epExclude });\n } else {\n for (const path of paths)\n entrypoints.push({ entrypoint: path, destination, obsolete, exclude: epExclude });\n }\n }\n }\n\n const defaultLocale = config.defaultLocale ?? \"en\";\n const locales = config.locales ?? [defaultLocale];\n const destination = config.destination ?? defaultDestination;\n const obsolete = config.obsolete ?? \"mark\";\n const walk = config.walk ?? true;\n const logLevel = config.logLevel ?? \"info\";\n const exclude = [...defaultExclude, ...normalizeExclude(config.exclude)];\n return { plugins, entrypoints, defaultLocale, locales, destination, obsolete, walk, logLevel, exclude };\n}\n","import type Parser from \"tree-sitter\";\n\nexport function buildTemplate(node: Parser.SyntaxNode): { text: string; error?: string } {\n const children = node.namedChildren.slice(1, -1);\n const strings: string[] = [\"\"];\n const values: string[] = [];\n for (const child of children) {\n if (child.type === \"jsx_text\") {\n strings[strings.length - 1] += child.text;\n } else if (child.type === \"jsx_expression\") {\n const expr = child.namedChildren[0];\n if (!expr || expr.type !== \"identifier\") {\n return { text: \"\", error: \"JSX expressions must be simple identifiers\" };\n }\n values.push(expr.text);\n strings.push(\"\");\n } else if (child.type === \"string\") {\n strings[strings.length - 1] += child.text.slice(1, -1);\n } else {\n return { text: \"\", error: \"Unsupported JSX child\" };\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 || expr.type !== \"identifier\") {\n return { text: \"\", error: \"JSX expressions must be simple identifiers\" };\n }\n return { text: `\\${${expr.text}}` };\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))\n (jsx_self_closing_element name: (identifier) @name)\n ] @call\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 Parser from \"tree-sitter\";\n\nimport { getParser } from \"../core/parse.ts\";\nimport { getReference } from \"../core/queries/comment.ts\";\nimport { importQuery } from \"../core/queries/import.ts\";\nimport { queries as coreQueries } from \"../core/queries/index.ts\";\nimport type { Context, Translation } from \"../core/queries/types.ts\";\nimport { queries as reactQueries } from \"./queries/index.ts\";\n\nexport interface ParseResult {\n translations: Translation[];\n imports: string[];\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 imports: string[] = [];\n const seen = new Set<number>();\n\n for (const spec of [...coreQueries, ...reactQueries]) {\n const query = new Parser.Query(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 console.warn(`Parsing error at ${reference}: ${error}`);\n }\n }\n }\n\n const importTreeQuery = new Parser.Query(language, importQuery.pattern);\n for (const match of importTreeQuery.matches(tree.rootNode)) {\n const imp = importQuery.extract(match);\n if (imp) imports.push(imp);\n }\n\n return { translations, imports };\n}\n","import { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nimport type { ExtractorPlugin } from \"../../plugin.ts\";\nimport { resolveImports } from \"../core/resolve.ts\";\nimport { parseSource } from \"./parse.ts\";\n\nconst filter = /\\.[cm]?[jt]sx$/;\n\nexport function react(): ExtractorPlugin {\n return {\n name: \"react\",\n setup(build) {\n build.context.logger?.debug(\"react plugin initialized\");\n build.onResolve({ filter: /.*/ }, ({ entrypoint, path }) => {\n return {\n entrypoint,\n path: resolve(path),\n };\n });\n build.onLoad({ filter }, async ({ entrypoint, path }) => {\n const contents = await readFile(path, \"utf8\");\n return { entrypoint, path, contents };\n });\n build.onExtract({ filter }, ({ entrypoint, path, contents }) => {\n const { translations, imports } = parseSource(contents, path);\n if (build.context.config.walk) {\n const paths = resolveImports(path, imports);\n for (const p of paths) {\n build.resolvePath({ entrypoint, path: p });\n }\n }\n return {\n entrypoint,\n path,\n translations,\n };\n });\n },\n } satisfies ExtractorPlugin;\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.7",
3
+ "version": "1.0.8",
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.7",
23
+ "@let-value/translate": "1.0.8",
24
24
  "gettext-parser": "8.0.0",
25
25
  "oxc-resolver": "11.7.1",
26
26
  "plural-forms": "0.5.5",
@@ -1 +0,0 @@
1
- {"version":3,"file":"run-CDoyE55S.js","names":["queue: ResolveArgs[]","context: ExtractContext","resolves: { filter: RegExp; hook: ResolveHook }[]","loads: { filter: RegExp; hook: LoadHook }[]","extracts: { filter: RegExp; hook: ExtractHook }[]","collects: { filter: RegExp; hook: CollectHook }[]","generates: { filter: RegExp; hook: GenerateHook }[]","build: ExtractBuild","results: ExtractResult[]","result","destination","result: Record<string, CollectResult[]>"],"sources":["../src/run.ts"],"sourcesContent":["import type { ResolvedConfig } from \"./configuration.ts\";\nimport type { Logger } from \"./logger.ts\";\nimport type {\n CollectArgs,\n CollectHook,\n CollectResult,\n ExtractArgs,\n ExtractBuild,\n ExtractContext,\n ExtractHook,\n ExtractResult,\n GenerateHook,\n LoadArgs,\n LoadHook,\n LoadResult,\n ResolveArgs,\n ResolveHook,\n ResolveResult,\n} from \"./plugin.ts\";\n\nexport async function run(\n entrypoint: string,\n { locale, config, logger }: { locale: string; config: ResolvedConfig; logger?: Logger },\n) {\n const entryConfig = config.entrypoints.find((e) => e.entrypoint === entrypoint);\n const destination = entryConfig?.destination ?? config.destination;\n const obsolete = entryConfig?.obsolete ?? config.obsolete;\n const exclude = entryConfig?.exclude ?? config.exclude;\n\n const queue: ResolveArgs[] = [{ entrypoint, path: entrypoint }];\n\n logger?.info({ entrypoint, locale }, \"starting extraction\");\n\n const context: ExtractContext = {\n entry: entrypoint,\n config: { ...config, destination, obsolete, exclude },\n generatedAt: new Date(),\n locale,\n logger,\n };\n\n const resolves: { filter: RegExp; hook: ResolveHook }[] = [];\n const loads: { filter: RegExp; hook: LoadHook }[] = [];\n const extracts: { filter: RegExp; hook: ExtractHook }[] = [];\n const collects: { filter: RegExp; hook: CollectHook }[] = [];\n const generates: { filter: RegExp; hook: GenerateHook }[] = [];\n\n function resolvePath(args: ResolveArgs) {\n for (const ex of context.config.exclude) {\n if (ex instanceof RegExp ? ex.test(args.path) : ex(args.path)) {\n return;\n }\n }\n if (context.config.walk) {\n queue.push(args);\n }\n }\n\n const build: ExtractBuild = {\n onResolve({ filter }, hook) {\n resolves.push({ filter, hook });\n },\n onLoad({ filter }, hook) {\n loads.push({ filter, hook });\n },\n onExtract({ filter }, hook) {\n extracts.push({ filter, hook });\n },\n onCollect({ filter }, hook) {\n collects.push({ filter, hook });\n },\n onGenerate({ filter }, hook) {\n generates.push({ filter, hook });\n },\n resolvePath,\n context,\n };\n\n for (const plugin of config.plugins) {\n logger?.debug({ plugin: plugin.name }, \"setting up plugin\");\n plugin.setup(build);\n }\n\n const visited = new Set<string>();\n const results: ExtractResult[] = [];\n\n async function applyResolve({ entrypoint, path }: ResolveArgs): Promise<ResolveResult | undefined> {\n for (const { filter, hook } of resolves) {\n if (!filter.test(path)) continue;\n const result = await hook({ entrypoint, path }, context);\n if (result) {\n logger?.debug({ entrypoint, path }, \"resolved\");\n }\n if (result) return result;\n }\n return undefined;\n }\n\n async function applyLoad({ entrypoint, path }: LoadArgs): Promise<LoadResult | undefined> {\n for (const { filter, hook } of loads) {\n if (!filter.test(path)) continue;\n const result = await hook({ entrypoint, path }, context);\n if (result) {\n logger?.debug({ entrypoint, path }, \"loaded\");\n }\n if (result) return result;\n }\n return undefined;\n }\n\n async function applyExtract({ entrypoint, path, contents }: ExtractArgs): Promise<ExtractResult | undefined> {\n for (const { filter, hook } of extracts) {\n if (!filter.test(path)) continue;\n const result = await hook({ entrypoint, path, contents }, context);\n if (result) {\n logger?.debug({ entrypoint, path }, \"extracted\");\n }\n if (result) return result;\n }\n return undefined;\n }\n\n async function applyCollect({\n entrypoint,\n path,\n translations,\n destination,\n }: CollectArgs): Promise<CollectResult | undefined> {\n for (const { filter, hook } of collects) {\n if (!filter.test(path)) continue;\n const result = await hook({ entrypoint, path, translations, destination }, context);\n if (result) {\n logger?.debug(\n {\n entrypoint,\n path,\n destination,\n ...(destination !== result.destination && { redirected: result.destination }),\n },\n \"collected\",\n );\n }\n if (result) return result;\n }\n return undefined;\n }\n\n const result: Record<string, CollectResult[]> = {};\n\n while (queue.length) {\n // biome-ignore lint/style/noNonNullAssertion: queue is checked above\n const args = queue.shift()!;\n const resolved = await applyResolve(args);\n if (!resolved || visited.has(resolved.path)) continue;\n visited.add(resolved.path);\n\n const loaded = await applyLoad(resolved);\n if (!loaded) continue;\n\n const extracted = await applyExtract(loaded);\n if (!extracted) continue;\n\n const destination = context.config.destination({ entrypoint, locale, path: resolved.path });\n const collected = await applyCollect({ ...extracted, destination });\n if (!collected) continue;\n\n if (!result[collected.destination]) {\n result[collected.destination] = [];\n }\n\n result[collected.destination].push(collected);\n }\n\n for (const [path, collected] of Object.entries(result)) {\n for (const { filter, hook } of generates) {\n if (!filter.test(path)) continue;\n logger?.info({ path }, \"generating output\");\n await hook({ entrypoint, path, collected }, context);\n }\n }\n\n logger?.info({ entrypoint, locale }, \"extraction completed\");\n return results;\n}\n"],"mappings":"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"}