@immense/vue-pom-generator 1.0.33 → 1.0.34
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 +21 -25
- 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 +177 -54
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +177 -54
- 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,35 +1,31 @@
|
|
|
1
|
-
● #
|
|
1
|
+
● # v1.0.34
|
|
2
2
|
|
|
3
3
|
## Highlights
|
|
4
4
|
|
|
5
|
-
- Fixed
|
|
6
|
-
-
|
|
7
|
-
|
|
8
|
-
-
|
|
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
|
|
5
|
+
- Fixed strict click collision detection to prevent false positives
|
|
6
|
+
- Improved lazy route component naming for better code generation
|
|
7
|
+
- Enhanced router introspection with significant improvements to route handling
|
|
8
|
+
- Added comprehensive test coverage for class generation and router introspection
|
|
12
9
|
|
|
13
10
|
## Changes
|
|
14
11
|
|
|
15
|
-
**
|
|
16
|
-
- Fixed
|
|
17
|
-
-
|
|
12
|
+
**Bug Fixes**
|
|
13
|
+
- Fixed strict click collision detection logic in transform pipeline
|
|
14
|
+
- Corrected lazy route component naming in class generation
|
|
18
15
|
|
|
19
|
-
**
|
|
20
|
-
- Added
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
`plugin/support/build-plugin.ts`
|
|
16
|
+
**Testing & Quality**
|
|
17
|
+
- Added 70+ lines of new tests for class-generation coverage
|
|
18
|
+
- Added 64+ lines of new tests for router introspection
|
|
19
|
+
- Added 37+ lines of new tests for transform logic
|
|
24
20
|
|
|
25
|
-
**
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
21
|
+
**Internal Improvements**
|
|
22
|
+
- Enhanced router introspection with 140+ lines of improvements
|
|
23
|
+
- Updated plugin path utilities with better handling
|
|
24
|
+
- Improved support plugins for both build and dev modes
|
|
29
25
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
## Breaking Changes
|
|
27
|
+
|
|
28
|
+
None.
|
|
33
29
|
|
|
34
30
|
## Pull Requests Included
|
|
35
31
|
|
|
@@ -38,6 +34,6 @@
|
|
|
38
34
|
|
|
39
35
|
## Testing
|
|
40
36
|
|
|
41
|
-
|
|
42
|
-
tests passing.
|
|
37
|
+
Comprehensive test coverage added across class generation, router introspection, and transform
|
|
38
|
+
modules. All tests passing.
|
|
43
39
|
|
|
@@ -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 = (() => {
|
|
@@ -5599,12 +5739,14 @@ Fix: remove the explicit ${attrLabel}, or change existingIdBehavior to "overwrit
|
|
|
5599
5739
|
});
|
|
5600
5740
|
const clickHint = trimLeadingSeparators(clickSuffix) || void 0;
|
|
5601
5741
|
const idOrName = getIdOrName(element) || void 0;
|
|
5602
|
-
const
|
|
5742
|
+
const semanticHintCandidates = [clickHint, idOrName, innerText, conditionalHint].map((value) => (value ?? "").trim()).filter(Boolean).filter((value, index, values) => values.indexOf(value) === index);
|
|
5743
|
+
const [semanticNameHint2, ...semanticNameHintAlternates] = semanticHintCandidates;
|
|
5603
5744
|
const pomMergeKey = clickHint ? `click:hint:${clickHint}` : void 0;
|
|
5604
5745
|
const testId = getClickDataTestId(clickSuffix);
|
|
5605
5746
|
applyResolvedDataTestIdForElement({
|
|
5606
5747
|
preferredGeneratedValue: testId,
|
|
5607
5748
|
semanticNameHint: semanticNameHint2,
|
|
5749
|
+
semanticNameHintAlternates,
|
|
5608
5750
|
pomMergeKey
|
|
5609
5751
|
});
|
|
5610
5752
|
{
|
|
@@ -5645,37 +5787,6 @@ Fix: remove the explicit ${attrLabel}, or change existingIdBehavior to "overwrit
|
|
|
5645
5787
|
}
|
|
5646
5788
|
};
|
|
5647
5789
|
}
|
|
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
5790
|
const devStartupMetricsByOutputKey = /* @__PURE__ */ new Map();
|
|
5680
5791
|
function createDevProcessorPlugin(options) {
|
|
5681
5792
|
const {
|
|
@@ -5722,6 +5833,7 @@ function createDevProcessorPlugin(options) {
|
|
|
5722
5833
|
scheduleVueFileRegen(ctx.file, "hmr");
|
|
5723
5834
|
},
|
|
5724
5835
|
configureServer(server) {
|
|
5836
|
+
const getViewsDirAbs = () => path.isAbsolute(viewsDir) ? viewsDir : path.resolve(projectRootRef.current, viewsDir);
|
|
5725
5837
|
const routerInitPromise = (async () => {
|
|
5726
5838
|
if (!routerAwarePoms) {
|
|
5727
5839
|
setRouteNameToComponentNameMap(/* @__PURE__ */ new Map());
|
|
@@ -5734,7 +5846,15 @@ function createDevProcessorPlugin(options) {
|
|
|
5734
5846
|
} else {
|
|
5735
5847
|
if (!resolvedRouterEntry)
|
|
5736
5848
|
throw new Error("[vue-pom-generator] router.entry is required when router introspection is enabled.");
|
|
5737
|
-
result = await parseRouterFileFromCwd(resolvedRouterEntry, {
|
|
5849
|
+
result = await parseRouterFileFromCwd(resolvedRouterEntry, {
|
|
5850
|
+
moduleShims: routerModuleShims,
|
|
5851
|
+
componentNaming: {
|
|
5852
|
+
projectRoot: projectRootRef.current,
|
|
5853
|
+
viewsDirAbs: getViewsDirAbs(),
|
|
5854
|
+
scanDirs,
|
|
5855
|
+
extraRoots: [process.cwd()]
|
|
5856
|
+
}
|
|
5857
|
+
});
|
|
5738
5858
|
}
|
|
5739
5859
|
const { routeNameMap, routePathMap } = result;
|
|
5740
5860
|
setRouteNameToComponentNameMap(routeNameMap);
|
|
@@ -5757,7 +5877,6 @@ function createDevProcessorPlugin(options) {
|
|
|
5757
5877
|
const logDebug = (message) => loggerRef.current.debug(message);
|
|
5758
5878
|
let scheduleVueFileRegenLocal = null;
|
|
5759
5879
|
const formatMs = (ms) => `${ms.toFixed(1)}ms`;
|
|
5760
|
-
const getViewsDirAbs = () => path.isAbsolute(viewsDir) ? viewsDir : path.resolve(projectRootRef.current, viewsDir);
|
|
5761
5880
|
const extractTemplateFromSfc = (source, filename) => {
|
|
5762
5881
|
const { descriptor } = compilerSfc.parse(source, {
|
|
5763
5882
|
filename: filename ?? "anonymous.vue"
|
|
@@ -5899,7 +6018,9 @@ function createDevProcessorPlugin(options) {
|
|
|
5899
6018
|
testIdAttribute,
|
|
5900
6019
|
vueRouterFluentChaining: routerAwarePoms,
|
|
5901
6020
|
routerEntry: resolvedRouterEntry,
|
|
5902
|
-
routerType
|
|
6021
|
+
routerType,
|
|
6022
|
+
viewsDir,
|
|
6023
|
+
scanDirs
|
|
5903
6024
|
});
|
|
5904
6025
|
if (reason === "startup") {
|
|
5905
6026
|
devStartupMetricsByOutputKey.set(generationMetricsKey, metrics);
|
|
@@ -6121,6 +6242,8 @@ function createSupportPlugins(options) {
|
|
|
6121
6242
|
const tsProcessor = createBuildProcessorPlugin({
|
|
6122
6243
|
componentHierarchyMap,
|
|
6123
6244
|
vueFilesPathMap,
|
|
6245
|
+
viewsDir,
|
|
6246
|
+
scanDirs,
|
|
6124
6247
|
basePageClassPath,
|
|
6125
6248
|
normalizedBasePagePath,
|
|
6126
6249
|
outDir,
|