Skip to content

Commit 2961728

Browse files
committed
Refinements
1 parent ec37a0c commit 2961728

File tree

14 files changed

+273
-243
lines changed

14 files changed

+273
-243
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,6 @@ Thumbs.db
2222
# Vite
2323
vite.config.js.timestamp-*
2424
vite.config.ts.timestamp-*
25+
26+
# Tarballs
27+
*.tgz

README.md

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
# @wjfe/n-savant
22

3-
> Small router for Svelte v5 SPA's specialized for micro-frontends.
3+
> The client-side router for Svelte v5 SPA's that invented multi hash routing.
44
55
## Features
66

7-
This router's code is small, revolving the **900** lines of code, including typing.
7+
> [!NOTE]
8+
> #### Small and Unique!
9+
>
10+
> + Less than **900** lines of code, including TypeScript typing.
11+
> + Always-on path and hash routing. Simultaneous and independent routing modes.
12+
> + The router that invented multi hash routing.
813
914
+ **Reactivity-based**: All data is reactive, reducing the need for events and imperative programming.
1015
+ **Always-on path and hash routing**: Add routers that use the URL's path name or the URL's hash value in the same
1116
application. Both routing modes are possible simultaneously.
12-
+ **Multi-hash routing**: Unique to this router and not found in any other router library, you can create named paths
13-
in the hash value of the URL and create router hierarchies that use a specific named path.
17+
+ **Multi-hash routing**: This is the first router in the world to do this: You can create named paths in the hash
18+
value of the URL and create router hierarchies that use a specific named path.
1419

1520
### `<Router>` Component
1621

@@ -165,15 +170,17 @@ or matches most of the time, so navigation links are available the mayority/all
165170

