@uni-helper/vite-plugin-uni-pages 0.2.3 → 0.2.5
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/dist/index.cjs +143 -80
- package/dist/index.d.ts +10 -4
- package/dist/index.mjs +141 -81
- package/package.json +9 -9
package/dist/index.cjs
CHANGED
|
@@ -7,6 +7,7 @@ const node_child_process = require('node:child_process');
|
|
|
7
7
|
const vite = require('vite');
|
|
8
8
|
const MagicString = require('magic-string');
|
|
9
9
|
const chokidar = require('chokidar');
|
|
10
|
+
const process$1 = require('node:process');
|
|
10
11
|
const unconfig = require('unconfig');
|
|
11
12
|
const uniEnv = require('@uni-helper/uni-env');
|
|
12
13
|
const Debug = require('debug');
|
|
@@ -22,6 +23,7 @@ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'defau
|
|
|
22
23
|
const path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
23
24
|
const MagicString__default = /*#__PURE__*/_interopDefaultCompat(MagicString);
|
|
24
25
|
const chokidar__default = /*#__PURE__*/_interopDefaultCompat(chokidar);
|
|
26
|
+
const process__default = /*#__PURE__*/_interopDefaultCompat(process$1);
|
|
25
27
|
const Debug__default = /*#__PURE__*/_interopDefaultCompat(Debug);
|
|
26
28
|
const fg__default = /*#__PURE__*/_interopDefaultCompat(fg);
|
|
27
29
|
const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
|
|
@@ -36,6 +38,72 @@ const RESOLVED_MODULE_ID_VIRTUAL = `\0${MODULE_ID_VIRTUAL}`;
|
|
|
36
38
|
const OUTPUT_NAME = "pages.json";
|
|
37
39
|
const FILE_EXTENSIONS = ["vue", "nvue", "uvue"];
|
|
38
40
|
|
|
41
|
+
async function parseSFC(code) {
|
|
42
|
+
try {
|
|
43
|
+
return compilerSfc.parse(code, {
|
|
44
|
+
pad: "space"
|
|
45
|
+
}).descriptor || compilerSfc.parse({
|
|
46
|
+
source: code
|
|
47
|
+
});
|
|
48
|
+
} catch {
|
|
49
|
+
throw new Error(
|
|
50
|
+
`[vite-plugin-uni-pages] Vue3's "@vue/compiler-sfc" is required.`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function parseCustomBlock(block, filePath, options) {
|
|
55
|
+
const lang = block.lang ?? options.routeBlockLang;
|
|
56
|
+
const attr = {
|
|
57
|
+
type: "page",
|
|
58
|
+
...block.attrs
|
|
59
|
+
};
|
|
60
|
+
let content;
|
|
61
|
+
debug.routeBlock(`use ${lang} parser`);
|
|
62
|
+
if (lang === "json5" || lang === "jsonc") {
|
|
63
|
+
try {
|
|
64
|
+
content = JSON5__default.parse(block.content);
|
|
65
|
+
} catch (err) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`Invalid JSON5 format of <${block.type}> content in ${filePath}
|
|
68
|
+
${err.message}`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
} else if (lang === "json") {
|
|
72
|
+
try {
|
|
73
|
+
content = JSON.parse(block.content);
|
|
74
|
+
} catch (err) {
|
|
75
|
+
throw new Error(
|
|
76
|
+
`Invalid JSON format of <${block.type}> content in ${filePath}
|
|
77
|
+
${err.message}`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
} else if (lang === "yaml" || lang === "yml") {
|
|
81
|
+
try {
|
|
82
|
+
content = yaml.parse(block.content);
|
|
83
|
+
} catch (err) {
|
|
84
|
+
throw new Error(
|
|
85
|
+
`Invalid YAML format of <${block.type}> content in ${filePath}
|
|
86
|
+
${err.message}`
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
attr,
|
|
92
|
+
content: content ?? {}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
async function getRouteSfcBlock(path) {
|
|
96
|
+
const content = fs__default.readFileSync(path, "utf8");
|
|
97
|
+
const parsedSFC = await parseSFC(content);
|
|
98
|
+
const blockStr = parsedSFC?.customBlocks.find((b) => b.type === "route");
|
|
99
|
+
return blockStr;
|
|
100
|
+
}
|
|
101
|
+
async function getRouteBlock(path, blockStr, options) {
|
|
102
|
+
if (!blockStr)
|
|
103
|
+
return;
|
|
104
|
+
return parseCustomBlock(blockStr, path, options);
|
|
105
|
+
}
|
|
106
|
+
|
|
39
107
|
function invalidatePagesModule(server) {
|
|
40
108
|
const { moduleGraph } = server;
|
|
41
109
|
const mods = moduleGraph.getModulesByFile(RESOLVED_MODULE_ID_VIRTUAL);
|
|
@@ -52,7 +120,8 @@ const debug = {
|
|
|
52
120
|
options: Debug__default("vite-plugin-uni-pages:options"),
|
|
53
121
|
pages: Debug__default("vite-plugin-uni-pages:pages"),
|
|
54
122
|
subPages: Debug__default("vite-plugin-uni-pages:subPages"),
|
|
55
|
-
error: Debug__default("vite-plugin-uni-pages:error")
|
|
123
|
+
error: Debug__default("vite-plugin-uni-pages:error"),
|
|
124
|
+
cache: Debug__default("vite-plugin-uni-pages:cache")
|
|
56
125
|
};
|
|
57
126
|
function extsToGlob(extensions) {
|
|
58
127
|
return extensions.length > 1 ? `{${extensions.join(",")}}` : extensions[0] || "";
|
|
@@ -85,6 +154,27 @@ async function getPagesConfigSourcePaths() {
|
|
|
85
154
|
absolute: true
|
|
86
155
|
});
|
|
87
156
|
}
|
|
157
|
+
function useCachedPages() {
|
|
158
|
+
const pages = /* @__PURE__ */ new Map();
|
|
159
|
+
function parseData(block) {
|
|
160
|
+
return {
|
|
161
|
+
content: block?.loc.source.trim() ?? "",
|
|
162
|
+
attr: block?.attrs ?? ""
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function setCache(filePath, routeBlock) {
|
|
166
|
+
pages.set(filePath, JSON.stringify(parseData(routeBlock)));
|
|
167
|
+
}
|
|
168
|
+
async function hasChanged(filePath, routeBlock) {
|
|
169
|
+
if (!routeBlock)
|
|
170
|
+
routeBlock = await getRouteSfcBlock(vite.normalizePath(filePath));
|
|
171
|
+
return !pages.has(filePath) || JSON.stringify(parseData(routeBlock)) !== pages.get(filePath);
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
setCache,
|
|
175
|
+
hasChanged
|
|
176
|
+
};
|
|
177
|
+
}
|
|
88
178
|
|
|
89
179
|
function resolveOptions(userOptions, viteRoot) {
|
|
90
180
|
const {
|
|
@@ -114,7 +204,7 @@ function resolveOptions(userOptions, viteRoot) {
|
|
|
114
204
|
onAfterWriteFile = () => {
|
|
115
205
|
}
|
|
116
206
|
} = userOptions;
|
|
117
|
-
const root = viteRoot || slash(
|
|
207
|
+
const root = viteRoot || slash(process__default.cwd());
|
|
118
208
|
const resolvedDirs = resolvePageDirs(dir, root, exclude);
|
|
119
209
|
const resolvedSubDirs = subPackages.map((dir2) => slash(dir2));
|
|
120
210
|
const ResolvedHomePage = typeof homePage === "string" ? [homePage] : homePage;
|
|
@@ -172,72 +262,10 @@ function writeFileSync(path, content) {
|
|
|
172
262
|
fs__default.writeFileSync(path, content, { encoding: "utf-8" });
|
|
173
263
|
}
|
|
174
264
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
return compilerSfc.parse(code, {
|
|
178
|
-
pad: "space"
|
|
179
|
-
}).descriptor || compilerSfc.parse({
|
|
180
|
-
source: code
|
|
181
|
-
});
|
|
182
|
-
} catch {
|
|
183
|
-
throw new Error(
|
|
184
|
-
`[vite-plugin-uni-pages] Vue3's "@vue/compiler-sfc" is required.`
|
|
185
|
-
);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
function parseCustomBlock(block, filePath, options) {
|
|
189
|
-
const lang = block.lang ?? options.routeBlockLang;
|
|
190
|
-
const attr = {
|
|
191
|
-
type: "page",
|
|
192
|
-
...block.attrs
|
|
193
|
-
};
|
|
194
|
-
let content;
|
|
195
|
-
debug.routeBlock(`use ${lang} parser`);
|
|
196
|
-
if (lang === "json5" || lang === "jsonc") {
|
|
197
|
-
try {
|
|
198
|
-
content = JSON5__default.parse(block.content);
|
|
199
|
-
} catch (err) {
|
|
200
|
-
throw new Error(
|
|
201
|
-
`Invalid JSON5 format of <${block.type}> content in ${filePath}
|
|
202
|
-
${err.message}`
|
|
203
|
-
);
|
|
204
|
-
}
|
|
205
|
-
} else if (lang === "json") {
|
|
206
|
-
try {
|
|
207
|
-
content = JSON.parse(block.content);
|
|
208
|
-
} catch (err) {
|
|
209
|
-
throw new Error(
|
|
210
|
-
`Invalid JSON format of <${block.type}> content in ${filePath}
|
|
211
|
-
${err.message}`
|
|
212
|
-
);
|
|
213
|
-
}
|
|
214
|
-
} else if (lang === "yaml" || lang === "yml") {
|
|
215
|
-
try {
|
|
216
|
-
content = yaml.parse(block.content);
|
|
217
|
-
} catch (err) {
|
|
218
|
-
throw new Error(
|
|
219
|
-
`Invalid YAML format of <${block.type}> content in ${filePath}
|
|
220
|
-
${err.message}`
|
|
221
|
-
);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
return {
|
|
225
|
-
attr,
|
|
226
|
-
content: content ?? {}
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
async function getRouteBlock(path, options) {
|
|
230
|
-
const content = fs__default.readFileSync(path, "utf8");
|
|
231
|
-
const parsedSFC = await parseSFC(content);
|
|
232
|
-
const blockStr = parsedSFC?.customBlocks.find((b) => b.type === "route");
|
|
233
|
-
if (!blockStr)
|
|
234
|
-
return;
|
|
235
|
-
const result = parseCustomBlock(blockStr, path, options);
|
|
236
|
-
return result;
|
|
237
|
-
}
|
|
238
|
-
|
|
265
|
+
let lsatPagesJson = "";
|
|
266
|
+
const { setCache, hasChanged } = useCachedPages();
|
|
239
267
|
class PageContext {
|
|
240
|
-
constructor(userOptions, viteRoot =
|
|
268
|
+
constructor(userOptions, viteRoot = process__default.cwd()) {
|
|
241
269
|
this.pagesPath = [];
|
|
242
270
|
this.subPagesPath = {};
|
|
243
271
|
this.pageMetaData = [];
|
|
@@ -260,10 +288,10 @@ class PageContext {
|
|
|
260
288
|
this.logger = logger;
|
|
261
289
|
}
|
|
262
290
|
async loadUserPagesConfig() {
|
|
263
|
-
const { config } = await unconfig.loadConfig({ sources: [{ files: "pages.config" }] });
|
|
291
|
+
const { config } = await unconfig.loadConfig({ cwd: this.root, sources: [{ files: "pages.config" }] });
|
|
264
292
|
if (!config) {
|
|
265
293
|
this.logger?.warn("Can't found pages.config, please create pages.config.(ts|mts|cts|js|cjs|mjs|json)");
|
|
266
|
-
|
|
294
|
+
process__default.exit(-1);
|
|
267
295
|
}
|
|
268
296
|
this.pagesGlobConfig = config;
|
|
269
297
|
debug.options(config);
|
|
@@ -295,29 +323,39 @@ class PageContext {
|
|
|
295
323
|
const configs = await getPagesConfigSourcePaths();
|
|
296
324
|
watcher.add(configs);
|
|
297
325
|
}
|
|
326
|
+
const targetDirs = [...this.options.dirs, ...this.options.subPackages].map((v) => slash(path__default.resolve(this.root, v)));
|
|
327
|
+
const isInTargetDirs = (path2) => targetDirs.some((v) => path2.startsWith(v));
|
|
298
328
|
watcher.on("add", async (path2) => {
|
|
299
329
|
path2 = slash(path2);
|
|
300
330
|
if (!isTargetFile(path2))
|
|
301
331
|
return;
|
|
332
|
+
if (!isInTargetDirs(path2))
|
|
333
|
+
return;
|
|
302
334
|
debug.pages(`File added: ${path2}`);
|
|
303
|
-
this.updatePagesJSON()
|
|
304
|
-
|
|
335
|
+
if (await this.updatePagesJSON())
|
|
336
|
+
this.onUpdate();
|
|
305
337
|
});
|
|
306
338
|
watcher.on("change", async (path2) => {
|
|
307
339
|
path2 = slash(path2);
|
|
308
340
|
if (!isTargetFile(path2) && !isConfigFile(path2))
|
|
309
341
|
return;
|
|
342
|
+
if (!isInTargetDirs(path2))
|
|
343
|
+
return;
|
|
310
344
|
debug.pages(`File changed: ${path2}`);
|
|
311
|
-
|
|
312
|
-
|
|
345
|
+
debug.pages(targetDirs);
|
|
346
|
+
debug.pages(isInTargetDirs(path2));
|
|
347
|
+
if (await this.updatePagesJSON(path2))
|
|
348
|
+
this.onUpdate();
|
|
313
349
|
});
|
|
314
350
|
watcher.on("unlink", async (path2) => {
|
|
315
351
|
path2 = slash(path2);
|
|
316
352
|
if (!isTargetFile(path2))
|
|
317
353
|
return;
|
|
354
|
+
if (!isInTargetDirs(path2))
|
|
355
|
+
return;
|
|
318
356
|
debug.pages(`File removed: ${path2}`);
|
|
319
|
-
this.updatePagesJSON()
|
|
320
|
-
|
|
357
|
+
if (await this.updatePagesJSON())
|
|
358
|
+
this.onUpdate();
|
|
321
359
|
});
|
|
322
360
|
}
|
|
323
361
|
onUpdate() {
|
|
@@ -331,7 +369,9 @@ class PageContext {
|
|
|
331
369
|
}
|
|
332
370
|
async parsePage(page) {
|
|
333
371
|
const { relativePath, absolutePath } = page;
|
|
334
|
-
const
|
|
372
|
+
const routeSfcBlock = await getRouteSfcBlock(absolutePath);
|
|
373
|
+
const routeBlock = await getRouteBlock(absolutePath, routeSfcBlock, this.options);
|
|
374
|
+
setCache(absolutePath, routeSfcBlock);
|
|
335
375
|
const relativePathWithFileName = relativePath.replace(path__default.extname(relativePath), "");
|
|
336
376
|
const pageMetaDatum = {
|
|
337
377
|
path: vite.normalizePath(relativePathWithFileName),
|
|
@@ -396,7 +436,13 @@ class PageContext {
|
|
|
396
436
|
this.subPageMetaData = subPageMetaData;
|
|
397
437
|
debug.subPages(this.subPageMetaData);
|
|
398
438
|
}
|
|
399
|
-
async updatePagesJSON() {
|
|
439
|
+
async updatePagesJSON(filepath) {
|
|
440
|
+
if (filepath) {
|
|
441
|
+
if (!await hasChanged(filepath)) {
|
|
442
|
+
debug.cache(`The route block on page ${filepath} did not send any changes, skipping`);
|
|
443
|
+
return false;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
400
446
|
checkPagesJsonFile(this.resolvedPagesJSONPath);
|
|
401
447
|
this.options.onBeforeLoadUserConfig(this);
|
|
402
448
|
await this.loadUserPagesConfig();
|
|
@@ -418,8 +464,14 @@ class PageContext {
|
|
|
418
464
|
subPackages: this.subPageMetaData
|
|
419
465
|
};
|
|
420
466
|
const pagesJson = JSON.stringify(data, null, this.options.minify ? void 0 : 2);
|
|
467
|
+
if (lsatPagesJson === pagesJson) {
|
|
468
|
+
debug.pages("PagesJson Not have change");
|
|
469
|
+
return false;
|
|
470
|
+
}
|
|
421
471
|
writeFileSync(this.resolvedPagesJSONPath, pagesJson);
|
|
472
|
+
lsatPagesJson = pagesJson;
|
|
422
473
|
this.options.onAfterWriteFile(this);
|
|
474
|
+
return true;
|
|
423
475
|
}
|
|
424
476
|
virtualModule() {
|
|
425
477
|
const pages = `export const pages = ${this.resolveRoutes()};`;
|
|
@@ -494,9 +546,9 @@ function VitePluginUniPages(userOptions = {}) {
|
|
|
494
546
|
},
|
|
495
547
|
// Applet do not support custom route block, so we need to remove the route block here
|
|
496
548
|
async transform(code, id) {
|
|
497
|
-
if (!/\.vue$/.test(id))
|
|
549
|
+
if (!/\.n?vue$/.test(id) && !code.includes("</route>"))
|
|
498
550
|
return null;
|
|
499
|
-
const s = new MagicString__default(code
|
|
551
|
+
const s = new MagicString__default(code);
|
|
500
552
|
const routeBlockMatches = s.original.matchAll(
|
|
501
553
|
/<route[^>]*>([\s\S]*?)<\/route>/g
|
|
502
554
|
);
|
|
@@ -505,7 +557,16 @@ function VitePluginUniPages(userOptions = {}) {
|
|
|
505
557
|
const length = match[0].length;
|
|
506
558
|
s.remove(index, index + length);
|
|
507
559
|
}
|
|
508
|
-
|
|
560
|
+
if (s.hasChanged()) {
|
|
561
|
+
return {
|
|
562
|
+
code: s.toString(),
|
|
563
|
+
map: s.generateMap({
|
|
564
|
+
source: code,
|
|
565
|
+
includeContent: true,
|
|
566
|
+
file: id
|
|
567
|
+
})
|
|
568
|
+
};
|
|
569
|
+
}
|
|
509
570
|
},
|
|
510
571
|
configureServer(server) {
|
|
511
572
|
ctx.setupViteServer(server);
|
|
@@ -535,6 +596,7 @@ exports.extsToGlob = extsToGlob;
|
|
|
535
596
|
exports.getPageFiles = getPageFiles;
|
|
536
597
|
exports.getPagesConfigSourcePaths = getPagesConfigSourcePaths;
|
|
537
598
|
exports.getRouteBlock = getRouteBlock;
|
|
599
|
+
exports.getRouteSfcBlock = getRouteSfcBlock;
|
|
538
600
|
exports.invalidatePagesModule = invalidatePagesModule;
|
|
539
601
|
exports.isConfigFile = isConfigFile;
|
|
540
602
|
exports.isTargetFile = isTargetFile;
|
|
@@ -543,4 +605,5 @@ exports.parseCustomBlock = parseCustomBlock;
|
|
|
543
605
|
exports.parseSFC = parseSFC;
|
|
544
606
|
exports.resolveOptions = resolveOptions;
|
|
545
607
|
exports.resolvePageDirs = resolvePageDirs;
|
|
608
|
+
exports.useCachedPages = useCachedPages;
|
|
546
609
|
exports.writeFileSync = writeFileSync;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Logger, ViteDevServer, Plugin } from 'vite';
|
|
2
2
|
import { FSWatcher } from 'chokidar';
|
|
3
3
|
import Debug from 'debug';
|
|
4
|
-
import {
|
|
4
|
+
import { SFCBlock, SFCDescriptor } from '@vue/compiler-sfc';
|
|
5
5
|
|
|
6
6
|
interface EasyCom {
|
|
7
7
|
autoscan: boolean;
|
|
@@ -660,7 +660,7 @@ declare class PageContext {
|
|
|
660
660
|
setHomePage(result: PageMetaDatum[]): true | undefined;
|
|
661
661
|
mergePageMetaData(): Promise<void>;
|
|
662
662
|
mergeSubPageMetaData(): Promise<void>;
|
|
663
|
-
updatePagesJSON(): Promise<
|
|
663
|
+
updatePagesJSON(filepath?: string): Promise<boolean>;
|
|
664
664
|
virtualModule(): string;
|
|
665
665
|
resolveRoutes(): string;
|
|
666
666
|
resolveSubRoutes(): string;
|
|
@@ -674,6 +674,7 @@ declare const debug: {
|
|
|
674
674
|
pages: Debug.Debugger;
|
|
675
675
|
subPages: Debug.Debugger;
|
|
676
676
|
error: Debug.Debugger;
|
|
677
|
+
cache: Debug.Debugger;
|
|
677
678
|
};
|
|
678
679
|
declare function extsToGlob(extensions: string[]): string;
|
|
679
680
|
declare function isTargetFile(path: string): boolean;
|
|
@@ -685,6 +686,10 @@ declare function isConfigFile(path: string): boolean;
|
|
|
685
686
|
*/
|
|
686
687
|
declare function mergePageMetaDataArray(pageMetaData: PageMetaDatum[]): PageMetaDatum[];
|
|
687
688
|
declare function getPagesConfigSourcePaths(): Promise<string[]>;
|
|
689
|
+
declare function useCachedPages(): {
|
|
690
|
+
setCache: (filePath: string, routeBlock?: SFCBlock) => void;
|
|
691
|
+
hasChanged: (filePath: string, routeBlock?: SFCBlock) => Promise<boolean>;
|
|
692
|
+
};
|
|
688
693
|
|
|
689
694
|
interface CustomBlock {
|
|
690
695
|
attr: Record<string, any>;
|
|
@@ -806,8 +811,9 @@ declare function resolvePageDirs(dir: string, root: string, exclude: string[]):
|
|
|
806
811
|
|
|
807
812
|
declare function parseSFC(code: string): Promise<SFCDescriptor>;
|
|
808
813
|
declare function parseCustomBlock(block: SFCBlock, filePath: string, options: ResolvedOptions): CustomBlock | undefined;
|
|
809
|
-
declare function
|
|
814
|
+
declare function getRouteSfcBlock(path: string): Promise<SFCBlock | undefined>;
|
|
815
|
+
declare function getRouteBlock(path: string, blockStr: SFCBlock | undefined, options: ResolvedOptions): Promise<CustomBlock | undefined>;
|
|
810
816
|
|
|
811
817
|
declare function VitePluginUniPages(userOptions?: UserOptions): Plugin;
|
|
812
818
|
|
|
813
|
-
export { Condition, ConditionItem, CustomBlock, EasyCom, FILE_EXTENSIONS, GlobalStyle, IconFont, MODULE_ID_VIRTUAL, MidButton, OUTPUT_NAME, Options, PageContext, PageMetaDatum, PagePath, PagesConfig, PreloadRule, RESOLVED_MODULE_ID_VIRTUAL, ResolvedOptions, SubPackage, SubPageMetaDatum, TabBar, TabBarItem, TheWindow, UniIdRouter, UserOptions, UserPagesConfig, VitePluginUniPages, checkPagesJsonFile, debug, debugType, VitePluginUniPages as default, defineUniPages, extsToGlob, getPageFiles, getPagesConfigSourcePaths, getRouteBlock, invalidatePagesModule, isConfigFile, isTargetFile, mergePageMetaDataArray, parseCustomBlock, parseSFC, resolveOptions, resolvePageDirs, writeFileSync };
|
|
819
|
+
export { Condition, ConditionItem, CustomBlock, EasyCom, FILE_EXTENSIONS, GlobalStyle, IconFont, MODULE_ID_VIRTUAL, MidButton, OUTPUT_NAME, Options, PageContext, PageMetaDatum, PagePath, PagesConfig, PreloadRule, RESOLVED_MODULE_ID_VIRTUAL, ResolvedOptions, SubPackage, SubPageMetaDatum, TabBar, TabBarItem, TheWindow, UniIdRouter, UserOptions, UserPagesConfig, VitePluginUniPages, checkPagesJsonFile, debug, debugType, VitePluginUniPages as default, defineUniPages, extsToGlob, getPageFiles, getPagesConfigSourcePaths, getRouteBlock, getRouteSfcBlock, invalidatePagesModule, isConfigFile, isTargetFile, mergePageMetaDataArray, parseCustomBlock, parseSFC, resolveOptions, resolvePageDirs, useCachedPages, writeFileSync };
|
package/dist/index.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import { spawn } from 'node:child_process';
|
|
|
3
3
|
import { normalizePath, createLogger } from 'vite';
|
|
4
4
|
import MagicString from 'magic-string';
|
|
5
5
|
import chokidar from 'chokidar';
|
|
6
|
+
import process$1 from 'node:process';
|
|
6
7
|
import { loadConfig } from 'unconfig';
|
|
7
8
|
import { isH5 } from '@uni-helper/uni-env';
|
|
8
9
|
import Debug from 'debug';
|
|
@@ -22,6 +23,72 @@ const RESOLVED_MODULE_ID_VIRTUAL = `\0${MODULE_ID_VIRTUAL}`;
|
|
|
22
23
|
const OUTPUT_NAME = "pages.json";
|
|
23
24
|
const FILE_EXTENSIONS = ["vue", "nvue", "uvue"];
|
|
24
25
|
|
|
26
|
+
async function parseSFC(code) {
|
|
27
|
+
try {
|
|
28
|
+
return parse(code, {
|
|
29
|
+
pad: "space"
|
|
30
|
+
}).descriptor || parse({
|
|
31
|
+
source: code
|
|
32
|
+
});
|
|
33
|
+
} catch {
|
|
34
|
+
throw new Error(
|
|
35
|
+
`[vite-plugin-uni-pages] Vue3's "@vue/compiler-sfc" is required.`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function parseCustomBlock(block, filePath, options) {
|
|
40
|
+
const lang = block.lang ?? options.routeBlockLang;
|
|
41
|
+
const attr = {
|
|
42
|
+
type: "page",
|
|
43
|
+
...block.attrs
|
|
44
|
+
};
|
|
45
|
+
let content;
|
|
46
|
+
debug.routeBlock(`use ${lang} parser`);
|
|
47
|
+
if (lang === "json5" || lang === "jsonc") {
|
|
48
|
+
try {
|
|
49
|
+
content = JSON5.parse(block.content);
|
|
50
|
+
} catch (err) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
`Invalid JSON5 format of <${block.type}> content in ${filePath}
|
|
53
|
+
${err.message}`
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
} else if (lang === "json") {
|
|
57
|
+
try {
|
|
58
|
+
content = JSON.parse(block.content);
|
|
59
|
+
} catch (err) {
|
|
60
|
+
throw new Error(
|
|
61
|
+
`Invalid JSON format of <${block.type}> content in ${filePath}
|
|
62
|
+
${err.message}`
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
} else if (lang === "yaml" || lang === "yml") {
|
|
66
|
+
try {
|
|
67
|
+
content = parse$1(block.content);
|
|
68
|
+
} catch (err) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
`Invalid YAML format of <${block.type}> content in ${filePath}
|
|
71
|
+
${err.message}`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
attr,
|
|
77
|
+
content: content ?? {}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
async function getRouteSfcBlock(path) {
|
|
81
|
+
const content = fs.readFileSync(path, "utf8");
|
|
82
|
+
const parsedSFC = await parseSFC(content);
|
|
83
|
+
const blockStr = parsedSFC?.customBlocks.find((b) => b.type === "route");
|
|
84
|
+
return blockStr;
|
|
85
|
+
}
|
|
86
|
+
async function getRouteBlock(path, blockStr, options) {
|
|
87
|
+
if (!blockStr)
|
|
88
|
+
return;
|
|
89
|
+
return parseCustomBlock(blockStr, path, options);
|
|
90
|
+
}
|
|
91
|
+
|
|
25
92
|
function invalidatePagesModule(server) {
|
|
26
93
|
const { moduleGraph } = server;
|
|
27
94
|
const mods = moduleGraph.getModulesByFile(RESOLVED_MODULE_ID_VIRTUAL);
|
|
@@ -38,7 +105,8 @@ const debug = {
|
|
|
38
105
|
options: Debug("vite-plugin-uni-pages:options"),
|
|
39
106
|
pages: Debug("vite-plugin-uni-pages:pages"),
|
|
40
107
|
subPages: Debug("vite-plugin-uni-pages:subPages"),
|
|
41
|
-
error: Debug("vite-plugin-uni-pages:error")
|
|
108
|
+
error: Debug("vite-plugin-uni-pages:error"),
|
|
109
|
+
cache: Debug("vite-plugin-uni-pages:cache")
|
|
42
110
|
};
|
|
43
111
|
function extsToGlob(extensions) {
|
|
44
112
|
return extensions.length > 1 ? `{${extensions.join(",")}}` : extensions[0] || "";
|
|
@@ -71,6 +139,27 @@ async function getPagesConfigSourcePaths() {
|
|
|
71
139
|
absolute: true
|
|
72
140
|
});
|
|
73
141
|
}
|
|
142
|
+
function useCachedPages() {
|
|
143
|
+
const pages = /* @__PURE__ */ new Map();
|
|
144
|
+
function parseData(block) {
|
|
145
|
+
return {
|
|
146
|
+
content: block?.loc.source.trim() ?? "",
|
|
147
|
+
attr: block?.attrs ?? ""
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function setCache(filePath, routeBlock) {
|
|
151
|
+
pages.set(filePath, JSON.stringify(parseData(routeBlock)));
|
|
152
|
+
}
|
|
153
|
+
async function hasChanged(filePath, routeBlock) {
|
|
154
|
+
if (!routeBlock)
|
|
155
|
+
routeBlock = await getRouteSfcBlock(normalizePath(filePath));
|
|
156
|
+
return !pages.has(filePath) || JSON.stringify(parseData(routeBlock)) !== pages.get(filePath);
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
setCache,
|
|
160
|
+
hasChanged
|
|
161
|
+
};
|
|
162
|
+
}
|
|
74
163
|
|
|
75
164
|
function resolveOptions(userOptions, viteRoot) {
|
|
76
165
|
const {
|
|
@@ -100,7 +189,7 @@ function resolveOptions(userOptions, viteRoot) {
|
|
|
100
189
|
onAfterWriteFile = () => {
|
|
101
190
|
}
|
|
102
191
|
} = userOptions;
|
|
103
|
-
const root = viteRoot || slash(process.cwd());
|
|
192
|
+
const root = viteRoot || slash(process$1.cwd());
|
|
104
193
|
const resolvedDirs = resolvePageDirs(dir, root, exclude);
|
|
105
194
|
const resolvedSubDirs = subPackages.map((dir2) => slash(dir2));
|
|
106
195
|
const ResolvedHomePage = typeof homePage === "string" ? [homePage] : homePage;
|
|
@@ -158,72 +247,10 @@ function writeFileSync(path, content) {
|
|
|
158
247
|
fs.writeFileSync(path, content, { encoding: "utf-8" });
|
|
159
248
|
}
|
|
160
249
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
return parse(code, {
|
|
164
|
-
pad: "space"
|
|
165
|
-
}).descriptor || parse({
|
|
166
|
-
source: code
|
|
167
|
-
});
|
|
168
|
-
} catch {
|
|
169
|
-
throw new Error(
|
|
170
|
-
`[vite-plugin-uni-pages] Vue3's "@vue/compiler-sfc" is required.`
|
|
171
|
-
);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
function parseCustomBlock(block, filePath, options) {
|
|
175
|
-
const lang = block.lang ?? options.routeBlockLang;
|
|
176
|
-
const attr = {
|
|
177
|
-
type: "page",
|
|
178
|
-
...block.attrs
|
|
179
|
-
};
|
|
180
|
-
let content;
|
|
181
|
-
debug.routeBlock(`use ${lang} parser`);
|
|
182
|
-
if (lang === "json5" || lang === "jsonc") {
|
|
183
|
-
try {
|
|
184
|
-
content = JSON5.parse(block.content);
|
|
185
|
-
} catch (err) {
|
|
186
|
-
throw new Error(
|
|
187
|
-
`Invalid JSON5 format of <${block.type}> content in ${filePath}
|
|
188
|
-
${err.message}`
|
|
189
|
-
);
|
|
190
|
-
}
|
|
191
|
-
} else if (lang === "json") {
|
|
192
|
-
try {
|
|
193
|
-
content = JSON.parse(block.content);
|
|
194
|
-
} catch (err) {
|
|
195
|
-
throw new Error(
|
|
196
|
-
`Invalid JSON format of <${block.type}> content in ${filePath}
|
|
197
|
-
${err.message}`
|
|
198
|
-
);
|
|
199
|
-
}
|
|
200
|
-
} else if (lang === "yaml" || lang === "yml") {
|
|
201
|
-
try {
|
|
202
|
-
content = parse$1(block.content);
|
|
203
|
-
} catch (err) {
|
|
204
|
-
throw new Error(
|
|
205
|
-
`Invalid YAML format of <${block.type}> content in ${filePath}
|
|
206
|
-
${err.message}`
|
|
207
|
-
);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
return {
|
|
211
|
-
attr,
|
|
212
|
-
content: content ?? {}
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
async function getRouteBlock(path, options) {
|
|
216
|
-
const content = fs.readFileSync(path, "utf8");
|
|
217
|
-
const parsedSFC = await parseSFC(content);
|
|
218
|
-
const blockStr = parsedSFC?.customBlocks.find((b) => b.type === "route");
|
|
219
|
-
if (!blockStr)
|
|
220
|
-
return;
|
|
221
|
-
const result = parseCustomBlock(blockStr, path, options);
|
|
222
|
-
return result;
|
|
223
|
-
}
|
|
224
|
-
|
|
250
|
+
let lsatPagesJson = "";
|
|
251
|
+
const { setCache, hasChanged } = useCachedPages();
|
|
225
252
|
class PageContext {
|
|
226
|
-
constructor(userOptions, viteRoot = process.cwd()) {
|
|
253
|
+
constructor(userOptions, viteRoot = process$1.cwd()) {
|
|
227
254
|
this.pagesPath = [];
|
|
228
255
|
this.subPagesPath = {};
|
|
229
256
|
this.pageMetaData = [];
|
|
@@ -246,10 +273,10 @@ class PageContext {
|
|
|
246
273
|
this.logger = logger;
|
|
247
274
|
}
|
|
248
275
|
async loadUserPagesConfig() {
|
|
249
|
-
const { config } = await loadConfig({ sources: [{ files: "pages.config" }] });
|
|
276
|
+
const { config } = await loadConfig({ cwd: this.root, sources: [{ files: "pages.config" }] });
|
|
250
277
|
if (!config) {
|
|
251
278
|
this.logger?.warn("Can't found pages.config, please create pages.config.(ts|mts|cts|js|cjs|mjs|json)");
|
|
252
|
-
process.exit(-1);
|
|
279
|
+
process$1.exit(-1);
|
|
253
280
|
}
|
|
254
281
|
this.pagesGlobConfig = config;
|
|
255
282
|
debug.options(config);
|
|
@@ -281,29 +308,39 @@ class PageContext {
|
|
|
281
308
|
const configs = await getPagesConfigSourcePaths();
|
|
282
309
|
watcher.add(configs);
|
|
283
310
|
}
|
|
311
|
+
const targetDirs = [...this.options.dirs, ...this.options.subPackages].map((v) => slash(path.resolve(this.root, v)));
|
|
312
|
+
const isInTargetDirs = (path2) => targetDirs.some((v) => path2.startsWith(v));
|
|
284
313
|
watcher.on("add", async (path2) => {
|
|
285
314
|
path2 = slash(path2);
|
|
286
315
|
if (!isTargetFile(path2))
|
|
287
316
|
return;
|
|
317
|
+
if (!isInTargetDirs(path2))
|
|
318
|
+
return;
|
|
288
319
|
debug.pages(`File added: ${path2}`);
|
|
289
|
-
this.updatePagesJSON()
|
|
290
|
-
|
|
320
|
+
if (await this.updatePagesJSON())
|
|
321
|
+
this.onUpdate();
|
|
291
322
|
});
|
|
292
323
|
watcher.on("change", async (path2) => {
|
|
293
324
|
path2 = slash(path2);
|
|
294
325
|
if (!isTargetFile(path2) && !isConfigFile(path2))
|
|
295
326
|
return;
|
|
327
|
+
if (!isInTargetDirs(path2))
|
|
328
|
+
return;
|
|
296
329
|
debug.pages(`File changed: ${path2}`);
|
|
297
|
-
|
|
298
|
-
|
|
330
|
+
debug.pages(targetDirs);
|
|
331
|
+
debug.pages(isInTargetDirs(path2));
|
|
332
|
+
if (await this.updatePagesJSON(path2))
|
|
333
|
+
this.onUpdate();
|
|
299
334
|
});
|
|
300
335
|
watcher.on("unlink", async (path2) => {
|
|
301
336
|
path2 = slash(path2);
|
|
302
337
|
if (!isTargetFile(path2))
|
|
303
338
|
return;
|
|
339
|
+
if (!isInTargetDirs(path2))
|
|
340
|
+
return;
|
|
304
341
|
debug.pages(`File removed: ${path2}`);
|
|
305
|
-
this.updatePagesJSON()
|
|
306
|
-
|
|
342
|
+
if (await this.updatePagesJSON())
|
|
343
|
+
this.onUpdate();
|
|
307
344
|
});
|
|
308
345
|
}
|
|
309
346
|
onUpdate() {
|
|
@@ -317,7 +354,9 @@ class PageContext {
|
|
|
317
354
|
}
|
|
318
355
|
async parsePage(page) {
|
|
319
356
|
const { relativePath, absolutePath } = page;
|
|
320
|
-
const
|
|
357
|
+
const routeSfcBlock = await getRouteSfcBlock(absolutePath);
|
|
358
|
+
const routeBlock = await getRouteBlock(absolutePath, routeSfcBlock, this.options);
|
|
359
|
+
setCache(absolutePath, routeSfcBlock);
|
|
321
360
|
const relativePathWithFileName = relativePath.replace(path.extname(relativePath), "");
|
|
322
361
|
const pageMetaDatum = {
|
|
323
362
|
path: normalizePath(relativePathWithFileName),
|
|
@@ -382,7 +421,13 @@ class PageContext {
|
|
|
382
421
|
this.subPageMetaData = subPageMetaData;
|
|
383
422
|
debug.subPages(this.subPageMetaData);
|
|
384
423
|
}
|
|
385
|
-
async updatePagesJSON() {
|
|
424
|
+
async updatePagesJSON(filepath) {
|
|
425
|
+
if (filepath) {
|
|
426
|
+
if (!await hasChanged(filepath)) {
|
|
427
|
+
debug.cache(`The route block on page ${filepath} did not send any changes, skipping`);
|
|
428
|
+
return false;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
386
431
|
checkPagesJsonFile(this.resolvedPagesJSONPath);
|
|
387
432
|
this.options.onBeforeLoadUserConfig(this);
|
|
388
433
|
await this.loadUserPagesConfig();
|
|
@@ -404,8 +449,14 @@ class PageContext {
|
|
|
404
449
|
subPackages: this.subPageMetaData
|
|
405
450
|
};
|
|
406
451
|
const pagesJson = JSON.stringify(data, null, this.options.minify ? void 0 : 2);
|
|
452
|
+
if (lsatPagesJson === pagesJson) {
|
|
453
|
+
debug.pages("PagesJson Not have change");
|
|
454
|
+
return false;
|
|
455
|
+
}
|
|
407
456
|
writeFileSync(this.resolvedPagesJSONPath, pagesJson);
|
|
457
|
+
lsatPagesJson = pagesJson;
|
|
408
458
|
this.options.onAfterWriteFile(this);
|
|
459
|
+
return true;
|
|
409
460
|
}
|
|
410
461
|
virtualModule() {
|
|
411
462
|
const pages = `export const pages = ${this.resolveRoutes()};`;
|
|
@@ -480,9 +531,9 @@ function VitePluginUniPages(userOptions = {}) {
|
|
|
480
531
|
},
|
|
481
532
|
// Applet do not support custom route block, so we need to remove the route block here
|
|
482
533
|
async transform(code, id) {
|
|
483
|
-
if (!/\.vue$/.test(id))
|
|
534
|
+
if (!/\.n?vue$/.test(id) && !code.includes("</route>"))
|
|
484
535
|
return null;
|
|
485
|
-
const s = new MagicString(code
|
|
536
|
+
const s = new MagicString(code);
|
|
486
537
|
const routeBlockMatches = s.original.matchAll(
|
|
487
538
|
/<route[^>]*>([\s\S]*?)<\/route>/g
|
|
488
539
|
);
|
|
@@ -491,7 +542,16 @@ function VitePluginUniPages(userOptions = {}) {
|
|
|
491
542
|
const length = match[0].length;
|
|
492
543
|
s.remove(index, index + length);
|
|
493
544
|
}
|
|
494
|
-
|
|
545
|
+
if (s.hasChanged()) {
|
|
546
|
+
return {
|
|
547
|
+
code: s.toString(),
|
|
548
|
+
map: s.generateMap({
|
|
549
|
+
source: code,
|
|
550
|
+
includeContent: true,
|
|
551
|
+
file: id
|
|
552
|
+
})
|
|
553
|
+
};
|
|
554
|
+
}
|
|
495
555
|
},
|
|
496
556
|
configureServer(server) {
|
|
497
557
|
ctx.setupViteServer(server);
|
|
@@ -507,4 +567,4 @@ function VitePluginUniPages(userOptions = {}) {
|
|
|
507
567
|
};
|
|
508
568
|
}
|
|
509
569
|
|
|
510
|
-
export { FILE_EXTENSIONS, MODULE_ID_VIRTUAL, OUTPUT_NAME, PageContext, RESOLVED_MODULE_ID_VIRTUAL, VitePluginUniPages, checkPagesJsonFile, debug, VitePluginUniPages as default, defineUniPages, extsToGlob, getPageFiles, getPagesConfigSourcePaths, getRouteBlock, invalidatePagesModule, isConfigFile, isTargetFile, mergePageMetaDataArray, parseCustomBlock, parseSFC, resolveOptions, resolvePageDirs, writeFileSync };
|
|
570
|
+
export { FILE_EXTENSIONS, MODULE_ID_VIRTUAL, OUTPUT_NAME, PageContext, RESOLVED_MODULE_ID_VIRTUAL, VitePluginUniPages, checkPagesJsonFile, debug, VitePluginUniPages as default, defineUniPages, extsToGlob, getPageFiles, getPagesConfigSourcePaths, getRouteBlock, getRouteSfcBlock, invalidatePagesModule, isConfigFile, isTargetFile, mergePageMetaDataArray, parseCustomBlock, parseSFC, resolveOptions, resolvePageDirs, useCachedPages, writeFileSync };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uni-helper/vite-plugin-uni-pages",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.5",
|
|
5
5
|
"description": "File system based routing for uni-app applications using Vite",
|
|
6
6
|
"author": "KeJun",
|
|
7
7
|
"license": "MIT",
|
|
@@ -32,20 +32,20 @@
|
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@uni-helper/uni-env": "^0.0.3",
|
|
35
|
-
"@vue/compiler-sfc": "^3.3.
|
|
35
|
+
"@vue/compiler-sfc": "^3.3.4",
|
|
36
36
|
"chokidar": "^3.5.3",
|
|
37
37
|
"debug": "^4.3.4",
|
|
38
|
-
"fast-glob": "^3.
|
|
38
|
+
"fast-glob": "^3.3.1",
|
|
39
39
|
"json5": "^2.2.3",
|
|
40
40
|
"lodash-unified": "^1.0.3",
|
|
41
|
-
"magic-string": "^0.30.
|
|
42
|
-
"unconfig": "^0.3.
|
|
43
|
-
"yaml": "^2.
|
|
41
|
+
"magic-string": "^0.30.2",
|
|
42
|
+
"unconfig": "^0.3.10",
|
|
43
|
+
"yaml": "^2.3.1"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@antfu/utils": "^0.7.
|
|
47
|
-
"@types/debug": "^4.1.
|
|
48
|
-
"@types/node": "^18.
|
|
46
|
+
"@antfu/utils": "^0.7.5",
|
|
47
|
+
"@types/debug": "^4.1.8",
|
|
48
|
+
"@types/node": "^18.17.1"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build": "unbuild",
|