@immense/vue-pom-generator 1.0.66 → 1.0.68
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/AGENTS.md +21 -0
- package/README.md +1 -0
- package/RELEASE_NOTES.md +16 -9
- package/class-generation/index.ts +16 -5
- package/dist/class-generation/index.d.ts.map +1 -1
- package/dist/compiler-metadata-utils.d.ts.map +1 -1
- package/dist/index.cjs +309 -97
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +309 -97
- 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 +2 -0
- 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/internal/build-plugin.d.ts.map +1 -0
- package/dist/plugin/internal/dev-plugin.d.ts.map +1 -0
- package/dist/plugin/internal/virtual-modules.d.ts.map +1 -0
- package/dist/plugin/{support-plugins.d.ts → internal-plugins.d.ts} +14 -3
- package/dist/plugin/internal-plugins.d.ts.map +1 -0
- package/dist/plugin/path-utils.d.ts +12 -0
- package/dist/plugin/path-utils.d.ts.map +1 -1
- package/dist/plugin/runtime/annotator/client.d.ts +67 -0
- package/dist/plugin/runtime/annotator/client.d.ts.map +1 -0
- package/dist/plugin/runtime/annotator/format.d.ts +13 -0
- package/dist/plugin/runtime/annotator/format.d.ts.map +1 -0
- package/dist/plugin/runtime/annotator/plugin.d.ts +12 -0
- package/dist/plugin/runtime/annotator/plugin.d.ts.map +1 -0
- package/dist/plugin/runtime/annotator/styles.d.ts +3 -0
- package/dist/plugin/runtime/annotator/styles.d.ts.map +1 -0
- package/dist/plugin/runtime/annotator/vue-detector.d.ts +12 -0
- package/dist/plugin/runtime/annotator/vue-detector.d.ts.map +1 -0
- package/dist/plugin/types.d.ts +58 -3
- package/dist/plugin/types.d.ts.map +1 -1
- package/dist/plugin/vue-plugin.d.ts +4 -0
- package/dist/plugin/vue-plugin.d.ts.map +1 -1
- package/dist/tests/path-utils-scope.test.d.ts +2 -0
- package/dist/tests/path-utils-scope.test.d.ts.map +1 -0
- package/dist/transform.d.ts +4 -0
- package/dist/transform.d.ts.map +1 -1
- package/dist/utils.d.ts +19 -0
- package/dist/utils.d.ts.map +1 -1
- package/package.json +3 -1
- package/plugin/runtime/annotator/client.ts +1005 -0
- package/plugin/runtime/annotator/format.ts +76 -0
- package/plugin/runtime/annotator/plugin.ts +109 -0
- package/plugin/runtime/annotator/styles.ts +379 -0
- package/plugin/runtime/annotator/vue-detector.ts +216 -0
- package/dist/plugin/support/build-plugin.d.ts.map +0 -1
- package/dist/plugin/support/dev-plugin.d.ts.map +0 -1
- package/dist/plugin/support/virtual-modules.d.ts.map +0 -1
- package/dist/plugin/support-plugins.d.ts.map +0 -1
- /package/dist/plugin/{support → internal}/build-plugin.d.ts +0 -0
- /package/dist/plugin/{support → internal}/dev-plugin.d.ts +0 -0
- /package/dist/plugin/{support → internal}/virtual-modules.d.ts +0 -0
package/dist/index.cjs
CHANGED
|
@@ -686,7 +686,7 @@ function createInlineParameter(name, options = {}) {
|
|
|
686
686
|
initializer: options.initializer
|
|
687
687
|
};
|
|
688
688
|
}
|
|
689
|
-
function removeByKeySegment
|
|
689
|
+
function removeByKeySegment(value) {
|
|
690
690
|
const idx = value.lastIndexOf("ByKey");
|
|
691
691
|
if (idx < 0) {
|
|
692
692
|
return value;
|
|
@@ -890,13 +890,13 @@ function generateGetElementByDataTestId(componentName, methodName, nativeRole, s
|
|
|
890
890
|
const roleSuffix = upperFirst$1(nativeRole || "Element");
|
|
891
891
|
const baseName = upperFirst$1(methodName);
|
|
892
892
|
const numericSuffix = baseName.startsWith(roleSuffix) ? baseName.slice(roleSuffix.length) : "";
|
|
893
|
-
const
|
|
894
|
-
const propertyName =
|
|
893
|
+
const hasRoleSuffix = baseName.endsWith(roleSuffix) || baseName.startsWith(roleSuffix) && isAllDigits(numericSuffix);
|
|
894
|
+
const propertyName = hasRoleSuffix ? `${baseName}` : `${baseName}${roleSuffix}`;
|
|
895
895
|
const selectorParams = orderPomPatternParameters(parameters, [selector]);
|
|
896
896
|
const indexedVariable = getIndexedPomPatternVariable(selector);
|
|
897
897
|
if (indexedVariable) {
|
|
898
898
|
const keyType = getPomParameter(selectorParams, indexedVariable)?.typeExpression || "string";
|
|
899
|
-
const keyedPropertyName = getterNameOverride ?? removeByKeySegment
|
|
899
|
+
const keyedPropertyName = getterNameOverride ?? removeByKeySegment(propertyName);
|
|
900
900
|
return [
|
|
901
901
|
createClassGetter({
|
|
902
902
|
name: keyedPropertyName,
|
|
@@ -2935,7 +2935,7 @@ Fix: either (1) include ${bestKeyPreservePlaceholder} in your :${attrLabel} temp
|
|
|
2935
2935
|
}
|
|
2936
2936
|
return value.slice(0, idx) + value.slice(idx + "ByKey".length);
|
|
2937
2937
|
};
|
|
2938
|
-
const
|
|
2938
|
+
const hasRoleSuffix = (baseName, roleSuffix) => {
|
|
2939
2939
|
if (baseName.endsWith(roleSuffix)) {
|
|
2940
2940
|
return true;
|
|
2941
2941
|
}
|
|
@@ -2945,13 +2945,13 @@ Fix: either (1) include ${bestKeyPreservePlaceholder} in your :${attrLabel} temp
|
|
|
2945
2945
|
const getPrimaryGetterName = (primaryMethodName) => {
|
|
2946
2946
|
const roleSuffix = upperFirst(normalizedRole || "Element");
|
|
2947
2947
|
const baseName = upperFirst(primaryMethodName);
|
|
2948
|
-
const propertyName =
|
|
2948
|
+
const propertyName = hasRoleSuffix(baseName, roleSuffix) ? baseName : `${baseName}${roleSuffix}`;
|
|
2949
2949
|
return selectorIsParameterized ? removeByKeySegment2(propertyName) : propertyName;
|
|
2950
2950
|
};
|
|
2951
2951
|
const getPrimaryGetterNameCandidates = (primaryMethodName) => {
|
|
2952
2952
|
const roleSuffix = upperFirst(normalizedRole || "Element");
|
|
2953
2953
|
const baseName = upperFirst(primaryMethodName);
|
|
2954
|
-
const propertyName =
|
|
2954
|
+
const propertyName = hasRoleSuffix(baseName, roleSuffix) ? baseName : `${baseName}${roleSuffix}`;
|
|
2955
2955
|
if (!selectorIsParameterized) {
|
|
2956
2956
|
return { primary: propertyName };
|
|
2957
2957
|
}
|
|
@@ -3078,7 +3078,7 @@ Fix: either (1) include ${bestKeyPreservePlaceholder} in your :${attrLabel} temp
|
|
|
3078
3078
|
if (conflicts && nameCollisionBehavior === "error") {
|
|
3079
3079
|
const roleSuffix = upperFirst(normalizedRole || "Element");
|
|
3080
3080
|
const baseNameUpper = upperFirst(baseWithSuffix);
|
|
3081
|
-
if (!
|
|
3081
|
+
if (!hasRoleSuffix(baseNameUpper, roleSuffix)) {
|
|
3082
3082
|
const baseWithRoleSuffix = `${baseWithSuffix}${roleSuffix}`;
|
|
3083
3083
|
const candidateWithRoleSuffix = selectorIsParameterized ? `${baseWithRoleSuffix}ByKey` : baseWithRoleSuffix;
|
|
3084
3084
|
const actionNameWithRoleSuffix = getPrimaryActionMethodName(candidateWithRoleSuffix);
|
|
@@ -3188,12 +3188,32 @@ Fix: make the element identifiable (e.g. add id/name/inner text or use a more sp
|
|
|
3188
3188
|
alternateSelectors: void 0,
|
|
3189
3189
|
mergeKey: args.pomMergeKey,
|
|
3190
3190
|
parameters: normalizedParameters,
|
|
3191
|
-
keyValuesOverride: args.keyValuesOverride ?? null
|
|
3191
|
+
keyValuesOverride: args.keyValuesOverride ?? null,
|
|
3192
|
+
generatedActionName: getPrimaryActionMethodName(methodName),
|
|
3193
|
+
generatedPropertyName: getterNameOverride ?? getPrimaryGetterName(methodName)
|
|
3192
3194
|
// emitPrimary defaults to true; special cases (including merge) may set it to false below.
|
|
3193
3195
|
};
|
|
3194
3196
|
if (mergedIntoExisting && dataTestIdEntry.pom) {
|
|
3195
3197
|
dataTestIdEntry.pom.emitPrimary = false;
|
|
3196
3198
|
}
|
|
3199
|
+
if (addHtmlAttribute && args.annotatorMetadata && dataTestIdEntry.pom) {
|
|
3200
|
+
const filename = args.contextFilename?.trim();
|
|
3201
|
+
if (!filename) {
|
|
3202
|
+
throw new Error(`[vue-pom-generator] runtime.annotator.enabled requires contextFilename for ${args.componentName}.`);
|
|
3203
|
+
}
|
|
3204
|
+
const sourceLocation = args.element.loc?.start;
|
|
3205
|
+
if (!sourceLocation) {
|
|
3206
|
+
throw new Error(`[vue-pom-generator] runtime.annotator.enabled requires element source locations for ${args.componentName}.`);
|
|
3207
|
+
}
|
|
3208
|
+
const metadataAttributePrefix = args.annotatorMetadata.metadataAttributePrefix;
|
|
3209
|
+
upsertAttribute(args.element, args.annotatorMetadata.sourceAttribute, staticAttributeValue(`${filename}:${sourceLocation.line}:${sourceLocation.column}`));
|
|
3210
|
+
upsertAttribute(args.element, `${metadataAttributePrefix}-component`, staticAttributeValue(args.componentName));
|
|
3211
|
+
upsertAttribute(args.element, `${metadataAttributePrefix}-tag`, staticAttributeValue(args.element.tag));
|
|
3212
|
+
upsertAttribute(args.element, `${metadataAttributePrefix}-testid`, runtimeDataTestId);
|
|
3213
|
+
upsertAttribute(args.element, `${metadataAttributePrefix}-action`, staticAttributeValue(buildPomGeneratedActionName(dataTestIdEntry.pom)));
|
|
3214
|
+
upsertAttribute(args.element, `${metadataAttributePrefix}-property`, staticAttributeValue(buildPomGeneratedPropertyName(dataTestIdEntry.pom)));
|
|
3215
|
+
upsertAttribute(args.element, `${metadataAttributePrefix}-role`, staticAttributeValue(normalizedRole));
|
|
3216
|
+
}
|
|
3197
3217
|
args.dependencies.childrenComponentSet.add(childComponentName);
|
|
3198
3218
|
args.dependencies.usedComponentSet.add(childComponentName);
|
|
3199
3219
|
args.dependencies.dataTestIdSet.add(dataTestIdEntry);
|
|
@@ -3392,7 +3412,7 @@ Fix: make the element identifiable (e.g. add id/name/inner text or use a more sp
|
|
|
3392
3412
|
registerGeneratedMethodSignature(generatedName2, createPomMethodSignature([createPomParameterSpec("annotationText", `string = ""`)]));
|
|
3393
3413
|
}
|
|
3394
3414
|
}
|
|
3395
|
-
return { selectorValue: dataTestId, runtimeValue: runtimeDataTestId, fromExisting };
|
|
3415
|
+
return { selectorValue: dataTestId, runtimeValue: runtimeDataTestId, fromExisting, entry: dataTestIdEntry };
|
|
3396
3416
|
}
|
|
3397
3417
|
const generatedName = ensureUniqueGeneratedName(`select${upperFirst(methodName || "Radio")}`);
|
|
3398
3418
|
if (dataTestIdEntry.pom) {
|
|
@@ -3419,7 +3439,7 @@ Fix: make the element identifiable (e.g. add id/name/inner text or use a more sp
|
|
|
3419
3439
|
createPomParameterSpec("annotationText", `string = ""`)
|
|
3420
3440
|
]));
|
|
3421
3441
|
}
|
|
3422
|
-
return { selectorValue: dataTestId, runtimeValue: runtimeDataTestId, fromExisting };
|
|
3442
|
+
return { selectorValue: dataTestId, runtimeValue: runtimeDataTestId, fromExisting, entry: dataTestIdEntry };
|
|
3423
3443
|
}
|
|
3424
3444
|
const staticKeyValues = args.keyValuesOverride ?? null;
|
|
3425
3445
|
const needsKey = hasPomParameter(normalizedParameters, "key") && selectorIsParameterized;
|
|
@@ -3453,7 +3473,7 @@ Fix: make the element identifiable (e.g. add id/name/inner text or use a more sp
|
|
|
3453
3473
|
]));
|
|
3454
3474
|
}
|
|
3455
3475
|
}
|
|
3456
|
-
return { selectorValue: dataTestId, runtimeValue: runtimeDataTestId, fromExisting };
|
|
3476
|
+
return { selectorValue: dataTestId, runtimeValue: runtimeDataTestId, fromExisting, entry: dataTestIdEntry };
|
|
3457
3477
|
}
|
|
3458
3478
|
if (dataTestIdEntry.pom) {
|
|
3459
3479
|
if (dataTestIdEntry.pom.emitPrimary !== false) {
|
|
@@ -3467,7 +3487,66 @@ Fix: make the element identifiable (e.g. add id/name/inner text or use a more sp
|
|
|
3467
3487
|
const generatedName = getGeneratedMethodName();
|
|
3468
3488
|
registerGeneratedMethodSignature(generatedName, signature);
|
|
3469
3489
|
}
|
|
3470
|
-
return { selectorValue: dataTestId, runtimeValue: runtimeDataTestId, fromExisting };
|
|
3490
|
+
return { selectorValue: dataTestId, runtimeValue: runtimeDataTestId, fromExisting, entry: dataTestIdEntry };
|
|
3491
|
+
}
|
|
3492
|
+
function requireStructuredPomName(value, fieldName, pom) {
|
|
3493
|
+
const normalized = value?.trim();
|
|
3494
|
+
if (normalized) {
|
|
3495
|
+
return normalized;
|
|
3496
|
+
}
|
|
3497
|
+
throw new Error(`[vue-pom-generator] Missing ${fieldName} for POM spec ${pom.methodName}.`);
|
|
3498
|
+
}
|
|
3499
|
+
function buildPomGeneratedPropertyName(pom) {
|
|
3500
|
+
return requireStructuredPomName(pom.generatedPropertyName, "generatedPropertyName", pom);
|
|
3501
|
+
}
|
|
3502
|
+
function buildPomGeneratedActionName(pom) {
|
|
3503
|
+
return requireStructuredPomName(pom.generatedActionName, "generatedActionName", pom);
|
|
3504
|
+
}
|
|
3505
|
+
const STANDALONE_WRAPPER_FALLBACK_ROLES = /* @__PURE__ */ new Set([
|
|
3506
|
+
"button",
|
|
3507
|
+
"input",
|
|
3508
|
+
"select",
|
|
3509
|
+
"vselect",
|
|
3510
|
+
"checkbox",
|
|
3511
|
+
"toggle",
|
|
3512
|
+
"radio"
|
|
3513
|
+
]);
|
|
3514
|
+
function stripTrailingAsciiDigits(value) {
|
|
3515
|
+
let end = value.length;
|
|
3516
|
+
while (end > 0 && isAsciiDigitCode(value.charCodeAt(end - 1))) {
|
|
3517
|
+
end -= 1;
|
|
3518
|
+
}
|
|
3519
|
+
return value.slice(0, end);
|
|
3520
|
+
}
|
|
3521
|
+
function matchesStandaloneWrapperFallbackMethodName(methodName, componentClassName) {
|
|
3522
|
+
let normalizedMethodName = methodName;
|
|
3523
|
+
if (normalizedMethodName.endsWith("ByKey")) {
|
|
3524
|
+
normalizedMethodName = normalizedMethodName.slice(0, -"ByKey".length);
|
|
3525
|
+
}
|
|
3526
|
+
normalizedMethodName = stripTrailingAsciiDigits(normalizedMethodName);
|
|
3527
|
+
return normalizedMethodName === componentClassName;
|
|
3528
|
+
}
|
|
3529
|
+
function shouldSuppressStandaloneWrapperFallbackSurface(componentName, dependencies) {
|
|
3530
|
+
if (dependencies.isView || (dependencies.pomExtraMethods?.length ?? 0) > 0) {
|
|
3531
|
+
return false;
|
|
3532
|
+
}
|
|
3533
|
+
const entries = Array.from(dependencies.dataTestIdSet ?? []);
|
|
3534
|
+
if (!entries.length) {
|
|
3535
|
+
return false;
|
|
3536
|
+
}
|
|
3537
|
+
const primaryEntries = entries.filter((entry) => {
|
|
3538
|
+
return !!entry.pom && entry.pom.emitPrimary !== false;
|
|
3539
|
+
});
|
|
3540
|
+
if (!primaryEntries.length || primaryEntries.length !== entries.length) {
|
|
3541
|
+
return false;
|
|
3542
|
+
}
|
|
3543
|
+
const componentClassName = toPascalCase(componentName.endsWith(".vue") ? componentName.slice(0, -4) : componentName);
|
|
3544
|
+
if (!componentClassName) {
|
|
3545
|
+
return false;
|
|
3546
|
+
}
|
|
3547
|
+
return primaryEntries.every(({ pom }) => {
|
|
3548
|
+
return STANDALONE_WRAPPER_FALLBACK_ROLES.has(pom.nativeRole) && matchesStandaloneWrapperFallbackMethodName(pom.methodName, componentClassName);
|
|
3549
|
+
});
|
|
3471
3550
|
}
|
|
3472
3551
|
function safeRealpath(value) {
|
|
3473
3552
|
try {
|
|
@@ -3484,6 +3563,14 @@ function safeRealpath(value) {
|
|
|
3484
3563
|
const resolvedParent = safeRealpath(parent);
|
|
3485
3564
|
return resolvedParent === parent ? value : path.join(resolvedParent, path.basename(value));
|
|
3486
3565
|
}
|
|
3566
|
+
function normalizeScopePath(value, pathImpl = path) {
|
|
3567
|
+
return pathImpl.normalize(value);
|
|
3568
|
+
}
|
|
3569
|
+
function isNormalizedPathWithinDir(filePathAbs, dirPathAbs, pathImpl = path) {
|
|
3570
|
+
const normalizedFileAbs = normalizeScopePath(filePathAbs, pathImpl);
|
|
3571
|
+
const normalizedDirAbs = normalizeScopePath(dirPathAbs, pathImpl);
|
|
3572
|
+
return normalizedFileAbs === normalizedDirAbs || normalizedFileAbs.startsWith(`${normalizedDirAbs}${pathImpl.sep}`);
|
|
3573
|
+
}
|
|
3487
3574
|
function isPathWithinDir(filePathAbs, dirPathAbs) {
|
|
3488
3575
|
const fileAbs = path.resolve(filePathAbs);
|
|
3489
3576
|
const dirAbs = path.resolve(dirPathAbs);
|
|
@@ -3513,6 +3600,43 @@ function resolveComponentNameFromPath(options) {
|
|
|
3513
3600
|
}
|
|
3514
3601
|
return toPascalCase(path.parse(normalizedAbsFilename).name);
|
|
3515
3602
|
}
|
|
3603
|
+
function isFileInConfiguredSourceScope(options) {
|
|
3604
|
+
const { filename, projectRoot, viewsDirAbs, sourceDirs, extraRoots = [], pathImpl = path } = options;
|
|
3605
|
+
if (!filename) {
|
|
3606
|
+
return false;
|
|
3607
|
+
}
|
|
3608
|
+
const cleanFilename = filename.includes("?") ? filename.substring(0, filename.indexOf("?")) : filename;
|
|
3609
|
+
const normalizedProjectRoot = normalizeScopePath(projectRoot, pathImpl);
|
|
3610
|
+
const normalizedAbsFilename = normalizeScopePath(
|
|
3611
|
+
pathImpl.isAbsolute(cleanFilename) ? cleanFilename : pathImpl.resolve(normalizedProjectRoot, cleanFilename),
|
|
3612
|
+
pathImpl
|
|
3613
|
+
);
|
|
3614
|
+
if (normalizedAbsFilename.includes(`${pathImpl.sep}node_modules${pathImpl.sep}`) || normalizedAbsFilename.includes("/node_modules/")) {
|
|
3615
|
+
return false;
|
|
3616
|
+
}
|
|
3617
|
+
const normalizedViewsDirAbs = normalizeScopePath(viewsDirAbs, pathImpl);
|
|
3618
|
+
if (isNormalizedPathWithinDir(normalizedAbsFilename, normalizedViewsDirAbs, pathImpl)) {
|
|
3619
|
+
return true;
|
|
3620
|
+
}
|
|
3621
|
+
const rootsToTry = Array.from(/* @__PURE__ */ new Set([
|
|
3622
|
+
normalizedProjectRoot,
|
|
3623
|
+
...extraRoots.map((root) => normalizeScopePath(root, pathImpl))
|
|
3624
|
+
]));
|
|
3625
|
+
return sourceDirs.some((dir) => {
|
|
3626
|
+
return rootsToTry.some((root) => {
|
|
3627
|
+
const normalizedAbsDir = normalizeScopePath(pathImpl.resolve(root, dir), pathImpl);
|
|
3628
|
+
if (isNormalizedPathWithinDir(normalizedAbsFilename, normalizedAbsDir, pathImpl)) {
|
|
3629
|
+
return true;
|
|
3630
|
+
}
|
|
3631
|
+
if (dir.startsWith("app/") && pathImpl.basename(root) === "app") {
|
|
3632
|
+
const relativeDir = dir.substring(4);
|
|
3633
|
+
const normalizedAbsDirAlt = normalizeScopePath(pathImpl.resolve(root, relativeDir), pathImpl);
|
|
3634
|
+
return isNormalizedPathWithinDir(normalizedAbsFilename, normalizedAbsDirAlt, pathImpl);
|
|
3635
|
+
}
|
|
3636
|
+
return false;
|
|
3637
|
+
});
|
|
3638
|
+
});
|
|
3639
|
+
}
|
|
3516
3640
|
let routerIntrospectionQueue = Promise.resolve();
|
|
3517
3641
|
async function runRouterIntrospectionExclusive(fn) {
|
|
3518
3642
|
const prev = routerIntrospectionQueue.catch(() => void 0);
|
|
@@ -4767,6 +4891,11 @@ async function generateFiles(componentHierarchyMap, vueFilesPathMap, basePageCla
|
|
|
4767
4891
|
componentDirs,
|
|
4768
4892
|
layoutDirs
|
|
4769
4893
|
}) : void 0);
|
|
4894
|
+
const emittableComponentHierarchyMap = new Map(
|
|
4895
|
+
Array.from(componentHierarchyMap.entries()).filter(([componentName, dependencies]) => {
|
|
4896
|
+
return !shouldSuppressStandaloneWrapperFallbackSurface(componentName, dependencies);
|
|
4897
|
+
})
|
|
4898
|
+
);
|
|
4770
4899
|
const generatedFilePaths = [];
|
|
4771
4900
|
const writeGeneratedFile = (file) => {
|
|
4772
4901
|
const resolvedFilePath = path.resolve(file.filePath);
|
|
@@ -4774,7 +4903,7 @@ async function generateFiles(componentHierarchyMap, vueFilesPathMap, basePageCla
|
|
|
4774
4903
|
generatedFilePaths.push(resolvedFilePath);
|
|
4775
4904
|
};
|
|
4776
4905
|
if (emitLanguages.includes("ts")) {
|
|
4777
|
-
const files = typescriptOutputStructure === "split" ? await generateSplitTypeScriptFiles(
|
|
4906
|
+
const files = typescriptOutputStructure === "split" ? await generateSplitTypeScriptFiles(emittableComponentHierarchyMap, vueFilesPathMap, basePageClassPath, outDir, {
|
|
4778
4907
|
customPomAttachments,
|
|
4779
4908
|
projectRoot,
|
|
4780
4909
|
customPomDir,
|
|
@@ -4784,7 +4913,7 @@ async function generateFiles(componentHierarchyMap, vueFilesPathMap, basePageCla
|
|
|
4784
4913
|
testIdAttribute,
|
|
4785
4914
|
routeMetaByComponent,
|
|
4786
4915
|
vueRouterFluentChaining
|
|
4787
|
-
}) : await generateAggregatedFiles(
|
|
4916
|
+
}) : await generateAggregatedFiles(emittableComponentHierarchyMap, vueFilesPathMap, basePageClassPath, outDir, {
|
|
4788
4917
|
customPomAttachments,
|
|
4789
4918
|
projectRoot,
|
|
4790
4919
|
customPomDir,
|
|
@@ -4798,7 +4927,7 @@ async function generateFiles(componentHierarchyMap, vueFilesPathMap, basePageCla
|
|
|
4798
4927
|
for (const file of files) {
|
|
4799
4928
|
writeGeneratedFile(file);
|
|
4800
4929
|
}
|
|
4801
|
-
const fixtureRegistryFile = maybeGenerateFixtureRegistry(
|
|
4930
|
+
const fixtureRegistryFile = maybeGenerateFixtureRegistry(emittableComponentHierarchyMap, {
|
|
4802
4931
|
generateFixtures,
|
|
4803
4932
|
pomOutDir: outDir,
|
|
4804
4933
|
projectRoot,
|
|
@@ -4809,7 +4938,7 @@ async function generateFiles(componentHierarchyMap, vueFilesPathMap, basePageCla
|
|
|
4809
4938
|
}
|
|
4810
4939
|
}
|
|
4811
4940
|
if (emitLanguages.includes("csharp")) {
|
|
4812
|
-
const csFiles = generateAggregatedCSharpFiles(
|
|
4941
|
+
const csFiles = generateAggregatedCSharpFiles(emittableComponentHierarchyMap, outDir, {
|
|
4813
4942
|
testIdAttribute,
|
|
4814
4943
|
csharp
|
|
4815
4944
|
});
|
|
@@ -5546,7 +5675,12 @@ function prepareViewObjectModelClass(componentName, dependencies, componentHiera
|
|
|
5546
5675
|
const rawComponentRefsForInstances = isView ? usedComponentSet?.size ? usedComponentSet : childrenComponentSet : childrenComponentSet;
|
|
5547
5676
|
const componentRefsForInstances = /* @__PURE__ */ new Set();
|
|
5548
5677
|
for (const ref of rawComponentRefsForInstances) {
|
|
5549
|
-
|
|
5678
|
+
const resolvedRef = resolveTrackedComponentRef(ref) ?? normalizeTrackedComponentRef(ref);
|
|
5679
|
+
const resolvedDependencies = componentHierarchyMap.get(resolvedRef);
|
|
5680
|
+
if (!resolvedDependencies?.dataTestIdSet.size) {
|
|
5681
|
+
continue;
|
|
5682
|
+
}
|
|
5683
|
+
componentRefsForInstances.add(resolvedRef);
|
|
5550
5684
|
}
|
|
5551
5685
|
const hasChildComponent = (needle) => {
|
|
5552
5686
|
const normalizedNeedle = normalizeTrackedComponentRef(needle);
|
|
@@ -7105,6 +7239,7 @@ function createTestIdTransform(componentName, componentHierarchyMap, nativeWrapp
|
|
|
7105
7239
|
const warn = options.warn;
|
|
7106
7240
|
const vueFilesPathMap = options.vueFilesPathMap;
|
|
7107
7241
|
const wrapperSearchRoots = options.wrapperSearchRoots ?? [];
|
|
7242
|
+
const annotatorMetadata = options.annotatorMetadata ?? null;
|
|
7108
7243
|
const safeRealpath2 = (p) => {
|
|
7109
7244
|
try {
|
|
7110
7245
|
return fs.existsSync(p) ? fs.realpathSync(p) : p;
|
|
@@ -7368,7 +7503,8 @@ function createTestIdTransform(componentName, componentHierarchyMap, nativeWrapp
|
|
|
7368
7503
|
testIdAttribute,
|
|
7369
7504
|
existingIdBehavior,
|
|
7370
7505
|
nameCollisionBehavior,
|
|
7371
|
-
warn
|
|
7506
|
+
warn,
|
|
7507
|
+
annotatorMetadata
|
|
7372
7508
|
});
|
|
7373
7509
|
};
|
|
7374
7510
|
const { nativeWrappersValue, optionDataTestIdPrefixValue, semanticNameHint } = getNativeWrapperTransformInfo(element, componentName, nativeWrappers);
|
|
@@ -8359,48 +8495,6 @@ function collectAccessibilityReviewWarnings(manifest) {
|
|
|
8359
8495
|
}
|
|
8360
8496
|
return warnings;
|
|
8361
8497
|
}
|
|
8362
|
-
function removeByKeySegment(value) {
|
|
8363
|
-
const idx = value.indexOf("ByKey");
|
|
8364
|
-
if (idx < 0) {
|
|
8365
|
-
return value;
|
|
8366
|
-
}
|
|
8367
|
-
return value.slice(0, idx) + value.slice(idx + "ByKey".length);
|
|
8368
|
-
}
|
|
8369
|
-
function hasRoleSuffix(baseName, roleSuffix) {
|
|
8370
|
-
if (baseName.endsWith(roleSuffix)) {
|
|
8371
|
-
return true;
|
|
8372
|
-
}
|
|
8373
|
-
const re = new RegExp(`^${roleSuffix}\\d+$`);
|
|
8374
|
-
return re.test(baseName);
|
|
8375
|
-
}
|
|
8376
|
-
function getGeneratedPropertyName(pom) {
|
|
8377
|
-
if (pom.getterNameOverride) {
|
|
8378
|
-
return pom.getterNameOverride;
|
|
8379
|
-
}
|
|
8380
|
-
const roleSuffix = upperFirst(pom.nativeRole || "Element");
|
|
8381
|
-
const baseName = upperFirst(pom.methodName);
|
|
8382
|
-
const propertyName = hasRoleSuffix(baseName, roleSuffix) ? baseName : `${baseName}${roleSuffix}`;
|
|
8383
|
-
return pom.selector.patternKind === "parameterized" ? removeByKeySegment(propertyName) : propertyName;
|
|
8384
|
-
}
|
|
8385
|
-
function getGeneratedActionName(entry, pom) {
|
|
8386
|
-
const methodNameUpper = upperFirst(pom.methodName);
|
|
8387
|
-
const radioMethodNameUpper = upperFirst(pom.methodName || "Radio");
|
|
8388
|
-
const isNavigation = !!entry.targetPageObjectModelClass;
|
|
8389
|
-
if (isNavigation) {
|
|
8390
|
-
return `goTo${methodNameUpper}`;
|
|
8391
|
-
}
|
|
8392
|
-
switch (pom.nativeRole) {
|
|
8393
|
-
case "input":
|
|
8394
|
-
return `type${methodNameUpper}`;
|
|
8395
|
-
case "select":
|
|
8396
|
-
case "vselect":
|
|
8397
|
-
return `select${methodNameUpper}`;
|
|
8398
|
-
case "radio":
|
|
8399
|
-
return `select${radioMethodNameUpper}`;
|
|
8400
|
-
default:
|
|
8401
|
-
return `click${methodNameUpper}`;
|
|
8402
|
-
}
|
|
8403
|
-
}
|
|
8404
8498
|
function matchesPrimarySelector(extraMethod, pom) {
|
|
8405
8499
|
if (extraMethod.selector.kind !== "testId") {
|
|
8406
8500
|
return false;
|
|
@@ -8411,7 +8505,7 @@ function getManifestEntry(componentName, entry, componentMetadata, extraMethods)
|
|
|
8411
8505
|
const testId = entry.selectorValue.formatted;
|
|
8412
8506
|
const metadata = componentMetadata?.get(testId);
|
|
8413
8507
|
const pom = entry.pom;
|
|
8414
|
-
const generatedActionName = pom ?
|
|
8508
|
+
const generatedActionName = pom ? buildPomGeneratedActionName(pom) : null;
|
|
8415
8509
|
const extraActionNames = pom ? extraMethods.filter((extraMethod) => matchesPrimarySelector(extraMethod, pom)).map((extraMethod) => extraMethod.name).sort((a, b) => a.localeCompare(b)) : [];
|
|
8416
8510
|
const generatedActionNames = Array.from(/* @__PURE__ */ new Set([
|
|
8417
8511
|
...generatedActionName ? [generatedActionName] : [],
|
|
@@ -8429,13 +8523,15 @@ function getManifestEntry(componentName, entry, componentMetadata, extraMethods)
|
|
|
8429
8523
|
}) : componentName,
|
|
8430
8524
|
inferredRole: pom?.nativeRole ?? null,
|
|
8431
8525
|
...accessibility ? { accessibility } : {},
|
|
8432
|
-
generatedPropertyName: pom ?
|
|
8526
|
+
generatedPropertyName: pom ? buildPomGeneratedPropertyName(pom) : null,
|
|
8433
8527
|
generatedActionName,
|
|
8434
8528
|
generatedActionNames,
|
|
8435
8529
|
emitPrimary: pom?.emitPrimary !== false,
|
|
8436
8530
|
...entry.targetPageObjectModelClass ? { targetPageObjectModelClass: entry.targetPageObjectModelClass } : {},
|
|
8437
8531
|
...metadata?.tag ? { sourceTag: metadata.tag } : {},
|
|
8438
8532
|
...metadata ? { sourceTagType: metadata.tagType } : {},
|
|
8533
|
+
...metadata?.sourceLine !== void 0 ? { sourceLine: metadata.sourceLine } : {},
|
|
8534
|
+
...metadata?.sourceColumn !== void 0 ? { sourceColumn: metadata.sourceColumn } : {},
|
|
8439
8535
|
...metadata?.patchFlag !== void 0 ? { patchFlag: metadata.patchFlag } : {},
|
|
8440
8536
|
...metadata?.dynamicProps?.length ? { dynamicProps: metadata.dynamicProps } : {},
|
|
8441
8537
|
...metadata?.hasClickHandler !== void 0 ? { hasClickHandler: metadata.hasClickHandler } : {},
|
|
@@ -8445,7 +8541,7 @@ function getManifestEntry(componentName, entry, componentMetadata, extraMethods)
|
|
|
8445
8541
|
};
|
|
8446
8542
|
}
|
|
8447
8543
|
function buildPomManifest(componentHierarchyMap, elementMetadata) {
|
|
8448
|
-
const manifestEntries = Array.from(componentHierarchyMap.entries()).sort((a, b) => a[0].localeCompare(b[0])).map(([componentName, dependencies]) => {
|
|
8544
|
+
const manifestEntries = Array.from(componentHierarchyMap.entries()).filter(([componentName, dependencies]) => !shouldSuppressStandaloneWrapperFallbackSurface(componentName, dependencies)).sort((a, b) => a[0].localeCompare(b[0])).map(([componentName, dependencies]) => {
|
|
8449
8545
|
const entries = Array.from(dependencies.dataTestIdSet).sort((a, b) => a.selectorValue.formatted.localeCompare(b.selectorValue.formatted)).map((entry) => getManifestEntry(componentName, entry, elementMetadata.get(componentName), dependencies.pomExtraMethods ?? []));
|
|
8450
8546
|
if (!entries.length) {
|
|
8451
8547
|
return null;
|
|
@@ -8461,9 +8557,15 @@ function buildPomManifest(componentHierarchyMap, elementMetadata) {
|
|
|
8461
8557
|
}).filter((entry) => entry !== null);
|
|
8462
8558
|
return Object.fromEntries(manifestEntries);
|
|
8463
8559
|
}
|
|
8464
|
-
function buildTestIdManifest(
|
|
8560
|
+
function buildTestIdManifest(componentHierarchyMap) {
|
|
8465
8561
|
return Object.fromEntries(
|
|
8466
|
-
|
|
8562
|
+
Array.from(componentHierarchyMap.entries()).sort((a, b) => a[0].localeCompare(b[0])).map(([componentName, dependencies]) => {
|
|
8563
|
+
const testIds = Array.from(dependencies.dataTestIdSet).map((entry) => entry.selectorValue.formatted).filter(Boolean);
|
|
8564
|
+
if (!testIds.length) {
|
|
8565
|
+
return null;
|
|
8566
|
+
}
|
|
8567
|
+
return [componentName, Array.from(new Set(testIds)).sort((a, b) => a.localeCompare(b))];
|
|
8568
|
+
}).filter((entry) => entry !== null)
|
|
8467
8569
|
);
|
|
8468
8570
|
}
|
|
8469
8571
|
function writeConstJson(value) {
|
|
@@ -8473,7 +8575,7 @@ function writeConstJson(value) {
|
|
|
8473
8575
|
}
|
|
8474
8576
|
function generateTestIdsModule(componentHierarchyMap, elementMetadata) {
|
|
8475
8577
|
const pomManifest = buildPomManifest(componentHierarchyMap, elementMetadata);
|
|
8476
|
-
const testIdManifest = buildTestIdManifest(
|
|
8578
|
+
const testIdManifest = buildTestIdManifest(componentHierarchyMap);
|
|
8477
8579
|
return renderSourceFile("virtual-testids.ts", (sourceFile) => {
|
|
8478
8580
|
sourceFile.addStatements("// Virtual module: test id manifest");
|
|
8479
8581
|
sourceFile.addVariableStatement({
|
|
@@ -8559,7 +8661,89 @@ function createTestIdsVirtualModulesPlugin(componentHierarchyMap, elementMetadat
|
|
|
8559
8661
|
}
|
|
8560
8662
|
};
|
|
8561
8663
|
}
|
|
8562
|
-
|
|
8664
|
+
const ANNOTATOR_CLIENT_VIRTUAL_ID = "virtual:vue-pom-generator/annotator-client";
|
|
8665
|
+
const ANNOTATOR_CLIENT_RESOLVED_ID = `\0${ANNOTATOR_CLIENT_VIRTUAL_ID}`;
|
|
8666
|
+
const DEFAULT_ENTRY_SUFFIXES = [
|
|
8667
|
+
"/src/main.ts",
|
|
8668
|
+
"/src/main.js",
|
|
8669
|
+
"/src/main.mts",
|
|
8670
|
+
"/src/main.tsx",
|
|
8671
|
+
"/src/main.jsx"
|
|
8672
|
+
];
|
|
8673
|
+
function toFsImportPath(filePath) {
|
|
8674
|
+
return `/@fs/${filePath.replace(/\\/g, "/")}`;
|
|
8675
|
+
}
|
|
8676
|
+
function resolveAnnotatorClientPath() {
|
|
8677
|
+
const candidates = [
|
|
8678
|
+
node_url.fileURLToPath(new URL("./client.ts", typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index.cjs", document.baseURI).href)),
|
|
8679
|
+
node_url.fileURLToPath(new URL("../plugin/runtime/annotator/client.ts", typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index.cjs", document.baseURI).href))
|
|
8680
|
+
];
|
|
8681
|
+
const resolved = candidates.find((candidate) => fs.existsSync(candidate));
|
|
8682
|
+
if (!resolved) {
|
|
8683
|
+
throw new Error("[vue-pom-generator] Unable to locate annotator client source.");
|
|
8684
|
+
}
|
|
8685
|
+
return path.resolve(resolved);
|
|
8686
|
+
}
|
|
8687
|
+
function createAnnotatorUiPlugin(options) {
|
|
8688
|
+
const clientPath = resolveAnnotatorClientPath();
|
|
8689
|
+
const clientImportPath = toFsImportPath(clientPath);
|
|
8690
|
+
const clientOptions = JSON.stringify({
|
|
8691
|
+
sourceAttribute: options.sourceAttribute,
|
|
8692
|
+
metadataAttributePrefix: options.metadataAttributePrefix,
|
|
8693
|
+
outputDetail: options.outputDetail,
|
|
8694
|
+
copyToClipboard: options.copyToClipboard,
|
|
8695
|
+
showComponentTree: options.showComponentTree
|
|
8696
|
+
});
|
|
8697
|
+
return {
|
|
8698
|
+
name: "vue-pom-generator:annotator-ui",
|
|
8699
|
+
apply: "serve",
|
|
8700
|
+
resolveId(id) {
|
|
8701
|
+
if (id === ANNOTATOR_CLIENT_VIRTUAL_ID) {
|
|
8702
|
+
return ANNOTATOR_CLIENT_RESOLVED_ID;
|
|
8703
|
+
}
|
|
8704
|
+
},
|
|
8705
|
+
load(id) {
|
|
8706
|
+
if (id !== ANNOTATOR_CLIENT_RESOLVED_ID) {
|
|
8707
|
+
return null;
|
|
8708
|
+
}
|
|
8709
|
+
return [
|
|
8710
|
+
`import { mountAnnotatorClient } from ${JSON.stringify(clientImportPath)};`,
|
|
8711
|
+
`mountAnnotatorClient(${clientOptions});`,
|
|
8712
|
+
""
|
|
8713
|
+
].join("\n");
|
|
8714
|
+
},
|
|
8715
|
+
transform(code, id) {
|
|
8716
|
+
if (!options.enabled) {
|
|
8717
|
+
return null;
|
|
8718
|
+
}
|
|
8719
|
+
const normalizedId = id.replace(/\\/g, "/");
|
|
8720
|
+
if (!DEFAULT_ENTRY_SUFFIXES.some((suffix) => normalizedId.endsWith(suffix))) {
|
|
8721
|
+
return null;
|
|
8722
|
+
}
|
|
8723
|
+
if (code.includes(ANNOTATOR_CLIENT_VIRTUAL_ID)) {
|
|
8724
|
+
return null;
|
|
8725
|
+
}
|
|
8726
|
+
return {
|
|
8727
|
+
code: `import ${JSON.stringify(ANNOTATOR_CLIENT_VIRTUAL_ID)};
|
|
8728
|
+
${code}`,
|
|
8729
|
+
map: null
|
|
8730
|
+
};
|
|
8731
|
+
},
|
|
8732
|
+
transformIndexHtml() {
|
|
8733
|
+
if (!options.enabled) {
|
|
8734
|
+
return void 0;
|
|
8735
|
+
}
|
|
8736
|
+
const tag = {
|
|
8737
|
+
tag: "script",
|
|
8738
|
+
attrs: { type: "module" },
|
|
8739
|
+
children: `import ${JSON.stringify(ANNOTATOR_CLIENT_VIRTUAL_ID)};`,
|
|
8740
|
+
injectTo: "body"
|
|
8741
|
+
};
|
|
8742
|
+
return [tag];
|
|
8743
|
+
}
|
|
8744
|
+
};
|
|
8745
|
+
}
|
|
8746
|
+
function createInternalPlugins(options) {
|
|
8563
8747
|
const {
|
|
8564
8748
|
componentHierarchyMap,
|
|
8565
8749
|
elementMetadata,
|
|
@@ -8575,7 +8759,8 @@ function createSupportPlugins(options) {
|
|
|
8575
8759
|
generation,
|
|
8576
8760
|
projectRootRef,
|
|
8577
8761
|
basePageClassPath: basePageClassPathOverride,
|
|
8578
|
-
loggerRef
|
|
8762
|
+
loggerRef,
|
|
8763
|
+
annotatorRuntime
|
|
8579
8764
|
} = options;
|
|
8580
8765
|
const {
|
|
8581
8766
|
outDir,
|
|
@@ -8649,7 +8834,13 @@ function createSupportPlugins(options) {
|
|
|
8649
8834
|
loggerRef
|
|
8650
8835
|
});
|
|
8651
8836
|
const virtualModules = createTestIdsVirtualModulesPlugin(componentHierarchyMap, elementMetadata);
|
|
8652
|
-
|
|
8837
|
+
const annotatorUiPlugin = createAnnotatorUiPlugin({
|
|
8838
|
+
...annotatorRuntime.ui,
|
|
8839
|
+
enabled: annotatorRuntime.enabled && annotatorRuntime.ui.enabled,
|
|
8840
|
+
sourceAttribute: annotatorRuntime.sourceAttribute,
|
|
8841
|
+
metadataAttributePrefix: annotatorRuntime.metadataAttributePrefix
|
|
8842
|
+
});
|
|
8843
|
+
return [tsProcessor, devProcessor, virtualModules, annotatorUiPlugin];
|
|
8653
8844
|
}
|
|
8654
8845
|
function findDataTestIdProp(element, attributeName = "data-testid") {
|
|
8655
8846
|
return element.props.find(
|
|
@@ -8769,7 +8960,9 @@ function tryCreateElementMetadata(args) {
|
|
|
8769
8960
|
staticAriaLabel: findStaticAttributeValue(element, "aria-label"),
|
|
8770
8961
|
staticRole: findStaticAttributeValue(element, "role"),
|
|
8771
8962
|
staticTitle: findStaticAttributeValue(element, "title"),
|
|
8772
|
-
staticTextContent: collectStaticTextContent(element.children)
|
|
8963
|
+
staticTextContent: collectStaticTextContent(element.children),
|
|
8964
|
+
sourceLine: element.loc?.start.line,
|
|
8965
|
+
sourceColumn: element.loc?.start.column
|
|
8773
8966
|
};
|
|
8774
8967
|
return metadata;
|
|
8775
8968
|
}
|
|
@@ -8841,7 +9034,8 @@ function createVuePluginWithTestIds(options) {
|
|
|
8841
9034
|
loggerRef,
|
|
8842
9035
|
getSourceDirs,
|
|
8843
9036
|
getWrapperSearchRoots,
|
|
8844
|
-
getProjectRoot
|
|
9037
|
+
getProjectRoot,
|
|
9038
|
+
annotatorMetadata
|
|
8845
9039
|
} = options;
|
|
8846
9040
|
const lastAccessibilityWarningSignatureByComponent = /* @__PURE__ */ new Map();
|
|
8847
9041
|
const getComponentNameFromPath = (filename) => {
|
|
@@ -8858,27 +9052,15 @@ function createVuePluginWithTestIds(options) {
|
|
|
8858
9052
|
return false;
|
|
8859
9053
|
const cleanPath = filename.includes("?") ? filename.substring(0, filename.indexOf("?")) : filename;
|
|
8860
9054
|
const projectRoot = getProjectRoot();
|
|
8861
|
-
const
|
|
8862
|
-
|
|
8863
|
-
|
|
8864
|
-
|
|
8865
|
-
|
|
8866
|
-
|
|
8867
|
-
const rootsToTry = [projectRoot, process.cwd()];
|
|
8868
|
-
const matched = getSourceDirs().some((dir) => {
|
|
8869
|
-
return rootsToTry.some((root) => {
|
|
8870
|
-
const absDir = path.resolve(root, dir);
|
|
8871
|
-
if (absFilename.startsWith(absDir + path.sep) || absFilename === absDir)
|
|
8872
|
-
return true;
|
|
8873
|
-
if (dir.startsWith("app/") && root.endsWith("/app")) {
|
|
8874
|
-
const relativeDir = dir.substring(4);
|
|
8875
|
-
const absDirAlt = path.resolve(root, relativeDir);
|
|
8876
|
-
return absFilename.startsWith(absDirAlt + path.sep) || absFilename === absDirAlt;
|
|
8877
|
-
}
|
|
8878
|
-
return false;
|
|
8879
|
-
});
|
|
9055
|
+
const matched = isFileInConfiguredSourceScope({
|
|
9056
|
+
filename,
|
|
9057
|
+
projectRoot,
|
|
9058
|
+
viewsDirAbs: getViewsDirAbs(),
|
|
9059
|
+
sourceDirs: getSourceDirs(),
|
|
9060
|
+
extraRoots: [process.cwd()]
|
|
8880
9061
|
});
|
|
8881
9062
|
if (cleanPath.endsWith(".vue") && !matched) {
|
|
9063
|
+
const absFilename = path.normalize(path.isAbsolute(cleanPath) ? cleanPath : path.resolve(projectRoot, cleanPath));
|
|
8882
9064
|
loggerRef.current.debug(`[isFileInScope] REJECTED: ${absFilename} (Clean: ${cleanPath})`);
|
|
8883
9065
|
}
|
|
8884
9066
|
return matched;
|
|
@@ -8912,7 +9094,8 @@ function createVuePluginWithTestIds(options) {
|
|
|
8912
9094
|
missingSemanticNameBehavior,
|
|
8913
9095
|
warn: (message) => loggerRef.current.warn(message),
|
|
8914
9096
|
vueFilesPathMap,
|
|
8915
|
-
wrapperSearchRoots: getWrapperSearchRoots()
|
|
9097
|
+
wrapperSearchRoots: getWrapperSearchRoots(),
|
|
9098
|
+
annotatorMetadata
|
|
8916
9099
|
}
|
|
8917
9100
|
)
|
|
8918
9101
|
);
|
|
@@ -8967,7 +9150,8 @@ function createVuePluginWithTestIds(options) {
|
|
|
8967
9150
|
missingSemanticNameBehavior,
|
|
8968
9151
|
warn: (message) => loggerRef.current.warn(message),
|
|
8969
9152
|
vueFilesPathMap,
|
|
8970
|
-
wrapperSearchRoots: getWrapperSearchRoots()
|
|
9153
|
+
wrapperSearchRoots: getWrapperSearchRoots(),
|
|
9154
|
+
annotatorMetadata
|
|
8971
9155
|
}
|
|
8972
9156
|
);
|
|
8973
9157
|
perFileTransform.set(componentName, transform);
|
|
@@ -9112,6 +9296,12 @@ function assertOneOf(value, allowed, name) {
|
|
|
9112
9296
|
}
|
|
9113
9297
|
throw new TypeError(`${name} must be one of: ${allowed.join(", ")}.`);
|
|
9114
9298
|
}
|
|
9299
|
+
function assertDataAttributeName(value, name) {
|
|
9300
|
+
assertNonEmptyString(value, name);
|
|
9301
|
+
if (!value.startsWith("data-")) {
|
|
9302
|
+
throw new TypeError(`${name} must start with "data-".`);
|
|
9303
|
+
}
|
|
9304
|
+
}
|
|
9115
9305
|
function readPackageJson(projectRoot) {
|
|
9116
9306
|
const packageJsonPath = path.join(projectRoot, "package.json");
|
|
9117
9307
|
if (!fs.existsSync(packageJsonPath)) {
|
|
@@ -9275,6 +9465,19 @@ function createVuePomGeneratorPlugins(options = {}) {
|
|
|
9275
9465
|
const generationEnabled = generationOptions !== null;
|
|
9276
9466
|
const vueGenerationOptions = generationOptions;
|
|
9277
9467
|
const verbosity = options.logging?.verbosity ?? "warn";
|
|
9468
|
+
const annotatorRuntimeOptions = options.runtime?.annotator;
|
|
9469
|
+
const annotatorUiRuntimeOptions = annotatorRuntimeOptions?.ui;
|
|
9470
|
+
const resolvedAnnotatorRuntimeOptions = {
|
|
9471
|
+
enabled: annotatorRuntimeOptions?.enabled === true,
|
|
9472
|
+
sourceAttribute: annotatorRuntimeOptions?.sourceAttribute ?? "data-v-inspector",
|
|
9473
|
+
metadataAttributePrefix: annotatorRuntimeOptions?.metadataAttributePrefix ?? "data-v-pom",
|
|
9474
|
+
ui: {
|
|
9475
|
+
enabled: annotatorUiRuntimeOptions?.enabled === true,
|
|
9476
|
+
outputDetail: annotatorUiRuntimeOptions?.outputDetail ?? "forensic",
|
|
9477
|
+
copyToClipboard: annotatorUiRuntimeOptions?.copyToClipboard ?? false,
|
|
9478
|
+
showComponentTree: annotatorUiRuntimeOptions?.showComponentTree ?? true
|
|
9479
|
+
}
|
|
9480
|
+
};
|
|
9278
9481
|
const vueOptions = options.vueOptions;
|
|
9279
9482
|
const resolvedInjectionOptionsRef = {
|
|
9280
9483
|
current: resolveInjectionSupportOptions({
|
|
@@ -9378,6 +9581,10 @@ function createVuePomGeneratorPlugins(options = {}) {
|
|
|
9378
9581
|
assertNonEmptyStringArray(getComponentDirs(), "[vue-pom-generator] injection.componentDirs");
|
|
9379
9582
|
assertNonEmptyStringArray(getLayoutDirs(), "[vue-pom-generator] injection.layoutDirs");
|
|
9380
9583
|
assertNonEmptyStringArray(getWrapperSearchRoots(), "[vue-pom-generator] injection.wrapperSearchRoots");
|
|
9584
|
+
if (resolvedAnnotatorRuntimeOptions.enabled) {
|
|
9585
|
+
assertDataAttributeName(resolvedAnnotatorRuntimeOptions.sourceAttribute, "[vue-pom-generator] runtime.annotator.sourceAttribute");
|
|
9586
|
+
assertDataAttributeName(resolvedAnnotatorRuntimeOptions.metadataAttributePrefix, "[vue-pom-generator] runtime.annotator.metadataAttributePrefix");
|
|
9587
|
+
}
|
|
9381
9588
|
if (generationEnabled) {
|
|
9382
9589
|
assertNonEmptyString(resolvedGenerationOptions.outDir, "[vue-pom-generator] generation.outDir");
|
|
9383
9590
|
assertOneOf(resolvedGenerationOptions.typescriptOutputStructure, ["aggregated", "split"], "[vue-pom-generator] generation.playwright.outputStructure");
|
|
@@ -9420,10 +9627,14 @@ function createVuePomGeneratorPlugins(options = {}) {
|
|
|
9420
9627
|
loggerRef,
|
|
9421
9628
|
getSourceDirs,
|
|
9422
9629
|
getWrapperSearchRoots: getWrapperSearchRootsAbs,
|
|
9423
|
-
getProjectRoot: () => projectRootRef.current
|
|
9630
|
+
getProjectRoot: () => projectRootRef.current,
|
|
9631
|
+
annotatorMetadata: resolvedAnnotatorRuntimeOptions.enabled ? {
|
|
9632
|
+
sourceAttribute: resolvedAnnotatorRuntimeOptions.sourceAttribute,
|
|
9633
|
+
metadataAttributePrefix: resolvedAnnotatorRuntimeOptions.metadataAttributePrefix
|
|
9634
|
+
} : null
|
|
9424
9635
|
});
|
|
9425
9636
|
templateCompilerOptionsForResolvedPlugin = templateCompilerOptions;
|
|
9426
|
-
const
|
|
9637
|
+
const internalPlugins = createInternalPlugins({
|
|
9427
9638
|
componentHierarchyMap,
|
|
9428
9639
|
elementMetadata,
|
|
9429
9640
|
vueFilesPathMap,
|
|
@@ -9438,7 +9649,8 @@ function createVuePomGeneratorPlugins(options = {}) {
|
|
|
9438
9649
|
generation: resolvedGenerationOptions,
|
|
9439
9650
|
projectRootRef,
|
|
9440
9651
|
basePageClassPath: basePageClassPathOverride,
|
|
9441
|
-
loggerRef
|
|
9652
|
+
loggerRef,
|
|
9653
|
+
annotatorRuntime: resolvedAnnotatorRuntimeOptions
|
|
9442
9654
|
});
|
|
9443
9655
|
if (isNuxt) {
|
|
9444
9656
|
loggerRef.current.info("Nuxt environment detected. Skipping internal @vitejs/plugin-vue to avoid conflicts.");
|
|
@@ -9449,7 +9661,7 @@ function createVuePomGeneratorPlugins(options = {}) {
|
|
|
9449
9661
|
configPlugin,
|
|
9450
9662
|
metadataCollectorPlugin,
|
|
9451
9663
|
...usesExternalVuePlugin ? [] : [internalVuePlugin],
|
|
9452
|
-
...
|
|
9664
|
+
...internalPlugins
|
|
9453
9665
|
];
|
|
9454
9666
|
if (!generationEnabled) {
|
|
9455
9667
|
const virtualModules = createTestIdsVirtualModulesPlugin(componentHierarchyMap, elementMetadata);
|