@immense/vue-pom-generator 1.0.63 → 1.0.64

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/RELEASE_NOTES.md CHANGED
@@ -1,30 +1,48 @@
1
- ```markdown
1
+ Based on the commit message and changes, here are the release notes:
2
+
3
+ ---
4
+
5
+ # v1.0.64
6
+
2
7
  ## Highlights
3
8
 
4
- - Fixed nested component POMs not being properly attached to their parent views
5
- - Added comprehensive test coverage for nested component POM attachment
9
+ - **TypeScript template expression support** Compiler now parses TypeScript annotations in Vue
10
+ template expressions (e.g., `@row-click="(row: RowType) => ..."`), fixing crashes in Nuxt 4 +
11
+ TS codebases
12
+ - **Graceful submit-button fallback** – Submit buttons with dynamic labels now respect
13
+ `missingSemanticNameBehavior: "ignore"` and generate `SubmitButton` / `clickSubmit()` methods
14
+ instead of throwing
15
+ - **Improved TypeScript compatibility** – All three plugin compilation paths (dev-plugin,
16
+ build-plugin, vue-plugin) now support TypeScript expression syntax
6
17
 
7
18
  ## Changes
8
19
 
9
- ### Bug Fixes
10
- - Resolved issue where nested component POMs were not correctly associated with view classes
11
- during generation
12
- - Improved POM attachment logic in class generation module
20
+ ### Parser Enhancements
21
+ - Added `expressionPlugins: ["typescript"]` to all `compilerDom.compile()` call sites
22
+ (dev-plugin, build-plugin, vue-plugin)
23
+ - Vue plugin merges expression plugins with user-supplied `userCompilerOptions` to preserve
24
+ custom configuration
13
25
 
14
- ### Testing
15
- - Added 54 lines of test coverage for class generation including nested component scenarios
16
-
17
- ## Breaking Changes
26
+ ### Submit Button Handling
27
+ - Submit buttons with dynamic inner text (e.g., ternary expressions like `{{ isNew ? 'Create' :
28
+ 'Save' }}`) now honor `missingSemanticNameBehavior: "ignore"` option
29
+ - Falls back to literal `"submit"` identifier when semantic name cannot be derived, generating
30
+ `SubmitButton` / `clickSubmit()` POM surface
31
+ - Default behavior (throwing on missing semantic name) remains unchanged
18
32
 
19
- None
33
+ ### Testing
34
+ - Added 3 regression tests for TypeScript expression parsing and submit-button fallback behavior
35
+ - Test suite: 163 → 166 tests passing
36
+ - All validation passes: typecheck, eslint, build
20
37
 
21
38
  ## Pull Requests Included
22
39
 
23
- None (direct commit to main)
40
+ - fix: parse TypeScript template expressions + allow submit-button fallback
41
+ [#20](https://github.com/immense/vue-pom-generator/pull/20)
24
42
 
25
43
  ## Testing
26
44
 
27
- Tests added to validate nested component POM attachment behavior. Run test suite with `npm
28
- test`.
29
- ```
45
+ Validated on Nuxt 4 + Vue 3 + TypeScript codebase. Three new regression tests added covering
46
+ TypeScript expression parsing and submit-button fallback scenarios. Full test suite passes (166
47
+ tests).
30
48
 
