kdu-router 3.4.0-beta.0 → 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 -9
  3. package/dist/composables.js +253 -0
  4. package/dist/composables.mjs +244 -0
  5. package/dist/kdu-router.common.js +2682 -2572
  6. package/dist/kdu-router.esm.browser.js +2677 -2563
  7. package/dist/kdu-router.esm.browser.min.js +5 -5
  8. package/dist/kdu-router.esm.js +2685 -2572
  9. package/dist/kdu-router.js +2682 -2573
  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 -111
  14. package/src/components/link.js +224 -197
  15. package/src/components/view.js +155 -149
  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 -200
  22. package/src/create-route-map.js +220 -205
  23. package/src/entries/cjs.js +3 -0
  24. package/src/entries/esm.js +12 -0
  25. package/src/history/abstract.js +72 -68
  26. package/src/history/base.js +379 -400
  27. package/src/history/hash.js +152 -163
  28. package/src/history/html5.js +99 -94
  29. package/src/index.js +3 -277
  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 -85
  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 -96
  41. package/src/util/resolve-components.js +109 -109
  42. package/src/util/route.js +151 -132
  43. package/src/util/scroll.js +175 -165
  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 -17
  48. package/types/kdu.d.ts +22 -22
  49. package/types/router.d.ts +564 -170
@@ -1,163 +1,152 @@
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
+ /* @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,94 +1,99 @@
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
- }
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
+ }