@shuvi/router 0.0.1-pre.1 → 0.0.1-pre.2

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 (51) hide show
  1. package/esm/createRoutesFromArray.d.ts +2 -0
  2. package/esm/createRoutesFromArray.js +9 -0
  3. package/esm/getRedirectFromRoutes.d.ts +2 -0
  4. package/esm/getRedirectFromRoutes.js +8 -0
  5. package/esm/history/base.d.ts +53 -0
  6. package/esm/history/base.js +80 -0
  7. package/esm/history/browser.d.ts +12 -0
  8. package/esm/history/browser.js +104 -0
  9. package/esm/history/hash.d.ts +13 -0
  10. package/esm/history/hash.js +135 -0
  11. package/esm/history/index.d.ts +7 -0
  12. package/esm/history/index.js +13 -0
  13. package/esm/history/memory.d.ts +22 -0
  14. package/esm/history/memory.js +75 -0
  15. package/esm/index.d.ts +7 -0
  16. package/esm/index.js +7 -0
  17. package/esm/matchPathname.d.ts +15 -0
  18. package/esm/matchPathname.js +54 -0
  19. package/esm/matchRoutes.d.ts +6 -0
  20. package/esm/matchRoutes.js +92 -0
  21. package/esm/pathParserRanker.d.ts +65 -0
  22. package/esm/pathParserRanker.js +223 -0
  23. package/esm/pathTokenizer.d.ts +23 -0
  24. package/esm/pathTokenizer.js +149 -0
  25. package/esm/router.d.ts +10 -0
  26. package/esm/router.js +207 -0
  27. package/esm/types/history.d.ts +176 -0
  28. package/esm/types/history.js +0 -0
  29. package/esm/types/index.d.ts +2 -0
  30. package/esm/types/index.js +1 -0
  31. package/esm/types/router.d.ts +78 -0
  32. package/esm/types/router.js +0 -0
  33. package/esm/utils/async.d.ts +2 -0
  34. package/esm/utils/async.js +18 -0
  35. package/esm/utils/createRedirector.d.ts +8 -0
  36. package/esm/utils/createRedirector.js +30 -0
  37. package/esm/utils/dom.d.ts +1 -0
  38. package/esm/utils/dom.js +1 -0
  39. package/esm/utils/error.d.ts +1 -0
  40. package/esm/utils/error.js +3 -0
  41. package/esm/utils/extract-hooks.d.ts +3 -0
  42. package/esm/utils/extract-hooks.js +16 -0
  43. package/esm/utils/history.d.ts +12 -0
  44. package/esm/utils/history.js +51 -0
  45. package/esm/utils/index.d.ts +4 -0
  46. package/esm/utils/index.js +4 -0
  47. package/esm/utils/misc.d.ts +11 -0
  48. package/esm/utils/misc.js +41 -0
  49. package/esm/utils/path.d.ts +13 -0
  50. package/esm/utils/path.js +101 -0
  51. package/package.json +5 -4
