@esmx/router 3.0.0-rc.17 → 3.0.0-rc.19

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.
Files changed (155) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +70 -0
  3. package/README.zh-CN.md +70 -0
  4. package/dist/error.d.ts +23 -0
  5. package/dist/error.mjs +61 -0
  6. package/dist/increment-id.d.ts +7 -0
  7. package/dist/increment-id.mjs +11 -0
  8. package/dist/index.d.ts +5 -3
  9. package/dist/index.mjs +14 -3
  10. package/dist/index.test.mjs +8 -0
  11. package/dist/location.d.ts +15 -0
  12. package/dist/location.mjs +53 -0
  13. package/dist/location.test.d.ts +8 -0
  14. package/dist/location.test.mjs +370 -0
  15. package/dist/matcher.d.ts +3 -0
  16. package/dist/matcher.mjs +44 -0
  17. package/dist/matcher.test.mjs +1492 -0
  18. package/dist/micro-app.d.ts +18 -0
  19. package/dist/micro-app.dom.test.d.ts +1 -0
  20. package/dist/micro-app.dom.test.mjs +532 -0
  21. package/dist/micro-app.mjs +80 -0
  22. package/dist/navigation.d.ts +43 -0
  23. package/dist/navigation.mjs +143 -0
  24. package/dist/navigation.test.d.ts +1 -0
  25. package/dist/navigation.test.mjs +681 -0
  26. package/dist/options.d.ts +4 -0
  27. package/dist/options.mjs +88 -0
  28. package/dist/route-task.d.ts +40 -0
  29. package/dist/route-task.mjs +75 -0
  30. package/dist/route-task.test.d.ts +1 -0
  31. package/dist/route-task.test.mjs +673 -0
  32. package/dist/route-transition.d.ts +53 -0
  33. package/dist/route-transition.mjs +307 -0
  34. package/dist/route-transition.test.d.ts +1 -0
  35. package/dist/route-transition.test.mjs +146 -0
  36. package/dist/route.d.ts +72 -0
  37. package/dist/route.mjs +194 -0
  38. package/dist/route.test.d.ts +1 -0
  39. package/dist/route.test.mjs +1664 -0
  40. package/dist/router-back.test.d.ts +1 -0
  41. package/dist/router-back.test.mjs +361 -0
  42. package/dist/router-forward.test.d.ts +1 -0
  43. package/dist/router-forward.test.mjs +376 -0
  44. package/dist/router-go.test.d.ts +1 -0
  45. package/dist/router-go.test.mjs +73 -0
  46. package/dist/router-guards-cleanup.test.d.ts +1 -0
  47. package/dist/router-guards-cleanup.test.mjs +437 -0
  48. package/dist/router-link.d.ts +10 -0
  49. package/dist/router-link.mjs +126 -0
  50. package/dist/router-push.test.d.ts +1 -0
  51. package/dist/router-push.test.mjs +115 -0
  52. package/dist/router-replace.test.d.ts +1 -0
  53. package/dist/router-replace.test.mjs +114 -0
  54. package/dist/router-resolve.test.d.ts +1 -0
  55. package/dist/router-resolve.test.mjs +393 -0
  56. package/dist/router-restart-app.dom.test.d.ts +1 -0
  57. package/dist/router-restart-app.dom.test.mjs +616 -0
  58. package/dist/router-window-navigation.test.d.ts +1 -0
  59. package/dist/router-window-navigation.test.mjs +359 -0
  60. package/dist/router.d.ts +109 -102
  61. package/dist/router.mjs +260 -361
  62. package/dist/types.d.ts +246 -0
  63. package/dist/types.mjs +18 -0
  64. package/dist/util.d.ts +26 -0
  65. package/dist/util.mjs +53 -0
  66. package/dist/util.test.d.ts +1 -0
  67. package/dist/util.test.mjs +1020 -0
  68. package/package.json +10 -13
  69. package/src/error.ts +84 -0
  70. package/src/increment-id.ts +12 -0
  71. package/src/index.test.ts +9 -0
  72. package/src/index.ts +54 -3
  73. package/src/location.test.ts +406 -0
  74. package/src/location.ts +96 -0
  75. package/src/matcher.test.ts +1685 -0
  76. package/src/matcher.ts +59 -0
  77. package/src/micro-app.dom.test.ts +708 -0
  78. package/src/micro-app.ts +101 -0
  79. package/src/navigation.test.ts +858 -0
  80. package/src/navigation.ts +195 -0
  81. package/src/options.ts +131 -0
  82. package/src/route-task.test.ts +901 -0
  83. package/src/route-task.ts +105 -0
  84. package/src/route-transition.test.ts +178 -0
  85. package/src/route-transition.ts +425 -0
  86. package/src/route.test.ts +2014 -0
  87. package/src/route.ts +308 -0
  88. package/src/router-back.test.ts +487 -0
  89. package/src/router-forward.test.ts +506 -0
  90. package/src/router-go.test.ts +91 -0
  91. package/src/router-guards-cleanup.test.ts +595 -0
  92. package/src/router-link.ts +235 -0
  93. package/src/router-push.test.ts +140 -0
  94. package/src/router-replace.test.ts +139 -0
  95. package/src/router-resolve.test.ts +475 -0
  96. package/src/router-restart-app.dom.test.ts +783 -0
  97. package/src/router-window-navigation.test.ts +457 -0
  98. package/src/router.ts +289 -470
  99. package/src/types.ts +341 -0
  100. package/src/util.test.ts +1262 -0
  101. package/src/util.ts +116 -0
  102. package/dist/history/abstract.d.ts +0 -29
  103. package/dist/history/abstract.mjs +0 -107
  104. package/dist/history/base.d.ts +0 -79
  105. package/dist/history/base.mjs +0 -275
  106. package/dist/history/html.d.ts +0 -22
  107. package/dist/history/html.mjs +0 -183
  108. package/dist/history/index.d.ts +0 -7
  109. package/dist/history/index.mjs +0 -16
  110. package/dist/matcher/create-matcher.d.ts +0 -5
  111. package/dist/matcher/create-matcher.mjs +0 -218
  112. package/dist/matcher/create-matcher.spec.mjs +0 -0
  113. package/dist/matcher/index.d.ts +0 -1
  114. package/dist/matcher/index.mjs +0 -1
  115. package/dist/task-pipe/index.d.ts +0 -1
  116. package/dist/task-pipe/index.mjs +0 -1
  117. package/dist/task-pipe/task.d.ts +0 -30
  118. package/dist/task-pipe/task.mjs +0 -66
  119. package/dist/utils/bom.d.ts +0 -5
  120. package/dist/utils/bom.mjs +0 -10
  121. package/dist/utils/encoding.d.ts +0 -48
  122. package/dist/utils/encoding.mjs +0 -44
  123. package/dist/utils/guards.d.ts +0 -9
  124. package/dist/utils/guards.mjs +0 -12
  125. package/dist/utils/index.d.ts +0 -7
  126. package/dist/utils/index.mjs +0 -27
  127. package/dist/utils/path.d.ts +0 -60
  128. package/dist/utils/path.mjs +0 -281
  129. package/dist/utils/path.spec.mjs +0 -27
  130. package/dist/utils/scroll.d.ts +0 -25
  131. package/dist/utils/scroll.mjs +0 -59
  132. package/dist/utils/utils.d.ts +0 -16
  133. package/dist/utils/utils.mjs +0 -11
  134. package/dist/utils/warn.d.ts +0 -2
  135. package/dist/utils/warn.mjs +0 -12
  136. package/src/history/abstract.ts +0 -149
  137. package/src/history/base.ts +0 -408
  138. package/src/history/html.ts +0 -228
  139. package/src/history/index.ts +0 -20
  140. package/src/matcher/create-matcher.spec.ts +0 -3
  141. package/src/matcher/create-matcher.ts +0 -293
  142. package/src/matcher/index.ts +0 -1
  143. package/src/task-pipe/index.ts +0 -1
  144. package/src/task-pipe/task.ts +0 -97
  145. package/src/utils/bom.ts +0 -14
  146. package/src/utils/encoding.ts +0 -153
  147. package/src/utils/guards.ts +0 -25
  148. package/src/utils/index.ts +0 -27
  149. package/src/utils/path.spec.ts +0 -32
  150. package/src/utils/path.ts +0 -417
  151. package/src/utils/scroll.ts +0 -120
  152. package/src/utils/utils.ts +0 -30
  153. package/src/utils/warn.ts +0 -13
  154. /package/dist/{matcher/create-matcher.spec.d.ts → index.test.d.ts} +0 -0
  155. /package/dist/{utils/path.spec.d.ts → matcher.test.d.ts} +0 -0
