@immense/vue-pom-generator 1.0.63 → 1.0.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -5,5 +5,5 @@ export { createVuePomGeneratorPlugins as vuePomGenerator };
5
5
  export default createVuePomGeneratorPlugins;
6
6
  export declare function defineVuePomGeneratorConfig(options: VuePomGeneratorPluginOptions): VuePomGeneratorPluginOptions;
7
7
  export declare function defineNuxtPomGeneratorConfig(options: NuxtPomGeneratorPluginOptions): NuxtPomGeneratorPluginOptions;
8
- export type { ExistingIdBehavior, NuxtPomGeneratorPluginOptions, PomGeneratorPluginOptions, PomNameCollisionBehavior, VuePomGeneratorPluginOptions } from "./plugin/types";
8
+ export type { ExistingIdBehavior, MissingSemanticNameBehavior, NuxtPomGeneratorPluginOptions, PomGeneratorPluginOptions, PomNameCollisionBehavior, VuePomGeneratorPluginOptions } from "./plugin/types";
9
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,4BAA4B,MAAM,2CAA2C,CAAC;AAErF,OAAO,KAAK,EAAE,6BAA6B,EAAE,4BAA4B,EAAE,MAAM,gBAAgB,CAAC;AAIlG,OAAO,EAAE,4BAA4B,EAAE,CAAC;AACxC,OAAO,EAAE,4BAA4B,IAAI,eAAe,EAAE,CAAC;AAC3D,eAAe,4BAA4B,CAAC;AAE5C,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,4BAA4B,GAAG,4BAA4B,CAE/G;AAED,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,6BAA6B,GAAG,6BAA6B,CAOlH;AAED,YAAY,EAAE,kBAAkB,EAAE,6BAA6B,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,4BAA4B,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,4BAA4B,MAAM,2CAA2C,CAAC;AAErF,OAAO,KAAK,EAAE,6BAA6B,EAAE,4BAA4B,EAAE,MAAM,gBAAgB,CAAC;AAIlG,OAAO,EAAE,4BAA4B,EAAE,CAAC;AACxC,OAAO,EAAE,4BAA4B,IAAI,eAAe,EAAE,CAAC;AAC3D,eAAe,4BAA4B,CAAC;AAE5C,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,4BAA4B,GAAG,4BAA4B,CAE/G;AAED,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,6BAA6B,GAAG,6BAA6B,CAOlH;AAED,YAAY,EAAE,kBAAkB,EAAE,2BAA2B,EAAE,6BAA6B,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,4BAA4B,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.mjs CHANGED
@@ -217,6 +217,7 @@ function resolveGenerationSupportOptions(options) {
217
217
  customPomImportAliases: options.customPomImportAliases,
218
218
  customPomImportNameCollisionBehavior: options.customPomImportNameCollisionBehavior ?? "error",
219
219
  nameCollisionBehavior: options.nameCollisionBehavior ?? "error",
220
+ missingSemanticNameBehavior: options.missingSemanticNameBehavior ?? "error",
220
221
  existingIdBehavior: options.existingIdBehavior ?? "error",
221
222
  testIdAttribute: (options.testIdAttribute ?? "data-testid").trim() || "data-testid",
222
223
  accessibilityAudit: options.accessibilityAudit ?? false,
@@ -1853,6 +1854,12 @@ function nodeHandlerAttributeInfo(node) {
1853
1854
  const n = node2;
1854
1855
  return typeof n.computed === "boolean" && typeof n.key === "object" && n.key !== null && typeof n.value === "object" && n.value !== null;
1855
1856
  };
1857
+ const isLogicalExpressionNode = (node2) => {
1858
+ if (!isNodeType2(node2, "LogicalExpression"))
1859
+ return false;
1860
+ const n = node2;
1861
+ return typeof n.operator === "string" && typeof n.left === "object" && n.left !== null && typeof n.right === "object" && n.right !== null;
1862
+ };
1856
1863
  const getLastIdentifierFromMemberChain = (node2) => {
1857
1864
  if (!node2)
1858
1865
  return null;
@@ -2023,48 +2030,66 @@ function nodeHandlerAttributeInfo(node) {
2023
2030
  const semanticNameHint2 = suffix ? `${toPascalCase(name)}${suffix}` : toPascalCase(name);
2024
2031
  return semanticNameHint2;
2025
2032
  };
2033
+ const unwrapSemanticHelperCall = (candidateExpr) => {
2034
+ if (!isCallExpressionNode(candidateExpr)) {
2035
+ return null;
2036
+ }
2037
+ const calleeName = getLastIdentifierFromMemberChain(candidateExpr.callee);
2038
+ if (calleeName !== "_unref" && calleeName !== "unref" && calleeName !== "_withModifiers" && calleeName !== "withModifiers") {
2039
+ return null;
2040
+ }
2041
+ const firstArg = candidateExpr.arguments[0];
2042
+ return typeof firstArg === "object" && firstArg !== null ? firstArg : null;
2043
+ };
2026
2044
  const resolveSemanticName = (candidateExpr) => {
2027
2045
  if (!candidateExpr) {
2028
2046
  return null;
2029
2047
  }
2048
+ const unwrappedHelperCandidate = unwrapSemanticHelperCall(candidateExpr);
2049
+ if (unwrappedHelperCandidate) {
2050
+ return resolveSemanticName(unwrappedHelperCandidate);
2051
+ }
2030
2052
  const direct = getLastIdentifierFromMemberChain(candidateExpr);
2031
2053
  if (direct) {
2032
2054
  return toPascalCase(direct);
2033
2055
  }
2056
+ const directCall = tryFromCallExpression(candidateExpr);
2057
+ if (directCall) {
2058
+ return directCall;
2059
+ }
2060
+ if (isAssignmentExpressionNode(candidateExpr)) {
2061
+ const lhs = getAssignmentTargetName(candidateExpr.left);
2062
+ if (lhs) {
2063
+ const rhs = stableWordFromValue(candidateExpr.right);
2064
+ return `Set${toPascalCase(lhs)}${rhs ?? ""}`;
2065
+ }
2066
+ }
2067
+ if (isLogicalExpressionNode(candidateExpr) && candidateExpr.operator === "&&") {
2068
+ return resolveSemanticName(candidateExpr.right);
2069
+ }
2034
2070
  if (isArrowFunctionExpressionNode(candidateExpr)) {
2035
2071
  const body = candidateExpr.body;
2036
- const directCall = tryFromCallExpression(body);
2037
- if (directCall) {
2038
- return directCall;
2039
- }
2040
- if (isAssignmentExpressionNode(body)) {
2041
- const lhs = getAssignmentTargetName(body.left);
2042
- if (lhs) {
2043
- const rhs = stableWordFromValue(body.right);
2044
- return `Set${toPascalCase(lhs)}${rhs ?? ""}`;
2045
- }
2046
- }
2047
2072
  if (isBlockStatementNode(body)) {
2048
2073
  const stmts = body.body ?? [];
2049
2074
  if (stmts.length > 0) {
2050
2075
  const firstStmt = stmts[0];
2051
2076
  if (isReturnStatementNode(firstStmt)) {
2052
- const fromReturn = tryFromCallExpression(firstStmt.argument ?? null);
2077
+ const fromReturn = resolveSemanticName(firstStmt.argument ?? null);
2053
2078
  if (fromReturn) {
2054
2079
  return fromReturn;
2055
2080
  }
2056
2081
  }
2057
2082
  if (isExpressionStatementNode(firstStmt)) {
2058
- const fromExpr = tryFromCallExpression(firstStmt.expression ?? null);
2083
+ const fromExpr = resolveSemanticName(firstStmt.expression ?? null);
2059
2084
  if (fromExpr) {
2060
2085
  return fromExpr;
2061
2086
  }
2062
2087
  }
2063
2088
  }
2064
2089
  }
2065
- const bodyName = getLastIdentifierFromMemberChain(body);
2090
+ const bodyName = resolveSemanticName(body);
2066
2091
  if (bodyName) {
2067
- return toPascalCase(bodyName);
2092
+ return bodyName;
2068
2093
  }
2069
2094
  }
2070
2095
  return null;
@@ -7035,6 +7060,7 @@ function createTestIdTransform(componentName, componentHierarchyMap, nativeWrapp
7035
7060
  const existingIdBehavior = options.existingIdBehavior ?? "error";
7036
7061
  const testIdAttribute = (options.testIdAttribute || "data-testid").trim() || "data-testid";
7037
7062
  const nameCollisionBehavior = options.nameCollisionBehavior ?? "error";
7063
+ const missingSemanticNameBehavior = options.missingSemanticNameBehavior ?? "error";
7038
7064
  const warn = options.warn;
7039
7065
  const vueFilesPathMap = options.vueFilesPathMap;
7040
7066
  const wrapperSearchRoots = options.wrapperSearchRoots ?? [];
@@ -7478,13 +7504,16 @@ Fix: remove the explicit ${attrLabel}, or change existingIdBehavior to "overwrit
7478
7504
  }
7479
7505
  const isSubmit = element.props.find((p) => p.type === NodeTypes.ATTRIBUTE && p.name === "type")?.value?.content === "submit";
7480
7506
  if (isSubmit) {
7481
- const identifier = getStaticIdOrNameHint(element) || innerText;
7507
+ let identifier = getStaticIdOrNameHint(element) || innerText;
7482
7508
  if (!identifier) {
7483
- const loc = element.loc?.start;
7484
- const locationHint = loc ? `${loc.line}:${loc.column}` : "unknown";
7485
- throw new Error(
7486
- `[vue-pom-generator] submit button appears identifiable but no usable identity could be derived in ${componentName} (${context.filename ?? "unknown"}:${locationHint}) — id/name were missing/empty and innerText was also missing/invalid`
7487
- );
7509
+ if (missingSemanticNameBehavior === "error") {
7510
+ const loc = element.loc?.start;
7511
+ const locationHint = loc ? `${loc.line}:${loc.column}` : "unknown";
7512
+ throw new Error(
7513
+ `[vue-pom-generator] submit button appears identifiable but no usable identity could be derived in ${componentName} (${context.filename ?? "unknown"}:${locationHint}) — id/name were missing/empty and innerText was also missing/invalid. Fix: give the button a static id/name, a static inner text, or set missingSemanticNameBehavior = "ignore" to fall back to the generic "submit" identifier.`
7514
+ );
7515
+ }
7516
+ identifier = "submit";
7488
7517
  }
7489
7518
  const testId = getSubmitDataTestId(identifier);
7490
7519
  applyResolvedDataTestIdForElement({
@@ -7551,6 +7580,7 @@ function createBuildProcessorPlugin(options) {
7551
7580
  customPomImportNameCollisionBehavior,
7552
7581
  testIdAttribute,
7553
7582
  nameCollisionBehavior,
7583
+ missingSemanticNameBehavior,
7554
7584
  existingIdBehavior,
7555
7585
  routerAwarePoms,
7556
7586
  routerType,
@@ -7646,6 +7676,9 @@ function createBuildProcessorPlugin(options) {
7646
7676
  prefixIdentifiers: true,
7647
7677
  inline: isScriptSetup,
7648
7678
  bindingMetadata,
7679
+ // See dev-plugin.ts — same rationale: enable TS in template
7680
+ // expressions so `(row: RowType) => ...` handlers parse.
7681
+ expressionPlugins: ["typescript"],
7649
7682
  nodeTransforms: [
7650
7683
  createTestIdTransform(
7651
7684
  componentName,
@@ -7657,6 +7690,7 @@ function createBuildProcessorPlugin(options) {
7657
7690
  existingIdBehavior: existingIdBehavior ?? "error",
7658
7691
  testIdAttribute,
7659
7692
  nameCollisionBehavior,
7693
+ missingSemanticNameBehavior,
7660
7694
  warn: (message) => loggerRef.current.warn(message),
7661
7695
  vueFilesPathMap,
7662
7696
  wrapperSearchRoots: getWrapperSearchRoots()
@@ -7804,6 +7838,7 @@ function createDevProcessorPlugin(options) {
7804
7838
  customPomImportAliases,
7805
7839
  customPomImportNameCollisionBehavior,
7806
7840
  nameCollisionBehavior,
7841
+ missingSemanticNameBehavior,
7807
7842
  existingIdBehavior,
7808
7843
  testIdAttribute,
7809
7844
  routerAwarePoms,
@@ -7988,6 +8023,12 @@ function createDevProcessorPlugin(options) {
7988
8023
  prefixIdentifiers: true,
7989
8024
  inline: isScriptSetup,
7990
8025
  bindingMetadata,
8026
+ // Vue templates may contain TypeScript type annotations in expressions
8027
+ // (e.g. `@row-click="(row: RowType) => navigateTo(...)"` in Nuxt + TS
8028
+ // apps). Without this flag, Vue's internal processExpression step
8029
+ // delegates to @babel/parser without the TS plugin and crashes on
8030
+ // "Unexpected token, expected ','".
8031
+ expressionPlugins: ["typescript"],
7991
8032
  nodeTransforms: [
7992
8033
  createTestIdTransform(
7993
8034
  componentName,
@@ -7998,6 +8039,7 @@ function createDevProcessorPlugin(options) {
7998
8039
  {
7999
8040
  existingIdBehavior: existingIdBehavior ?? "error",
8000
8041
  nameCollisionBehavior,
8042
+ missingSemanticNameBehavior,
8001
8043
  testIdAttribute,
8002
8044
  warn: (message) => loggerRef.current.warn(message),
8003
8045
  vueFilesPathMap: provisionalVuePathMap,
@@ -8745,6 +8787,7 @@ function createVuePluginWithTestIds(options) {
8745
8787
  vueOptions,
8746
8788
  existingIdBehavior,
8747
8789
  nameCollisionBehavior,
8790
+ missingSemanticNameBehavior = "error",
8748
8791
  nativeWrappers,
8749
8792
  elementMetadata,
8750
8793
  semanticNameMap,
@@ -8825,6 +8868,7 @@ function createVuePluginWithTestIds(options) {
8825
8868
  existingIdBehavior,
8826
8869
  testIdAttribute,
8827
8870
  nameCollisionBehavior,
8871
+ missingSemanticNameBehavior,
8828
8872
  warn: (message) => loggerRef.current.warn(message),
8829
8873
  vueFilesPathMap,
8830
8874
  wrapperSearchRoots: getWrapperSearchRoots()
@@ -8879,6 +8923,7 @@ function createVuePluginWithTestIds(options) {
8879
8923
  existingIdBehavior,
8880
8924
  testIdAttribute,
8881
8925
  nameCollisionBehavior,
8926
+ missingSemanticNameBehavior,
8882
8927
  warn: (message) => loggerRef.current.warn(message),
8883
8928
  vueFilesPathMap,
8884
8929
  wrapperSearchRoots: getWrapperSearchRoots()
@@ -8926,9 +8971,16 @@ function createVuePluginWithTestIds(options) {
8926
8971
  const compile = compilerDom2.compile;
8927
8972
  const { descriptor } = parse2(code, { filename: cleanPath });
8928
8973
  if (descriptor.template) {
8974
+ const mergedExpressionPlugins = Array.from(
8975
+ /* @__PURE__ */ new Set([
8976
+ "typescript",
8977
+ ...userCompilerOptions.expressionPlugins ?? []
8978
+ ])
8979
+ );
8929
8980
  compile(descriptor.template.content, {
8930
8981
  ...userCompilerOptions,
8931
8982
  filename: cleanPath,
8983
+ expressionPlugins: mergedExpressionPlugins,
8932
8984
  nodeTransforms: getNodeTransforms(cleanPath, componentName)
8933
8985
  });
8934
8986
  loggerRef.current.debug(`Metadata collected for ${cleanPath}`);
@@ -9225,6 +9277,7 @@ function createVuePomGeneratorPlugins(options = {}) {
9225
9277
  customPomImportAliases: resolvedCustomPomImportAliases,
9226
9278
  customPomImportNameCollisionBehavior: customPoms?.importNameCollisionBehavior,
9227
9279
  nameCollisionBehavior: generationOptions?.nameCollisionBehavior,
9280
+ missingSemanticNameBehavior: generationOptions?.missingSemanticNameBehavior,
9228
9281
  existingIdBehavior: resolvedInjectionOptions.existingIdBehavior,
9229
9282
  testIdAttribute,
9230
9283
  accessibilityAudit: generationOptions?.accessibilityAudit,
@@ -9313,6 +9366,7 @@ function createVuePomGeneratorPlugins(options = {}) {
9313
9366
  vueOptions,
9314
9367
  existingIdBehavior: resolvedGenerationOptions.existingIdBehavior,
9315
9368
  nameCollisionBehavior: resolvedGenerationOptions.nameCollisionBehavior,
9369
+ missingSemanticNameBehavior: resolvedGenerationOptions.missingSemanticNameBehavior,
9316
9370
  nativeWrappers,
9317
9371
  elementMetadata,
9318
9372
  semanticNameMap,