@dxup/nuxt 0.3.1 → 0.4.0
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 +20 -5
- package/dist/module.d.mts +14 -6
- package/dist/module.mjs +17 -6
- package/dist/typescript.cjs +61 -28
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -62,7 +62,20 @@ useFetch("/api/foo");
|
|
|
62
62
|
|
|
63
63
|
It will fallback to resolve the URL from your `public` directory when no nitro routes match.
|
|
64
64
|
|
|
65
|
-
### 4.
|
|
65
|
+
### 4. pageMeta
|
|
66
|
+
|
|
67
|
+
Go to definition for page metadata.
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
definePageMeta({
|
|
71
|
+
layout: "admin",
|
|
72
|
+
// ^^^^^^^
|
|
73
|
+
middleware: ["auth"],
|
|
74
|
+
// ^^^^^^
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 5. runtimeConfig
|
|
66
79
|
|
|
67
80
|
Go to definition for runtime config.
|
|
68
81
|
|
|
@@ -73,7 +86,7 @@ Go to definition for runtime config.
|
|
|
73
86
|
</template>
|
|
74
87
|
```
|
|
75
88
|
|
|
76
|
-
###
|
|
89
|
+
### 6. typedPages
|
|
77
90
|
|
|
78
91
|
Go to definition for typed pages.
|
|
79
92
|
|
|
@@ -86,7 +99,11 @@ Go to definition for typed pages.
|
|
|
86
99
|
|
|
87
100
|
It can be triggered on the `name` property of an object literal constrained by the `RouteLocationRaw` type.
|
|
88
101
|
|
|
89
|
-
###
|
|
102
|
+
### 7. unimport
|
|
103
|
+
|
|
104
|
+
Please refer to the [@dxup/unimport](/packages/unimport) package for more details.
|
|
105
|
+
|
|
106
|
+
### 8. unofficial
|
|
90
107
|
|
|
91
108
|
Find references for SFC on `<template>`.
|
|
92
109
|
|
|
@@ -95,5 +112,3 @@ Find references for SFC on `<template>`.
|
|
|
95
112
|
<!-- ^^^^^^^^ -->
|
|
96
113
|
</template>
|
|
97
114
|
```
|
|
98
|
-
|
|
99
|
-
Please refer to the [@dxup/unimport](/packages/unimport) package for more details.
|
package/dist/module.d.mts
CHANGED
|
@@ -18,6 +18,11 @@ interface ModuleOptions {
|
|
|
18
18
|
* @default true
|
|
19
19
|
*/
|
|
20
20
|
nitroRoutes?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Whether to enable Go to Definition for page metadata.
|
|
23
|
+
* @default true
|
|
24
|
+
*/
|
|
25
|
+
pageMeta?: boolean;
|
|
21
26
|
/**
|
|
22
27
|
* Whether to enable Go to Definition for runtime config.
|
|
23
28
|
* @default true
|
|
@@ -32,12 +37,13 @@ interface ModuleOptions {
|
|
|
32
37
|
* Whether to enable enhanced navigation for auto imported APIs.
|
|
33
38
|
* @default true
|
|
34
39
|
*/
|
|
35
|
-
unimport?: boolean
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
unimport?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Whether to enable unofficial features for Vue itself.
|
|
43
|
+
* - find references for SFC on `<template>`
|
|
44
|
+
* @default true
|
|
45
|
+
*/
|
|
46
|
+
unofficial?: boolean;
|
|
41
47
|
};
|
|
42
48
|
}
|
|
43
49
|
declare const _default: _nuxt_schema0.NuxtModule<ModuleOptions, {
|
|
@@ -45,9 +51,11 @@ declare const _default: _nuxt_schema0.NuxtModule<ModuleOptions, {
|
|
|
45
51
|
components: true;
|
|
46
52
|
importGlob: true;
|
|
47
53
|
nitroRoutes: true;
|
|
54
|
+
pageMeta: true;
|
|
48
55
|
runtimeConfig: true;
|
|
49
56
|
typedPages: true;
|
|
50
57
|
unimport: true;
|
|
58
|
+
unofficial: true;
|
|
51
59
|
};
|
|
52
60
|
}, true>;
|
|
53
61
|
//#endregion
|
package/dist/module.mjs
CHANGED
|
@@ -73,9 +73,11 @@ var module_default = defineNuxtModule().with({
|
|
|
73
73
|
components: true,
|
|
74
74
|
importGlob: true,
|
|
75
75
|
nitroRoutes: true,
|
|
76
|
+
pageMeta: true,
|
|
76
77
|
runtimeConfig: true,
|
|
77
78
|
typedPages: true,
|
|
78
|
-
unimport: true
|
|
79
|
+
unimport: true,
|
|
80
|
+
unofficial: true
|
|
79
81
|
} },
|
|
80
82
|
async setup(options, nuxt) {
|
|
81
83
|
const pluginsTs = [{ name: "@dxup/nuxt" }];
|
|
@@ -88,20 +90,29 @@ var module_default = defineNuxtModule().with({
|
|
|
88
90
|
filename: "dxup/data.json",
|
|
89
91
|
write: true,
|
|
90
92
|
getContents({ nuxt: nuxt$1, app }) {
|
|
93
|
+
const layouts = Object.fromEntries(Object.values(app.layouts).map((item) => [item.name, item.file]));
|
|
94
|
+
const middleware = app.middleware.reduce((acc, item) => {
|
|
95
|
+
if (!item.global) acc[item.name] = item.path;
|
|
96
|
+
return acc;
|
|
97
|
+
}, {});
|
|
91
98
|
const nitroRoutes = useNitro().scannedHandlers.reduce((acc, item) => {
|
|
92
99
|
if (item.route && item.method) (acc[item.route] ??= {})[item.method] = item.handler;
|
|
93
100
|
return acc;
|
|
94
101
|
}, {});
|
|
102
|
+
const typedPages = app.pages?.reduce(function reducer(acc, page) {
|
|
103
|
+
if (page.name && page.file) acc[page.name] = page.file;
|
|
104
|
+
if (page.children) for (const child of page.children) reducer(acc, child);
|
|
105
|
+
return acc;
|
|
106
|
+
}, {});
|
|
95
107
|
const data = {
|
|
96
108
|
buildDir: nuxt$1.options.buildDir,
|
|
97
109
|
publicDir: nuxt$1.options.dir.public,
|
|
98
110
|
configFiles: [...nuxt$1.options._nuxtConfigFiles, ...nuxt$1.options._layers.map((layer) => layer._configFile).filter(Boolean)],
|
|
111
|
+
layouts,
|
|
112
|
+
middleware,
|
|
99
113
|
nitroRoutes,
|
|
100
|
-
typedPages
|
|
101
|
-
features:
|
|
102
|
-
...options.features,
|
|
103
|
-
unimport: { componentReferences: typeof options.features.unimport === "object" ? options.features.unimport.componentReferences : options.features.unimport }
|
|
104
|
-
}
|
|
114
|
+
typedPages,
|
|
115
|
+
features: options.features
|
|
105
116
|
};
|
|
106
117
|
return JSON.stringify(data, null, 2);
|
|
107
118
|
}
|
package/dist/typescript.cjs
CHANGED
|
@@ -36,15 +36,18 @@ const initialValue = {
|
|
|
36
36
|
buildDir: "",
|
|
37
37
|
publicDir: "",
|
|
38
38
|
configFiles: [],
|
|
39
|
+
layouts: {},
|
|
40
|
+
middleware: {},
|
|
39
41
|
nitroRoutes: {},
|
|
40
42
|
typedPages: {},
|
|
41
43
|
features: {
|
|
42
44
|
components: true,
|
|
43
45
|
importGlob: true,
|
|
44
46
|
nitroRoutes: true,
|
|
47
|
+
pageMeta: true,
|
|
45
48
|
runtimeConfig: true,
|
|
46
49
|
typedPages: true,
|
|
47
|
-
|
|
50
|
+
unofficial: true
|
|
48
51
|
}
|
|
49
52
|
};
|
|
50
53
|
const callbacks = {};
|
|
@@ -84,18 +87,6 @@ function createModuleDefinition(ts, path) {
|
|
|
84
87
|
function isVueVirtualCode(code) {
|
|
85
88
|
return code?.languageId === "vue";
|
|
86
89
|
}
|
|
87
|
-
function toSourceSpan(language, fileName, textSpan) {
|
|
88
|
-
const sourceScript = language?.scripts.get(fileName);
|
|
89
|
-
if (!sourceScript?.generated) return;
|
|
90
|
-
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
|
|
91
|
-
if (!serviceScript) return;
|
|
92
|
-
const map = language.maps.get(serviceScript.code, sourceScript);
|
|
93
|
-
const leadingOffset = sourceScript.snapshot.getLength();
|
|
94
|
-
for (const [start, end] of map.toSourceRange(textSpan.start - leadingOffset, textSpan.start + textSpan.length - leadingOffset, false)) return {
|
|
95
|
-
start,
|
|
96
|
-
length: end - start
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
90
|
function withVirtualOffset(language, sourceScript, position, method) {
|
|
100
91
|
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
|
|
101
92
|
if (!serviceScript) return;
|
|
@@ -133,7 +124,7 @@ function postprocess$1(context, language, findReferences) {
|
|
|
133
124
|
return (...args) => {
|
|
134
125
|
const result = findReferences(...args);
|
|
135
126
|
if (!result?.length) {
|
|
136
|
-
const sourceScript = language.scripts.get(args[0]);
|
|
127
|
+
const sourceScript = language.scripts.get(args[0].replaceAll("\\", "/"));
|
|
137
128
|
const root = sourceScript?.generated?.root;
|
|
138
129
|
if (!isVueVirtualCode(root)) return;
|
|
139
130
|
const start = (root.sfc.template?.start ?? Infinity) + 1;
|
|
@@ -198,12 +189,13 @@ const fetchFunctions = new Set([
|
|
|
198
189
|
"useFetch",
|
|
199
190
|
"useLazyFetch"
|
|
200
191
|
]);
|
|
192
|
+
const pageMetaKeys = new Set(["layout", "middleware"]);
|
|
201
193
|
function postprocess(context, language, getDefinitionAndBoundSpan) {
|
|
202
194
|
const { ts } = context;
|
|
203
195
|
return (...args) => {
|
|
204
196
|
const result = getDefinitionAndBoundSpan(...args);
|
|
205
197
|
if (!result?.definitions?.length) {
|
|
206
|
-
const root = language.scripts.get(args[0])?.generated?.root;
|
|
198
|
+
const root = language.scripts.get(args[0].replaceAll("\\", "/"))?.generated?.root;
|
|
207
199
|
if (!isVueVirtualCode(root)) return result;
|
|
208
200
|
const textSpan = {
|
|
209
201
|
start: (root.sfc.template?.start ?? Infinity) + 1,
|
|
@@ -238,6 +230,7 @@ function preprocess$1(context, getDefinitionAndBoundSpan) {
|
|
|
238
230
|
for (const node of forEachTouchingNode(ts, sourceFile, args[1])) {
|
|
239
231
|
if (data.features.importGlob) result$1 ??= visitImportGlob(ts, info, sourceFile, node, args[1]);
|
|
240
232
|
if (data.features.nitroRoutes) result$1 ??= visitNitroRoutes(ts, data, checker, sourceFile, node, args[1]);
|
|
233
|
+
if (data.features.pageMeta) result$1 ??= visitPageMeta(ts, data, sourceFile, node, args[1]);
|
|
241
234
|
if (data.features.typedPages) result$1 ??= visitTypedPages(ts, data, checker, sourceFile, node, args[1]);
|
|
242
235
|
}
|
|
243
236
|
if (result$1) return result$1;
|
|
@@ -331,12 +324,51 @@ function visitNitroRoutes(ts, data, checker, sourceFile, node, position) {
|
|
|
331
324
|
definitions: paths.map((path) => createModuleDefinition(ts, path))
|
|
332
325
|
};
|
|
333
326
|
}
|
|
327
|
+
function visitPageMeta(ts, data, sourceFile, node, position) {
|
|
328
|
+
if (!ts.isPropertyAssignment(node) || !ts.isIdentifier(node.name) || !pageMetaKeys.has(node.name.text) || !ts.isCallExpression(node.parent.parent) || !ts.isIdentifier(node.parent.parent.expression) || node.parent.parent.expression.text !== "definePageMeta") return;
|
|
329
|
+
switch (node.name.text) {
|
|
330
|
+
case "layout": {
|
|
331
|
+
if (!ts.isStringLiteralLike(node.initializer)) return;
|
|
332
|
+
const start = node.initializer.getStart(sourceFile);
|
|
333
|
+
const end = node.initializer.getEnd();
|
|
334
|
+
if (position < start || position > end) return;
|
|
335
|
+
const path = data.layouts[node.initializer.text];
|
|
336
|
+
if (path === void 0) return;
|
|
337
|
+
return {
|
|
338
|
+
textSpan: {
|
|
339
|
+
start,
|
|
340
|
+
length: end - start
|
|
341
|
+
},
|
|
342
|
+
definitions: [createModuleDefinition(ts, path)]
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
case "middleware": {
|
|
346
|
+
const literals = ts.isStringLiteralLike(node.initializer) ? [node.initializer] : ts.isArrayLiteralExpression(node.initializer) ? node.initializer.elements.filter(ts.isStringLiteralLike) : [];
|
|
347
|
+
for (const literal of literals) {
|
|
348
|
+
const start = literal.getStart(sourceFile);
|
|
349
|
+
const end = literal.getEnd();
|
|
350
|
+
if (position < start || position > end) continue;
|
|
351
|
+
const path = data.middleware[literal.text];
|
|
352
|
+
if (path === void 0) continue;
|
|
353
|
+
return {
|
|
354
|
+
textSpan: {
|
|
355
|
+
start,
|
|
356
|
+
length: end - start
|
|
357
|
+
},
|
|
358
|
+
definitions: [createModuleDefinition(ts, path)]
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
break;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
334
365
|
function visitTypedPages(ts, data, checker, sourceFile, node, position) {
|
|
335
366
|
if (!ts.isPropertyAssignment(node) || !ts.isIdentifier(node.name) || node.name.text !== "name" || !ts.isStringLiteralLike(node.initializer)) return;
|
|
336
367
|
const start = node.initializer.getStart(sourceFile);
|
|
337
368
|
const end = node.initializer.getEnd();
|
|
338
369
|
if (position < start || position > end) return;
|
|
339
|
-
|
|
370
|
+
const contextualType = checker.getContextualType(node.parent)?.getNonNullableType();
|
|
371
|
+
if (contextualType?.aliasSymbol?.name !== "RouteLocationRaw" && (!contextualType?.isUnion() || contextualType.types.every((type) => type.symbol?.name !== "RouteLocationAsPathTyped"))) return;
|
|
340
372
|
const path = data.typedPages[node.initializer.text];
|
|
341
373
|
if (path === void 0) return;
|
|
342
374
|
return {
|
|
@@ -430,30 +462,31 @@ function preprocess(context, getEditsForFileRename) {
|
|
|
430
462
|
return (...args) => {
|
|
431
463
|
const result = getEditsForFileRename(...args);
|
|
432
464
|
if (!result?.length) return result;
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
const
|
|
437
|
-
|
|
465
|
+
if (data.features.components) {
|
|
466
|
+
const languageService = info.project.getLanguageService();
|
|
467
|
+
const program = languageService.getProgram();
|
|
468
|
+
const references = {};
|
|
469
|
+
for (const { fileName, textChanges } of result) {
|
|
470
|
+
if (!fileName.endsWith("components.d.ts")) continue;
|
|
438
471
|
const sourceFile = program.getSourceFile(fileName);
|
|
439
472
|
if (!sourceFile) continue;
|
|
440
473
|
for (const { span } of textChanges) for (const node of forEachTouchingNode(ts, sourceFile, span.start)) {
|
|
441
474
|
if (!ts.isPropertySignature(node) && !ts.isVariableDeclaration(node)) continue;
|
|
442
475
|
const position = node.name.getStart(sourceFile);
|
|
443
|
-
const res =
|
|
476
|
+
const res = languageService.getReferencesAtPosition(fileName, position)?.filter((entry) => !entry.fileName.startsWith(data.buildDir))?.sort((a, b) => a.textSpan.start - b.textSpan.start);
|
|
444
477
|
const lazy = node.type && ts.isTypeReferenceNode(node.type) && ts.isIdentifier(node.type.typeName) && node.type.typeName.text === "LazyComponent";
|
|
445
478
|
for (const { fileName: fileName$1, textSpan } of res ?? []) (references[fileName$1] ??= []).push({
|
|
446
|
-
textSpan
|
|
479
|
+
textSpan,
|
|
447
480
|
lazy: lazy || void 0
|
|
448
481
|
});
|
|
449
482
|
break;
|
|
450
483
|
}
|
|
451
484
|
}
|
|
485
|
+
if (Object.keys(references).length) server.write("components:rename", {
|
|
486
|
+
fileName: args[1],
|
|
487
|
+
references
|
|
488
|
+
});
|
|
452
489
|
}
|
|
453
|
-
if (Object.keys(references).length) server.write("components:rename", {
|
|
454
|
-
fileName: args[1],
|
|
455
|
-
references
|
|
456
|
-
});
|
|
457
490
|
return result.filter((change) => {
|
|
458
491
|
return !change.fileName.startsWith(data.buildDir);
|
|
459
492
|
});
|
|
@@ -474,7 +507,7 @@ const plugin = (module$1) => {
|
|
|
474
507
|
};
|
|
475
508
|
queueMicrotask(() => {
|
|
476
509
|
context.language = info.project.__vue__?.language;
|
|
477
|
-
if (!context.language || !data.features.
|
|
510
|
+
if (!context.language || !data.features.unofficial) return;
|
|
478
511
|
const languageService = info.project.getLanguageService();
|
|
479
512
|
const methods = {};
|
|
480
513
|
for (const [key, method] of [["findReferences", findReferences_exports], ["getDefinitionAndBoundSpan", getDefinitionAndBoundSpan_exports]]) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxup/nuxt",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.0",
|
|
5
5
|
"description": "TypeScript plugin for Nuxt",
|
|
6
6
|
"author": "KazariEX",
|
|
7
7
|
"license": "MIT",
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
"files": [
|
|
16
16
|
"dist"
|
|
17
17
|
],
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"typescript": "*"
|
|
20
|
+
},
|
|
18
21
|
"dependencies": {
|
|
19
22
|
"@nuxt/kit": "^4.2.2",
|
|
20
23
|
"chokidar": "^5.0.0",
|
|
@@ -24,9 +27,9 @@
|
|
|
24
27
|
},
|
|
25
28
|
"devDependencies": {
|
|
26
29
|
"@dxup/shared": "",
|
|
27
|
-
"@volar/language-core": "^2.4.
|
|
28
|
-
"@volar/typescript": "^2.4.
|
|
29
|
-
"@vue/language-core": "^3.1
|
|
30
|
+
"@volar/language-core": "^2.4.27",
|
|
31
|
+
"@volar/typescript": "^2.4.27",
|
|
32
|
+
"@vue/language-core": "^3.2.1",
|
|
30
33
|
"nuxt": "^4.2.2",
|
|
31
34
|
"typescript": "^5.9.3"
|
|
32
35
|
},
|