@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.
- package/LICENSE +1 -1
- package/README.md +70 -0
- package/README.zh-CN.md +70 -0
- package/dist/error.d.ts +23 -0
- package/dist/error.mjs +61 -0
- package/dist/increment-id.d.ts +7 -0
- package/dist/increment-id.mjs +11 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.mjs +14 -3
- package/dist/index.test.mjs +8 -0
- package/dist/location.d.ts +15 -0
- package/dist/location.mjs +53 -0
- package/dist/location.test.d.ts +8 -0
- package/dist/location.test.mjs +370 -0
- package/dist/matcher.d.ts +3 -0
- package/dist/matcher.mjs +44 -0
- package/dist/matcher.test.mjs +1492 -0
- package/dist/micro-app.d.ts +18 -0
- package/dist/micro-app.dom.test.d.ts +1 -0
- package/dist/micro-app.dom.test.mjs +532 -0
- package/dist/micro-app.mjs +80 -0
- package/dist/navigation.d.ts +43 -0
- package/dist/navigation.mjs +143 -0
- package/dist/navigation.test.d.ts +1 -0
- package/dist/navigation.test.mjs +681 -0
- package/dist/options.d.ts +4 -0
- package/dist/options.mjs +88 -0
- package/dist/route-task.d.ts +40 -0
- package/dist/route-task.mjs +75 -0
- package/dist/route-task.test.d.ts +1 -0
- package/dist/route-task.test.mjs +673 -0
- package/dist/route-transition.d.ts +53 -0
- package/dist/route-transition.mjs +307 -0
- package/dist/route-transition.test.d.ts +1 -0
- package/dist/route-transition.test.mjs +146 -0
- package/dist/route.d.ts +72 -0
- package/dist/route.mjs +194 -0
- package/dist/route.test.d.ts +1 -0
- package/dist/route.test.mjs +1664 -0
- package/dist/router-back.test.d.ts +1 -0
- package/dist/router-back.test.mjs +361 -0
- package/dist/router-forward.test.d.ts +1 -0
- package/dist/router-forward.test.mjs +376 -0
- package/dist/router-go.test.d.ts +1 -0
- package/dist/router-go.test.mjs +73 -0
- package/dist/router-guards-cleanup.test.d.ts +1 -0
- package/dist/router-guards-cleanup.test.mjs +437 -0
- package/dist/router-link.d.ts +10 -0
- package/dist/router-link.mjs +126 -0
- package/dist/router-push.test.d.ts +1 -0
- package/dist/router-push.test.mjs +115 -0
- package/dist/router-replace.test.d.ts +1 -0
- package/dist/router-replace.test.mjs +114 -0
- package/dist/router-resolve.test.d.ts +1 -0
- package/dist/router-resolve.test.mjs +393 -0
- package/dist/router-restart-app.dom.test.d.ts +1 -0
- package/dist/router-restart-app.dom.test.mjs +616 -0
- package/dist/router-window-navigation.test.d.ts +1 -0
- package/dist/router-window-navigation.test.mjs +359 -0
- package/dist/router.d.ts +109 -102
- package/dist/router.mjs +260 -361
- package/dist/types.d.ts +246 -0
- package/dist/types.mjs +18 -0
- package/dist/util.d.ts +26 -0
- package/dist/util.mjs +53 -0
- package/dist/util.test.d.ts +1 -0
- package/dist/util.test.mjs +1020 -0
- package/package.json +10 -13
- package/src/error.ts +84 -0
- package/src/increment-id.ts +12 -0
- package/src/index.test.ts +9 -0
- package/src/index.ts +54 -3
- package/src/location.test.ts +406 -0
- package/src/location.ts +96 -0
- package/src/matcher.test.ts +1685 -0
- package/src/matcher.ts +59 -0
- package/src/micro-app.dom.test.ts +708 -0
- package/src/micro-app.ts +101 -0
- package/src/navigation.test.ts +858 -0
- package/src/navigation.ts +195 -0
- package/src/options.ts +131 -0
- package/src/route-task.test.ts +901 -0
- package/src/route-task.ts +105 -0
- package/src/route-transition.test.ts +178 -0
- package/src/route-transition.ts +425 -0
- package/src/route.test.ts +2014 -0
- package/src/route.ts +308 -0
- package/src/router-back.test.ts +487 -0
- package/src/router-forward.test.ts +506 -0
- package/src/router-go.test.ts +91 -0
- package/src/router-guards-cleanup.test.ts +595 -0
- package/src/router-link.ts +235 -0
- package/src/router-push.test.ts +140 -0
- package/src/router-replace.test.ts +139 -0
- package/src/router-resolve.test.ts +475 -0
- package/src/router-restart-app.dom.test.ts +783 -0
- package/src/router-window-navigation.test.ts +457 -0
- package/src/router.ts +289 -470
- package/src/types.ts +341 -0
- package/src/util.test.ts +1262 -0
- package/src/util.ts +116 -0
- package/dist/history/abstract.d.ts +0 -29
- package/dist/history/abstract.mjs +0 -107
- package/dist/history/base.d.ts +0 -79
- package/dist/history/base.mjs +0 -275
- package/dist/history/html.d.ts +0 -22
- package/dist/history/html.mjs +0 -183
- package/dist/history/index.d.ts +0 -7
- package/dist/history/index.mjs +0 -16
- package/dist/matcher/create-matcher.d.ts +0 -5
- package/dist/matcher/create-matcher.mjs +0 -218
- package/dist/matcher/create-matcher.spec.mjs +0 -0
- package/dist/matcher/index.d.ts +0 -1
- package/dist/matcher/index.mjs +0 -1
- package/dist/task-pipe/index.d.ts +0 -1
- package/dist/task-pipe/index.mjs +0 -1
- package/dist/task-pipe/task.d.ts +0 -30
- package/dist/task-pipe/task.mjs +0 -66
- package/dist/utils/bom.d.ts +0 -5
- package/dist/utils/bom.mjs +0 -10
- package/dist/utils/encoding.d.ts +0 -48
- package/dist/utils/encoding.mjs +0 -44
- package/dist/utils/guards.d.ts +0 -9
- package/dist/utils/guards.mjs +0 -12
- package/dist/utils/index.d.ts +0 -7
- package/dist/utils/index.mjs +0 -27
- package/dist/utils/path.d.ts +0 -60
- package/dist/utils/path.mjs +0 -281
- package/dist/utils/path.spec.mjs +0 -27
- package/dist/utils/scroll.d.ts +0 -25
- package/dist/utils/scroll.mjs +0 -59
- package/dist/utils/utils.d.ts +0 -16
- package/dist/utils/utils.mjs +0 -11
- package/dist/utils/warn.d.ts +0 -2
- package/dist/utils/warn.mjs +0 -12
- package/src/history/abstract.ts +0 -149
- package/src/history/base.ts +0 -408
- package/src/history/html.ts +0 -228
- package/src/history/index.ts +0 -20
- package/src/matcher/create-matcher.spec.ts +0 -3
- package/src/matcher/create-matcher.ts +0 -293
- package/src/matcher/index.ts +0 -1
- package/src/task-pipe/index.ts +0 -1
- package/src/task-pipe/task.ts +0 -97
- package/src/utils/bom.ts +0 -14
- package/src/utils/encoding.ts +0 -153
- package/src/utils/guards.ts +0 -25
- package/src/utils/index.ts +0 -27
- package/src/utils/path.spec.ts +0 -32
- package/src/utils/path.ts +0 -417
- package/src/utils/scroll.ts +0 -120
- package/src/utils/utils.ts +0 -30
- package/src/utils/warn.ts +0 -13
- /package/dist/{matcher/create-matcher.spec.d.ts → index.test.d.ts} +0 -0
- /package/dist/{utils/path.spec.d.ts → matcher.test.d.ts} +0 -0
package/LICENSE
CHANGED
package/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="https://www.esmnext.com/logo.svg?t=2025" width="120" alt="Esmx Logo" />
|
|
3
|
+
<h1>@esmx/router</h1>
|
|
4
|
+
|
|
5
|
+
<div>
|
|
6
|
+
<a href="https://www.npmjs.com/package/@esmx/router">
|
|
7
|
+
<img src="https://img.shields.io/npm/v/@esmx/router.svg" alt="npm version" />
|
|
8
|
+
</a>
|
|
9
|
+
<a href="https://github.com/esmnext/esmx/actions/workflows/build.yml">
|
|
10
|
+
<img src="https://github.com/esmnext/esmx/actions/workflows/build.yml/badge.svg" alt="Build" />
|
|
11
|
+
</a>
|
|
12
|
+
<a href="https://www.esmnext.com/coverage/">
|
|
13
|
+
<img src="https://img.shields.io/badge/coverage-live%20report-brightgreen" alt="Coverage Report" />
|
|
14
|
+
</a>
|
|
15
|
+
<a href="https://nodejs.org/">
|
|
16
|
+
<img src="https://img.shields.io/node/v/@esmx/router.svg" alt="node version" />
|
|
17
|
+
</a>
|
|
18
|
+
<a href="https://bundlephobia.com/package/@esmx/router">
|
|
19
|
+
<img src="https://img.shields.io/bundlephobia/minzip/@esmx/router" alt="size" />
|
|
20
|
+
</a>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<p>A universal, framework-agnostic router that works seamlessly with modern frontend frameworks</p>
|
|
24
|
+
|
|
25
|
+
<p>
|
|
26
|
+
English | <a href="https://github.com/esmnext/esmx/blob/master/packages/router/README.zh-CN.md">中文</a>
|
|
27
|
+
</p>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
## 🚀 Features
|
|
31
|
+
|
|
32
|
+
- **Framework Agnostic** - Works with any frontend framework (Vue, React, Preact, Solid, etc.)
|
|
33
|
+
- **Universal Support** - Runs in both browser and Node.js environments
|
|
34
|
+
- **TypeScript Ready** - Full TypeScript support with excellent type inference
|
|
35
|
+
- **High Performance** - Optimized for production use with minimal bundle size
|
|
36
|
+
- **SSR Compatible** - Complete server-side rendering support
|
|
37
|
+
- **Modern API** - Clean and intuitive API design
|
|
38
|
+
|
|
39
|
+
## 📦 Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install @esmx/router
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 🚀 Quick Start
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { Router, RouterMode } from '@esmx/router';
|
|
49
|
+
|
|
50
|
+
// Create router instance
|
|
51
|
+
const router = new Router({
|
|
52
|
+
root: '#app', // Required in browser environment
|
|
53
|
+
mode: RouterMode.history,
|
|
54
|
+
routes: [
|
|
55
|
+
{ path: '/', component: () => 'Home Page' },
|
|
56
|
+
{ path: '/about', component: () => 'About Page' }
|
|
57
|
+
]
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Navigate to route
|
|
61
|
+
await router.push('/about');
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 📚 Documentation
|
|
65
|
+
|
|
66
|
+
Visit the [official documentation](https://www.esmnext.com) for detailed usage guides and API reference.
|
|
67
|
+
|
|
68
|
+
## 📄 License
|
|
69
|
+
|
|
70
|
+
MIT © [Esmx Team](https://github.com/esmnext/esmx)
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="https://www.esmnext.com/logo.svg?t=2025" width="120" alt="Esmx Logo" />
|
|
3
|
+
<h1>@esmx/router</h1>
|
|
4
|
+
|
|
5
|
+
<div>
|
|
6
|
+
<a href="https://www.npmjs.com/package/@esmx/router">
|
|
7
|
+
<img src="https://img.shields.io/npm/v/@esmx/router.svg" alt="npm version" />
|
|
8
|
+
</a>
|
|
9
|
+
<a href="https://github.com/esmnext/esmx/actions/workflows/build.yml">
|
|
10
|
+
<img src="https://github.com/esmnext/esmx/actions/workflows/build.yml/badge.svg" alt="Build" />
|
|
11
|
+
</a>
|
|
12
|
+
<a href="https://www.esmnext.com/coverage/">
|
|
13
|
+
<img src="https://img.shields.io/badge/coverage-live%20report-brightgreen" alt="Coverage Report" />
|
|
14
|
+
</a>
|
|
15
|
+
<a href="https://nodejs.org/">
|
|
16
|
+
<img src="https://img.shields.io/node/v/@esmx/router.svg" alt="node version" />
|
|
17
|
+
</a>
|
|
18
|
+
<a href="https://bundlephobia.com/package/@esmx/router">
|
|
19
|
+
<img src="https://img.shields.io/bundlephobia/minzip/@esmx/router" alt="size" />
|
|
20
|
+
</a>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<p>通用的框架无关路由器,与现代前端框架无缝协作</p>
|
|
24
|
+
|
|
25
|
+
<p>
|
|
26
|
+
<a href="https://github.com/esmnext/esmx/blob/master/packages/router/README.md">English</a> | 中文
|
|
27
|
+
</p>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
## 🚀 特性
|
|
31
|
+
|
|
32
|
+
- **框架无关** - 适用于任何前端框架(Vue、React、Preact、Solid 等)
|
|
33
|
+
- **通用支持** - 在浏览器和 Node.js 环境中运行
|
|
34
|
+
- **TypeScript 就绪** - 完整的 TypeScript 支持,出色的类型推断
|
|
35
|
+
- **高性能** - 为生产环境优化,最小化包体积
|
|
36
|
+
- **SSR 兼容** - 完整的服务端渲染支持
|
|
37
|
+
- **现代 API** - 简洁直观的 API 设计
|
|
38
|
+
|
|
39
|
+
## 📦 安装
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install @esmx/router
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 🚀 快速开始
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { Router, RouterMode } from '@esmx/router';
|
|
49
|
+
|
|
50
|
+
// 创建路由器实例
|
|
51
|
+
const router = new Router({
|
|
52
|
+
root: '#app', // 浏览器环境中必需
|
|
53
|
+
mode: RouterMode.history,
|
|
54
|
+
routes: [
|
|
55
|
+
{ path: '/', component: () => '首页' },
|
|
56
|
+
{ path: '/about', component: () => '关于页面' }
|
|
57
|
+
]
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// 导航到路由
|
|
61
|
+
await router.push('/about');
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 📚 文档
|
|
65
|
+
|
|
66
|
+
访问[官方文档](https://www.esmnext.com)获取详细的使用指南和 API 参考。
|
|
67
|
+
|
|
68
|
+
## 📄 许可证
|
|
69
|
+
|
|
70
|
+
MIT © [Esmx Team](https://github.com/esmnext/esmx)
|
package/dist/error.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Route } from './route';
|
|
2
|
+
export declare class RouteError extends Error {
|
|
3
|
+
readonly code: string;
|
|
4
|
+
readonly to: Route;
|
|
5
|
+
readonly from: Route | null;
|
|
6
|
+
constructor(message: string, code: string, to: Route, from?: Route | null);
|
|
7
|
+
}
|
|
8
|
+
export declare class RouteTaskCancelledError extends RouteError {
|
|
9
|
+
readonly taskName: string;
|
|
10
|
+
constructor(taskName: string, to: Route, from?: Route | null);
|
|
11
|
+
}
|
|
12
|
+
export declare class RouteTaskExecutionError extends RouteError {
|
|
13
|
+
readonly taskName: string;
|
|
14
|
+
readonly originalError: Error;
|
|
15
|
+
constructor(taskName: string, to: Route, from?: Route | null, originalError?: unknown);
|
|
16
|
+
}
|
|
17
|
+
export declare class RouteNavigationAbortedError extends RouteError {
|
|
18
|
+
readonly taskName: string;
|
|
19
|
+
constructor(taskName: string, to: Route, from?: Route | null);
|
|
20
|
+
}
|
|
21
|
+
export declare class RouteSelfRedirectionError extends RouteError {
|
|
22
|
+
constructor(fullPath: string, to: Route, from?: Route | null);
|
|
23
|
+
}
|
package/dist/error.mjs
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export class RouteError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
to;
|
|
4
|
+
from;
|
|
5
|
+
constructor(message, code, to, from = null) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "RouteError";
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.to = to;
|
|
10
|
+
this.from = from;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class RouteTaskCancelledError extends RouteError {
|
|
14
|
+
taskName;
|
|
15
|
+
constructor(taskName, to, from = null) {
|
|
16
|
+
super(
|
|
17
|
+
`Route task "${taskName}" was cancelled`,
|
|
18
|
+
"ROUTE_TASK_CANCELLED",
|
|
19
|
+
to,
|
|
20
|
+
from
|
|
21
|
+
);
|
|
22
|
+
this.name = "RouteTaskCancelledError";
|
|
23
|
+
this.taskName = taskName;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export class RouteTaskExecutionError extends RouteError {
|
|
27
|
+
taskName;
|
|
28
|
+
originalError;
|
|
29
|
+
constructor(taskName, to, from = null, originalError) {
|
|
30
|
+
const error = originalError instanceof Error ? originalError : new Error(String(originalError));
|
|
31
|
+
const message = `Route task "${taskName}" failed${error.message ? `: ${error.message}` : ""}`;
|
|
32
|
+
super(message, "ROUTE_TASK_EXECUTION_ERROR", to, from);
|
|
33
|
+
this.name = "RouteTaskExecutionError";
|
|
34
|
+
this.taskName = taskName;
|
|
35
|
+
this.originalError = error;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export class RouteNavigationAbortedError extends RouteError {
|
|
39
|
+
taskName;
|
|
40
|
+
constructor(taskName, to, from = null) {
|
|
41
|
+
super(
|
|
42
|
+
`Navigation was aborted by task "${taskName}"`,
|
|
43
|
+
"ROUTE_NAVIGATION_ABORTED",
|
|
44
|
+
to,
|
|
45
|
+
from
|
|
46
|
+
);
|
|
47
|
+
this.name = "RouteNavigationAbortedError";
|
|
48
|
+
this.taskName = taskName;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export class RouteSelfRedirectionError extends RouteError {
|
|
52
|
+
constructor(fullPath, to, from = null) {
|
|
53
|
+
super(
|
|
54
|
+
`Detected a self-redirection to "${fullPath}". Aborting navigation.`,
|
|
55
|
+
"ROUTE_SELF_REDIRECTION",
|
|
56
|
+
to,
|
|
57
|
+
from
|
|
58
|
+
);
|
|
59
|
+
this.name = "RouteSelfRedirectionError";
|
|
60
|
+
}
|
|
61
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export
|
|
3
|
-
export
|
|
1
|
+
export { Router } from './router';
|
|
2
|
+
export { Route } from './route';
|
|
3
|
+
export { RouteTransition, ROUTE_TYPE_HANDLERS } from './route-transition';
|
|
4
|
+
export { type Awaitable, RouterMode, RouteType, type RouteConfirmHook, type RouteConfirmHookResult, type RouteVerifyHook, type RouteHandleHook, type RouteNotifyHook, type RouteMeta, type RouteState, type RouteHandleResult, type RouteMatchType, type RouteLocation, type RouteLocationInput, type RouteConfig, type RouteParsedConfig, type RouteMatchResult, type RouteMatcher, type RouteOptions, type RouteLayerOptions, type RouteLayerResult, type RouterLayerOptions, type RouterMicroApp, type RouterMicroAppCallback, type RouterMicroAppOptions, type RouterOptions, type RouterParsedOptions, type RouterLinkType, type RouterLinkAttributes, type RouterLinkProps, type RouterLinkResolved } from './types';
|
|
5
|
+
export { RouteError, RouteTaskCancelledError, RouteTaskExecutionError, RouteNavigationAbortedError, RouteSelfRedirectionError } from './error';
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export
|
|
3
|
-
export
|
|
1
|
+
export { Router } from "./router.mjs";
|
|
2
|
+
export { Route } from "./route.mjs";
|
|
3
|
+
export { RouteTransition, ROUTE_TYPE_HANDLERS } from "./route-transition.mjs";
|
|
4
|
+
export {
|
|
5
|
+
RouterMode,
|
|
6
|
+
RouteType
|
|
7
|
+
} from "./types.mjs";
|
|
8
|
+
export {
|
|
9
|
+
RouteError,
|
|
10
|
+
RouteTaskCancelledError,
|
|
11
|
+
RouteTaskExecutionError,
|
|
12
|
+
RouteNavigationAbortedError,
|
|
13
|
+
RouteSelfRedirectionError
|
|
14
|
+
} from "./error.mjs";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { Router as IndexRouter } from "./index.mjs";
|
|
3
|
+
import { Router } from "./router.mjs";
|
|
4
|
+
describe("index exports", () => {
|
|
5
|
+
it("should export Router correctly", () => {
|
|
6
|
+
expect(IndexRouter).toBe(Router);
|
|
7
|
+
});
|
|
8
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { RouteLocationInput } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Normalizes a URL input into a URL object.
|
|
4
|
+
* @param url - The URL or string to normalize.
|
|
5
|
+
* @param base - The base URL to resolve against if the input is relative.
|
|
6
|
+
* @returns A URL object.
|
|
7
|
+
*/
|
|
8
|
+
export declare function normalizeURL(url: string | URL, base: URL): URL;
|
|
9
|
+
/**
|
|
10
|
+
* Parses a RouteLocationInput object into a full URL.
|
|
11
|
+
* @param toInput - The route location input.
|
|
12
|
+
* @param baseURL - The base URL to resolve against.
|
|
13
|
+
* @returns The parsed URL object.
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseLocation(toInput: RouteLocationInput, baseURL: URL): URL;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { isNotNullish } from "./util.mjs";
|
|
2
|
+
export function normalizeURL(url, base) {
|
|
3
|
+
if (url instanceof URL) {
|
|
4
|
+
return url;
|
|
5
|
+
}
|
|
6
|
+
if (url.startsWith("//")) {
|
|
7
|
+
return new URL(`http:${url}`);
|
|
8
|
+
}
|
|
9
|
+
if (url.startsWith("/")) {
|
|
10
|
+
const newBase = new URL(".", base);
|
|
11
|
+
const parsed = new URL(url, newBase);
|
|
12
|
+
parsed.pathname = newBase.pathname.slice(0, -1) + parsed.pathname;
|
|
13
|
+
return parsed;
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
return new URL(url);
|
|
17
|
+
} catch (e) {
|
|
18
|
+
return new URL(url, base);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function parseLocation(toInput, baseURL) {
|
|
22
|
+
if (typeof toInput === "string") {
|
|
23
|
+
return normalizeURL(toInput, baseURL);
|
|
24
|
+
}
|
|
25
|
+
const url = normalizeURL(toInput.path ?? toInput.url ?? "", baseURL);
|
|
26
|
+
const searchParams = url.searchParams;
|
|
27
|
+
const mergedQuery = {};
|
|
28
|
+
if (toInput.query) {
|
|
29
|
+
Object.entries(toInput.query).forEach(([key, value]) => {
|
|
30
|
+
if (typeof value !== "undefined") {
|
|
31
|
+
mergedQuery[key] = value;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
if (toInput.queryArray) {
|
|
36
|
+
Object.entries(toInput.queryArray).forEach(([key, value]) => {
|
|
37
|
+
if (typeof value !== "undefined") {
|
|
38
|
+
mergedQuery[key] = value;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
Object.entries(mergedQuery).forEach(([key, value]) => {
|
|
43
|
+
searchParams.delete(key);
|
|
44
|
+
value = Array.isArray(value) ? value : [value];
|
|
45
|
+
value.filter((v) => isNotNullish(v) && !Number.isNaN(v)).forEach((v) => {
|
|
46
|
+
searchParams.append(key, String(v));
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
if (toInput.hash) {
|
|
50
|
+
url.hash = toInput.hash;
|
|
51
|
+
}
|
|
52
|
+
return url;
|
|
53
|
+
}
|