kdu-router 3.4.0-beta.0 → 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 -6
  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 -92
  13. package/dist/kdu-router.common.js +0 -3040
  14. package/dist/kdu-router.esm.browser.js +0 -3005
  15. package/dist/kdu-router.esm.browser.min.js +0 -11
  16. package/dist/kdu-router.esm.js +0 -3038
  17. package/dist/kdu-router.js +0 -3046
  18. package/dist/kdu-router.min.js +0 -11
  19. package/src/components/link.js +0 -197
  20. package/src/components/view.js +0 -149
  21. package/src/create-matcher.js +0 -200
  22. package/src/create-route-map.js +0 -205
  23. package/src/history/abstract.js +0 -68
  24. package/src/history/base.js +0 -400
  25. package/src/history/hash.js +0 -163
  26. package/src/history/html5.js +0 -94
  27. package/src/index.js +0 -277
  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 -85
  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 -96
  38. package/src/util/resolve-components.js +0 -109
  39. package/src/util/route.js +0 -132
  40. package/src/util/scroll.js +0 -165
  41. package/src/util/state-key.js +0 -22
  42. package/src/util/warn.js +0 -14
  43. package/types/index.d.ts +0 -17
  44. package/types/kdu.d.ts +0 -22
  45. package/types/router.d.ts +0 -170
