space-router 0.9.5 → 1.0.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 (63) hide show
  1. package/README.md +1 -0
  2. package/dist/history.d.ts +12 -0
  3. package/dist/history.js +98 -0
  4. package/dist/index.d.ts +6 -0
  5. package/dist/index.js +3 -0
  6. package/dist/match.d.ts +16 -0
  7. package/dist/match.js +68 -0
  8. package/dist/qs.d.ts +5 -0
  9. package/dist/qs.js +27 -0
  10. package/dist/router.d.ts +42 -0
  11. package/dist/router.js +131 -0
  12. package/package.json +29 -22
  13. package/src/history.ts +116 -0
  14. package/src/index.ts +7 -0
  15. package/src/match.ts +88 -0
  16. package/src/qs.ts +33 -0
  17. package/src/router.ts +197 -0
  18. package/.prettierignore +0 -5
  19. package/.prettierrc +0 -6
  20. package/.swc-cjs +0 -11
  21. package/.swc-esm +0 -1
  22. package/CHANGELOG.md +0 -68
  23. package/dist/cjs/history.js +0 -100
  24. package/dist/cjs/index.js +0 -27
  25. package/dist/cjs/match.js +0 -94
  26. package/dist/cjs/qs.js +0 -27
  27. package/dist/cjs/router.js +0 -279
  28. package/dist/esm/history.js +0 -90
  29. package/dist/esm/index.js +0 -3
  30. package/dist/esm/match.js +0 -76
  31. package/dist/esm/qs.js +0 -17
  32. package/dist/esm/router.js +0 -258
  33. package/docs/archetypes/default.md +0 -7
  34. package/docs/assets/js/bg.js +0 -742
  35. package/docs/assets/styles/base.scss +0 -2816
  36. package/docs/assets/styles/main.scss +0 -1368
  37. package/docs/assets/styles/syntax-m.scss +0 -264
  38. package/docs/assets/styles/syntax.scss +0 -240
  39. package/docs/config.toml +0 -9
  40. package/docs/content/_index.md +0 -189
  41. package/docs/layouts/404.html +0 -0
  42. package/docs/layouts/_default/baseof.html +0 -68
  43. package/docs/layouts/index.html +0 -31
  44. package/docs/layouts/partials/favicon.html +0 -5
  45. package/docs/layouts/partials/header.html +0 -0
  46. package/docs/layouts/partials/meta/name-author.html +0 -6
  47. package/docs/layouts/partials/meta/ogimage.html +0 -8
  48. package/docs/layouts/partials/site-verification.html +0 -12
  49. package/docs/layouts/shortcodes/callout.html +0 -1
  50. package/docs/static/js/highlightjs-9.15.10.min.js +0 -2
  51. package/docs/static/js/master.js +0 -0
  52. package/docs/static/js/tocbot.min.js +0 -18
  53. package/docs/static/space.png +0 -0
  54. package/oxlintrc.json +0 -6
  55. package/src/history.js +0 -97
  56. package/src/index.js +0 -3
  57. package/src/match.js +0 -87
  58. package/src/qs.js +0 -20
  59. package/src/router.js +0 -147
  60. package/tasks/build.js +0 -16
  61. package/test/flatten.test.js +0 -58
  62. package/test/match.test.js +0 -68
  63. package/test/router.test.js +0 -157
