@farbenmeer/router 0.2.0 → 0.3.0

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 (3) hide show
  1. package/README.md +25 -11
  2. package/dist/route.js +17 -2
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -8,7 +8,8 @@ The `@farbenmeer/router` package provides a very lightweight routing solution fo
8
8
 
9
9
  - **Declarative routing** with React components
10
10
  - **Nested routes** with parameter inheritance
11
- - **Path parameters** with bracket notation (`[id]`)
11
+ - **Path parameters** with colon syntax (`:id`)
12
+ - **Wildcard routes** for catch-all paths (`*` and `*name`)
12
13
  - **Immutable search parameters** for predictable state management
13
14
  - **Client-side navigation** with history management
14
15
  - **TypeScript support** for better development experience
@@ -38,7 +39,7 @@ function App() {
38
39
  <Route exact>
39
40
  <UsersList />
40
41
  </Route>
41
- <Route path="[id]">
42
+ <Route path=":id">
42
43
  <UserProfile />
43
44
  </Route>
44
45
  </Route>
@@ -65,7 +66,8 @@ The root component that provides routing context to your application.
65
66
  ### [Route](./docs/Route.md)
66
67
  Conditionally renders content based on the current pathname.
67
68
 
68
- - Path matching with parameters (`/users/[id]`)
69
+ - Path matching with parameters (`/users/:id`)
70
+ - Wildcard matching (`/files/*` or `/files/*path`)
69
71
  - Exact matching option
70
72
  - Nested route support
71
73
  - Parameter inheritance from parent routes
@@ -109,7 +111,7 @@ const newParams = searchParams.set("filter", "active");
109
111
  Extract parameters from dynamic route segments.
110
112
 
111
113
  ```tsx
112
- // Route: /users/[id]/posts/[postId]
114
+ // Route: /users/:id/posts/:postId
113
115
  const params = useParams(); // { id: "123", postId: "456" }
114
116
  ```
115
117
 
@@ -128,13 +130,13 @@ const activeTab = hash.slice(1) || "overview";
128
130
  Create hierarchical route structures with parameter inheritance:
129
131
 
130
132
  ```tsx
131
- <Route path="/organizations/[orgId]">
133
+ <Route path="/organizations/:orgId">
132
134
  <OrganizationLayout />
133
135
 
134
- <Route path="teams/[teamId]">
136
+ <Route path="teams/:teamId">
135
137
  <TeamLayout />
136
138
 
137
- <Route path="members/[memberId]">
139
+ <Route path="members/:memberId">
138
140
  <MemberProfile />
139
141
  </Route>
140
142
  </Route>
@@ -143,14 +145,26 @@ Create hierarchical route structures with parameter inheritance:
143
145
 
144
146
  ### Path Parameters
145
147
 
146
- Define dynamic segments with bracket notation:
148
+ Define dynamic segments with colon syntax:
147
149
 
148
150
  ```tsx
149
- <Route path="/users/[id]"> {/* /users/123 */}
150
- <Route path="/posts/[slug]"> {/* /posts/hello-world */}
151
- <Route path="/api/[version]"> {/* /api/v1 */}
151
+ <Route path="/users/:id"> {/* /users/123 */}
152
+ <Route path="/posts/:slug"> {/* /posts/hello-world */}
153
+ <Route path="/api/:version"> {/* /api/v1 */}
152
154
  ```
153
155
 
156
+ ### Wildcard Routes
157
+
158
+ Match arbitrary paths with wildcards:
159
+
160
+ ```tsx
161
+ <Route path="/files/*"> {/* Matches /files/a, /files/a/b/c, etc. */}
162
+ <Route path="/docs/*path"> {/* Matches and captures as params.path */}
163
+ <Route path="/api/:version/*rest"> {/* Combines params with wildcards */}
164
+ ```
165
+
166
+ The `*` wildcard matches everything including slashes, making it perfect for catch-all routes. Use `*name` to capture the matched path as a parameter accessible via `useParams()`.
167
+
154
168
  ### Immutable Search Parameters
155
169
 
156
170
  Safely update URL search parameters without mutations:
package/dist/route.js CHANGED
@@ -20,13 +20,28 @@ function compilePathRegex(path) {
20
20
  if (path === "/") {
21
21
  return /^\//;
22
22
  }
23
- return new RegExp(`^(${path.replaceAll(/\[(\w+)\]/g, "(?<$1>[\\w-]+)")})(/.*)?$`);
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})(/.*)?$`);
24
34
  }
25
35
  function compileExactPathRegex(path) {
26
36
  if (path === "/") {
27
37
  return /^\/$/;
28
38
  }
29
- return new RegExp(`^(${path.replaceAll(/\[(\w+)\]/g, "(?<$1>[\\w-]+)")})$`);
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})$`);
30
45
  }
31
46
  function buildFullPath(parentPath, path) {
32
47
  if (path?.startsWith("/")) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farbenmeer/router",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "author": {
5
5
  "name": "Michel Smola",
6
6
  "email": "michel.smola@farbenmeer.de"