soseki 0.0.5 → 0.0.6
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 +21 -0
- package/dist/src/components/browser-router.d.ts +19 -0
- package/dist/src/components/browser-router.d.ts.map +1 -0
- package/dist/src/components/browser-router.jsx +15 -0
- package/dist/src/components/outlet.d.ts +8 -0
- package/dist/src/components/outlet.d.ts.map +1 -0
- package/dist/src/components/outlet.jsx +15 -0
- package/dist/src/components/router.d.ts +21 -0
- package/dist/src/components/router.d.ts.map +1 -0
- package/dist/src/components/router.jsx +138 -0
- package/dist/src/contexts/route-context.d.ts +19 -0
- package/dist/src/contexts/route-context.d.ts.map +1 -0
- package/dist/src/contexts/route-context.js +6 -0
- package/dist/src/contexts/router-context.d.ts +55 -0
- package/dist/src/contexts/router-context.d.ts.map +1 -0
- package/dist/src/contexts/router-context.js +8 -0
- package/dist/src/core/_compare-route-paths.d.ts +11 -0
- package/dist/src/core/_compare-route-paths.d.ts.map +1 -0
- package/dist/src/core/_compare-route-paths.js +92 -0
- package/dist/src/core/_match-route-path.d.ts +22 -0
- package/dist/src/core/_match-route-path.d.ts.map +1 -0
- package/dist/src/core/_match-route-path.js +26 -0
- package/dist/src/core/_process-routes.d.ts +14 -0
- package/dist/src/core/_process-routes.d.ts.map +1 -0
- package/dist/src/core/_process-routes.js +45 -0
- package/dist/src/core/_singleton.d.ts +12 -0
- package/dist/src/core/_singleton.d.ts.map +1 -0
- package/dist/src/core/_singleton.js +18 -0
- package/dist/src/core/_unreachable.d.ts +16 -0
- package/dist/src/core/_unreachable.d.ts.map +1 -0
- package/dist/src/core/_unreachable.js +8 -0
- package/dist/src/core/_valibot.d.ts +25 -0
- package/dist/src/core/_valibot.d.ts.map +1 -0
- package/dist/src/core/_valibot.js +30 -0
- package/dist/src/core/errors.d.ts +182 -0
- package/dist/src/core/errors.d.ts.map +1 -0
- package/dist/src/core/errors.js +166 -0
- package/dist/src/core/expect-history-entry.d.ts +59 -0
- package/dist/src/core/expect-history-entry.d.ts.map +1 -0
- package/dist/src/core/expect-history-entry.js +42 -0
- package/dist/src/core/form-data-to-html-form-element.d.ts +11 -0
- package/dist/src/core/form-data-to-html-form-element.d.ts.map +1 -0
- package/dist/src/core/form-data-to-html-form-element.js +31 -0
- package/dist/src/core/history-entry-id-schema.d.ts +17 -0
- package/dist/src/core/history-entry-id-schema.d.ts.map +1 -0
- package/dist/src/core/history-entry-id-schema.js +9 -0
- package/dist/src/core/history-entry-url-schema.d.ts +18 -0
- package/dist/src/core/history-entry-url-schema.d.ts.map +1 -0
- package/dist/src/core/history-entry-url-schema.js +20 -0
- package/dist/src/core/init-loaders.d.ts +28 -0
- package/dist/src/core/init-loaders.d.ts.map +1 -0
- package/dist/src/core/init-loaders.js +30 -0
- package/dist/src/core/match-routes.d.ts +28 -0
- package/dist/src/core/match-routes.d.ts.map +1 -0
- package/dist/src/core/match-routes.js +31 -0
- package/dist/src/core/readonly-form-data.types.d.ts +74 -0
- package/dist/src/core/readonly-form-data.types.d.ts.map +1 -0
- package/dist/src/core/readonly-url.types.d.ts +164 -0
- package/dist/src/core/readonly-url.types.d.ts.map +1 -0
- package/dist/src/core/redirect-response.d.ts +37 -0
- package/dist/src/core/redirect-response.d.ts.map +1 -0
- package/dist/src/core/redirect-response.js +19 -0
- package/dist/src/core/route-path.d.ts +57 -0
- package/dist/src/core/route-path.d.ts.map +1 -0
- package/dist/src/core/route-path.js +93 -0
- package/dist/src/core/route-request.d.ts +149 -0
- package/dist/src/core/route-request.d.ts.map +1 -0
- package/dist/src/core/route-request.js +41 -0
- package/dist/src/core/route.types.d.ts +296 -0
- package/dist/src/core/route.types.d.ts.map +1 -0
- package/dist/src/core/start-action.d.ts +53 -0
- package/dist/src/core/start-action.d.ts.map +1 -0
- package/dist/src/core/start-action.js +95 -0
- package/dist/src/core/start-loaders.d.ts +63 -0
- package/dist/src/core/start-loaders.d.ts.map +1 -0
- package/dist/src/core/start-loaders.js +138 -0
- package/dist/{core.d.ts → src/core.d.ts} +7 -11
- package/dist/src/core.d.ts.map +1 -0
- package/dist/{core.js → src/core.js} +2 -4
- package/dist/src/engines/engine.types.d.ts +216 -0
- package/dist/src/engines/engine.types.d.ts.map +1 -0
- package/dist/src/engines/navigation-api-engine.d.ts +50 -0
- package/dist/src/engines/navigation-api-engine.d.ts.map +1 -0
- package/dist/src/engines/navigation-api-engine.js +411 -0
- package/dist/src/engines.d.ts +4 -0
- package/dist/src/engines.d.ts.map +1 -0
- package/dist/src/engines.js +1 -0
- package/dist/src/hooks/_use-singleton.d.ts +11 -0
- package/dist/src/hooks/_use-singleton.d.ts.map +1 -0
- package/dist/src/hooks/_use-singleton.js +26 -0
- package/dist/src/hooks/use-action-data.d.ts +17 -0
- package/dist/src/hooks/use-action-data.d.ts.map +1 -0
- package/dist/src/hooks/use-action-data.js +16 -0
- package/dist/src/hooks/use-form-action.d.ts +7 -0
- package/dist/src/hooks/use-form-action.d.ts.map +1 -0
- package/dist/src/hooks/use-form-action.js +9 -0
- package/dist/src/hooks/use-loader-data.d.ts +9 -0
- package/dist/src/hooks/use-loader-data.d.ts.map +1 -0
- package/dist/src/hooks/use-loader-data.js +20 -0
- package/dist/src/hooks/use-navigate.d.ts +53 -0
- package/dist/src/hooks/use-navigate.d.ts.map +1 -0
- package/dist/src/hooks/use-navigate.js +43 -0
- package/dist/{hooks → src/hooks}/use-params.d.ts +2 -2
- package/dist/src/hooks/use-params.d.ts.map +1 -0
- package/dist/{hooks → src/hooks}/use-params.js +1 -1
- package/dist/src/hooks/use-route-context.d.ts +10 -0
- package/dist/src/hooks/use-route-context.d.ts.map +1 -0
- package/dist/src/hooks/use-route-context.js +17 -0
- package/dist/src/hooks/use-router-context.d.ts +12 -0
- package/dist/src/hooks/use-router-context.d.ts.map +1 -0
- package/dist/src/hooks/use-router-context.js +20 -0
- package/dist/src/hooks/use-submit.d.ts +59 -0
- package/dist/src/hooks/use-submit.d.ts.map +1 -0
- package/dist/src/hooks/use-submit.js +38 -0
- package/dist/src/soseki.d.ts +31 -0
- package/dist/src/soseki.d.ts.map +1 -0
- package/dist/src/soseki.js +12 -0
- package/dist/src/utils/redirect.d.ts +11 -0
- package/dist/src/utils/redirect.d.ts.map +1 -0
- package/dist/src/utils/redirect.js +12 -0
- package/package.json +47 -40
- package/src/components/browser-router.tsx +8 -11
- package/src/components/outlet.tsx +3 -2
- package/src/components/router.tsx +139 -145
- package/src/contexts/route-context.ts +6 -5
- package/src/contexts/router-context.ts +36 -19
- package/src/core/_compare-route-paths.ts +48 -34
- package/src/core/_match-route-path.ts +21 -15
- package/src/core/_process-routes.ts +44 -46
- package/src/core/_singleton.ts +13 -38
- package/src/core/_unreachable.ts +12 -7
- package/src/core/_valibot.ts +19 -116
- package/src/core/errors.ts +150 -495
- package/src/core/expect-history-entry.ts +40 -41
- package/src/core/form-data-to-html-form-element.ts +37 -0
- package/src/core/history-entry-id-schema.ts +6 -11
- package/src/core/history-entry-url-schema.ts +25 -18
- package/src/core/init-loaders.ts +35 -57
- package/src/core/match-routes.ts +33 -65
- package/src/core/readonly-form-data.types.ts +48 -28
- package/src/core/readonly-url.types.ts +57 -28
- package/src/core/redirect-response.ts +26 -15
- package/src/core/route-path.ts +114 -0
- package/src/core/route-request.ts +144 -32
- package/src/core/route.types.ts +250 -226
- package/src/core/start-action.ts +164 -0
- package/src/core/start-loaders.ts +190 -212
- package/src/core.ts +8 -15
- package/src/engines/engine.types.ts +204 -166
- package/src/engines/navigation-api-engine.ts +332 -233
- package/src/engines.ts +4 -0
- package/src/hooks/_use-singleton.ts +30 -0
- package/src/hooks/use-action-data.ts +21 -26
- package/src/hooks/use-form-action.ts +4 -5
- package/src/hooks/use-loader-data.ts +16 -18
- package/src/hooks/use-navigate.ts +69 -28
- package/src/hooks/use-params.ts +4 -4
- package/src/hooks/use-route-context.ts +20 -0
- package/src/hooks/use-router-context.ts +25 -0
- package/src/hooks/use-submit.ts +48 -53
- package/src/soseki.ts +27 -34
- package/src/utils/redirect.ts +5 -5
- package/dist/components/action-id.d.ts +0 -19
- package/dist/components/action-id.d.ts.map +0 -1
- package/dist/components/action-id.jsx +0 -14
- package/dist/components/browser-router.d.ts +0 -17
- package/dist/components/browser-router.d.ts.map +0 -1
- package/dist/components/browser-router.jsx +0 -13
- package/dist/components/hidden-input.d.ts +0 -20
- package/dist/components/hidden-input.d.ts.map +0 -1
- package/dist/components/hidden-input.jsx +0 -8
- package/dist/components/outlet.d.ts +0 -8
- package/dist/components/outlet.d.ts.map +0 -1
- package/dist/components/outlet.jsx +0 -15
- package/dist/components/router.d.ts +0 -23
- package/dist/components/router.d.ts.map +0 -1
- package/dist/components/router.jsx +0 -128
- package/dist/contexts/route-context.d.ts +0 -19
- package/dist/contexts/route-context.d.ts.map +0 -1
- package/dist/contexts/route-context.js +0 -6
- package/dist/contexts/router-context.d.ts +0 -46
- package/dist/contexts/router-context.d.ts.map +0 -1
- package/dist/contexts/router-context.js +0 -8
- package/dist/core/_action-id-registry.d.ts +0 -10
- package/dist/core/_action-id-registry.d.ts.map +0 -1
- package/dist/core/_action-id-registry.js +0 -8
- package/dist/core/_capture-stack-trace.d.ts +0 -8
- package/dist/core/_capture-stack-trace.d.ts.map +0 -1
- package/dist/core/_capture-stack-trace.js +0 -12
- package/dist/core/_compare-route-paths.d.ts +0 -11
- package/dist/core/_compare-route-paths.d.ts.map +0 -1
- package/dist/core/_compare-route-paths.js +0 -80
- package/dist/core/_create-html-form-element-form-form-data.d.ts +0 -9
- package/dist/core/_create-html-form-element-form-form-data.d.ts.map +0 -1
- package/dist/core/_create-html-form-element-form-form-data.js +0 -27
- package/dist/core/_encode-pathname.d.ts +0 -10
- package/dist/core/_encode-pathname.d.ts.map +0 -1
- package/dist/core/_encode-pathname.js +0 -16
- package/dist/core/_is-error.d.ts +0 -3
- package/dist/core/_is-error.d.ts.map +0 -1
- package/dist/core/_is-error.js +0 -13
- package/dist/core/_is-promise-like.d.ts +0 -8
- package/dist/core/_is-promise-like.d.ts.map +0 -1
- package/dist/core/_is-promise-like.js +0 -12
- package/dist/core/_match-route-path.d.ts +0 -19
- package/dist/core/_match-route-path.d.ts.map +0 -1
- package/dist/core/_match-route-path.js +0 -22
- package/dist/core/_process-routes.d.ts +0 -9
- package/dist/core/_process-routes.d.ts.map +0 -1
- package/dist/core/_process-routes.js +0 -47
- package/dist/core/_singleton.d.ts +0 -18
- package/dist/core/_singleton.d.ts.map +0 -1
- package/dist/core/_singleton.js +0 -37
- package/dist/core/_unreachable.d.ts +0 -12
- package/dist/core/_unreachable.d.ts.map +0 -1
- package/dist/core/_unreachable.js +0 -8
- package/dist/core/_use-singleton.d.ts +0 -11
- package/dist/core/_use-singleton.d.ts.map +0 -1
- package/dist/core/_use-singleton.js +0 -21
- package/dist/core/_valibot.d.ts +0 -52
- package/dist/core/_valibot.d.ts.map +0 -1
- package/dist/core/_valibot.js +0 -107
- package/dist/core/_weak-id-registry.d.ts +0 -76
- package/dist/core/_weak-id-registry.d.ts.map +0 -1
- package/dist/core/_weak-id-registry.js +0 -67
- package/dist/core/constants.d.ts +0 -5
- package/dist/core/constants.d.ts.map +0 -1
- package/dist/core/constants.js +0 -4
- package/dist/core/data-map.types.d.ts +0 -23
- package/dist/core/data-map.types.d.ts.map +0 -1
- package/dist/core/data-map.types.js +0 -1
- package/dist/core/data-store.types.d.ts +0 -22
- package/dist/core/data-store.types.d.ts.map +0 -1
- package/dist/core/data-store.types.js +0 -1
- package/dist/core/deferred-promise.d.ts +0 -203
- package/dist/core/deferred-promise.d.ts.map +0 -1
- package/dist/core/deferred-promise.js +0 -200
- package/dist/core/errors.d.ts +0 -303
- package/dist/core/errors.d.ts.map +0 -1
- package/dist/core/errors.js +0 -400
- package/dist/core/expect-history-entry.d.ts +0 -52
- package/dist/core/expect-history-entry.d.ts.map +0 -1
- package/dist/core/expect-history-entry.js +0 -38
- package/dist/core/history-entry-id-schema.d.ts +0 -17
- package/dist/core/history-entry-id-schema.d.ts.map +0 -1
- package/dist/core/history-entry-id-schema.js +0 -9
- package/dist/core/history-entry-url-schema.d.ts +0 -20
- package/dist/core/history-entry-url-schema.d.ts.map +0 -1
- package/dist/core/history-entry-url-schema.js +0 -16
- package/dist/core/init-loaders.d.ts +0 -37
- package/dist/core/init-loaders.d.ts.map +0 -1
- package/dist/core/init-loaders.js +0 -38
- package/dist/core/match-routes.d.ts +0 -31
- package/dist/core/match-routes.d.ts.map +0 -1
- package/dist/core/match-routes.js +0 -54
- package/dist/core/readonly-form-data.types.d.ts +0 -32
- package/dist/core/readonly-form-data.types.d.ts.map +0 -1
- package/dist/core/readonly-url.types.d.ts +0 -135
- package/dist/core/readonly-url.types.d.ts.map +0 -1
- package/dist/core/redirect-response.d.ts +0 -29
- package/dist/core/redirect-response.d.ts.map +0 -1
- package/dist/core/redirect-response.js +0 -17
- package/dist/core/route-request.d.ts +0 -52
- package/dist/core/route-request.d.ts.map +0 -1
- package/dist/core/route-request.js +0 -26
- package/dist/core/route.types.d.ts +0 -309
- package/dist/core/route.types.d.ts.map +0 -1
- package/dist/core/start-actions.d.ts +0 -60
- package/dist/core/start-actions.d.ts.map +0 -1
- package/dist/core/start-actions.js +0 -186
- package/dist/core/start-loaders.d.ts +0 -69
- package/dist/core/start-loaders.d.ts.map +0 -1
- package/dist/core/start-loaders.js +0 -154
- package/dist/core.d.ts.map +0 -1
- package/dist/engines/engine.types.d.ts +0 -190
- package/dist/engines/engine.types.d.ts.map +0 -1
- package/dist/engines/navigation-api-engine.d.ts +0 -48
- package/dist/engines/navigation-api-engine.d.ts.map +0 -1
- package/dist/engines/navigation-api-engine.js +0 -332
- package/dist/hooks/_use-route-context.d.ts +0 -10
- package/dist/hooks/_use-route-context.d.ts.map +0 -1
- package/dist/hooks/_use-route-context.js +0 -17
- package/dist/hooks/_use-router-context.d.ts +0 -10
- package/dist/hooks/_use-router-context.d.ts.map +0 -1
- package/dist/hooks/_use-router-context.js +0 -18
- package/dist/hooks/use-action-data.d.ts +0 -23
- package/dist/hooks/use-action-data.d.ts.map +0 -1
- package/dist/hooks/use-action-data.js +0 -16
- package/dist/hooks/use-form-action.d.ts +0 -7
- package/dist/hooks/use-form-action.d.ts.map +0 -1
- package/dist/hooks/use-form-action.js +0 -10
- package/dist/hooks/use-loader-data.d.ts +0 -11
- package/dist/hooks/use-loader-data.d.ts.map +0 -1
- package/dist/hooks/use-loader-data.js +0 -19
- package/dist/hooks/use-navigate.d.ts +0 -39
- package/dist/hooks/use-navigate.d.ts.map +0 -1
- package/dist/hooks/use-navigate.js +0 -26
- package/dist/hooks/use-params.d.ts.map +0 -1
- package/dist/hooks/use-pathname.d.ts +0 -7
- package/dist/hooks/use-pathname.d.ts.map +0 -1
- package/dist/hooks/use-pathname.js +0 -9
- package/dist/hooks/use-submit.d.ts +0 -66
- package/dist/hooks/use-submit.d.ts.map +0 -1
- package/dist/hooks/use-submit.js +0 -35
- package/dist/soseki.d.ts +0 -42
- package/dist/soseki.d.ts.map +0 -1
- package/dist/soseki.js +0 -19
- package/dist/utils/get-action-id.d.ts +0 -8
- package/dist/utils/get-action-id.d.ts.map +0 -1
- package/dist/utils/get-action-id.js +0 -11
- package/dist/utils/href.d.ts +0 -11
- package/dist/utils/href.d.ts.map +0 -1
- package/dist/utils/href.js +0 -12
- package/dist/utils/redirect.d.ts +0 -11
- package/dist/utils/redirect.d.ts.map +0 -1
- package/dist/utils/redirect.js +0 -12
- package/dist/utils/route-index.d.ts +0 -41
- package/dist/utils/route-index.d.ts.map +0 -1
- package/dist/utils/route-index.js +0 -12
- package/dist/utils/route-route.d.ts +0 -62
- package/dist/utils/route-route.d.ts.map +0 -1
- package/dist/utils/route-route.js +0 -25
- package/dist/utils/set-action-id.d.ts +0 -9
- package/dist/utils/set-action-id.d.ts.map +0 -1
- package/dist/utils/set-action-id.js +0 -12
- package/src/components/action-id.tsx +0 -35
- package/src/components/hidden-input.tsx +0 -39
- package/src/core/_action-id-registry.ts +0 -11
- package/src/core/_capture-stack-trace.ts +0 -12
- package/src/core/_create-html-form-element-form-form-data.ts +0 -32
- package/src/core/_encode-pathname.ts +0 -17
- package/src/core/_is-error.ts +0 -16
- package/src/core/_is-promise-like.ts +0 -14
- package/src/core/_use-singleton.ts +0 -24
- package/src/core/_weak-id-registry.ts +0 -125
- package/src/core/constants.ts +0 -4
- package/src/core/data-map.types.ts +0 -28
- package/src/core/data-store.types.ts +0 -25
- package/src/core/deferred-promise.ts +0 -408
- package/src/core/start-actions.ts +0 -274
- package/src/hooks/_use-route-context.ts +0 -19
- package/src/hooks/_use-router-context.ts +0 -25
- package/src/hooks/use-pathname.ts +0 -10
- package/src/utils/get-action-id.ts +0 -12
- package/src/utils/href.ts +0 -17
- package/src/utils/route-index.ts +0 -70
- package/src/utils/route-route.ts +0 -111
- package/src/utils/set-action-id.ts +0 -14
- /package/dist/{core → src/core}/readonly-form-data.types.js +0 -0
- /package/dist/{core → src/core}/readonly-url.types.js +0 -0
- /package/dist/{core → src/core}/route.types.js +0 -0
- /package/dist/{engines → src/engines}/engine.types.js +0 -0
|
@@ -1,233 +1,227 @@
|
|
|
1
|
+
import type { NinjaPromise } from "ninja-promise";
|
|
1
2
|
import * as React from "react";
|
|
3
|
+
|
|
2
4
|
import RouteContext from "../contexts/route-context.js";
|
|
3
5
|
import RouterContext, {
|
|
4
|
-
type RouterContextValue,
|
|
5
6
|
type RouterRef,
|
|
7
|
+
type RouterContextValue,
|
|
6
8
|
} from "../contexts/router-context.js";
|
|
7
9
|
import processRoutes from "../core/_process-routes.js";
|
|
8
|
-
import type { IDataStore } from "../core/data-store.types.js";
|
|
9
10
|
import type { HistoryEntry } from "../core/expect-history-entry.js";
|
|
11
|
+
import type { HistoryEntryId } from "../core/history-entry-id-schema.js";
|
|
10
12
|
import type { MatchedRoute } from "../core/match-routes.js";
|
|
11
|
-
import type {
|
|
12
|
-
import type { IEngine, RouterState
|
|
13
|
-
import type { NavigateArgs } from "../engines/engine.types.js";
|
|
13
|
+
import type { ActionFunction, LoaderFunction, RouteDefinition } from "../core/route.types.js";
|
|
14
|
+
import type { IEngine, RouterState } from "../engines/engine.types.js";
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
|
-
* ComponentRenderer コンポーネントに渡されるプロパティーの型定義です。
|
|
17
|
+
* `ComponentRenderer` コンポーネントに渡されるプロパティーの型定義です。
|
|
17
18
|
*/
|
|
18
19
|
type ComponentRendererProps = {
|
|
19
20
|
/**
|
|
20
|
-
*
|
|
21
|
+
* レンダリング対象となる、マッチした単一のルート情報です。
|
|
21
22
|
*/
|
|
22
23
|
route: MatchedRoute;
|
|
23
24
|
|
|
24
25
|
/**
|
|
25
|
-
*
|
|
26
|
+
* このルートの配下に描画されるべき子コンポーネントの要素です。
|
|
26
27
|
*/
|
|
27
28
|
outlet: React.ReactElement<RouteRendererProps, typeof RouteRenderer> | null;
|
|
28
29
|
};
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
|
-
*
|
|
32
|
+
* マッチした個々のルートコンポーネントを、固有の `RouteContext` で包み込みながら再帰的にマウント・展開していくための内部レンダラーコンポーネントです。
|
|
32
33
|
*/
|
|
33
34
|
function ComponentRenderer(props: ComponentRendererProps): React.JSX.Element | null {
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
path,
|
|
37
|
-
index,
|
|
38
|
-
params,
|
|
39
|
-
urlPath,
|
|
40
|
-
component: Component,
|
|
41
|
-
},
|
|
42
|
-
outlet,
|
|
43
|
-
} = props;
|
|
35
|
+
const parentRoute = React.use(RouteContext);
|
|
36
|
+
const { route, outlet } = props;
|
|
44
37
|
const context = {
|
|
45
|
-
|
|
46
|
-
index,
|
|
47
|
-
params,
|
|
38
|
+
...route,
|
|
48
39
|
outlet,
|
|
49
|
-
|
|
40
|
+
// 親ルートのアクションとローダーを引き継ぐことで、`useActionData` と `useLoaderData` がデータを参照できようにします。
|
|
41
|
+
action: route.action ?? parentRoute?.action,
|
|
42
|
+
loader: route.loader ?? parentRoute?.loader,
|
|
50
43
|
};
|
|
44
|
+
const Comp = route.component;
|
|
51
45
|
|
|
52
46
|
return (
|
|
53
|
-
<RouteContext value={context}>
|
|
54
|
-
{Component ? <Component /> : outlet}
|
|
55
|
-
</RouteContext>
|
|
47
|
+
<RouteContext value={context}>{typeof Comp === "function" ? <Comp /> : outlet}</RouteContext>
|
|
56
48
|
);
|
|
57
49
|
}
|
|
58
50
|
|
|
59
51
|
/**
|
|
60
|
-
*
|
|
52
|
+
* `RouteRenderer` コンポーネントに渡されるプロパティーの型定義です。
|
|
61
53
|
*/
|
|
62
54
|
type RouteRendererProps = {
|
|
63
55
|
/**
|
|
64
|
-
*
|
|
56
|
+
* マッチしたルートの階層配列です。
|
|
65
57
|
*/
|
|
66
58
|
routes: readonly MatchedRoute[];
|
|
67
59
|
|
|
68
60
|
/**
|
|
69
|
-
*
|
|
61
|
+
* 現在処理しているルート配列のインデックス(深さ)です。
|
|
70
62
|
*/
|
|
71
63
|
index?: number;
|
|
72
64
|
};
|
|
73
65
|
|
|
74
66
|
/**
|
|
75
|
-
*
|
|
67
|
+
* マッチしたルート配列を親から子の順番へと正しく巡回し、各階層を入れ子状の React エレメントツリーへと再帰的にビルドするコンポーネントです。
|
|
76
68
|
*/
|
|
77
69
|
function RouteRenderer(props: RouteRendererProps): React.ReactElement {
|
|
78
|
-
const {
|
|
79
|
-
index = 0,
|
|
80
|
-
routes,
|
|
81
|
-
} = props;
|
|
70
|
+
const { index = 0, routes } = props;
|
|
82
71
|
const route = routes[index]!;
|
|
83
|
-
const outlet = index < routes.length - 1
|
|
84
|
-
? <RouteRenderer routes={routes} index={index + 1} />
|
|
85
|
-
: null;
|
|
86
72
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
);
|
|
73
|
+
// 配列の終端に達していない場合はインデックスを 1 進めて自身を再帰的に呼び出し、ネストされる子要素を生成します。
|
|
74
|
+
const outlet =
|
|
75
|
+
index < routes.length - 1 ? <RouteRenderer routes={routes} index={index + 1} /> : null;
|
|
76
|
+
|
|
77
|
+
return <ComponentRenderer route={route} outlet={outlet} />;
|
|
93
78
|
}
|
|
94
79
|
|
|
95
80
|
/**
|
|
96
|
-
* Router
|
|
81
|
+
* `Router` コンポーネントに渡されるルートプロパティーの型定義です。
|
|
97
82
|
*/
|
|
98
83
|
export type RouterProps = {
|
|
99
84
|
/**
|
|
100
|
-
*
|
|
85
|
+
* プラグイン形式で差し込まれる、ルーティングの実装です。
|
|
101
86
|
*/
|
|
102
87
|
engine: IEngine;
|
|
103
88
|
|
|
104
89
|
/**
|
|
105
|
-
*
|
|
90
|
+
* ユーザーがアプリケーションに定義したルート定義の配列です。
|
|
106
91
|
*/
|
|
107
92
|
routes: readonly RouteDefinition[];
|
|
108
93
|
};
|
|
109
94
|
|
|
110
95
|
/**
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* エンジンの管理、状態の同期、およびルートのレンダリングを担います。
|
|
96
|
+
* 宣言的なルート定義と、命令的なルーティング実行エンジンを仲介・統合し、アプリケーションの最上位でルーティングのライフサイクルと状態管理を司るプロバイダーコンポーネントです。
|
|
114
97
|
*/
|
|
115
98
|
export default function Router(props: RouterProps) {
|
|
116
|
-
const {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
99
|
+
const { engine, routes: routesProp } = props;
|
|
100
|
+
|
|
101
|
+
// レンダリングを跨いで常に同一参照を維持し、かつ子コンポーネントから不要な再レンダリングなしでメソッドを叩けるように、ルーターコアの外部参照実体を useRef で永続管理します。
|
|
102
|
+
const routerRef = React.useRef(
|
|
103
|
+
{} as {
|
|
104
|
+
submit(args: IEngine.SubmitArgs): void;
|
|
105
|
+
navigate(args: IEngine.NavigateArgs): void;
|
|
106
|
+
currentEntry: HistoryEntry;
|
|
107
|
+
actionDataStore: Map<HistoryEntryId, Map<ActionFunction, NinjaPromise<unknown>>>;
|
|
108
|
+
loaderDataStore: Map<HistoryEntryId, Map<LoaderFunction, NinjaPromise<unknown>>>;
|
|
109
|
+
},
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
// エンジン、ストア、イベント購読メカニズムのセットアップを一元化し、useMemo でインスタンス化します。
|
|
127
113
|
const router = React.useMemo<{
|
|
128
|
-
start()
|
|
129
|
-
context: RouterContextValue;
|
|
130
|
-
getRoutes()
|
|
131
|
-
}>(
|
|
132
|
-
()
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
114
|
+
readonly start: () => () => void;
|
|
115
|
+
readonly context: RouterContextValue;
|
|
116
|
+
readonly getRoutes: () => readonly MatchedRoute[] | undefined;
|
|
117
|
+
}>(() => {
|
|
118
|
+
const actionDataStore = new Map<HistoryEntryId, Map<ActionFunction, NinjaPromise<unknown>>>();
|
|
119
|
+
const loaderDataStore = new Map<HistoryEntryId, Map<LoaderFunction, NinjaPromise<unknown>>>();
|
|
120
|
+
const subscribers = new Set<() => void>();
|
|
121
|
+
const routes = processRoutes(routesProp);
|
|
122
|
+
let ac: AbortController | null = null;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* 現在のフェーズで有効な、シングルトン構造の中断シグナルをオンデマンドで生成・回収します。
|
|
126
|
+
*/
|
|
127
|
+
function getAbortSignal(): AbortSignal {
|
|
128
|
+
return (ac ||= new AbortController()).signal;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// エンジンを初期化し、初期ロード時のマッチングルートおよび解決済みのデータマップを取得・登録します。
|
|
132
|
+
const initialState = engine.init({
|
|
133
|
+
routes,
|
|
134
|
+
getSignal: getAbortSignal,
|
|
135
|
+
loaderDataStore,
|
|
136
|
+
});
|
|
137
|
+
let currentRoutes = initialState?.routes;
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* エンジン内部での遷移確定時に、状態を React 側へ通知・マージするための状態更新関数です。
|
|
141
|
+
*/
|
|
142
|
+
function updateRouter(newState?: RouterState | null) {
|
|
143
|
+
if (newState !== undefined) {
|
|
144
|
+
currentRoutes = newState?.routes;
|
|
141
145
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
routes,
|
|
145
|
-
getSignal: getAbortSignal,
|
|
146
|
-
loaderDataStore,
|
|
147
|
-
});
|
|
148
|
-
let currentRoutes = initialState?.routes;
|
|
149
|
-
|
|
150
|
-
function updateRouter(newState?: RouterState | null) {
|
|
151
|
-
if (newState !== undefined) {
|
|
152
|
-
currentRoutes = newState?.routes;
|
|
153
|
-
}
|
|
154
|
-
if (newState) {
|
|
155
|
-
routerRef.current.currentEntry = newState.entry;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// 登録されているすべてのサブスクライバーに通知します。
|
|
159
|
-
subscribers.forEach(notify => notify());
|
|
146
|
+
if (newState) {
|
|
147
|
+
routerRef.current.currentEntry = newState.entry;
|
|
160
148
|
}
|
|
161
149
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
update: updateRouter,
|
|
166
|
-
getSignal: getAbortSignal,
|
|
167
|
-
actionDataStore,
|
|
168
|
-
loaderDataStore,
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
return function stopRouterEngine() {
|
|
172
|
-
try {
|
|
173
|
-
// エンジンの動作を停止します。
|
|
174
|
-
stop?.();
|
|
175
|
-
} finally {
|
|
176
|
-
// 進行中のすべての非同期処理を中断します。
|
|
177
|
-
try {
|
|
178
|
-
ac?.abort();
|
|
179
|
-
} catch {
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// 中断後は次回の呼び出しに備えてコントローラーを破棄します。
|
|
183
|
-
ac = null;
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
}
|
|
150
|
+
// 状態変更の発生を、React の useSyncExternalStore などのすべての購読者に一斉通知して再描画を促します。
|
|
151
|
+
subscribers.forEach((notify) => notify());
|
|
152
|
+
}
|
|
187
153
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
154
|
+
/**
|
|
155
|
+
* エンジンによるイベントのリアルタイム監視を開始するトリガー関数です。
|
|
156
|
+
*/
|
|
157
|
+
function startRouterEngine() {
|
|
158
|
+
const stop = engine.start({
|
|
159
|
+
routes,
|
|
160
|
+
update: updateRouter,
|
|
161
|
+
getSignal: getAbortSignal,
|
|
196
162
|
actionDataStore,
|
|
197
163
|
loaderDataStore,
|
|
198
164
|
});
|
|
199
165
|
|
|
200
|
-
return {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
getRoutes() {
|
|
212
|
-
return currentRoutes;
|
|
213
|
-
},
|
|
166
|
+
return function stopRouterEngine() {
|
|
167
|
+
try {
|
|
168
|
+
if (typeof stop === "function") {
|
|
169
|
+
stop();
|
|
170
|
+
}
|
|
171
|
+
} finally {
|
|
172
|
+
try {
|
|
173
|
+
ac?.abort();
|
|
174
|
+
} catch {}
|
|
175
|
+
ac = null;
|
|
176
|
+
}
|
|
214
177
|
};
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// 作成した各種ストアや命令型メソッドの参照を、永続化 Ref オブジェクトへと安全にマージします。
|
|
181
|
+
Object.assign<RouterRef["current"], RouterRef["current"]>(routerRef.current, {
|
|
182
|
+
submit(args) {
|
|
183
|
+
return engine.submit(args);
|
|
184
|
+
},
|
|
185
|
+
navigate(args) {
|
|
186
|
+
return engine.navigate(args);
|
|
187
|
+
},
|
|
188
|
+
currentEntry: initialState?.entry as HistoryEntry,
|
|
189
|
+
actionDataStore,
|
|
190
|
+
loaderDataStore,
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
start: startRouterEngine,
|
|
195
|
+
context: {
|
|
196
|
+
routerRef,
|
|
197
|
+
subscribe(cb) {
|
|
198
|
+
subscribers.add(cb);
|
|
199
|
+
return () => {
|
|
200
|
+
subscribers.delete(cb);
|
|
201
|
+
};
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
getRoutes() {
|
|
205
|
+
return currentRoutes;
|
|
206
|
+
},
|
|
207
|
+
};
|
|
208
|
+
}, [engine, routesProp]);
|
|
221
209
|
|
|
222
|
-
|
|
210
|
+
// コンポーネントのマウント時にルーターエンジンを始動させ、アンマウント時には自動的に破棄タスクを連動させます。
|
|
211
|
+
React.useEffect(() => router.start(), [router]);
|
|
223
212
|
|
|
213
|
+
// マッチしたルート階層配列をリアクティブに常時監視します。
|
|
224
214
|
const routes = React.useSyncExternalStore(router.context.subscribe, router.getRoutes);
|
|
215
|
+
|
|
216
|
+
// 有効なルートマッチングがない場合は何も描画しません。
|
|
225
217
|
if (!routes) {
|
|
218
|
+
// TODO(tai-kun): 404 Not Found ページを表示できるようにします。
|
|
226
219
|
return null;
|
|
227
220
|
}
|
|
228
221
|
|
|
229
222
|
return (
|
|
230
223
|
<RouterContext value={router.context}>
|
|
224
|
+
{/* マッチルート配列は詳細度の高い「子 -> 親」の順で並んでいるため、React のネストレイアウト構造(親の中に子を入れる)に適合させるために `.toReversed()` で「親 -> 子」の順に反転させてからレンダラーへ投入します。*/}
|
|
231
225
|
<RouteRenderer routes={routes.toReversed()} />
|
|
232
226
|
</RouterContext>
|
|
233
227
|
);
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
+
|
|
2
3
|
import type { MatchedRoute } from "../core/match-routes.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
|
-
*
|
|
6
|
+
* 現在のコンポーネント階層に紐づいている個別ルートのコンテキスト形状定義です。
|
|
6
7
|
*/
|
|
7
|
-
export type RouteContextValue =
|
|
8
|
+
export type RouteContextValue = MatchedRoute & {
|
|
8
9
|
/**
|
|
9
|
-
*
|
|
10
|
+
* 現在のルートの下位に位置する子ルートを表示するための React 要素です。
|
|
10
11
|
*
|
|
11
|
-
*
|
|
12
|
+
* これ以上下位にマッチする子ルートが存在しない場合は `null` になります。
|
|
12
13
|
*/
|
|
13
14
|
readonly outlet: React.ReactElement | null;
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
|
-
*
|
|
18
|
+
* 階層的にネストされたルーターのレイアウト構造において、親ルートから子ルートへそれぞれの階層固有のルート情報伝播させるための React コンテキストです。
|
|
18
19
|
*/
|
|
19
20
|
const RouteContext = /*#__PURE__*/ React.createContext<RouteContextValue | null>(null);
|
|
20
21
|
|
|
@@ -1,54 +1,71 @@
|
|
|
1
|
+
import type { NinjaPromise } from "ninja-promise";
|
|
1
2
|
import * as React from "react";
|
|
2
|
-
|
|
3
|
+
|
|
3
4
|
import type { HistoryEntry } from "../core/expect-history-entry.js";
|
|
4
|
-
import type {
|
|
5
|
-
import type {
|
|
5
|
+
import type { HistoryEntryId } from "../core/history-entry-id-schema.js";
|
|
6
|
+
import type { ActionFunction, LoaderFunction } from "../core/route.types.js";
|
|
7
|
+
import type { IEngine } from "../engines/engine.types.js";
|
|
6
8
|
|
|
9
|
+
/**
|
|
10
|
+
* ルーターの実体へのアクセスを提供する、読み取り専用の Ref オブジェクト型です。
|
|
11
|
+
*/
|
|
7
12
|
export type RouterRef = Readonly<
|
|
8
13
|
React.RefObject<{
|
|
9
14
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* @param args 送信内容と送信先を含む引数です。
|
|
15
|
+
* フォームデータやクエリーパラメーターをルーターに送信するための関数です。
|
|
13
16
|
*/
|
|
14
|
-
readonly submit: (args: SubmitArgs) => void;
|
|
17
|
+
readonly submit: (args: IEngine.SubmitArgs) => void;
|
|
15
18
|
|
|
16
19
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* @param args 遷移先と遷移オプションを含む引数です。
|
|
20
|
+
* URL 遷移や履歴スタックの相対移動をルーターに命令するための関数です。
|
|
20
21
|
*/
|
|
21
|
-
readonly navigate: (args: NavigateArgs) => void;
|
|
22
|
+
readonly navigate: (args: IEngine.NavigateArgs) => void;
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
|
-
*
|
|
25
|
+
* 現在ブラウザー上でアクティブになっている履歴エントリーの情報です。
|
|
25
26
|
*/
|
|
26
27
|
readonly currentEntry: HistoryEntry;
|
|
27
28
|
|
|
28
29
|
/**
|
|
29
|
-
*
|
|
30
|
+
* 履歴エントリーの ID ごとにアクションの実行状態を管理するデータストアです。
|
|
30
31
|
*/
|
|
31
|
-
readonly actionDataStore:
|
|
32
|
+
readonly actionDataStore: ReadonlyMap<
|
|
33
|
+
HistoryEntryId,
|
|
34
|
+
ReadonlyMap<ActionFunction, NinjaPromise<unknown>>
|
|
35
|
+
>;
|
|
32
36
|
|
|
33
37
|
/**
|
|
34
|
-
*
|
|
38
|
+
* 履歴エントリーの ID ごとにローダーの実行状態を管理するデータストアです。
|
|
35
39
|
*/
|
|
36
|
-
readonly loaderDataStore:
|
|
40
|
+
readonly loaderDataStore: ReadonlyMap<
|
|
41
|
+
HistoryEntryId,
|
|
42
|
+
ReadonlyMap<LoaderFunction, NinjaPromise<unknown>>
|
|
43
|
+
>;
|
|
37
44
|
}>
|
|
38
45
|
>;
|
|
39
46
|
|
|
40
47
|
/**
|
|
41
|
-
*
|
|
48
|
+
* `RouterContext` がコンポーネントツリーの配下に供給するオブジェクトの型定義です。
|
|
42
49
|
*/
|
|
43
50
|
export type RouterContextValue = {
|
|
51
|
+
/**
|
|
52
|
+
* ルーターの最新実体への参照を保持する Ref オブジェクトです。
|
|
53
|
+
*/
|
|
44
54
|
readonly routerRef: RouterRef;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* ルーターの状態変更を監視するための購読関数です。
|
|
58
|
+
*
|
|
59
|
+
* @param onRouterChange ルーターの内部状態が変化した際に実行されるコールバック関数です。
|
|
60
|
+
* @returns 監視を安全に解除するためのクリーンアップ関数を返します。
|
|
61
|
+
*/
|
|
45
62
|
readonly subscribe: (onRouterChange: () => void) => () => void;
|
|
46
63
|
};
|
|
47
64
|
|
|
48
65
|
/**
|
|
49
|
-
*
|
|
66
|
+
* アプリケーションの最上位からルーターのグローバル状態を子コンポーネントへ一元的に伝播させるための React コンテキストです。
|
|
50
67
|
*
|
|
51
|
-
*
|
|
68
|
+
* パフォーマンス最適化のためにプロバイダー自体は基本的に更新されず、子コンポーネントは `subscribe` と `useSyncExternalStore`を使って必要な部分データだけを購読します。
|
|
52
69
|
*/
|
|
53
70
|
const RouterContext = /*#__PURE__*/ React.createContext<RouterContextValue | null>(null);
|
|
54
71
|
|
|
@@ -1,60 +1,74 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* セグメントの種類に応じたスコア定数です。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* 数値が大きいほど優先順位(詳細度)が高いです。
|
|
5
|
+
*
|
|
6
|
+
* 詳細度(regexparam の README より):
|
|
7
|
+
* | 順位 | 種別 | 例 |
|
|
8
|
+
* | --: | :-- | :-- |
|
|
9
|
+
* | 1 | Static | `/foo`, `/foo/bar` |
|
|
10
|
+
* | 2 | Parameter with suffix | `/movies/:title.mp4`, `/movies/:title.(mp4\|mov)` |
|
|
11
|
+
* | 3 | Parameter | `/:title`, `/books/:title`, `/books/:genre/:title` |
|
|
12
|
+
* | 4 | Optional Parameters | `/:title?`, `/books/:title?`, `/books/:genre/:title?` |
|
|
13
|
+
* | 5 | Wildcards | `*`, `/books/*`, `/books/:genre/*` |
|
|
14
|
+
* | 6 | Optional Wildcard | `/books/*?` |
|
|
15
|
+
*
|
|
16
|
+
* @see https://github.com/lukeed/regexparam
|
|
5
17
|
*/
|
|
6
18
|
const SCORE = {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
* 必須のパラメーターセグメントのスコアです。
|
|
14
|
-
*/
|
|
15
|
-
PARAMETER: 3,
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* 任意のパラメーターセグメントのスコアです。
|
|
19
|
-
*/
|
|
20
|
-
OPTIONAL_PARAM: 2,
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* ワイルドカードセグメントのスコアです。
|
|
24
|
-
*/
|
|
25
|
-
WILDCARD: 1,
|
|
19
|
+
PARAM: 4,
|
|
20
|
+
STATIC: 6,
|
|
21
|
+
WILDCARD: 2,
|
|
22
|
+
OPTIONAL_PARAM: 3,
|
|
23
|
+
OPTIONAL_WILDCARD: 1,
|
|
24
|
+
PARAM_WITH_SUFFIX: 5,
|
|
26
25
|
} as const;
|
|
27
26
|
|
|
28
27
|
/**
|
|
29
|
-
*
|
|
28
|
+
* 与えられた単一のセグメント文字列を解析し、その特性に応じた詳細度スコアを算出します。
|
|
30
29
|
*
|
|
31
|
-
* @param s
|
|
32
|
-
* @returns
|
|
30
|
+
* @param s 解析対象となるセグメント文字列です。
|
|
31
|
+
* @returns セグメントの種別に対応する、`SCORE` 定数から抽出された数値スコアです。
|
|
33
32
|
*/
|
|
34
33
|
function getSegmentScore(s: string): number {
|
|
35
|
-
if (s
|
|
34
|
+
if (s === "*?") {
|
|
35
|
+
return SCORE.OPTIONAL_WILDCARD;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (s === "*") {
|
|
36
39
|
return SCORE.WILDCARD;
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
if (s
|
|
40
|
-
if (s.
|
|
42
|
+
if (s[0] === ":") {
|
|
43
|
+
if (s[s.length - 1] === "?") {
|
|
41
44
|
return SCORE.OPTIONAL_PARAM;
|
|
42
|
-
} else {
|
|
43
|
-
return SCORE.PARAMETER;
|
|
44
45
|
}
|
|
46
|
+
|
|
47
|
+
if (s.indexOf(".") < 0) {
|
|
48
|
+
return SCORE.PARAM;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return SCORE.PARAM_WITH_SUFFIX;
|
|
45
52
|
}
|
|
46
53
|
|
|
47
54
|
return SCORE.STATIC;
|
|
48
55
|
}
|
|
49
56
|
|
|
50
57
|
/**
|
|
51
|
-
*
|
|
58
|
+
* 英語のロケール設定に基づき、大文字小文字などを標準化した文字列比較を行うための `Intl.Collator` インスタンスです。
|
|
59
|
+
*
|
|
60
|
+
* 決定論的な辞書順ソートを保証するために使用します。
|
|
61
|
+
*/
|
|
62
|
+
const enCollator = new Intl.Collator("en");
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 2つのルートパスの優先順位を比較し、ソート順を決定するための比較関数です。
|
|
52
66
|
*
|
|
53
|
-
*
|
|
67
|
+
* より具体的で制限の厳しいパス(詳細度スコアが高いパス)が、ソート結果においてより前方に配置されるように負の値を返します。
|
|
54
68
|
*
|
|
55
|
-
* @param pathA
|
|
56
|
-
* @param pathB
|
|
57
|
-
* @returns
|
|
69
|
+
* @param pathA 比較対象となる1つ目のパス文字列です。
|
|
70
|
+
* @param pathB 比較対象となる2つ目のパス文字列です。
|
|
71
|
+
* @returns `pathA` を優先する場合は負の数、`pathB` を優先する場合は正の数、等価である場合は `0` を返します。
|
|
58
72
|
*/
|
|
59
73
|
export default function compareRoutePaths(pathA: string, pathB: string): number {
|
|
60
74
|
const partsA = pathA.split("/").filter(Boolean);
|
|
@@ -82,7 +96,7 @@ export default function compareRoutePaths(pathA: string, pathB: string): number
|
|
|
82
96
|
}
|
|
83
97
|
// スコアが同じ場合は、文字列の辞書順で比較します。
|
|
84
98
|
if (a !== b) {
|
|
85
|
-
return
|
|
99
|
+
return enCollator.compare(a, b);
|
|
86
100
|
}
|
|
87
101
|
}
|
|
88
102
|
|