@immense/vue-pom-generator 1.0.61 → 1.0.62

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,49 +1,39 @@
1
- # Release Notes: v1.0.61
1
+ I'll examine the commits to generate accurate release notes.
2
2
 
3
- ## Highlights
4
-
5
- - **New accessibility audit system** to detect and warn about common ARIA and semantic HTML
6
- issues during POM generation
7
- - Audit signals now included in the manifest output for downstream consumption
8
- - Enhanced compiler metadata utilities to extract role and label information from templates
9
- - Comprehensive test coverage for the new accessibility audit features
3
+ Based on the commit details, here are the release notes for v1.0.62:
10
4
 
11
- ## Changes
5
+ ---
12
6
 
13
- ### Accessibility & Quality
14
- - Added `accessibility-audit.ts` module with audit functions for detecting missing labels,
15
- invalid ARIA usage, and semantic violations
16
- - Integrated audit warnings into the Vite plugin pipeline with configurable severity
17
- - Extended manifest generator to include `auditSignals` for each component
7
+ ## Highlights
18
8
 
19
- ### Plugin & Configuration
20
- - Added `auditSeverity` option to plugin configuration (default: `"warn"`)
21
- - Enhanced `ResolvedGenerationOptions` to support audit configuration
22
- - Updated plugin to emit warnings when accessibility issues are detected during build
9
+ - Fixed handler name preservation after Vue compiler transformations
10
+ - Improved fallback logic to extract semantic names from author-written source code
11
+ - Enhanced test coverage for handler attribute parsing edge cases
23
12
 
24
- ### Compiler & Metadata
25
- - Improved `compiler-metadata-utils.ts` to extract `role` and `aria-label` attributes
26
- - Enhanced metadata collector to capture accessibility-related attributes
13
+ ## Changes
27
14
 
28
- ### Documentation
29
- - Updated README with information about the new accessibility audit feature
15
+ **Bug Fixes**
16
+ - Preserve original handler names when Vue compiler rewrites expressions during compilation
17
+ - Extract semantic names from author source (`loc.content`) rather than transformed source when
18
+ they differ
19
+ - Add fallback expression parsing to handle cases where Vue's transformation breaks Babel AST
20
+ parsing
30
21
 
31
- ### Testing
32
- - Added comprehensive test suite in `tests/accessibility-audit.test.ts` (54 new tests)
33
- - Added tests for resolved generation options
34
- - Updated existing tests to accommodate new audit functionality
22
+ **Testing**
23
+ - Added 38 new test cases for handler attribute transformation scenarios
24
+ - Improved coverage for `utils.ts` edge cases with 36 additional tests
25
+ - Fixed missing `SimpleExpressionNode` import in test files
35
26
 
36
27
  ## Breaking Changes
37
28
 
38
- None.
29
+ None
39
30
 
40
31
  ## Pull Requests Included
41
32
 
