kdu-router 3.5.4 → 3.6.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 (49) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +11 -11
  3. package/dist/composables.js +253 -0
  4. package/dist/composables.mjs +244 -0
  5. package/dist/kdu-router.common.js +2668 -2665
  6. package/dist/kdu-router.esm.browser.js +2676 -2670
  7. package/dist/kdu-router.esm.browser.min.js +5 -5
  8. package/dist/kdu-router.esm.js +2680 -2674
  9. package/dist/kdu-router.js +2675 -2672
  10. package/dist/kdu-router.min.js +5 -5
  11. package/ketur/attributes.json +38 -38
  12. package/ketur/tags.json +20 -20
  13. package/package.json +115 -90
  14. package/src/components/link.js +224 -224
  15. package/src/components/view.js +155 -155
  16. package/src/composables/globals.js +34 -0
  17. package/src/composables/guards.js +68 -0
  18. package/src/composables/index.js +3 -0
  19. package/src/composables/useLink.js +113 -0
  20. package/src/composables/utils.js +11 -0
  21. package/src/create-matcher.js +226 -226
  22. package/src/create-route-map.js +220 -220
  23. package/src/entries/cjs.js +3 -0
  24. package/src/entries/esm.js +12 -0
  25. package/src/history/abstract.js +72 -72
  26. package/src/history/base.js +379 -379
  27. package/src/history/hash.js +152 -152
  28. package/src/history/html5.js +99 -99
  29. package/src/index.js +3 -293
  30. package/src/install.js +52 -52
  31. package/src/router.js +293 -0
  32. package/src/util/async.js +18 -18
  33. package/src/util/dom.js +3 -3
  34. package/src/util/errors.js +86 -86
  35. package/src/util/location.js +69 -69
  36. package/src/util/misc.js +6 -6
  37. package/src/util/params.js +37 -37
  38. package/src/util/path.js +74 -74
  39. package/src/util/push-state.js +46 -46
  40. package/src/util/query.js +113 -113
  41. package/src/util/resolve-components.js +109 -109
  42. package/src/util/route.js +151 -151
  43. package/src/util/scroll.js +175 -175
  44. package/src/util/state-key.js +22 -22
  45. package/src/util/warn.js +14 -14
  46. package/types/composables.d.ts +53 -0
  47. package/types/index.d.ts +25 -21
  48. package/types/kdu.d.ts +22 -22
  49. package/types/router.d.ts +564 -211
