@farbenmeer/router 0.5.0 → 0.6.1
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/dist/context.d.ts +3 -2
- package/dist/context.d.ts.map +1 -1
- package/dist/path.d.ts +3 -0
- package/dist/path.d.ts.map +1 -1
- package/dist/path.js +39 -0
- package/dist/route.d.ts +2 -3
- package/dist/route.d.ts.map +1 -1
- package/dist/route.js +1 -39
- package/dist/switch.d.ts +8 -0
- package/dist/switch.d.ts.map +1 -0
- package/dist/switch.js +43 -0
- package/package.json +4 -2
package/dist/context.d.ts
CHANGED
|
@@ -6,9 +6,10 @@ export declare const RouterContext: import("react").Context<{
|
|
|
6
6
|
push: (href: string) => void;
|
|
7
7
|
replace: (href: string) => void;
|
|
8
8
|
}>;
|
|
9
|
-
export
|
|
9
|
+
export interface RouteContextValue {
|
|
10
10
|
path: string;
|
|
11
11
|
params: Record<string, string | string[]>;
|
|
12
12
|
matchedPathname: string;
|
|
13
|
-
}
|
|
13
|
+
}
|
|
14
|
+
export declare const RouteContext: import("react").Context<RouteContextValue>;
|
|
14
15
|
//# sourceMappingURL=context.d.ts.map
|
package/dist/context.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,eAAO,MAAM,eAAe,iCAA6B,CAAC;AAE1D,eAAO,MAAM,mBAAmB,gDAE/B,CAAC;AAEF,eAAO,MAAM,WAAW,iCAA4B,CAAC;AAErD,eAAO,MAAM,aAAa;UAClB,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;aACnB,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;EAI/B,CAAC;AAEH,
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,eAAO,MAAM,eAAe,iCAA6B,CAAC;AAE1D,eAAO,MAAM,mBAAmB,gDAE/B,CAAC;AAEF,eAAO,MAAM,WAAW,iCAA4B,CAAC;AAErD,eAAO,MAAM,aAAa;UAClB,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;aACnB,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;EAI/B,CAAC;AAEH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,YAAY,4CAIvB,CAAC"}
|
package/dist/path.d.ts
CHANGED
|
@@ -6,5 +6,8 @@ interface Options {
|
|
|
6
6
|
}
|
|
7
7
|
export declare function resolve(path: string, { pathname, parentPathname, searchParams }: Options): string;
|
|
8
8
|
export declare function removeTrailingSlash(path: string): string;
|
|
9
|
+
export declare function compilePathRegex(path: string): RegExp;
|
|
10
|
+
export declare function compileExactPathRegex(path: string): RegExp;
|
|
11
|
+
export declare function buildFullPath(parentPath: string, path?: string): string;
|
|
9
12
|
export {};
|
|
10
13
|
//# sourceMappingURL=path.d.ts.map
|
package/dist/path.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../src/path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,UAAU,OAAO;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,qBAAqB,CAAC;CACrC;AAED,wBAAgB,OAAO,CACrB,IAAI,EAAE,MAAM,EACZ,EAAE,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,EAAE,OAAO,UAepD;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGxD"}
|
|
1
|
+
{"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../src/path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,UAAU,OAAO;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,qBAAqB,CAAC;CACrC;AAED,wBAAgB,OAAO,CACrB,IAAI,EAAE,MAAM,EACZ,EAAE,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,EAAE,OAAO,UAepD;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGxD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAiBrD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAU1D;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,UAa9D"}
|
package/dist/path.js
CHANGED
|
@@ -19,3 +19,42 @@ export function removeTrailingSlash(path) {
|
|
|
19
19
|
return path;
|
|
20
20
|
return path.endsWith("/") ? path.slice(0, -1) : path;
|
|
21
21
|
}
|
|
22
|
+
export function compilePathRegex(path) {
|
|
23
|
+
if (path === "/") {
|
|
24
|
+
return /^\//;
|
|
25
|
+
}
|
|
26
|
+
// Handle wildcards: *name captures as named group, * catches all without capturing
|
|
27
|
+
const pattern = path
|
|
28
|
+
.replaceAll(/\*(\w+)/g, "(?<$1>.+)") // *name -> named capture group
|
|
29
|
+
.replaceAll(/\*/g, ".+") // * -> match everything including /
|
|
30
|
+
.replaceAll(/:(\w+)/g, "(?<$1>[^\\/]+)"); // :param -> named capture group
|
|
31
|
+
// If pattern contains a wildcard, it already matches everything - use exact match
|
|
32
|
+
if (path.includes("*")) {
|
|
33
|
+
return new RegExp(`^(${pattern})$`);
|
|
34
|
+
}
|
|
35
|
+
// For non-wildcard paths, allow optional trailing paths
|
|
36
|
+
return new RegExp(`^(${pattern})(/.*)?$`);
|
|
37
|
+
}
|
|
38
|
+
export function compileExactPathRegex(path) {
|
|
39
|
+
if (path === "/") {
|
|
40
|
+
return /^\/$/;
|
|
41
|
+
}
|
|
42
|
+
// Handle wildcards: *name captures as named group, * catches all without capturing
|
|
43
|
+
const pattern = path
|
|
44
|
+
.replaceAll(/\*(\w+)/g, "(?<$1>.+)") // *name -> named capture group
|
|
45
|
+
.replaceAll(/\*/g, ".+") // * -> match everything including /
|
|
46
|
+
.replaceAll(/:(\w+)/g, "(?<$1>[^\\/]+)"); // :param -> named capture group
|
|
47
|
+
return new RegExp(`^(${pattern})$`);
|
|
48
|
+
}
|
|
49
|
+
export function buildFullPath(parentPath, path) {
|
|
50
|
+
if (path?.startsWith("/")) {
|
|
51
|
+
return path;
|
|
52
|
+
}
|
|
53
|
+
if (path) {
|
|
54
|
+
if (parentPath === "/") {
|
|
55
|
+
return "/" + path;
|
|
56
|
+
}
|
|
57
|
+
return parentPath + "/" + path;
|
|
58
|
+
}
|
|
59
|
+
return parentPath;
|
|
60
|
+
}
|
package/dist/route.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
interface
|
|
1
|
+
export interface RouteProps {
|
|
2
2
|
path?: string;
|
|
3
3
|
exact?: boolean;
|
|
4
4
|
children: React.ReactNode;
|
|
5
5
|
}
|
|
6
|
-
export declare function Route({ path, exact, children }:
|
|
7
|
-
export {};
|
|
6
|
+
export declare function Route({ path, exact, children }: RouteProps): import("react/jsx-runtime").JSX.Element | null;
|
|
8
7
|
//# sourceMappingURL=route.d.ts.map
|
package/dist/route.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../src/route.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../src/route.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,wBAAgB,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,UAAU,kDA0B1D"}
|
package/dist/route.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { use, useMemo } from "react";
|
|
3
3
|
import { PathnameContext, RouteContext } from "./context";
|
|
4
|
+
import { buildFullPath, compileExactPathRegex, compilePathRegex } from "./path";
|
|
4
5
|
export function Route({ path, exact, children }) {
|
|
5
6
|
const parentRoute = use(RouteContext);
|
|
6
7
|
const pathname = use(PathnameContext);
|
|
@@ -16,42 +17,3 @@ export function Route({ path, exact, children }) {
|
|
|
16
17
|
return null;
|
|
17
18
|
return _jsx(RouteContext, { value: routeContextValue, children: children });
|
|
18
19
|
}
|
|
19
|
-
function compilePathRegex(path) {
|
|
20
|
-
if (path === "/") {
|
|
21
|
-
return /^\//;
|
|
22
|
-
}
|
|
23
|
-
// Handle wildcards: *name captures as named group, * catches all without capturing
|
|
24
|
-
const pattern = path
|
|
25
|
-
.replaceAll(/\*(\w+)/g, "(?<$1>.+)") // *name -> named capture group
|
|
26
|
-
.replaceAll(/\*/g, ".+") // * -> match everything including /
|
|
27
|
-
.replaceAll(/:(\w+)/g, "(?<$1>[\\w-]+)"); // :param -> named capture group
|
|
28
|
-
// If pattern contains a wildcard, it already matches everything - use exact match
|
|
29
|
-
if (path.includes("*")) {
|
|
30
|
-
return new RegExp(`^(${pattern})$`);
|
|
31
|
-
}
|
|
32
|
-
// For non-wildcard paths, allow optional trailing paths
|
|
33
|
-
return new RegExp(`^(${pattern})(/.*)?$`);
|
|
34
|
-
}
|
|
35
|
-
function compileExactPathRegex(path) {
|
|
36
|
-
if (path === "/") {
|
|
37
|
-
return /^\/$/;
|
|
38
|
-
}
|
|
39
|
-
// Handle wildcards: *name captures as named group, * catches all without capturing
|
|
40
|
-
const pattern = path
|
|
41
|
-
.replaceAll(/\*(\w+)/g, "(?<$1>.+)") // *name -> named capture group
|
|
42
|
-
.replaceAll(/\*/g, ".+") // * -> match everything including /
|
|
43
|
-
.replaceAll(/:(\w+)/g, "(?<$1>[\\w-]+)"); // :param -> named capture group
|
|
44
|
-
return new RegExp(`^(${pattern})$`);
|
|
45
|
-
}
|
|
46
|
-
function buildFullPath(parentPath, path) {
|
|
47
|
-
if (path?.startsWith("/")) {
|
|
48
|
-
return path;
|
|
49
|
-
}
|
|
50
|
-
if (path) {
|
|
51
|
-
if (parentPath === "/") {
|
|
52
|
-
return "/" + path;
|
|
53
|
-
}
|
|
54
|
-
return parentPath + "/" + path;
|
|
55
|
-
}
|
|
56
|
-
return parentPath;
|
|
57
|
-
}
|
package/dist/switch.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ReactElement } from "react";
|
|
2
|
+
import type { Route, RouteProps } from "./route";
|
|
3
|
+
interface Props {
|
|
4
|
+
children: ReactElement<RouteProps, typeof Route> | ReactElement<RouteProps, typeof Route>[];
|
|
5
|
+
}
|
|
6
|
+
export declare function Switch({ children }: Props): import("react/jsx-runtime").JSX.Element | null;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=switch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"switch.d.ts","sourceRoot":"","sources":["../src/switch.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAQjD,UAAU,KAAK;IACb,QAAQ,EACJ,YAAY,CAAC,UAAU,EAAE,OAAO,KAAK,CAAC,GACtC,YAAY,CAAC,UAAU,EAAE,OAAO,KAAK,CAAC,EAAE,CAAC;CAC9C;AAED,wBAAgB,MAAM,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,kDAmDzC"}
|
package/dist/switch.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Children, use, useMemo } from "react";
|
|
3
|
+
import { PathnameContext, RouteContext, } from "./context";
|
|
4
|
+
import { buildFullPath, compileExactPathRegex, compilePathRegex } from "./path";
|
|
5
|
+
export function Switch({ children }) {
|
|
6
|
+
const parentRoute = use(RouteContext);
|
|
7
|
+
const pathname = use(PathnameContext);
|
|
8
|
+
const props = Children.map(children, (route) => route.props);
|
|
9
|
+
const routeMeta = useMemo(() => props.map((route) => {
|
|
10
|
+
const path = route.path ?? "";
|
|
11
|
+
const fullPath = buildFullPath(parentRoute.path, path);
|
|
12
|
+
return {
|
|
13
|
+
path,
|
|
14
|
+
fullPath,
|
|
15
|
+
pathRegex: route.exact
|
|
16
|
+
? compileExactPathRegex(fullPath)
|
|
17
|
+
: compilePathRegex(fullPath),
|
|
18
|
+
};
|
|
19
|
+
}), [
|
|
20
|
+
parentRoute.path,
|
|
21
|
+
props.map((route) => (route.exact ? "e" : "l" + route.path)).join(" "),
|
|
22
|
+
]);
|
|
23
|
+
const match = useMemo(() => {
|
|
24
|
+
for (const meta of routeMeta) {
|
|
25
|
+
const match = pathname.match(meta.pathRegex);
|
|
26
|
+
if (match)
|
|
27
|
+
return [
|
|
28
|
+
meta.path,
|
|
29
|
+
{
|
|
30
|
+
path: meta.fullPath,
|
|
31
|
+
params: match?.groups ?? {},
|
|
32
|
+
matchedPathname: match?.[1] ?? "",
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}, [routeMeta]);
|
|
38
|
+
if (!match) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const [path, context] = match;
|
|
42
|
+
return (_jsx(RouteContext, { value: context, children: props.find((route) => route.path === path)?.children }));
|
|
43
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farbenmeer/router",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "Michel Smola",
|
|
6
6
|
"email": "michel.smola@farbenmeer.de"
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"@vitest/browser-playwright": "^4.0.16",
|
|
26
26
|
"react": "^19.1.1",
|
|
27
27
|
"vitest": "^4.0.16",
|
|
28
|
+
"playwright": "^1.58.1",
|
|
28
29
|
"vitest-browser-react": "^2.0.2"
|
|
29
30
|
},
|
|
30
31
|
"peerDependencies": {
|
|
@@ -34,6 +35,7 @@
|
|
|
34
35
|
"scripts": {
|
|
35
36
|
"build": "tsc -p tsconfig.build.json",
|
|
36
37
|
"release": "pnpm run build && pnpm publish",
|
|
37
|
-
"test": "vitest"
|
|
38
|
+
"test": "vitest",
|
|
39
|
+
"ci-setup": "playwright install --with-deps"
|
|
38
40
|
}
|
|
39
41
|
}
|