@immense/vue-pom-generator 1.0.60 → 1.0.61
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/README.md +9 -1
- package/RELEASE_NOTES.md +32 -28
- package/dist/accessibility-audit.d.ts +20 -0
- package/dist/accessibility-audit.d.ts.map +1 -0
- package/dist/compiler-metadata-utils.d.ts.map +1 -1
- package/dist/index.cjs +119 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +119 -7
- package/dist/index.mjs.map +1 -1
- package/dist/manifest-generator.d.ts +2 -0
- package/dist/manifest-generator.d.ts.map +1 -1
- package/dist/metadata-collector.d.ts +5 -1
- package/dist/metadata-collector.d.ts.map +1 -1
- package/dist/plugin/create-vue-pom-generator-plugins.d.ts.map +1 -1
- package/dist/plugin/resolved-generation-options.d.ts +1 -0
- package/dist/plugin/resolved-generation-options.d.ts.map +1 -1
- package/dist/plugin/types.d.ts +7 -0
- package/dist/plugin/types.d.ts.map +1 -1
- package/dist/plugin/vue-plugin.d.ts +1 -0
- package/dist/plugin/vue-plugin.d.ts.map +1 -1
- package/dist/tests/accessibility-audit.test.d.ts +2 -0
- package/dist/tests/accessibility-audit.test.d.ts.map +1 -0
- package/dist/tests/resolved-generation-options.test.d.ts +2 -0
- package/dist/tests/resolved-generation-options.test.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -219,6 +219,7 @@ function resolveGenerationSupportOptions(options) {
|
|
|
219
219
|
nameCollisionBehavior: options.nameCollisionBehavior ?? "error",
|
|
220
220
|
existingIdBehavior: options.existingIdBehavior ?? "error",
|
|
221
221
|
testIdAttribute: (options.testIdAttribute ?? "data-testid").trim() || "data-testid",
|
|
222
|
+
accessibilityAudit: options.accessibilityAudit ?? false,
|
|
222
223
|
routerAwarePoms: options.routerAwarePoms ?? false,
|
|
223
224
|
routerEntry: options.routerEntry,
|
|
224
225
|
routerType: options.routerType ?? "vue-router",
|
|
@@ -8173,6 +8174,59 @@ function createDevProcessorPlugin(options) {
|
|
|
8173
8174
|
}
|
|
8174
8175
|
};
|
|
8175
8176
|
}
|
|
8177
|
+
function supportsInlineTextAccessibleName(role) {
|
|
8178
|
+
return role === "button" || role === "radio";
|
|
8179
|
+
}
|
|
8180
|
+
function buildAccessibilityAudit(metadata, inferredRole) {
|
|
8181
|
+
if (!metadata || !inferredRole) {
|
|
8182
|
+
return void 0;
|
|
8183
|
+
}
|
|
8184
|
+
const role = normalizePomRoleLabel(inferredRole).toLowerCase();
|
|
8185
|
+
const dynamicProps = new Set(metadata.dynamicProps ?? []);
|
|
8186
|
+
const hasDynamicAccessibleNameSignal = dynamicProps.has("aria-label") || dynamicProps.has("title") || !!metadata.hasDynamicText;
|
|
8187
|
+
let accessibleNameSource;
|
|
8188
|
+
const reasons = [];
|
|
8189
|
+
if (metadata.staticAriaLabel) {
|
|
8190
|
+
accessibleNameSource = "aria-label";
|
|
8191
|
+
} else if (supportsInlineTextAccessibleName(role) && metadata.staticTextContent) {
|
|
8192
|
+
accessibleNameSource = "text";
|
|
8193
|
+
} else if (metadata.staticTitle) {
|
|
8194
|
+
accessibleNameSource = "title";
|
|
8195
|
+
} else if (hasDynamicAccessibleNameSignal) {
|
|
8196
|
+
accessibleNameSource = "dynamic";
|
|
8197
|
+
} else if (role === "input" || role === "select") {
|
|
8198
|
+
accessibleNameSource = "unknown";
|
|
8199
|
+
reasons.push("No inline accessible-name signal was found; the element may rely on external markup such as a separate <label>.");
|
|
8200
|
+
} else {
|
|
8201
|
+
accessibleNameSource = "missing";
|
|
8202
|
+
reasons.push("No compile-time accessible-name signal was found.");
|
|
8203
|
+
}
|
|
8204
|
+
return {
|
|
8205
|
+
needsReview: accessibleNameSource === "unknown" || accessibleNameSource === "missing",
|
|
8206
|
+
accessibleNameSource,
|
|
8207
|
+
reasons,
|
|
8208
|
+
...metadata.staticAriaLabel ? { staticAriaLabel: metadata.staticAriaLabel } : {},
|
|
8209
|
+
...metadata.staticRole ? { staticRole: metadata.staticRole } : {},
|
|
8210
|
+
...metadata.staticTitle ? { staticTitle: metadata.staticTitle } : {},
|
|
8211
|
+
...metadata.staticTextContent ? { staticTextContent: metadata.staticTextContent } : {}
|
|
8212
|
+
};
|
|
8213
|
+
}
|
|
8214
|
+
function collectAccessibilityReviewWarnings(manifest) {
|
|
8215
|
+
const warnings = [];
|
|
8216
|
+
for (const [componentName, component] of Object.entries(manifest)) {
|
|
8217
|
+
for (const entry of component.entries) {
|
|
8218
|
+
if (!entry.accessibility?.needsReview) {
|
|
8219
|
+
continue;
|
|
8220
|
+
}
|
|
8221
|
+
const entryLabel = entry.generatedPropertyName ?? entry.testId;
|
|
8222
|
+
const reasonText = entry.accessibility.reasons.join(" ");
|
|
8223
|
+
warnings.push(
|
|
8224
|
+
`[vue-pom-generator] Accessibility review suggested for ${componentName}.${entryLabel} (role=${entry.inferredRole ?? "unknown"}, testId=${JSON.stringify(entry.testId)}): ${reasonText}`
|
|
8225
|
+
);
|
|
8226
|
+
}
|
|
8227
|
+
}
|
|
8228
|
+
return warnings;
|
|
8229
|
+
}
|
|
8176
8230
|
function removeByKeySegment(value) {
|
|
8177
8231
|
const idx = value.indexOf("ByKey");
|
|
8178
8232
|
if (idx < 0) {
|
|
@@ -8231,6 +8285,7 @@ function getManifestEntry(componentName, entry, componentMetadata, extraMethods)
|
|
|
8231
8285
|
...generatedActionName ? [generatedActionName] : [],
|
|
8232
8286
|
...extraActionNames.filter((name) => name !== generatedActionName)
|
|
8233
8287
|
]));
|
|
8288
|
+
const accessibility = buildAccessibilityAudit(metadata, pom?.nativeRole ?? null);
|
|
8234
8289
|
return {
|
|
8235
8290
|
testId,
|
|
8236
8291
|
selectorPatternKind: entry.selectorValue.patternKind,
|
|
@@ -8241,6 +8296,7 @@ function getManifestEntry(componentName, entry, componentMetadata, extraMethods)
|
|
|
8241
8296
|
nativeRole: pom.nativeRole
|
|
8242
8297
|
}) : componentName,
|
|
8243
8298
|
inferredRole: pom?.nativeRole ?? null,
|
|
8299
|
+
...accessibility ? { accessibility } : {},
|
|
8244
8300
|
generatedPropertyName: pom ? getGeneratedPropertyName(pom) : null,
|
|
8245
8301
|
generatedActionName,
|
|
8246
8302
|
generatedActionNames,
|
|
@@ -8516,6 +8572,33 @@ function parseDynamicProps(dynamicProps) {
|
|
|
8516
8572
|
}
|
|
8517
8573
|
return void 0;
|
|
8518
8574
|
}
|
|
8575
|
+
function findStaticAttributeValue(element, attributeName) {
|
|
8576
|
+
const attribute = element.props.find(
|
|
8577
|
+
(prop) => prop.type === NodeTypes.ATTRIBUTE && prop.name === attributeName
|
|
8578
|
+
);
|
|
8579
|
+
const value = attribute?.value?.content?.trim();
|
|
8580
|
+
return value ? value : void 0;
|
|
8581
|
+
}
|
|
8582
|
+
function collectStaticTextContent(children) {
|
|
8583
|
+
const parts = [];
|
|
8584
|
+
const visit = (nodes) => {
|
|
8585
|
+
for (const node of nodes) {
|
|
8586
|
+
if (node.type === NodeTypes.TEXT) {
|
|
8587
|
+
const text2 = node.content.replace(/\s+/g, " ").trim();
|
|
8588
|
+
if (text2) {
|
|
8589
|
+
parts.push(text2);
|
|
8590
|
+
}
|
|
8591
|
+
continue;
|
|
8592
|
+
}
|
|
8593
|
+
if (node.type === NodeTypes.ELEMENT) {
|
|
8594
|
+
visit(node.children);
|
|
8595
|
+
}
|
|
8596
|
+
}
|
|
8597
|
+
};
|
|
8598
|
+
visit(children);
|
|
8599
|
+
const text = parts.join(" ").replace(/\s+/g, " ").trim();
|
|
8600
|
+
return text || void 0;
|
|
8601
|
+
}
|
|
8519
8602
|
function tryCreateElementMetadata(args) {
|
|
8520
8603
|
const { element, semanticNameMap } = args;
|
|
8521
8604
|
const testIdAttribute = (args.testIdAttribute ?? "data-testid").trim() || "data-testid";
|
|
@@ -8539,13 +8622,9 @@ function tryCreateElementMetadata(args) {
|
|
|
8539
8622
|
dynamicPropsList = [content];
|
|
8540
8623
|
}
|
|
8541
8624
|
}
|
|
8542
|
-
const semanticName = semanticNameMap.get(testId);
|
|
8543
|
-
if (!semanticName) {
|
|
8544
|
-
return null;
|
|
8545
|
-
}
|
|
8546
8625
|
const metadata = {
|
|
8547
8626
|
testId,
|
|
8548
|
-
semanticName,
|
|
8627
|
+
semanticName: semanticNameMap.get(testId),
|
|
8549
8628
|
tag: element.tag,
|
|
8550
8629
|
tagType: element.tagType,
|
|
8551
8630
|
patchFlag,
|
|
@@ -8554,7 +8633,11 @@ function tryCreateElementMetadata(args) {
|
|
|
8554
8633
|
hasClickHandler: patchFlag ? Boolean(patchFlag & 32) : void 0,
|
|
8555
8634
|
hasDynamicClass: patchFlag ? Boolean(patchFlag & 2) : void 0,
|
|
8556
8635
|
hasDynamicStyle: patchFlag ? Boolean(patchFlag & 4) : void 0,
|
|
8557
|
-
hasDynamicText: patchFlag ? Boolean(patchFlag & 1) : void 0
|
|
8636
|
+
hasDynamicText: patchFlag ? Boolean(patchFlag & 1) : void 0,
|
|
8637
|
+
staticAriaLabel: findStaticAttributeValue(element, "aria-label"),
|
|
8638
|
+
staticRole: findStaticAttributeValue(element, "role"),
|
|
8639
|
+
staticTitle: findStaticAttributeValue(element, "title"),
|
|
8640
|
+
staticTextContent: collectStaticTextContent(element.children)
|
|
8558
8641
|
};
|
|
8559
8642
|
return metadata;
|
|
8560
8643
|
}
|
|
@@ -8606,6 +8689,7 @@ function extractMetadataAfterTransform(ast, componentName, elementMetadata, sema
|
|
|
8606
8689
|
if (componentMetadata.size > 0) {
|
|
8607
8690
|
elementMetadata.set(componentName, componentMetadata);
|
|
8608
8691
|
}
|
|
8692
|
+
return componentMetadata;
|
|
8609
8693
|
}
|
|
8610
8694
|
function createVuePluginWithTestIds(options) {
|
|
8611
8695
|
const {
|
|
@@ -8620,11 +8704,13 @@ function createVuePluginWithTestIds(options) {
|
|
|
8620
8704
|
excludedComponents,
|
|
8621
8705
|
getViewsDirAbs,
|
|
8622
8706
|
testIdAttribute,
|
|
8707
|
+
accessibilityAudit,
|
|
8623
8708
|
loggerRef,
|
|
8624
8709
|
getSourceDirs,
|
|
8625
8710
|
getWrapperSearchRoots,
|
|
8626
8711
|
getProjectRoot
|
|
8627
8712
|
} = options;
|
|
8713
|
+
const lastAccessibilityWarningSignatureByComponent = /* @__PURE__ */ new Map();
|
|
8628
8714
|
const getComponentNameFromPath = (filename) => {
|
|
8629
8715
|
return resolveComponentNameFromPath({
|
|
8630
8716
|
filename,
|
|
@@ -8697,13 +8783,37 @@ function createVuePluginWithTestIds(options) {
|
|
|
8697
8783
|
)
|
|
8698
8784
|
);
|
|
8699
8785
|
return () => {
|
|
8700
|
-
extractMetadataAfterTransform(
|
|
8786
|
+
const componentMetadata = extractMetadataAfterTransform(
|
|
8701
8787
|
node,
|
|
8702
8788
|
componentName,
|
|
8703
8789
|
elementMetadata,
|
|
8704
8790
|
semanticNameMap,
|
|
8705
8791
|
testIdAttribute
|
|
8706
8792
|
);
|
|
8793
|
+
if (!accessibilityAudit) {
|
|
8794
|
+
return;
|
|
8795
|
+
}
|
|
8796
|
+
const dependencies = componentHierarchyMap.get(componentName);
|
|
8797
|
+
if (!dependencies || componentMetadata.size === 0) {
|
|
8798
|
+
return;
|
|
8799
|
+
}
|
|
8800
|
+
const manifest = buildPomManifest(
|
|
8801
|
+
/* @__PURE__ */ new Map([[componentName, dependencies]]),
|
|
8802
|
+
/* @__PURE__ */ new Map([[componentName, componentMetadata]])
|
|
8803
|
+
);
|
|
8804
|
+
const warnings = collectAccessibilityReviewWarnings(manifest);
|
|
8805
|
+
const signature = warnings.join("\n");
|
|
8806
|
+
if (!signature) {
|
|
8807
|
+
lastAccessibilityWarningSignatureByComponent.delete(componentName);
|
|
8808
|
+
return;
|
|
8809
|
+
}
|
|
8810
|
+
if (lastAccessibilityWarningSignatureByComponent.get(componentName) === signature) {
|
|
8811
|
+
return;
|
|
8812
|
+
}
|
|
8813
|
+
lastAccessibilityWarningSignatureByComponent.set(componentName, signature);
|
|
8814
|
+
for (const warning of warnings) {
|
|
8815
|
+
loggerRef.current.warn(warning);
|
|
8816
|
+
}
|
|
8707
8817
|
};
|
|
8708
8818
|
}
|
|
8709
8819
|
let transform = perFileTransform.get(componentName);
|
|
@@ -9068,6 +9178,7 @@ function createVuePomGeneratorPlugins(options = {}) {
|
|
|
9068
9178
|
nameCollisionBehavior: generationOptions?.nameCollisionBehavior,
|
|
9069
9179
|
existingIdBehavior: resolvedInjectionOptions.existingIdBehavior,
|
|
9070
9180
|
testIdAttribute,
|
|
9181
|
+
accessibilityAudit: generationOptions?.accessibilityAudit,
|
|
9071
9182
|
routerAwarePoms: typeof routerEntry === "string" && routerEntry.trim().length > 0 || routerType === "nuxt",
|
|
9072
9183
|
routerEntry,
|
|
9073
9184
|
routerType,
|
|
@@ -9161,6 +9272,7 @@ function createVuePomGeneratorPlugins(options = {}) {
|
|
|
9161
9272
|
excludedComponents,
|
|
9162
9273
|
getViewsDirAbs,
|
|
9163
9274
|
testIdAttribute,
|
|
9275
|
+
accessibilityAudit: resolvedGenerationOptions.accessibilityAudit,
|
|
9164
9276
|
loggerRef,
|
|
9165
9277
|
getSourceDirs,
|
|
9166
9278
|
getWrapperSearchRoots: getWrapperSearchRootsAbs,
|