@immense/vue-pom-generator 1.0.33 → 1.0.35
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 +13 -28
- package/class-generation/index.ts +29 -4
- package/dist/class-generation/index.d.ts +2 -0
- package/dist/class-generation/index.d.ts.map +1 -1
- package/dist/index.cjs +189 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +189 -57
- package/dist/index.mjs.map +1 -1
- package/dist/plugin/path-utils.d.ts.map +1 -1
- package/dist/plugin/support/build-plugin.d.ts +2 -0
- package/dist/plugin/support/build-plugin.d.ts.map +1 -1
- package/dist/plugin/support/dev-plugin.d.ts.map +1 -1
- package/dist/plugin/support-plugins.d.ts.map +1 -1
- package/dist/router-introspection.d.ts +10 -0
- package/dist/router-introspection.d.ts.map +1 -1
- package/dist/transform.d.ts.map +1 -1
- package/package.json +1 -1
package/RELEASE_NOTES.md
CHANGED
|
@@ -1,43 +1,28 @@
|
|
|
1
|
-
● # Release Notes: v1.0.
|
|
1
|
+
● # Release Notes: v1.0.35
|
|
2
2
|
|
|
3
3
|
## Highlights
|
|
4
|
-
|
|
5
|
-
-
|
|
6
|
-
-
|
|
7
|
-
transform operations
|
|
8
|
-
- Introduced new `generation-metrics.ts` module for tracking and reporting code generation
|
|
9
|
-
statistics
|
|
10
|
-
- Expanded transform logic with 192 additional lines of processing logic
|
|
11
|
-
- Enhanced plugin architecture with improved metric collection in dev and build modes
|
|
4
|
+
- Fixed wrapper collision fallbacks in transform logic
|
|
5
|
+
- Added comprehensive test coverage for wrapper collision scenarios
|
|
6
|
+
- Improved PR workflow with release-notes preview comments
|
|
12
7
|
|
|
13
8
|
## Changes
|
|
14
9
|
|
|
15
|
-
|
|
16
|
-
-
|
|
17
|
-
- Expanded `transform.ts` with enhanced processing capabilities
|
|
10
|
+
### Bug Fixes
|
|
11
|
+
- Resolved issues with wrapper collision fallback behavior in transform module
|
|
18
12
|
|
|
19
|
-
|
|
20
|
-
- Added
|
|
21
|
-
- Updated `plugin/vue-plugin.ts` with enhanced metrics collection (85 lines modified)
|
|
22
|
-
- Improved diagnostic output in `plugin/support/dev-plugin.ts` and
|
|
23
|
-
`plugin/support/build-plugin.ts`
|
|
13
|
+
### Testing
|
|
14
|
+
- Added 41 lines of new tests for wrapper collision scenarios in `transform.test.ts`
|
|
24
15
|
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
-
- Expanded `tests/transform.test.ts` with 131 additional test cases
|
|
28
|
-
- Enhanced `tests/options.test.ts` with 72 new test cases
|
|
16
|
+
### Developer Experience
|
|
17
|
+
- Integrated automated release-notes preview comments on pull requests
|
|
29
18
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
- Minor utility adjustments in `utils.ts`
|
|
19
|
+
## Breaking Changes
|
|
20
|
+
None
|
|
33
21
|
|
|
34
22
|
## Pull Requests Included
|
|
35
|
-
|
|
36
23
|
- #1 Add PR release-notes preview comments (https://github.com/immense/vue-pom-generator/pull/1)
|
|
37
24
|
by @dkattan
|
|
38
25
|
|
|
39
26
|
## Testing
|
|
40
|
-
|
|
41
|
-
Added 250+ new test cases across generation metrics, transform logic, and options handling. All
|
|
42
|
-
tests passing.
|
|
27
|
+
New test cases added to validate wrapper collision fallback fixes. All tests passing.
|
|
43
28
|
|
|
@@ -66,12 +66,27 @@ async function getRouteMetaByComponent(
|
|
|
66
66
|
projectRoot?: string,
|
|
67
67
|
routerEntry?: string,
|
|
68
68
|
routerType?: "vue-router" | "nuxt",
|
|
69
|
+
options: {
|
|
70
|
+
viewsDir?: string;
|
|
71
|
+
scanDirs?: string[];
|
|
72
|
+
} = {},
|
|
69
73
|
): Promise<Record<string, RouteMeta>> {
|
|
70
74
|
const root = projectRoot ?? process.cwd();
|
|
75
|
+
const viewsDir = options.viewsDir ?? "src/views";
|
|
76
|
+
const viewsDirAbs = path.isAbsolute(viewsDir) ? viewsDir : path.resolve(root, viewsDir);
|
|
77
|
+
const scanDirs = options.scanDirs?.length ? options.scanDirs : ["src"];
|
|
78
|
+
const extraRoots = process.cwd() !== root ? [process.cwd()] : [];
|
|
71
79
|
|
|
72
80
|
const { routeMetaEntries } = routerType === "nuxt"
|
|
73
81
|
? await introspectNuxtPages(root)
|
|
74
|
-
: await parseRouterFileFromCwd(resolveRouterEntry(root, routerEntry)
|
|
82
|
+
: await parseRouterFileFromCwd(resolveRouterEntry(root, routerEntry), {
|
|
83
|
+
componentNaming: {
|
|
84
|
+
projectRoot: root,
|
|
85
|
+
viewsDirAbs,
|
|
86
|
+
scanDirs,
|
|
87
|
+
extraRoots,
|
|
88
|
+
},
|
|
89
|
+
});
|
|
75
90
|
|
|
76
91
|
const map = new Map<string, RouteMeta[]>();
|
|
77
92
|
for (const entry of routeMetaEntries) {
|
|
@@ -382,6 +397,9 @@ export interface GenerateFilesOptions {
|
|
|
382
397
|
/** The type of router introspection to perform. */
|
|
383
398
|
routerType?: "vue-router" | "nuxt";
|
|
384
399
|
|
|
400
|
+
viewsDir?: string;
|
|
401
|
+
scanDirs?: string[];
|
|
402
|
+
|
|
385
403
|
routeMetaByComponent?: Record<string, RouteMeta>;
|
|
386
404
|
}
|
|
387
405
|
|
|
@@ -443,6 +461,9 @@ export async function generateFiles(
|
|
|
443
461
|
vueRouterFluentChaining,
|
|
444
462
|
routerEntry,
|
|
445
463
|
routerType,
|
|
464
|
+
viewsDir,
|
|
465
|
+
scanDirs,
|
|
466
|
+
routeMetaByComponent: routeMetaByComponentOverride,
|
|
446
467
|
} = options;
|
|
447
468
|
|
|
448
469
|
const emitLanguages: Array<"ts" | "csharp"> = emitLanguagesOverride?.length
|
|
@@ -451,9 +472,13 @@ export async function generateFiles(
|
|
|
451
472
|
|
|
452
473
|
const outDir = outDirOverride ?? "./pom";
|
|
453
474
|
|
|
454
|
-
const routeMetaByComponent =
|
|
455
|
-
|
|
456
|
-
|
|
475
|
+
const routeMetaByComponent = routeMetaByComponentOverride
|
|
476
|
+
?? (vueRouterFluentChaining
|
|
477
|
+
? await getRouteMetaByComponent(projectRoot, routerEntry, routerType, {
|
|
478
|
+
viewsDir,
|
|
479
|
+
scanDirs,
|
|
480
|
+
})
|
|
481
|
+
: undefined);
|
|
457
482
|
const generatedFilePaths: string[] = [];
|
|
458
483
|
const writeGeneratedFile = (file: GeneratedFileOutput) => {
|
|
459
484
|
const resolvedFilePath = path.resolve(file.filePath);
|
|
@@ -81,6 +81,8 @@ export interface GenerateFilesOptions {
|
|
|
81
81
|
routerEntry?: string;
|
|
82
82
|
/** The type of router introspection to perform. */
|
|
83
83
|
routerType?: "vue-router" | "nuxt";
|
|
84
|
+
viewsDir?: string;
|
|
85
|
+
scanDirs?: string[];
|
|
84
86
|
routeMetaByComponent?: Record<string, RouteMeta>;
|
|
85
87
|
}
|
|
86
88
|
export declare function generateFiles(componentHierarchyMap: Map<string, IComponentDependencies>, vueFilesPathMap: Map<string, string>, basePageClassPath: string, options?: GenerateFilesOptions): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../class-generation/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,oCAAoC,EAAE,MAAM,sBAAsB,CAAC;AAE5E,OAAO,EAAE,sBAAsB,EAAoE,MAAM,UAAU,CAAC;AAQpH,OAAO,EAAE,oCAAoC,EAAE,CAAC;AA8ChD,UAAU,SAAS;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../class-generation/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,oCAAoC,EAAE,MAAM,sBAAsB,CAAC;AAE5E,OAAO,EAAE,sBAAsB,EAAoE,MAAM,UAAU,CAAC;AAQpH,OAAO,EAAE,oCAAoC,EAAE,CAAC;AA8ChD,UAAU,SAAS;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAwPD,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAE1D;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;;;OAOG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEhD;;;;;OAKG;IACH,oCAAoC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAEzD;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,KAAK,CAAC;QAC3B,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,wBAAwB,EAAE,MAAM,EAAE,CAAC;QAEnC;;;WAGG;QACH,QAAQ,CAAC,EAAE,OAAO,GAAG,YAAY,GAAG,MAAM,CAAC;KAC5C,CAAC,CAAC;IAEH,yEAAyE;IACzE,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,uDAAuD;IACvD,aAAa,CAAC,EAAE,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC;IAEvC,6BAA6B;IAC7B,MAAM,CAAC,EAAE;QACP,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IAEF,6EAA6E;IAC7E,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAElC,2FAA2F;IAC3F,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,mDAAmD;IACnD,UAAU,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IAEnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CAClD;AAwCD,wBAAsB,aAAa,CACjC,qBAAqB,EAAE,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,EAC1D,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,iBAAiB,EAAE,MAAM,EACzB,OAAO,GAAE,oBAAyB,iBAkFnC"}
|
package/dist/index.cjs
CHANGED
|
@@ -2569,6 +2569,53 @@ Fix: make the element identifiable (e.g. add id/name/inner text or use a more sp
|
|
|
2569
2569
|
registerGeneratedMethodSignature(generatedName, signature);
|
|
2570
2570
|
}
|
|
2571
2571
|
}
|
|
2572
|
+
function safeRealpath(value) {
|
|
2573
|
+
try {
|
|
2574
|
+
if (fs.existsSync(value)) {
|
|
2575
|
+
return fs.realpathSync(value);
|
|
2576
|
+
}
|
|
2577
|
+
} catch {
|
|
2578
|
+
return value;
|
|
2579
|
+
}
|
|
2580
|
+
const parent = path.dirname(value);
|
|
2581
|
+
if (!parent || parent === value) {
|
|
2582
|
+
return value;
|
|
2583
|
+
}
|
|
2584
|
+
const resolvedParent = safeRealpath(parent);
|
|
2585
|
+
return resolvedParent === parent ? value : path.join(resolvedParent, path.basename(value));
|
|
2586
|
+
}
|
|
2587
|
+
function resolveComponentNameFromPath(options) {
|
|
2588
|
+
const { projectRoot, viewsDirAbs, scanDirs, extraRoots = [] } = options;
|
|
2589
|
+
const cleanFilename = options.filename.includes("?") ? options.filename.substring(0, options.filename.indexOf("?")) : options.filename;
|
|
2590
|
+
const absFilename = path.isAbsolute(cleanFilename) ? cleanFilename : path.resolve(projectRoot, cleanFilename);
|
|
2591
|
+
const normalizedAbsFilename = path.normalize(safeRealpath(absFilename));
|
|
2592
|
+
const rootBases = [projectRoot, ...extraRoots.filter((r) => r !== projectRoot)];
|
|
2593
|
+
const roots = [viewsDirAbs, ...rootBases.flatMap((base) => scanDirs.map((d) => path.resolve(base, d)))];
|
|
2594
|
+
for (const base of rootBases) {
|
|
2595
|
+
for (const dir of scanDirs) {
|
|
2596
|
+
const absDir = path.resolve(base, dir);
|
|
2597
|
+
try {
|
|
2598
|
+
const pagesDir = path.join(absDir, "pages");
|
|
2599
|
+
if (fs.existsSync(pagesDir))
|
|
2600
|
+
roots.push(pagesDir);
|
|
2601
|
+
const componentsDir = path.join(absDir, "components");
|
|
2602
|
+
if (fs.existsSync(componentsDir))
|
|
2603
|
+
roots.push(componentsDir);
|
|
2604
|
+
} catch {
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
const potentialRoots = Array.from(new Set(roots.map((r) => path.normalize(safeRealpath(r))))).sort((a, b) => b.length - a.length);
|
|
2609
|
+
for (const root of potentialRoots) {
|
|
2610
|
+
if (normalizedAbsFilename.startsWith(root + path.sep) || normalizedAbsFilename === root) {
|
|
2611
|
+
const rel = path.relative(root, normalizedAbsFilename);
|
|
2612
|
+
const parsed = path.parse(rel);
|
|
2613
|
+
const segments = path.join(parsed.dir, parsed.name);
|
|
2614
|
+
return toPascalCase(segments);
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
return toPascalCase(path.parse(normalizedAbsFilename).name);
|
|
2618
|
+
}
|
|
2572
2619
|
let routerIntrospectionQueue = Promise.resolve();
|
|
2573
2620
|
async function runRouterIntrospectionExclusive(fn) {
|
|
2574
2621
|
const prev = routerIntrospectionQueue.catch(() => void 0);
|
|
@@ -2848,20 +2895,84 @@ function getRouteParamMeta(router, record, paramNames) {
|
|
|
2848
2895
|
}
|
|
2849
2896
|
});
|
|
2850
2897
|
}
|
|
2851
|
-
function
|
|
2852
|
-
const
|
|
2853
|
-
|
|
2898
|
+
function normalizeRouteComponentFilePath(filePath, options = {}) {
|
|
2899
|
+
const queryIndex = filePath.indexOf("?");
|
|
2900
|
+
const cleanPath = queryIndex === -1 ? filePath : filePath.slice(0, queryIndex);
|
|
2901
|
+
if (cleanPath.startsWith("/@fs/")) {
|
|
2902
|
+
return path.normalize(cleanPath.slice("/@fs/".length));
|
|
2903
|
+
}
|
|
2904
|
+
if (path.isAbsolute(cleanPath)) {
|
|
2905
|
+
if (fs.existsSync(cleanPath) || !options.rootDir)
|
|
2906
|
+
return path.normalize(cleanPath);
|
|
2907
|
+
return path.normalize(path.resolve(options.rootDir, `.${cleanPath}`));
|
|
2908
|
+
}
|
|
2909
|
+
if (!options.rootDir)
|
|
2854
2910
|
return null;
|
|
2911
|
+
return path.normalize(path.resolve(options.rootDir, cleanPath));
|
|
2912
|
+
}
|
|
2913
|
+
function getComponentInfoFromVueComponent(comp, options = {}) {
|
|
2914
|
+
if (!comp) {
|
|
2915
|
+
return {
|
|
2916
|
+
componentName: null,
|
|
2917
|
+
filePath: null
|
|
2918
|
+
};
|
|
2919
|
+
}
|
|
2920
|
+
let componentName = null;
|
|
2921
|
+
let filePath = null;
|
|
2855
2922
|
if (typeof comp.__file === "string" && comp.__file.length) {
|
|
2923
|
+
filePath = normalizeRouteComponentFilePath(comp.__file, { rootDir: options.rootDir });
|
|
2856
2924
|
const base = path.posix.basename(path.posix.normalize(comp.__file));
|
|
2857
2925
|
if (base.toLowerCase().endsWith(".vue"))
|
|
2858
|
-
|
|
2926
|
+
componentName = base.slice(0, -".vue".length);
|
|
2859
2927
|
}
|
|
2860
|
-
if (typeof comp.__name === "string" && comp.__name.length)
|
|
2861
|
-
|
|
2862
|
-
if (typeof comp.name === "string" && comp.name.length)
|
|
2863
|
-
|
|
2864
|
-
|
|
2928
|
+
if (!componentName && typeof comp.__name === "string" && comp.__name.length)
|
|
2929
|
+
componentName = comp.__name;
|
|
2930
|
+
if (!componentName && options.allowFunctionNameFallback !== false && typeof comp.name === "string" && comp.name.length) {
|
|
2931
|
+
componentName = comp.name;
|
|
2932
|
+
}
|
|
2933
|
+
return {
|
|
2934
|
+
componentName,
|
|
2935
|
+
filePath
|
|
2936
|
+
};
|
|
2937
|
+
}
|
|
2938
|
+
async function getComponentInfoFromRouteRecord(record, options = {}) {
|
|
2939
|
+
const comp = record.components?.default;
|
|
2940
|
+
if (!comp) {
|
|
2941
|
+
return {
|
|
2942
|
+
componentName: null,
|
|
2943
|
+
filePath: null
|
|
2944
|
+
};
|
|
2945
|
+
}
|
|
2946
|
+
if (typeof comp !== "function") {
|
|
2947
|
+
return getComponentInfoFromVueComponent(comp, options);
|
|
2948
|
+
}
|
|
2949
|
+
const directInfo = getComponentInfoFromVueComponent(comp, {
|
|
2950
|
+
allowFunctionNameFallback: false,
|
|
2951
|
+
rootDir: options.rootDir
|
|
2952
|
+
});
|
|
2953
|
+
if (directInfo.componentName || directInfo.filePath)
|
|
2954
|
+
return directInfo;
|
|
2955
|
+
try {
|
|
2956
|
+
const loaded = await comp();
|
|
2957
|
+
const resolved = loaded && typeof loaded === "object" && "default" in loaded ? loaded.default : loaded;
|
|
2958
|
+
const loadedInfo = getComponentInfoFromVueComponent(resolved, options);
|
|
2959
|
+
if (loadedInfo.componentName || loadedInfo.filePath)
|
|
2960
|
+
return loadedInfo;
|
|
2961
|
+
} catch {
|
|
2962
|
+
}
|
|
2963
|
+
return getComponentInfoFromVueComponent(comp, options);
|
|
2964
|
+
}
|
|
2965
|
+
function resolveIntrospectedComponentName(componentInfo, componentNaming) {
|
|
2966
|
+
if (componentInfo.filePath && componentNaming) {
|
|
2967
|
+
return resolveComponentNameFromPath({
|
|
2968
|
+
filename: componentInfo.filePath,
|
|
2969
|
+
projectRoot: componentNaming.projectRoot,
|
|
2970
|
+
viewsDirAbs: componentNaming.viewsDirAbs,
|
|
2971
|
+
scanDirs: componentNaming.scanDirs,
|
|
2972
|
+
extraRoots: componentNaming.extraRoots
|
|
2973
|
+
});
|
|
2974
|
+
}
|
|
2975
|
+
return componentInfo.componentName;
|
|
2865
2976
|
}
|
|
2866
2977
|
async function ensureDomShim() {
|
|
2867
2978
|
const domShimHtml = "<!doctype html><html><head></head><body><div id='app'></div></body></html>";
|
|
@@ -3107,7 +3218,8 @@ async function parseRouterFileFromCwd(routerEntryPath, options = {}) {
|
|
|
3107
3218
|
const routePathMap = /* @__PURE__ */ new Map();
|
|
3108
3219
|
const routeMetaEntries = [];
|
|
3109
3220
|
for (const r of router.getRoutes()) {
|
|
3110
|
-
const
|
|
3221
|
+
const componentInfo = await getComponentInfoFromRouteRecord(r, { rootDir: cwd });
|
|
3222
|
+
const componentName = resolveIntrospectedComponentName(componentInfo, options.componentNaming);
|
|
3111
3223
|
if (!componentName)
|
|
3112
3224
|
continue;
|
|
3113
3225
|
if (typeof r.path === "string" && r.path.length) {
|
|
@@ -3165,9 +3277,20 @@ function resolveRouterEntry(projectRoot, routerEntry) {
|
|
|
3165
3277
|
const root = projectRoot ?? process.cwd();
|
|
3166
3278
|
return path.isAbsolute(routerEntry) ? routerEntry : path.resolve(root, routerEntry);
|
|
3167
3279
|
}
|
|
3168
|
-
async function getRouteMetaByComponent(projectRoot, routerEntry, routerType) {
|
|
3280
|
+
async function getRouteMetaByComponent(projectRoot, routerEntry, routerType, options = {}) {
|
|
3169
3281
|
const root = projectRoot ?? process.cwd();
|
|
3170
|
-
const
|
|
3282
|
+
const viewsDir = options.viewsDir ?? "src/views";
|
|
3283
|
+
const viewsDirAbs = path.isAbsolute(viewsDir) ? viewsDir : path.resolve(root, viewsDir);
|
|
3284
|
+
const scanDirs = options.scanDirs?.length ? options.scanDirs : ["src"];
|
|
3285
|
+
const extraRoots = process.cwd() !== root ? [process.cwd()] : [];
|
|
3286
|
+
const { routeMetaEntries } = routerType === "nuxt" ? await introspectNuxtPages(root) : await parseRouterFileFromCwd(resolveRouterEntry(root, routerEntry), {
|
|
3287
|
+
componentNaming: {
|
|
3288
|
+
projectRoot: root,
|
|
3289
|
+
viewsDirAbs,
|
|
3290
|
+
scanDirs,
|
|
3291
|
+
extraRoots
|
|
3292
|
+
}
|
|
3293
|
+
});
|
|
3171
3294
|
const map = /* @__PURE__ */ new Map();
|
|
3172
3295
|
for (const entry of routeMetaEntries) {
|
|
3173
3296
|
const list = map.get(entry.componentName) ?? [];
|
|
@@ -3344,11 +3467,17 @@ async function generateFiles(componentHierarchyMap, vueFilesPathMap, basePageCla
|
|
|
3344
3467
|
csharp,
|
|
3345
3468
|
vueRouterFluentChaining,
|
|
3346
3469
|
routerEntry,
|
|
3347
|
-
routerType
|
|
3470
|
+
routerType,
|
|
3471
|
+
viewsDir,
|
|
3472
|
+
scanDirs,
|
|
3473
|
+
routeMetaByComponent: routeMetaByComponentOverride
|
|
3348
3474
|
} = options;
|
|
3349
3475
|
const emitLanguages = emitLanguagesOverride?.length ? emitLanguagesOverride : ["ts"];
|
|
3350
3476
|
const outDir = outDirOverride ?? "./pom";
|
|
3351
|
-
const routeMetaByComponent = vueRouterFluentChaining ? await getRouteMetaByComponent(projectRoot, routerEntry, routerType
|
|
3477
|
+
const routeMetaByComponent = routeMetaByComponentOverride ?? (vueRouterFluentChaining ? await getRouteMetaByComponent(projectRoot, routerEntry, routerType, {
|
|
3478
|
+
viewsDir,
|
|
3479
|
+
scanDirs
|
|
3480
|
+
}) : void 0);
|
|
3352
3481
|
const generatedFilePaths = [];
|
|
3353
3482
|
const writeGeneratedFile = (file) => {
|
|
3354
3483
|
const resolvedFilePath = path.resolve(file.filePath);
|
|
@@ -4478,6 +4607,8 @@ function createBuildProcessorPlugin(options) {
|
|
|
4478
4607
|
const {
|
|
4479
4608
|
componentHierarchyMap,
|
|
4480
4609
|
vueFilesPathMap,
|
|
4610
|
+
viewsDir,
|
|
4611
|
+
scanDirs,
|
|
4481
4612
|
basePageClassPath,
|
|
4482
4613
|
normalizedBasePagePath,
|
|
4483
4614
|
outDir,
|
|
@@ -4513,7 +4644,14 @@ function createBuildProcessorPlugin(options) {
|
|
|
4513
4644
|
} else {
|
|
4514
4645
|
if (!resolvedRouterEntry)
|
|
4515
4646
|
throw new Error("[vue-pom-generator] router.entry is required when router introspection is enabled.");
|
|
4516
|
-
result = await parseRouterFileFromCwd(resolvedRouterEntry, {
|
|
4647
|
+
result = await parseRouterFileFromCwd(resolvedRouterEntry, {
|
|
4648
|
+
moduleShims: routerModuleShims,
|
|
4649
|
+
componentNaming: {
|
|
4650
|
+
projectRoot: projectRootRef.current,
|
|
4651
|
+
viewsDirAbs: path.isAbsolute(viewsDir) ? viewsDir : path.resolve(projectRootRef.current, viewsDir),
|
|
4652
|
+
scanDirs
|
|
4653
|
+
}
|
|
4654
|
+
});
|
|
4517
4655
|
}
|
|
4518
4656
|
const { routeNameMap, routePathMap } = result;
|
|
4519
4657
|
setRouteNameToComponentNameMap(routeNameMap);
|
|
@@ -4564,7 +4702,9 @@ function createBuildProcessorPlugin(options) {
|
|
|
4564
4702
|
testIdAttribute,
|
|
4565
4703
|
vueRouterFluentChaining: routerAwarePoms,
|
|
4566
4704
|
routerEntry: resolvedRouterEntry,
|
|
4567
|
-
routerType
|
|
4705
|
+
routerType,
|
|
4706
|
+
viewsDir,
|
|
4707
|
+
scanDirs
|
|
4568
4708
|
});
|
|
4569
4709
|
buildGenerationMetricsByOutputKey.set(generationMetricsKey, metrics);
|
|
4570
4710
|
loggerRef.current.info(`generated POMs (${metrics.entryCount} entries, ${metrics.selectorCount} selectors)`);
|
|
@@ -5220,14 +5360,14 @@ function createTestIdTransform(componentName, componentHierarchyMap, nativeWrapp
|
|
|
5220
5360
|
const warn = options.warn;
|
|
5221
5361
|
const vueFilesPathMap = options.vueFilesPathMap;
|
|
5222
5362
|
const wrapperSearchRoots = options.wrapperSearchRoots ?? [];
|
|
5223
|
-
const
|
|
5363
|
+
const safeRealpath2 = (p) => {
|
|
5224
5364
|
try {
|
|
5225
5365
|
return fs.existsSync(p) ? fs.realpathSync(p) : p;
|
|
5226
5366
|
} catch {
|
|
5227
5367
|
return p;
|
|
5228
5368
|
}
|
|
5229
5369
|
};
|
|
5230
|
-
const normalizedViewsDirAbs = path.normalize(
|
|
5370
|
+
const normalizedViewsDirAbs = path.normalize(safeRealpath2(path.resolve(viewsDirAbs)));
|
|
5231
5371
|
const generatedMethodContentByComponent = /* @__PURE__ */ new Map();
|
|
5232
5372
|
const lastConditionalHintByParent = /* @__PURE__ */ new WeakMap();
|
|
5233
5373
|
const lastConditionalMergeGroupByParent = /* @__PURE__ */ new WeakMap();
|
|
@@ -5315,7 +5455,7 @@ function createTestIdTransform(componentName, componentHierarchyMap, nativeWrapp
|
|
|
5315
5455
|
const parentIsRoot = context?.parent?.type === compilerCore.NodeTypes.ROOT;
|
|
5316
5456
|
const parentElement = !parentIsRoot && context?.parent?.type === compilerCore.NodeTypes.ELEMENT ? context.parent : null;
|
|
5317
5457
|
hierarchyMap.set(element, parentElement);
|
|
5318
|
-
const normalizeFilePath = (filePath) => path.normalize(
|
|
5458
|
+
const normalizeFilePath = (filePath) => path.normalize(safeRealpath2(path.resolve(filePath)));
|
|
5319
5459
|
const normalizedFilePath = normalizeFilePath(context.filename);
|
|
5320
5460
|
const parentComponentName = componentName;
|
|
5321
5461
|
const dependencies = (() => {
|
|
@@ -5502,14 +5642,23 @@ Fix: remove the explicit ${attrLabel}, or change existingIdBehavior to "overwrit
|
|
|
5502
5642
|
upsertAttribute(element, "option-data-testid-prefix", optionDataTestIdPrefixValue);
|
|
5503
5643
|
}
|
|
5504
5644
|
const nativeRole = nativeWrappers[element.tag]?.role ?? element.tag;
|
|
5505
|
-
const
|
|
5506
|
-
|
|
5645
|
+
const wrapperHintCandidates = [
|
|
5646
|
+
semanticNameHint,
|
|
5647
|
+
getStaticAttributeContent(element, "title"),
|
|
5648
|
+
getStaticAttributeContent(element, "label"),
|
|
5649
|
+
getStaticAttributeContent(element, "okTitle"),
|
|
5650
|
+
getStaticAttributeContent(element, "cancelTitle"),
|
|
5651
|
+
getStaticAttributeContent(element, "id") || getStaticAttributeContent(element, "name"),
|
|
5652
|
+
getInnerText(element) || null,
|
|
5653
|
+
nameCollisionBehavior === "error" && semanticNameHint && conditionalHint ? `${semanticNameHint} ${conditionalHint}` : conditionalHint
|
|
5654
|
+
].map((value) => (value ?? "").trim()).filter(Boolean).filter((value, index, values) => values.indexOf(value) === index);
|
|
5655
|
+
const [primarySemanticHint, ...alternates] = wrapperHintCandidates;
|
|
5507
5656
|
const pomMergeKey = semanticNameHint && conditionalMergeGroupKey ? `wrapper:ifgroup:${conditionalMergeGroupKey}:model:${semanticNameHint}` : void 0;
|
|
5508
5657
|
applyResolvedDataTestIdForElement({
|
|
5509
5658
|
preferredGeneratedValue: nativeWrappersValue,
|
|
5510
5659
|
nativeRoleOverride: nativeRole,
|
|
5511
5660
|
semanticNameHint: primarySemanticHint,
|
|
5512
|
-
semanticNameHintAlternates: alternates,
|
|
5661
|
+
semanticNameHintAlternates: alternates.length ? alternates : void 0,
|
|
5513
5662
|
pomMergeKey
|
|
5514
5663
|
});
|
|
5515
5664
|
return;
|
|
@@ -5599,12 +5748,14 @@ Fix: remove the explicit ${attrLabel}, or change existingIdBehavior to "overwrit
|
|
|
5599
5748
|
});
|
|
5600
5749
|
const clickHint = trimLeadingSeparators(clickSuffix) || void 0;
|
|
5601
5750
|
const idOrName = getIdOrName(element) || void 0;
|
|
5602
|
-
const
|
|
5751
|
+
const semanticHintCandidates = [clickHint, idOrName, innerText, conditionalHint].map((value) => (value ?? "").trim()).filter(Boolean).filter((value, index, values) => values.indexOf(value) === index);
|
|
5752
|
+
const [semanticNameHint2, ...semanticNameHintAlternates] = semanticHintCandidates;
|
|
5603
5753
|
const pomMergeKey = clickHint ? `click:hint:${clickHint}` : void 0;
|
|
5604
5754
|
const testId = getClickDataTestId(clickSuffix);
|
|
5605
5755
|
applyResolvedDataTestIdForElement({
|
|
5606
5756
|
preferredGeneratedValue: testId,
|
|
5607
5757
|
semanticNameHint: semanticNameHint2,
|
|
5758
|
+
semanticNameHintAlternates,
|
|
5608
5759
|
pomMergeKey
|
|
5609
5760
|
});
|
|
5610
5761
|
{
|
|
@@ -5645,37 +5796,6 @@ Fix: remove the explicit ${attrLabel}, or change existingIdBehavior to "overwrit
|
|
|
5645
5796
|
}
|
|
5646
5797
|
};
|
|
5647
5798
|
}
|
|
5648
|
-
function resolveComponentNameFromPath(options) {
|
|
5649
|
-
const { projectRoot, viewsDirAbs, scanDirs, extraRoots = [] } = options;
|
|
5650
|
-
const cleanFilename = options.filename.includes("?") ? options.filename.substring(0, options.filename.indexOf("?")) : options.filename;
|
|
5651
|
-
const absFilename = path.isAbsolute(cleanFilename) ? cleanFilename : path.resolve(projectRoot, cleanFilename);
|
|
5652
|
-
const rootBases = [projectRoot, ...extraRoots.filter((r) => r !== projectRoot)];
|
|
5653
|
-
const roots = [viewsDirAbs, ...rootBases.flatMap((base) => scanDirs.map((d) => path.resolve(base, d)))];
|
|
5654
|
-
for (const base of rootBases) {
|
|
5655
|
-
for (const dir of scanDirs) {
|
|
5656
|
-
const absDir = path.resolve(base, dir);
|
|
5657
|
-
try {
|
|
5658
|
-
const pagesDir = path.join(absDir, "pages");
|
|
5659
|
-
if (fs.existsSync(pagesDir))
|
|
5660
|
-
roots.push(pagesDir);
|
|
5661
|
-
const componentsDir = path.join(absDir, "components");
|
|
5662
|
-
if (fs.existsSync(componentsDir))
|
|
5663
|
-
roots.push(componentsDir);
|
|
5664
|
-
} catch {
|
|
5665
|
-
}
|
|
5666
|
-
}
|
|
5667
|
-
}
|
|
5668
|
-
const potentialRoots = Array.from(new Set(roots.map((r) => path.normalize(r)))).sort((a, b) => b.length - a.length);
|
|
5669
|
-
for (const root of potentialRoots) {
|
|
5670
|
-
if (absFilename.startsWith(root + path.sep) || absFilename === root) {
|
|
5671
|
-
const rel = path.relative(root, absFilename);
|
|
5672
|
-
const parsed = path.parse(rel);
|
|
5673
|
-
const segments = path.join(parsed.dir, parsed.name);
|
|
5674
|
-
return toPascalCase(segments);
|
|
5675
|
-
}
|
|
5676
|
-
}
|
|
5677
|
-
return toPascalCase(path.parse(absFilename).name);
|
|
5678
|
-
}
|
|
5679
5799
|
const devStartupMetricsByOutputKey = /* @__PURE__ */ new Map();
|
|
5680
5800
|
function createDevProcessorPlugin(options) {
|
|
5681
5801
|
const {
|
|
@@ -5722,6 +5842,7 @@ function createDevProcessorPlugin(options) {
|
|
|
5722
5842
|
scheduleVueFileRegen(ctx.file, "hmr");
|
|
5723
5843
|
},
|
|
5724
5844
|
configureServer(server) {
|
|
5845
|
+
const getViewsDirAbs = () => path.isAbsolute(viewsDir) ? viewsDir : path.resolve(projectRootRef.current, viewsDir);
|
|
5725
5846
|
const routerInitPromise = (async () => {
|
|
5726
5847
|
if (!routerAwarePoms) {
|
|
5727
5848
|
setRouteNameToComponentNameMap(/* @__PURE__ */ new Map());
|
|
@@ -5734,7 +5855,15 @@ function createDevProcessorPlugin(options) {
|
|
|
5734
5855
|
} else {
|
|
5735
5856
|
if (!resolvedRouterEntry)
|
|
5736
5857
|
throw new Error("[vue-pom-generator] router.entry is required when router introspection is enabled.");
|
|
5737
|
-
result = await parseRouterFileFromCwd(resolvedRouterEntry, {
|
|
5858
|
+
result = await parseRouterFileFromCwd(resolvedRouterEntry, {
|
|
5859
|
+
moduleShims: routerModuleShims,
|
|
5860
|
+
componentNaming: {
|
|
5861
|
+
projectRoot: projectRootRef.current,
|
|
5862
|
+
viewsDirAbs: getViewsDirAbs(),
|
|
5863
|
+
scanDirs,
|
|
5864
|
+
extraRoots: [process.cwd()]
|
|
5865
|
+
}
|
|
5866
|
+
});
|
|
5738
5867
|
}
|
|
5739
5868
|
const { routeNameMap, routePathMap } = result;
|
|
5740
5869
|
setRouteNameToComponentNameMap(routeNameMap);
|
|
@@ -5757,7 +5886,6 @@ function createDevProcessorPlugin(options) {
|
|
|
5757
5886
|
const logDebug = (message) => loggerRef.current.debug(message);
|
|
5758
5887
|
let scheduleVueFileRegenLocal = null;
|
|
5759
5888
|
const formatMs = (ms) => `${ms.toFixed(1)}ms`;
|
|
5760
|
-
const getViewsDirAbs = () => path.isAbsolute(viewsDir) ? viewsDir : path.resolve(projectRootRef.current, viewsDir);
|
|
5761
5889
|
const extractTemplateFromSfc = (source, filename) => {
|
|
5762
5890
|
const { descriptor } = compilerSfc.parse(source, {
|
|
5763
5891
|
filename: filename ?? "anonymous.vue"
|
|
@@ -5899,7 +6027,9 @@ function createDevProcessorPlugin(options) {
|
|
|
5899
6027
|
testIdAttribute,
|
|
5900
6028
|
vueRouterFluentChaining: routerAwarePoms,
|
|
5901
6029
|
routerEntry: resolvedRouterEntry,
|
|
5902
|
-
routerType
|
|
6030
|
+
routerType,
|
|
6031
|
+
viewsDir,
|
|
6032
|
+
scanDirs
|
|
5903
6033
|
});
|
|
5904
6034
|
if (reason === "startup") {
|
|
5905
6035
|
devStartupMetricsByOutputKey.set(generationMetricsKey, metrics);
|
|
@@ -6121,6 +6251,8 @@ function createSupportPlugins(options) {
|
|
|
6121
6251
|
const tsProcessor = createBuildProcessorPlugin({
|
|
6122
6252
|
componentHierarchyMap,
|
|
6123
6253
|
vueFilesPathMap,
|
|
6254
|
+
viewsDir,
|
|
6255
|
+
scanDirs,
|
|
6124
6256
|
basePageClassPath,
|
|
6125
6257
|
normalizedBasePagePath,
|
|
6126
6258
|
outDir,
|