@@ -0,0 +1,370 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { normalizeURL, parseLocation } from "./location.mjs";
3
+ expect.extend({
4
+ toEqURL: (received, expected) => {
5
+ if (!(received instanceof URL)) {
6
+ return {
7
+ message: () => `expected ${received} to be an instance of URL`,
8
+ pass: false
9
+ };
10
+ }
11
+ (received = new URL(received)).searchParams.sort();
12
+ (expected = new URL(expected)).searchParams.sort();
13
+ received.hash = received.hash;
14
+ expected.hash = expected.hash;
15
+ return {
16
+ message: () => `expected ${received.href} to be ${expected.href}`,
17
+ pass: received.href === expected.href
18
+ };
19
+ }
20
+ });
21
+ describe("normalizeURL", () => {
22
+ const testCases = [
23
+ {
24
+ input: "//example.com/path",
25
+ base: "https://github.com",
26
+ expected: "http://example.com/path",
27
+ description: "should handle protocol-relative URLs (starting with //)"
28
+ },
29
+ {
30
+ input: "http://github.com/path?a#h",
31
+ base: "http://example.com",
32
+ expected: "http://github.com/path?a#h",
33
+ description: "should handle absolute URLs"
34
+ },
35
+ {
36
+ input: "/path",
37
+ base: "http://example.com/en/",
38
+ expected: "http://example.com/en/path",
39
+ description: "should handle relative paths with a base URL"
40
+ },
41
+ {
42
+ input: "github.com",
43
+ base: "http://example.com",
44
+ expected: "http://example.com/github.com",
45
+ description: "should treat bare domains as relative paths"
46
+ },
47
+ {
48
+ input: new URL("http://example.com/path"),
49
+ base: "http://example.com",
50
+ expected: "http://example.com/path",
51
+ description: "should handle URL objects"
52
+ },
53
+ {
54
+ input: "-a://example.com",
55
+ base: "http://example.com",
56
+ expected: "http://example.com/-a://example.com",
57
+ description: "should treat strings that fail to parse as a protocol as relative paths"
58
+ }
59
+ ];
60
+ testCases.forEach(({ input, base, expected, description }) => {
61
+ test(description, () => {
62
+ const result = normalizeURL(input, new URL(base));
63
+ expect(result).toEqURL(expected);
64
+ });
65
+ });
66
+ });
67
+ describe("parseLocation", () => {
68
+ const testCases = [
69
+ {
70
+ input: "/products",
71
+ base: "http://example.com",
72
+ expected: "http://example.com/products",
73
+ description: "should handle string paths"
74
+ },
75
+ {
76
+ input: { path: "/products" },
77
+ base: "http://example.com",
78
+ expected: "http://example.com/products",
79
+ description: "should handle objects with a path property"
80
+ },
81
+ {
82
+ input: { url: "/products" },
83
+ base: "http://example.com",
84
+ expected: "http://example.com/products",
85
+ description: "should handle objects with a url property"
86
+ },
87
+ {
88
+ input: {
89
+ path: "/products",
90
+ query: { id: "123", category: "electronics" }
91
+ },
92
+ base: "http://example.com",
93
+ expected: "http://example.com/products?id=123&category=electronics",
94
+ description: "should handle objects with query parameters"
95
+ },
96
+ {
97
+ input: { path: "/products", query: { id: "123" }, hash: "details" },
98
+ base: "http://example.com",
99
+ expected: "http://example.com/products?id=123#details",
100
+ description: "should handle objects with a hash"
101
+ },
102
+ {
103
+ input: { path: "/products", queryArray: { tag: ["new", "sale"] } },
104
+ base: "http://example.com",
105
+ expected: "http://example.com/products?tag=new&tag=sale",
106
+ description: "should handle objects with queryArray"
107
+ },
108
+ {
109
+ input: {
110
+ path: "/products",
111
+ query: { id: "123", category: "electronics" },
112
+ queryArray: { tag: ["new", "sale"] },
113
+ hash: "details"
114
+ },
115
+ base: "http://example.com",
116
+ expected: "http://example.com/products?id=123&category=electronics&tag=new&tag=sale#details",
117
+ description: "should handle complex objects with all properties"
118
+ },
119
+ {
120
+ input: {
121
+ path: "/products",
122
+ hash: "#a?a"
123
+ },
124
+ base: "http://example.com",
125
+ expected: "http://example.com/products#a?a",
126
+ description: "should handle special hash characters correctly"
127
+ },
128
+ {
129
+ input: {
130
+ path: "/products",
131
+ hash: "#a?a#b"
132
+ },
133
+ base: "http://example.com",
134
+ expected: "http://example.com/products#a?a#b",
135
+ description: "should handle special hash characters correctly"
136
+ },
137
+ {
138
+ input: {
139
+ path: "/products",
140
+ query: {
141
+ id: null,
142
+ category: void 0,
143
+ symbol: Symbol(),
144
+ fn: async () => "",
145
+ obj: { a: 10 },
146
+ big: 12345678901234567891234567890123456789n,
147
+ a: Number.NaN,
148
+ b: "",
149
+ c: "0",
150
+ d: 0,
151
+ e: 1
152
+ }
153
+ },
154
+ base: "http://example.com",
155
+ expected: `http://example.com/products?symbol=Symbol()&fn=${String(
156
+ async () => ""
157
+ )}&obj=${String({})}&big=12345678901234567891234567890123456789&b&c=0&d=0&e=1`,
158
+ description: "should ignore null, undefined, and NaN query parameters"
159
+ },
160
+ {
161
+ input: { path: "/products", queryArray: { tag: [] } },
162
+ base: "http://example.com",
163
+ expected: "http://example.com/products",
164
+ description: "should handle empty queryArray"
165
+ },
166
+ {
167
+ input: {
168
+ path: "/products?id=path&a",
169
+ query: { id: "query" }
170
+ },
171
+ base: "http://example.com",
172
+ expected: "http://example.com/products?id=query&a",
173
+ description: "query value should override query parameter in path"
174
+ },
175
+ {
176
+ input: {
177
+ path: "/products?id=path&a",
178
+ query: { id: "query" },
179
+ queryArray: { id: ["queryArray"] }
180
+ },
181
+ base: "http://example.com",
182
+ expected: "http://example.com/products?id=queryArray&a",
183
+ description: "queryArray value should override query and path parameters"
184
+ },
185
+ {
186
+ input: {
187
+ path: "/products?id=path&a",
188
+ queryArray: { id: ["queryArray"] }
189
+ },
190
+ base: "http://example.com",
191
+ expected: "http://example.com/products?id=queryArray&a",
192
+ description: "queryArray value should override query parameter in path"
193
+ },
194
+ {
195
+ input: {
196
+ path: "?a&a=&a&a",
197
+ query: { a: "" },
198
+ queryArray: { a: ["", ""] }
199
+ },
200
+ base: "http://example.com",
201
+ expected: "http://example.com?a&a",
202
+ description: "should handle empty strings and duplicate query parameters correctly"
203
+ },
204
+ {
205
+ input: { path: "/products?id=123", url: "/products?id=456" },
206
+ base: "http://example.com",
207
+ expected: "http://example.com/products?id=123",
208
+ description: "path should take priority over url when both are present"
209
+ },
210
+ {
211
+ input: { url: "/products?id=456" },
212
+ base: "http://example.com",
213
+ expected: "http://example.com/products?id=456",
214
+ description: "url should be used when path is not present"
215
+ },
216
+ {
217
+ input: {},
218
+ base: "http://example.com",
219
+ expected: "http://example.com/",
220
+ description: "empty input object should default to base URL"
221
+ }
222
+ ];
223
+ testCases.forEach(({ input, base, expected, description }) => {
224
+ test(description, () => {
225
+ const result = parseLocation(input, new URL(base));
226
+ expect(result).toEqURL(expected);
227
+ });
228
+ });
229
+ });
230
+ describe("normalizeURL more", () => {
231
+ describe.for(
232
+ // biome-ignore format:
233
+ Object.entries({
234
+ "https://www.esmx.dev": {
235
+ "/": "https://www.esmx.dev/",
236
+ "/new": "https://www.esmx.dev/new",
237
+ "/new/": "https://www.esmx.dev/new/",
238
+ "/new/100": "https://www.esmx.dev/new/100",
239
+ "/new/100/": "https://www.esmx.dev/new/100/",
240
+ "..": "https://www.esmx.dev/",
241
+ "../": "https://www.esmx.dev/",
242
+ "../new": "https://www.esmx.dev/new",
243
+ "../new/": "https://www.esmx.dev/new/",
244
+ "../new/100": "https://www.esmx.dev/new/100",
245
+ "../new/100/": "https://www.esmx.dev/new/100/",
246
+ "": "https://www.esmx.dev/",
247
+ "new": "https://www.esmx.dev/new",
248
+ "new/": "https://www.esmx.dev/new/",
249
+ "new/100": "https://www.esmx.dev/new/100",
250
+ "new/100/": "https://www.esmx.dev/new/100/",
251
+ ".": "https://www.esmx.dev/",
252
+ "./": "https://www.esmx.dev/",
253
+ "./new": "https://www.esmx.dev/new",
254
+ "./new/": "https://www.esmx.dev/new/",
255
+ "./new/100": "https://www.esmx.dev/new/100",
256
+ "./new/100/": "https://www.esmx.dev/new/100/",
257
+ ".a": "https://www.esmx.dev/.a",
258
+ "..a": "https://www.esmx.dev/..a",
259
+ ".a/": "https://www.esmx.dev/.a/",
260
+ "..a/": "https://www.esmx.dev/..a/",
261
+ "new/../.": "https://www.esmx.dev/"
262
+ },
263
+ "https://www.esmx.dev/": {
264
+ "/": "https://www.esmx.dev/",
265
+ "/new": "https://www.esmx.dev/new",
266
+ "/new/": "https://www.esmx.dev/new/",
267
+ "/new/100": "https://www.esmx.dev/new/100",
268
+ "/new/100/": "https://www.esmx.dev/new/100/",
269
+ "..": "https://www.esmx.dev/",
270
+ "../": "https://www.esmx.dev/",
271
+ "../new": "https://www.esmx.dev/new",
272
+ "../new/": "https://www.esmx.dev/new/",
273
+ "../new/100": "https://www.esmx.dev/new/100",
274
+ "../new/100/": "https://www.esmx.dev/new/100/",
275
+ "": "https://www.esmx.dev/",
276
+ "new": "https://www.esmx.dev/new",
277
+ "new/": "https://www.esmx.dev/new/",
278
+ "new/100": "https://www.esmx.dev/new/100",
279
+ "new/100/": "https://www.esmx.dev/new/100/",
280
+ ".": "https://www.esmx.dev/",
281
+ "./": "https://www.esmx.dev/",
282
+ "./new": "https://www.esmx.dev/new",
283
+ "./new/": "https://www.esmx.dev/new/",
284
+ "./new/100": "https://www.esmx.dev/new/100",
285
+ "./new/100/": "https://www.esmx.dev/new/100/",
286
+ ".a": "https://www.esmx.dev/.a",
287
+ "..a": "https://www.esmx.dev/..a",
288
+ ".a/": "https://www.esmx.dev/.a/",
289
+ "..a/": "https://www.esmx.dev/..a/",
290
+ "new/../.": "https://www.esmx.dev/"
291
+ },
292
+ "https://www.esmx.dev/a/b/c": {
293
+ "/": "https://www.esmx.dev/a/b/",
294
+ "/new": "https://www.esmx.dev/a/b/new",
295
+ "/new/": "https://www.esmx.dev/a/b/new/",
296
+ "/new/100": "https://www.esmx.dev/a/b/new/100",
297
+ "/new/100/": "https://www.esmx.dev/a/b/new/100/",
298
+ "..": "https://www.esmx.dev/a/",
299
+ "../": "https://www.esmx.dev/a/",
300
+ "../new": "https://www.esmx.dev/a/new",
301
+ "../new/": "https://www.esmx.dev/a/new/",
302
+ "../new/100": "https://www.esmx.dev/a/new/100",
303
+ "../new/100/": "https://www.esmx.dev/a/new/100/",
304
+ "": "https://www.esmx.dev/a/b/c",
305
+ "new": "https://www.esmx.dev/a/b/new",
306
+ "new/": "https://www.esmx.dev/a/b/new/",
307
+ "new/100": "https://www.esmx.dev/a/b/new/100",
308
+ "new/100/": "https://www.esmx.dev/a/b/new/100/",
309
+ ".": "https://www.esmx.dev/a/b/",
310
+ "./": "https://www.esmx.dev/a/b/",
311
+ "./new": "https://www.esmx.dev/a/b/new",
312
+ "./new/": "https://www.esmx.dev/a/b/new/",
313
+ "./new/100": "https://www.esmx.dev/a/b/new/100",
314
+ "./new/100/": "https://www.esmx.dev/a/b/new/100/",
315
+ ".a": "https://www.esmx.dev/a/b/.a",
316
+ "..a": "https://www.esmx.dev/a/b/..a",
317
+ ".a/": "https://www.esmx.dev/a/b/.a/",
318
+ "..a/": "https://www.esmx.dev/a/b/..a/",
319
+ "new/../.": "https://www.esmx.dev/a/b/",
320
+ "new/.././a/../../x/": "https://www.esmx.dev/a/x/"
321
+ },
322
+ "https://www.esmx.dev/a/b/c/": {
323
+ "/": "https://www.esmx.dev/a/b/c/",
324
+ "/new": "https://www.esmx.dev/a/b/c/new",
325
+ "/new/": "https://www.esmx.dev/a/b/c/new/",
326
+ "/new/100": "https://www.esmx.dev/a/b/c/new/100",
327
+ "/new/100/": "https://www.esmx.dev/a/b/c/new/100/",
328
+ "..": "https://www.esmx.dev/a/b/",
329
+ "../": "https://www.esmx.dev/a/b/",
330
+ "../new": "https://www.esmx.dev/a/b/new",
331
+ "../new/": "https://www.esmx.dev/a/b/new/",
332
+ "../new/100": "https://www.esmx.dev/a/b/new/100",
333
+ "../new/100/": "https://www.esmx.dev/a/b/new/100/",
334
+ "": "https://www.esmx.dev/a/b/c/",
335
+ "new": "https://www.esmx.dev/a/b/c/new",
336
+ "new/": "https://www.esmx.dev/a/b/c/new/",
337
+ "new/100": "https://www.esmx.dev/a/b/c/new/100",
338
+ "new/100/": "https://www.esmx.dev/a/b/c/new/100/",
339
+ ".": "https://www.esmx.dev/a/b/c/",
340
+ "./": "https://www.esmx.dev/a/b/c/",
341
+ "./new": "https://www.esmx.dev/a/b/c/new",
342
+ "./new/": "https://www.esmx.dev/a/b/c/new/",
343
+ "./new/100": "https://www.esmx.dev/a/b/c/new/100",
344
+ "./new/100/": "https://www.esmx.dev/a/b/c/new/100/",
345
+ ".a": "https://www.esmx.dev/a/b/c/.a",
346
+ "..a": "https://www.esmx.dev/a/b/c/..a",
347
+ ".a/": "https://www.esmx.dev/a/b/c/.a/",
348
+ "..a/": "https://www.esmx.dev/a/b/c/..a/",
349
+ "new/.././": "https://www.esmx.dev/a/b/c/",
350
+ "new/.././a/../../x/": "https://www.esmx.dev/a/b/x/"
351
+ }
352
+ })
353
+ )(`base: $0`, ([base, cases]) => {
354
+ test.each(Object.entries(cases))(`input: $0`, (input, expected) => {
355
+ const url = normalizeURL(input, new URL(base));
356
+ expect(url).toEqURL(expected);
357
+ const pathSuffix = "?a&b=1&c=2&a=&a=4&base=10#hash";
358
+ const urlWithSuffix = normalizeURL(
359
+ input + pathSuffix,
360
+ new URL(base)
361
+ );
362
+ expect(urlWithSuffix).toEqURL(expected + pathSuffix);
363
+ const urlWithBaseSuffix = normalizeURL(
364
+ input + pathSuffix,
365
+ new URL(base + "?base=base#base")
366
+ );
367
+ expect(urlWithBaseSuffix).toEqURL(expected + pathSuffix);
368
+ });
369
+ });
370
+ });
@@ -0,0 +1,3 @@
1
+ import type { RouteConfig, RouteMatcher } from './types';
2
+ export declare function createMatcher(routes: RouteConfig[]): RouteMatcher;
3
+ export declare function joinPathname(pathname: string, base?: string): string;
@@ -0,0 +1,44 @@
1
+ import { compile, match } from "path-to-regexp";
2
+ export function createMatcher(routes) {
3
+ const compiledRoutes = createRouteMatches(routes);
4
+ return (toURL, baseURL) => {
5
+ const matchPath = toURL.pathname.substring(baseURL.pathname.length - 1);
6
+ const matches = [];
7
+ const params = {};
8
+ const collectMatchingRoutes = (routes2) => {
9
+ for (const item of routes2) {
10
+ if (item.children.length && collectMatchingRoutes(item.children)) {
11
+ matches.unshift(item);
12
+ return true;
13
+ }
14
+ const result = item.match(matchPath);
15
+ if (result) {
16
+ matches.unshift(item);
17
+ if (typeof result === "object") {
18
+ Object.assign(params, result.params);
19
+ }
20
+ return true;
21
+ }
22
+ }
23
+ return false;
24
+ };
25
+ collectMatchingRoutes(compiledRoutes);
26
+ return { matches: Object.freeze(matches), params };
27
+ };
28
+ }
29
+ function createRouteMatches(routes, base = "") {
30
+ return routes.map((route) => {
31
+ const compilePath = joinPathname(route.path, base);
32
+ return {
33
+ ...route,
34
+ compilePath,
35
+ match: match(compilePath),
36
+ compile: compile(compilePath),
37
+ meta: route.meta || {},
38
+ children: Array.isArray(route.children) ? createRouteMatches(route.children, compilePath) : []
39
+ };
40
+ });
41
+ }
42
+ export function joinPathname(pathname, base = "") {
43
+ return "/" + `${base}/${pathname}`.split("/").filter(Boolean).join("/");
44
+ }