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

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.
@@ -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);