bobe-router 0.0.66 → 0.0.68
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/bobe-router.cjs +1108 -0
- package/dist/bobe-router.cjs.map +1 -0
- package/dist/bobe-router.esm.js +980 -204
- package/dist/bobe-router.esm.js.map +1 -1
- package/dist/index.d.ts +194 -68
- package/dist/index.umd.js +978 -203
- package/dist/index.umd.js.map +1 -1
- package/dist/{plugin.cjs.js → plugin.cjs} +141 -21
- package/dist/plugin.cjs.map +1 -0
- package/dist/plugin.esm.js +141 -21
- package/dist/plugin.esm.js.map +1 -1
- package/package.json +6 -5
- package/dist/bobe-router.cjs.js +0 -333
- package/dist/bobe-router.cjs.js.map +0 -1
- package/dist/plugin.cjs.js.map +0 -1
package/dist/bobe-router.cjs.js
DELETED
|
@@ -1,333 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var aoye = require('aoye');
|
|
4
|
-
|
|
5
|
-
function compilePattern(pattern) {
|
|
6
|
-
const paramNames = [];
|
|
7
|
-
const regexStr = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/:([a-zA-Z_]\w*)/g, (_, name) => {
|
|
8
|
-
paramNames.push(name);
|
|
9
|
-
return '([^/]+)';
|
|
10
|
-
});
|
|
11
|
-
return {
|
|
12
|
-
regex: new RegExp(`^${regexStr}$`),
|
|
13
|
-
params: paramNames
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
let compiledCache = null;
|
|
17
|
-
let cacheKey = null;
|
|
18
|
-
function compileRoutes(map) {
|
|
19
|
-
if (cacheKey === map && compiledCache) return compiledCache;
|
|
20
|
-
compiledCache = Object.keys(map).filter(k => k !== '*').map(pattern => {
|
|
21
|
-
const _compilePattern = compilePattern(pattern),
|
|
22
|
-
regex = _compilePattern.regex,
|
|
23
|
-
paramNames = _compilePattern.params;
|
|
24
|
-
return {
|
|
25
|
-
pattern,
|
|
26
|
-
regex,
|
|
27
|
-
paramNames
|
|
28
|
-
};
|
|
29
|
-
});
|
|
30
|
-
if (map['*']) {
|
|
31
|
-
compiledCache.push({
|
|
32
|
-
pattern: '*',
|
|
33
|
-
regex: /.*/,
|
|
34
|
-
paramNames: []
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
cacheKey = map;
|
|
38
|
-
return compiledCache;
|
|
39
|
-
}
|
|
40
|
-
function match(path, map) {
|
|
41
|
-
const normalized = path.startsWith('/') ? path : `/${path}`;
|
|
42
|
-
for (const compiled of compileRoutes(map)) {
|
|
43
|
-
const m = normalized.match(compiled.regex);
|
|
44
|
-
if (!m) continue;
|
|
45
|
-
const params = {};
|
|
46
|
-
for (let i = 0; i < compiled.paramNames.length; i++) {
|
|
47
|
-
params[compiled.paramNames[i]] = m[i + 1];
|
|
48
|
-
}
|
|
49
|
-
return {
|
|
50
|
-
path: compiled.pattern,
|
|
51
|
-
params
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
let GlobalKey = function (GlobalKey) {
|
|
58
|
-
GlobalKey["Routes"] = "__BOBE_INIT_ROUTES__";
|
|
59
|
-
GlobalKey["Menus"] = "__BOBE_INIT_MENUS__";
|
|
60
|
-
GlobalKey["Path"] = "__BOBE_INIT_PATH__";
|
|
61
|
-
return GlobalKey;
|
|
62
|
-
}({});
|
|
63
|
-
|
|
64
|
-
function createRouteRecord(opts = {}) {
|
|
65
|
-
return {
|
|
66
|
-
import: opts.import,
|
|
67
|
-
component: opts.component,
|
|
68
|
-
status: opts.component ? 'loaded' : 'idle',
|
|
69
|
-
params: opts.params,
|
|
70
|
-
meta: opts.meta,
|
|
71
|
-
layout: opts.layout
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
class Router extends aoye.Store {
|
|
75
|
-
static [aoye.StoreIgnoreKeys] = ['routes', 'menus', 'stack', 'ready'];
|
|
76
|
-
active = null;
|
|
77
|
-
routes = {};
|
|
78
|
-
menus = [];
|
|
79
|
-
stack = [];
|
|
80
|
-
stackIndex = 0;
|
|
81
|
-
idleSet = new Set();
|
|
82
|
-
maxPreload = 3;
|
|
83
|
-
loadingCount = 0;
|
|
84
|
-
ready(cb) {
|
|
85
|
-
if (cb) {
|
|
86
|
-
if (this.#inited) {
|
|
87
|
-
cb();
|
|
88
|
-
} else {
|
|
89
|
-
this.#readyQueue.push(cb);
|
|
90
|
-
}
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
return new Promise(resolve => this.ready(resolve));
|
|
94
|
-
}
|
|
95
|
-
#inited = false;
|
|
96
|
-
#readyQueue = [];
|
|
97
|
-
constructor(opt) {
|
|
98
|
-
super();
|
|
99
|
-
const routes = opt?.routes;
|
|
100
|
-
const initialPath = opt?.initialPath;
|
|
101
|
-
this.routes = routes || globalThis[GlobalKey.Routes] || {};
|
|
102
|
-
const injectedMenus = globalThis[GlobalKey.Menus];
|
|
103
|
-
if (injectedMenus) this.menus = injectedMenus;
|
|
104
|
-
const path = initialPath || globalThis[GlobalKey.Path] || (typeof location !== 'undefined' ? location.pathname : '/');
|
|
105
|
-
this.#init(path);
|
|
106
|
-
}
|
|
107
|
-
async #init(path) {
|
|
108
|
-
this.#initIdleSet();
|
|
109
|
-
const result = match(path, this.routes);
|
|
110
|
-
if (result) {
|
|
111
|
-
const route = this.routes[result.path];
|
|
112
|
-
if (route?.component) {
|
|
113
|
-
route.status = 'loaded';
|
|
114
|
-
} else {
|
|
115
|
-
await this.#loadComponent(result.path);
|
|
116
|
-
}
|
|
117
|
-
this.active = {
|
|
118
|
-
path,
|
|
119
|
-
params: result.params,
|
|
120
|
-
component: route?.component,
|
|
121
|
-
meta: route?.meta,
|
|
122
|
-
layout: route?.layout
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
this.stack = [{
|
|
126
|
-
path,
|
|
127
|
-
params: this.active?.params ?? {}
|
|
128
|
-
}];
|
|
129
|
-
this.stackIndex = 0;
|
|
130
|
-
this.#initBrowser();
|
|
131
|
-
this.#inited = true;
|
|
132
|
-
const q = this.#readyQueue;
|
|
133
|
-
this.#readyQueue = [];
|
|
134
|
-
for (const cb of q) cb();
|
|
135
|
-
}
|
|
136
|
-
#initBrowser() {
|
|
137
|
-
if (typeof window === 'undefined') return;
|
|
138
|
-
document.addEventListener('click', this.#onClick);
|
|
139
|
-
window.addEventListener('popstate', this.#onPopstate);
|
|
140
|
-
}
|
|
141
|
-
#initIdleSet() {
|
|
142
|
-
for (const path of Object.keys(this.routes)) {
|
|
143
|
-
if (this.routes[path].status === 'idle') {
|
|
144
|
-
this.idleSet.add(path);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
if (this.active) {
|
|
148
|
-
this.idleSet.delete(this.active.path);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
async pushState(url) {
|
|
152
|
-
const result = match(url, this.routes);
|
|
153
|
-
if (!result) return;
|
|
154
|
-
const target = {
|
|
155
|
-
path: url,
|
|
156
|
-
params: result.params
|
|
157
|
-
};
|
|
158
|
-
this.stack.length = this.stackIndex + 1;
|
|
159
|
-
this.stack.push(target);
|
|
160
|
-
this.stackIndex = this.stack.length - 1;
|
|
161
|
-
await this.#navigate(target);
|
|
162
|
-
}
|
|
163
|
-
async replaceState(url) {
|
|
164
|
-
const result = match(url, this.routes);
|
|
165
|
-
if (!result) return;
|
|
166
|
-
const target = {
|
|
167
|
-
path: url,
|
|
168
|
-
params: result.params
|
|
169
|
-
};
|
|
170
|
-
this.stack[this.stackIndex] = target;
|
|
171
|
-
await this.#navigate(target, {
|
|
172
|
-
replace: true
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
async back() {
|
|
176
|
-
if (this.stackIndex <= 0) return;
|
|
177
|
-
if (!(await this.#checkGuard(this.active, 'leave'))) return;
|
|
178
|
-
const target = this.stack[this.stackIndex - 1];
|
|
179
|
-
if (!(await this.#checkGuard(target, 'enter'))) return;
|
|
180
|
-
history.back();
|
|
181
|
-
}
|
|
182
|
-
async forward() {
|
|
183
|
-
if (this.stackIndex >= this.stack.length - 1) return;
|
|
184
|
-
if (!(await this.#checkGuard(this.active, 'leave'))) return;
|
|
185
|
-
const target = this.stack[this.stackIndex + 1];
|
|
186
|
-
if (!(await this.#checkGuard(target, 'enter'))) return;
|
|
187
|
-
history.forward();
|
|
188
|
-
}
|
|
189
|
-
async go(delta) {
|
|
190
|
-
if (delta === 0) return;
|
|
191
|
-
const newIdx = this.stackIndex + delta;
|
|
192
|
-
if (newIdx < 0 || newIdx >= this.stack.length) return;
|
|
193
|
-
if (!(await this.#checkGuard(this.active, 'leave'))) return;
|
|
194
|
-
if (!(await this.#checkGuard(this.stack[newIdx], 'enter'))) return;
|
|
195
|
-
history.go(delta);
|
|
196
|
-
}
|
|
197
|
-
navId = 0;
|
|
198
|
-
async #navigate(target, opts = {}) {
|
|
199
|
-
const id = ++this.navId;
|
|
200
|
-
if (!(await this.#checkGuard(this.active, 'leave'))) return;
|
|
201
|
-
if (id !== this.navId) return;
|
|
202
|
-
if (!(await this.#checkGuard(target, 'enter'))) return;
|
|
203
|
-
if (id !== this.navId) return;
|
|
204
|
-
if (this.active && this.stack[this.stackIndex]) {
|
|
205
|
-
this.stack[this.stackIndex].scroll = window.scrollY;
|
|
206
|
-
}
|
|
207
|
-
if (!opts.replace) {
|
|
208
|
-
history.pushState(null, '', target.path);
|
|
209
|
-
} else {
|
|
210
|
-
history.replaceState(null, '', target.path);
|
|
211
|
-
}
|
|
212
|
-
await this.#loadComponent(target.path);
|
|
213
|
-
if (id !== this.navId) return;
|
|
214
|
-
const route = this.routes[target.path];
|
|
215
|
-
target.component = route?.component;
|
|
216
|
-
target.meta = route?.meta;
|
|
217
|
-
target.layout = route?.layout;
|
|
218
|
-
this.active = target;
|
|
219
|
-
const hash = new URL(target.path, location.origin).hash;
|
|
220
|
-
if (hash) {
|
|
221
|
-
const el = document.querySelector(decodeURIComponent(hash));
|
|
222
|
-
if (el) el.scrollIntoView({
|
|
223
|
-
behavior: 'smooth'
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
this.#preloadNext();
|
|
227
|
-
}
|
|
228
|
-
async #checkGuard(entry, type) {
|
|
229
|
-
if (type === 'enter' && this.enterGuard) {
|
|
230
|
-
const result = await this.enterGuard(entry);
|
|
231
|
-
if (result === false) return false;
|
|
232
|
-
if (typeof result === 'object' && !result.ok) return false;
|
|
233
|
-
}
|
|
234
|
-
if (type === 'leave' && this.leaveGuard) {
|
|
235
|
-
const result = await this.leaveGuard(entry);
|
|
236
|
-
if (result === false) return false;
|
|
237
|
-
if (typeof result === 'object' && !result.ok) return false;
|
|
238
|
-
}
|
|
239
|
-
return true;
|
|
240
|
-
}
|
|
241
|
-
async #loadComponent(path) {
|
|
242
|
-
const route = this.routes[path];
|
|
243
|
-
if (!route) return undefined;
|
|
244
|
-
switch (route.status) {
|
|
245
|
-
case 'loaded':
|
|
246
|
-
return route.component;
|
|
247
|
-
case 'loading':
|
|
248
|
-
return route.promise;
|
|
249
|
-
}
|
|
250
|
-
if (!route.import) {
|
|
251
|
-
throw new Error(`Route "${path}" has no import function`);
|
|
252
|
-
}
|
|
253
|
-
this.idleSet.delete(path);
|
|
254
|
-
route.status = 'loading';
|
|
255
|
-
route.promise = route.import().then(mod => {
|
|
256
|
-
const Comp = mod.default || mod;
|
|
257
|
-
route.status = 'loaded';
|
|
258
|
-
route.component = Comp;
|
|
259
|
-
if (!route.meta && mod.routeMeta) {
|
|
260
|
-
route.meta = mod.routeMeta;
|
|
261
|
-
}
|
|
262
|
-
if (!route.layout && mod.layout) {
|
|
263
|
-
route.layout = mod.layout;
|
|
264
|
-
}
|
|
265
|
-
return route.component;
|
|
266
|
-
}).catch(err => {
|
|
267
|
-
route.status = 'error';
|
|
268
|
-
throw err;
|
|
269
|
-
}).finally(() => {
|
|
270
|
-
this.loadingCount--;
|
|
271
|
-
this.#preloadNext();
|
|
272
|
-
});
|
|
273
|
-
return route.promise;
|
|
274
|
-
}
|
|
275
|
-
#preloadNext() {
|
|
276
|
-
while (this.loadingCount < this.maxPreload && this.idleSet.size > 0) {
|
|
277
|
-
const path = this.idleSet.values().next().value;
|
|
278
|
-
this.loadingCount++;
|
|
279
|
-
const scheduler = typeof requestIdleCallback !== 'undefined' ? requestIdleCallback : fn => setTimeout(fn, 0);
|
|
280
|
-
scheduler(() => {
|
|
281
|
-
this.#loadComponent(path);
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
#onClick = e => {
|
|
286
|
-
const link = e.target.closest('a');
|
|
287
|
-
if (!link) return;
|
|
288
|
-
const href = link.getAttribute('href');
|
|
289
|
-
if (!href) return;
|
|
290
|
-
if (href.startsWith('#')) return;
|
|
291
|
-
try {
|
|
292
|
-
const url = new URL(href, location.origin);
|
|
293
|
-
if (url.origin !== location.origin) return;
|
|
294
|
-
if (link.target === '_blank') return;
|
|
295
|
-
if (link.hasAttribute('download')) return;
|
|
296
|
-
if (e.ctrlKey || e.metaKey || e.shiftKey) return;
|
|
297
|
-
e.preventDefault();
|
|
298
|
-
this.pushState(url.pathname + url.search + url.hash);
|
|
299
|
-
} catch {}
|
|
300
|
-
};
|
|
301
|
-
#onPopstate = () => {
|
|
302
|
-
const current = location.pathname + location.search;
|
|
303
|
-
const idx = this.stack.findLastIndex(r => r.path === current);
|
|
304
|
-
if (idx !== -1) {
|
|
305
|
-
if (idx === this.stackIndex) return;
|
|
306
|
-
this.stackIndex = idx;
|
|
307
|
-
const entry = this.stack[idx];
|
|
308
|
-
this.#navigate(entry, {
|
|
309
|
-
replace: true
|
|
310
|
-
});
|
|
311
|
-
if (entry.scroll != null) {
|
|
312
|
-
window.scrollTo(0, entry.scroll);
|
|
313
|
-
}
|
|
314
|
-
} else {
|
|
315
|
-
const result = match(current, this.routes);
|
|
316
|
-
const route = result ? this.routes[result.path] : undefined;
|
|
317
|
-
const entry = {
|
|
318
|
-
path: current,
|
|
319
|
-
params: result?.params ?? {},
|
|
320
|
-
meta: route?.meta,
|
|
321
|
-
layout: route?.layout
|
|
322
|
-
};
|
|
323
|
-
this.stack = [entry];
|
|
324
|
-
this.stackIndex = 0;
|
|
325
|
-
this.active = entry;
|
|
326
|
-
}
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
exports.Router = Router;
|
|
331
|
-
exports.createRouteRecord = createRouteRecord;
|
|
332
|
-
exports.match = match;
|
|
333
|
-
//# sourceMappingURL=bobe-router.cjs.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bobe-router.cjs.js","sources":["../src/match.ts","../src/global.ts","../src/router.ts"],"sourcesContent":["import type { RouteMap, MatchResult } from './type';\n\n/** 编译路径模式为正则:/post/:id → ^\\/post\\/([^/]+)$,捕获名为 id */\nfunction compilePattern(pattern: string): { regex: RegExp; params: string[] } {\n const paramNames: string[] = [];\n const regexStr = pattern\n .replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&') // 转义正则特殊字符\n .replace(/:([a-zA-Z_]\\w*)/g, (_, name) => {\n paramNames.push(name);\n return '([^/]+)';\n });\n return {\n regex: new RegExp(`^${regexStr}$`),\n params: paramNames,\n };\n}\n\n/** 预编译所有路由的正则 */\ntype CompiledRoute = {\n pattern: string;\n regex: RegExp;\n paramNames: string[];\n};\n\nlet compiledCache: CompiledRoute[] | null = null;\nlet cacheKey: RouteMap | null = null;\n\nfunction compileRoutes(map: RouteMap): CompiledRoute[] {\n if (cacheKey === map && compiledCache) return compiledCache;\n compiledCache = Object.keys(map)\n .filter((k) => k !== '*') // 通配符最后匹配\n .map((pattern) => {\n const { regex, params: paramNames } = compilePattern(pattern);\n return { pattern, regex, paramNames };\n });\n // 通配符路由放最后\n if (map['*']) {\n compiledCache.push({ pattern: '*', regex: /.*/, paramNames: [] });\n }\n cacheKey = map;\n return compiledCache;\n}\n\n/**\n * 根据路径匹配路由表\n * @param path - URL 路径,如 /post/42\n * @param map - 路由表\n * @returns 匹配结果,含路径参数;null 表示 404\n */\nexport function match(path: string, map: RouteMap): MatchResult | null {\n // 确保以 / 开头\n const normalized = path.startsWith('/') ? path : `/${path}`;\n\n for (const compiled of compileRoutes(map)) {\n const m = normalized.match(compiled.regex);\n if (!m) continue;\n\n const params: Record<string, string> = {};\n for (let i = 0; i < compiled.paramNames.length; i++) {\n params[compiled.paramNames[i]] = m[i + 1];\n }\n return { path: compiled.pattern, params };\n }\n return null;\n}\n","/** 通过 globalThis 传递的路由全局变量名 */\nexport enum GlobalKey {\n /** 路由表:{ [url]: { import/component } } */\n Routes = '__BOBE_INIT_ROUTES__',\n /** 菜单树:Menu[] */\n Menus = '__BOBE_INIT_MENUS__',\n /** 初始路径 */\n Path = '__BOBE_INIT_PATH__',\n}\n","import { Store, StoreIgnoreKeys } from 'aoye';\nimport type { RouteMap, RouteEntry, RouteRecord, GuardResult, Menu, RouterOptions } from './type';\nimport { match } from './match';\nimport { GlobalKey } from './global';\n\n/** 创建带初始数据的 RouteRecord */\nexport function createRouteRecord(\n opts: Partial<Pick<RouteRecord, 'import' | 'component' | 'params' | 'meta' | 'layout'>> = {}\n): RouteRecord {\n return {\n import: opts.import,\n component: opts.component,\n status: opts.component ? 'loaded' : 'idle',\n params: opts.params,\n meta: opts.meta,\n layout: opts.layout,\n };\n}\n\nexport class Router extends Store {\n static [StoreIgnoreKeys] = ['routes', 'menus', 'stack', 'ready'] as string[];\n\n /** 当前激活的路由,模板用 {active.component} 渲染 */\n active: RouteEntry | null = null;\n\n /** 路由表 */\n routes: RouteMap = {};\n\n /** 目录嵌套菜单 */\n menus: Menu[] = [];\n\n /** 进入守卫 */\n enterGuard?: (to: RouteEntry) => GuardResult | Promise<GuardResult>;\n\n /** 离开守卫 */\n leaveGuard?: (from: RouteEntry) => GuardResult | Promise<GuardResult>;\n\n /** 历史栈(不响应式) */\n private stack: RouteEntry[] = [];\n private stackIndex = 0;\n\n /** 待预加载的路径集合 */\n private idleSet = new Set<string>();\n\n /** 最大并行预加载数 */\n maxPreload = 3;\n\n /** 当前正在加载的组件数 */\n private loadingCount = 0;\n\n /**\n * 注册首屏就绪回调。\n * - 已初始化 → 同步执行 cb\n * - 未初始化 → 入队,首屏加载完成后执行\n * 支持多次调用。\n * 无参数时返回 Promise。\n */\n ready(): Promise<void>;\n ready(cb: () => void): void;\n ready(cb?: () => void): Promise<void> | void {\n if (cb) {\n if (this.#inited) { cb(); }\n else { this.#readyQueue.push(cb); }\n return;\n }\n return new Promise<void>(resolve => this.ready(resolve));\n }\n\n #inited = false;\n #readyQueue: (() => void)[] = [];\n\n constructor(opt?: RouterOptions) {\n super();\n\n const routes = opt?.routes;\n const initialPath = opt?.initialPath;\n\n // 1. routes 优先级:用户传入 > SSR 注入 > 空\n this.routes = routes\n || (globalThis as any)[GlobalKey.Routes]\n || {};\n\n // 2. menus 优先级:SSR 注入 > 空\n const injectedMenus = (globalThis as any)[GlobalKey.Menus];\n if (injectedMenus) this.menus = injectedMenus;\n\n // 3. path 优先级:用户传入 > SSR 注入 > location > '/'\n const path = initialPath\n || (globalThis as any)[GlobalKey.Path]\n || (typeof location !== 'undefined' ? location.pathname : '/');\n\n this.#init(path);\n }\n\n // ====== 初始化 ======\n async #init(path: string): Promise<void> {\n\n // 1. 初始化 idleSet(在加载首屏前,让预加载尽早启动)\n this.#initIdleSet();\n\n // 2. 首屏:匹配路由,已有 component 则跳过 load\n const result = match(path, this.routes);\n if (result) {\n const route = this.routes[result.path];\n\n if (route?.component) {\n // SSR 注入或构造函数传入的 component,直接复用\n route.status = 'loaded';\n } else {\n await this.#loadComponent(result.path);\n }\n\n this.active = {\n path,\n params: result.params,\n component: route?.component,\n meta: route?.meta,\n layout: route?.layout,\n };\n }\n\n this.stack = [{ path, params: this.active?.params ?? {} }];\n this.stackIndex = 0;\n this.#initBrowser();\n\n // 就绪:执行所有排队回调\n this.#inited = true;\n const q = this.#readyQueue;\n this.#readyQueue = [];\n for (const cb of q) cb();\n }\n\n // ====== 浏览器初始化 ======\n\n #initBrowser(): void {\n if (typeof window === 'undefined') return;\n\n // 劫持容器内链接点击\n document.addEventListener('click', this.#onClick);\n\n // 浏览器前进/后退\n window.addEventListener('popstate', this.#onPopstate);\n }\n\n #initIdleSet(): void {\n for (const path of Object.keys(this.routes)) {\n if (this.routes[path].status === 'idle') {\n this.idleSet.add(path);\n }\n }\n // 移除首屏路径\n if (this.active) {\n this.idleSet.delete(this.active.path);\n }\n }\n\n // ====== 五个公开方法 ======\n\n /** 导航到新页面(追加历史记录) */\n async pushState(url: string): Promise<void> {\n const result = match(url, this.routes);\n if (!result) return;\n\n const target: RouteEntry = { path: url, params: result.params };\n // 截断当前位置之后的历史,再追加\n this.stack.length = this.stackIndex + 1;\n this.stack.push(target);\n this.stackIndex = this.stack.length - 1;\n await this.#navigate(target);\n }\n\n /** 替换当前页面(不追加历史记录) */\n async replaceState(url: string): Promise<void> {\n const result = match(url, this.routes);\n if (!result) return;\n\n const target: RouteEntry = { path: url, params: result.params };\n this.stack[this.stackIndex] = target;\n await this.#navigate(target, { replace: true });\n }\n\n /** 后退 */\n async back(): Promise<void> {\n if (this.stackIndex <= 0) return;\n if (!(await this.#checkGuard(this.active!, 'leave'))) return;\n\n const target = this.stack[this.stackIndex - 1];\n if (!(await this.#checkGuard(target, 'enter'))) return;\n\n history.back(); // popstate 触发 Index 同步\n }\n\n /** 前进 */\n async forward(): Promise<void> {\n if (this.stackIndex >= this.stack.length - 1) return;\n if (!(await this.#checkGuard(this.active!, 'leave'))) return;\n\n const target = this.stack[this.stackIndex + 1];\n if (!(await this.#checkGuard(target, 'enter'))) return;\n\n history.forward(); // popstate 触发 Index 同步\n }\n\n /** 跳转多步 */\n async go(delta: number): Promise<void> {\n if (delta === 0) return;\n const newIdx = this.stackIndex + delta;\n if (newIdx < 0 || newIdx >= this.stack.length) return;\n\n if (!(await this.#checkGuard(this.active!, 'leave'))) return;\n if (!(await this.#checkGuard(this.stack[newIdx], 'enter'))) return;\n\n history.go(delta);\n }\n\n // ====== 内部实现 ======\n\n private navId = 0;\n\n async #navigate(target: RouteEntry, opts: { replace?: boolean } = {}): Promise<void> {\n const id = ++this.navId;\n\n if (!(await this.#checkGuard(this.active!, 'leave'))) return;\n if (id !== this.navId) return; // 守卫期间有新导航,丢弃本次\n if (!(await this.#checkGuard(target, 'enter'))) return;\n if (id !== this.navId) return;\n\n // 保存当前页滚动位置\n if (this.active && this.stack[this.stackIndex]) {\n this.stack[this.stackIndex].scroll = window.scrollY;\n }\n\n if (!opts.replace) {\n history.pushState(null, '', target.path);\n } else {\n history.replaceState(null, '', target.path);\n }\n\n // 加载组件\n await this.#loadComponent(target.path);\n if (id !== this.navId) return; // 加载期间有新导航,丢弃本次\n\n const route = this.routes[target.path];\n target.component = route?.component;\n target.meta = route?.meta;\n target.layout = route?.layout;\n this.active = target;\n\n // hash 滚动\n const hash = new URL(target.path, location.origin).hash;\n if (hash) {\n const el = document.querySelector(decodeURIComponent(hash));\n if (el) (el as HTMLElement).scrollIntoView({ behavior: 'smooth' });\n }\n\n this.#preloadNext();\n }\n\n async #checkGuard(\n entry: RouteEntry,\n type: 'enter' | 'leave'\n ): Promise<boolean> {\n if (type === 'enter' && this.enterGuard) {\n const result = await this.enterGuard(entry);\n if (result === false) return false;\n if (typeof result === 'object' && !result.ok) return false;\n }\n if (type === 'leave' && this.leaveGuard) {\n const result = await this.leaveGuard(entry);\n if (result === false) return false;\n if (typeof result === 'object' && !result.ok) return false;\n }\n return true;\n }\n\n // ====== 组件异步加载 ======\n\n async #loadComponent(path: string): Promise<any> {\n const route = this.routes[path];\n if (!route) return undefined;\n\n switch (route.status) {\n case 'loaded':\n return route.component;\n case 'loading':\n return route.promise;\n case 'error':\n break; // 可重试\n case 'idle':\n break;\n }\n\n if (!route.import) {\n throw new Error(`Route \"${path}\" has no import function`);\n }\n\n this.idleSet.delete(path);\n route.status = 'loading';\n route.promise = route\n .import()\n .then((mod: any) => {\n const Comp = mod.default || mod;\n route.status = 'loaded';\n route.component = Comp;\n // 从模块 named export 提取 routeMeta(构建时未提取到时的回退)\n if (!route.meta && mod.routeMeta) {\n route.meta = mod.routeMeta;\n }\n // 从模块 named export 提取 layout(若未显式设置)\n if (!route.layout && mod.layout) {\n route.layout = mod.layout;\n }\n return route.component;\n })\n .catch((err) => {\n route.status = 'error';\n throw err;\n })\n .finally(() => {\n this.loadingCount--;\n this.#preloadNext();\n });\n\n return route.promise;\n }\n\n // ====== 空闲预加载 ======\n\n #preloadNext(): void {\n while (this.loadingCount < this.maxPreload && this.idleSet.size > 0) {\n const path = this.idleSet.values().next().value!;\n this.loadingCount++;\n const scheduler =\n typeof requestIdleCallback !== 'undefined'\n ? requestIdleCallback\n : (fn: () => void) => setTimeout(fn, 0);\n scheduler(() => {\n this.#loadComponent(path);\n });\n }\n }\n\n // ====== 链接劫持 ======\n\n #onClick = (e: MouseEvent): void => {\n const link = (e.target as Element).closest('a');\n if (!link) return;\n\n const href = link.getAttribute('href');\n if (!href) return;\n\n // 纯 hash 链接放行,浏览器原生处理滚动\n if (href.startsWith('#')) return;\n\n try {\n const url = new URL(href, location.origin);\n // 外部链接不拦截\n if (url.origin !== location.origin) return;\n // 新窗口、下载、快捷键不拦截\n if (link.target === '_blank') return;\n if (link.hasAttribute('download')) return;\n if (e.ctrlKey || e.metaKey || e.shiftKey) return;\n\n e.preventDefault();\n this.pushState(url.pathname + url.search + url.hash);\n } catch {\n // 无效 URL,不拦截\n }\n };\n\n // ====== popstate 回调 ======\n\n #onPopstate = (): void => {\n const current = location.pathname + location.search;\n const idx = this.stack.findLastIndex((r) => r.path === current);\n\n if (idx !== -1) {\n // 仅 hash 变化,浏览器已更新 URL 并处理滚动,跳过 #navigate(避免 replaceState 抹掉 hash)\n if (idx === this.stackIndex) return;\n // 在栈中 → Router 产生的历史,移动指针\n this.stackIndex = idx;\n const entry = this.stack[idx];\n this.#navigate(entry, { replace: true });\n // 恢复滚动位置\n if (entry.scroll != null) {\n window.scrollTo(0, entry.scroll);\n }\n } else {\n // 不在栈中 → 外部跳转,重置栈\n const result = match(current, this.routes);\n const route = result ? this.routes[result.path] : undefined;\n const entry: RouteEntry = {\n path: current,\n params: result?.params ?? {},\n meta: route?.meta,\n layout: route?.layout,\n };\n this.stack = [entry];\n this.stackIndex = 0;\n this.active = entry;\n }\n };\n}\n"],"names":["compilePattern","pattern","paramNames","regexStr","replace","_","name","push","regex","RegExp","params","compiledCache","cacheKey","compileRoutes","map","Object","keys","filter","k","_compilePattern","match","path","normalized","startsWith","compiled","m","i","length","GlobalKey","createRouteRecord","opts","import","component","status","meta","layout","Router","Store","StoreIgnoreKeys","active","routes","menus","stack","stackIndex","idleSet","Set","maxPreload","loadingCount","ready","cb","Promise","resolve","constructor","opt","initialPath","globalThis","Routes","injectedMenus","Menus","Path","location","pathname","#init","result","route","q","#initBrowser","window","document","addEventListener","#initIdleSet","add","delete","pushState","url","target","replaceState","back","history","forward","go","delta","newIdx","navId","#navigate","id","scroll","scrollY","hash","URL","origin","el","querySelector","decodeURIComponent","scrollIntoView","behavior","#checkGuard","entry","type","enterGuard","ok","leaveGuard","#loadComponent","undefined","promise","Error","then","mod","Comp","default","routeMeta","catch","err","finally","#preloadNext","size","values","next","value","scheduler","requestIdleCallback","fn","setTimeout","e","link","closest","href","getAttribute","hasAttribute","ctrlKey","metaKey","shiftKey","preventDefault","search","#onPopstate","current","idx","findLastIndex","r","scrollTo"],"mappings":"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"}
|
package/dist/plugin.cjs.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.cjs.js","sources":["../src/plugin/scan.ts","../src/global.ts","../src/plugin/generate.ts","../src/plugin/index.ts"],"sourcesContent":["import { Menu } from '#/type';\nimport { Dirent, readdirSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport matter from 'gray-matter';\n\nexport interface ScanItem {\n url: string;\n file: string;\n menuName?: string;\n /** routeMeta 对象字面量源文(用于嵌入生成代码) */\n metaRaw?: string;\n}\n\nconst RE_DIR = /^(?:(\\d+)_)?([^_]+?)(?:_(.+?))?$/;\n\nconst DEFAULT_EXTENSIONS = ['js', 'jsx', 'ts', 'tsx'];\n\nfunction buildFileRegex(extensions: string[]): RegExp {\n const exts = extensions.map(e => e.replace(/^\\./, '')).join('|');\n return new RegExp(`^(?:(\\\\d+)_)?([^_]+?)(?:_(.*))?\\\\.(${exts})$`);\n}\n\nfunction buildUrl(base: string, part: string): string {\n return (base === '/' ? '' : base) + '/' + part.replace(/\\./g, '/');\n}\n\n/**\n * 从页面文件源文中提取 `export const routeMeta = {...}`。\n * 返回 { raw: 源文, value: 求值后的对象 },无导出时返回 undefined。\n */\nfunction extractRouteMeta(filePath: string): { raw: string; value: Record<string, any> } | undefined {\n try {\n const ext = filePath.split('.').pop()?.toLowerCase();\n\n // .md/.mdx:解析 YAML frontmatter 中的 meta 字段\n if (ext === 'md' || ext === 'mdx') {\n const content = readFileSync(filePath, 'utf-8');\n const { data } = matter(content);\n if (!data.meta || typeof data.meta !== 'object') return undefined;\n const meta = data.meta as Record<string, any>;\n return { raw: JSON.stringify(meta), value: meta };\n }\n\n const content = readFileSync(filePath, 'utf-8');\n // 匹配 export const routeMeta(兼容 TS 类型标注 `: SomeType`)\n const metaExportRe = /export\\s+const\\s+routeMeta(\\s*:\\s*[\\w.]+(?:\\s*<[^>]*>)?)?\\s*=\\s*/;\n const match = content.match(metaExportRe);\n if (!match) return undefined;\n\n const startIdx = match.index! + match[0].length;\n let braceDepth = 0;\n let inString = false;\n let stringChar: string | null = null;\n let endIdx = startIdx;\n\n for (let i = startIdx; i < content.length; i++) {\n const ch = content[i];\n const prev = i > 0 ? content[i - 1] : '';\n\n // 字符串状态跟踪,避免字符串内的括号干扰\n if (!inString && (ch === '\"' || ch === \"'\" || ch === '`')) {\n inString = true;\n stringChar = ch;\n } else if (inString && ch === stringChar && prev !== '\\\\') {\n inString = false;\n stringChar = null;\n }\n\n if (!inString) {\n if (ch === '{') braceDepth++;\n else if (ch === '}') {\n braceDepth--;\n if (braceDepth === 0) {\n endIdx = i + 1;\n break;\n }\n }\n }\n }\n\n const raw = content.slice(startIdx, endIdx).trim();\n if (!raw) return undefined;\n\n // 尝试求值为 JS 对象(用于 Menu)\n let value: Record<string, any> | undefined;\n try {\n value = new Function('return ' + raw)() as Record<string, any>;\n } catch {\n // 求值失败(如 import 引用),Menu 无 meta 但仍返回 raw 用于嵌入路由表\n }\n\n return { raw, value: value || {} };\n } catch {\n return undefined;\n }\n}\n\n/**\n * 检测文件是否有 default 导出(即有组件),还是仅导出 routeMeta。\n * .ts/.js: 检查是否有 `export default`\n * .md/.mdx: 检查 frontmatter 之后是否有实际 markdown 内容\n */\nfunction hasDefaultExport(filePath: string): boolean {\n try {\n const ext = filePath.split('.').pop()?.toLowerCase();\n\n if (ext === 'md' || ext === 'mdx') {\n const content = readFileSync(filePath, 'utf-8');\n const { content: mdContent } = matter(content);\n return mdContent.trim().length > 0;\n }\n\n // .ts/.js/.tsx/.jsx:检查 export default\n const content = readFileSync(filePath, 'utf-8');\n return /export\\s+default\\s/.test(content);\n } catch {\n return false;\n }\n}\n\nfunction parseEntry(name: string, fileRe: RegExp): { order: number; pathPart: string; menuName?: string } | null {\n const dirMatch = name.match(RE_DIR);\n const isDir = !name.includes('.');\n\n if (isDir && dirMatch) {\n const [, orderStr, pathPart, menuName] = dirMatch;\n return { order: orderStr ? parseInt(orderStr, 10) : Infinity, pathPart, menuName };\n }\n\n const fileMatch = name.match(fileRe);\n if (fileMatch) {\n const [, orderStr, pathPart, menuName] = fileMatch;\n return { order: orderStr ? parseInt(orderStr, 10) : Infinity, pathPart, menuName };\n }\n\n return null;\n}\n\nfunction sortEntries(entries: Dirent[], fileRe: RegExp): Dirent[] {\n return entries.sort((a, b) => {\n const pa = parseEntry(a.name, fileRe);\n const pb = parseEntry(b.name, fileRe);\n const oa = pa?.order ?? Infinity;\n const ob = pb?.order ?? Infinity;\n if (oa !== ob) return oa - ob;\n return a.name.localeCompare(b.name);\n });\n}\n\nexport function scanDir(\n absDir: string,\n basePath = absDir,\n parentPath = '',\n menuRef?: Menu,\n extensions: string[] = DEFAULT_EXTENSIONS\n): { routes: ScanItem[]; menus: Menu[] } {\n const routes: ScanItem[] = [];\n const menus: Menu[] = [];\n let entries: Dirent[];\n const fileRe = buildFileRegex(extensions);\n\n try {\n entries = readdirSync(absDir, { withFileTypes: true });\n } catch {\n return { routes, menus };\n }\n\n entries = sortEntries(entries, fileRe);\n\n for (const ent of entries) {\n const full = join(absDir, ent.name);\n const parsed = parseEntry(ent.name, fileRe);\n if (!parsed) continue;\n\n const { pathPart, menuName } = parsed;\n\n if (ent.isDirectory()) {\n const urlPath = buildUrl(parentPath, pathPart);\n const menu: Menu = {\n name: menuName || pathPart,\n hasComponent: false,\n children: []\n };\n const child = scanDir(full, basePath, urlPath, menu, extensions);\n routes.push(...child.routes);\n menu.children = child.menus;\n menus.push(menu);\n } else if (ent.isFile()) {\n const isIndex = pathPart === 'index';\n const relFile = '/' + full.slice(basePath.length).replace(/^[/\\\\]/, '');\n const urlPath = buildUrl(parentPath, pathPart);\n\n // 提取 routeMeta\n const metaResult = extractRouteMeta(full);\n const metaRaw = metaResult?.raw;\n const meta = metaResult?.value && Object.keys(metaResult.value).length > 0\n ? metaResult.value\n : undefined;\n\n // 检测是否有 default 导出(有组件 = 有路由页面)\n const hasComp = hasDefaultExport(full);\n\n if (isIndex) {\n const url = parentPath || '/';\n\n // 仅有 routeMeta 无 default 导出的文件不加入路由表\n if (hasComp) {\n routes.push({ url, file: relFile, menuName, metaRaw });\n }\n\n if (menuRef) {\n // 直接修改父菜单,不走 push\n if (menuName) menuRef.name = menuName;\n if (hasComp) {\n menuRef.path = url;\n menuRef.hasComponent = true;\n }\n if (meta) menuRef.meta = meta;\n } else if (menuName) {\n menus.push({ name: menuName, path: hasComp ? '/' : undefined, hasComponent: hasComp, children: [], meta });\n }\n } else {\n if (hasComp) {\n routes.push({ url: urlPath, file: relFile, menuName, metaRaw });\n }\n if (menuName || meta) {\n menus.push({ name: menuName || pathPart, path: hasComp ? urlPath : undefined, hasComponent: hasComp, meta });\n }\n }\n }\n }\n\n return { routes, menus };\n}\n","/** 通过 globalThis 传递的路由全局变量名 */\nexport enum GlobalKey {\n /** 路由表:{ [url]: { import/component } } */\n Routes = '__BOBE_INIT_ROUTES__',\n /** 菜单树:Menu[] */\n Menus = '__BOBE_INIT_MENUS__',\n /** 初始路径 */\n Path = '__BOBE_INIT_PATH__',\n}\n","import { GlobalKey } from '#/global';\nimport { Menu } from '#/type';\nimport type { ScanItem } from './scan';\n\nconst { Routes, Menus } = GlobalKey;\n\nexport function generateCsrInit(items: ScanItem[]): string {\n const entries = items.map(({ url, file, metaRaw }) => {\n const metaPart = metaRaw ? `, meta: ${metaRaw}` : '';\n return ` '${url}': { import: () => import('${file}')${metaPart} }`;\n });\n return `globalThis['${Routes}'] = {\\n` + entries.join(',\\n') + '\\n};';\n}\n\nexport function generateSsgInit(items: ScanItem[]): string {\n const imports = items.map(({ file }, i) =>\n `import * as __module_${i} from '${file}';`\n );\n const names = items.map((_, i) => `__module_${i}.default`);\n const entries = items.map(({ url, metaRaw }, i) => {\n const metaPart = metaRaw ? `, meta: ${metaRaw}` : '';\n return ` '${url}': { component: __module_${i}.default, layout: __module_${i}.layout${metaPart} }`;\n });\n return imports.join('\\n')\n + `\\n\\nglobalThis['${Routes}'] = {\\n` + entries.join(',\\n') + '\\n};'\n + `\\nexport const __bobe_routes = [${names.join(', ')}];`;\n}\n\nexport function generateCsrMenus(menus: Menu[]): string {\n return `globalThis['${Menus}'] = ${JSON.stringify(menus)};`;\n}\n","import type { Plugin } from 'vite';\nimport { resolve } from 'path';\nimport { scanDir } from './scan';\nimport { generateCsrInit, generateSsgInit, generateCsrMenus } from './generate';\n\nexport interface BobeRouterPluginOptions {\n dir?: string;\n ssg?: boolean;\n /** 可识别的文件后缀,默认 ['js', 'jsx', 'ts', 'tsx'] */\n extensions?: string[];\n}\n\nexport default function bobeRouter(opt: BobeRouterPluginOptions = {}): Plugin[] {\n const dir = opt.dir || 'pages';\n const extensions = opt.extensions || ['js', 'jsx', 'ts', 'tsx'];\n\n let root: string;\n\n return [{\n name: 'bobe-router',\n enforce: 'pre',\n configResolved(config) {\n root = config.root;\n },\n\n resolveId(id) {\n if (id === 'bobe-router/csr-routes') return '\\0bobe-router/csr-routes';\n },\n\n load(id) {\n if (id === '\\0bobe-router/csr-routes') {\n const absDir = resolve(root, dir);\n const { routes, menus } = scanDir(absDir, root, '', undefined, extensions);\n return generateCsrInit(routes) + (menus.length ? '\\n' + generateCsrMenus(menus) : '');\n }\n },\n\n // SSR routes 直接注入到 entry-server.ts,不走虚拟模块(避免 Rollup tree-shake)\n transform(code, id) {\n if (id.includes('entry-server.ts')) {\n const absDir = resolve(root, dir);\n const { routes, menus } = scanDir(absDir, root, '', undefined, extensions);\n const ssg = generateSsgInit(routes) + (menus.length ? '\\n' + generateCsrMenus(menus) : '');\n return ssg + '\\n' + code;\n }\n }\n }];\n}\n"],"names":["RE_DIR","DEFAULT_EXTENSIONS","buildFileRegex","extensions","exts","map","e","replace","join","RegExp","buildUrl","base","part","extractRouteMeta","filePath","ext","split","pop","toLowerCase","content","readFileSync","_matter","matter","data","meta","undefined","raw","JSON","stringify","value","metaExportRe","match","startIdx","index","length","braceDepth","inString","stringChar","endIdx","i","ch","prev","slice","trim","Function","hasDefaultExport","_matter2","mdContent","test","parseEntry","name","fileRe","dirMatch","isDir","includes","_dirMatch","_slicedToArray","orderStr","pathPart","menuName","order","parseInt","Infinity","fileMatch","_fileMatch","sortEntries","entries","sort","a","b","pa","pb","oa","ob","localeCompare","scanDir","absDir","basePath","parentPath","menuRef","routes","menus","readdirSync","withFileTypes","ent","full","parsed","isDirectory","urlPath","menu","hasComponent","children","child","push","isFile","isIndex","relFile","metaResult","metaRaw","Object","keys","hasComp","url","file","path","GlobalKey","Routes","Menus","generateCsrInit","items","metaPart","generateSsgInit","imports","names","_","generateCsrMenus","bobeRouter","opt","dir","root","enforce","configResolved","config","resolveId","id","load","resolve","_scanDir","transform","code","_scanDir2","ssg"],"mappings":"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"}
|