kdu-router 3.5.4 → 4.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 (45) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +8 -8
  3. package/dist/kdu-router.cjs.js +2848 -0
  4. package/dist/kdu-router.cjs.prod.js +2610 -0
  5. package/dist/kdu-router.d.ts +1255 -0
  6. package/dist/kdu-router.esm-browser.js +3332 -0
  7. package/dist/kdu-router.esm-bundler.js +3343 -0
  8. package/dist/kdu-router.global.js +3354 -0
  9. package/dist/kdu-router.global.prod.js +6 -0
  10. package/ketur/attributes.json +8 -14
  11. package/ketur/tags.json +2 -12
  12. package/package.json +64 -71
  13. package/dist/kdu-router.common.js +0 -3147
  14. package/dist/kdu-router.esm.browser.js +0 -3113
  15. package/dist/kdu-router.esm.browser.min.js +0 -11
  16. package/dist/kdu-router.esm.js +0 -3145
  17. package/dist/kdu-router.js +0 -3152
  18. package/dist/kdu-router.min.js +0 -11
  19. package/src/components/link.js +0 -224
  20. package/src/components/view.js +0 -155
  21. package/src/create-matcher.js +0 -226
  22. package/src/create-route-map.js +0 -220
  23. package/src/history/abstract.js +0 -72
  24. package/src/history/base.js +0 -379
  25. package/src/history/hash.js +0 -152
  26. package/src/history/html5.js +0 -99
  27. package/src/index.js +0 -293
  28. package/src/install.js +0 -52
  29. package/src/util/async.js +0 -18
  30. package/src/util/dom.js +0 -3
  31. package/src/util/errors.js +0 -86
  32. package/src/util/location.js +0 -69
  33. package/src/util/misc.js +0 -6
  34. package/src/util/params.js +0 -37
  35. package/src/util/path.js +0 -74
  36. package/src/util/push-state.js +0 -46
  37. package/src/util/query.js +0 -113
  38. package/src/util/resolve-components.js +0 -109
  39. package/src/util/route.js +0 -151
  40. package/src/util/scroll.js +0 -175
  41. package/src/util/state-key.js +0 -22
  42. package/src/util/warn.js +0 -14
  43. package/types/index.d.ts +0 -21
  44. package/types/kdu.d.ts +0 -22
  45. package/types/router.d.ts +0 -211