package/dist/index.cjs CHANGED
@@ -258,6 +258,7 @@ function resolveGenerationSupportOptions(options) {
258
258
  customPomImportAliases: options.customPomImportAliases,
259
259
  customPomImportNameCollisionBehavior: options.customPomImportNameCollisionBehavior ?? "error",
260
260
  nameCollisionBehavior: options.nameCollisionBehavior ?? "error",
261
+ missingSemanticNameBehavior: options.missingSemanticNameBehavior ?? "error",
261
262
  existingIdBehavior: options.existingIdBehavior ?? "error",
262
263
  testIdAttribute: (options.testIdAttribute ?? "data-testid").trim() || "data-testid",
263
264
  accessibilityAudit: options.accessibilityAudit ?? false,
@@ -7076,6 +7077,7 @@ function createTestIdTransform(componentName, componentHierarchyMap, nativeWrapp
7076
7077
  const existingIdBehavior = options.existingIdBehavior ?? "error";
7077
7078
  const testIdAttribute = (options.testIdAttribute || "data-testid").trim() || "data-testid";
7078
7079
  const nameCollisionBehavior = options.nameCollisionBehavior ?? "error";
7080
+ const missingSemanticNameBehavior = options.missingSemanticNameBehavior ?? "error";
7079
7081
  const warn = options.warn;
7080
7082
  const vueFilesPathMap = options.vueFilesPathMap;
7081
7083
  const wrapperSearchRoots = options.wrapperSearchRoots ?? [];
@@ -7519,13 +7521,16 @@ Fix: remove the explicit ${attrLabel}, or change existingIdBehavior to "overwrit
7519
7521
  }
7520
7522
  const isSubmit = element.props.find((p) => p.type === compilerCore.NodeTypes.ATTRIBUTE && p.name === "type")?.value?.content === "submit";
7521
7523
  if (isSubmit) {
7522
- const identifier = getStaticIdOrNameHint(element) || innerText;
7524
+ let identifier = getStaticIdOrNameHint(element) || innerText;
7523
7525
  if (!identifier) {
7524
- const loc = element.loc?.start;
7525
- const locationHint = loc ? `${loc.line}:${loc.column}` : "unknown";
7526
- throw new Error(
7527
- `[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`
7528
- );
7526
+ if (missingSemanticNameBehavior === "error") {
7527
+ const loc = element.loc?.start;
7528
+ const locationHint = loc ? `${loc.line}:${loc.column}` : "unknown";
7529
+ throw new Error(
7530
+ `[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.`
7531
+ );
7532
+ }
7533
+ identifier = "submit";
7529
7534
  }
7530
7535
  const testId = getSubmitDataTestId(identifier);
7531
7536
  applyResolvedDataTestIdForElement({
@@ -7592,6 +7597,7 @@ function createBuildProcessorPlugin(options) {
7592
7597
  customPomImportNameCollisionBehavior,
7593
7598
  testIdAttribute,
7594
7599
  nameCollisionBehavior,
7600
+ missingSemanticNameBehavior,
7595
7601
  existingIdBehavior,
7596
7602
  routerAwarePoms,
7597
7603
  routerType,
@@ -7687,6 +7693,9 @@ function createBuildProcessorPlugin(options) {
7687
7693
  prefixIdentifiers: true,
7688
7694
  inline: isScriptSetup,
7689
7695
  bindingMetadata,
7696
+ // See dev-plugin.ts — same rationale: enable TS in template
7697
+ // expressions so `(row: RowType) => ...` handlers parse.
7698
+ expressionPlugins: ["typescript"],
7690
7699
  nodeTransforms: [
7691
7700
  createTestIdTransform(
7692
7701
  componentName,
@@ -7698,6 +7707,7 @@ function createBuildProcessorPlugin(options) {
7698
7707
  existingIdBehavior: existingIdBehavior ?? "error",
7699
7708
  testIdAttribute,
7700
7709
  nameCollisionBehavior,
7710
+ missingSemanticNameBehavior,
7701
7711
  warn: (message) => loggerRef.current.warn(message),
7702
7712
  vueFilesPathMap,
7703
7713
  wrapperSearchRoots: getWrapperSearchRoots()
@@ -7845,6 +7855,7 @@ function createDevProcessorPlugin(options) {
7845
7855
  customPomImportAliases,
7846
7856
  customPomImportNameCollisionBehavior,
7847
7857
  nameCollisionBehavior,
7858
+ missingSemanticNameBehavior,
7848
7859
  existingIdBehavior,
7849
7860
  testIdAttribute,
7850
7861
  routerAwarePoms,
@@ -8029,6 +8040,12 @@ function createDevProcessorPlugin(options) {
8029
8040
  prefixIdentifiers: true,
8030
8041
  inline: isScriptSetup,
8031
8042
  bindingMetadata,
8043
+ // Vue templates may contain TypeScript type annotations in expressions
8044
+ // (e.g. `@row-click="(row: RowType) => navigateTo(...)"` in Nuxt + TS
8045
+ // apps). Without this flag, Vue's internal processExpression step
8046
+ // delegates to @babel/parser without the TS plugin and crashes on
8047
+ // "Unexpected token, expected ','".
8048
+ expressionPlugins: ["typescript"],
8032
8049
  nodeTransforms: [
8033
8050
  createTestIdTransform(
8034
8051
  componentName,
@@ -8039,6 +8056,7 @@ function createDevProcessorPlugin(options) {
8039
8056
  {
8040
8057
  existingIdBehavior: existingIdBehavior ?? "error",
8041
8058
  nameCollisionBehavior,
8059
+ missingSemanticNameBehavior,
8042
8060
  testIdAttribute,
8043
8061
  warn: (message) => loggerRef.current.warn(message),
8044
8062
  vueFilesPathMap: provisionalVuePathMap,
@@ -8786,6 +8804,7 @@ function createVuePluginWithTestIds(options) {
8786
8804
  vueOptions,
8787
8805
  existingIdBehavior,
8788
8806
  nameCollisionBehavior,
8807
+ missingSemanticNameBehavior = "error",
8789
8808
  nativeWrappers,
8790
8809
  elementMetadata,
8791
8810
  semanticNameMap,
@@ -8866,6 +8885,7 @@ function createVuePluginWithTestIds(options) {
8866
8885
  existingIdBehavior,
8867
8886
  testIdAttribute,
8868
8887
  nameCollisionBehavior,
8888
+ missingSemanticNameBehavior,
8869
8889
  warn: (message) => loggerRef.current.warn(message),
8870
8890
  vueFilesPathMap,
8871
8891
  wrapperSearchRoots: getWrapperSearchRoots()
@@ -8920,6 +8940,7 @@ function createVuePluginWithTestIds(options) {
8920
8940
  existingIdBehavior,
8921
8941
  testIdAttribute,
8922
8942
  nameCollisionBehavior,
8943
+ missingSemanticNameBehavior,
8923
8944
  warn: (message) => loggerRef.current.warn(message),
8924
8945
  vueFilesPathMap,
8925
8946
  wrapperSearchRoots: getWrapperSearchRoots()
@@ -8967,9 +8988,16 @@ function createVuePluginWithTestIds(options) {
8967
8988
  const compile = compilerDom2.compile;
8968
8989
  const { descriptor } = parse(code, { filename: cleanPath });
8969
8990
  if (descriptor.template) {
8991
+ const mergedExpressionPlugins = Array.from(
8992
+ /* @__PURE__ */ new Set([
8993
+ "typescript",
8994
+ ...userCompilerOptions.expressionPlugins ?? []
8995
+ ])
8996
+ );
8970
8997
  compile(descriptor.template.content, {
8971
8998
  ...userCompilerOptions,
8972
8999
  filename: cleanPath,
9000
+ expressionPlugins: mergedExpressionPlugins,
8973
9001
  nodeTransforms: getNodeTransforms(cleanPath, componentName)
8974
9002
  });
8975
9003
  loggerRef.current.debug(`Metadata collected for ${cleanPath}`);
@@ -9266,6 +9294,7 @@ function createVuePomGeneratorPlugins(options = {}) {
9266
9294
  customPomImportAliases: resolvedCustomPomImportAliases,
9267
9295
  customPomImportNameCollisionBehavior: customPoms?.importNameCollisionBehavior,
9268
9296
  nameCollisionBehavior: generationOptions?.nameCollisionBehavior,
9297
+ missingSemanticNameBehavior: generationOptions?.missingSemanticNameBehavior,
9269
9298
  existingIdBehavior: resolvedInjectionOptions.existingIdBehavior,
9270
9299
  testIdAttribute,
9271
9300
  accessibilityAudit: generationOptions?.accessibilityAudit,
@@ -9354,6 +9383,7 @@ function createVuePomGeneratorPlugins(options = {}) {
9354
9383
  vueOptions,
9355
9384
  existingIdBehavior: resolvedGenerationOptions.existingIdBehavior,
9356
9385
  nameCollisionBehavior: resolvedGenerationOptions.nameCollisionBehavior,
9386
+ missingSemanticNameBehavior: resolvedGenerationOptions.missingSemanticNameBehavior,
9357
9387
  nativeWrappers,
9358
9388
  elementMetadata,
9359
9389
  semanticNameMap,