@@ -1,264 +0,0 @@
1
- /* Background */
2
- .chroma {
3
- color: #f8f8f2;
4
- background-color: #282a36;
5
- border-radius: 10px;
6
- }
7
- /* LineTableTD */
8
- .chroma .lntd {
9
- vertical-align: top;
10
- padding: 0;
11
- margin: 0;
12
- border: 0;
13
- }
14
- /* LineTable */
15
- .chroma .lntable {
16
- border-spacing: 0;
17
- padding: 0;
18
- margin: 0;
19
- border: 0;
20
- width: auto;
21
- overflow: auto;
22
- display: block;
23
- }
24
- /* LineHighlight */
25
- .chroma .hl {
26
- display: block;
27
- width: 100%;
28
- background-color: #ffffcc;
29
- }
30
- /* LineNumbersTable */
31
- .chroma .lnt {
32
- margin-right: 0.4em;
33
- padding: 0 0.4em 0 0.4em;
34
- color: #7f7f7f;
35
- }
36
- /* LineNumbers */
37
- .chroma .ln {
38
- margin-right: 0.4em;
39
- padding: 0 0.4em 0 0.4em;
40
- color: #7f7f7f;
41
- }
42
- /* Keyword */
43
- .chroma .k {
44
- color: #ff79c6;
45
- }
46
- /* KeywordConstant */
47
- .chroma .kc {
48
- color: #ff79c6;
49
- }
50
- /* KeywordDeclaration */
51
- .chroma .kd {
52
- color: #8be9fd;
53
- font-style: italic;
54
- }
55
- /* KeywordNamespace */
56
- .chroma .kn {
57
- color: #ff79c6;
58
- }
59
- /* KeywordPseudo */
60
- .chroma .kp {
61
- color: #ff79c6;
62
- }
63
- /* KeywordReserved */
64
- .chroma .kr {
65
- color: #ff79c6;
66
- }
67
- /* KeywordType */
68
- .chroma .kt {
69
- color: #8be9fd;
70
- }
71
- /* NameAttribute */
72
- .chroma .na {
73
- color: #50fa7b;
74
- }
75
- /* NameBuiltin */
76
- .chroma .nb {
77
- color: #8be9fd;
78
- font-style: italic;
79
- }
80
- /* NameClass */
81
- .chroma .nc {
82
- color: #50fa7b;
83
- }
84
- /* NameFunction */
85
- .chroma .nf {
86
- color: #50fa7b;
87
- }
88
- /* NameLabel */
89
- .chroma .nl {
90
- color: #8be9fd;
91
- font-style: italic;
92
- }
93
- /* NameTag */
94
- .chroma .nt {
95
- color: #ff79c6;
96
- }
97
- /* NameVariable */
98
- .chroma .nv {
99
- color: #8be9fd;
100
- font-style: italic;
101
- }
102
- /* NameVariableClass */
103
- .chroma .vc {
104
- color: #8be9fd;
105
- font-style: italic;
106
- }
107
- /* NameVariableGlobal */
108
- .chroma .vg {
109
- color: #8be9fd;
110
- font-style: italic;
111
- }
112
- /* NameVariableInstance */
113
- .chroma .vi {
114
- color: #8be9fd;
115
- font-style: italic;
116
- }
117
- /* LiteralString */
118
- .chroma .s {
119
- color: #f1fa8c;
120
- }
121
- /* LiteralStringAffix */
122
- .chroma .sa {
123
- color: #f1fa8c;
124
- }
125
- /* LiteralStringBacktick */
126
- .chroma .sb {
127
- color: #f1fa8c;
128
- }
129
- /* LiteralStringChar */
130
- .chroma .sc {
131
- color: #f1fa8c;
132
- }
133
- /* LiteralStringDelimiter */
134
- .chroma .dl {
135
- color: #f1fa8c;
136
- }
137
- /* LiteralStringDoc */
138
- .chroma .sd {
139
- color: #f1fa8c;
140
- }
141
- /* LiteralStringDouble */
142
- .chroma .s2 {
143
- color: #f1fa8c;
144
- }
145
- /* LiteralStringEscape */
146
- .chroma .se {
147
- color: #f1fa8c;
148
- }
149
- /* LiteralStringHeredoc */
150
- .chroma .sh {
151
- color: #f1fa8c;
152
- }
153
- /* LiteralStringInterpol */
154
- .chroma .si {
155
- color: #f1fa8c;
156
- }
157
- /* LiteralStringOther */
158
- .chroma .sx {
159
- color: #f1fa8c;
160
- }
161
- /* LiteralStringRegex */
162
- .chroma .sr {
163
- color: #f1fa8c;
164
- }
165
- /* LiteralStringSingle */
166
- .chroma .s1 {
167
- color: #f1fa8c;
168
- }
169
- /* LiteralStringSymbol */
170
- .chroma .ss {
171
- color: #f1fa8c;
172
- }
173
- /* LiteralNumber */
174
- .chroma .m {
175
- color: #bd93f9;
176
- }
177
- /* LiteralNumberBin */
178
- .chroma .mb {
179
- color: #bd93f9;
180
- }
181
- /* LiteralNumberFloat */
182
- .chroma .mf {
183
- color: #bd93f9;
184
- }
185
- /* LiteralNumberHex */
186
- .chroma .mh {
187
- color: #bd93f9;
188
- }
189
- /* LiteralNumberInteger */
190
- .chroma .mi {
191
- color: #bd93f9;
192
- }
193
- /* LiteralNumberIntegerLong */
194
- .chroma .il {
195
- color: #bd93f9;
196
- }
197
- /* LiteralNumberOct */
198
- .chroma .mo {
199
- color: #bd93f9;
200
- }
201
- /* Operator */
202
- .chroma .o {
203
- color: #ff79c6;
204
- }
205
- /* OperatorWord */
206
- .chroma .ow {
207
- color: #ff79c6;
208
- }
209
- /* Comment */
210
- .chroma .c {
211
- color: #6272a4;
212
- }
213
- /* CommentHashbang */
214
- .chroma .ch {
215
- color: #6272a4;
216
- }
217
- /* CommentMultiline */
218
- .chroma .cm {
219
- color: #6272a4;
220
- }
221
- /* CommentSingle */
222
- .chroma .c1 {
223
- color: #6272a4;
224
- }
225
- /* CommentSpecial */
226
- .chroma .cs {
227
- color: #6272a4;
228
- }
229
- /* CommentPreproc */
230
- .chroma .cp {
231
- color: #ff79c6;
232
- }
233
- /* CommentPreprocFile */
234
- .chroma .cpf {
235
- color: #ff79c6;
236
- }
237
- /* GenericDeleted */
238
- .chroma .gd {
239
- color: #8b080b;
240
- }
241
- /* GenericEmph */
242
- .chroma .ge {
243
- text-decoration: underline;
244
- }
245
- /* GenericHeading */
246
- .chroma .gh {
247
- font-weight: bold;
248
- }
249
- /* GenericInserted */
250
- .chroma .gi {
251
- font-weight: bold;
252
- }
253
- /* GenericOutput */
254
- .chroma .go {
255
- color: #44475a;
256
- }
257
- /* GenericSubheading */
258
- .chroma .gu {
259
- font-weight: bold;
260
- }
261
- /* GenericUnderline */
262
- .chroma .gl {
263
- text-decoration: underline;
264
- }
@@ -1,240 +0,0 @@
1
- .chroma {
2
- background-color: rgba(#d9e8ff, 0.2);
3
- }
4
- .chroma .err {
5
- }
6
- .chroma .lntd {
7
- vertical-align: top;
8
- padding: 0;
9
- margin: 0;
10
- border: 0;
11
- }
12
- .chroma .lntable {
13
- border-spacing: 0;
14
- padding: 0;
15
- margin: 0;
16
- border: 0;
17
- width: auto;
18
- overflow: auto;
19
- display: block;
20
- }
21
- .chroma .hl {
22
- display: block;
23
- width: 100%;
24
- background-color: #dfdfdf;
25
- }
26
- .chroma .lnt {
27
- margin-right: 0.4em;
28
- padding: 0 0.4em 0 0.4em;
29
- color: #7f7f7f;
30
- }
31
- .chroma .ln {
32
- margin-right: 0.4em;
33
- padding: 0 0.4em 0 0.4em;
34
- color: #7f7f7f;
35
- }
36
- .chroma .k {
37
- color: #aa22ff;
38
- font-weight: bold;
39
- }
40
- .chroma .kc {
41
- color: #aa22ff;
42
- font-weight: bold;
43
- }
44
- .chroma .kd {
45
- color: #aa22ff;
46
- font-weight: bold;
47
- }
48
- .chroma .kn {
49
- color: #aa22ff;
50
- font-weight: bold;
51
- }
52
- .chroma .kp {
53
- color: #aa22ff;
54
- }
55
- .chroma .kr {
56
- color: #aa22ff;
57
- font-weight: bold;
58
- }
59
- .chroma .kt {
60
- color: #00bb00;
61
- font-weight: bold;
62
- }
63
- .chroma .na {
64
- color: #bb4444;
65
- }
66
- .chroma .nb {
67
- color: #aa22ff;
68
- }
69
- .chroma .nc {
70
- color: #0000ff;
71
- }
72
- .chroma .no {
73
- color: #880000;
74
- }
75
- .chroma .nd {
76
- color: #aa22ff;
77
- }
78
- .chroma .ni {
79
- color: #999999;
80
- font-weight: bold;
81
- }
82
- .chroma .ne {
83
- color: #d2413a;
84
- font-weight: bold;
85
- }
86
- .chroma .nf {
87
- color: #00a000;
88
- }
89
- .chroma .nl {
90
- color: #a0a000;
91
- }
92
- .chroma .nn {
93
- color: #0000ff;
94
- font-weight: bold;
95
- }
96
- .chroma .nt {
97
- color: #008000;
98
- font-weight: bold;
99
- }
100
- .chroma .nv {
101
- color: #b8860b;
102
- }
103
- .chroma .s {
104
- color: #bb4444;
105
- }
106
- .chroma .sa {
107
- color: #bb4444;
108
- }
109
- .chroma .sb {
110
- color: #bb4444;
111
- }
112
- .chroma .sc {
113
- color: #bb4444;
114
- }
115
- .chroma .dl {
116
- color: #bb4444;
117
- }
118
- .chroma .sd {
119
- color: #bb4444;
120
- font-style: italic;
121
- }
122
- .chroma .s2 {
123
- color: #bb4444;
124
- }
125
- .chroma .se {
126
- color: #bb6622;
127
- font-weight: bold;
128
- }
129
- .chroma .sh {
130
- color: #bb4444;
131
- }
132
- .chroma .si {
133
- color: #bb6688;
134
- font-weight: bold;
135
- }
136
- .chroma .sx {
137
- color: #008000;
138
- }
139
- .chroma .sr {
140
- color: #bb6688;
141
- }
142
- .chroma .s1 {
143
- color: #bb4444;
144
- }
145
- .chroma .ss {
146
- color: #b8860b;
147
- }
148
- .chroma .m {
149
- color: #666666;
150
- }
151
- .chroma .mb {
152
- color: #666666;
153
- }
154
- .chroma .mf {
155
- color: #666666;
156
- }
157
- .chroma .mh {
158
- color: #666666;
159
- }
160
- .chroma .mi {
161
- color: #666666;
162
- }
163
- .chroma .il {
164
- color: #666666;
165
- }
166
- .chroma .mo {
167
- color: #666666;
168
- }
169
- .chroma .o {
170
- color: #666666;
171
- }
172
- .chroma .ow {
173
- color: #aa22ff;
174
- font-weight: bold;
175
- }
176
- .chroma .c {
177
- color: #008800;
178
- font-style: italic;
179
- }
180
- .chroma .ch {
181
- color: #008800;
182
- font-style: italic;
183
- }
184
- .chroma .cm {
185
- color: #008800;
186
- font-style: italic;
187
- }
188
- .chroma .c1 {
189
- color: #008800;
190
- font-style: italic;
191
- }
192
- .chroma .cs {
193
- color: #008800;
194
- font-weight: bold;
195
- }
196
- .chroma .cp {
197
- color: #008800;
198
- }
199
- .chroma .cpf {
200
- color: #008800;
201
- }
202
- .chroma .gd {
203
- color: #a00000;
204
- }
205
- .chroma .ge {
206
- font-style: italic;
207
- }
208
- .chroma .gr {
209
- color: #ff0000;
210
- }
211
- .chroma .gh {
212
- color: #000080;
213
- font-weight: bold;
214
- }
215
- .chroma .gi {
216
- color: #00a000;
217
- }
218
- .chroma .go {
219
- color: #888888;
220
- }
221
- .chroma .gp {
222
- color: #000080;
223
- font-weight: bold;
224
- }
225
- .chroma .gs {
226
- font-weight: bold;
227
- }
228
- .chroma .gu {
229
- color: #800080;
230
- font-weight: bold;
231
- }
232
- .chroma .gt {
233
- color: #0044dd;
234
- }
235
- .chroma .gl {
236
- text-decoration: underline;
237
- }
238
- .chroma .w {
239
- color: #bbbbbb;
240
- }
package/docs/config.toml DELETED
@@ -1,9 +0,0 @@
1
- baseURL = "https://kidkarolis.github.io/space-router"
2
- languageCode = "en-us"
3
- title = "Space Router"
4
- description = "A web router with all the essentials."
5
-
6
- [markup]
7
- [markup.highlight]
8
- noClasses = false
9
- tabWidth = 4
@@ -1,189 +0,0 @@
1
- ---
2
- title: 'Space Router'
3
- draft: false
4
- toc: true
5
- ---
6
-
7
- # Space Router
8
-
9
- > Framework agnostic router for single page apps
10
-
11
- Space Router packs all the features you need to keep your app in sync with the url. It's distinct from many other routers in that there is only **a single callback**. This callback can be used to re-render your applocation, update a store and perform other actions on each url change. Space Router is **stateless**, it doesn't store the current route leaving state completely up to you to handle.
12
-
13
- In summary, Space Router:
14
-
15
- - listens to url changes using popstate or hashchange event
16
- - extracts url parameters and parses query strings
17
- - supports nested routes and arbitrary route metadata
18
- - fits into a wide range of application architectures and frameworks
19
- - has no dependencies and weighs less than 2kb
20
-
21
- ## Why?
22
-
23
- Space Router was first created in 2017 to create a minimal library after learning from the various routing approaches used in Backbone, Ember and then React eras. Each new framework brought new requirements for a router, but each new router had a core that was very similar – listening to url changes, parsing url params and queries, performing navigations and generating links. Space Router was created as a framework agnostic router that should be easy enough to use standalone _or_ to built on top of to create more sophisticated bindings for specific frameworks or applications architectures.
24
-
25
- What about [remix-run/history](https://github.com/remix-run/history/)? History wraps the history API only. Space Router takes a more holistic approach with handling url and query parsing and declaring and matching route configurations to create a fully usable standalone router. It doesn't have all the bells of whistles of the `history` package, but if you need them - use that instead.
26
-
27
- See [React Space Router](https://humaans.github.io/react-space-router) for the official React bindings that provide a set of hooks and components to make space router a fully featured routing library for React.
28
-
29
- ## Install
30
-
31
- ```sh
32
- npm i space-router
33
- ```
34
-
35
- ## Example
36
-
37
- ```js
38
- import Preact from 'preact'
39
- import { createRouter } from 'space-router'
40
- import { App, Home, Shows, Show, ShowSettings, NotFound } from './components'
41
-
42
- // define your routes as a nested array of routes
43
- const routes = [
44
- {
45
- component: App,
46
- routes: [
47
- { path: '/', component: Home },
48
- { path: '/shows', component: Shows },
49
- {
50
- path: '/shows/:id',
51
- component: Show,
52
- routes: [{ path: '/shows/:id/settings', component: ShowSettings }],
53
- },
54
- ],
55
- },
56
- { path: '*', component: NotFound },
57
- ]
58
-
59
- // create the router
60
- const router = createRouter()
61
-
62
- // start listening to the url changes and kick of the initial render
63
- // based on the current url
64
- export const dispose = router.listen(routes, render)
65
-
66
- // every time the route changes, do something, e.g. re-render your app
67
- // or implement more complex behaviours, such as fetching route components,
68
- // route data, updating a store and so on, bind this to your application
69
- // the way it makes sense for your framework and architecture
70
- function render(route) {
71
- // using reduceRight here to take the list of the nested components
72
- // e.g. App > Home and render then right to left inside each other
73
- const app = route.data.reduceRight((children, d) => {
74
- const { component: Component } = d
75
- return <Component params={route.params}>{children}</Component>
76
- }, null)
77
- Preact.render(app, document.body, document.body.lastElementChild)
78
- }
79
- ```
80
-
81
- ## API
82
-
83
- ### `createRouter`
84
-
85
- ```js
86
- const router = createRouter(options)
87
- ```
88
-
89
- Create the router object.
90
-
91
- - `options` object
92
- - `mode` - one of `history`, `hash`, `memory`, default is `history`
93
- - `qs` - a custom query string parser, an object of shape `{ parse, stringify }`
94
-
95
- ### `listen`
96
-
97
- ```js
98
- const dispose = router.listen(routes, onChange)
99
- ```
100
-
101
- Start listening to url changes. Every time the url changes via back/forward button or by performing programmatic navigations, the `onChange` callback will get called with the matched `route` object.
102
-
103
- Note, calling listen will immediately call `onChange` based on the current url when in `history` or `hash` modes. This does not happen in `memory` mode so that you could perform the initial navigation yourself since there is no url to read from in that case.
104
-
105
- - `routes` an array of arrays of route definitions, where each route is an object of shape `{ path, redirect, routes, ...metadata }`
106
- - `path` is the url pattern to match that can include named parameters as segments
107
- - `redirect` can be a string or a function that redirects upon entering that route
108
- - `routes` is a nested object of nested route definitions
109
- - `...metadata` all other other keys can be chosen by you
110
- - `onChange` is called with the `route` object
111
-
112
- `route` is an object of shape `{ url, pathname, params, query, search, hash, pattern, data }`:
113
-
114
- - `url` full relative url string including query string and hash if any
115
- - `pathname` the pathname portion of the target url, which can include named segments
116
- - `params` params extracted from the named pathname segments
117
- - `query` query object that was parsed with `qs.parse`
118
- - `search` full unparsed query string
119
- - `hash` hash fragment
120
- - `pattern` the matched route pattern as defined in the route config
121
- - `data` an array of nested matched route objects with any metadata found in the route config
122
-
123
- Listen returns a `dispose` function that stops listening to url changes.
124
-
125
- ### `navigate`
126
-
127
- ```js
128
- router.navigate(to)
129
-
130
- // examples
131
- router.navigate('/shows')
132
- router.navigate({ url: '/show/1' })
133
- router.navigate({ url: '/show/2', replace: true })
134
- router.navigate({ pathname: '/shows', query: { 'most-recent': 1 } })
135
- router.navigate({ query: { 'top-rated': 1 }, merge: true })
136
- router.navigate({ query: { 'top-rated': undefined }, merge: true })
137
- ```
138
-
139
- Navigate to a url. Navigating will update the browser's location bar (unless in `memory` mode) and will call the router listener callback with the newly matched route.
140
-
141
- - `to` - a `string` url or an `object` with the following properties
142
- - `url` a relative url string or a route pattern
143
- - `pathname` the pathname portion of the target url, which can include named segments
144
- - `params` params to interpolate into the named pathname segments
145
- - `query` the query object that will be passed through `qs.stringify`
146
- - `hash` the hash fragment to append to the url of the url
147
- - `replace` set to true to replace the current entry in the navigation stack instead of pushing
148
- - `merge` set to true to merge in the params from the current url, alternatively set to the current route object to use that as the current route to be used in merging
149
-
150
- Note, if `url` option is provided, the `pathname`, `params`, `query` and `hash` will be ignored.
151
-
152
- Note, be careful when using `merge` as this reads the location's current url which might be different from the one you store in your application's state in case you're performing async logic in the listen callback.
153
-
154
- ### `match`
155
-
156
- ```js
157
- const route = router.match(url)
158
- ```
159
-
160
- Match the url string against the routes and return the matching route object.
161
-
162
- ### `href`
163
-
164
- ```js
165
- const url = router.href(to)
166
-
167
- // examples
168
- router.href('/shows')
169
- router.href({ url: '/show/1' })
170
- router.href({ pathname: '/shows', query: { 'most-recent': 1 } })
171
- router.href({ query: { 'top-rated': 1 }, merge: true })
172
- router.href({ query: { 'top-rated': undefined }, merge: true })
173
- ```
174
-
175
- Create a relative url string to use in `<a href>` attribute.
176
-
177
- - `to` object of shape `{ pathname, params, query, hash }`. The `params` will be interpolated into the pathname if the pathname contains any parametrised segments. The `query` is an object that will be passed through `qs.stringify`.
178
-
179
- Note: `to` can be a string, in which case `href` simply returns the input. Similarly, the to can contain `{ url }` key in which case `href` returns that url. This is to align the function signature with that of `navigate` so the two can be used interchangeably.
180
-
181
- ### `getUrl`
182
-
183
- ```js
184
- const url = router.getUrl()
185
- ```
186
-
187
- Get the current url string. Note, this only includes the path and does not not include the protocol and host.
188
-
189
- You shouldn't need to read this most of the time since the updates to url changes and the matching route will be provided in the `listen` callback. Be especially careful if you're performing asynchronous logic in your callback, such as lazily importing some modules, where you're then constructing links based on the current url - use route provided to your listener instead of calling `getUrl` as the url might already have been updated to another value in the meantime.
File without changes