166171
Components (`Router`, `Route`, `Link`, `Fallback` and `RouterTrace`) with the same value of the `hash` property belong
167172
to the same "universe". Components with different hash values belong to different universes, and these universes are
168-
parallel universes. Components with hash value `false` use the URL's path name and will never interere with routers
173+
parallel universes. Components with hash value `false` use the URL's path name and will never interfere with routers
169174
that use hash routing (hash value `true` or a path's name). The main micro-frontend(s) may route using the URL's path
170175
name, while specialty MFE's could route using the path in the hash part of the URL.
171176

172177
### Multi-Hash Routing
173178

174-
Following up from the previous, imagine a scenario where your MFE application would like to show side-by-side two
175-
micro-frontends that are router-enabled (meaning they use or need to work with a path). With traditional routing, you
176-
could not have this setup because one MFE would take over the path, leaving the other MFE without one.
179+
As of Februrary 2025, no other router in the world can do this.
180+
181+
Imagine a scenario where your MFE application would like to show side-by-side two micro-frontends that are
182+
router-enabled (meaning they use or need to work with a path). With traditional routing, you could not have this setup
183+
because one MFE would take over the path, leaving the other MFE without one.
177184

178185
Mutli-hash routing creates named paths in the hash value, giving routers the ability to share the hash value with other
179186
routers. A hash value of the form `#path1=/path/1;path2=/path/2;...` could power side-by-side MFE's on, say, 4K
@@ -182,14 +189,14 @@ layouts.
182189
### EXPERIMENTAL - Replacing the `single-spa` Router
183190

184191
It is the author's intent to implement micro-frontends with only `single-spa` parcels and this router. In other words,
185-
abandon the use of `registerApplication()` and `start()` and just mount parcels.
192+
abandon the use of `registerApplication()` and `start()` and just mount parcels using this router.
186193

187194
[single-spa](https://single-spa.js.org)
188195

189196
## Unintrusive Philosophy
190197

191198
This mini router library imposes minimal restrictions. Here are some features provided by other much larger codebases
192-
(most notably `dvcol/svelte-simple-router`) that are not provided here because Svelte already has the capability.
199+
that are not provided here because Svelte already has the capability.
193200

194201
### Transitions
195202

@@ -214,18 +221,19 @@ Nothing prevents you to add transitions to anything.
214221
Guard routes however you wish. Maybe with an `{#if}` block, or maybe using the route's `and` property that allows you
215222
to specify a predicate function. There are probably many other ways.
216223

217-
### Exact Property on Routes
224+
### `Exact` Property on Routes
218225

219226
Not needed. All matching is exact path matching, and if you want to opt out of the exact route matching, simply add
220-
the rest parameter specifier:
227+
the `rest` parameter specifier (`/*`):
221228

222229
```svelte
223230
<Route key="admin" path="/admin/*">
224231
...
225232
</Route>
226233
```
227234

228-
If you don't care about the value of the parameter, just ignore it.
235+
Now route matching for this route will behave as "starts with". If you don't care about the value of the parameter,
236+
just ignore it.
229237

230238
### Lazy-Loading
231239

@@ -344,8 +352,10 @@ import { location } from "@wjfe/n-savant";
344352

345353
// Path routing navigation:
346354
location.navigate('/new/path', { replace: true, state: { custom: 'Hi' }});
355+
347356
// Hash routing navigation:
348357
location.navigate('#/new/path', { replace: true, state: { custom: 'Hi' }});
358+
349359
// Multi-hash routing navigation:
350360
location.navigate('/new/path', 'path1', { replace: true, state: { custom: 'Hi' }});
351361
```
@@ -360,8 +370,10 @@ Just in case you are wondering: The navigation logic is already there in `<Link
360370
```svelte
361371
<!-- Path Routing => https://example.com/new/path -->
362372
<Link hash="false" href="/new/path">Click Me!</Link>
373+
363374
<!-- Hash Routing => https://example.com/#/new/path -->
364375
<Link hash="true" href="/new/path">Click Me!</Link>
376+
365377
<!-- Multi Hash Routing => https://example.com/#path1=/new/path -->
366378
<!-- Will also preserve any other named paths -->
367379
<Link hash="path1" href="/new/path">Click Me!</Link>
@@ -382,6 +394,6 @@ on the router layouts, again, **at your own risk**.
382394

383395
---
384396

385-
[Full Documentation @ Hashnode Pages](https://wjfe-n-savant.hashnode.pages)
397+
[Full Documentation @ Hashnode Space](https://wjfe-n-savant.hashnode.space)
386398

387399
If you would like to report a bug or request a feature, head to the [Issues page](https://github.com/WJSoftware/wjfe-n-savant/issues).

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
"version": "0.1.0",
44
"scripts": {
55
"dev": "vite dev",
6-
"build": "vite build && npm run prepack && pwsh ./update-svelte-files.ps1",
6+
"build": "vite build && npm run prepack",
77
"preview": "vite preview",
8-
"prepack": "svelte-kit sync && svelte-package && publint",
8+
"prepack": "svelte-kit sync && svelte-package && publint && pwsh ./update-svelte-files.ps1",
99
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
1010
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
1111
"format": "prettier --write .",

src/lib/Fallback/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Fallback
2+
3+
The `Fallback` component can be thought about as a `Route` component that only render its children if there are no
4+
other routes in the parent router engine that match.
5+
6+
Internally, it checks the parent router engine's `noMatches` value, which is a reactive value calculated when all other
7+
route status data is calculated.
8+
9+
## Props
10+
11+
| Property | Type | Default Value | Bindable | Description |
12+
|-|-|-|-|-|
13+
| `hash` | `boolean \| string` | `undefined` | | Sets the hash mode of the component. |
14+
| `children` | `Snippet` | `undefined` | | Renders the children of the component. |
15+
16+
[Online Documentation](https://wjfe-n-savant.hashnode.space/wjfe-n-savant/components/fallback)
17+
18+
## Examples
19+
20+
See the examples for the `Router` component.

src/lib/Link/Link.svelte

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { location } from '$lib/core/Location.js';
33
import { joinPaths, resolveHashValue } from '$lib/core/RouterEngine.svelte.js';
44
import { getRouterContext } from '$lib/Router/Router.svelte';
5+
import type { ActiveState } from '$lib/types.js';
56
import { type Snippet } from 'svelte';
67
import type { HTMLAnchorAttributes } from 'svelte/elements';
78
@@ -58,32 +59,7 @@
5859
*
5960
* **IMPORTANT**: This only works if the component is within a `Router` component.
6061
*/
61-
activeState?: {
62-
/**
63-
* Sets the route key that the link will use to determine if it should render as active.
64-
*/
65-
key?: string;
66-
/**
67-
* Sets the class that the link will use when rendering as active.
68-
*
69-
* For example, set it to `"active"` for Bootstrap setups.
70-
*/
71-
class?: string;
72-
/**
73-
* Sets the style that the link will use when rendering as active.
74-
*
75-
* This can be a string of CSS styles or an object of key-value pairs.
76-
*/
77-
style?: HTMLAnchorAttributes['style'] | Record<string, string>;
78-
/**
79-
* Sets the value of the `aria-current` attribute when the link is active.
80-
*
81-
* The possible values are defined by the HTML specification.
82-
*
83-
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current#values)
84-
*/
85-
ariaCurrent?: HTMLAnchorAttributes['aria-current'];
86-
};
62+
activeState?: ActiveState;
8763
/**
8864
* Configures the component to prepend the parent router's base path to the `href` property.
8965
*

src/lib/Link/README.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Link
2+
3+
The `Link` component renders HTML anchor elements that behave in accordance to its `hash` property, allowing
4+
SPA-friendly navigation (navigation without reloading).
5+
6+
## Props
7+
8+
| Property | Type | Default Value | Bindable | Description |
9+
|-|-|-|-|-|
10+
| `hash` | `boolean \| string` | `undefined` | | Sets the hash mode of the component. |
11+
| `href` | `string` | (none) | | Sets the URL to navigate to. |
12+
| `replace` | `boolean` | `false` | | Configures the link so it replaces the current URL as opposed to pushing the URL as a new entry in the browser's History API. |
13+
| `state` | `any` | `undefined` | | Sets the state object to pass to the browser's History API when pushing or replacing the URL. |
14+
| `activeState` | `ActiveState` | `undefined` | | Sets the various options that are used to automatically style the anchor tag whenever a particular route becomes active. |
15+
| `prependBasePath` | `boolean` | `false` | | Configures the component to prepend the parent router's base path to the `href` property. |
16+
| `children` | `Snippet` | `undefined` | | Renders the children of the component. |
17+
18+
[Online Documentation](https://wjfe-n-savant.hashnode.space/wjfe-n-savant/components/link)
19+
20+
## Examples
21+
22+
### Basic Usage
23+
24+
These don't require a parent router:
25+
26+
```svelte
27+
<!-- Path Routing => https://example.com/new/path -->
28+
<Link hash="false" href="/new/path">Click Me!</Link>
29+
30+
<!-- Hash Routing => https://example.com/#/new/path -->
31+
<Link hash="true" href="/new/path">Click Me!</Link>
32+
33+
<!-- Multi Hash Routing => https://example.com/#path1=/new/path -->
34+
<!-- Will also preserve any other named paths -->
35+
<Link hash="path1" href="/new/path">Click Me!</Link>
36+
```
37+
38+
### Usage Within a Parent Router
39+
40+
In this example, the `Link` component will take advantage of the parent router to inherit its base path and to
41+
automatically trigger its active appearance based on a specific route becoming active.
42+
43+
```svelte
44+
<Router basePath="/some/base">
45+
<Link
46+
hash="path1"
47+
href="/admin/users"
48+
prependBasePath
49+
activeState={{ key: 'adminUsers', class: 'active', }}
50+
>
51+
Click Me!
52+
</Link>
53+
<Route key="adminUsers" path="/admin/users">
54+
...
55+
</Route>
56+
</Router>
57+
```

0 commit comments

Comments
 (0)