@@ -1,163 +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
- // decode the hash but not the search or hash
128
- // as search(query) is already decoded
129
- const searchIndex = href.indexOf('?')
130
- if (searchIndex < 0) {
131
- const hashIndex = href.indexOf('#')
132
- if (hashIndex > -1) {
133
- href = decodeURI(href.slice(0, hashIndex)) + href.slice(hashIndex)
134
- } else href = decodeURI(href)
135
- } else {
136
- href = decodeURI(href.slice(0, searchIndex)) + href.slice(searchIndex)
137
- }
138
-
139
- return href
140
- }
141
-
142
- function getUrl (path) {
143
- const href = window.location.href
144
- const i = href.indexOf('#')
145
- const base = i >= 0 ? href.slice(0, i) : href
146
- return `${base}#${path}`
147
- }
148
-
149
- function pushHash (path) {
150
- if (supportsPushState) {
151
- pushState(getUrl(path))
152
- } else {
153
- window.location.hash = path
154
- }
155
- }
156
-
157
- function replaceHash (path) {
158
- if (supportsPushState) {
159
- replaceState(getUrl(path))
160
- } else {
161
- window.location.replace(getUrl(path))
162
- }
163
- }
@@ -1,94 +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 = decodeURI(window.location.pathname)
90
- if (base && path.toLowerCase().indexOf(base.toLowerCase()) === 0) {
91
- path = path.slice(base.length)
92
- }
93
- return (path || '/') + window.location.search + window.location.hash
94
- }
package/src/index.js DELETED
@@ -1,277 +0,0 @@
1
- /* @flow */
2
-
3
- import { install } from './install'
4
- import { START } from './util/route'
5
- import { assert } 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
-
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
- this.app = null
42
- this.apps = []
43
- this.options = options
44
- this.beforeHooks = []
45
- this.resolveHooks = []
46
- this.afterHooks = []
47
- this.matcher = createMatcher(options.routes || [], this)
48
-
49
- let mode = options.mode || 'hash'
50
- this.fallback =
51
- mode === 'history' && !supportsPushState && options.fallback !== false
52
- if (this.fallback) {
53
- mode = 'hash'
54
- }
55
- if (!inBrowser) {
56
- mode = 'abstract'
57
- }
58
- this.mode = mode
59
-
60
- switch (mode) {
61
- case 'history':
62
- this.history = new HTML5History(this, options.base)
63
- break
64
- case 'hash':
65
- this.history = new HashHistory(this, options.base, this.fallback)
66
- break
67
- case 'abstract':
68
- this.history = new AbstractHistory(this, options.base)
69
- break
70
- default:
71
- if (process.env.NODE_ENV !== 'production') {
72
- assert(false, `invalid mode: ${mode}`)
73
- }
74
- }
75
- }
76
-
77
- match (raw: RawLocation, current?: Route, redirectedFrom?: Location): Route {
78
- return this.matcher.match(raw, current, redirectedFrom)
79
- }
80
-
81
- get currentRoute (): ?Route {
82
- return this.history && this.history.current
83
- }
84
-
85
- init (app: any /* Kdu component instance */) {
86
- process.env.NODE_ENV !== 'production' &&
87
- assert(
88
- install.installed,
89
- `not installed. Make sure to call \`Kdu.use(KduRouter)\` ` +
90
- `before creating root instance.`
91
- )
92
-
93
- this.apps.push(app)
94
-
95
- // set up app destroyed handler
96
- app.$once('hook:destroyed', () => {
97
- // clean out app from this.apps array once destroyed
98
- const index = this.apps.indexOf(app)
99
- if (index > -1) this.apps.splice(index, 1)
100
- // ensure we still have a main app or null if no apps
101
- // we do not release the router so it can be reused
102
- if (this.app === app) this.app = this.apps[0] || null
103
-
104
- if (!this.app) {
105
- // clean up event listeners
106
- this.history.teardownListeners()
107
- }
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
- addRoutes (routes: Array<RouteConfig>) {
250
- this.matcher.addRoutes(routes)
251
- if (this.history.current !== START) {
252
- this.history.transitionTo(this.history.getCurrentLocation())
253
- }
254
- }
255
- }
256
-
257
- function registerHook (list: Array<any>, fn: Function): Function {
258
- list.push(fn)
259
- return () => {
260
- const i = list.indexOf(fn)
261
- if (i > -1) list.splice(i, 1)
262
- }
263
- }
264
-
265
- function createHref (base: string, fullPath: string, mode) {
266
- var path = mode === 'hash' ? '#' + fullPath : fullPath
267
- return base ? cleanPath(base + '/' + path) : path
268
- }
269
-
270
- KduRouter.install = install
271
- KduRouter.version = '__VERSION__'
272
- KduRouter.isNavigationFailure = isNavigationFailure
273
- KduRouter.NavigationFailureType = NavigationFailureType
274
-
275
- if (inBrowser && window.Kdu) {
276
- window.Kdu.use(KduRouter)
277
- }
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,85 +0,0 @@
1
- export const NavigationFailureType = {
2
- redirected: 2,
3
- aborted: 4,
4
- cancelled: 8,
5
- duplicated: 16
6
- }
7
-
8
- export function createNavigationRedirectedError (from, to) {
9
- return createRouterError(
10
- from,
11
- to,
12
- NavigationFailureType.redirected,
13
- `Redirected when going from "${from.fullPath}" to "${stringifyRoute(
14
- to
15
- )}" via a navigation guard.`
16
- )
17
- }
18
-
19
- export function createNavigationDuplicatedError (from, to) {
20
- const error = createRouterError(
21
- from,
22
- to,
23
- NavigationFailureType.duplicated,
24
- `Avoided redundant navigation to current location: "${from.fullPath}".`
25
- )
26
- // backwards compatible with the first introduction of Errors
27
- error.name = 'NavigationDuplicated'
28
- return error
29
- }
30
-
31
- export function createNavigationCancelledError (from, to) {
32
- return createRouterError(
33
- from,
34
- to,
35
- NavigationFailureType.cancelled,
36
- `Navigation cancelled from "${from.fullPath}" to "${
37
- to.fullPath
38
- }" with a new navigation.`
39
- )
40
- }
41
-
42
- export function createNavigationAbortedError (from, to) {
43
- return createRouterError(
44
- from,
45
- to,
46
- NavigationFailureType.aborted,
47
- `Navigation aborted from "${from.fullPath}" to "${
48
- to.fullPath
49
- }" via a navigation guard.`
50
- )
51
- }
52
-
53
- function createRouterError (from, to, type, message) {
54
- const error = new Error(message)
55
- error._isRouter = true
56
- error.from = from
57
- error.to = to
58
- error.type = type
59
-
60
- return error
61
- }
62
-
63
- const propertiesToLog = ['params', 'query', 'hash']
64
-
65
- function stringifyRoute (to) {
66
- if (typeof to === 'string') return to
67
- if ('path' in to) return to.path
68
- const location = {}
69
- propertiesToLog.forEach(key => {
70
- if (key in to) location[key] = to[key]
71
- })
72
- return JSON.stringify(location, null, 2)
73
- }
74
-
75
- export function isError (err) {
76
- return Object.prototype.toString.call(err).indexOf('Error') > -1
77
- }
78
-
79
- export function isNavigationFailure (err, errorType) {
80
- return (
81
- isError(err) &&
82
- err._isRouter &&
83
- (errorType == null || err.type === errorType)
84
- )
85
- }