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.
@@ -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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"}
@@ -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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"}