@@ -0,0 +1,2 @@
1
+ import { IPartialRouteRecord, IRouteRecord } from './types';
2
+ export declare function createRoutesFromArray<T extends IPartialRouteRecord, U extends IRouteRecord>(array: T[]): U[];
@@ -0,0 +1,9 @@
1
+ export function createRoutesFromArray(array) {
2
+ return array.map(partialRoute => {
3
+ let route = Object.assign(Object.assign({}, partialRoute), { caseSensitive: !!partialRoute.caseSensitive, path: partialRoute.path || '/' });
4
+ if (partialRoute.children) {
5
+ route.children = createRoutesFromArray(partialRoute.children);
6
+ }
7
+ return route;
8
+ });
9
+ }
@@ -0,0 +1,2 @@
1
+ import { IRouteMatch, IRouteRecord } from './types';
2
+ export declare function getRedirectFromRoutes<Route extends IRouteRecord>(appRoutes: IRouteMatch<Route>[]): string | null;
@@ -0,0 +1,8 @@
1
+ export function getRedirectFromRoutes(appRoutes) {
2
+ return appRoutes.reduceRight((redirectPath, { route: { redirect } }) => {
3
+ if (!redirectPath && redirect) {
4
+ return redirect;
5
+ }
6
+ return redirectPath;
7
+ }, null);
8
+ }
@@ -0,0 +1,53 @@
1
+ import { State, HistoryState, Blocker, Location, ResolvedPath, PathRecord, Action } from '../types';
2
+ /**
3
+ * A POP indicates a change to an arbitrary index in the history stack, such
4
+ * as a back or forward navigation. It does not describe the direction of the
5
+ * navigation, only that the current index changed.
6
+ *
7
+ * Note: This is the default action for newly created history objects.
8
+ */
9
+ export declare const ACTION_POP: Action;
10
+ /**
11
+ * A Push indicates a new entry being added to the history stack, such as when
12
+ * a link is clicked and a new page loads. When this happens, all subsequent
13
+ * entries in the stack are lost.
14
+ */
15
+ export declare const ACTION_PUSH: Action;
16
+ /**
17
+ * A REPLACE indicates the entry at the current index in the history stack
18
+ * being replaced by a new one.
19
+ */
20
+ export declare const ACTION_REPLACE: Action;
21
+ export interface TransitionOptions {
22
+ state?: State;
23
+ action?: Action;
24
+ redirectedFrom?: PathRecord;
25
+ onTransition(event: {
26
+ location: Location;
27
+ state: HistoryState;
28
+ url: string;
29
+ }): void;
30
+ onAbort?(): void;
31
+ }
32
+ export interface PushOptions {
33
+ state?: object | null | undefined;
34
+ redirectedFrom?: PathRecord;
35
+ }
36
+ export default abstract class BaseHistory {
37
+ action: Action;
38
+ location: Location;
39
+ doTransition: (to: PathRecord, onComplete: Function, onAbort?: Function) => void;
40
+ protected _index: number;
41
+ protected _blockers: import("../utils").Events<Blocker<State>>;
42
+ protected abstract getIndexAndLocation(): [number, Location];
43
+ abstract setup(): void;
44
+ abstract push(to: PathRecord, options: PushOptions): void;
45
+ abstract replace(to: PathRecord, options?: PushOptions): void;
46
+ abstract go(delta: number): void;
47
+ abstract block(blocker: Blocker<State>): () => void;
48
+ back(): void;
49
+ forward(): void;
50
+ resolve(to: any, from?: any): ResolvedPath;
51
+ transitionTo(to: PathRecord, { onTransition, onAbort, action, state, redirectedFrom }: TransitionOptions): void;
52
+ private _updateState;
53
+ }
@@ -0,0 +1,80 @@
1
+ import { createLocation, createEvents, resolvePath, pathToString } from '../utils';
2
+ /**
3
+ * A POP indicates a change to an arbitrary index in the history stack, such
4
+ * as a back or forward navigation. It does not describe the direction of the
5
+ * navigation, only that the current index changed.
6
+ *
7
+ * Note: This is the default action for newly created history objects.
8
+ */
9
+ export const ACTION_POP = 'POP';
10
+ /**
11
+ * A Push indicates a new entry being added to the history stack, such as when
12
+ * a link is clicked and a new page loads. When this happens, all subsequent
13
+ * entries in the stack are lost.
14
+ */
15
+ export const ACTION_PUSH = 'PUSH';
16
+ /**
17
+ * A REPLACE indicates the entry at the current index in the history stack
18
+ * being replaced by a new one.
19
+ */
20
+ export const ACTION_REPLACE = 'REPLACE';
21
+ export default class BaseHistory {
22
+ constructor() {
23
+ this.action = ACTION_POP;
24
+ this.location = createLocation('/');
25
+ this.doTransition = () => void 0;
26
+ this._index = 0;
27
+ this._blockers = createEvents();
28
+ }
29
+ back() {
30
+ this.go(-1);
31
+ }
32
+ forward() {
33
+ this.go(1);
34
+ }
35
+ resolve(to, from) {
36
+ const toPath = resolvePath(to, from);
37
+ return {
38
+ path: toPath,
39
+ href: pathToString(toPath)
40
+ };
41
+ }
42
+ transitionTo(to, { onTransition, onAbort, action = ACTION_PUSH, state = null, redirectedFrom }) {
43
+ const { path } = this.resolve(to, this.location.pathname);
44
+ const nextLocation = createLocation(path, { state, redirectedFrom });
45
+ // check transition
46
+ if (this._blockers.length) {
47
+ this._blockers.call({
48
+ action,
49
+ location: nextLocation,
50
+ retry: () => {
51
+ this.transitionTo(to, {
52
+ onTransition,
53
+ onAbort,
54
+ action,
55
+ state,
56
+ redirectedFrom
57
+ });
58
+ }
59
+ });
60
+ return;
61
+ }
62
+ this.doTransition(to, () => {
63
+ onTransition({
64
+ location: nextLocation,
65
+ state: {
66
+ usr: nextLocation.state,
67
+ key: nextLocation.key,
68
+ idx: this._index + 1
69
+ },
70
+ url: this.resolve(nextLocation).href
71
+ });
72
+ this._updateState(action);
73
+ }, onAbort);
74
+ }
75
+ _updateState(nextAction) {
76
+ // update state
77
+ this.action = nextAction;
78
+ [this._index, this.location] = this.getIndexAndLocation();
79
+ }
80
+ }
@@ -0,0 +1,12 @@
1
+ import { PathRecord, Location, Blocker } from '../types';
2
+ import BaseHistory, { PushOptions } from './base';
3
+ export default class BrowserHistory extends BaseHistory {
4
+ private _history;
5
+ constructor();
6
+ push(to: PathRecord, { state, redirectedFrom }?: PushOptions): void;
7
+ replace(to: PathRecord, { state, redirectedFrom }?: PushOptions): void;
8
+ go(delta: number): void;
9
+ block(blocker: Blocker): () => void;
10
+ setup(): void;
11
+ protected getIndexAndLocation(): [number, Location];
12
+ }
@@ -0,0 +1,104 @@
1
+ import { createLocation, pushState, replaceState, addBlocker, warning } from '../utils';
2
+ import BaseHistory, { ACTION_POP, ACTION_REPLACE } from './base';
3
+ export default class BrowserHistory extends BaseHistory {
4
+ constructor() {
5
+ super();
6
+ this._history = window.history;
7
+ [this._index, this.location] = this.getIndexAndLocation();
8
+ if (this._index == null) {
9
+ this._index = 0;
10
+ this._history.replaceState(Object.assign(Object.assign({}, this._history.state), { idx: this._index }), '');
11
+ }
12
+ }
13
+ push(to, { state, redirectedFrom } = {}) {
14
+ return this.transitionTo(to, {
15
+ state,
16
+ redirectedFrom,
17
+ onTransition({ state, url }) {
18
+ pushState(state, url);
19
+ }
20
+ });
21
+ }
22
+ replace(to, { state, redirectedFrom } = {}) {
23
+ return this.transitionTo(to, {
24
+ state,
25
+ action: ACTION_REPLACE,
26
+ redirectedFrom,
27
+ onTransition({ state, url }) {
28
+ replaceState(state, url);
29
+ }
30
+ });
31
+ }
32
+ go(delta) {
33
+ this._history.go(delta);
34
+ }
35
+ block(blocker) {
36
+ return addBlocker(this._blockers, blocker);
37
+ }
38
+ setup() {
39
+ let blockedPopTx = null;
40
+ const handlePop = () => {
41
+ const index = this._index;
42
+ const blockers = this._blockers;
43
+ if (blockedPopTx) {
44
+ blockers.call(blockedPopTx);
45
+ blockedPopTx = null;
46
+ }
47
+ else {
48
+ let nextAction = ACTION_POP;
49
+ let [nextIndex, nextLocation] = this.getIndexAndLocation();
50
+ if (blockers.length) {
51
+ if (nextIndex != null) {
52
+ let delta = index - nextIndex;
53
+ if (delta) {
54
+ // Revert the POP
55
+ blockedPopTx = {
56
+ action: nextAction,
57
+ location: nextLocation,
58
+ retry: () => {
59
+ this.go(delta * -1);
60
+ }
61
+ };
62
+ this.go(delta);
63
+ }
64
+ }
65
+ else {
66
+ // Trying to POP to a location with no index. We did not create
67
+ // this location, so we can't effectively block the navigation.
68
+ warning(false,
69
+ // TODO: Write up a doc that explains our blocking strategy in
70
+ // detail and link to it here so people can understand better what
71
+ // is going on and how to avoid it.
72
+ `You are trying to block a POP navigation to a location that was not ` +
73
+ `created by the history library. The block will fail silently in ` +
74
+ `production, but in general you should do all navigation with the ` +
75
+ `history library (instead of using window.history.pushState directly) ` +
76
+ `to avoid this situation.`);
77
+ }
78
+ }
79
+ else {
80
+ this.transitionTo(nextLocation, {
81
+ onTransition: () => { },
82
+ action: nextAction
83
+ });
84
+ }
85
+ }
86
+ };
87
+ window.addEventListener('popstate', handlePop);
88
+ }
89
+ getIndexAndLocation() {
90
+ const { pathname, search, hash } = window.location;
91
+ const state = this._history.state || {};
92
+ return [
93
+ state.idx,
94
+ createLocation({
95
+ pathname,
96
+ search,
97
+ hash
98
+ }, {
99
+ state: state.usr || null,
100
+ key: state.key || 'default'
101
+ })
102
+ ];
103
+ }
104
+ }
@@ -0,0 +1,13 @@
1
+ import { PathRecord, Location, Blocker, ResolvedPath } from '../types';
2
+ import BaseHistory, { PushOptions } from './base';
3
+ export default class HashHistory extends BaseHistory {
4
+ private _history;
5
+ constructor();
6
+ push(to: PathRecord, { state, redirectedFrom }?: PushOptions): void;
7
+ replace(to: PathRecord, { state, redirectedFrom }?: PushOptions): void;
8
+ go(delta: number): void;
9
+ block(blocker: Blocker): () => void;
10
+ resolve(to: any, from?: any): ResolvedPath;
11
+ setup(): void;
12
+ protected getIndexAndLocation(): [number, Location];
13
+ }
@@ -0,0 +1,135 @@
1
+ import { createLocation, pushState, replaceState, addBlocker, resolvePath, pathToString, warning } from '../utils';
2
+ import BaseHistory, { ACTION_POP, ACTION_REPLACE } from './base';
3
+ function getBaseHref() {
4
+ let base = document.querySelector('base');
5
+ let href = '';
6
+ if (base && base.getAttribute('href')) {
7
+ let url = window.location.href;
8
+ let hashIndex = url.indexOf('#');
9
+ href = hashIndex === -1 ? url : url.slice(0, hashIndex);
10
+ }
11
+ return href;
12
+ }
13
+ function createHref(to) {
14
+ return (getBaseHref() +
15
+ '#' +
16
+ (typeof to === 'string' ? to : pathToString(resolvePath(to))));
17
+ }
18
+ export default class HashHistory extends BaseHistory {
19
+ constructor() {
20
+ super();
21
+ this._history = window.history;
22
+ [this._index, this.location] = this.getIndexAndLocation();
23
+ if (this._index == null) {
24
+ this._index = 0;
25
+ this._history.replaceState(Object.assign(Object.assign({}, this._history.state), { idx: this._index }), '');
26
+ }
27
+ }
28
+ push(to, { state, redirectedFrom } = {}) {
29
+ return this.transitionTo(to, {
30
+ state,
31
+ redirectedFrom,
32
+ onTransition({ state, url }) {
33
+ pushState(state, url);
34
+ }
35
+ });
36
+ }
37
+ replace(to, { state, redirectedFrom } = {}) {
38
+ return this.transitionTo(to, {
39
+ state,
40
+ action: ACTION_REPLACE,
41
+ redirectedFrom,
42
+ onTransition({ state, url }) {
43
+ replaceState(state, url);
44
+ }
45
+ });
46
+ }
47
+ go(delta) {
48
+ this._history.go(delta);
49
+ }
50
+ block(blocker) {
51
+ return addBlocker(this._blockers, blocker);
52
+ }
53
+ resolve(to, from) {
54
+ const toPath = resolvePath(to, from);
55
+ return {
56
+ path: toPath,
57
+ href: createHref(toPath)
58
+ };
59
+ }
60
+ setup() {
61
+ let blockedPopTx = null;
62
+ const handlePop = () => {
63
+ const index = this._index;
64
+ const blockers = this._blockers;
65
+ if (blockedPopTx) {
66
+ blockers.call(blockedPopTx);
67
+ blockedPopTx = null;
68
+ }
69
+ else {
70
+ let nextAction = ACTION_POP;
71
+ let [nextIndex, nextLocation] = this.getIndexAndLocation();
72
+ if (blockers.length) {
73
+ if (nextIndex != null) {
74
+ let delta = index - nextIndex;
75
+ if (delta) {
76
+ // Revert the POP
77
+ blockedPopTx = {
78
+ action: nextAction,
79
+ location: nextLocation,
80
+ retry: () => {
81
+ this.go(delta * -1);
82
+ }
83
+ };
84
+ this.go(delta);
85
+ }
86
+ }
87
+ else {
88
+ // Trying to POP to a location with no index. We did not create
89
+ // this location, so we can't effectively block the navigation.
90
+ warning(false,
91
+ // TODO: Write up a doc that explains our blocking strategy in
92
+ // detail and link to it here so people can understand better what
93
+ // is going on and how to avoid it.
94
+ `You are trying to block a POP navigation to a location that was not ` +
95
+ `created by the history library. The block will fail silently in ` +
96
+ `production, but in general you should do all navigation with the ` +
97
+ `history library (instead of using window.history.pushState directly) ` +
98
+ `to avoid this situation.`);
99
+ }
100
+ }
101
+ else {
102
+ this.transitionTo(nextLocation, {
103
+ onTransition: () => { },
104
+ action: nextAction
105
+ });
106
+ }
107
+ }
108
+ };
109
+ window.addEventListener('popstate', handlePop);
110
+ // popstate does not fire on hashchange in IE 11 and old (trident) Edge
111
+ // https://developer.mozilla.org/de/docs/Web/API/Window/popstate_event
112
+ window.addEventListener('hashchange', () => {
113
+ const [, nextLocation] = this.getIndexAndLocation();
114
+ // Ignore extraneous hashchange events.
115
+ if (pathToString(nextLocation) !== pathToString(this.location)) {
116
+ handlePop();
117
+ }
118
+ });
119
+ }
120
+ getIndexAndLocation() {
121
+ const { pathname, search, hash } = resolvePath(window.location.hash.substr(1));
122
+ const state = this._history.state || {};
123
+ return [
124
+ state.idx,
125
+ createLocation({
126
+ pathname,
127
+ search,
128
+ hash
129
+ }, {
130
+ state: state.usr || null,
131
+ key: state.key || 'default'
132
+ })
133
+ ];
134
+ }
135
+ }
@@ -0,0 +1,7 @@
1
+ import MemoryHistory, { MemoryHistoryOptions, InitialEntry } from './memory';
2
+ import BrowserHistory from './browser';
3
+ import HashHistory from './hash';
4
+ export { MemoryHistory, MemoryHistoryOptions, InitialEntry };
5
+ export declare function createBrowserHistory(): BrowserHistory;
6
+ export declare function createHashHistory(): HashHistory;
7
+ export declare function createMemoryHistory(options?: MemoryHistoryOptions): MemoryHistory;
@@ -0,0 +1,13 @@
1
+ import MemoryHistory from './memory';
2
+ import BrowserHistory from './browser';
3
+ import HashHistory from './hash';
4
+ export { MemoryHistory };
5
+ export function createBrowserHistory() {
6
+ return new BrowserHistory();
7
+ }
8
+ export function createHashHistory() {
9
+ return new HashHistory();
10
+ }
11
+ export function createMemoryHistory(options = {}) {
12
+ return new MemoryHistory(options);
13
+ }
@@ -0,0 +1,22 @@
1
+ import { PathRecord, Location, Blocker, PartialLocation, ResolvedPath } from '../types';
2
+ import BaseHistory, { PushOptions } from './base';
3
+ /**
4
+ * A user-supplied object that describes a location. Used when providing
5
+ * entries to `createMemoryHistory` via its `initialEntries` option.
6
+ */
7
+ export declare type InitialEntry = string | PartialLocation;
8
+ export declare type MemoryHistoryOptions = {
9
+ initialEntries?: InitialEntry[];
10
+ initialIndex?: number;
11
+ };
12
+ export default class MemoryHistory extends BaseHistory {
13
+ private _entries;
14
+ constructor({ initialEntries, initialIndex }?: MemoryHistoryOptions);
15
+ setup(): void;
16
+ push(to: PathRecord, { state, redirectedFrom }?: PushOptions): void;
17
+ replace(to: PathRecord, { state, redirectedFrom }?: PushOptions): void;
18
+ go(delta: number): void;
19
+ block(blocker: Blocker): () => void;
20
+ resolve(to: PathRecord, from?: string): ResolvedPath;
21
+ protected getIndexAndLocation(): [number, Location];
22
+ }
@@ -0,0 +1,75 @@
1
+ import { createLocation, resolvePath, pathToString, warning } from '../utils';
2
+ import BaseHistory, { ACTION_POP, ACTION_REPLACE } from './base';
3
+ function clamp(n, lowerBound, upperBound) {
4
+ return Math.min(Math.max(n, lowerBound), upperBound);
5
+ }
6
+ export default class MemoryHistory extends BaseHistory {
7
+ constructor({ initialEntries = ['/'], initialIndex } = {}) {
8
+ super();
9
+ this._entries = [];
10
+ this._entries = initialEntries.map(entry => {
11
+ let location = createLocation(Object.assign({ pathname: '/', search: '', hash: '' }, (typeof entry === 'string' ? resolvePath(entry) : entry)));
12
+ warning(location.pathname.charAt(0) === '/', `Relative pathnames are not supported in createMemoryHistory({ initialEntries }) (invalid entry: ${JSON.stringify(entry)})`);
13
+ return location;
14
+ });
15
+ this._index = clamp(initialIndex == null ? this._entries.length - 1 : initialIndex, 0, this._entries.length - 1);
16
+ this.location = this._entries[this._index];
17
+ }
18
+ setup() {
19
+ // do nothing
20
+ }
21
+ push(to, { state, redirectedFrom } = {}) {
22
+ return this.transitionTo(to, {
23
+ state,
24
+ redirectedFrom,
25
+ onTransition: ({ location }) => {
26
+ this._index += 1;
27
+ this._entries.splice(this._index, this._entries.length, location);
28
+ }
29
+ });
30
+ }
31
+ replace(to, { state, redirectedFrom } = {}) {
32
+ return this.transitionTo(to, {
33
+ state,
34
+ action: ACTION_REPLACE,
35
+ redirectedFrom,
36
+ onTransition: ({ location }) => {
37
+ this._entries[this._index] = location;
38
+ }
39
+ });
40
+ }
41
+ go(delta) {
42
+ const { _index: index, _entries: entries } = this;
43
+ let nextIndex = clamp(index + delta, 0, entries.length - 1);
44
+ let nextAction = ACTION_POP;
45
+ let nextLocation = entries[nextIndex];
46
+ // check transition
47
+ if (this._blockers.length) {
48
+ this._blockers.call({
49
+ action: nextAction,
50
+ location: nextLocation,
51
+ retry: () => {
52
+ this.go(delta);
53
+ }
54
+ });
55
+ return;
56
+ }
57
+ this.transitionTo(nextLocation.pathname, Object.assign(Object.assign({}, nextLocation), { action: nextAction, onTransition: ({ location }) => {
58
+ this._index = nextIndex;
59
+ } }));
60
+ }
61
+ block(blocker) {
62
+ return this._blockers.push(blocker);
63
+ }
64
+ resolve(to, from) {
65
+ const toPath = resolvePath(to, from);
66
+ return {
67
+ path: toPath,
68
+ href: pathToString(toPath)
69
+ };
70
+ }
71
+ getIndexAndLocation() {
72
+ const index = this._index;
73
+ return [index, this._entries[index]];
74
+ }
75
+ }
package/esm/index.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ export { createRoutesFromArray } from './createRoutesFromArray';
2
+ export { matchPathname, matchStringify } from './matchPathname';
3
+ export { matchRoutes, IRouteBaseObject, rankRouteBranches } from './matchRoutes';
4
+ export { pathToString, parseQuery, resolvePath, createLocation, createRedirector } from './utils';
5
+ export * from './types';
6
+ export * from './history';
7
+ export * from './router';
package/esm/index.js ADDED
@@ -0,0 +1,7 @@
1
+ export { createRoutesFromArray } from './createRoutesFromArray';
2
+ export { matchPathname, matchStringify } from './matchPathname';
3
+ export { matchRoutes, rankRouteBranches } from './matchRoutes';
4
+ export { pathToString, parseQuery, resolvePath, createLocation, createRedirector } from './utils';
5
+ export * from './types';
6
+ export * from './history';
7
+ export * from './router';
@@ -0,0 +1,15 @@
1
+ import { IPathPattern, IPathMatch, IParams } from './types';
2
+ import { PathParserOptions } from './pathParserRanker';
3
+ /**
4
+ * match pathname, online link https://paths.esm.dev/?p=AAMeJSyAwR4UbFDAFxAcAGAIJnMCo0SmCHGYBdyBsATSBUQBsAPABAwxsAHeGVJwuLlARA..#
5
+ * @param pattern
6
+ * @param pathname
7
+ */
8
+ export declare function matchPathname(pattern: IPathPattern, pathname: string): IPathMatch | null;
9
+ /**
10
+ * stringify path to string by params and options
11
+ * @param path
12
+ * @param params
13
+ * @param options
14
+ */
15
+ export declare function matchStringify(path: string, params: IParams, options?: PathParserOptions): string;
@@ -0,0 +1,54 @@
1
+ import { tokensToParser } from './pathParserRanker';
2
+ import { tokenizePath } from './pathTokenizer';
3
+ function safelyDecodeURIComponent(value, paramName, optional) {
4
+ try {
5
+ if (Array.isArray(value)) {
6
+ return value.map((item) => {
7
+ return decodeURIComponent(item.replace(/\+/g, ' '));
8
+ });
9
+ }
10
+ return decodeURIComponent(value.replace(/\+/g, ' '));
11
+ }
12
+ catch (error) {
13
+ if (!optional) {
14
+ console.warn(`The value for the URL param "${paramName}" will not be decoded because` +
15
+ ` the string "${value}" is a malformed URL segment. This is probably` +
16
+ ` due to a bad percent encoding (${error}).`);
17
+ }
18
+ return value;
19
+ }
20
+ }
21
+ /**
22
+ * match pathname, online link https://paths.esm.dev/?p=AAMeJSyAwR4UbFDAFxAcAGAIJnMCo0SmCHGYBdyBsATSBUQBsAPABAwxsAHeGVJwuLlARA..#
23
+ * @param pattern
24
+ * @param pathname
25
+ */
26
+ export function matchPathname(pattern, pathname) {
27
+ if (typeof pattern === 'string') {
28
+ pattern = { path: pattern };
29
+ }
30
+ const { path, caseSensitive = false, end = true } = pattern;
31
+ const pathParser = tokensToParser(tokenizePath(path), { end, sensitive: caseSensitive });
32
+ ;
33
+ const matchResult = pathParser.parse(pathname);
34
+ if (!matchResult)
35
+ return null;
36
+ const { keys = [] } = pathParser;
37
+ const { match, params } = matchResult;
38
+ const safelyDecodetParams = (keys).reduce((memo, key, index) => {
39
+ const keyName = key.name;
40
+ memo[keyName] = safelyDecodeURIComponent(params[keyName], String(keyName), key.optional);
41
+ return memo;
42
+ }, {});
43
+ return { path, pathname: match, params: safelyDecodetParams };
44
+ }
45
+ /**
46
+ * stringify path to string by params and options
47
+ * @param path
48
+ * @param params
49
+ * @param options
50
+ */
51
+ export function matchStringify(path, params, options) {
52
+ const pathParser = tokensToParser(tokenizePath(path), options);
53
+ return pathParser.stringify(params);
54
+ }
@@ -0,0 +1,6 @@
1
+ import { IRouteRecord, IRouteMatch, PartialLocation } from './types';
2
+ export interface IRouteBaseObject<Element = any> extends Omit<IRouteRecord<Element>, 'children' | 'element' | 'filepath'> {
3
+ children?: IRouteBaseObject<Element>[];
4
+ }
5
+ export declare function rankRouteBranches<T extends [string, ...any[]]>(branches: T[]): T[];
6
+ export declare function matchRoutes<T extends IRouteBaseObject>(routes: T[], location: string | PartialLocation, basename?: string): IRouteMatch<T>[] | null;