@esmx/router 3.0.0-rc.49 → 3.0.0-rc.51
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/matcher.mjs +4 -1
- package/dist/options.mjs +1 -1
- package/dist/route.mjs +14 -7
- package/dist/types.d.ts +3 -1
- package/package.json +3 -3
- package/src/matcher.ts +8 -1
- package/src/options.ts +7 -2
- package/src/route.ts +21 -13
- package/src/types.ts +7 -1
package/dist/matcher.mjs
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { compile, match } from "path-to-regexp";
|
|
2
2
|
export function createMatcher(routes) {
|
|
3
3
|
const compiledRoutes = createRouteMatches(routes);
|
|
4
|
-
return (toURL, baseURL) => {
|
|
4
|
+
return (toURL, baseURL, cb) => {
|
|
5
5
|
const matchPath = toURL.pathname.substring(baseURL.pathname.length - 1);
|
|
6
6
|
const matches = [];
|
|
7
7
|
const params = {};
|
|
8
8
|
const collectMatchingRoutes = (routes2) => {
|
|
9
9
|
for (const item of routes2) {
|
|
10
|
+
if (cb && !cb(item)) {
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
10
13
|
if (item.children.length && collectMatchingRoutes(item.children)) {
|
|
11
14
|
matches.unshift(item);
|
|
12
15
|
return true;
|
package/dist/options.mjs
CHANGED
|
@@ -32,7 +32,7 @@ function getBaseUrl(options) {
|
|
|
32
32
|
export function parsedOptions(options = {}) {
|
|
33
33
|
var _a, _b, _c, _d, _e, _f;
|
|
34
34
|
const base = getBaseUrl(options);
|
|
35
|
-
const routes =
|
|
35
|
+
const routes = (_a = options.routes) != null ? _a : [];
|
|
36
36
|
return Object.freeze({
|
|
37
37
|
rootStyle: options.rootStyle || false,
|
|
38
38
|
root: options.root || "",
|
package/dist/route.mjs
CHANGED
|
@@ -85,9 +85,20 @@ export class Route {
|
|
|
85
85
|
const base = options.base;
|
|
86
86
|
const toInput = resolveRouteLocationInput(routeOptions.toInput, from);
|
|
87
87
|
const to = options.normalizeURL(parseLocation(toInput, base), from);
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
let match = null;
|
|
89
|
+
if (to.origin === base.origin && to.pathname.startsWith(base.pathname)) {
|
|
90
|
+
const isLayer = toType === RouteType.pushLayer;
|
|
91
|
+
match = options.matcher(to, base, (config) => {
|
|
92
|
+
if (isLayer) {
|
|
93
|
+
return config.layer !== false;
|
|
94
|
+
}
|
|
95
|
+
return config.layer !== true;
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
if (match) {
|
|
99
|
+
applyRouteParams(match, toInput, base, to);
|
|
100
|
+
Object.assign(this.params, match.params);
|
|
101
|
+
}
|
|
91
102
|
this.url = to;
|
|
92
103
|
this.path = match ? to.pathname.substring(base.pathname.length - 1) : to.pathname;
|
|
93
104
|
this.fullPath = (match ? this.path : to.pathname) + to.search + to.hash;
|
|
@@ -107,10 +118,6 @@ export class Route {
|
|
|
107
118
|
this.queryArray[key] = to.searchParams.getAll(key);
|
|
108
119
|
}
|
|
109
120
|
this.hash = to.hash;
|
|
110
|
-
if (match) {
|
|
111
|
-
applyRouteParams(match, toInput, base, to);
|
|
112
|
-
Object.assign(this.params, match.params);
|
|
113
|
-
}
|
|
114
121
|
if (typeof toInput.statusCode === "number") {
|
|
115
122
|
this.statusCode = toInput.statusCode;
|
|
116
123
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -61,6 +61,8 @@ export interface RouteConfig {
|
|
|
61
61
|
beforeEnter?: RouteConfirmHook;
|
|
62
62
|
beforeUpdate?: RouteConfirmHook;
|
|
63
63
|
beforeLeave?: RouteConfirmHook;
|
|
64
|
+
/** Mark this route as only effective in layer mode */
|
|
65
|
+
layer?: boolean;
|
|
64
66
|
/**
|
|
65
67
|
* Route override function for hybrid app development
|
|
66
68
|
*
|
|
@@ -91,7 +93,7 @@ export interface RouteMatchResult {
|
|
|
91
93
|
readonly matches: readonly RouteParsedConfig[];
|
|
92
94
|
readonly params: Record<string, string | string[] | undefined>;
|
|
93
95
|
}
|
|
94
|
-
export type RouteMatcher = (
|
|
96
|
+
export type RouteMatcher = (to: URL, base: URL, cb?: (item: RouteParsedConfig) => boolean) => RouteMatchResult;
|
|
95
97
|
/**
|
|
96
98
|
* Route constructor options interface
|
|
97
99
|
*/
|
package/package.json
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@biomejs/biome": "1.9.4",
|
|
35
|
-
"@esmx/lint": "3.0.0-rc.
|
|
35
|
+
"@esmx/lint": "3.0.0-rc.51",
|
|
36
36
|
"@types/node": "^24.0.0",
|
|
37
37
|
"@vitest/coverage-v8": "3.2.4",
|
|
38
38
|
"happy-dom": "^18.0.1",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"unbuild": "3.5.0",
|
|
42
42
|
"vitest": "3.2.4"
|
|
43
43
|
},
|
|
44
|
-
"version": "3.0.0-rc.
|
|
44
|
+
"version": "3.0.0-rc.51",
|
|
45
45
|
"type": "module",
|
|
46
46
|
"private": false,
|
|
47
47
|
"exports": {
|
|
@@ -60,5 +60,5 @@
|
|
|
60
60
|
"template",
|
|
61
61
|
"public"
|
|
62
62
|
],
|
|
63
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "5556ca6bbaf29a673861c685a19414d5853b9166"
|
|
64
64
|
}
|
package/src/matcher.ts
CHANGED
|
@@ -3,7 +3,11 @@ import type { RouteConfig, RouteMatcher, RouteParsedConfig } from './types';
|
|
|
3
3
|
|
|
4
4
|
export function createMatcher(routes: RouteConfig[]): RouteMatcher {
|
|
5
5
|
const compiledRoutes = createRouteMatches(routes);
|
|
6
|
-
return (
|
|
6
|
+
return (
|
|
7
|
+
toURL: URL,
|
|
8
|
+
baseURL: URL,
|
|
9
|
+
cb?: (item: RouteParsedConfig) => boolean
|
|
10
|
+
) => {
|
|
7
11
|
const matchPath = toURL.pathname.substring(baseURL.pathname.length - 1);
|
|
8
12
|
const matches: RouteParsedConfig[] = [];
|
|
9
13
|
const params: Record<string, string | string[]> = {};
|
|
@@ -11,6 +15,9 @@ export function createMatcher(routes: RouteConfig[]): RouteMatcher {
|
|
|
11
15
|
routes: RouteParsedConfig[]
|
|
12
16
|
): boolean => {
|
|
13
17
|
for (const item of routes) {
|
|
18
|
+
if (cb && !cb(item)) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
14
21
|
// Depth-first traversal
|
|
15
22
|
if (
|
|
16
23
|
item.children.length &&
|
package/src/options.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { createMatcher } from './matcher';
|
|
2
2
|
import type { Router } from './router';
|
|
3
3
|
import { RouterMode } from './types';
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
Route,
|
|
6
|
+
RouteConfig,
|
|
7
|
+
RouterOptions,
|
|
8
|
+
RouterParsedOptions
|
|
9
|
+
} from './types';
|
|
5
10
|
import { isBrowser } from './util';
|
|
6
11
|
|
|
7
12
|
/**
|
|
@@ -60,7 +65,7 @@ export function parsedOptions(
|
|
|
60
65
|
options: RouterOptions = {}
|
|
61
66
|
): RouterParsedOptions {
|
|
62
67
|
const base = getBaseUrl(options);
|
|
63
|
-
const routes =
|
|
68
|
+
const routes = options.routes ?? [];
|
|
64
69
|
return Object.freeze<RouterParsedOptions>({
|
|
65
70
|
rootStyle: options.rootStyle || false,
|
|
66
71
|
root: options.root || '',
|
package/src/route.ts
CHANGED
|
@@ -153,10 +153,27 @@ export class Route {
|
|
|
153
153
|
const base = options.base;
|
|
154
154
|
const toInput = resolveRouteLocationInput(routeOptions.toInput, from);
|
|
155
155
|
const to = options.normalizeURL(parseLocation(toInput, base), from);
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
156
|
+
let match: RouteMatchResult | null = null;
|
|
157
|
+
|
|
158
|
+
// Check if URL origin matches base origin (protocol + hostname + port)
|
|
159
|
+
// If origins don't match, treat as external URL and don't attempt route matching
|
|
160
|
+
if (
|
|
161
|
+
to.origin === base.origin &&
|
|
162
|
+
to.pathname.startsWith(base.pathname)
|
|
163
|
+
) {
|
|
164
|
+
const isLayer = toType === RouteType.pushLayer;
|
|
165
|
+
match = options.matcher(to, base, (config) => {
|
|
166
|
+
if (isLayer) {
|
|
167
|
+
return config.layer !== false;
|
|
168
|
+
}
|
|
169
|
+
return config.layer !== true;
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (match) {
|
|
174
|
+
applyRouteParams(match, toInput, base, to);
|
|
175
|
+
Object.assign(this.params, match.params);
|
|
176
|
+
}
|
|
160
177
|
|
|
161
178
|
this.url = to;
|
|
162
179
|
this.path = match
|
|
@@ -176,27 +193,18 @@ export class Route {
|
|
|
176
193
|
: null;
|
|
177
194
|
this.meta = this.config?.meta || {};
|
|
178
195
|
|
|
179
|
-
// Initialize state object - create new local object, merge externally passed state
|
|
180
196
|
const state: RouteState = {};
|
|
181
197
|
if (toInput.state) {
|
|
182
198
|
Object.assign(state, toInput.state);
|
|
183
199
|
}
|
|
184
200
|
this.state = state;
|
|
185
201
|
|
|
186
|
-
// Process query parameters
|
|
187
202
|
for (const key of new Set(to.searchParams.keys())) {
|
|
188
203
|
this.query[key] = to.searchParams.get(key)!;
|
|
189
204
|
this.queryArray[key] = to.searchParams.getAll(key);
|
|
190
205
|
}
|
|
191
206
|
this.hash = to.hash;
|
|
192
207
|
|
|
193
|
-
// Apply user-provided route parameters (if match is successful)
|
|
194
|
-
if (match) {
|
|
195
|
-
applyRouteParams(match, toInput, base, to);
|
|
196
|
-
// Assign matched parameters to route object
|
|
197
|
-
Object.assign(this.params, match.params);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
208
|
// Set status code
|
|
201
209
|
// Prioritize user-provided statusCode
|
|
202
210
|
if (typeof toInput.statusCode === 'number') {
|
package/src/types.ts
CHANGED
|
@@ -110,6 +110,8 @@ export interface RouteConfig {
|
|
|
110
110
|
beforeEnter?: RouteConfirmHook;
|
|
111
111
|
beforeUpdate?: RouteConfirmHook;
|
|
112
112
|
beforeLeave?: RouteConfirmHook;
|
|
113
|
+
/** Mark this route as only effective in layer mode */
|
|
114
|
+
layer?: boolean;
|
|
113
115
|
|
|
114
116
|
/**
|
|
115
117
|
* Route override function for hybrid app development
|
|
@@ -144,7 +146,11 @@ export interface RouteMatchResult {
|
|
|
144
146
|
readonly params: Record<string, string | string[] | undefined>;
|
|
145
147
|
}
|
|
146
148
|
|
|
147
|
-
export type RouteMatcher = (
|
|
149
|
+
export type RouteMatcher = (
|
|
150
|
+
to: URL,
|
|
151
|
+
base: URL,
|
|
152
|
+
cb?: (item: RouteParsedConfig) => boolean
|
|
153
|
+
) => RouteMatchResult;
|
|
148
154
|
|
|
149
155
|
/**
|
|
150
156
|
* Route constructor options interface
|