soseki 0.0.9 → 0.0.10

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.
@@ -0,0 +1,46 @@
1
+ /**
2
+ * ルーティングの照合対象となる URL 情報を表すインターフェースです。
3
+ */
4
+ export interface MatchRoutePathTargetURL {
5
+ /**
6
+ * 照合対象のパス名です。
7
+ */
8
+ readonly pathname: string;
9
+ }
10
+ /**
11
+ * `matchRoutePath` 関数の動作を設定するための型定義です。
12
+ */
13
+ export type MatchRoutePathOptions = {
14
+ /**
15
+ * 照合の基準となるルーティングのパターン文字列です。
16
+ */
17
+ readonly pattern: string;
18
+ /**
19
+ * 照合対象とする文字列または URL オブジェクトです。
20
+ */
21
+ readonly target: string | MatchRoutePathTargetURL;
22
+ /**
23
+ * 子ディレクトリーへの前方一致を許可するかどうかを制御するフラグです。
24
+ *
25
+ * @default false
26
+ */
27
+ readonly allowChild?: boolean | undefined;
28
+ };
29
+ /**
30
+ * 指定されたパターンと対象のパス名が一致するかどうかを判定します。
31
+ *
32
+ * @param options パターン、対象、および一致条件を含む設定オブジェクトです。
33
+ * @returns パターンに一致した場合は `true` を、一致しない場合は `false` を返します。
34
+ */
35
+ declare function matchRoutePath(options: MatchRoutePathOptions): boolean;
36
+ /**
37
+ * 指定されたパターンと対象のパス名が一致するかどうかを判定します。
38
+ *
39
+ * @param pattern 照合の基準となるルーティングのパターン文字列です。
40
+ * @param target 照合対象とする文字列または URL オブジェクトです。
41
+ * @param options オプションです。
42
+ * @returns パターンに一致した場合は `true` を、一致しない場合は `false` を返します。
43
+ */
44
+ declare function matchRoutePath(pattern: MatchRoutePathOptions["pattern"], target: MatchRoutePathOptions["target"], options?: Omit<MatchRoutePathOptions, "pattern" | "target">): boolean;
45
+ export default matchRoutePath;
46
+ //# sourceMappingURL=match-route-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"match-route-path.d.ts","sourceRoot":"","sources":["../../../src/core/match-route-path.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,uBAAuB,CAAC;IAElD;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC3C,CAAC;AAEF;;;;;GAKG;AACH,iBAAS,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC;AAEjE;;;;;;;GAOG;AACH,iBAAS,cAAc,CACrB,OAAO,EAAE,qBAAqB,CAAC,SAAS,CAAC,EACzC,MAAM,EAAE,qBAAqB,CAAC,QAAQ,CAAC,EACvC,OAAO,CAAC,EAAE,IAAI,CAAC,qBAAqB,EAAE,SAAS,GAAG,QAAQ,CAAC,GAC1D,OAAO,CAAC;AAqBX,eAAe,cAAc,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { parse } from "regexparam";
2
+ import RoutePath from "./route-path.js";
3
+ function matchRoutePath(...args) {
4
+ const { target, pattern, allowChild = false, } = typeof args[0] !== "string"
5
+ ? args[0]
6
+ : {
7
+ ...args[2],
8
+ target: args[1],
9
+ pattern: args[0],
10
+ };
11
+ const patternPathname = new RoutePath(pattern).pathname;
12
+ const targetPathname = typeof target === "string" ? target : target.pathname;
13
+ const patternRegex = parse(patternPathname, allowChild).pattern;
14
+ return patternRegex.test(targetPathname);
15
+ }
16
+ export default matchRoutePath;
@@ -1 +1 @@
1
- {"version":3,"file":"navigation-api-engine.d.ts","sourceRoot":"","sources":["../../../src/engines/navigation-api-engine.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAoB,YAAW,OAAO;IACzD;;OAEG;IACH,OAAO,CAAC,UAAU,CAAa;IAE/B;;OAEG;IACH,OAAO,CAAC,kBAAkB,CAAsB;IAEhD;;OAEG;IACH,OAAO,CAAC,kBAAkB,CAAyB;IAEnD;;;;OAIG;;IAwBH;;;;;OAKG;IACH,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC,UAAU;IA2BhD;;;;OAIG;IACH,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,WAAW;IAgSnD;;;;OAIG;IACH,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,GAAG,IAAI;IAkCtC;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,GAAG,IAAI;CAgE3C"}
1
+ {"version":3,"file":"navigation-api-engine.d.ts","sourceRoot":"","sources":["../../../src/engines/navigation-api-engine.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAoB,YAAW,OAAO;IACzD;;OAEG;IACH,OAAO,CAAC,UAAU,CAAa;IAE/B;;OAEG;IACH,OAAO,CAAC,kBAAkB,CAAsB;IAEhD;;OAEG;IACH,OAAO,CAAC,kBAAkB,CAAyB;IAEnD;;;;OAIG;;IAwBH;;;;;OAKG;IACH,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC,UAAU;IA2BhD;;;;OAIG;IACH,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,WAAW;IA8RnD;;;;OAIG;IACH,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,GAAG,IAAI;IAkCtC;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,GAAG,IAAI;CAgE3C"}
@@ -78,8 +78,7 @@ export default class NavigationApiEngine {
78
78
  * ユーザーのアクションによって発生したすべての遷移要求をインターセプトして処理する、ルーティングの中枢ハンドラーです。
79
79
  */
80
80
  const handleNavigate = (event) => {
81
- // 処理すべきでない通常のブラウザー固有のナビゲーション(ハッシュ変更、ファイルのダウンロードなど)は、
82
- // 標準の挙動を妨げないようにインターセプトせず即座にスルーします。
81
+ // 処理すべきでない通常のブラウザー固有のナビゲーション(ハッシュ変更、ファイルのダウンロードなど)は、標準の挙動を妨げないようにインターセプトせず即座にスルーします。
83
82
  // 参照: https://developer.mozilla.org/docs/Web/API/Navigation_API#handling_a_navigation_using_intercept
84
83
  if (!event.isTrusted ||
85
84
  !event.canIntercept ||
@@ -146,19 +145,18 @@ export default class NavigationApiEngine {
146
145
  switch (action.data.status) {
147
146
  case "rejected": {
148
147
  // アクションがエラーで失敗した場合は、URL を変更せず現在の元のページに強制リダイレクトさせます。
149
- const { pathname, search, hash } = currentEntry.url;
150
- controller.redirect(pathname + search + hash);
148
+ controller.redirect(RoutePath.encode(currentEntry.url));
151
149
  break;
152
150
  }
153
151
  case "fulfilled": {
154
152
  // アクションが正常終了した場合、返り値にリダイレクト指示が含まれていればその目的地へ遷移させます。
155
153
  // リダイレクトがなければそのまま本来の目的地へとブラウザーのコミット先を書き換えます。
156
154
  const { redirectTo = currentEntry.url } = actionResponse;
157
- const { pathname, search, hash } = redirectTo;
158
- controller.redirect(pathname + search + hash);
159
- redirectUrl.pathname = pathname;
160
- redirectUrl.search = search;
161
- redirectUrl.hash = hash;
155
+ const redirectPath = new RoutePath(redirectTo);
156
+ controller.redirect(redirectPath.toString());
157
+ redirectUrl.pathname = redirectPath.pathname;
158
+ redirectUrl.search = redirectPath.search;
159
+ redirectUrl.hash = redirectPath.hash;
162
160
  break;
163
161
  }
164
162
  default:
@@ -5,6 +5,8 @@ export { default as Outlet } from "./components/outlet.jsx";
5
5
  /**************************************************************************************************/
6
6
  export type { Issue, UnreachableErrorArgs, UnreachableErrorMeta, LoaderConditionErrorArgs, LoaderConditionErrorMeta, LoaderDataNotFoundErrorArgs, LoaderDataNotFoundErrorMeta, UnexpectedValidationErrorArgs, UnexpectedValidationErrorMeta, } from "./core/errors.js";
7
7
  export { ErrorBase, setErrorMessage, UnreachableError, ValidationErrorBase, LoaderConditionError, LoaderDataNotFoundError, RouteContextMissingError, RouterContextMissingError, UnexpectedValidationError, NavigationApiNotSupportedError, } from "./core/errors.js";
8
+ export type * from "./core/match-route-path.js";
9
+ export { default as matchRoutePath } from "./core/match-route-path.js";
8
10
  export type * from "./core/readonly-form-data.types.js";
9
11
  export type * from "./core/readonly-url.types.js";
10
12
  export type * from "./core/redirect-response.js";
@@ -1 +1 @@
1
- {"version":3,"file":"soseki.d.ts","sourceRoot":"","sources":["../../src/soseki.ts"],"names":[],"mappings":"AAAA,mBAAmB,iCAAiC,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAE3E,mBAAmB,yBAAyB,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAE5D,oGAAoG;AAEpG,YAAY,EACV,KAAK,EACL,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,2BAA2B,EAC3B,2BAA2B,EAC3B,6BAA6B,EAC7B,6BAA6B,GAC9B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,EACzB,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,kBAAkB,CAAC;AAE1B,mBAAmB,oCAAoC,CAAC;AAExD,mBAAmB,8BAA8B,CAAC;AAElD,mBAAmB,6BAA6B,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAE1E,mBAAmB,yBAAyB,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAElE,mBAAmB,uBAAuB,CAAC;AAE3C,oGAAoG;AAEpG,mBAAmB,4BAA4B,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEtE,mBAAmB,4BAA4B,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEtE,mBAAmB,4BAA4B,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEtE,mBAAmB,yBAAyB,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEjE,mBAAmB,uBAAuB,CAAC;AAC3C,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAE7D,mBAAmB,2BAA2B,CAAC;AAC/C,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEpE,mBAAmB,uBAAuB,CAAC;AAC3C,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAE7D,oGAAoG;AAEpG,mBAAmB,qBAAqB,CAAC;AACzC,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"soseki.d.ts","sourceRoot":"","sources":["../../src/soseki.ts"],"names":[],"mappings":"AAAA,mBAAmB,iCAAiC,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAE3E,mBAAmB,yBAAyB,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAE5D,oGAAoG;AAEpG,YAAY,EACV,KAAK,EACL,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,2BAA2B,EAC3B,2BAA2B,EAC3B,6BAA6B,EAC7B,6BAA6B,GAC9B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,EACzB,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,kBAAkB,CAAC;AAE1B,mBAAmB,4BAA4B,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEvE,mBAAmB,oCAAoC,CAAC;AAExD,mBAAmB,8BAA8B,CAAC;AAElD,mBAAmB,6BAA6B,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAE1E,mBAAmB,yBAAyB,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAElE,mBAAmB,uBAAuB,CAAC;AAE3C,oGAAoG;AAEpG,mBAAmB,4BAA4B,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEtE,mBAAmB,4BAA4B,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEtE,mBAAmB,4BAA4B,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEtE,mBAAmB,yBAAyB,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEjE,mBAAmB,uBAAuB,CAAC;AAC3C,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAE7D,mBAAmB,2BAA2B,CAAC;AAC/C,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEpE,mBAAmB,uBAAuB,CAAC;AAC3C,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAE7D,oGAAoG;AAEpG,mBAAmB,qBAAqB,CAAC;AACzC,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,qBAAqB,CAAC"}
@@ -1,6 +1,7 @@
1
1
  export { default as BrowserRouter } from "./components/browser-router.jsx";
2
2
  export { default as Outlet } from "./components/outlet.jsx";
3
3
  export { ErrorBase, setErrorMessage, UnreachableError, ValidationErrorBase, LoaderConditionError, LoaderDataNotFoundError, RouteContextMissingError, RouterContextMissingError, UnexpectedValidationError, NavigationApiNotSupportedError, } from "./core/errors.js";
4
+ export { default as matchRoutePath } from "./core/match-route-path.js";
4
5
  export { default as RedirectResponse } from "./core/redirect-response.js";
5
6
  export { default as RouteRequest } from "./core/route-request.js";
6
7
  export { default as useActionData } from "./hooks/use-action-data.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "soseki",
3
- "version": "0.0.9",
3
+ "version": "0.0.10",
4
4
  "description": "",
5
5
  "homepage": "https://github.com/tai-kun/soseki.js",
6
6
  "license": "MIT",
@@ -0,0 +1,78 @@
1
+ import { parse } from "regexparam";
2
+
3
+ import RoutePath from "./route-path.js";
4
+
5
+ /**
6
+ * ルーティングの照合対象となる URL 情報を表すインターフェースです。
7
+ */
8
+ export interface MatchRoutePathTargetURL {
9
+ /**
10
+ * 照合対象のパス名です。
11
+ */
12
+ readonly pathname: string;
13
+ }
14
+
15
+ /**
16
+ * `matchRoutePath` 関数の動作を設定するための型定義です。
17
+ */
18
+ export type MatchRoutePathOptions = {
19
+ /**
20
+ * 照合の基準となるルーティングのパターン文字列です。
21
+ */
22
+ readonly pattern: string;
23
+
24
+ /**
25
+ * 照合対象とする文字列または URL オブジェクトです。
26
+ */
27
+ readonly target: string | MatchRoutePathTargetURL;
28
+
29
+ /**
30
+ * 子ディレクトリーへの前方一致を許可するかどうかを制御するフラグです。
31
+ *
32
+ * @default false
33
+ */
34
+ readonly allowChild?: boolean | undefined;
35
+ };
36
+
37
+ /**
38
+ * 指定されたパターンと対象のパス名が一致するかどうかを判定します。
39
+ *
40
+ * @param options パターン、対象、および一致条件を含む設定オブジェクトです。
41
+ * @returns パターンに一致した場合は `true` を、一致しない場合は `false` を返します。
42
+ */
43
+ function matchRoutePath(options: MatchRoutePathOptions): boolean;
44
+
45
+ /**
46
+ * 指定されたパターンと対象のパス名が一致するかどうかを判定します。
47
+ *
48
+ * @param pattern 照合の基準となるルーティングのパターン文字列です。
49
+ * @param target 照合対象とする文字列または URL オブジェクトです。
50
+ * @param options オプションです。
51
+ * @returns パターンに一致した場合は `true` を、一致しない場合は `false` を返します。
52
+ */
53
+ function matchRoutePath(
54
+ pattern: MatchRoutePathOptions["pattern"],
55
+ target: MatchRoutePathOptions["target"],
56
+ options?: Omit<MatchRoutePathOptions, "pattern" | "target">,
57
+ ): boolean;
58
+
59
+ function matchRoutePath(...args: any): boolean {
60
+ const {
61
+ target,
62
+ pattern,
63
+ allowChild = false,
64
+ }: MatchRoutePathOptions = typeof args[0] !== "string"
65
+ ? args[0]
66
+ : {
67
+ ...args[2],
68
+ target: args[1],
69
+ pattern: args[0],
70
+ };
71
+ const patternPathname = new RoutePath(pattern).pathname;
72
+ const targetPathname = typeof target === "string" ? target : target.pathname;
73
+ const patternRegex = parse(patternPathname, allowChild).pattern;
74
+
75
+ return patternRegex.test(targetPathname);
76
+ }
77
+
78
+ export default matchRoutePath;
@@ -105,8 +105,7 @@ export default class NavigationApiEngine implements IEngine {
105
105
  * ユーザーのアクションによって発生したすべての遷移要求をインターセプトして処理する、ルーティングの中枢ハンドラーです。
106
106
  */
107
107
  const handleNavigate = (event: NavigateEvent): void => {
108
- // 処理すべきでない通常のブラウザー固有のナビゲーション(ハッシュ変更、ファイルのダウンロードなど)は、
109
- // 標準の挙動を妨げないようにインターセプトせず即座にスルーします。
108
+ // 処理すべきでない通常のブラウザー固有のナビゲーション(ハッシュ変更、ファイルのダウンロードなど)は、標準の挙動を妨げないようにインターセプトせず即座にスルーします。
110
109
  // 参照: https://developer.mozilla.org/docs/Web/API/Navigation_API#handling_a_navigation_using_intercept
111
110
  if (
112
111
  !event.isTrusted ||
@@ -187,8 +186,7 @@ export default class NavigationApiEngine implements IEngine {
187
186
  switch (action.data.status) {
188
187
  case "rejected": {
189
188
  // アクションがエラーで失敗した場合は、URL を変更せず現在の元のページに強制リダイレクトさせます。
190
- const { pathname, search, hash } = currentEntry.url;
191
- controller.redirect(pathname + search + hash);
189
+ controller.redirect(RoutePath.encode(currentEntry.url));
192
190
 
193
191
  break;
194
192
  }
@@ -197,12 +195,12 @@ export default class NavigationApiEngine implements IEngine {
197
195
  // アクションが正常終了した場合、返り値にリダイレクト指示が含まれていればその目的地へ遷移させます。
198
196
  // リダイレクトがなければそのまま本来の目的地へとブラウザーのコミット先を書き換えます。
199
197
  const { redirectTo = currentEntry.url } = actionResponse;
200
- const { pathname, search, hash } = redirectTo;
201
- controller.redirect(pathname + search + hash);
198
+ const redirectPath = new RoutePath(redirectTo);
199
+ controller.redirect(redirectPath.toString());
202
200
 
203
- redirectUrl.pathname = pathname;
204
- redirectUrl.search = search;
205
- redirectUrl.hash = hash;
201
+ redirectUrl.pathname = redirectPath.pathname;
202
+ redirectUrl.search = redirectPath.search;
203
+ redirectUrl.hash = redirectPath.hash;
206
204
 
207
205
  break;
208
206
  }
package/src/soseki.ts CHANGED
@@ -30,6 +30,9 @@ export {
30
30
  NavigationApiNotSupportedError,
31
31
  } from "./core/errors.js";
32
32
 
33
+ export type * from "./core/match-route-path.js";
34
+ export { default as matchRoutePath } from "./core/match-route-path.js";
35
+
33
36
  export type * from "./core/readonly-form-data.types.js";
34
37
 
35
38
  export type * from "./core/readonly-url.types.js";