@generaltranslation/vue-extractor 0.1.0-iris.0 → 0.1.0

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.
@@ -223,7 +223,14 @@ function malformedSuffixHasGTProvenance(sourceCode, filePath, options, language,
223
223
  }
224
224
  /** Removes block closers orphaned when recovery starts inside a function. */
225
225
  function trimTrailingRecoveryClosers(sourceCode) {
226
- return sourceCode.replace(/(?:\s*\}\s*)+$/u, "").trimEnd();
226
+ let end = sourceCode.length;
227
+ while (end > 0 && sourceCode[end - 1].trim() === "") end -= 1;
228
+ if (sourceCode[end - 1] !== "}") return sourceCode.slice(0, end);
229
+ do {
230
+ end -= 1;
231
+ while (end > 0 && sourceCode[end - 1].trim() === "") end -= 1;
232
+ } while (sourceCode[end - 1] === "}");
233
+ return sourceCode.slice(0, end);
227
234
  }
228
235
  /** Chooses the grammar that parsed furthest before a recoverable error. */
229
236
  function selectMalformedSuffixLanguage(sourceCode, languages) {
@@ -1 +1 @@
1
- {"version":3,"file":"extractFromVueSource.js","names":["initModuleLexer","parseModuleImports"],"sources":["../../src/internal/extractFromVueSource.ts"],"sourcesContent":["import { extname } from 'node:path';\nimport {\n init as initModuleLexer,\n parse as parseModuleImports,\n} from 'es-module-lexer';\nimport type { ParserPlugin } from '@babel/parser';\nimport type { SFCBlock, TemplateCompiler } from '#vue-compiler-sfc';\nimport type { RootNode } from '@vue/compiler-dom';\nimport type {\n VueCompilerOptions,\n VueExtractionOptions,\n VueExtractionOutput,\n} from '../types.js';\nimport {\n collectVueScriptImports,\n createVueScriptAnalysis,\n exposeVueScriptImportsToTemplate,\n parseVueScript,\n type VueScriptAnalysis,\n} from './script.js';\nimport { parseScriptAst } from './script/parser.js';\nimport {\n shiftCompilerAstLocations,\n shiftCompilerLocation,\n} from './compilerAst.js';\nimport {\n createLocalModuleResolver,\n type LocalModuleResolver,\n} from './script/localModules.js';\nimport { parseVueTemplate } from './template.js';\nimport type { TemplateBindings, VueExtractionContext } from './types.js';\nimport { addVueError, createVueExtractionContext } from './utils.js';\nimport {\n inspectVueCompiler,\n resolveVueCompiler,\n type ResolvedVueCompiler,\n} from './vueCompiler.js';\n\nconst DEFAULT_SURROUNDING_LINE_COUNT = 5;\nconst MAX_MALFORMED_SUFFIX_RECOVERIES = 64;\n\n/** Parser options supported at runtime but omitted from Vue 3.3 declarations. */\ntype CompatibleTemplateParserOptions = NonNullable<\n Parameters<TemplateCompiler['parse']>[1]\n> & {\n expressionPlugins?: ParserPlugin[];\n};\n\n/** compiler-dom options supported at runtime across the supported Vue range. */\ntype CompatibleCompilerDomParserOptions = NonNullable<\n Parameters<NonNullable<ResolvedVueCompiler['parseTemplate']>>[1]\n> & {\n expressionPlugins?: ParserPlugin[];\n};\n\n/**\n * Extracts General Translation content from one Vue SFC or JavaScript file.\n *\n * This low-level API lets callers parse an individual in-memory source file.\n * Use `@generaltranslation/vue-extractor/project` when discovery, I/O,\n * compiler configuration, hashing, and deduplication should be handled by the\n * package as one project-level operation.\n */\nexport async function extractFromVueSource(\n sourceCode: string,\n filePath: string,\n options: VueExtractionOptions = {}\n): Promise<VueExtractionOutput> {\n const results: VueExtractionOutput['results'] = [];\n const errors: string[] = [];\n const warnings = new Set<string>();\n const context = createVueExtractionContext(\n filePath,\n sourceCode,\n options.projectRoot ?? process.cwd(),\n options.includeSourceCodeContext ?? false,\n options.surroundingLineCount ?? DEFAULT_SURROUNDING_LINE_COUNT,\n results,\n errors,\n warnings\n );\n const extension = extname(filePath).toLowerCase();\n const scriptAnalysis = createVueScriptAnalysis();\n scriptAnalysis.entryFile = filePath;\n scriptAnalysis.localModules = createLocalModuleResolver(\n options.resolveModule\n );\n\n if (extension === '.vue') {\n const compilerResolution =\n options.compiler !== undefined\n ? inspectVueCompiler(options.compiler)\n : resolveVueCompiler(filePath, options.projectRoot ?? process.cwd());\n if (!compilerResolution.ok) {\n addVueError(\n context,\n undefined,\n 'Could not load the Vue compiler used by this single-file component',\n `Install a supported Vue 3 compiler beside the app. ${compilerResolution.details}`\n );\n return { results, errors, warnings: [...warnings] };\n }\n context.implicitSlotWhitespace =\n compilerResolution.value.implicitSlotWhitespace;\n context.valuedVIsReplacesElement =\n compilerResolution.value.valuedVIsReplacesElement;\n parseVueSingleFileComponent(\n sourceCode,\n context,\n options.compilerOptions ?? {},\n compilerResolution.value,\n scriptAnalysis\n );\n } else {\n if (\n options.requireGTProvenance &&\n !(await hasStandaloneGTProvenance(sourceCode, filePath, options))\n ) {\n return { results, errors, warnings: [...warnings] };\n }\n parseVueScript(\n sourceCode,\n languageFromExtension(extension),\n context,\n createTemplateBindings(),\n false,\n scriptAnalysis,\n false\n );\n }\n\n return { results, errors, warnings: [...warnings] };\n}\n\n/**\n * Uses the declared language, then permissive TSX and Flow, to prove gt-vue\n * ownership without changing the grammar used for extraction.\n *\n * The normal extraction pass still parses the file according to its extension.\n * Diagnostics caused only by GT-shaped names do not establish ownership. This\n * keeps mixed-framework dispatch from making otherwise valid React files fatal.\n */\nasync function hasStandaloneGTProvenance(\n sourceCode: string,\n filePath: string,\n options: VueExtractionOptions\n): Promise<boolean> {\n const extension = extname(filePath).toLowerCase();\n const probeLanguages = new Set<StandaloneProbeLanguage>([\n languageFromExtension(extension),\n 'tsx',\n 'flow',\n ]);\n const localModules = createLocalModuleResolver(options.resolveModule);\n for (const language of probeLanguages) {\n const probe = probeStandaloneGTProvenance(\n sourceCode,\n filePath,\n options,\n language,\n localModules\n );\n if (probe.hasProvenance) return true;\n if (probe.parsed) return false;\n }\n const suffixSelection = selectMalformedSuffixLanguage(\n sourceCode,\n probeLanguages\n );\n const moduleRecovery = suffixSelection?.recoverable\n ? await recoverMalformedModuleReferences(\n sourceCode,\n filePath,\n options,\n probeLanguages,\n localModules\n )\n : { hasProvenance: false, preamble: '' };\n if (moduleRecovery.hasProvenance) {\n return true;\n }\n return hasMalformedStandaloneGTProvenance(\n sourceCode,\n filePath,\n options,\n probeLanguages,\n localModules,\n moduleRecovery.preamble\n );\n}\n\n/**\n * Recovers static module ownership without reparsing an entire malformed file.\n *\n * es-module-lexer ignores comments and literal contents while continuing past\n * unrelated syntax errors. Each declaration is then analyzed on its own,\n * preserving type-only and binding-specific local-barrel semantics. Parseable\n * declarations are also returned as a preamble for later recovered uses.\n */\nasync function recoverMalformedModuleReferences(\n sourceCode: string,\n filePath: string,\n options: VueExtractionOptions,\n languages: ReadonlySet<StandaloneProbeLanguage>,\n localModules: LocalModuleResolver\n): Promise<{ hasProvenance: boolean; preamble: string }> {\n await initModuleLexer;\n let imports: ReturnType<typeof parseModuleImports>[0];\n try {\n [imports] = parseModuleImports(sourceCode);\n } catch {\n imports = [];\n }\n\n const declarations = new Set<string>();\n for (const moduleImport of imports) {\n if (!moduleImport.n) continue;\n for (const declaration of readModuleStatementCandidates(\n sourceCode,\n moduleImport.ss,\n moduleImport.se\n )) {\n for (const language of languages) {\n const probe = probeStandaloneGTProvenance(\n declaration,\n filePath,\n options,\n language,\n localModules\n );\n if (probe.hasProvenance) {\n return { hasProvenance: true, preamble: '' };\n }\n if (probe.parsed) {\n declarations.add(declaration);\n break;\n }\n }\n if (declarations.has(declaration)) break;\n }\n }\n return {\n hasProvenance: false,\n preamble: [...declarations].join('\\n'),\n };\n}\n\n/** Returns small statement slices enclosing one lexed module reference. */\nfunction readModuleStatementCandidates(\n sourceCode: string,\n statementStart: number,\n specifierEnd: number\n): string[] {\n const precedingBoundaries = [';', '\\n', '{', '}']\n .map((separator) => sourceCode.lastIndexOf(separator, statementStart - 1))\n .filter((offset) => offset >= 0)\n .map((offset) => offset + 1);\n precedingBoundaries.push(0);\n const followingBoundaries = [';', '\\n', '}']\n .map((separator) => sourceCode.indexOf(separator, specifierEnd))\n .filter((offset) => offset >= 0)\n .map((offset) => offset + 1);\n const starts = [\n ...precedingBoundaries.sort((left, right) => right - left),\n statementStart,\n ];\n const ends = [\n ...followingBoundaries.sort((left, right) => left - right),\n specifierEnd,\n ];\n const candidates = new Set<string>();\n for (const start of starts) {\n for (const end of ends) {\n if (end <= start) continue;\n const candidate = sourceCode.slice(start, end).trim();\n if (candidate) candidates.add(candidate);\n }\n }\n return [...candidates];\n}\n\ntype StandaloneProbeLanguage = 'flow' | 'js' | 'jsx' | 'ts' | 'tsx';\n\n/** Runs one syntax-tolerant, read-only provenance classification pass. */\nfunction probeStandaloneGTProvenance(\n sourceCode: string,\n filePath: string,\n options: VueExtractionOptions,\n language: StandaloneProbeLanguage,\n localModules: LocalModuleResolver\n): { hasProvenance: boolean; parsed: boolean } {\n const results: VueExtractionOutput['results'] = [];\n const errors: string[] = [];\n const warnings = new Set<string>();\n const projectRoot = options.projectRoot ?? process.cwd();\n const context = createVueExtractionContext(\n filePath,\n sourceCode,\n projectRoot,\n false,\n options.surroundingLineCount ?? DEFAULT_SURROUNDING_LINE_COUNT,\n results,\n errors,\n warnings\n );\n const analysis = createVueScriptAnalysis();\n analysis.entryFile = filePath;\n analysis.localModules = localModules;\n const parsed = parseVueScript(\n sourceCode,\n language,\n context,\n createTemplateBindings(),\n false,\n analysis,\n false\n );\n if (results.length > 0 || analysisHasGTProvenance(analysis)) {\n return { hasProvenance: true, parsed };\n }\n return { hasProvenance: false, parsed };\n}\n\n/**\n * Finds concrete module references when malformed syntax prevents a full AST.\n *\n * Each supported grammar recovers a complete prefix, then the grammar that\n * parsed furthest gets a bounded suffix search. Unterminated literal errors\n * never receive suffix recovery, so literal contents cannot become code.\n */\nfunction hasMalformedStandaloneGTProvenance(\n sourceCode: string,\n filePath: string,\n options: VueExtractionOptions,\n languages: ReadonlySet<StandaloneProbeLanguage>,\n localModules: LocalModuleResolver,\n recoveredPreamble: string\n): boolean {\n for (const language of languages) {\n if (\n leadingStatementPrefixHasGTProvenance(\n sourceCode,\n filePath,\n options,\n language,\n localModules\n )\n ) {\n return true;\n }\n }\n const suffixSelection = selectMalformedSuffixLanguage(sourceCode, languages);\n return Boolean(\n suffixSelection?.recoverable &&\n malformedSuffixHasGTProvenance(\n sourceCode,\n filePath,\n options,\n suffixSelection.language,\n localModules,\n recoveredPreamble\n )\n );\n}\n\n/** Preserves CommonJS and TypeScript import ownership before a syntax error. */\nfunction leadingStatementPrefixHasGTProvenance(\n sourceCode: string,\n filePath: string,\n options: VueExtractionOptions,\n language: StandaloneProbeLanguage,\n localModules: LocalModuleResolver\n): boolean {\n let errorOffset: number;\n try {\n parseScriptAst(sourceCode, language);\n return false;\n } catch (error) {\n const offset = (error as { pos?: unknown }).pos;\n if (typeof offset !== 'number') return false;\n errorOffset = offset;\n }\n const boundary = Math.max(\n sourceCode.lastIndexOf(';', errorOffset - 1) + 1,\n sourceCode.lastIndexOf('\\n', errorOffset - 1) + 1,\n sourceCode.lastIndexOf('}', errorOffset - 1) + 1\n );\n if (boundary <= 0) return false;\n const prefix = sourceCode.slice(0, boundary).trimEnd();\n if (!prefix) return false;\n const probe = probeStandaloneGTProvenance(\n prefix,\n filePath,\n options,\n language,\n localModules\n );\n return probe.hasProvenance;\n}\n\n/** Recovers later imports and CommonJS calls after a bounded number of errors. */\nfunction malformedSuffixHasGTProvenance(\n sourceCode: string,\n filePath: string,\n options: VueExtractionOptions,\n language: StandaloneProbeLanguage,\n localModules: LocalModuleResolver,\n recoveredPreamble: string\n): boolean {\n let remaining = sourceCode;\n for (let attempt = 0; attempt < MAX_MALFORMED_SUFFIX_RECOVERIES; attempt++) {\n let errorOffset: number;\n try {\n parseScriptAst(remaining, language);\n const recoveredSource = recoveredPreamble\n ? `${recoveredPreamble}\\n${remaining}`\n : remaining;\n const recoveredProbe = probeStandaloneGTProvenance(\n recoveredSource,\n filePath,\n options,\n language,\n localModules\n );\n if (recoveredProbe.parsed) return recoveredProbe.hasProvenance;\n // The remaining suffix may already contain the declaration retained in\n // the preamble. Probe it alone to avoid a duplicate-binding parse error.\n return probeStandaloneGTProvenance(\n remaining,\n filePath,\n options,\n language,\n localModules\n ).hasProvenance;\n } catch (error) {\n const parseError = readRecoverableParseError(error);\n if (!parseError) return false;\n errorOffset = parseError.offset;\n }\n const boundary = findMalformedRecoveryBoundary(remaining, errorOffset);\n if (boundary <= 0 || boundary >= remaining.length) return false;\n remaining = remaining.slice(boundary);\n const recoveredSource = recoveredPreamble\n ? `${recoveredPreamble}\\n${remaining}`\n : remaining;\n let probe = probeStandaloneGTProvenance(\n recoveredSource,\n filePath,\n options,\n language,\n localModules\n );\n if (!probe.parsed && recoveredPreamble) {\n const trimmedRemaining = trimTrailingRecoveryClosers(remaining);\n if (trimmedRemaining !== remaining) {\n probe = probeStandaloneGTProvenance(\n `${recoveredPreamble}\\n${trimmedRemaining}`,\n filePath,\n options,\n language,\n localModules\n );\n }\n }\n if (probe.hasProvenance) return true;\n if (probe.parsed) return false;\n }\n return false;\n}\n\n/** Removes block closers orphaned when recovery starts inside a function. */\nfunction trimTrailingRecoveryClosers(sourceCode: string): string {\n return sourceCode.replace(/(?:\\s*\\}\\s*)+$/u, '').trimEnd();\n}\n\n/** Chooses the grammar that parsed furthest before a recoverable error. */\nfunction selectMalformedSuffixLanguage(\n sourceCode: string,\n languages: ReadonlySet<StandaloneProbeLanguage>\n): { language: StandaloneProbeLanguage; recoverable: boolean } | undefined {\n let selected:\n | { language: StandaloneProbeLanguage; recoverable: boolean }\n | undefined;\n let furthestOffset = -1;\n for (const language of languages) {\n try {\n parseScriptAst(sourceCode, language);\n } catch (error) {\n const parseError = readParseError(error);\n if (parseError && parseError.offset > furthestOffset) {\n selected = {\n language,\n recoverable: parseError.recoverable,\n };\n furthestOffset = parseError.offset;\n }\n }\n }\n return selected;\n}\n\n/** Rejects recovery that could reinterpret unterminated literal contents. */\nfunction readRecoverableParseError(\n error: unknown\n): { offset: number } | undefined {\n const parsed = readParseError(error);\n return parsed?.recoverable ? { offset: parsed.offset } : undefined;\n}\n\n/** Reads one Babel parser error without trusting unterminated literal state. */\nfunction readParseError(\n error: unknown\n): { offset: number; recoverable: boolean } | undefined {\n const parsed = error as { pos?: unknown; reasonCode?: unknown };\n if (typeof parsed.pos !== 'number') return undefined;\n const unsafeReasonCodes = new Set([\n 'UnterminatedComment',\n 'UnterminatedJsxContent',\n 'UnterminatedRegExp',\n 'UnterminatedString',\n 'UnterminatedTemplate',\n ]);\n return {\n offset: parsed.pos,\n recoverable:\n typeof parsed.reasonCode !== 'string' ||\n !unsafeReasonCodes.has(parsed.reasonCode),\n };\n}\n\n/** Selects the first statement-like boundary after a parser error. */\nfunction findMalformedRecoveryBoundary(\n sourceCode: string,\n errorOffset: number\n): number {\n const candidates = [';', '\\n', '}']\n .map((separator) => sourceCode.indexOf(separator, errorOffset))\n .filter((offset) => offset >= 0);\n return candidates.length > 0 ? Math.min(...candidates) + 1 : -1;\n}\n\n/** Returns whether permissive analysis reached a concrete gt-vue identity. */\nfunction analysisHasGTProvenance(analysis: VueScriptAnalysis): boolean {\n return analysis.hasGTSourceReference;\n}\n\nfunction parseVueSingleFileComponent(\n source: string,\n context: VueExtractionContext,\n compilerOptions: VueCompilerOptions,\n resolvedCompiler: ResolvedVueCompiler,\n scriptAnalysis: VueScriptAnalysis\n): void {\n const { compiler } = resolvedCompiler;\n if (\n compilerOptions.delimiters &&\n !resolvedCompiler.templateCompiler &&\n !resolvedCompiler.templateParseOptionsSupported\n ) {\n addVueError(\n context,\n undefined,\n 'Could not safely apply custom Vue template delimiters with the supplied compiler',\n 'Let the extractor resolve the consuming app compiler, or supply a Vue compiler that applies templateParseOptions during SFC parsing'\n );\n return;\n }\n const expressionPlugins: ParserPlugin[] = sourceUsesTypeScript(source)\n ? ['typescript']\n : [];\n const templateCompiler = createConfiguredTemplateCompiler(\n resolvedCompiler,\n compilerOptions,\n expressionPlugins,\n true\n );\n const result = compiler.parse(source, {\n ...(templateCompiler && { compiler: templateCompiler }),\n filename: context.file,\n pad: 'space',\n sourceMap: false,\n templateParseOptions: {\n ...compilerOptions,\n comments: true,\n expressionPlugins,\n },\n });\n\n for (const error of result.errors) {\n const compilerError =\n typeof error === 'string'\n ? undefined\n : (error as SyntaxError & {\n loc?: Parameters<typeof normalizeCompilerLocation>[0];\n });\n addVueError(\n context,\n compilerError?.loc\n ? normalizeCompilerLocation(compilerError.loc)\n : undefined,\n `Could not parse a gt-vue single-file component: ${typeof error === 'string' ? error : error.message}`,\n 'Fix the Vue template syntax before extracting translations'\n );\n }\n // Vue's SFC parser recovers a partial AST for malformed markup. Publishing\n // translations from that recovery tree can replace complete catalogs with\n // an incomplete source set, so structural parse errors are file-fatal.\n if (result.errors.length > 0) return;\n\n const bindings = createTemplateBindings();\n collectScriptBlockImports(result.descriptor.script, scriptAnalysis);\n collectScriptBlockImports(result.descriptor.scriptSetup, scriptAnalysis);\n const scriptValid = parseScriptBlock(\n result.descriptor.script,\n false,\n context,\n bindings,\n scriptAnalysis\n );\n if (result.descriptor.scriptSetup) {\n exposeVueScriptImportsToTemplate(scriptAnalysis, bindings);\n }\n const scriptSetupValid = parseScriptBlock(\n result.descriptor.scriptSetup,\n true,\n context,\n bindings,\n scriptAnalysis\n );\n if (!scriptValid || !scriptSetupValid) {\n context.results.length = 0;\n return;\n }\n\n const template = result.descriptor.template;\n if (!template) return;\n if (template.lang && template.lang !== 'html') {\n addVueError(\n context,\n template.loc,\n `Found unsupported Vue template language \"${template.lang}\"`,\n 'Use a standard HTML Vue template for gt-vue extraction'\n );\n context.results.length = 0;\n return;\n }\n if (template.src) {\n addVueError(\n context,\n template.loc,\n 'Found an externally sourced Vue template',\n 'Keep the template in the .vue file so gt-vue can extract it'\n );\n context.results.length = 0;\n return;\n }\n const templateAst = resolvedCompiler.parseTemplate\n ? parseTemplateWithCompiler(\n template.content,\n compilerOptions,\n expressionPlugins,\n true,\n context,\n resolvedCompiler.parseTemplate,\n template.loc.start\n )\n : (template.ast as unknown as RootNode);\n if (templateAst) {\n const templateResultStart = context.results.length;\n const templateErrorStart = context.errors.length;\n parseVueTemplate(templateAst, bindings, expressionPlugins, context);\n if (\n context.errors.length === templateErrorStart &&\n template.content.includes('<!--') &&\n !matchesProductionTemplate(\n source,\n compilerOptions,\n expressionPlugins,\n bindings,\n context,\n templateResultStart,\n resolvedCompiler\n )\n ) {\n context.results.length = templateResultStart;\n addVueError(\n context,\n template.loc,\n 'Found translatable Vue content whose hash changes between development and production',\n 'Remove comments that split translatable text or whitespace, or move those comments outside gt-vue <T> components'\n );\n }\n }\n}\n\n/**\n * Verifies that Vite's production comment stripping preserves extracted data.\n *\n * Vue parses templates with comments in development and without them in\n * production. Removing a comment can renormalize adjacent whitespace, so a\n * single persisted catalog key cannot serve both builds. The second parse is\n * limited to templates that contain comments and never executes project code.\n */\nfunction matchesProductionTemplate(\n source: string,\n compilerOptions: VueCompilerOptions,\n expressionPlugins: ParserPlugin[],\n bindings: TemplateBindings,\n context: VueExtractionContext,\n developmentResultStart: number,\n resolvedCompiler: ResolvedVueCompiler\n): boolean {\n const { compiler } = resolvedCompiler;\n const templateCompiler = createConfiguredTemplateCompiler(\n resolvedCompiler,\n compilerOptions,\n expressionPlugins,\n false\n );\n const production = compiler.parse(source, {\n ...(templateCompiler && { compiler: templateCompiler }),\n filename: context.file,\n pad: 'space',\n sourceMap: false,\n templateParseOptions: {\n ...compilerOptions,\n comments: false,\n expressionPlugins,\n },\n });\n const template = production.descriptor.template;\n if (production.errors.length > 0 || !template) return false;\n\n const productionContext: VueExtractionContext = {\n ...context,\n errors: [],\n results: [],\n warnings: new Set(),\n };\n const templateAst = resolvedCompiler.parseTemplate\n ? parseTemplateWithCompiler(\n template.content,\n compilerOptions,\n expressionPlugins,\n false,\n productionContext,\n resolvedCompiler.parseTemplate,\n template.loc.start\n )\n : (template.ast as unknown as RootNode);\n if (!templateAst) return false;\n parseVueTemplate(templateAst, bindings, expressionPlugins, productionContext);\n if (productionContext.errors.length > 0) return false;\n\n const developmentResults = context.results.slice(developmentResultStart);\n return (\n comparableTemplateResults(developmentResults) ===\n comparableTemplateResults(productionContext.results)\n );\n}\n\n/**\n * Applies hash-affecting options during compiler-sfc's structural parse.\n *\n * Vue 3.3 ignores `templateParseOptions`, which can make delimiter-shaped text\n * close an SFC block before the exact template-content parse runs. Supplying\n * the adjacent compiler-dom parser makes the descriptor structural parse use\n * the same delimiters and whitespace. Vue 3.3 caches SFC parses using the\n * parser function's string form, so its deterministic identity includes every\n * closure-captured option to prevent cross-option cache poisoning.\n */\nfunction createConfiguredTemplateCompiler(\n resolvedCompiler: ResolvedVueCompiler,\n compilerOptions: VueCompilerOptions,\n expressionPlugins: ParserPlugin[],\n comments: boolean\n): TemplateCompiler | undefined {\n const templateCompiler = resolvedCompiler.templateCompiler;\n if (!templateCompiler) return undefined;\n\n const parse: TemplateCompiler['parse'] = (source, baseOptions) => {\n const options: CompatibleTemplateParserOptions = {\n ...baseOptions,\n ...compilerOptions,\n comments,\n expressionPlugins,\n };\n return templateCompiler.parse(source, options);\n };\n const identity = JSON.stringify({\n comments,\n delimiters: compilerOptions.delimiters,\n expressionPlugins,\n version: resolvedCompiler.version,\n whitespace: compilerOptions.whitespace,\n });\n Object.defineProperty(parse, 'toString', {\n value: () => `gtVueTemplateParse:${identity}`,\n });\n\n return { compile: templateCompiler.compile, parse };\n}\n\n/** Parses template content with the exact compiler-dom beside consumer Vue. */\nfunction parseTemplateWithCompiler(\n source: string,\n compilerOptions: VueCompilerOptions,\n expressionPlugins: ParserPlugin[],\n comments: boolean,\n context: VueExtractionContext,\n parseTemplate: NonNullable<ResolvedVueCompiler['parseTemplate']>,\n origin: CompilerPosition\n): RootNode | undefined {\n const errors: Array<SyntaxError & { loc?: ExtractionLocationLike }> = [];\n const options: CompatibleCompilerDomParserOptions = {\n ...compilerOptions,\n comments,\n expressionPlugins,\n onError(error) {\n errors.push(error as SyntaxError & { loc?: ExtractionLocationLike });\n },\n };\n const ast = parseTemplate(source, options);\n if (errors.length === 0) {\n shiftCompilerAstLocations(ast, origin);\n return ast;\n }\n const shiftedErrorPositions = new WeakSet<object>();\n for (const error of errors) {\n if (error.loc) {\n shiftCompilerLocation(error.loc, origin, shiftedErrorPositions);\n }\n addVueError(\n context,\n error.loc ? normalizeCompilerLocation(error.loc) : undefined,\n `Could not parse a gt-vue template: ${error.message}`,\n 'Fix the Vue template syntax before extracting translations'\n );\n }\n return undefined;\n}\n\ntype ExtractionLocationLike = Parameters<typeof normalizeCompilerLocation>[0];\ntype CompilerPosition = {\n column: number;\n line: number;\n offset: number;\n};\n\n/** Omits location-only metadata while comparing persisted template content. */\nfunction comparableTemplateResults(\n results: VueExtractionOutput['results']\n): string {\n return JSON.stringify(\n results.map((result) => ({\n dataFormat: result.dataFormat,\n metadata: {\n context: result.metadata.context,\n id: result.metadata.id,\n maxChars: result.metadata.maxChars,\n requiresReview: result.metadata.requiresReview,\n },\n source: result.source,\n }))\n );\n}\n\nfunction collectScriptBlockImports(\n block: SFCBlock | null,\n scriptAnalysis: VueScriptAnalysis\n): void {\n if (!block || block.src || !isSupportedScriptLanguage(block.lang)) return;\n collectVueScriptImports(block.content, block.lang, scriptAnalysis);\n}\n\nfunction parseScriptBlock(\n block: SFCBlock | null,\n exposeToTemplate: boolean,\n context: VueExtractionContext,\n bindings: TemplateBindings,\n scriptAnalysis: VueScriptAnalysis\n): boolean {\n if (!block) return true;\n if (block.src) {\n addVueError(\n context,\n block.loc,\n 'Found an externally sourced Vue script block',\n 'Keep translation calls and gt-vue imports in the .vue file'\n );\n return false;\n }\n if (!isSupportedScriptLanguage(block.lang)) {\n addVueError(\n context,\n block.loc,\n `Found unsupported Vue script language \"${block.lang}\"`,\n 'Use JavaScript or TypeScript for gt-vue extraction'\n );\n return false;\n }\n\n return parseVueScript(\n block.content,\n block.lang,\n context,\n bindings,\n exposeToTemplate,\n scriptAnalysis\n );\n}\n\nfunction createTemplateBindings(): TemplateBindings {\n return {\n arrayLengths: new Map(),\n componentFactories: new Set(),\n components: new Map(),\n containerKinds: new Map(),\n possibleGTContainers: new Set(),\n gtContainerFactories: new Set(),\n directBindings: new Set(),\n registeredComponents: new Map(),\n registeredVueBuiltins: new Map(),\n staticValues: new Map(),\n identityFunctions: new Set(),\n possibleStaticStrings: new Map(),\n stringFunctions: new Map(),\n uncertainStringFunctions: new Set(),\n uncertainComponents: new Set(),\n uncertainGTComponents: new Set(),\n gtComponentFactories: new Set(),\n uncertainRegisteredComponents: new Set(),\n uncertainRegisteredGTComponents: new Set(),\n vueBuiltins: new Map(),\n };\n}\n\nfunction sourceUsesTypeScript(source: string): boolean {\n let offset = 0;\n while (offset < source.length) {\n const start = source.indexOf('<script', offset);\n if (start === -1) return false;\n const boundary = source[start + '<script'.length];\n if (boundary !== '>' && !boundary?.match(/\\s/)) {\n offset = start + '<script'.length;\n continue;\n }\n\n const end = findOpeningTagEnd(source, start + '<script'.length);\n if (end === -1) return false;\n const language = readOpeningTagAttribute(\n source.slice(start + '<script'.length, end),\n 'lang'\n );\n if (typeof language === 'string' && /^tsx?$/i.test(language)) return true;\n offset = end + 1;\n }\n return false;\n}\n\nfunction isSupportedScriptLanguage(language: string | undefined): boolean {\n const normalizedLanguage = language?.toLowerCase();\n return (\n normalizedLanguage === undefined ||\n normalizedLanguage === 'js' ||\n normalizedLanguage === 'jsx' ||\n normalizedLanguage === 'ts' ||\n normalizedLanguage === 'tsx'\n );\n}\n\n/** Finds an opening tag boundary while respecting quoted attribute values. */\nfunction findOpeningTagEnd(source: string, start: number): number {\n let quote: '\"' | \"'\" | undefined;\n for (let index = start; index < source.length; index += 1) {\n const character = source[index];\n if (quote) {\n if (character === quote) quote = undefined;\n } else if (character === '\"' || character === \"'\") {\n quote = character;\n } else if (character === '>') {\n return index;\n }\n }\n return -1;\n}\n\n/** Reads one case-sensitive SFC attribute with quoted or unquoted syntax. */\nfunction readOpeningTagAttribute(\n attributes: string,\n requestedName: string\n): string | true | undefined {\n let offset = 0;\n while (offset < attributes.length) {\n while (offset < attributes.length && /\\s/.test(attributes[offset])) {\n offset += 1;\n }\n if (attributes[offset] === '/') {\n offset += 1;\n continue;\n }\n const nameStart = offset;\n while (offset < attributes.length && !/[\\s=]/.test(attributes[offset])) {\n offset += 1;\n }\n const name = attributes.slice(nameStart, offset);\n if (!name) break;\n\n while (offset < attributes.length && /\\s/.test(attributes[offset])) {\n offset += 1;\n }\n let value: string | true = true;\n if (attributes[offset] === '=') {\n offset += 1;\n while (offset < attributes.length && /\\s/.test(attributes[offset])) {\n offset += 1;\n }\n const quote = attributes[offset];\n if (quote === '\"' || quote === \"'\") {\n offset += 1;\n const valueStart = offset;\n while (offset < attributes.length && attributes[offset] !== quote) {\n offset += 1;\n }\n value = attributes.slice(valueStart, offset);\n if (attributes[offset] === quote) offset += 1;\n } else {\n const valueStart = offset;\n while (offset < attributes.length && !/\\s/.test(attributes[offset])) {\n offset += 1;\n }\n value = attributes.slice(valueStart, offset);\n }\n }\n if (name === requestedName) return value;\n }\n return undefined;\n}\n\nfunction languageFromExtension(\n extension: string\n): Exclude<StandaloneProbeLanguage, 'flow'> {\n if (extension === '.ts' || extension === '.mts' || extension === '.cts') {\n return 'ts';\n }\n if (extension === '.tsx') return 'tsx';\n if (extension === '.jsx') return 'jsx';\n return 'js';\n}\n\nfunction normalizeCompilerLocation(location: {\n end?: { column?: number; line?: number; offset?: number };\n start?: { column?: number; line?: number; offset?: number };\n}) {\n const start = location.start ?? {};\n const end = location.end ?? start;\n return {\n start: {\n column: start.column ?? 1,\n line: start.line ?? 1,\n offset: start.offset ?? 0,\n },\n end: {\n column: end.column ?? start.column ?? 1,\n line: end.line ?? start.line ?? 1,\n offset: end.offset ?? start.offset ?? 0,\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"extractFromVueSource.js","names":["initModuleLexer","parseModuleImports"],"sources":["../../src/internal/extractFromVueSource.ts"],"sourcesContent":["import { extname } from 'node:path';\nimport {\n init as initModuleLexer,\n parse as parseModuleImports,\n} from 'es-module-lexer';\nimport type { ParserPlugin } from '@babel/parser';\nimport type { SFCBlock, TemplateCompiler } from '#vue-compiler-sfc';\nimport type { RootNode } from '@vue/compiler-dom';\nimport type {\n VueCompilerOptions,\n VueExtractionOptions,\n VueExtractionOutput,\n} from '../types.js';\nimport {\n collectVueScriptImports,\n createVueScriptAnalysis,\n exposeVueScriptImportsToTemplate,\n parseVueScript,\n type VueScriptAnalysis,\n} from './script.js';\nimport { parseScriptAst } from './script/parser.js';\nimport {\n shiftCompilerAstLocations,\n shiftCompilerLocation,\n} from './compilerAst.js';\nimport {\n createLocalModuleResolver,\n type LocalModuleResolver,\n} from './script/localModules.js';\nimport { parseVueTemplate } from './template.js';\nimport type { TemplateBindings, VueExtractionContext } from './types.js';\nimport { addVueError, createVueExtractionContext } from './utils.js';\nimport {\n inspectVueCompiler,\n resolveVueCompiler,\n type ResolvedVueCompiler,\n} from './vueCompiler.js';\n\nconst DEFAULT_SURROUNDING_LINE_COUNT = 5;\nconst MAX_MALFORMED_SUFFIX_RECOVERIES = 64;\n\n/** Parser options supported at runtime but omitted from Vue 3.3 declarations. */\ntype CompatibleTemplateParserOptions = NonNullable<\n Parameters<TemplateCompiler['parse']>[1]\n> & {\n expressionPlugins?: ParserPlugin[];\n};\n\n/** compiler-dom options supported at runtime across the supported Vue range. */\ntype CompatibleCompilerDomParserOptions = NonNullable<\n Parameters<NonNullable<ResolvedVueCompiler['parseTemplate']>>[1]\n> & {\n expressionPlugins?: ParserPlugin[];\n};\n\n/**\n * Extracts General Translation content from one Vue SFC or JavaScript file.\n *\n * This low-level API lets callers parse an individual in-memory source file.\n * Use `@generaltranslation/vue-extractor/project` when discovery, I/O,\n * compiler configuration, hashing, and deduplication should be handled by the\n * package as one project-level operation.\n */\nexport async function extractFromVueSource(\n sourceCode: string,\n filePath: string,\n options: VueExtractionOptions = {}\n): Promise<VueExtractionOutput> {\n const results: VueExtractionOutput['results'] = [];\n const errors: string[] = [];\n const warnings = new Set<string>();\n const context = createVueExtractionContext(\n filePath,\n sourceCode,\n options.projectRoot ?? process.cwd(),\n options.includeSourceCodeContext ?? false,\n options.surroundingLineCount ?? DEFAULT_SURROUNDING_LINE_COUNT,\n results,\n errors,\n warnings\n );\n const extension = extname(filePath).toLowerCase();\n const scriptAnalysis = createVueScriptAnalysis();\n scriptAnalysis.entryFile = filePath;\n scriptAnalysis.localModules = createLocalModuleResolver(\n options.resolveModule\n );\n\n if (extension === '.vue') {\n const compilerResolution =\n options.compiler !== undefined\n ? inspectVueCompiler(options.compiler)\n : resolveVueCompiler(filePath, options.projectRoot ?? process.cwd());\n if (!compilerResolution.ok) {\n addVueError(\n context,\n undefined,\n 'Could not load the Vue compiler used by this single-file component',\n `Install a supported Vue 3 compiler beside the app. ${compilerResolution.details}`\n );\n return { results, errors, warnings: [...warnings] };\n }\n context.implicitSlotWhitespace =\n compilerResolution.value.implicitSlotWhitespace;\n context.valuedVIsReplacesElement =\n compilerResolution.value.valuedVIsReplacesElement;\n parseVueSingleFileComponent(\n sourceCode,\n context,\n options.compilerOptions ?? {},\n compilerResolution.value,\n scriptAnalysis\n );\n } else {\n if (\n options.requireGTProvenance &&\n !(await hasStandaloneGTProvenance(sourceCode, filePath, options))\n ) {\n return { results, errors, warnings: [...warnings] };\n }\n parseVueScript(\n sourceCode,\n languageFromExtension(extension),\n context,\n createTemplateBindings(),\n false,\n scriptAnalysis,\n false\n );\n }\n\n return { results, errors, warnings: [...warnings] };\n}\n\n/**\n * Uses the declared language, then permissive TSX and Flow, to prove gt-vue\n * ownership without changing the grammar used for extraction.\n *\n * The normal extraction pass still parses the file according to its extension.\n * Diagnostics caused only by GT-shaped names do not establish ownership. This\n * keeps mixed-framework dispatch from making otherwise valid React files fatal.\n */\nasync function hasStandaloneGTProvenance(\n sourceCode: string,\n filePath: string,\n options: VueExtractionOptions\n): Promise<boolean> {\n const extension = extname(filePath).toLowerCase();\n const probeLanguages = new Set<StandaloneProbeLanguage>([\n languageFromExtension(extension),\n 'tsx',\n 'flow',\n ]);\n const localModules = createLocalModuleResolver(options.resolveModule);\n for (const language of probeLanguages) {\n const probe = probeStandaloneGTProvenance(\n sourceCode,\n filePath,\n options,\n language,\n localModules\n );\n if (probe.hasProvenance) return true;\n if (probe.parsed) return false;\n }\n const suffixSelection = selectMalformedSuffixLanguage(\n sourceCode,\n probeLanguages\n );\n const moduleRecovery = suffixSelection?.recoverable\n ? await recoverMalformedModuleReferences(\n sourceCode,\n filePath,\n options,\n probeLanguages,\n localModules\n )\n : { hasProvenance: false, preamble: '' };\n if (moduleRecovery.hasProvenance) {\n return true;\n }\n return hasMalformedStandaloneGTProvenance(\n sourceCode,\n filePath,\n options,\n probeLanguages,\n localModules,\n moduleRecovery.preamble\n );\n}\n\n/**\n * Recovers static module ownership without reparsing an entire malformed file.\n *\n * es-module-lexer ignores comments and literal contents while continuing past\n * unrelated syntax errors. Each declaration is then analyzed on its own,\n * preserving type-only and binding-specific local-barrel semantics. Parseable\n * declarations are also returned as a preamble for later recovered uses.\n */\nasync function recoverMalformedModuleReferences(\n sourceCode: string,\n filePath: string,\n options: VueExtractionOptions,\n languages: ReadonlySet<StandaloneProbeLanguage>,\n localModules: LocalModuleResolver\n): Promise<{ hasProvenance: boolean; preamble: string }> {\n await initModuleLexer;\n let imports: ReturnType<typeof parseModuleImports>[0];\n try {\n [imports] = parseModuleImports(sourceCode);\n } catch {\n imports = [];\n }\n\n const declarations = new Set<string>();\n for (const moduleImport of imports) {\n if (!moduleImport.n) continue;\n for (const declaration of readModuleStatementCandidates(\n sourceCode,\n moduleImport.ss,\n moduleImport.se\n )) {\n for (const language of languages) {\n const probe = probeStandaloneGTProvenance(\n declaration,\n filePath,\n options,\n language,\n localModules\n );\n if (probe.hasProvenance) {\n return { hasProvenance: true, preamble: '' };\n }\n if (probe.parsed) {\n declarations.add(declaration);\n break;\n }\n }\n if (declarations.has(declaration)) break;\n }\n }\n return {\n hasProvenance: false,\n preamble: [...declarations].join('\\n'),\n };\n}\n\n/** Returns small statement slices enclosing one lexed module reference. */\nfunction readModuleStatementCandidates(\n sourceCode: string,\n statementStart: number,\n specifierEnd: number\n): string[] {\n const precedingBoundaries = [';', '\\n', '{', '}']\n .map((separator) => sourceCode.lastIndexOf(separator, statementStart - 1))\n .filter((offset) => offset >= 0)\n .map((offset) => offset + 1);\n precedingBoundaries.push(0);\n const followingBoundaries = [';', '\\n', '}']\n .map((separator) => sourceCode.indexOf(separator, specifierEnd))\n .filter((offset) => offset >= 0)\n .map((offset) => offset + 1);\n const starts = [\n ...precedingBoundaries.sort((left, right) => right - left),\n statementStart,\n ];\n const ends = [\n ...followingBoundaries.sort((left, right) => left - right),\n specifierEnd,\n ];\n const candidates = new Set<string>();\n for (const start of starts) {\n for (const end of ends) {\n if (end <= start) continue;\n const candidate = sourceCode.slice(start, end).trim();\n if (candidate) candidates.add(candidate);\n }\n }\n return [...candidates];\n}\n\ntype StandaloneProbeLanguage = 'flow' | 'js' | 'jsx' | 'ts' | 'tsx';\n\n/** Runs one syntax-tolerant, read-only provenance classification pass. */\nfunction probeStandaloneGTProvenance(\n sourceCode: string,\n filePath: string,\n options: VueExtractionOptions,\n language: StandaloneProbeLanguage,\n localModules: LocalModuleResolver\n): { hasProvenance: boolean; parsed: boolean } {\n const results: VueExtractionOutput['results'] = [];\n const errors: string[] = [];\n const warnings = new Set<string>();\n const projectRoot = options.projectRoot ?? process.cwd();\n const context = createVueExtractionContext(\n filePath,\n sourceCode,\n projectRoot,\n false,\n options.surroundingLineCount ?? DEFAULT_SURROUNDING_LINE_COUNT,\n results,\n errors,\n warnings\n );\n const analysis = createVueScriptAnalysis();\n analysis.entryFile = filePath;\n analysis.localModules = localModules;\n const parsed = parseVueScript(\n sourceCode,\n language,\n context,\n createTemplateBindings(),\n false,\n analysis,\n false\n );\n if (results.length > 0 || analysisHasGTProvenance(analysis)) {\n return { hasProvenance: true, parsed };\n }\n return { hasProvenance: false, parsed };\n}\n\n/**\n * Finds concrete module references when malformed syntax prevents a full AST.\n *\n * Each supported grammar recovers a complete prefix, then the grammar that\n * parsed furthest gets a bounded suffix search. Unterminated literal errors\n * never receive suffix recovery, so literal contents cannot become code.\n */\nfunction hasMalformedStandaloneGTProvenance(\n sourceCode: string,\n filePath: string,\n options: VueExtractionOptions,\n languages: ReadonlySet<StandaloneProbeLanguage>,\n localModules: LocalModuleResolver,\n recoveredPreamble: string\n): boolean {\n for (const language of languages) {\n if (\n leadingStatementPrefixHasGTProvenance(\n sourceCode,\n filePath,\n options,\n language,\n localModules\n )\n ) {\n return true;\n }\n }\n const suffixSelection = selectMalformedSuffixLanguage(sourceCode, languages);\n return Boolean(\n suffixSelection?.recoverable &&\n malformedSuffixHasGTProvenance(\n sourceCode,\n filePath,\n options,\n suffixSelection.language,\n localModules,\n recoveredPreamble\n )\n );\n}\n\n/** Preserves CommonJS and TypeScript import ownership before a syntax error. */\nfunction leadingStatementPrefixHasGTProvenance(\n sourceCode: string,\n filePath: string,\n options: VueExtractionOptions,\n language: StandaloneProbeLanguage,\n localModules: LocalModuleResolver\n): boolean {\n let errorOffset: number;\n try {\n parseScriptAst(sourceCode, language);\n return false;\n } catch (error) {\n const offset = (error as { pos?: unknown }).pos;\n if (typeof offset !== 'number') return false;\n errorOffset = offset;\n }\n const boundary = Math.max(\n sourceCode.lastIndexOf(';', errorOffset - 1) + 1,\n sourceCode.lastIndexOf('\\n', errorOffset - 1) + 1,\n sourceCode.lastIndexOf('}', errorOffset - 1) + 1\n );\n if (boundary <= 0) return false;\n const prefix = sourceCode.slice(0, boundary).trimEnd();\n if (!prefix) return false;\n const probe = probeStandaloneGTProvenance(\n prefix,\n filePath,\n options,\n language,\n localModules\n );\n return probe.hasProvenance;\n}\n\n/** Recovers later imports and CommonJS calls after a bounded number of errors. */\nfunction malformedSuffixHasGTProvenance(\n sourceCode: string,\n filePath: string,\n options: VueExtractionOptions,\n language: StandaloneProbeLanguage,\n localModules: LocalModuleResolver,\n recoveredPreamble: string\n): boolean {\n let remaining = sourceCode;\n for (let attempt = 0; attempt < MAX_MALFORMED_SUFFIX_RECOVERIES; attempt++) {\n let errorOffset: number;\n try {\n parseScriptAst(remaining, language);\n const recoveredSource = recoveredPreamble\n ? `${recoveredPreamble}\\n${remaining}`\n : remaining;\n const recoveredProbe = probeStandaloneGTProvenance(\n recoveredSource,\n filePath,\n options,\n language,\n localModules\n );\n if (recoveredProbe.parsed) return recoveredProbe.hasProvenance;\n // The remaining suffix may already contain the declaration retained in\n // the preamble. Probe it alone to avoid a duplicate-binding parse error.\n return probeStandaloneGTProvenance(\n remaining,\n filePath,\n options,\n language,\n localModules\n ).hasProvenance;\n } catch (error) {\n const parseError = readRecoverableParseError(error);\n if (!parseError) return false;\n errorOffset = parseError.offset;\n }\n const boundary = findMalformedRecoveryBoundary(remaining, errorOffset);\n if (boundary <= 0 || boundary >= remaining.length) return false;\n remaining = remaining.slice(boundary);\n const recoveredSource = recoveredPreamble\n ? `${recoveredPreamble}\\n${remaining}`\n : remaining;\n let probe = probeStandaloneGTProvenance(\n recoveredSource,\n filePath,\n options,\n language,\n localModules\n );\n if (!probe.parsed && recoveredPreamble) {\n const trimmedRemaining = trimTrailingRecoveryClosers(remaining);\n if (trimmedRemaining !== remaining) {\n probe = probeStandaloneGTProvenance(\n `${recoveredPreamble}\\n${trimmedRemaining}`,\n filePath,\n options,\n language,\n localModules\n );\n }\n }\n if (probe.hasProvenance) return true;\n if (probe.parsed) return false;\n }\n return false;\n}\n\n/** Removes block closers orphaned when recovery starts inside a function. */\nfunction trimTrailingRecoveryClosers(sourceCode: string): string {\n let end = sourceCode.length;\n while (end > 0 && sourceCode[end - 1]!.trim() === '') end -= 1;\n if (sourceCode[end - 1] !== '}') return sourceCode.slice(0, end);\n\n do {\n end -= 1;\n while (end > 0 && sourceCode[end - 1]!.trim() === '') end -= 1;\n } while (sourceCode[end - 1] === '}');\n return sourceCode.slice(0, end);\n}\n\n/** Chooses the grammar that parsed furthest before a recoverable error. */\nfunction selectMalformedSuffixLanguage(\n sourceCode: string,\n languages: ReadonlySet<StandaloneProbeLanguage>\n): { language: StandaloneProbeLanguage; recoverable: boolean } | undefined {\n let selected:\n | { language: StandaloneProbeLanguage; recoverable: boolean }\n | undefined;\n let furthestOffset = -1;\n for (const language of languages) {\n try {\n parseScriptAst(sourceCode, language);\n } catch (error) {\n const parseError = readParseError(error);\n if (parseError && parseError.offset > furthestOffset) {\n selected = {\n language,\n recoverable: parseError.recoverable,\n };\n furthestOffset = parseError.offset;\n }\n }\n }\n return selected;\n}\n\n/** Rejects recovery that could reinterpret unterminated literal contents. */\nfunction readRecoverableParseError(\n error: unknown\n): { offset: number } | undefined {\n const parsed = readParseError(error);\n return parsed?.recoverable ? { offset: parsed.offset } : undefined;\n}\n\n/** Reads one Babel parser error without trusting unterminated literal state. */\nfunction readParseError(\n error: unknown\n): { offset: number; recoverable: boolean } | undefined {\n const parsed = error as { pos?: unknown; reasonCode?: unknown };\n if (typeof parsed.pos !== 'number') return undefined;\n const unsafeReasonCodes = new Set([\n 'UnterminatedComment',\n 'UnterminatedJsxContent',\n 'UnterminatedRegExp',\n 'UnterminatedString',\n 'UnterminatedTemplate',\n ]);\n return {\n offset: parsed.pos,\n recoverable:\n typeof parsed.reasonCode !== 'string' ||\n !unsafeReasonCodes.has(parsed.reasonCode),\n };\n}\n\n/** Selects the first statement-like boundary after a parser error. */\nfunction findMalformedRecoveryBoundary(\n sourceCode: string,\n errorOffset: number\n): number {\n const candidates = [';', '\\n', '}']\n .map((separator) => sourceCode.indexOf(separator, errorOffset))\n .filter((offset) => offset >= 0);\n return candidates.length > 0 ? Math.min(...candidates) + 1 : -1;\n}\n\n/** Returns whether permissive analysis reached a concrete gt-vue identity. */\nfunction analysisHasGTProvenance(analysis: VueScriptAnalysis): boolean {\n return analysis.hasGTSourceReference;\n}\n\nfunction parseVueSingleFileComponent(\n source: string,\n context: VueExtractionContext,\n compilerOptions: VueCompilerOptions,\n resolvedCompiler: ResolvedVueCompiler,\n scriptAnalysis: VueScriptAnalysis\n): void {\n const { compiler } = resolvedCompiler;\n if (\n compilerOptions.delimiters &&\n !resolvedCompiler.templateCompiler &&\n !resolvedCompiler.templateParseOptionsSupported\n ) {\n addVueError(\n context,\n undefined,\n 'Could not safely apply custom Vue template delimiters with the supplied compiler',\n 'Let the extractor resolve the consuming app compiler, or supply a Vue compiler that applies templateParseOptions during SFC parsing'\n );\n return;\n }\n const expressionPlugins: ParserPlugin[] = sourceUsesTypeScript(source)\n ? ['typescript']\n : [];\n const templateCompiler = createConfiguredTemplateCompiler(\n resolvedCompiler,\n compilerOptions,\n expressionPlugins,\n true\n );\n const result = compiler.parse(source, {\n ...(templateCompiler && { compiler: templateCompiler }),\n filename: context.file,\n pad: 'space',\n sourceMap: false,\n templateParseOptions: {\n ...compilerOptions,\n comments: true,\n expressionPlugins,\n },\n });\n\n for (const error of result.errors) {\n const compilerError =\n typeof error === 'string'\n ? undefined\n : (error as SyntaxError & {\n loc?: Parameters<typeof normalizeCompilerLocation>[0];\n });\n addVueError(\n context,\n compilerError?.loc\n ? normalizeCompilerLocation(compilerError.loc)\n : undefined,\n `Could not parse a gt-vue single-file component: ${typeof error === 'string' ? error : error.message}`,\n 'Fix the Vue template syntax before extracting translations'\n );\n }\n // Vue's SFC parser recovers a partial AST for malformed markup. Publishing\n // translations from that recovery tree can replace complete catalogs with\n // an incomplete source set, so structural parse errors are file-fatal.\n if (result.errors.length > 0) return;\n\n const bindings = createTemplateBindings();\n collectScriptBlockImports(result.descriptor.script, scriptAnalysis);\n collectScriptBlockImports(result.descriptor.scriptSetup, scriptAnalysis);\n const scriptValid = parseScriptBlock(\n result.descriptor.script,\n false,\n context,\n bindings,\n scriptAnalysis\n );\n if (result.descriptor.scriptSetup) {\n exposeVueScriptImportsToTemplate(scriptAnalysis, bindings);\n }\n const scriptSetupValid = parseScriptBlock(\n result.descriptor.scriptSetup,\n true,\n context,\n bindings,\n scriptAnalysis\n );\n if (!scriptValid || !scriptSetupValid) {\n context.results.length = 0;\n return;\n }\n\n const template = result.descriptor.template;\n if (!template) return;\n if (template.lang && template.lang !== 'html') {\n addVueError(\n context,\n template.loc,\n `Found unsupported Vue template language \"${template.lang}\"`,\n 'Use a standard HTML Vue template for gt-vue extraction'\n );\n context.results.length = 0;\n return;\n }\n if (template.src) {\n addVueError(\n context,\n template.loc,\n 'Found an externally sourced Vue template',\n 'Keep the template in the .vue file so gt-vue can extract it'\n );\n context.results.length = 0;\n return;\n }\n const templateAst = resolvedCompiler.parseTemplate\n ? parseTemplateWithCompiler(\n template.content,\n compilerOptions,\n expressionPlugins,\n true,\n context,\n resolvedCompiler.parseTemplate,\n template.loc.start\n )\n : (template.ast as unknown as RootNode);\n if (templateAst) {\n const templateResultStart = context.results.length;\n const templateErrorStart = context.errors.length;\n parseVueTemplate(templateAst, bindings, expressionPlugins, context);\n if (\n context.errors.length === templateErrorStart &&\n template.content.includes('<!--') &&\n !matchesProductionTemplate(\n source,\n compilerOptions,\n expressionPlugins,\n bindings,\n context,\n templateResultStart,\n resolvedCompiler\n )\n ) {\n context.results.length = templateResultStart;\n addVueError(\n context,\n template.loc,\n 'Found translatable Vue content whose hash changes between development and production',\n 'Remove comments that split translatable text or whitespace, or move those comments outside gt-vue <T> components'\n );\n }\n }\n}\n\n/**\n * Verifies that Vite's production comment stripping preserves extracted data.\n *\n * Vue parses templates with comments in development and without them in\n * production. Removing a comment can renormalize adjacent whitespace, so a\n * single persisted catalog key cannot serve both builds. The second parse is\n * limited to templates that contain comments and never executes project code.\n */\nfunction matchesProductionTemplate(\n source: string,\n compilerOptions: VueCompilerOptions,\n expressionPlugins: ParserPlugin[],\n bindings: TemplateBindings,\n context: VueExtractionContext,\n developmentResultStart: number,\n resolvedCompiler: ResolvedVueCompiler\n): boolean {\n const { compiler } = resolvedCompiler;\n const templateCompiler = createConfiguredTemplateCompiler(\n resolvedCompiler,\n compilerOptions,\n expressionPlugins,\n false\n );\n const production = compiler.parse(source, {\n ...(templateCompiler && { compiler: templateCompiler }),\n filename: context.file,\n pad: 'space',\n sourceMap: false,\n templateParseOptions: {\n ...compilerOptions,\n comments: false,\n expressionPlugins,\n },\n });\n const template = production.descriptor.template;\n if (production.errors.length > 0 || !template) return false;\n\n const productionContext: VueExtractionContext = {\n ...context,\n errors: [],\n results: [],\n warnings: new Set(),\n };\n const templateAst = resolvedCompiler.parseTemplate\n ? parseTemplateWithCompiler(\n template.content,\n compilerOptions,\n expressionPlugins,\n false,\n productionContext,\n resolvedCompiler.parseTemplate,\n template.loc.start\n )\n : (template.ast as unknown as RootNode);\n if (!templateAst) return false;\n parseVueTemplate(templateAst, bindings, expressionPlugins, productionContext);\n if (productionContext.errors.length > 0) return false;\n\n const developmentResults = context.results.slice(developmentResultStart);\n return (\n comparableTemplateResults(developmentResults) ===\n comparableTemplateResults(productionContext.results)\n );\n}\n\n/**\n * Applies hash-affecting options during compiler-sfc's structural parse.\n *\n * Vue 3.3 ignores `templateParseOptions`, which can make delimiter-shaped text\n * close an SFC block before the exact template-content parse runs. Supplying\n * the adjacent compiler-dom parser makes the descriptor structural parse use\n * the same delimiters and whitespace. Vue 3.3 caches SFC parses using the\n * parser function's string form, so its deterministic identity includes every\n * closure-captured option to prevent cross-option cache poisoning.\n */\nfunction createConfiguredTemplateCompiler(\n resolvedCompiler: ResolvedVueCompiler,\n compilerOptions: VueCompilerOptions,\n expressionPlugins: ParserPlugin[],\n comments: boolean\n): TemplateCompiler | undefined {\n const templateCompiler = resolvedCompiler.templateCompiler;\n if (!templateCompiler) return undefined;\n\n const parse: TemplateCompiler['parse'] = (source, baseOptions) => {\n const options: CompatibleTemplateParserOptions = {\n ...baseOptions,\n ...compilerOptions,\n comments,\n expressionPlugins,\n };\n return templateCompiler.parse(source, options);\n };\n const identity = JSON.stringify({\n comments,\n delimiters: compilerOptions.delimiters,\n expressionPlugins,\n version: resolvedCompiler.version,\n whitespace: compilerOptions.whitespace,\n });\n Object.defineProperty(parse, 'toString', {\n value: () => `gtVueTemplateParse:${identity}`,\n });\n\n return { compile: templateCompiler.compile, parse };\n}\n\n/** Parses template content with the exact compiler-dom beside consumer Vue. */\nfunction parseTemplateWithCompiler(\n source: string,\n compilerOptions: VueCompilerOptions,\n expressionPlugins: ParserPlugin[],\n comments: boolean,\n context: VueExtractionContext,\n parseTemplate: NonNullable<ResolvedVueCompiler['parseTemplate']>,\n origin: CompilerPosition\n): RootNode | undefined {\n const errors: Array<SyntaxError & { loc?: ExtractionLocationLike }> = [];\n const options: CompatibleCompilerDomParserOptions = {\n ...compilerOptions,\n comments,\n expressionPlugins,\n onError(error) {\n errors.push(error as SyntaxError & { loc?: ExtractionLocationLike });\n },\n };\n const ast = parseTemplate(source, options);\n if (errors.length === 0) {\n shiftCompilerAstLocations(ast, origin);\n return ast;\n }\n const shiftedErrorPositions = new WeakSet<object>();\n for (const error of errors) {\n if (error.loc) {\n shiftCompilerLocation(error.loc, origin, shiftedErrorPositions);\n }\n addVueError(\n context,\n error.loc ? normalizeCompilerLocation(error.loc) : undefined,\n `Could not parse a gt-vue template: ${error.message}`,\n 'Fix the Vue template syntax before extracting translations'\n );\n }\n return undefined;\n}\n\ntype ExtractionLocationLike = Parameters<typeof normalizeCompilerLocation>[0];\ntype CompilerPosition = {\n column: number;\n line: number;\n offset: number;\n};\n\n/** Omits location-only metadata while comparing persisted template content. */\nfunction comparableTemplateResults(\n results: VueExtractionOutput['results']\n): string {\n return JSON.stringify(\n results.map((result) => ({\n dataFormat: result.dataFormat,\n metadata: {\n context: result.metadata.context,\n id: result.metadata.id,\n maxChars: result.metadata.maxChars,\n requiresReview: result.metadata.requiresReview,\n },\n source: result.source,\n }))\n );\n}\n\nfunction collectScriptBlockImports(\n block: SFCBlock | null,\n scriptAnalysis: VueScriptAnalysis\n): void {\n if (!block || block.src || !isSupportedScriptLanguage(block.lang)) return;\n collectVueScriptImports(block.content, block.lang, scriptAnalysis);\n}\n\nfunction parseScriptBlock(\n block: SFCBlock | null,\n exposeToTemplate: boolean,\n context: VueExtractionContext,\n bindings: TemplateBindings,\n scriptAnalysis: VueScriptAnalysis\n): boolean {\n if (!block) return true;\n if (block.src) {\n addVueError(\n context,\n block.loc,\n 'Found an externally sourced Vue script block',\n 'Keep translation calls and gt-vue imports in the .vue file'\n );\n return false;\n }\n if (!isSupportedScriptLanguage(block.lang)) {\n addVueError(\n context,\n block.loc,\n `Found unsupported Vue script language \"${block.lang}\"`,\n 'Use JavaScript or TypeScript for gt-vue extraction'\n );\n return false;\n }\n\n return parseVueScript(\n block.content,\n block.lang,\n context,\n bindings,\n exposeToTemplate,\n scriptAnalysis\n );\n}\n\nfunction createTemplateBindings(): TemplateBindings {\n return {\n arrayLengths: new Map(),\n componentFactories: new Set(),\n components: new Map(),\n containerKinds: new Map(),\n possibleGTContainers: new Set(),\n gtContainerFactories: new Set(),\n directBindings: new Set(),\n registeredComponents: new Map(),\n registeredVueBuiltins: new Map(),\n staticValues: new Map(),\n identityFunctions: new Set(),\n possibleStaticStrings: new Map(),\n stringFunctions: new Map(),\n uncertainStringFunctions: new Set(),\n uncertainComponents: new Set(),\n uncertainGTComponents: new Set(),\n gtComponentFactories: new Set(),\n uncertainRegisteredComponents: new Set(),\n uncertainRegisteredGTComponents: new Set(),\n vueBuiltins: new Map(),\n };\n}\n\nfunction sourceUsesTypeScript(source: string): boolean {\n let offset = 0;\n while (offset < source.length) {\n const start = source.indexOf('<script', offset);\n if (start === -1) return false;\n const boundary = source[start + '<script'.length];\n if (boundary !== '>' && !boundary?.match(/\\s/)) {\n offset = start + '<script'.length;\n continue;\n }\n\n const end = findOpeningTagEnd(source, start + '<script'.length);\n if (end === -1) return false;\n const language = readOpeningTagAttribute(\n source.slice(start + '<script'.length, end),\n 'lang'\n );\n if (typeof language === 'string' && /^tsx?$/i.test(language)) return true;\n offset = end + 1;\n }\n return false;\n}\n\nfunction isSupportedScriptLanguage(language: string | undefined): boolean {\n const normalizedLanguage = language?.toLowerCase();\n return (\n normalizedLanguage === undefined ||\n normalizedLanguage === 'js' ||\n normalizedLanguage === 'jsx' ||\n normalizedLanguage === 'ts' ||\n normalizedLanguage === 'tsx'\n );\n}\n\n/** Finds an opening tag boundary while respecting quoted attribute values. */\nfunction findOpeningTagEnd(source: string, start: number): number {\n let quote: '\"' | \"'\" | undefined;\n for (let index = start; index < source.length; index += 1) {\n const character = source[index];\n if (quote) {\n if (character === quote) quote = undefined;\n } else if (character === '\"' || character === \"'\") {\n quote = character;\n } else if (character === '>') {\n return index;\n }\n }\n return -1;\n}\n\n/** Reads one case-sensitive SFC attribute with quoted or unquoted syntax. */\nfunction readOpeningTagAttribute(\n attributes: string,\n requestedName: string\n): string | true | undefined {\n let offset = 0;\n while (offset < attributes.length) {\n while (offset < attributes.length && /\\s/.test(attributes[offset])) {\n offset += 1;\n }\n if (attributes[offset] === '/') {\n offset += 1;\n continue;\n }\n const nameStart = offset;\n while (offset < attributes.length && !/[\\s=]/.test(attributes[offset])) {\n offset += 1;\n }\n const name = attributes.slice(nameStart, offset);\n if (!name) break;\n\n while (offset < attributes.length && /\\s/.test(attributes[offset])) {\n offset += 1;\n }\n let value: string | true = true;\n if (attributes[offset] === '=') {\n offset += 1;\n while (offset < attributes.length && /\\s/.test(attributes[offset])) {\n offset += 1;\n }\n const quote = attributes[offset];\n if (quote === '\"' || quote === \"'\") {\n offset += 1;\n const valueStart = offset;\n while (offset < attributes.length && attributes[offset] !== quote) {\n offset += 1;\n }\n value = attributes.slice(valueStart, offset);\n if (attributes[offset] === quote) offset += 1;\n } else {\n const valueStart = offset;\n while (offset < attributes.length && !/\\s/.test(attributes[offset])) {\n offset += 1;\n }\n value = attributes.slice(valueStart, offset);\n }\n }\n if (name === requestedName) return value;\n }\n return undefined;\n}\n\nfunction languageFromExtension(\n extension: string\n): Exclude<StandaloneProbeLanguage, 'flow'> {\n if (extension === '.ts' || extension === '.mts' || extension === '.cts') {\n return 'ts';\n }\n if (extension === '.tsx') return 'tsx';\n if (extension === '.jsx') return 'jsx';\n return 'js';\n}\n\nfunction normalizeCompilerLocation(location: {\n end?: { column?: number; line?: number; offset?: number };\n start?: { column?: number; line?: number; offset?: number };\n}) {\n const start = location.start ?? {};\n const end = location.end ?? start;\n return {\n start: {\n column: start.column ?? 1,\n line: start.line ?? 1,\n offset: start.offset ?? 0,\n },\n end: {\n column: end.column ?? start.column ?? 1,\n line: end.line ?? start.line ?? 1,\n offset: end.offset ?? start.offset ?? 0,\n },\n };\n}\n"],"mappings":"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"}
@@ -138,7 +138,7 @@ function parseVueScript(source, language, context, templateBindings, exposeToTem
138
138
  const localCallable = resolveCalledFunction(path.node.callee, path.scope, state, /* @__PURE__ */ new Set());
139
139
  const calleePath = readResolvedMemberPath(path.node.callee, path.scope, state);
140
140
  const uncertainTranslationHelper = Boolean(calleePath && pathMayReferenceUncertainTranslationHelper(path.node.callee, calleePath, path.scope, state) && callArgumentsMayProvideTranslationFunction(path.node, path.scope, state));
141
- if (!callTarget.definitelyOrdinary && !localCallable && calleePath && (callTarget.possibleStringFunction || uncertainTranslationHelper || templateBindings.uncertainStringFunctions.has(calleePath) || state.analysis.uncertainStringFunctions.has(calleePath) || calleePath.endsWith(".value") && templateBindings.uncertainStringFunctions.has(calleePath.slice(0, -6)))) addVueError(context, consumerLocation, `Could not statically resolve possible gt-vue string function alias "${calleePath}"`, "Use a direct, immutable alias of useGT(), useMessages(), or msg()");
141
+ if (!callTarget.definitelyOrdinary && !localCallable && calleePath && (callTarget.possibleStringFunction || uncertainTranslationHelper || templateBindings.uncertainStringFunctions.has(calleePath) || state.analysis.uncertainStringFunctions.has(calleePath) || calleePath.endsWith(".value") && templateBindings.uncertainStringFunctions.has(calleePath.slice(0, -6)))) addVueError(context, consumerLocation, `Could not statically resolve possible gt-vue string function alias "${calleePath}"`, "Use a direct, immutable alias of useGT(), useMessages(), msg(), or t()");
142
142
  processForwardedTranslationCalls(path, consumerLocation);
143
143
  return;
144
144
  }
@@ -374,6 +374,7 @@ function recordRuntimeReexport(source, exportNames, importerFile, state) {
374
374
  if ((exportNames.includes("*") ? [
375
375
  ...COMPONENT_IMPORTS,
376
376
  "msg",
377
+ "t",
377
378
  "useGT",
378
379
  "useMessages"
379
380
  ] : exportNames).some((name) => resolver.hasGTExportReference(modulePath, name))) state.analysis.hasGTSourceReference = true;
@@ -447,6 +448,7 @@ function recordDynamicImportPattern(pattern, source, scope, importerFile, state)
447
448
  for (const exportName of [
448
449
  ...COMPONENT_IMPORTS,
449
450
  "msg",
451
+ "t",
450
452
  "useGT",
451
453
  "useMessages"
452
454
  ]) recordDynamicImportBinding(appendTemplatePath(pattern.name, exportName), exportName, modulePath, state, bindingReferencesNamespaceMember(binding, exportName, state));
@@ -456,11 +458,13 @@ function recordDynamicImportPattern(pattern, source, scope, importerFile, state)
456
458
  state.analysis.uncertainComponents.add(path);
457
459
  state.analysis.uncertainGTComponents.add(path);
458
460
  }
459
- for (const name of [
461
+ const stringFunctions = [
460
462
  "msg",
461
463
  "useGT",
462
464
  "useMessages"
463
- ]) state.analysis.uncertainStringFunctions.add(appendTemplatePath(pattern.name, name));
465
+ ];
466
+ if (source === "gt-vue") stringFunctions.push("t");
467
+ for (const name of stringFunctions) state.analysis.uncertainStringFunctions.add(appendTemplatePath(pattern.name, name));
464
468
  }
465
469
  return;
466
470
  }
@@ -470,14 +474,14 @@ function recordDynamicImportPattern(pattern, source, scope, importerFile, state)
470
474
  const exportedName = readPropertyKey(property);
471
475
  const localName = readPatternIdentifier(property.value);
472
476
  if (exportedName && localName) if (modulePath) recordDynamicImportBinding(localName, exportedName, modulePath, state, importerFile === state.analysis.entryFile);
473
- else recordUnresolvedGTShapedBinding(localName, exportedName, state);
477
+ else recordUnresolvedGTShapedBinding(localName, exportedName, state, source === "gt-vue");
474
478
  }
475
479
  for (const property of pattern.properties) {
476
480
  if (property.type !== "ObjectProperty" || !property.computed) continue;
477
481
  const exportedName = readResolvedPropertyKey(property, scope, state);
478
482
  const localName = readPatternIdentifier(property.value);
479
483
  if (exportedName && localName) if (modulePath) recordDynamicImportBinding(localName, exportedName, modulePath, state, importerFile === state.analysis.entryFile);
480
- else recordUnresolvedGTShapedBinding(localName, exportedName, state);
484
+ else recordUnresolvedGTShapedBinding(localName, exportedName, state, source === "gt-vue");
481
485
  }
482
486
  }
483
487
  /** Returns whether one namespace binding is used through a static member. */
@@ -678,6 +682,7 @@ function recordLocalNamespaceMembers(localName, modulePath, state, binding) {
678
682
  ...resolver.listExportNames(modulePath),
679
683
  ...COMPONENT_IMPORTS,
680
684
  "msg",
685
+ "t",
681
686
  "useGT",
682
687
  "useMessages"
683
688
  ]);
@@ -705,27 +710,29 @@ function recordLocalNamespaceMembers(localName, modulePath, state, binding) {
705
710
  /** Retains the original gt-vue role hidden by a malformed re-export alias. */
706
711
  function recordInvalidGTResolution(localName, resolution, state) {
707
712
  if (resolution.gtExportName === "*") {
708
- recordUnresolvedGTNamespace(localName, state);
713
+ recordUnresolvedGTNamespace(localName, state, true);
709
714
  return;
710
715
  }
711
716
  if (resolution.gtExportName) {
712
- recordUnresolvedGTShapedBinding(localName, resolution.gtExportName, state);
717
+ recordUnresolvedGTShapedBinding(localName, resolution.gtExportName, state, true);
713
718
  return;
714
719
  }
715
720
  state.analysis.uncertainTranslationHelpers.add(localName);
716
721
  }
717
722
  /** Marks the GT-shaped members of one unresolved namespace path. */
718
- function recordUnresolvedGTNamespace(localName, state) {
723
+ function recordUnresolvedGTNamespace(localName, state, includeImmediateTranslation = false) {
719
724
  for (const component of COMPONENT_IMPORTS) {
720
725
  const componentPath = appendTemplatePath(localName, component);
721
726
  state.analysis.uncertainComponents.add(componentPath);
722
727
  state.analysis.uncertainGTComponents.add(componentPath);
723
728
  }
724
- for (const name of [
729
+ const stringFunctions = [
725
730
  "msg",
726
731
  "useGT",
727
732
  "useMessages"
728
- ]) state.analysis.uncertainStringFunctions.add(appendTemplatePath(localName, name));
733
+ ];
734
+ if (includeImmediateTranslation) stringFunctions.push("t");
735
+ for (const name of stringFunctions) state.analysis.uncertainStringFunctions.add(appendTemplatePath(localName, name));
729
736
  }
730
737
  /** Records unresolved roles only when a local export can actually be GT. */
731
738
  function recordMaterializedLocalUncertainty(localName, materialized, state, forceKnownValues = false) {
@@ -768,12 +775,12 @@ function recordUncertainTranslationHelperBinding(localName, scope, state) {
768
775
  if (binding) state.uncertainTranslationHelperBindings.add(binding);
769
776
  }
770
777
  /** Records the conservative GT roles implied by an unresolved export name. */
771
- function recordUnresolvedGTShapedBinding(localName, exportName, state) {
778
+ function recordUnresolvedGTShapedBinding(localName, exportName, state, includeImmediateTranslation = false) {
772
779
  if (COMPONENT_IMPORTS.has(exportName)) {
773
780
  state.analysis.uncertainComponents.add(localName);
774
781
  state.analysis.uncertainGTComponents.add(localName);
775
782
  }
776
- if (exportName === "msg" || exportName === "useGT" || exportName === "useMessages") state.analysis.uncertainStringFunctions.add(localName);
783
+ if (exportName === "msg" || includeImmediateTranslation && exportName === "t" || exportName === "useGT" || exportName === "useMessages") state.analysis.uncertainStringFunctions.add(localName);
777
784
  }
778
785
  /** Fails closed when a resolved local export is ambiguous or mutable. */
779
786
  function recordAmbiguousLocalBinding(localName, state) {
@@ -1060,6 +1067,7 @@ function exposeKnownValue(localName, value, templateBindings, analysis) {
1060
1067
  else if (value.type === "namespace" && value.source === "gt-vue") {
1061
1068
  for (const component of COMPONENT_IMPORTS) templateBindings.components.set(appendTemplatePath(localName, component), component);
1062
1069
  templateBindings.stringFunctions.set(appendTemplatePath(localName, "msg"), "msg");
1070
+ templateBindings.stringFunctions.set(appendTemplatePath(localName, "t"), "t");
1063
1071
  } else if (value.type === "namespace" && value.source === "vue") {
1064
1072
  for (const builtin of VUE_BUILTIN_IMPORTS) templateBindings.vueBuiltins.set(appendTemplatePath(localName, builtin), builtin);
1065
1073
  templateBindings.identityFunctions.add(appendTemplatePath(localName, "markRaw"));
@@ -1104,6 +1112,7 @@ function exposeUncertainKnownValue(localName, value, uncertainComponents, uncert
1104
1112
  uncertainGTComponents.add(appendTemplatePath(localName, component));
1105
1113
  }
1106
1114
  uncertainStringFunctions.add(appendTemplatePath(localName, "msg"));
1115
+ uncertainStringFunctions.add(appendTemplatePath(localName, "t"));
1107
1116
  } else if (value.type === "namespace" && value.source === "vue") for (const builtin of VUE_BUILTIN_IMPORTS) uncertainComponents.add(appendTemplatePath(localName, builtin));
1108
1117
  }
1109
1118
  /** Exposes a callable whose return can affect template component identity. */
@@ -1324,21 +1333,28 @@ function collectNamespaceRestMemberCandidates(localName, binding, pattern, value
1324
1333
  return key !== void 0 ? [key] : [];
1325
1334
  }));
1326
1335
  const certain = isSafelyReadContainerBinding(binding, binding.identifier, Number.POSITIVE_INFINITY, true, state);
1327
- return (namespace.source === "gt-vue" ? [...[...COMPONENT_IMPORTS].map((name) => ({
1328
- type: "component",
1329
- name
1330
- })), {
1331
- type: "string",
1332
- kind: "msg"
1333
- }] : [...VUE_BUILTIN_IMPORTS].map((name) => ({
1336
+ return (namespace.source === "gt-vue" ? [
1337
+ ...[...COMPONENT_IMPORTS].map((name) => ({
1338
+ type: "component",
1339
+ name
1340
+ })),
1341
+ {
1342
+ type: "string",
1343
+ kind: "msg"
1344
+ },
1345
+ {
1346
+ type: "string",
1347
+ kind: "t"
1348
+ }
1349
+ ] : [...VUE_BUILTIN_IMPORTS].map((name) => ({
1334
1350
  type: "vue-builtin",
1335
1351
  name
1336
1352
  }))).filter((entry) => {
1337
- const name = entry.type === "component" ? entry.name : entry.type === "string" ? "msg" : entry.name;
1353
+ const name = entry.type === "component" ? entry.name : entry.type === "string" ? entry.kind : entry.name;
1338
1354
  return !excluded.has(name);
1339
1355
  }).map((entry) => ({
1340
1356
  certain,
1341
- name: appendTemplatePath(localName, entry.type === "component" ? entry.name : entry.type === "string" ? "msg" : entry.name),
1357
+ name: appendTemplatePath(localName, entry.type === "component" ? entry.name : entry.type === "string" ? entry.kind : entry.name),
1342
1358
  value: entry
1343
1359
  }));
1344
1360
  }
@@ -2171,13 +2187,12 @@ function resolveKnownExpression(node, scope, state, seen) {
2171
2187
  if (expression.type === "LogicalExpression") {
2172
2188
  const left = resolveKnownExpression(expression.left, scope, state, new Set(seen));
2173
2189
  if (left) return expression.operator === "&&" ? resolveKnownExpression(expression.right, scope, state, new Set(seen)) : left;
2174
- const staticLeft = readStaticFromScope(expression.left, scope, /* @__PURE__ */ new Set(), expression.left.end ?? Number.POSITIVE_INFINITY, state.analysis);
2175
- if (!staticLeft.ok) return void 0;
2176
- return (expression.operator === "??" ? staticLeft.value == null : expression.operator === "||" ? !staticLeft.value : Boolean(staticLeft.value)) ? resolveKnownExpression(expression.right, scope, state, new Set(seen)) : void 0;
2190
+ const selection = readStaticLogicalSelection(expression, scope, state, new Set(seen));
2191
+ return selection ? resolveKnownExpression(expression[selection], scope, state, new Set(seen)) : void 0;
2177
2192
  }
2178
2193
  if (expression.type === "ConditionalExpression") {
2179
- const condition = readStaticFromScope(expression.test, scope, /* @__PURE__ */ new Set(), expression.test.end ?? Number.POSITIVE_INFINITY, state.analysis);
2180
- if (condition.ok) return resolveKnownExpression(condition.value ? expression.consequent : expression.alternate, scope, state, new Set(seen));
2194
+ const condition = readStaticTruthiness(expression.test, scope, state, new Set(seen));
2195
+ if (condition) return resolveKnownExpression(condition === "truthy" ? expression.consequent : expression.alternate, scope, state, new Set(seen));
2181
2196
  const consequent = resolveKnownExpression(expression.consequent, scope, state, new Set(seen));
2182
2197
  const alternate = resolveKnownExpression(expression.alternate, scope, state, new Set(seen));
2183
2198
  return consequent && alternate && knownValueKey(consequent) === knownValueKey(alternate) ? consequent : void 0;
@@ -3629,6 +3644,31 @@ function bindingMayReferenceStringFunction(binding, state) {
3629
3644
  if (declaration.type === "VariableDeclarator" && declaration.init && patternMayProduceStringFunction(declaration.id, declaration.init, binding.identifier.name, binding.path.scope, state, new Set([binding]))) return true;
3630
3645
  return binding.constantViolations.some((violation) => violation.isAssignmentExpression() && patternContains(violation.node.left, binding.identifier.name) && expressionMayProduceStringFunction(violation.node.right, violation.scope, state, new Set([binding])));
3631
3646
  }
3647
+ /** Evaluates only side-effect-free truthiness needed for static branch choice. */
3648
+ function readStaticTruthiness(node, scope, state, seen) {
3649
+ const expression = unwrapExpression(node);
3650
+ if (!expression) return void 0;
3651
+ const primitive = readStaticFromScope(expression, scope, new Set(seen), expression.end ?? Number.POSITIVE_INFINITY, state.analysis);
3652
+ if (primitive.ok) {
3653
+ if (primitive.value == null) return "nullish";
3654
+ return primitive.value ? "truthy" : "falsy";
3655
+ }
3656
+ if (expression.type === "ConditionalExpression" || expression.type === "LogicalExpression") return;
3657
+ if (resolveKnownExpression(expression, scope, state, new Set(seen))) return "truthy";
3658
+ if (expression.type === "ArrayExpression" || expression.type === "ArrowFunctionExpression" || expression.type === "ClassExpression" || expression.type === "FunctionExpression" || expression.type === "ObjectExpression" || expression.type === "RegExpLiteral") return "truthy";
3659
+ if (expression.type === "Identifier") {
3660
+ const binding = scope.getBinding(expression.name);
3661
+ if (!binding) return expression.name !== "undefined" && ORDINARY_GLOBAL_VALUES.has(expression.name) ? "truthy" : void 0;
3662
+ if (!binding.constant || seen.has(binding)) return void 0;
3663
+ if (binding.path.isClassDeclaration() || binding.path.isFunctionDeclaration()) return "truthy";
3664
+ }
3665
+ }
3666
+ /** Selects a logical branch when the left value's truthiness is static. */
3667
+ function readStaticLogicalSelection(expression, scope, state, seen = /* @__PURE__ */ new Set()) {
3668
+ const value = readStaticTruthiness(expression.left, scope, state, seen);
3669
+ if (!value) return void 0;
3670
+ return (expression.operator === "??" ? value === "nullish" : expression.operator === "||" ? value !== "truthy" : value === "truthy") ? "right" : "left";
3671
+ }
3632
3672
  /** Tracks expressions whose resulting value can be a gt-vue string function. */
3633
3673
  function expressionMayProduceStringFunction(node, scope, state, seen) {
3634
3674
  if (state.analysis.stats) state.analysis.stats.stringFunctionVisits += 1;
@@ -3667,8 +3707,16 @@ function expressionMayProduceStringFunction(node, scope, state, seen) {
3667
3707
  }
3668
3708
  return expression.arguments.some((argument) => argument.type !== "ArgumentPlaceholder" && (expressionMayProduceStringFunction(argument.type === "SpreadElement" ? argument.argument : argument, scope, state, seen) || containerMayContainStringFunction(argument.type === "SpreadElement" ? argument.argument : argument, scope, state, /* @__PURE__ */ new Set())));
3669
3709
  }
3670
- if (expression.type === "ConditionalExpression") return expressionMayProduceStringFunction(expression.consequent, scope, state, seen) || expressionMayProduceStringFunction(expression.alternate, scope, state, seen);
3671
- if (expression.type === "LogicalExpression") return expressionMayProduceStringFunction(expression.left, scope, state, seen) || expressionMayProduceStringFunction(expression.right, scope, state, seen);
3710
+ if (expression.type === "ConditionalExpression") {
3711
+ const condition = readStaticTruthiness(expression.test, scope, state, seen);
3712
+ if (condition) return expressionMayProduceStringFunction(condition === "truthy" ? expression.consequent : expression.alternate, scope, state, seen);
3713
+ return expressionMayProduceStringFunction(expression.consequent, scope, state, seen) || expressionMayProduceStringFunction(expression.alternate, scope, state, seen);
3714
+ }
3715
+ if (expression.type === "LogicalExpression") {
3716
+ const selection = readStaticLogicalSelection(expression, scope, state);
3717
+ if (selection) return expressionMayProduceStringFunction(expression[selection], scope, state, seen);
3718
+ return expressionMayProduceStringFunction(expression.left, scope, state, seen) || expressionMayProduceStringFunction(expression.right, scope, state, seen);
3719
+ }
3672
3720
  if (expression.type === "SequenceExpression") return expressionMayProduceStringFunction(expression.expressions.at(-1), scope, state, seen);
3673
3721
  if (expression.type === "AssignmentExpression") return expressionMayProduceStringFunction(expression.right, scope, state, seen);
3674
3722
  if (expression.type === "AwaitExpression" || expression.type === "YieldExpression") return expressionMayProduceStringFunction(expression.argument, scope, state, seen);