@@ -1,152 +0,0 @@
1
- /* @flow */
2
-
3
- import type Router from '../index'
4
- import { History } from './base'
5
- import { cleanPath } from '../util/path'
6
- import { getLocation } from './html5'
7
- import { setupScroll, handleScroll } from '../util/scroll'
8
- import { pushState, replaceState, supportsPushState } from '../util/push-state'
9
-
10
- export class HashHistory extends History {
11
- constructor (router: Router, base: ?string, fallback: boolean) {
12
- super(router, base)
13
- // check history fallback deeplinking
14
- if (fallback && checkFallback(this.base)) {
15
- return
16
- }
17
- ensureSlash()
18
- }
19
-
20
- // this is delayed until the app mounts
21
- // to avoid the hashchange listener being fired too early
22
- setupListeners () {
23
- if (this.listeners.length > 0) {
24
- return
25
- }
26
-
27
- const router = this.router
28
- const expectScroll = router.options.scrollBehavior
29
- const supportsScroll = supportsPushState && expectScroll
30
-
31
- if (supportsScroll) {
32
- this.listeners.push(setupScroll())
33
- }
34
-
35
- const handleRoutingEvent = () => {
36
- const current = this.current
37
- if (!ensureSlash()) {
38
- return
39
- }
40
- this.transitionTo(getHash(), route => {
41
- if (supportsScroll) {
42
- handleScroll(this.router, route, current, true)
43
- }
44
- if (!supportsPushState) {
45
- replaceHash(route.fullPath)
46
- }
47
- })
48
- }
49
- const eventType = supportsPushState ? 'popstate' : 'hashchange'
50
- window.addEventListener(
51
- eventType,
52
- handleRoutingEvent
53
- )
54
- this.listeners.push(() => {
55
- window.removeEventListener(eventType, handleRoutingEvent)
56
- })
57
- }
58
-
59
- push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
60
- const { current: fromRoute } = this
61
- this.transitionTo(
62
- location,
63
- route => {
64
- pushHash(route.fullPath)
65
- handleScroll(this.router, route, fromRoute, false)
66
- onComplete && onComplete(route)
67
- },
68
- onAbort
69
- )
70
- }
71
-
72
- replace (location: RawLocation, onComplete?: Function, onAbort?: Function) {
73
- const { current: fromRoute } = this
74
- this.transitionTo(
75
- location,
76
- route => {
77
- replaceHash(route.fullPath)
78
- handleScroll(this.router, route, fromRoute, false)
79
- onComplete && onComplete(route)
80
- },
81
- onAbort
82
- )
83
- }
84
-
85
- go (n: number) {
86
- window.history.go(n)
87
- }
88
-
89
- ensureURL (push?: boolean) {
90
- const current = this.current.fullPath
91
- if (getHash() !== current) {
92
- push ? pushHash(current) : replaceHash(current)
93
- }
94
- }
95
-
96
- getCurrentLocation () {
97
- return getHash()
98
- }
99
- }
100
-
101
- function checkFallback (base) {
102
- const location = getLocation(base)
103
- if (!/^\/#/.test(location)) {
104
- window.location.replace(cleanPath(base + '/#' + location))
105
- return true
106
- }
107
- }
108
-
109
- function ensureSlash (): boolean {
110
- const path = getHash()
111
- if (path.charAt(0) === '/') {
112
- return true
113
- }
114
- replaceHash('/' + path)
115
- return false
116
- }
117
-
118
- export function getHash (): string {
119
- // We can't use window.location.hash here because it's not
120
- // consistent across browsers - Firefox will pre-decode it!
121
- let href = window.location.href
122
- const index = href.indexOf('#')
123
- // empty path
124
- if (index < 0) return ''
125
-
126
- href = href.slice(index + 1)
127
-
128
- return href
129
- }
130
-
131
- function getUrl (path) {
132
- const href = window.location.href
133
- const i = href.indexOf('#')
134
- const base = i >= 0 ? href.slice(0, i) : href
135
- return `${base}#${path}`
136
- }
137
-
138
- function pushHash (path) {
139
- if (supportsPushState) {
140
- pushState(getUrl(path))
141
- } else {
142
- window.location.hash = path
143
- }
144
- }
145
-
146
- function replaceHash (path) {
147
- if (supportsPushState) {
148
- replaceState(getUrl(path))
149
- } else {
150
- window.location.replace(getUrl(path))
151
- }
152
- }
@@ -1,99 +0,0 @@
1
- /* @flow */
2
-
3
- import type Router from '../index'
4
- import { History } from './base'
5
- import { cleanPath } from '../util/path'
6
- import { START } from '../util/route'
7
- import { setupScroll, handleScroll } from '../util/scroll'
8
- import { pushState, replaceState, supportsPushState } from '../util/push-state'
9
-
10
- export class HTML5History extends History {
11
- _startLocation: string
12
-
13
- constructor (router: Router, base: ?string) {
14
- super(router, base)
15
-
16
- this._startLocation = getLocation(this.base)
17
- }
18
-
19
- setupListeners () {
20
- if (this.listeners.length > 0) {
21
- return
22
- }
23
-
24
- const router = this.router
25
- const expectScroll = router.options.scrollBehavior
26
- const supportsScroll = supportsPushState && expectScroll
27
-
28
- if (supportsScroll) {
29
- this.listeners.push(setupScroll())
30
- }
31
-
32
- const handleRoutingEvent = () => {
33
- const current = this.current
34
-
35
- // Avoiding first `popstate` event dispatched in some browsers but first
36
- // history route not updated since async guard at the same time.
37
- const location = getLocation(this.base)
38
- if (this.current === START && location === this._startLocation) {
39
- return
40
- }
41
-
42
- this.transitionTo(location, route => {
43
- if (supportsScroll) {
44
- handleScroll(router, route, current, true)
45
- }
46
- })
47
- }
48
- window.addEventListener('popstate', handleRoutingEvent)
49
- this.listeners.push(() => {
50
- window.removeEventListener('popstate', handleRoutingEvent)
51
- })
52
- }
53
-
54
- go (n: number) {
55
- window.history.go(n)
56
- }
57
-
58
- push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
59
- const { current: fromRoute } = this
60
- this.transitionTo(location, route => {
61
- pushState(cleanPath(this.base + route.fullPath))
62
- handleScroll(this.router, route, fromRoute, false)
63
- onComplete && onComplete(route)
64
- }, onAbort)
65
- }
66
-
67
- replace (location: RawLocation, onComplete?: Function, onAbort?: Function) {
68
- const { current: fromRoute } = this
69
- this.transitionTo(location, route => {
70
- replaceState(cleanPath(this.base + route.fullPath))
71
- handleScroll(this.router, route, fromRoute, false)
72
- onComplete && onComplete(route)
73
- }, onAbort)
74
- }
75
-
76
- ensureURL (push?: boolean) {
77
- if (getLocation(this.base) !== this.current.fullPath) {
78
- const current = cleanPath(this.base + this.current.fullPath)
79
- push ? pushState(current) : replaceState(current)
80
- }
81
- }
82
-
83
- getCurrentLocation (): string {
84
- return getLocation(this.base)
85
- }
86
- }
87
-
88
- export function getLocation (base: string): string {
89
- let path = window.location.pathname
90
- const pathLowerCase = path.toLowerCase()
91
- const baseLowerCase = base.toLowerCase()
92
- // base="/a" shouldn't turn path="/app" into "/a/pp"
93
- // so we ensure the trailing slash in the base
94
- if (base && ((pathLowerCase === baseLowerCase) ||
95
- (pathLowerCase.indexOf(cleanPath(baseLowerCase + '/')) === 0))) {
96
- path = path.slice(base.length)
97
- }
98
- return (path || '/') + window.location.search + window.location.hash
99
- }
package/src/index.js DELETED
@@ -1,293 +0,0 @@
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
- }
package/src/install.js DELETED
@@ -1,52 +0,0 @@
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/util/async.js DELETED
@@ -1,18 +0,0 @@
1
- /* @flow */
2
-
3
- export function runQueue (queue: Array<?NavigationGuard>, fn: Function, cb: Function) {
4
- const step = index => {
5
- if (index >= queue.length) {
6
- cb()
7
- } else {
8
- if (queue[index]) {
9
- fn(queue[index], () => {
10
- step(index + 1)
11
- })
12
- } else {
13
- step(index + 1)
14
- }
15
- }
16
- }
17
- step(0)
18
- }
package/src/util/dom.js DELETED
@@ -1,3 +0,0 @@
1
- /* @flow */
2
-
3
- export const inBrowser = typeof window !== 'undefined'
@@ -1,86 +0,0 @@
1
- // When changing thing, also edit router.d.ts
2
- export const NavigationFailureType = {
3
- redirected: 2,
4
- aborted: 4,
5
- cancelled: 8,
6
- duplicated: 16
7
- }
8
-
9
- export function createNavigationRedirectedError (from, to) {
10
- return createRouterError(
11
- from,
12
- to,
13
- NavigationFailureType.redirected,
14
- `Redirected when going from "${from.fullPath}" to "${stringifyRoute(
15
- to
16
- )}" via a navigation guard.`
17
- )
18
- }
19
-
20
- export function createNavigationDuplicatedError (from, to) {
21
- const error = createRouterError(
22
- from,
23
- to,
24
- NavigationFailureType.duplicated,
25
- `Avoided redundant navigation to current location: "${from.fullPath}".`
26
- )
27
- // backwards compatible with the first introduction of Errors
28
- error.name = 'NavigationDuplicated'
29
- return error
30
- }
31
-
32
- export function createNavigationCancelledError (from, to) {
33
- return createRouterError(
34
- from,
35
- to,
36
- NavigationFailureType.cancelled,
37
- `Navigation cancelled from "${from.fullPath}" to "${
38
- to.fullPath
39
- }" with a new navigation.`
40
- )
41
- }
42
-
43
- export function createNavigationAbortedError (from, to) {
44
- return createRouterError(
45
- from,
46
- to,
47
- NavigationFailureType.aborted,
48
- `Navigation aborted from "${from.fullPath}" to "${
49
- to.fullPath
50
- }" via a navigation guard.`
51
- )
52
- }
53
-
54
- function createRouterError (from, to, type, message) {
55
- const error = new Error(message)
56
- error._isRouter = true
57
- error.from = from
58
- error.to = to
59
- error.type = type
60
-
61
- return error
62
- }
63
-
64
- const propertiesToLog = ['params', 'query', 'hash']
65
-
66
- function stringifyRoute (to) {
67
- if (typeof to === 'string') return to
68
- if ('path' in to) return to.path
69
- const location = {}
70
- propertiesToLog.forEach(key => {
71
- if (key in to) location[key] = to[key]
72
- })
73
- return JSON.stringify(location, null, 2)
74
- }
75
-
76
- export function isError (err) {
77
- return Object.prototype.toString.call(err).indexOf('Error') > -1
78
- }
79
-
80
- export function isNavigationFailure (err, errorType) {
81
- return (
82
- isError(err) &&
83
- err._isRouter &&
84
- (errorType == null || err.type === errorType)
85
- )
86
- }