42
- - #25 feat: add accessibility audit metadata and warnings
43
- (https://github.com/immense/vue-pom-generator/pull/25) by @dkattan
33
+ None (direct commits to main)
44
34
 
45
35
  ## Testing
46
36
 
47
- All changes include full test coverage. New test suite validates audit detection for missing
48
- labels, invalid ARIA attributes, redundant roles, and other semantic issues.
37
+ All changes include comprehensive test coverage. Added 75+ new test cases covering handler
38
+ attribute parsing, Vue compiler transformations, and semantic name extraction edge cases.
49
39
 
package/dist/index.cjs CHANGED
@@ -1802,11 +1802,12 @@ function nodeHandlerAttributeInfo(node) {
1802
1802
  return null;
1803
1803
  }
1804
1804
  const exp = handlerDirective.exp;
1805
- const source = getVueExpressionSource(exp, "content", "compiled");
1806
- if (!source) {
1805
+ const transformedSource = getVueExpressionSource(exp, "content", "compiled");
1806
+ const authorSource = getVueExpressionSource(exp, "loc", "content", "compiled");
1807
+ if (!authorSource) {
1807
1808
  return null;
1808
1809
  }
1809
- const mergeKey = `handler:expr:${source}`;
1810
+ const mergeKey = `handler:expr:${authorSource}`;
1810
1811
  const expr = tryGetDirectiveBabelAst(handlerDirective, {
1811
1812
  preferredViews: ["content", "compiled"],
1812
1813
  plugins: ["typescript", "jsx"],
@@ -1814,9 +1815,7 @@ function nodeHandlerAttributeInfo(node) {
1814
1815
  // That is fine for Vue codegen, but our semantic-name extraction needs a normal Babel parse tree.
1815
1816
  preferExistingAst: false
1816
1817
  });
1817
- if (!expr) {
1818
- return null;
1819
- }
1818
+ const fallbackExpr = transformedSource !== authorSource ? tryParseBabelExpressionFromSource(authorSource, ["typescript", "jsx"]) : null;
1820
1819
  const isNodeType2 = (node2, type) => {
1821
1820
  return node2 !== null && node2.type === type;
1822
1821
  };
@@ -2052,59 +2051,73 @@ function nodeHandlerAttributeInfo(node) {
2052
2051
  const limited = parts.slice(0, 2);
2053
2052
  return limited.map((p) => `${toPascalCase(p.key)}${p.value}`).join("");
2054
2053
  };
2055
- const direct = getLastIdentifierFromMemberChain(expr);
2056
- if (direct) {
2057
- return { semanticNameHint: toPascalCase(direct), mergeKey };
2058
- }
2059
- if (isArrowFunctionExpressionNode(expr)) {
2060
- const body = expr.body;
2061
- const tryFromCallExpression = (call) => {
2062
- const resolvedCall = isAwaitExpressionNode(call) ? call.argument : call;
2063
- if (!isCallExpressionNode(resolvedCall)) {
2064
- return null;
2065
- }
2066
- const name = getLastIdentifierFromMemberChain(resolvedCall.callee);
2067
- if (!name) {
2068
- return null;
2054
+ const tryFromCallExpression = (call) => {
2055
+ const resolvedCall = isAwaitExpressionNode(call) ? call.argument : call;
2056
+ if (!isCallExpressionNode(resolvedCall)) {
2057
+ return null;
2058
+ }
2059
+ const name = getLastIdentifierFromMemberChain(resolvedCall.callee);
2060
+ if (!name) {
2061
+ return null;
2062
+ }
2063
+ const suffix = getStableSuffixFromCall(resolvedCall);
2064
+ const semanticNameHint2 = suffix ? `${toPascalCase(name)}${suffix}` : toPascalCase(name);
2065
+ return semanticNameHint2;
2066
+ };
2067
+ const resolveSemanticName = (candidateExpr) => {
2068
+ if (!candidateExpr) {
2069
+ return null;
2070
+ }
2071
+ const direct = getLastIdentifierFromMemberChain(candidateExpr);
2072
+ if (direct) {
2073
+ return toPascalCase(direct);
2074
+ }
2075
+ if (isArrowFunctionExpressionNode(candidateExpr)) {
2076
+ const body = candidateExpr.body;
2077
+ const directCall = tryFromCallExpression(body);
2078
+ if (directCall) {
2079
+ return directCall;
2080
+ }
2081
+ if (isAssignmentExpressionNode(body)) {
2082
+ const lhs = getAssignmentTargetName(body.left);
2083
+ if (lhs) {
2084
+ const rhs = stableWordFromValue(body.right);
2085
+ return `Set${toPascalCase(lhs)}${rhs ?? ""}`;
2086
+ }
2069
2087
  }
2070
- const suffix = getStableSuffixFromCall(resolvedCall);
2071
- const semanticNameHint = suffix ? `${toPascalCase(name)}${suffix}` : toPascalCase(name);
2072
- return semanticNameHint;
2073
- };
2074
- const directCall = tryFromCallExpression(body);
2075
- if (directCall) {
2076
- return { semanticNameHint: directCall, mergeKey };
2077
- }
2078
- if (isAssignmentExpressionNode(body)) {
2079
- const lhs = getAssignmentTargetName(body.left);
2080
- if (lhs) {
2081
- const rhs = stableWordFromValue(body.right);
2082
- const semanticNameHint = `Set${toPascalCase(lhs)}${rhs ?? ""}`;
2083
- return { semanticNameHint, mergeKey };
2084
- }
2085
- }
2086
- if (isBlockStatementNode(body)) {
2087
- const stmts = body.body ?? [];
2088
- if (stmts.length > 0) {
2089
- const firstStmt = stmts[0];
2090
- if (isReturnStatementNode(firstStmt)) {
2091
- const fromReturn = tryFromCallExpression(firstStmt.argument ?? null);
2092
- if (fromReturn) {
2093
- return { semanticNameHint: fromReturn, mergeKey };
2088
+ if (isBlockStatementNode(body)) {
2089
+ const stmts = body.body ?? [];
2090
+ if (stmts.length > 0) {
2091
+ const firstStmt = stmts[0];
2092
+ if (isReturnStatementNode(firstStmt)) {
2093
+ const fromReturn = tryFromCallExpression(firstStmt.argument ?? null);
2094
+ if (fromReturn) {
2095
+ return fromReturn;
2096
+ }
2094
2097
  }
2095
- }
2096
- if (isExpressionStatementNode(firstStmt)) {
2097
- const fromExpr = tryFromCallExpression(firstStmt.expression ?? null);
2098
- if (fromExpr) {
2099
- return { semanticNameHint: fromExpr, mergeKey };
2098
+ if (isExpressionStatementNode(firstStmt)) {
2099
+ const fromExpr = tryFromCallExpression(firstStmt.expression ?? null);
2100
+ if (fromExpr) {
2101
+ return fromExpr;
2102
+ }
2100
2103
  }
2101
2104
  }
2102
2105
  }
2106
+ const bodyName = getLastIdentifierFromMemberChain(body);
2107
+ if (bodyName) {
2108
+ return toPascalCase(bodyName);
2109
+ }
2103
2110
  }
2104
- const bodyName = getLastIdentifierFromMemberChain(body);
2105
- if (bodyName) {
2106
- return { semanticNameHint: toPascalCase(bodyName), mergeKey };
2107
- }
2111
+ return null;
2112
+ };
2113
+ const isVueRefValueAccess = (candidate) => {
2114
+ return isMemberExpressionNode(candidate) && candidate.computed === false && isIdentifierNode2(candidate.property) && candidate.property.name === "value";
2115
+ };
2116
+ const transformedSemanticName = resolveSemanticName(expr);
2117
+ const fallbackSemanticName = resolveSemanticName(fallbackExpr);
2118
+ const semanticNameHint = fallbackSemanticName && transformedSource !== authorSource && isVueRefValueAccess(expr) ? fallbackSemanticName : transformedSemanticName ?? fallbackSemanticName;
2119
+ if (semanticNameHint) {
2120
+ return { semanticNameHint, mergeKey };
2108
2121
  }
2109
2122
  return null;
2110
2123
  }