@immense/vue-pom-generator 1.0.29 → 1.0.31
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 +11 -7
- package/RELEASE_NOTES.md +40 -26
- package/class-generation/index.ts +9 -0
- package/dist/index.cjs +323 -91
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +324 -92
- package/dist/index.mjs.map +1 -1
- package/dist/plugin/create-vue-pom-generator-plugins.d.ts.map +1 -1
- package/dist/plugin/support/dev-plugin.d.ts +1 -0
- package/dist/plugin/support/dev-plugin.d.ts.map +1 -1
- package/dist/plugin/support-plugins.d.ts +1 -0
- package/dist/plugin/support-plugins.d.ts.map +1 -1
- package/dist/plugin/types.d.ts +25 -13
- 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/transform.d.ts +1 -0
- package/dist/transform.d.ts.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -606,6 +606,124 @@ function getTemplateSlotScope(node) {
|
|
|
606
606
|
}
|
|
607
607
|
return null;
|
|
608
608
|
}
|
|
609
|
+
function isSimpleScopeIdentifier(value) {
|
|
610
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(value);
|
|
611
|
+
}
|
|
612
|
+
function buildSlotScopeFallbackKeyExpression(identifier) {
|
|
613
|
+
return `${identifier}.key ?? ${identifier}.data?.id ?? ${identifier}.id ?? ${identifier}.value ?? ${identifier}`;
|
|
614
|
+
}
|
|
615
|
+
function tryGetBindingIdentifierName(node) {
|
|
616
|
+
if (!node) {
|
|
617
|
+
return null;
|
|
618
|
+
}
|
|
619
|
+
if (types.isIdentifier(node)) {
|
|
620
|
+
return node.name;
|
|
621
|
+
}
|
|
622
|
+
if (types.isAssignmentPattern(node)) {
|
|
623
|
+
return tryGetBindingIdentifierName(node.left);
|
|
624
|
+
}
|
|
625
|
+
if (types.isRestElement(node)) {
|
|
626
|
+
return tryGetBindingIdentifierName(node.argument);
|
|
627
|
+
}
|
|
628
|
+
return null;
|
|
629
|
+
}
|
|
630
|
+
function getSlotScopeObjectPropertyKeyName(node) {
|
|
631
|
+
if (types.isIdentifier(node)) {
|
|
632
|
+
return node.name;
|
|
633
|
+
}
|
|
634
|
+
if (types.isStringLiteral(node)) {
|
|
635
|
+
return node.value;
|
|
636
|
+
}
|
|
637
|
+
return null;
|
|
638
|
+
}
|
|
639
|
+
function tryGetSlotScopeKeyCandidate(node) {
|
|
640
|
+
if (!node) {
|
|
641
|
+
return null;
|
|
642
|
+
}
|
|
643
|
+
if (types.isIdentifier(node)) {
|
|
644
|
+
return {
|
|
645
|
+
priority: 2,
|
|
646
|
+
expression: buildSlotScopeFallbackKeyExpression(node.name)
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
if (types.isAssignmentPattern(node)) {
|
|
650
|
+
return tryGetSlotScopeKeyCandidate(node.left);
|
|
651
|
+
}
|
|
652
|
+
if (types.isRestElement(node)) {
|
|
653
|
+
return tryGetSlotScopeKeyCandidate(node.argument);
|
|
654
|
+
}
|
|
655
|
+
if (!types.isObjectPattern(node)) {
|
|
656
|
+
return null;
|
|
657
|
+
}
|
|
658
|
+
let best = null;
|
|
659
|
+
for (const property of node.properties) {
|
|
660
|
+
let candidate = null;
|
|
661
|
+
if (types.isRestElement(property)) {
|
|
662
|
+
candidate = tryGetSlotScopeKeyCandidate(property.argument);
|
|
663
|
+
if (candidate) {
|
|
664
|
+
candidate = { ...candidate, priority: Math.max(candidate.priority, 2) };
|
|
665
|
+
}
|
|
666
|
+
} else if (types.isObjectProperty(property)) {
|
|
667
|
+
const keyName = getSlotScopeObjectPropertyKeyName(property.key);
|
|
668
|
+
const bindingName = tryGetBindingIdentifierName(property.value) ?? tryGetBindingIdentifierName(property.key);
|
|
669
|
+
if (bindingName) {
|
|
670
|
+
if (keyName === "key" || bindingName === "key") {
|
|
671
|
+
candidate = {
|
|
672
|
+
priority: 0,
|
|
673
|
+
expression: bindingName
|
|
674
|
+
};
|
|
675
|
+
} else {
|
|
676
|
+
candidate = {
|
|
677
|
+
priority: keyName === "data" ? 1 : 2,
|
|
678
|
+
expression: buildSlotScopeFallbackKeyExpression(bindingName)
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
if (candidate && (!best || candidate.priority < best.priority)) {
|
|
684
|
+
best = candidate;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
return best;
|
|
688
|
+
}
|
|
689
|
+
function tryGetTemplateSlotScopeKeyExpression(scope) {
|
|
690
|
+
const trimmed = scope.trim();
|
|
691
|
+
if (!trimmed) {
|
|
692
|
+
return null;
|
|
693
|
+
}
|
|
694
|
+
if (isSimpleScopeIdentifier(trimmed)) {
|
|
695
|
+
return buildSlotScopeFallbackKeyExpression(trimmed);
|
|
696
|
+
}
|
|
697
|
+
try {
|
|
698
|
+
const parsed = parser.parse(`(${trimmed}) => {}`, {
|
|
699
|
+
sourceType: "module",
|
|
700
|
+
plugins: ["typescript"]
|
|
701
|
+
});
|
|
702
|
+
const statement = parsed.program.body[0];
|
|
703
|
+
if (statement && types.isExpressionStatement(statement) && types.isArrowFunctionExpression(statement.expression)) {
|
|
704
|
+
return tryGetSlotScopeKeyCandidate(statement.expression.params[0])?.expression ?? null;
|
|
705
|
+
}
|
|
706
|
+
} catch {
|
|
707
|
+
}
|
|
708
|
+
if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
|
|
709
|
+
const inner = trimmed.slice(1, -1).trim();
|
|
710
|
+
let cutIdx = -1;
|
|
711
|
+
const commaIdx = inner.indexOf(",");
|
|
712
|
+
const colonIdx = inner.indexOf(":");
|
|
713
|
+
if (commaIdx !== -1 && colonIdx !== -1) {
|
|
714
|
+
cutIdx = Math.min(commaIdx, colonIdx);
|
|
715
|
+
} else if (commaIdx !== -1) {
|
|
716
|
+
cutIdx = commaIdx;
|
|
717
|
+
} else if (colonIdx !== -1) {
|
|
718
|
+
cutIdx = colonIdx;
|
|
719
|
+
}
|
|
720
|
+
const first = (cutIdx === -1 ? inner : inner.slice(0, cutIdx)).trim();
|
|
721
|
+
if (first && isSimpleScopeIdentifier(first)) {
|
|
722
|
+
return buildSlotScopeFallbackKeyExpression(first);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
return trimmed;
|
|
726
|
+
}
|
|
609
727
|
function nodeHasToDirective(node) {
|
|
610
728
|
const toDirective = findDirectiveByName(node, "bind", "to");
|
|
611
729
|
if (toDirective?.exp) {
|
|
@@ -681,25 +799,7 @@ function getContainedInSlotDataKeyValue(node, hierarchyMap2) {
|
|
|
681
799
|
if (parent.type === compilerCore.NodeTypes.ELEMENT && parent.tag === "template") {
|
|
682
800
|
const scope = getTemplateSlotScope(parent);
|
|
683
801
|
if (scope) {
|
|
684
|
-
|
|
685
|
-
if (key.startsWith("{") && key.endsWith("}")) {
|
|
686
|
-
const inner = key.slice(1, -1).trim();
|
|
687
|
-
let cutIdx = -1;
|
|
688
|
-
const commaIdx = inner.indexOf(",");
|
|
689
|
-
const colonIdx = inner.indexOf(":");
|
|
690
|
-
if (commaIdx !== -1 && colonIdx !== -1) {
|
|
691
|
-
cutIdx = Math.min(commaIdx, colonIdx);
|
|
692
|
-
} else if (commaIdx !== -1) {
|
|
693
|
-
cutIdx = commaIdx;
|
|
694
|
-
} else if (colonIdx !== -1) {
|
|
695
|
-
cutIdx = colonIdx;
|
|
696
|
-
}
|
|
697
|
-
const first = (cutIdx === -1 ? inner : inner.slice(0, cutIdx)).trim();
|
|
698
|
-
if (first) {
|
|
699
|
-
key = first;
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
return key;
|
|
802
|
+
return tryGetTemplateSlotScopeKeyExpression(scope);
|
|
703
803
|
}
|
|
704
804
|
}
|
|
705
805
|
parent = getParent(hierarchyMap2, parent);
|
|
@@ -1350,11 +1450,11 @@ function getStableClickHandlerNameFromExpression(exp) {
|
|
|
1350
1450
|
return extractNameFromCallee(callee);
|
|
1351
1451
|
}
|
|
1352
1452
|
if (types.isAssignmentExpression(exp)) {
|
|
1353
|
-
const left = exp.left;
|
|
1354
|
-
if (
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1453
|
+
const left = getAssignmentTargetNameFromBabel(exp.left);
|
|
1454
|
+
if (left) {
|
|
1455
|
+
const right = getStableAssignmentValueSuffixFromBabel(exp.right);
|
|
1456
|
+
return `Set${toPascalCase(left)}${right}`;
|
|
1457
|
+
}
|
|
1358
1458
|
return "";
|
|
1359
1459
|
}
|
|
1360
1460
|
if (types.isOptionalMemberExpression(exp)) {
|
|
@@ -1429,6 +1529,71 @@ function extractMemberPropertyName(member) {
|
|
|
1429
1529
|
}
|
|
1430
1530
|
return "";
|
|
1431
1531
|
}
|
|
1532
|
+
function getLastIdentifierFromMemberChainBabel(node) {
|
|
1533
|
+
if (!node) {
|
|
1534
|
+
return "";
|
|
1535
|
+
}
|
|
1536
|
+
if (types.isIdentifier(node)) {
|
|
1537
|
+
return node.name;
|
|
1538
|
+
}
|
|
1539
|
+
if (types.isMemberExpression(node) || types.isOptionalMemberExpression(node)) {
|
|
1540
|
+
if (!node.computed) {
|
|
1541
|
+
if (types.isIdentifier(node.property)) {
|
|
1542
|
+
return node.property.name;
|
|
1543
|
+
}
|
|
1544
|
+
} else if (types.isStringLiteral(node.property)) {
|
|
1545
|
+
return node.property.value;
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
return "";
|
|
1549
|
+
}
|
|
1550
|
+
function getAssignmentTargetNameFromBabel(node) {
|
|
1551
|
+
if (!node) {
|
|
1552
|
+
return "";
|
|
1553
|
+
}
|
|
1554
|
+
if (types.isIdentifier(node)) {
|
|
1555
|
+
return node.name;
|
|
1556
|
+
}
|
|
1557
|
+
if (types.isMemberExpression(node) || types.isOptionalMemberExpression(node)) {
|
|
1558
|
+
if (!node.computed && types.isIdentifier(node.property) && node.property.name === "value") {
|
|
1559
|
+
return getLastIdentifierFromMemberChainBabel(node.object);
|
|
1560
|
+
}
|
|
1561
|
+
return getLastIdentifierFromMemberChainBabel(node);
|
|
1562
|
+
}
|
|
1563
|
+
return "";
|
|
1564
|
+
}
|
|
1565
|
+
function getStableAssignmentValueSuffixFromBabel(node) {
|
|
1566
|
+
if (!node) {
|
|
1567
|
+
return "";
|
|
1568
|
+
}
|
|
1569
|
+
if (types.isBooleanLiteral(node)) {
|
|
1570
|
+
return node.value ? "True" : "False";
|
|
1571
|
+
}
|
|
1572
|
+
if (types.isNumericLiteral(node)) {
|
|
1573
|
+
return `Value${String(node.value)}`;
|
|
1574
|
+
}
|
|
1575
|
+
if (types.isNullLiteral(node)) {
|
|
1576
|
+
return "Null";
|
|
1577
|
+
}
|
|
1578
|
+
if (types.isStringLiteral(node)) {
|
|
1579
|
+
const cleaned = (node.value ?? "").trim();
|
|
1580
|
+
return cleaned ? toPascalCase(cleaned.slice(0, 24)) : "";
|
|
1581
|
+
}
|
|
1582
|
+
if (types.isTemplateLiteral(node) && node.expressions.length === 0) {
|
|
1583
|
+
const value = node.quasis.map((q) => q.value?.cooked ?? "").join("").trim();
|
|
1584
|
+
return value ? toPascalCase(value.slice(0, 24)) : "";
|
|
1585
|
+
}
|
|
1586
|
+
if (types.isMemberExpression(node) || types.isOptionalMemberExpression(node)) {
|
|
1587
|
+
const name = getLastIdentifierFromMemberChainBabel(node);
|
|
1588
|
+
return name ? toPascalCase(name.slice(0, 24)) : "";
|
|
1589
|
+
}
|
|
1590
|
+
if (types.isIdentifier(node)) {
|
|
1591
|
+
const firstChar = node.name.charAt(0);
|
|
1592
|
+
const isUpperAlpha = firstChar !== "" && firstChar === firstChar.toUpperCase() && firstChar !== firstChar.toLowerCase();
|
|
1593
|
+
return isUpperAlpha ? toPascalCase(node.name.slice(0, 24)) : "";
|
|
1594
|
+
}
|
|
1595
|
+
return "";
|
|
1596
|
+
}
|
|
1432
1597
|
function isCompilerGeneratedReferenceRoot(name) {
|
|
1433
1598
|
return name.startsWith("_") || name.startsWith("$");
|
|
1434
1599
|
}
|
|
@@ -3240,6 +3405,10 @@ function escapeGitAttributesPattern(value) {
|
|
|
3240
3405
|
}
|
|
3241
3406
|
return output;
|
|
3242
3407
|
}
|
|
3408
|
+
function pathUsesGeneratedHeuristic(filePath) {
|
|
3409
|
+
const normalized = path.normalize(filePath);
|
|
3410
|
+
return normalized.split(path.sep).includes("__generated__");
|
|
3411
|
+
}
|
|
3243
3412
|
function buildManagedGitAttributesBlock(entries) {
|
|
3244
3413
|
return [
|
|
3245
3414
|
GENERATED_GITATTRIBUTES_BLOCK_START,
|
|
@@ -3287,6 +3456,9 @@ function buildGeneratedGitAttributesFiles(generatedFilePaths) {
|
|
|
3287
3456
|
if (path.basename(resolvedFilePath) === ".gitattributes") {
|
|
3288
3457
|
continue;
|
|
3289
3458
|
}
|
|
3459
|
+
if (pathUsesGeneratedHeuristic(resolvedFilePath)) {
|
|
3460
|
+
continue;
|
|
3461
|
+
}
|
|
3290
3462
|
const dir = path.dirname(resolvedFilePath);
|
|
3291
3463
|
const entry = `${escapeGitAttributesPattern(path.basename(resolvedFilePath))} linguist-generated`;
|
|
3292
3464
|
const entries = entriesByDir.get(dir) ?? /* @__PURE__ */ new Set();
|
|
@@ -4363,15 +4535,57 @@ function createBuildProcessorPlugin(options) {
|
|
|
4363
4535
|
const TESTID_CLICK_EVENT_NAME = "__testid_event__";
|
|
4364
4536
|
const TESTID_CLICK_EVENT_STRICT_FLAG = "__testid_click_event_strict__";
|
|
4365
4537
|
const CLICK_EVENT_NAME = TESTID_CLICK_EVENT_NAME;
|
|
4366
|
-
const
|
|
4367
|
-
const
|
|
4368
|
-
|
|
4538
|
+
const inferredNativeWrapperConfigByLookup = /* @__PURE__ */ new Map();
|
|
4539
|
+
const inferredSfcPathByLookup = /* @__PURE__ */ new Map();
|
|
4540
|
+
const indexedVueSfcPathsByRoots = /* @__PURE__ */ new Map();
|
|
4369
4541
|
function toKebabCaseTag(tag) {
|
|
4370
|
-
|
|
4542
|
+
let result = "";
|
|
4543
|
+
let previousWasSeparator = false;
|
|
4544
|
+
for (let i = 0; i < tag.length; i += 1) {
|
|
4545
|
+
const ch = tag[i];
|
|
4546
|
+
const code = ch.charCodeAt(0);
|
|
4547
|
+
if (ch === "_" || ch === "-" || ch === "." || ch === " " || ch === " " || ch === "\n" || ch === "\r") {
|
|
4548
|
+
if (result && !previousWasSeparator) {
|
|
4549
|
+
result += "-";
|
|
4550
|
+
}
|
|
4551
|
+
previousWasSeparator = true;
|
|
4552
|
+
continue;
|
|
4553
|
+
}
|
|
4554
|
+
const previous = i > 0 ? tag[i - 1] : "";
|
|
4555
|
+
const previousCode = previous ? previous.charCodeAt(0) : 0;
|
|
4556
|
+
const hasPrevious = i > 0;
|
|
4557
|
+
const shouldInsertSeparator = hasPrevious && isAsciiUppercaseLetterCode(code) && (isAsciiLetterCode(previousCode) || isAsciiDigitCode(previousCode)) && !previousWasSeparator;
|
|
4558
|
+
if (shouldInsertSeparator) {
|
|
4559
|
+
result += "-";
|
|
4560
|
+
}
|
|
4561
|
+
result += ch.toLowerCase();
|
|
4562
|
+
previousWasSeparator = false;
|
|
4563
|
+
}
|
|
4564
|
+
return result;
|
|
4371
4565
|
}
|
|
4372
|
-
function
|
|
4373
|
-
|
|
4374
|
-
|
|
4566
|
+
function normalizeSearchRoots(wrapperSearchRoots) {
|
|
4567
|
+
const normalized = /* @__PURE__ */ new Set();
|
|
4568
|
+
for (const root of wrapperSearchRoots) {
|
|
4569
|
+
const resolved = path.resolve(root);
|
|
4570
|
+
try {
|
|
4571
|
+
if (!fs.existsSync(resolved) || !fs.statSync(resolved).isDirectory()) {
|
|
4572
|
+
continue;
|
|
4573
|
+
}
|
|
4574
|
+
normalized.add(path.normalize(fs.realpathSync(resolved)));
|
|
4575
|
+
} catch {
|
|
4576
|
+
continue;
|
|
4577
|
+
}
|
|
4578
|
+
}
|
|
4579
|
+
return [...normalized];
|
|
4580
|
+
}
|
|
4581
|
+
function buildSearchRootsKey(searchRoots) {
|
|
4582
|
+
return searchRoots.join("\n");
|
|
4583
|
+
}
|
|
4584
|
+
function buildVueSfcPathIndex(searchRoots) {
|
|
4585
|
+
const indexKey = buildSearchRootsKey(searchRoots);
|
|
4586
|
+
const existingIndex = indexedVueSfcPathsByRoots.get(indexKey);
|
|
4587
|
+
if (existingIndex) {
|
|
4588
|
+
return existingIndex;
|
|
4375
4589
|
}
|
|
4376
4590
|
const index = /* @__PURE__ */ new Map();
|
|
4377
4591
|
const ignoredDirNames = /* @__PURE__ */ new Set([
|
|
@@ -4389,22 +4603,6 @@ function buildVueSfcPathIndex() {
|
|
|
4389
4603
|
"out",
|
|
4390
4604
|
"tmp"
|
|
4391
4605
|
]);
|
|
4392
|
-
const cwd = process.cwd();
|
|
4393
|
-
const parent = path.resolve(cwd, "..");
|
|
4394
|
-
const searchRoots = /* @__PURE__ */ new Set();
|
|
4395
|
-
const enqueueIfDirectory = (dirPath) => {
|
|
4396
|
-
try {
|
|
4397
|
-
if (fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory()) {
|
|
4398
|
-
searchRoots.add(dirPath);
|
|
4399
|
-
}
|
|
4400
|
-
} catch {
|
|
4401
|
-
}
|
|
4402
|
-
};
|
|
4403
|
-
for (const root of [cwd, parent]) {
|
|
4404
|
-
for (const rel of ["src", "components", "app", "shared", "packages", "libs"]) {
|
|
4405
|
-
enqueueIfDirectory(path.resolve(root, rel));
|
|
4406
|
-
}
|
|
4407
|
-
}
|
|
4408
4606
|
const stack = [...searchRoots];
|
|
4409
4607
|
const seenDirs = /* @__PURE__ */ new Set();
|
|
4410
4608
|
while (stack.length > 0) {
|
|
@@ -4437,52 +4635,58 @@ function buildVueSfcPathIndex() {
|
|
|
4437
4635
|
index.set(entry.name, matches);
|
|
4438
4636
|
}
|
|
4439
4637
|
}
|
|
4440
|
-
|
|
4638
|
+
indexedVueSfcPathsByRoots.set(indexKey, index);
|
|
4441
4639
|
return index;
|
|
4442
4640
|
}
|
|
4443
|
-
function tryResolveSfcPathForTag(tag, vueFilesPathMap) {
|
|
4444
|
-
if (inferredSfcPathByTag.has(tag)) {
|
|
4445
|
-
return inferredSfcPathByTag.get(tag) ?? null;
|
|
4446
|
-
}
|
|
4641
|
+
function tryResolveSfcPathForTag(tag, vueFilesPathMap, wrapperSearchRoots = []) {
|
|
4447
4642
|
const registeredPath = vueFilesPathMap?.get(tag);
|
|
4643
|
+
const normalizedSearchRoots = normalizeSearchRoots(wrapperSearchRoots);
|
|
4644
|
+
const lookupKey = `${tag}
|
|
4645
|
+
${registeredPath ?? ""}
|
|
4646
|
+
${buildSearchRootsKey(normalizedSearchRoots)}`;
|
|
4647
|
+
if (inferredSfcPathByLookup.has(lookupKey)) {
|
|
4648
|
+
return inferredSfcPathByLookup.get(lookupKey) ?? null;
|
|
4649
|
+
}
|
|
4448
4650
|
const candidateNames = [`${tag}.vue`, `${toKebabCaseTag(tag)}.vue`];
|
|
4449
4651
|
const directCandidates = [
|
|
4450
4652
|
registeredPath ? path.resolve(process.cwd(), registeredPath) : null,
|
|
4451
|
-
...
|
|
4452
|
-
path.resolve(process.cwd(), "src/components", fileName),
|
|
4453
|
-
path.resolve(process.cwd(), "components", fileName),
|
|
4454
|
-
path.resolve(process.cwd(), "app/components", fileName),
|
|
4455
|
-
path.resolve(process.cwd(), "shared/ui/src/components", fileName),
|
|
4456
|
-
path.resolve(process.cwd(), "..", "shared/ui/src/components", fileName)
|
|
4457
|
-
])
|
|
4653
|
+
...normalizedSearchRoots.flatMap((root) => candidateNames.map((fileName) => path.join(root, fileName)))
|
|
4458
4654
|
].filter((value) => !!value);
|
|
4459
4655
|
const directMatch = directCandidates.find((candidatePath) => fs.existsSync(candidatePath));
|
|
4460
4656
|
if (directMatch) {
|
|
4461
|
-
|
|
4657
|
+
inferredSfcPathByLookup.set(lookupKey, directMatch);
|
|
4462
4658
|
return directMatch;
|
|
4463
4659
|
}
|
|
4464
|
-
|
|
4660
|
+
if (normalizedSearchRoots.length === 0) {
|
|
4661
|
+
inferredSfcPathByLookup.set(lookupKey, null);
|
|
4662
|
+
return null;
|
|
4663
|
+
}
|
|
4664
|
+
const index = buildVueSfcPathIndex(normalizedSearchRoots);
|
|
4465
4665
|
const scorePath = (candidatePath) => {
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
}
|
|
4473
|
-
return score;
|
|
4666
|
+
const rootIndex = normalizedSearchRoots.findIndex((root) => {
|
|
4667
|
+
return candidatePath === root || candidatePath.startsWith(root + path.sep);
|
|
4668
|
+
});
|
|
4669
|
+
const effectiveRootIndex = rootIndex === -1 ? Number.MAX_SAFE_INTEGER : rootIndex;
|
|
4670
|
+
const relativeLength = rootIndex === -1 ? candidatePath.length : path.relative(normalizedSearchRoots[rootIndex], candidatePath).length;
|
|
4671
|
+
return [effectiveRootIndex, relativeLength, candidatePath];
|
|
4474
4672
|
};
|
|
4673
|
+
let bestMatch = null;
|
|
4674
|
+
let bestScore = null;
|
|
4475
4675
|
for (const fileName of candidateNames) {
|
|
4476
4676
|
const matches = index.get(fileName);
|
|
4477
4677
|
if (!matches?.length) {
|
|
4478
4678
|
continue;
|
|
4479
4679
|
}
|
|
4480
|
-
const
|
|
4481
|
-
|
|
4482
|
-
|
|
4680
|
+
for (const match of matches) {
|
|
4681
|
+
const score = scorePath(match);
|
|
4682
|
+
if (!bestScore || score[0] < bestScore[0] || score[0] === bestScore[0] && score[1] < bestScore[1] || score[0] === bestScore[0] && score[1] === bestScore[1] && score[2] < bestScore[2]) {
|
|
4683
|
+
bestScore = score;
|
|
4684
|
+
bestMatch = match;
|
|
4685
|
+
}
|
|
4686
|
+
}
|
|
4483
4687
|
}
|
|
4484
|
-
|
|
4485
|
-
return
|
|
4688
|
+
inferredSfcPathByLookup.set(lookupKey, bestMatch);
|
|
4689
|
+
return bestMatch;
|
|
4486
4690
|
}
|
|
4487
4691
|
function trimLeadingSeparators(value) {
|
|
4488
4692
|
if (!value) {
|
|
@@ -4597,7 +4801,7 @@ function tryExtractStableHintFromConditionalExpressionSource(source) {
|
|
|
4597
4801
|
return null;
|
|
4598
4802
|
}
|
|
4599
4803
|
}
|
|
4600
|
-
function tryInferNativeWrapperRoleFromSfc(tag, vueFilesPathMap, seenTags = /* @__PURE__ */ new Set()) {
|
|
4804
|
+
function tryInferNativeWrapperRoleFromSfc(tag, vueFilesPathMap, wrapperSearchRoots = [], seenTags = /* @__PURE__ */ new Set()) {
|
|
4601
4805
|
const first = tag.charCodeAt(0);
|
|
4602
4806
|
const isUpper = isAsciiUppercaseLetterCode(first);
|
|
4603
4807
|
if (!isUpper)
|
|
@@ -4605,19 +4809,23 @@ function tryInferNativeWrapperRoleFromSfc(tag, vueFilesPathMap, seenTags = /* @_
|
|
|
4605
4809
|
if (seenTags.has(tag)) {
|
|
4606
4810
|
return null;
|
|
4607
4811
|
}
|
|
4608
|
-
const
|
|
4812
|
+
const normalizedSearchRoots = normalizeSearchRoots(wrapperSearchRoots);
|
|
4813
|
+
const cacheKey = `${tag}
|
|
4814
|
+
${vueFilesPathMap?.get(tag) ?? ""}
|
|
4815
|
+
${buildSearchRootsKey(normalizedSearchRoots)}`;
|
|
4816
|
+
const cached = inferredNativeWrapperConfigByLookup.get(cacheKey);
|
|
4609
4817
|
if (cached)
|
|
4610
4818
|
return cached.role ? cached : null;
|
|
4611
|
-
const filePath = tryResolveSfcPathForTag(tag, vueFilesPathMap);
|
|
4819
|
+
const filePath = tryResolveSfcPathForTag(tag, vueFilesPathMap, normalizedSearchRoots);
|
|
4612
4820
|
if (!filePath) {
|
|
4613
|
-
|
|
4821
|
+
inferredNativeWrapperConfigByLookup.set(cacheKey, { role: "" });
|
|
4614
4822
|
return null;
|
|
4615
4823
|
}
|
|
4616
4824
|
let source = "";
|
|
4617
4825
|
try {
|
|
4618
4826
|
source = fs.readFileSync(filePath, "utf8");
|
|
4619
4827
|
} catch {
|
|
4620
|
-
|
|
4828
|
+
inferredNativeWrapperConfigByLookup.set(cacheKey, { role: "" });
|
|
4621
4829
|
return null;
|
|
4622
4830
|
}
|
|
4623
4831
|
let template = "";
|
|
@@ -4625,11 +4833,11 @@ function tryInferNativeWrapperRoleFromSfc(tag, vueFilesPathMap, seenTags = /* @_
|
|
|
4625
4833
|
const { descriptor } = compilerSfc.parse(source, { filename: filePath });
|
|
4626
4834
|
template = descriptor.template?.content ?? "";
|
|
4627
4835
|
} catch {
|
|
4628
|
-
|
|
4836
|
+
inferredNativeWrapperConfigByLookup.set(cacheKey, { role: "" });
|
|
4629
4837
|
return null;
|
|
4630
4838
|
}
|
|
4631
4839
|
if (!template.trim()) {
|
|
4632
|
-
|
|
4840
|
+
inferredNativeWrapperConfigByLookup.set(cacheKey, { role: "" });
|
|
4633
4841
|
return null;
|
|
4634
4842
|
}
|
|
4635
4843
|
try {
|
|
@@ -4648,6 +4856,7 @@ function tryInferNativeWrapperRoleFromSfc(tag, vueFilesPathMap, seenTags = /* @_
|
|
|
4648
4856
|
});
|
|
4649
4857
|
return (typeAttr?.value?.content ?? "").toLowerCase();
|
|
4650
4858
|
};
|
|
4859
|
+
let inferRoleFromNode;
|
|
4651
4860
|
const inferRoleFromElement = (element) => {
|
|
4652
4861
|
const elementTag = (element.tag || "").toLowerCase();
|
|
4653
4862
|
const inputType = getStaticTypeAttribute(element);
|
|
@@ -4667,7 +4876,7 @@ function tryInferNativeWrapperRoleFromSfc(tag, vueFilesPathMap, seenTags = /* @_
|
|
|
4667
4876
|
if (elementTag === "button" || elementTag === "ubutton")
|
|
4668
4877
|
return { role: "button" };
|
|
4669
4878
|
if (isComponentLikeTag(element.tag) && element.tag !== tag) {
|
|
4670
|
-
const nested = tryInferNativeWrapperRoleFromSfc(element.tag, vueFilesPathMap, nextSeen);
|
|
4879
|
+
const nested = tryInferNativeWrapperRoleFromSfc(element.tag, vueFilesPathMap, normalizedSearchRoots, nextSeen);
|
|
4671
4880
|
if (nested)
|
|
4672
4881
|
return nested;
|
|
4673
4882
|
}
|
|
@@ -4678,7 +4887,7 @@ function tryInferNativeWrapperRoleFromSfc(tag, vueFilesPathMap, seenTags = /* @_
|
|
|
4678
4887
|
}
|
|
4679
4888
|
return null;
|
|
4680
4889
|
};
|
|
4681
|
-
|
|
4890
|
+
inferRoleFromNode = (node) => {
|
|
4682
4891
|
if (!node || typeof node !== "object")
|
|
4683
4892
|
return null;
|
|
4684
4893
|
if (node.type === compilerCore.NodeTypes.ELEMENT) {
|
|
@@ -4703,14 +4912,14 @@ function tryInferNativeWrapperRoleFromSfc(tag, vueFilesPathMap, seenTags = /* @_
|
|
|
4703
4912
|
};
|
|
4704
4913
|
const inferred = inferRoleFromNode(ast);
|
|
4705
4914
|
if (inferred) {
|
|
4706
|
-
|
|
4915
|
+
inferredNativeWrapperConfigByLookup.set(cacheKey, inferred);
|
|
4707
4916
|
return inferred;
|
|
4708
4917
|
}
|
|
4709
4918
|
} catch {
|
|
4710
|
-
|
|
4919
|
+
inferredNativeWrapperConfigByLookup.set(cacheKey, { role: "" });
|
|
4711
4920
|
return null;
|
|
4712
4921
|
}
|
|
4713
|
-
|
|
4922
|
+
inferredNativeWrapperConfigByLookup.set(cacheKey, { role: "" });
|
|
4714
4923
|
return null;
|
|
4715
4924
|
}
|
|
4716
4925
|
function tryWrapClickDirectiveForTestEvents(element, testIdAttribute) {
|
|
@@ -4885,6 +5094,7 @@ function createTestIdTransform(componentName, componentHierarchyMap, nativeWrapp
|
|
|
4885
5094
|
const nameCollisionBehavior = options.nameCollisionBehavior ?? "suffix";
|
|
4886
5095
|
const warn = options.warn;
|
|
4887
5096
|
const vueFilesPathMap = options.vueFilesPathMap;
|
|
5097
|
+
const wrapperSearchRoots = options.wrapperSearchRoots ?? [];
|
|
4888
5098
|
const safeRealpath = (p) => {
|
|
4889
5099
|
try {
|
|
4890
5100
|
return fs.existsSync(p) ? fs.realpathSync(p) : p;
|
|
@@ -5010,7 +5220,7 @@ function createTestIdTransform(componentName, componentHierarchyMap, nativeWrapp
|
|
|
5010
5220
|
dependencies.usedComponentSet.add(element.tag);
|
|
5011
5221
|
}
|
|
5012
5222
|
if (!nativeWrappers[element.tag]) {
|
|
5013
|
-
const inferred = tryInferNativeWrapperRoleFromSfc(element.tag, vueFilesPathMap);
|
|
5223
|
+
const inferred = tryInferNativeWrapperRoleFromSfc(element.tag, vueFilesPathMap, wrapperSearchRoots);
|
|
5014
5224
|
if (inferred?.role) {
|
|
5015
5225
|
nativeWrappers[element.tag] = { role: inferred.role, inferred: true };
|
|
5016
5226
|
} else if (element.tag.endsWith("Button") || element.tag === "AylaButton") {
|
|
@@ -5301,6 +5511,7 @@ function createDevProcessorPlugin(options) {
|
|
|
5301
5511
|
excludedComponents,
|
|
5302
5512
|
viewsDir,
|
|
5303
5513
|
scanDirs,
|
|
5514
|
+
getWrapperSearchRoots,
|
|
5304
5515
|
projectRootRef,
|
|
5305
5516
|
normalizedBasePagePath,
|
|
5306
5517
|
basePageClassPath,
|
|
@@ -5451,7 +5662,11 @@ function createDevProcessorPlugin(options) {
|
|
|
5451
5662
|
nativeWrappers,
|
|
5452
5663
|
excludedComponents,
|
|
5453
5664
|
getViewsDirAbs(),
|
|
5454
|
-
{
|
|
5665
|
+
{
|
|
5666
|
+
existingIdBehavior: "preserve",
|
|
5667
|
+
testIdAttribute,
|
|
5668
|
+
wrapperSearchRoots: getWrapperSearchRoots()
|
|
5669
|
+
}
|
|
5455
5670
|
)
|
|
5456
5671
|
]
|
|
5457
5672
|
});
|
|
@@ -5676,6 +5891,7 @@ function createSupportPlugins(options) {
|
|
|
5676
5891
|
excludedComponents,
|
|
5677
5892
|
viewsDir,
|
|
5678
5893
|
scanDirs,
|
|
5894
|
+
getWrapperSearchRoots,
|
|
5679
5895
|
outDir,
|
|
5680
5896
|
emitLanguages,
|
|
5681
5897
|
csharp,
|
|
@@ -5738,6 +5954,7 @@ function createSupportPlugins(options) {
|
|
|
5738
5954
|
excludedComponents,
|
|
5739
5955
|
viewsDir,
|
|
5740
5956
|
scanDirs,
|
|
5957
|
+
getWrapperSearchRoots,
|
|
5741
5958
|
projectRootRef,
|
|
5742
5959
|
normalizedBasePagePath,
|
|
5743
5960
|
basePageClassPath,
|
|
@@ -5910,6 +6127,7 @@ function createVuePluginWithTestIds(options) {
|
|
|
5910
6127
|
testIdAttribute,
|
|
5911
6128
|
loggerRef,
|
|
5912
6129
|
scanDirs = ["src"],
|
|
6130
|
+
getWrapperSearchRoots,
|
|
5913
6131
|
getProjectRoot
|
|
5914
6132
|
} = options;
|
|
5915
6133
|
const getComponentNameFromPath = (filename) => {
|
|
@@ -5978,7 +6196,8 @@ function createVuePluginWithTestIds(options) {
|
|
|
5978
6196
|
testIdAttribute,
|
|
5979
6197
|
nameCollisionBehavior,
|
|
5980
6198
|
warn: (message) => loggerRef.current.warn(message),
|
|
5981
|
-
vueFilesPathMap
|
|
6199
|
+
vueFilesPathMap,
|
|
6200
|
+
wrapperSearchRoots: getWrapperSearchRoots()
|
|
5982
6201
|
}
|
|
5983
6202
|
)
|
|
5984
6203
|
);
|
|
@@ -6007,7 +6226,8 @@ function createVuePluginWithTestIds(options) {
|
|
|
6007
6226
|
testIdAttribute,
|
|
6008
6227
|
nameCollisionBehavior,
|
|
6009
6228
|
warn: (message) => loggerRef.current.warn(message),
|
|
6010
|
-
vueFilesPathMap
|
|
6229
|
+
vueFilesPathMap,
|
|
6230
|
+
wrapperSearchRoots: getWrapperSearchRoots()
|
|
6011
6231
|
}
|
|
6012
6232
|
);
|
|
6013
6233
|
perFileTransform.set(componentName, transform);
|
|
@@ -6075,6 +6295,13 @@ function assertNonEmptyString(value, name) {
|
|
|
6075
6295
|
throw new Error(`${name} must be a non-empty string.`);
|
|
6076
6296
|
}
|
|
6077
6297
|
}
|
|
6298
|
+
function assertNonEmptyStringArray(value, name) {
|
|
6299
|
+
if (!value)
|
|
6300
|
+
return;
|
|
6301
|
+
for (const [index, entry] of value.entries()) {
|
|
6302
|
+
assertNonEmptyString(entry, `${name}[${index}]`);
|
|
6303
|
+
}
|
|
6304
|
+
}
|
|
6078
6305
|
function assertRouterModuleShims(value, name) {
|
|
6079
6306
|
if (!value)
|
|
6080
6307
|
return;
|
|
@@ -6137,11 +6364,12 @@ function createVuePomGeneratorPlugins(options = {}) {
|
|
|
6137
6364
|
const vueOptions = options.vueOptions;
|
|
6138
6365
|
const viewsDir = injection.viewsDir ?? "src/views";
|
|
6139
6366
|
const scanDirs = injection.scanDirs ?? ["src"];
|
|
6367
|
+
const wrapperSearchRoots = injection.wrapperSearchRoots ?? [];
|
|
6140
6368
|
const nativeWrappers = injection.nativeWrappers ?? {};
|
|
6141
6369
|
const excludedComponents = injection.excludeComponents ?? [];
|
|
6142
6370
|
const testIdAttribute = (injection.attribute ?? "data-testid").trim() || "data-testid";
|
|
6143
6371
|
const existingIdBehavior = injection.existingIdBehavior ?? "preserve";
|
|
6144
|
-
const outDir = (generationOptions?.outDir ?? "tests/playwright/
|
|
6372
|
+
const outDir = (generationOptions?.outDir ?? "tests/playwright/__generated__").trim();
|
|
6145
6373
|
const emitLanguages = generationOptions?.emit && generationOptions.emit.length ? generationOptions.emit : ["ts"];
|
|
6146
6374
|
const nameCollisionBehavior = generationOptions?.nameCollisionBehavior ?? "suffix";
|
|
6147
6375
|
const routerEntry = generationOptions?.router?.entry;
|
|
@@ -6167,6 +6395,7 @@ function createVuePomGeneratorPlugins(options = {}) {
|
|
|
6167
6395
|
loggerRef.current = createLogger({ verbosity, viteLogger: config.logger });
|
|
6168
6396
|
assertNonEmptyString(testIdAttribute, "[vue-pom-generator] injection.attribute");
|
|
6169
6397
|
assertNonEmptyString(viewsDir, "[vue-pom-generator] injection.viewsDir");
|
|
6398
|
+
assertNonEmptyStringArray(wrapperSearchRoots, "[vue-pom-generator] injection.wrapperSearchRoots");
|
|
6170
6399
|
if (generationEnabled) {
|
|
6171
6400
|
assertNonEmptyString(outDir, "[vue-pom-generator] generation.outDir");
|
|
6172
6401
|
assertRouterModuleShims(routerModuleShims, "[vue-pom-generator] generation.router.moduleShims");
|
|
@@ -6179,6 +6408,7 @@ function createVuePomGeneratorPlugins(options = {}) {
|
|
|
6179
6408
|
}
|
|
6180
6409
|
};
|
|
6181
6410
|
const getViewsDirAbs = () => resolveFromProjectRoot(projectRootRef.current, viewsDir);
|
|
6411
|
+
const getWrapperSearchRootsAbs = () => wrapperSearchRoots.map((root) => resolveFromProjectRoot(projectRootRef.current, root));
|
|
6182
6412
|
const componentTestIds = /* @__PURE__ */ new Map();
|
|
6183
6413
|
const elementMetadata = /* @__PURE__ */ new Map();
|
|
6184
6414
|
const semanticNameMap = /* @__PURE__ */ new Map();
|
|
@@ -6198,6 +6428,7 @@ function createVuePomGeneratorPlugins(options = {}) {
|
|
|
6198
6428
|
testIdAttribute,
|
|
6199
6429
|
loggerRef,
|
|
6200
6430
|
scanDirs,
|
|
6431
|
+
getWrapperSearchRoots: getWrapperSearchRootsAbs,
|
|
6201
6432
|
getProjectRoot: () => projectRootRef.current
|
|
6202
6433
|
});
|
|
6203
6434
|
const routerAwarePoms = typeof routerEntry === "string" && routerEntry.trim().length > 0 || routerType === "nuxt";
|
|
@@ -6209,6 +6440,7 @@ function createVuePomGeneratorPlugins(options = {}) {
|
|
|
6209
6440
|
excludedComponents,
|
|
6210
6441
|
viewsDir,
|
|
6211
6442
|
scanDirs,
|
|
6443
|
+
getWrapperSearchRoots: getWrapperSearchRootsAbs,
|
|
6212
6444
|
outDir,
|
|
6213
6445
|
emitLanguages,
|
|
6214
6446
|
csharp,
|