package/src/index.js CHANGED
@@ -1,293 +1,3 @@
1
- /* @flow */
2
-
3
- import { install } from './install'
4
- import { START } from './util/route'
5
- import { assert, warn } from './util/warn'
6
- import { inBrowser } from './util/dom'
7
- import { cleanPath } from './util/path'
8
- import { createMatcher } from './create-matcher'
9
- import { normalizeLocation } from './util/location'
10
- import { supportsPushState } from './util/push-state'
11
- import { handleScroll } from './util/scroll'
12
-
13
- import { HashHistory } from './history/hash'
14
- import { HTML5History } from './history/html5'
15
- import { AbstractHistory } from './history/abstract'
16
-
17
- import type { Matcher } from './create-matcher'
18
-
19
- import { isNavigationFailure, NavigationFailureType } from './util/errors'
20
-
21
- export default class KduRouter {
22
- static install: () => void
23
- static version: string
24
- static isNavigationFailure: Function
25
- static NavigationFailureType: any
26
- static START_LOCATION: Route
27
-
28
- app: any
29
- apps: Array<any>
30
- ready: boolean
31
- readyCbs: Array<Function>
32
- options: RouterOptions
33
- mode: string
34
- history: HashHistory | HTML5History | AbstractHistory
35
- matcher: Matcher
36
- fallback: boolean
37
- beforeHooks: Array<?NavigationGuard>
38
- resolveHooks: Array<?NavigationGuard>
39
- afterHooks: Array<?AfterNavigationHook>
40
-
41
- constructor (options: RouterOptions = {}) {
42
- if (process.env.NODE_ENV !== 'production') {
43
- warn(this instanceof KduRouter, `Router must be called with the new operator.`)
44
- }
45
- this.app = null
46
- this.apps = []
47
- this.options = options
48
- this.beforeHooks = []
49
- this.resolveHooks = []
50
- this.afterHooks = []
51
- this.matcher = createMatcher(options.routes || [], this)
52
-
53
- let mode = options.mode || 'hash'
54
- this.fallback =
55
- mode === 'history' && !supportsPushState && options.fallback !== false
56
- if (this.fallback) {
57
- mode = 'hash'
58
- }
59
- if (!inBrowser) {
60
- mode = 'abstract'
61
- }
62
- this.mode = mode
63
-
64
- switch (mode) {
65
- case 'history':
66
- this.history = new HTML5History(this, options.base)
67
- break
68
- case 'hash':
69
- this.history = new HashHistory(this, options.base, this.fallback)
70
- break
71
- case 'abstract':
72
- this.history = new AbstractHistory(this, options.base)
73
- break
74
- default:
75
- if (process.env.NODE_ENV !== 'production') {
76
- assert(false, `invalid mode: ${mode}`)
77
- }
78
- }
79
- }
80
-
81
- match (raw: RawLocation, current?: Route, redirectedFrom?: Location): Route {
82
- return this.matcher.match(raw, current, redirectedFrom)
83
- }
84
-
85
- get currentRoute (): ?Route {
86
- return this.history && this.history.current
87
- }
88
-
89
- init (app: any /* Kdu component instance */) {
90
- process.env.NODE_ENV !== 'production' &&
91
- assert(
92
- install.installed,
93
- `not installed. Make sure to call \`Kdu.use(KduRouter)\` ` +
94
- `before creating root instance.`
95
- )
96
-
97
- this.apps.push(app)
98
-
99
- // set up app destroyed handler
100
- app.$once('hook:destroyed', () => {
101
- // clean out app from this.apps array once destroyed
102
- const index = this.apps.indexOf(app)
103
- if (index > -1) this.apps.splice(index, 1)
104
- // ensure we still have a main app or null if no apps
105
- // we do not release the router so it can be reused
106
- if (this.app === app) this.app = this.apps[0] || null
107
-
108
- if (!this.app) this.history.teardown()
109
- })
110
-
111
- // main app previously initialized
112
- // return as we don't need to set up new history listener
113
- if (this.app) {
114
- return
115
- }
116
-
117
- this.app = app
118
-
119
- const history = this.history
120
-
121
- if (history instanceof HTML5History || history instanceof HashHistory) {
122
- const handleInitialScroll = routeOrError => {
123
- const from = history.current
124
- const expectScroll = this.options.scrollBehavior
125
- const supportsScroll = supportsPushState && expectScroll
126
-
127
- if (supportsScroll && 'fullPath' in routeOrError) {
128
- handleScroll(this, routeOrError, from, false)
129
- }
130
- }
131
- const setupListeners = routeOrError => {
132
- history.setupListeners()
133
- handleInitialScroll(routeOrError)
134
- }
135
- history.transitionTo(
136
- history.getCurrentLocation(),
137
- setupListeners,
138
- setupListeners
139
- )
140
- }
141
-
142
- history.listen(route => {
143
- this.apps.forEach(app => {
144
- app._route = route
145
- })
146
- })
147
- }
148
-
149
- beforeEach (fn: Function): Function {
150
- return registerHook(this.beforeHooks, fn)
151
- }
152
-
153
- beforeResolve (fn: Function): Function {
154
- return registerHook(this.resolveHooks, fn)
155
- }
156
-
157
- afterEach (fn: Function): Function {
158
- return registerHook(this.afterHooks, fn)
159
- }
160
-
161
- onReady (cb: Function, errorCb?: Function) {
162
- this.history.onReady(cb, errorCb)
163
- }
164
-
165
- onError (errorCb: Function) {
166
- this.history.onError(errorCb)
167
- }
168
-
169
- push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
170
- // $flow-disable-line
171
- if (!onComplete && !onAbort && typeof Promise !== 'undefined') {
172
- return new Promise((resolve, reject) => {
173
- this.history.push(location, resolve, reject)
174
- })
175
- } else {
176
- this.history.push(location, onComplete, onAbort)
177
- }
178
- }
179
-
180
- replace (location: RawLocation, onComplete?: Function, onAbort?: Function) {
181
- // $flow-disable-line
182
- if (!onComplete && !onAbort && typeof Promise !== 'undefined') {
183
- return new Promise((resolve, reject) => {
184
- this.history.replace(location, resolve, reject)
185
- })
186
- } else {
187
- this.history.replace(location, onComplete, onAbort)
188
- }
189
- }
190
-
191
- go (n: number) {
192
- this.history.go(n)
193
- }
194
-
195
- back () {
196
- this.go(-1)
197
- }
198
-
199
- forward () {
200
- this.go(1)
201
- }
202
-
203
- getMatchedComponents (to?: RawLocation | Route): Array<any> {
204
- const route: any = to
205
- ? to.matched
206
- ? to
207
- : this.resolve(to).route
208
- : this.currentRoute
209
- if (!route) {
210
- return []
211
- }
212
- return [].concat.apply(
213
- [],
214
- route.matched.map(m => {
215
- return Object.keys(m.components).map(key => {
216
- return m.components[key]
217
- })
218
- })
219
- )
220
- }
221
-
222
- resolve (
223
- to: RawLocation,
224
- current?: Route,
225
- append?: boolean
226
- ): {
227
- location: Location,
228
- route: Route,
229
- href: string,
230
- // for backwards compat
231
- normalizedTo: Location,
232
- resolved: Route
233
- } {
234
- current = current || this.history.current
235
- const location = normalizeLocation(to, current, append, this)
236
- const route = this.match(location, current)
237
- const fullPath = route.redirectedFrom || route.fullPath
238
- const base = this.history.base
239
- const href = createHref(base, fullPath, this.mode)
240
- return {
241
- location,
242
- route,
243
- href,
244
- // for backwards compat
245
- normalizedTo: location,
246
- resolved: route
247
- }
248
- }
249
-
250
- getRoutes () {
251
- return this.matcher.getRoutes()
252
- }
253
-
254
- addRoute (parentOrRoute: string | RouteConfig, route?: RouteConfig) {
255
- this.matcher.addRoute(parentOrRoute, route)
256
- if (this.history.current !== START) {
257
- this.history.transitionTo(this.history.getCurrentLocation())
258
- }
259
- }
260
-
261
- addRoutes (routes: Array<RouteConfig>) {
262
- if (process.env.NODE_ENV !== 'production') {
263
- warn(false, 'router.addRoutes() is deprecated and has been removed in Kdu Router 4. Use router.addRoute() instead.')
264
- }
265
- this.matcher.addRoutes(routes)
266
- if (this.history.current !== START) {
267
- this.history.transitionTo(this.history.getCurrentLocation())
268
- }
269
- }
270
- }
271
-
272
- function registerHook (list: Array<any>, fn: Function): Function {
273
- list.push(fn)
274
- return () => {
275
- const i = list.indexOf(fn)
276
- if (i > -1) list.splice(i, 1)
277
- }
278
- }
279
-
280
- function createHref (base: string, fullPath: string, mode) {
281
- var path = mode === 'hash' ? '#' + fullPath : fullPath
282
- return base ? cleanPath(base + '/' + path) : path
283
- }
284
-
285
- KduRouter.install = install
286
- KduRouter.version = '__VERSION__'
287
- KduRouter.isNavigationFailure = isNavigationFailure
288
- KduRouter.NavigationFailureType = NavigationFailureType
289
- KduRouter.START_LOCATION = START
290
-
291
- if (inBrowser && window.Kdu) {
292
- window.Kdu.use(KduRouter)
293
- }
1
+ import KduRouter from './entries/cjs'
2
+
3
+ export default KduRouter
package/src/install.js CHANGED
@@ -1,52 +1,52 @@
1
- import View from './components/view'
2
- import Link from './components/link'
3
-
4
- export let _Kdu
5
-
6
- export function install (Kdu) {
7
- if (install.installed && _Kdu === Kdu) return
8
- install.installed = true
9
-
10
- _Kdu = Kdu
11
-
12
- const isDef = v => v !== undefined
13
-
14
- const registerInstance = (vm, callVal) => {
15
- let i = vm.$options._parentKnode
16
- if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
17
- i(vm, callVal)
18
- }
19
- }
20
-
21
- Kdu.mixin({
22
- beforeCreate () {
23
- if (isDef(this.$options.router)) {
24
- this._routerRoot = this
25
- this._router = this.$options.router
26
- this._router.init(this)
27
- Kdu.util.defineReactive(this, '_route', this._router.history.current)
28
- } else {
29
- this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
30
- }
31
- registerInstance(this, this)
32
- },
33
- destroyed () {
34
- registerInstance(this)
35
- }
36
- })
37
-
38
- Object.defineProperty(Kdu.prototype, '$router', {
39
- get () { return this._routerRoot._router }
40
- })
41
-
42
- Object.defineProperty(Kdu.prototype, '$route', {
43
- get () { return this._routerRoot._route }
44
- })
45
-
46
- Kdu.component('RouterView', View)
47
- Kdu.component('RouterLink', Link)
48
-
49
- const strats = Kdu.config.optionMergeStrategies
50
- // use the same hook merging strategy for route hooks
51
- strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created
52
- }
1
+ import View from './components/view'
2
+ import Link from './components/link'
3
+
4
+ export let _Kdu
5
+
6
+ export function install (Kdu) {
7
+ if (install.installed && _Kdu === Kdu) return
8
+ install.installed = true
9
+
10
+ _Kdu = Kdu
11
+
12
+ const isDef = v => v !== undefined
13
+
14
+ const registerInstance = (vm, callVal) => {
15
+ let i = vm.$options._parentKnode
16
+ if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
17
+ i(vm, callVal)
18
+ }
19
+ }
20
+
21
+ Kdu.mixin({
22
+ beforeCreate () {
23
+ if (isDef(this.$options.router)) {
24
+ this._routerRoot = this
25
+ this._router = this.$options.router
26
+ this._router.init(this)
27
+ Kdu.util.defineReactive(this, '_route', this._router.history.current)
28
+ } else {
29
+ this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
30
+ }
31
+ registerInstance(this, this)
32
+ },
33
+ destroyed () {
34
+ registerInstance(this)
35
+ }
36
+ })
37
+
38
+ Object.defineProperty(Kdu.prototype, '$router', {
39
+ get () { return this._routerRoot._router }
40
+ })
41
+
42
+ Object.defineProperty(Kdu.prototype, '$route', {
43
+ get () { return this._routerRoot._route }
44
+ })
45
+
46
+ Kdu.component('RouterView', View)
47
+ Kdu.component('RouterLink', Link)
48
+
49
+ const strats = Kdu.config.optionMergeStrategies
50
+ // use the same hook merging strategy for route hooks
51
+ strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created
52
+ }
package/src/router.js ADDED
@@ -0,0 +1,293 @@
1
+ /* @flow */
2
+
3
+ import { install } from './install'
4
+ import { START } from './util/route'
5
+ import { assert, warn } from './util/warn'
6
+ import { inBrowser } from './util/dom'
7
+ import { cleanPath } from './util/path'
8
+ import { createMatcher } from './create-matcher'
9
+ import { normalizeLocation } from './util/location'
10
+ import { supportsPushState } from './util/push-state'
11
+ import { handleScroll } from './util/scroll'
12
+ import { isNavigationFailure, NavigationFailureType } from './util/errors'
13
+
14
+ import { HashHistory } from './history/hash'
15
+ import { HTML5History } from './history/html5'
16
+ import { AbstractHistory } from './history/abstract'
17
+
18
+ import type { Matcher } from './create-matcher'
19
+
20
+ export default class KduRouter {
21
+ static install: () => void
22
+ static version: string
23
+ static isNavigationFailure: Function
24
+ static NavigationFailureType: any
25
+ static START_LOCATION: Route
26
+
27
+ app: any
28
+ apps: Array<any>
29
+ ready: boolean
30
+ readyCbs: Array<Function>
31
+ options: RouterOptions
32
+ mode: string
33
+ history: HashHistory | HTML5History | AbstractHistory
34
+ matcher: Matcher
35
+ fallback: boolean
36
+ beforeHooks: Array<?NavigationGuard>
37
+ resolveHooks: Array<?NavigationGuard>
38
+ afterHooks: Array<?AfterNavigationHook>
39
+
40
+ constructor (options: RouterOptions = {}) {
41
+ if (process.env.NODE_ENV !== 'production') {
42
+ warn(this instanceof KduRouter, `Router must be called with the new operator.`)
43
+ }
44
+ this.app = null
45
+ this.apps = []
46
+ this.options = options
47
+ this.beforeHooks = []
48
+ this.resolveHooks = []
49
+ this.afterHooks = []
50
+ this.matcher = createMatcher(options.routes || [], this)
51
+
52
+ let mode = options.mode || 'hash'
53
+ this.fallback =
54
+ mode === 'history' && !supportsPushState && options.fallback !== false
55
+ if (this.fallback) {
56
+ mode = 'hash'
57
+ }
58
+ if (!inBrowser) {
59
+ mode = 'abstract'
60
+ }
61
+ this.mode = mode
62
+
63
+ switch (mode) {
64
+ case 'history':
65
+ this.history = new HTML5History(this, options.base)
66
+ break
67
+ case 'hash':
68
+ this.history = new HashHistory(this, options.base, this.fallback)
69
+ break
70
+ case 'abstract':
71
+ this.history = new AbstractHistory(this, options.base)
72
+ break
73
+ default:
74
+ if (process.env.NODE_ENV !== 'production') {
75
+ assert(false, `invalid mode: ${mode}`)
76
+ }
77
+ }
78
+ }
79
+
80
+ match (raw: RawLocation, current?: Route, redirectedFrom?: Location): Route {
81
+ return this.matcher.match(raw, current, redirectedFrom)
82
+ }
83
+
84
+ get currentRoute (): ?Route {
85
+ return this.history && this.history.current
86
+ }
87
+
88
+ init (app: any /* Kdu component instance */) {
89
+ process.env.NODE_ENV !== 'production' &&
90
+ assert(
91
+ install.installed,
92
+ `not installed. Make sure to call \`Kdu.use(KduRouter)\` ` +
93
+ `before creating root instance.`
94
+ )
95
+
96
+ this.apps.push(app)
97
+
98
+ // set up app destroyed handler
99
+ app.$once('hook:destroyed', () => {
100
+ // clean out app from this.apps array once destroyed
101
+ const index = this.apps.indexOf(app)
102
+ if (index > -1) this.apps.splice(index, 1)
103
+ // ensure we still have a main app or null if no apps
104
+ // we do not release the router so it can be reused
105
+ if (this.app === app) this.app = this.apps[0] || null
106
+
107
+ if (!this.app) this.history.teardown()
108
+ })
109
+
110
+ // main app previously initialized
111
+ // return as we don't need to set up new history listener
112
+ if (this.app) {
113
+ return
114
+ }
115
+
116
+ this.app = app
117
+
118
+ const history = this.history
119
+
120
+ if (history instanceof HTML5History || history instanceof HashHistory) {
121
+ const handleInitialScroll = routeOrError => {
122
+ const from = history.current
123
+ const expectScroll = this.options.scrollBehavior
124
+ const supportsScroll = supportsPushState && expectScroll
125
+
126
+ if (supportsScroll && 'fullPath' in routeOrError) {
127
+ handleScroll(this, routeOrError, from, false)
128
+ }
129
+ }
130
+ const setupListeners = routeOrError => {
131
+ history.setupListeners()
132
+ handleInitialScroll(routeOrError)
133
+ }
134
+ history.transitionTo(
135
+ history.getCurrentLocation(),
136
+ setupListeners,
137
+ setupListeners
138
+ )
139
+ }
140
+
141
+ history.listen(route => {
142
+ this.apps.forEach(app => {
143
+ app._route = route
144
+ })
145
+ })
146
+ }
147
+
148
+ beforeEach (fn: Function): Function {
149
+ return registerHook(this.beforeHooks, fn)
150
+ }
151
+
152
+ beforeResolve (fn: Function): Function {
153
+ return registerHook(this.resolveHooks, fn)
154
+ }
155
+
156
+ afterEach (fn: Function): Function {
157
+ return registerHook(this.afterHooks, fn)
158
+ }
159
+
160
+ onReady (cb: Function, errorCb?: Function) {
161
+ this.history.onReady(cb, errorCb)
162
+ }
163
+
164
+ onError (errorCb: Function) {
165
+ this.history.onError(errorCb)
166
+ }
167
+
168
+ push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
169
+ // $flow-disable-line
170
+ if (!onComplete && !onAbort && typeof Promise !== 'undefined') {
171
+ return new Promise((resolve, reject) => {
172
+ this.history.push(location, resolve, reject)
173
+ })
174
+ } else {
175
+ this.history.push(location, onComplete, onAbort)
176
+ }
177
+ }
178
+
179
+ replace (location: RawLocation, onComplete?: Function, onAbort?: Function) {
180
+ // $flow-disable-line
181
+ if (!onComplete && !onAbort && typeof Promise !== 'undefined') {
182
+ return new Promise((resolve, reject) => {
183
+ this.history.replace(location, resolve, reject)
184
+ })
185
+ } else {
186
+ this.history.replace(location, onComplete, onAbort)
187
+ }
188
+ }
189
+
190
+ go (n: number) {
191
+ this.history.go(n)
192
+ }
193
+
194
+ back () {
195
+ this.go(-1)
196
+ }
197
+
198
+ forward () {
199
+ this.go(1)
200
+ }
201
+
202
+ getMatchedComponents (to?: RawLocation | Route): Array<any> {
203
+ const route: any = to
204
+ ? to.matched
205
+ ? to
206
+ : this.resolve(to).route
207
+ : this.currentRoute
208
+ if (!route) {
209
+ return []
210
+ }
211
+ return [].concat.apply(
212
+ [],
213
+ route.matched.map(m => {
214
+ return Object.keys(m.components).map(key => {
215
+ return m.components[key]
216
+ })
217
+ })
218
+ )
219
+ }
220
+
221
+ resolve (
222
+ to: RawLocation,
223
+ current?: Route,
224
+ append?: boolean
225
+ ): {
226
+ location: Location,
227
+ route: Route,
228
+ href: string,
229
+ // for backwards compat
230
+ normalizedTo: Location,
231
+ resolved: Route
232
+ } {
233
+ current = current || this.history.current
234
+ const location = normalizeLocation(to, current, append, this)
235
+ const route = this.match(location, current)
236
+ const fullPath = route.redirectedFrom || route.fullPath
237
+ const base = this.history.base
238
+ const href = createHref(base, fullPath, this.mode)
239
+ return {
240
+ location,
241
+ route,
242
+ href,
243
+ // for backwards compat
244
+ normalizedTo: location,
245
+ resolved: route
246
+ }
247
+ }
248
+
249
+ getRoutes () {
250
+ return this.matcher.getRoutes()
251
+ }
252
+
253
+ addRoute (parentOrRoute: string | RouteConfig, route?: RouteConfig) {
254
+ this.matcher.addRoute(parentOrRoute, route)
255
+ if (this.history.current !== START) {
256
+ this.history.transitionTo(this.history.getCurrentLocation())
257
+ }
258
+ }
259
+
260
+ addRoutes (routes: Array<RouteConfig>) {
261
+ if (process.env.NODE_ENV !== 'production') {
262
+ warn(false, 'router.addRoutes() is deprecated and has been removed in Kdu Router 4. Use router.addRoute() instead.')
263
+ }
264
+ this.matcher.addRoutes(routes)
265
+ if (this.history.current !== START) {
266
+ this.history.transitionTo(this.history.getCurrentLocation())
267
+ }
268
+ }
269
+ }
270
+
271
+ function registerHook (list: Array<any>, fn: Function): Function {
272
+ list.push(fn)
273
+ return () => {
274
+ const i = list.indexOf(fn)
275
+ if (i > -1) list.splice(i, 1)
276
+ }
277
+ }
278
+
279
+ function createHref (base: string, fullPath: string, mode) {
280
+ var path = mode === 'hash' ? '#' + fullPath : fullPath
281
+ return base ? cleanPath(base + '/' + path) : path
282
+ }
283
+
284
+ if (inBrowser && window.Kdu) {
285
+ window.Kdu.use(KduRouter)
286
+ }
287
+
288
+ // We cannot remove this as it would be a breaking change
289
+ KduRouter.install = install
290
+ KduRouter.version = '__VERSION__'
291
+ KduRouter.isNavigationFailure = isNavigationFailure
292
+ KduRouter.NavigationFailureType = NavigationFailureType
293
+ KduRouter.START_LOCATION = START