vuejs-rails 1.0.26 → 2.0.1
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.
- checksums.yaml +4 -4
- data/Readme.md +6 -0
- data/lib/vuejs-rails/version.rb +1 -1
- data/vendor/assets/javascripts/vue-resource.js +1226 -1020
- data/vendor/assets/javascripts/vue-router.js +1574 -2446
- data/vendor/assets/javascripts/vue.js +6770 -9441
- data/vuejs-rails.gemspec +1 -1
- metadata +2 -2
@@ -1,2709 +1,1837 @@
|
|
1
|
-
|
2
|
-
* vue-router
|
1
|
+
/**
|
2
|
+
* vue-router v2.0.0
|
3
3
|
* (c) 2016 Evan You
|
4
|
-
*
|
4
|
+
* @license MIT
|
5
5
|
*/
|
6
6
|
(function (global, factory) {
|
7
7
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
8
8
|
typeof define === 'function' && define.amd ? define(factory) :
|
9
|
-
global.VueRouter = factory();
|
10
|
-
}(this, function () { 'use strict';
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
9
|
+
(global.VueRouter = factory());
|
10
|
+
}(this, (function () { 'use strict';
|
11
|
+
|
12
|
+
var View = {
|
13
|
+
name: 'router-view',
|
14
|
+
functional: true,
|
15
|
+
props: {
|
16
|
+
name: {
|
17
|
+
type: String,
|
18
|
+
default: 'default'
|
17
19
|
}
|
18
|
-
}
|
19
|
-
function
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
},
|
21
|
+
render: function render (h, ref) {
|
22
|
+
var props = ref.props;
|
23
|
+
var children = ref.children;
|
24
|
+
var parent = ref.parent;
|
25
|
+
var data = ref.data;
|
24
26
|
|
25
|
-
|
26
|
-
to: function to(target, callback) {
|
27
|
-
var delegate = this.delegate;
|
27
|
+
data.routerView = true
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
var route = parent.$route
|
30
|
+
var cache = parent._routerViewCache || (parent._routerViewCache = {})
|
31
|
+
var depth = 0
|
32
|
+
var inactive = false
|
33
|
+
|
34
|
+
while (parent) {
|
35
|
+
if (parent.$vnode && parent.$vnode.data.routerView) {
|
36
|
+
depth++
|
37
|
+
}
|
38
|
+
if (parent._inactive) {
|
39
|
+
inactive = true
|
31
40
|
}
|
41
|
+
parent = parent.$parent
|
42
|
+
}
|
32
43
|
|
33
|
-
|
44
|
+
data.routerViewDepth = depth
|
45
|
+
var matched = route.matched[depth]
|
46
|
+
if (!matched) {
|
47
|
+
return h()
|
48
|
+
}
|
34
49
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
50
|
+
var component = inactive
|
51
|
+
? cache[props.name]
|
52
|
+
: (cache[props.name] = matched.components[props.name])
|
53
|
+
|
54
|
+
if (!inactive) {
|
55
|
+
(data.hook || (data.hook = {})).init = function (vnode) {
|
56
|
+
matched.instances[props.name] = vnode.child
|
40
57
|
}
|
41
|
-
return this;
|
42
58
|
}
|
43
|
-
};
|
44
59
|
|
45
|
-
|
46
|
-
this.routes = {};
|
47
|
-
this.children = {};
|
48
|
-
this.target = target;
|
60
|
+
return h(component, data, children)
|
49
61
|
}
|
62
|
+
}
|
50
63
|
|
51
|
-
|
52
|
-
add: function add(path, handler) {
|
53
|
-
this.routes[path] = handler;
|
54
|
-
},
|
55
|
-
|
56
|
-
addChild: function addChild(path, target, callback, delegate) {
|
57
|
-
var matcher = new Matcher(target);
|
58
|
-
this.children[path] = matcher;
|
59
|
-
|
60
|
-
var match = generateMatch(path, matcher, delegate);
|
64
|
+
/* */
|
61
65
|
|
62
|
-
|
63
|
-
|
64
|
-
|
66
|
+
function resolvePath (
|
67
|
+
relative,
|
68
|
+
base,
|
69
|
+
append
|
70
|
+
) {
|
71
|
+
if (relative.charAt(0) === '/') {
|
72
|
+
return relative
|
73
|
+
}
|
65
74
|
|
66
|
-
|
67
|
-
|
68
|
-
}
|
75
|
+
if (relative.charAt(0) === '?' || relative.charAt(0) === '#') {
|
76
|
+
return base + relative
|
77
|
+
}
|
69
78
|
|
70
|
-
|
71
|
-
return function (path, nestedCallback) {
|
72
|
-
var fullPath = startingPath + path;
|
79
|
+
var stack = base.split('/')
|
73
80
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
};
|
81
|
+
// remove trailing segment if:
|
82
|
+
// - not appending
|
83
|
+
// - appending to trailing slash (last segment is empty)
|
84
|
+
if (!append || !stack[stack.length - 1]) {
|
85
|
+
stack.pop()
|
80
86
|
}
|
81
87
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
88
|
+
// resolve relative path
|
89
|
+
var segments = relative.replace(/^\//, '').split('/')
|
90
|
+
for (var i = 0; i < segments.length; i++) {
|
91
|
+
var segment = segments[i]
|
92
|
+
if (segment === '.') {
|
93
|
+
continue
|
94
|
+
} else if (segment === '..') {
|
95
|
+
stack.pop()
|
96
|
+
} else {
|
97
|
+
stack.push(segment)
|
86
98
|
}
|
99
|
+
}
|
87
100
|
|
88
|
-
|
89
|
-
|
90
|
-
|
101
|
+
// ensure leading slash
|
102
|
+
if (stack[0] !== '') {
|
103
|
+
stack.unshift('')
|
91
104
|
}
|
92
105
|
|
93
|
-
|
94
|
-
|
106
|
+
return stack.join('/')
|
107
|
+
}
|
95
108
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
addRoute(routeArray, path, routes[path]);
|
109
|
+
function parsePath (path) {
|
110
|
+
var hash = ''
|
111
|
+
var query = ''
|
100
112
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
}
|
106
|
-
}
|
107
|
-
}
|
113
|
+
var hashIndex = path.indexOf('#')
|
114
|
+
if (hashIndex >= 0) {
|
115
|
+
hash = path.slice(hashIndex)
|
116
|
+
path = path.slice(0, hashIndex)
|
108
117
|
}
|
109
118
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
119
|
+
var queryIndex = path.indexOf('?')
|
120
|
+
if (queryIndex >= 0) {
|
121
|
+
query = path.slice(queryIndex + 1)
|
122
|
+
path = path.slice(0, queryIndex)
|
123
|
+
}
|
114
124
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
this.add(route);
|
120
|
-
}
|
121
|
-
}, this);
|
125
|
+
return {
|
126
|
+
path: path,
|
127
|
+
query: query,
|
128
|
+
hash: hash
|
122
129
|
}
|
130
|
+
}
|
123
131
|
|
124
|
-
|
132
|
+
function cleanPath (path) {
|
133
|
+
return path.replace(/\/\//g, '/')
|
134
|
+
}
|
125
135
|
|
126
|
-
|
136
|
+
/* */
|
127
137
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
console.error('[vue-router] ' + msg);
|
132
|
-
}
|
138
|
+
function assert (condition, message) {
|
139
|
+
if (!condition) {
|
140
|
+
throw new Error(("[vue-router] " + message))
|
133
141
|
}
|
142
|
+
}
|
134
143
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
} catch (e) {
|
139
|
-
warn('malformed URI' + (asComponent ? ' component: ' : ': ') + uri);
|
140
|
-
}
|
144
|
+
function warn (condition, message) {
|
145
|
+
if (!condition) {
|
146
|
+
typeof console !== 'undefined' && console.warn(("[vue-router] " + message))
|
141
147
|
}
|
148
|
+
}
|
142
149
|
|
143
|
-
|
144
|
-
return Object.prototype.toString.call(test) === "[object Array]";
|
145
|
-
}
|
150
|
+
/* */
|
146
151
|
|
147
|
-
|
148
|
-
|
149
|
-
//
|
150
|
-
// The `eachChar` method invokes the callback with one or more character
|
151
|
-
// specifications. A character specification consumes one or more input
|
152
|
-
// characters.
|
153
|
-
//
|
154
|
-
// The `regex` method returns a regex fragment for the segment. If the
|
155
|
-
// segment is a dynamic of star segment, the regex fragment also includes
|
156
|
-
// a capture.
|
157
|
-
//
|
158
|
-
// A character specification contains:
|
159
|
-
//
|
160
|
-
// * `validChars`: a String with a list of all valid characters, or
|
161
|
-
// * `invalidChars`: a String with a list of all invalid characters
|
162
|
-
// * `repeat`: true if the character specification can repeat
|
152
|
+
var encode = encodeURIComponent
|
153
|
+
var decode = decodeURIComponent
|
163
154
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
var string = this.string,
|
170
|
-
ch;
|
155
|
+
function resolveQuery (
|
156
|
+
query,
|
157
|
+
extraQuery
|
158
|
+
) {
|
159
|
+
if ( extraQuery === void 0 ) extraQuery = {};
|
171
160
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
}
|
161
|
+
if (query) {
|
162
|
+
var parsedQuery
|
163
|
+
try {
|
164
|
+
parsedQuery = parseQuery(query)
|
165
|
+
} catch (e) {
|
166
|
+
warn(false, e.message)
|
167
|
+
parsedQuery = {}
|
168
|
+
}
|
169
|
+
for (var key in extraQuery) {
|
170
|
+
parsedQuery[key] = extraQuery[key]
|
171
|
+
}
|
172
|
+
return parsedQuery
|
173
|
+
} else {
|
174
|
+
return extraQuery
|
175
|
+
}
|
176
|
+
}
|
177
177
|
|
178
|
-
|
179
|
-
|
180
|
-
},
|
178
|
+
function parseQuery (query) {
|
179
|
+
var res = Object.create(null)
|
181
180
|
|
182
|
-
|
183
|
-
return this.string;
|
184
|
-
}
|
185
|
-
};
|
181
|
+
query = query.trim().replace(/^(\?|#|&)/, '')
|
186
182
|
|
187
|
-
|
188
|
-
|
183
|
+
if (!query) {
|
184
|
+
return res
|
189
185
|
}
|
190
|
-
DynamicSegment.prototype = {
|
191
|
-
eachChar: function eachChar(callback) {
|
192
|
-
callback({ invalidChars: "/", repeat: true });
|
193
|
-
},
|
194
186
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
187
|
+
query.split('&').forEach(function (param) {
|
188
|
+
var parts = param.replace(/\+/g, ' ').split('=')
|
189
|
+
var key = decode(parts.shift())
|
190
|
+
var val = parts.length > 0
|
191
|
+
? decode(parts.join('='))
|
192
|
+
: null
|
193
|
+
|
194
|
+
if (res[key] === undefined) {
|
195
|
+
res[key] = val
|
196
|
+
} else if (Array.isArray(res[key])) {
|
197
|
+
res[key].push(val)
|
198
|
+
} else {
|
199
|
+
res[key] = [res[key], val]
|
202
200
|
}
|
203
|
-
}
|
201
|
+
})
|
204
202
|
|
205
|
-
|
206
|
-
|
207
|
-
}
|
208
|
-
StarSegment.prototype = {
|
209
|
-
eachChar: function eachChar(callback) {
|
210
|
-
callback({ invalidChars: "", repeat: true });
|
211
|
-
},
|
203
|
+
return res
|
204
|
+
}
|
212
205
|
|
213
|
-
|
214
|
-
|
215
|
-
|
206
|
+
function stringifyQuery (obj) {
|
207
|
+
var res = obj ? Object.keys(obj).sort().map(function (key) {
|
208
|
+
var val = obj[key]
|
216
209
|
|
217
|
-
|
218
|
-
|
219
|
-
return val == null ? ":" + this.name : val;
|
210
|
+
if (val === undefined) {
|
211
|
+
return ''
|
220
212
|
}
|
221
|
-
};
|
222
213
|
|
223
|
-
|
224
|
-
|
225
|
-
eachChar: function eachChar() {},
|
226
|
-
regex: function regex() {
|
227
|
-
return "";
|
228
|
-
},
|
229
|
-
generate: function generate() {
|
230
|
-
return "";
|
214
|
+
if (val === null) {
|
215
|
+
return encode(key)
|
231
216
|
}
|
232
|
-
};
|
233
217
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
218
|
+
if (Array.isArray(val)) {
|
219
|
+
var result = []
|
220
|
+
val.slice().forEach(function (val2) {
|
221
|
+
if (val2 === undefined) {
|
222
|
+
return
|
223
|
+
}
|
224
|
+
if (val2 === null) {
|
225
|
+
result.push(encode(key))
|
226
|
+
} else {
|
227
|
+
result.push(encode(key) + '=' + encode(val2))
|
228
|
+
}
|
229
|
+
})
|
230
|
+
return result.join('&')
|
239
231
|
}
|
240
232
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
233
|
+
return encode(key) + '=' + encode(val)
|
234
|
+
}).filter(function (x) { return x.length > 0; }).join('&') : null
|
235
|
+
return res ? ("?" + res) : ''
|
236
|
+
}
|
237
|
+
|
238
|
+
/* */
|
239
|
+
|
240
|
+
function createRoute (
|
241
|
+
record,
|
242
|
+
location,
|
243
|
+
redirectedFrom
|
244
|
+
) {
|
245
|
+
var route = {
|
246
|
+
name: location.name || (record && record.name),
|
247
|
+
meta: (record && record.meta) || {},
|
248
|
+
path: location.path || '/',
|
249
|
+
hash: location.hash || '',
|
250
|
+
query: location.query || {},
|
251
|
+
params: location.params || {},
|
252
|
+
fullPath: getFullPath(location),
|
253
|
+
matched: record ? formatMatch(record) : []
|
254
|
+
}
|
255
|
+
if (redirectedFrom) {
|
256
|
+
route.redirectedFrom = getFullPath(redirectedFrom)
|
257
|
+
}
|
258
|
+
return Object.freeze(route)
|
259
|
+
}
|
260
|
+
|
261
|
+
// the starting route that represents the initial state
|
262
|
+
var START = createRoute(null, {
|
263
|
+
path: '/'
|
264
|
+
})
|
265
|
+
|
266
|
+
function formatMatch (record) {
|
267
|
+
var res = []
|
268
|
+
while (record) {
|
269
|
+
res.unshift(record)
|
270
|
+
record = record.parent
|
271
|
+
}
|
272
|
+
return res
|
273
|
+
}
|
274
|
+
|
275
|
+
function getFullPath (ref) {
|
276
|
+
var path = ref.path;
|
277
|
+
var query = ref.query; if ( query === void 0 ) query = {};
|
278
|
+
var hash = ref.hash; if ( hash === void 0 ) hash = '';
|
279
|
+
|
280
|
+
return (path || '/') + stringifyQuery(query) + hash
|
281
|
+
}
|
282
|
+
|
283
|
+
var trailingSlashRE = /\/$/
|
284
|
+
function isSameRoute (a, b) {
|
285
|
+
if (b === START) {
|
286
|
+
return a === b
|
287
|
+
} else if (!b) {
|
288
|
+
return false
|
289
|
+
} else if (a.path && b.path) {
|
290
|
+
return (
|
291
|
+
a.path.replace(trailingSlashRE, '') === b.path.replace(trailingSlashRE, '') &&
|
292
|
+
a.hash === b.hash &&
|
293
|
+
isObjectEqual(a.query, b.query)
|
294
|
+
)
|
295
|
+
} else if (a.name && b.name) {
|
296
|
+
return (
|
297
|
+
a.name === b.name &&
|
298
|
+
a.hash === b.hash &&
|
299
|
+
isObjectEqual(a.query, b.query) &&
|
300
|
+
isObjectEqual(a.params, b.params)
|
301
|
+
)
|
302
|
+
} else {
|
303
|
+
return false
|
304
|
+
}
|
305
|
+
}
|
285
306
|
|
286
|
-
|
307
|
+
function isObjectEqual (a, b) {
|
308
|
+
if ( a === void 0 ) a = {};
|
309
|
+
if ( b === void 0 ) b = {};
|
287
310
|
|
288
|
-
|
311
|
+
var aKeys = Object.keys(a)
|
312
|
+
var bKeys = Object.keys(b)
|
313
|
+
if (aKeys.length !== bKeys.length) {
|
314
|
+
return false
|
315
|
+
}
|
316
|
+
return aKeys.every(function (key) { return String(a[key]) === String(b[key]); })
|
317
|
+
}
|
318
|
+
|
319
|
+
function isIncludedRoute (current, target) {
|
320
|
+
return (
|
321
|
+
current.path.indexOf(target.path) === 0 &&
|
322
|
+
(!target.hash || current.hash === target.hash) &&
|
323
|
+
queryIncludes(current.query, target.query)
|
324
|
+
)
|
325
|
+
}
|
326
|
+
|
327
|
+
function queryIncludes (current, target) {
|
328
|
+
for (var key in target) {
|
329
|
+
if (!(key in current)) {
|
330
|
+
return false
|
331
|
+
}
|
332
|
+
}
|
333
|
+
return true
|
334
|
+
}
|
335
|
+
|
336
|
+
/* */
|
337
|
+
|
338
|
+
function normalizeLocation (
|
339
|
+
raw,
|
340
|
+
current,
|
341
|
+
append
|
342
|
+
) {
|
343
|
+
var next = typeof raw === 'string' ? { path: raw } : raw
|
344
|
+
if (next.name || next._normalized) {
|
345
|
+
return next
|
289
346
|
}
|
290
347
|
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
// to registered handlers with the specified parameters
|
301
|
-
// * `types`: How many static, dynamic or star segments in this route. Used to
|
302
|
-
// decide which route to use if multiple registered routes match a path.
|
303
|
-
//
|
304
|
-
// Currently, State is implemented naively by looping over `nextStates` and
|
305
|
-
// comparing a character specification against a character. A more efficient
|
306
|
-
// implementation would use a hash of keys pointing at one or more next states.
|
307
|
-
|
308
|
-
function State(charSpec) {
|
309
|
-
this.charSpec = charSpec;
|
310
|
-
this.nextStates = [];
|
348
|
+
var parsedPath = parsePath(next.path || '')
|
349
|
+
var basePath = (current && current.path) || '/'
|
350
|
+
var path = parsedPath.path
|
351
|
+
? resolvePath(parsedPath.path, basePath, append)
|
352
|
+
: (current && current.path) || '/'
|
353
|
+
var query = resolveQuery(parsedPath.query, next.query)
|
354
|
+
var hash = next.hash || parsedPath.hash
|
355
|
+
if (hash && hash.charAt(0) !== '#') {
|
356
|
+
hash = "#" + hash
|
311
357
|
}
|
312
358
|
|
313
|
-
|
314
|
-
|
315
|
-
|
359
|
+
return {
|
360
|
+
_normalized: true,
|
361
|
+
path: path,
|
362
|
+
query: query,
|
363
|
+
hash: hash
|
364
|
+
}
|
365
|
+
}
|
316
366
|
|
317
|
-
|
318
|
-
var child = nextStates[i];
|
367
|
+
/* */
|
319
368
|
|
320
|
-
|
321
|
-
|
369
|
+
// work around weird flow bug
|
370
|
+
var toTypes = [String, Object]
|
322
371
|
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
372
|
+
var Link = {
|
373
|
+
name: 'router-link',
|
374
|
+
props: {
|
375
|
+
to: {
|
376
|
+
type: toTypes,
|
377
|
+
required: true
|
327
378
|
},
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
// If the character specification already exists in a child of the current
|
333
|
-
// state, just return that state.
|
334
|
-
if (state = this.get(charSpec)) {
|
335
|
-
return state;
|
336
|
-
}
|
337
|
-
|
338
|
-
// Make a new state for the character spec
|
339
|
-
state = new State(charSpec);
|
340
|
-
|
341
|
-
// Insert the new state as a child of the current state
|
342
|
-
this.nextStates.push(state);
|
343
|
-
|
344
|
-
// If this character specification repeats, insert the new state as a child
|
345
|
-
// of itself. Note that this will not trigger an infinite loop because each
|
346
|
-
// transition during recognition consumes a character.
|
347
|
-
if (charSpec.repeat) {
|
348
|
-
state.nextStates.push(state);
|
349
|
-
}
|
350
|
-
|
351
|
-
// Return the new state
|
352
|
-
return state;
|
379
|
+
tag: {
|
380
|
+
type: String,
|
381
|
+
default: 'a'
|
353
382
|
},
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
383
|
+
exact: Boolean,
|
384
|
+
append: Boolean,
|
385
|
+
replace: Boolean,
|
386
|
+
activeClass: String
|
387
|
+
},
|
388
|
+
render: function render (h) {
|
389
|
+
var this$1 = this;
|
390
|
+
|
391
|
+
var router = this.$router
|
392
|
+
var current = this.$route
|
393
|
+
var to = normalizeLocation(this.to, current, this.append)
|
394
|
+
var resolved = router.match(to)
|
395
|
+
var fullPath = resolved.redirectedFrom || resolved.fullPath
|
396
|
+
var base = router.history.base
|
397
|
+
var href = base ? cleanPath(base + fullPath) : fullPath
|
398
|
+
var classes = {}
|
399
|
+
var activeClass = this.activeClass || router.options.linkActiveClass || 'router-link-active'
|
400
|
+
var compareTarget = to.path ? createRoute(null, to) : resolved
|
401
|
+
classes[activeClass] = this.exact
|
402
|
+
? isSameRoute(current, compareTarget)
|
403
|
+
: isIncludedRoute(current, compareTarget)
|
404
|
+
|
405
|
+
var on = {
|
406
|
+
click: function (e) {
|
407
|
+
e.preventDefault()
|
408
|
+
if (this$1.replace) {
|
409
|
+
router.replace(to)
|
410
|
+
} else {
|
411
|
+
router.push(to)
|
379
412
|
}
|
380
413
|
}
|
414
|
+
}
|
381
415
|
|
382
|
-
|
416
|
+
var data = {
|
417
|
+
class: classes
|
383
418
|
}
|
384
419
|
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
420
|
+
if (this.tag === 'a') {
|
421
|
+
data.on = on
|
422
|
+
data.attrs = { href: href }
|
423
|
+
} else {
|
424
|
+
// find the first <a> child and apply listener and href
|
425
|
+
var a = findAnchor(this.$slots.default)
|
426
|
+
if (a) {
|
427
|
+
var aData = a.data || (a.data = {})
|
428
|
+
aData.on = on
|
429
|
+
var aAttrs = aData.attrs || (aData.attrs = {})
|
430
|
+
aAttrs.href = href
|
431
|
+
}
|
395
432
|
}
|
396
|
-
END IF **/
|
397
|
-
};
|
398
433
|
|
399
|
-
|
400
|
-
function debug(log) {
|
401
|
-
console.log(log);
|
434
|
+
return h(this.tag, data, this.$slots.default)
|
402
435
|
}
|
436
|
+
}
|
403
437
|
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
438
|
+
function findAnchor (children) {
|
439
|
+
if (children) {
|
440
|
+
var child
|
441
|
+
for (var i = 0; i < children.length; i++) {
|
442
|
+
child = children[i]
|
443
|
+
if (child.tag === 'a') {
|
444
|
+
return child
|
445
|
+
}
|
446
|
+
if (child.children && (child = findAnchor(child.children))) {
|
447
|
+
return child
|
448
|
+
}
|
449
|
+
}
|
409
450
|
}
|
410
|
-
|
451
|
+
}
|
411
452
|
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
return b.specificity.val - a.specificity.val;
|
416
|
-
});
|
417
|
-
}
|
453
|
+
function install (Vue) {
|
454
|
+
if (install.installed) { return }
|
455
|
+
install.installed = true
|
418
456
|
|
419
|
-
|
420
|
-
|
457
|
+
Object.defineProperty(Vue.prototype, '$router', {
|
458
|
+
get: function get () { return this.$root._router }
|
459
|
+
})
|
421
460
|
|
422
|
-
|
423
|
-
|
461
|
+
Object.defineProperty(Vue.prototype, '$route', {
|
462
|
+
get: function get$1 () { return this.$root._route }
|
463
|
+
})
|
424
464
|
|
425
|
-
|
465
|
+
Vue.mixin({
|
466
|
+
beforeCreate: function beforeCreate () {
|
467
|
+
if (this.$options.router) {
|
468
|
+
this._router = this.$options.router
|
469
|
+
this._router.init(this)
|
470
|
+
Vue.util.defineReactive(this, '_route', this._router.history.current)
|
471
|
+
}
|
426
472
|
}
|
473
|
+
})
|
427
474
|
|
428
|
-
|
429
|
-
|
475
|
+
Vue.component('router-view', View)
|
476
|
+
Vue.component('router-link', Link)
|
477
|
+
}
|
430
478
|
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
return new F();
|
435
|
-
};
|
479
|
+
var __moduleExports = Array.isArray || function (arr) {
|
480
|
+
return Object.prototype.toString.call(arr) == '[object Array]';
|
481
|
+
};
|
436
482
|
|
437
|
-
|
438
|
-
this.queryParams = queryParams || {};
|
439
|
-
}
|
440
|
-
RecognizeResults.prototype = oCreate({
|
441
|
-
splice: Array.prototype.splice,
|
442
|
-
slice: Array.prototype.slice,
|
443
|
-
push: Array.prototype.push,
|
444
|
-
length: 0,
|
445
|
-
queryParams: null
|
446
|
-
});
|
447
|
-
|
448
|
-
function findHandler(state, path, queryParams) {
|
449
|
-
var handlers = state.handlers,
|
450
|
-
regex = state.regex;
|
451
|
-
var captures = path.match(regex),
|
452
|
-
currentCapture = 1;
|
453
|
-
var result = new RecognizeResults(queryParams);
|
454
|
-
|
455
|
-
for (var i = 0, l = handlers.length; i < l; i++) {
|
456
|
-
var handler = handlers[i],
|
457
|
-
names = handler.names,
|
458
|
-
params = {};
|
459
|
-
|
460
|
-
for (var j = 0, m = names.length; j < m; j++) {
|
461
|
-
params[names[j]] = captures[currentCapture++];
|
462
|
-
}
|
483
|
+
var isarray = __moduleExports
|
463
484
|
|
464
|
-
|
485
|
+
/**
|
486
|
+
* Expose `pathToRegexp`.
|
487
|
+
*/
|
488
|
+
var index = pathToRegexp
|
489
|
+
var parse_1 = parse
|
490
|
+
var compile_1 = compile
|
491
|
+
var tokensToFunction_1 = tokensToFunction
|
492
|
+
var tokensToRegExp_1 = tokensToRegExp
|
493
|
+
|
494
|
+
/**
|
495
|
+
* The main path matching regexp utility.
|
496
|
+
*
|
497
|
+
* @type {RegExp}
|
498
|
+
*/
|
499
|
+
var PATH_REGEXP = new RegExp([
|
500
|
+
// Match escaped characters that would otherwise appear in future matches.
|
501
|
+
// This allows the user to escape special characters that won't transform.
|
502
|
+
'(\\\\.)',
|
503
|
+
// Match Express-style parameters and un-named parameters with a prefix
|
504
|
+
// and optional suffixes. Matches appear as:
|
505
|
+
//
|
506
|
+
// "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined]
|
507
|
+
// "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined, undefined]
|
508
|
+
// "/*" => ["/", undefined, undefined, undefined, undefined, "*"]
|
509
|
+
'([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))'
|
510
|
+
].join('|'), 'g')
|
511
|
+
|
512
|
+
/**
|
513
|
+
* Parse a string for the raw tokens.
|
514
|
+
*
|
515
|
+
* @param {string} str
|
516
|
+
* @return {!Array}
|
517
|
+
*/
|
518
|
+
function parse (str) {
|
519
|
+
var tokens = []
|
520
|
+
var key = 0
|
521
|
+
var index = 0
|
522
|
+
var path = ''
|
523
|
+
var res
|
524
|
+
|
525
|
+
while ((res = PATH_REGEXP.exec(str)) != null) {
|
526
|
+
var m = res[0]
|
527
|
+
var escaped = res[1]
|
528
|
+
var offset = res.index
|
529
|
+
path += str.slice(index, offset)
|
530
|
+
index = offset + m.length
|
531
|
+
|
532
|
+
// Ignore already escaped sequences.
|
533
|
+
if (escaped) {
|
534
|
+
path += escaped[1]
|
535
|
+
continue
|
465
536
|
}
|
466
537
|
|
467
|
-
|
468
|
-
|
538
|
+
var next = str[index]
|
539
|
+
var prefix = res[2]
|
540
|
+
var name = res[3]
|
541
|
+
var capture = res[4]
|
542
|
+
var group = res[5]
|
543
|
+
var modifier = res[6]
|
544
|
+
var asterisk = res[7]
|
545
|
+
|
546
|
+
// Push the current path onto the tokens.
|
547
|
+
if (path) {
|
548
|
+
tokens.push(path)
|
549
|
+
path = ''
|
550
|
+
}
|
469
551
|
|
470
|
-
|
471
|
-
|
472
|
-
|
552
|
+
var partial = prefix != null && next != null && next !== prefix
|
553
|
+
var repeat = modifier === '+' || modifier === '*'
|
554
|
+
var optional = modifier === '?' || modifier === '*'
|
555
|
+
var delimiter = res[2] || '/'
|
556
|
+
var pattern = capture || group || (asterisk ? '.*' : '[^' + delimiter + ']+?')
|
557
|
+
|
558
|
+
tokens.push({
|
559
|
+
name: name || key++,
|
560
|
+
prefix: prefix || '',
|
561
|
+
delimiter: delimiter,
|
562
|
+
optional: optional,
|
563
|
+
repeat: repeat,
|
564
|
+
partial: partial,
|
565
|
+
asterisk: !!asterisk,
|
566
|
+
pattern: escapeGroup(pattern)
|
567
|
+
})
|
568
|
+
}
|
473
569
|
|
474
|
-
|
475
|
-
|
570
|
+
// Match any characters still remaining.
|
571
|
+
if (index < str.length) {
|
572
|
+
path += str.substr(index)
|
573
|
+
}
|
476
574
|
|
477
|
-
|
575
|
+
// If the path exists, push it onto the end.
|
576
|
+
if (path) {
|
577
|
+
tokens.push(path)
|
478
578
|
}
|
479
579
|
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
580
|
+
return tokens
|
581
|
+
}
|
582
|
+
|
583
|
+
/**
|
584
|
+
* Compile a string to a template function for the path.
|
585
|
+
*
|
586
|
+
* @param {string} str
|
587
|
+
* @return {!function(Object=, Object=)}
|
588
|
+
*/
|
589
|
+
function compile (str) {
|
590
|
+
return tokensToFunction(parse(str))
|
591
|
+
}
|
592
|
+
|
593
|
+
/**
|
594
|
+
* Prettier encoding of URI path segments.
|
595
|
+
*
|
596
|
+
* @param {string}
|
597
|
+
* @return {string}
|
598
|
+
*/
|
599
|
+
function encodeURIComponentPretty (str) {
|
600
|
+
return encodeURI(str).replace(/[\/?#]/g, function (c) {
|
601
|
+
return '%' + c.charCodeAt(0).toString(16).toUpperCase()
|
602
|
+
})
|
603
|
+
}
|
604
|
+
|
605
|
+
/**
|
606
|
+
* Encode the asterisk parameter. Similar to `pretty`, but allows slashes.
|
607
|
+
*
|
608
|
+
* @param {string}
|
609
|
+
* @return {string}
|
610
|
+
*/
|
611
|
+
function encodeAsterisk (str) {
|
612
|
+
return encodeURI(str).replace(/[?#]/g, function (c) {
|
613
|
+
return '%' + c.charCodeAt(0).toString(16).toUpperCase()
|
614
|
+
})
|
615
|
+
}
|
616
|
+
|
617
|
+
/**
|
618
|
+
* Expose a method for transforming tokens into the path function.
|
619
|
+
*/
|
620
|
+
function tokensToFunction (tokens) {
|
621
|
+
// Compile all the tokens into regexps.
|
622
|
+
var matches = new Array(tokens.length)
|
623
|
+
|
624
|
+
// Compile all the patterns before compilation.
|
625
|
+
for (var i = 0; i < tokens.length; i++) {
|
626
|
+
if (typeof tokens[i] === 'object') {
|
627
|
+
matches[i] = new RegExp('^(?:' + tokens[i].pattern + ')$')
|
628
|
+
}
|
484
629
|
}
|
485
630
|
|
486
|
-
|
631
|
+
return function (obj, opts) {
|
632
|
+
var path = ''
|
633
|
+
var data = obj || {}
|
634
|
+
var options = opts || {}
|
635
|
+
var encode = options.pretty ? encodeURIComponentPretty : encodeURIComponent
|
487
636
|
|
488
|
-
|
489
|
-
|
490
|
-
this.names = {};
|
491
|
-
};
|
637
|
+
for (var i = 0; i < tokens.length; i++) {
|
638
|
+
var token = tokens[i]
|
492
639
|
|
493
|
-
|
494
|
-
|
495
|
-
var currentState = this.rootState,
|
496
|
-
regex = "^",
|
497
|
-
specificity = {},
|
498
|
-
handlers = [],
|
499
|
-
allSegments = [],
|
500
|
-
name;
|
640
|
+
if (typeof token === 'string') {
|
641
|
+
path += token
|
501
642
|
|
502
|
-
|
643
|
+
continue
|
644
|
+
}
|
503
645
|
|
504
|
-
|
505
|
-
|
506
|
-
names = [];
|
646
|
+
var value = data[token.name]
|
647
|
+
var segment
|
507
648
|
|
508
|
-
|
649
|
+
if (value == null) {
|
650
|
+
if (token.optional) {
|
651
|
+
// Prepend partial segment prefixes.
|
652
|
+
if (token.partial) {
|
653
|
+
path += token.prefix
|
654
|
+
}
|
509
655
|
|
510
|
-
|
656
|
+
continue
|
657
|
+
} else {
|
658
|
+
throw new TypeError('Expected "' + token.name + '" to be defined')
|
659
|
+
}
|
660
|
+
}
|
511
661
|
|
512
|
-
|
513
|
-
|
662
|
+
if (isarray(value)) {
|
663
|
+
if (!token.repeat) {
|
664
|
+
throw new TypeError('Expected "' + token.name + '" to not repeat, but received `' + JSON.stringify(value) + '`')
|
665
|
+
}
|
514
666
|
|
515
|
-
|
516
|
-
|
667
|
+
if (value.length === 0) {
|
668
|
+
if (token.optional) {
|
669
|
+
continue
|
670
|
+
} else {
|
671
|
+
throw new TypeError('Expected "' + token.name + '" to not be empty')
|
517
672
|
}
|
673
|
+
}
|
518
674
|
|
519
|
-
|
675
|
+
for (var j = 0; j < value.length; j++) {
|
676
|
+
segment = encode(value[j])
|
520
677
|
|
521
|
-
|
522
|
-
|
523
|
-
|
678
|
+
if (!matches[i].test(segment)) {
|
679
|
+
throw new TypeError('Expected all "' + token.name + '" to match "' + token.pattern + '", but received `' + JSON.stringify(segment) + '`')
|
680
|
+
}
|
524
681
|
|
525
|
-
|
526
|
-
currentState = addSegment(currentState, segment);
|
527
|
-
regex += segment.regex();
|
682
|
+
path += (j === 0 ? token.prefix : token.delimiter) + segment
|
528
683
|
}
|
529
684
|
|
530
|
-
|
531
|
-
handlers.push(handler);
|
685
|
+
continue
|
532
686
|
}
|
533
687
|
|
534
|
-
|
535
|
-
|
536
|
-
|
688
|
+
segment = token.asterisk ? encodeAsterisk(value) : encode(value)
|
689
|
+
|
690
|
+
if (!matches[i].test(segment)) {
|
691
|
+
throw new TypeError('Expected "' + token.name + '" to match "' + token.pattern + '", but received "' + segment + '"')
|
537
692
|
}
|
538
693
|
|
539
|
-
|
540
|
-
|
541
|
-
currentState.specificity = specificity;
|
694
|
+
path += token.prefix + segment
|
695
|
+
}
|
542
696
|
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
handlers: handlers
|
547
|
-
};
|
548
|
-
}
|
549
|
-
},
|
697
|
+
return path
|
698
|
+
}
|
699
|
+
}
|
550
700
|
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
701
|
+
/**
|
702
|
+
* Escape a regular expression string.
|
703
|
+
*
|
704
|
+
* @param {string} str
|
705
|
+
* @return {string}
|
706
|
+
*/
|
707
|
+
function escapeString (str) {
|
708
|
+
return str.replace(/([.+*?=^!:${}()[\]|\/\\])/g, '\\$1')
|
709
|
+
}
|
710
|
+
|
711
|
+
/**
|
712
|
+
* Escape the capturing group by escaping special characters and meaning.
|
713
|
+
*
|
714
|
+
* @param {string} group
|
715
|
+
* @return {string}
|
716
|
+
*/
|
717
|
+
function escapeGroup (group) {
|
718
|
+
return group.replace(/([=!:$\/()])/g, '\\$1')
|
719
|
+
}
|
720
|
+
|
721
|
+
/**
|
722
|
+
* Attach the keys as a property of the regexp.
|
723
|
+
*
|
724
|
+
* @param {!RegExp} re
|
725
|
+
* @param {Array} keys
|
726
|
+
* @return {!RegExp}
|
727
|
+
*/
|
728
|
+
function attachKeys (re, keys) {
|
729
|
+
re.keys = keys
|
730
|
+
return re
|
731
|
+
}
|
732
|
+
|
733
|
+
/**
|
734
|
+
* Get the flags for a regexp from the options.
|
735
|
+
*
|
736
|
+
* @param {Object} options
|
737
|
+
* @return {string}
|
738
|
+
*/
|
739
|
+
function flags (options) {
|
740
|
+
return options.sensitive ? '' : 'i'
|
741
|
+
}
|
742
|
+
|
743
|
+
/**
|
744
|
+
* Pull out keys from a regexp.
|
745
|
+
*
|
746
|
+
* @param {!RegExp} path
|
747
|
+
* @param {!Array} keys
|
748
|
+
* @return {!RegExp}
|
749
|
+
*/
|
750
|
+
function regexpToRegexp (path, keys) {
|
751
|
+
// Use a negative lookahead to match only capturing groups.
|
752
|
+
var groups = path.source.match(/\((?!\?)/g)
|
753
|
+
|
754
|
+
if (groups) {
|
755
|
+
for (var i = 0; i < groups.length; i++) {
|
756
|
+
keys.push({
|
757
|
+
name: i,
|
758
|
+
prefix: null,
|
759
|
+
delimiter: null,
|
760
|
+
optional: false,
|
761
|
+
repeat: false,
|
762
|
+
partial: false,
|
763
|
+
asterisk: false,
|
764
|
+
pattern: null
|
765
|
+
})
|
766
|
+
}
|
767
|
+
}
|
557
768
|
|
558
|
-
|
559
|
-
|
560
|
-
}
|
769
|
+
return attachKeys(path, keys)
|
770
|
+
}
|
561
771
|
|
562
|
-
|
563
|
-
|
772
|
+
/**
|
773
|
+
* Transform an array into a regexp.
|
774
|
+
*
|
775
|
+
* @param {!Array} path
|
776
|
+
* @param {Array} keys
|
777
|
+
* @param {!Object} options
|
778
|
+
* @return {!RegExp}
|
779
|
+
*/
|
780
|
+
function arrayToRegexp (path, keys, options) {
|
781
|
+
var parts = []
|
564
782
|
|
565
|
-
|
566
|
-
|
567
|
-
|
783
|
+
for (var i = 0; i < path.length; i++) {
|
784
|
+
parts.push(pathToRegexp(path[i], keys, options).source)
|
785
|
+
}
|
568
786
|
|
569
|
-
|
570
|
-
var route = this.names[name],
|
571
|
-
output = "";
|
572
|
-
if (!route) {
|
573
|
-
throw new Error("There is no route named " + name);
|
574
|
-
}
|
787
|
+
var regexp = new RegExp('(?:' + parts.join('|') + ')', flags(options))
|
575
788
|
|
576
|
-
|
789
|
+
return attachKeys(regexp, keys)
|
790
|
+
}
|
577
791
|
|
578
|
-
|
579
|
-
|
792
|
+
/**
|
793
|
+
* Create a path regexp from string input.
|
794
|
+
*
|
795
|
+
* @param {string} path
|
796
|
+
* @param {!Array} keys
|
797
|
+
* @param {!Object} options
|
798
|
+
* @return {!RegExp}
|
799
|
+
*/
|
800
|
+
function stringToRegexp (path, keys, options) {
|
801
|
+
var tokens = parse(path)
|
802
|
+
var re = tokensToRegExp(tokens, options)
|
803
|
+
|
804
|
+
// Attach keys back to the regexp.
|
805
|
+
for (var i = 0; i < tokens.length; i++) {
|
806
|
+
if (typeof tokens[i] !== 'string') {
|
807
|
+
keys.push(tokens[i])
|
808
|
+
}
|
809
|
+
}
|
580
810
|
|
581
|
-
|
582
|
-
|
583
|
-
}
|
811
|
+
return attachKeys(re, keys)
|
812
|
+
}
|
584
813
|
|
585
|
-
|
586
|
-
|
587
|
-
|
814
|
+
/**
|
815
|
+
* Expose a function for taking tokens and returning a RegExp.
|
816
|
+
*
|
817
|
+
* @param {!Array} tokens
|
818
|
+
* @param {Object=} options
|
819
|
+
* @return {!RegExp}
|
820
|
+
*/
|
821
|
+
function tokensToRegExp (tokens, options) {
|
822
|
+
options = options || {}
|
588
823
|
|
589
|
-
|
590
|
-
|
591
|
-
|
824
|
+
var strict = options.strict
|
825
|
+
var end = options.end !== false
|
826
|
+
var route = ''
|
827
|
+
var lastToken = tokens[tokens.length - 1]
|
828
|
+
var endsWithSlash = typeof lastToken === 'string' && /\/$/.test(lastToken)
|
592
829
|
|
593
|
-
|
594
|
-
|
595
|
-
|
830
|
+
// Iterate over the tokens and create our regexp string.
|
831
|
+
for (var i = 0; i < tokens.length; i++) {
|
832
|
+
var token = tokens[i]
|
596
833
|
|
597
|
-
|
598
|
-
|
834
|
+
if (typeof token === 'string') {
|
835
|
+
route += escapeString(token)
|
836
|
+
} else {
|
837
|
+
var prefix = escapeString(token.prefix)
|
838
|
+
var capture = '(?:' + token.pattern + ')'
|
599
839
|
|
600
|
-
|
601
|
-
|
602
|
-
var keys = [];
|
603
|
-
for (var key in params) {
|
604
|
-
if (params.hasOwnProperty(key)) {
|
605
|
-
keys.push(key);
|
606
|
-
}
|
840
|
+
if (token.repeat) {
|
841
|
+
capture += '(?:' + prefix + capture + ')*'
|
607
842
|
}
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
if (value == null) {
|
613
|
-
continue;
|
614
|
-
}
|
615
|
-
var pair = encodeURIComponent(key);
|
616
|
-
if (isArray(value)) {
|
617
|
-
for (var j = 0, l = value.length; j < l; j++) {
|
618
|
-
var arrayPair = key + '[]' + '=' + encodeURIComponent(value[j]);
|
619
|
-
pairs.push(arrayPair);
|
620
|
-
}
|
843
|
+
|
844
|
+
if (token.optional) {
|
845
|
+
if (!token.partial) {
|
846
|
+
capture = '(?:' + prefix + '(' + capture + '))?'
|
621
847
|
} else {
|
622
|
-
|
623
|
-
pairs.push(pair);
|
848
|
+
capture = prefix + '(' + capture + ')?'
|
624
849
|
}
|
850
|
+
} else {
|
851
|
+
capture = prefix + '(' + capture + ')'
|
625
852
|
}
|
626
853
|
|
627
|
-
|
628
|
-
|
629
|
-
|
854
|
+
route += capture
|
855
|
+
}
|
856
|
+
}
|
630
857
|
|
631
|
-
|
632
|
-
|
858
|
+
// In non-strict mode we allow a slash at the end of match. If the path to
|
859
|
+
// match already ends with a slash, we remove it for consistency. The slash
|
860
|
+
// is valid at the end of a path match, not in the middle. This is important
|
861
|
+
// in non-ending mode, where "/test/" shouldn't match "/test//route".
|
862
|
+
if (!strict) {
|
863
|
+
route = (endsWithSlash ? route.slice(0, -2) : route) + '(?:\\/(?=$))?'
|
864
|
+
}
|
633
865
|
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
isArray = false,
|
642
|
-
value;
|
643
|
-
if (pair.length === 1) {
|
644
|
-
value = 'true';
|
645
|
-
} else {
|
646
|
-
//Handle arrays
|
647
|
-
if (keyLength > 2 && key.slice(keyLength - 2) === '[]') {
|
648
|
-
isArray = true;
|
649
|
-
key = key.slice(0, keyLength - 2);
|
650
|
-
if (!queryParams[key]) {
|
651
|
-
queryParams[key] = [];
|
652
|
-
}
|
653
|
-
}
|
654
|
-
value = pair[1] ? decodeQueryParamPart(pair[1]) : '';
|
655
|
-
}
|
656
|
-
if (isArray) {
|
657
|
-
queryParams[key].push(value);
|
658
|
-
} else {
|
659
|
-
queryParams[key] = value;
|
660
|
-
}
|
661
|
-
}
|
662
|
-
return queryParams;
|
663
|
-
},
|
866
|
+
if (end) {
|
867
|
+
route += '$'
|
868
|
+
} else {
|
869
|
+
// In non-ending mode, we need the capturing groups to match as much as
|
870
|
+
// possible by using a positive lookahead to the end or next path segment.
|
871
|
+
route += strict && endsWithSlash ? '' : '(?=\\/|$)'
|
872
|
+
}
|
664
873
|
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
874
|
+
return new RegExp('^' + route, flags(options))
|
875
|
+
}
|
876
|
+
|
877
|
+
/**
|
878
|
+
* Normalize the given path string, returning a regular expression.
|
879
|
+
*
|
880
|
+
* An empty array can be passed in for the keys, which will hold the
|
881
|
+
* placeholder key descriptions. For example, using `/user/:id`, `keys` will
|
882
|
+
* contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.
|
883
|
+
*
|
884
|
+
* @param {(string|RegExp|Array)} path
|
885
|
+
* @param {(Array|Object)=} keys
|
886
|
+
* @param {Object=} options
|
887
|
+
* @return {!RegExp}
|
888
|
+
*/
|
889
|
+
function pathToRegexp (path, keys, options) {
|
890
|
+
keys = keys || []
|
891
|
+
|
892
|
+
if (!isarray(keys)) {
|
893
|
+
options = /** @type {!Object} */ (keys)
|
894
|
+
keys = []
|
895
|
+
} else if (!options) {
|
896
|
+
options = {}
|
897
|
+
}
|
683
898
|
|
684
|
-
|
685
|
-
|
899
|
+
if (path instanceof RegExp) {
|
900
|
+
return regexpToRegexp(path, /** @type {!Array} */ (keys))
|
901
|
+
}
|
686
902
|
|
687
|
-
|
903
|
+
if (isarray(path)) {
|
904
|
+
return arrayToRegexp(/** @type {!Array} */ (path), /** @type {!Array} */ (keys), options)
|
905
|
+
}
|
688
906
|
|
689
|
-
|
690
|
-
|
691
|
-
}
|
907
|
+
return stringToRegexp(/** @type {string} */ (path), /** @type {!Array} */ (keys), options)
|
908
|
+
}
|
692
909
|
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
}
|
910
|
+
index.parse = parse_1;
|
911
|
+
index.compile = compile_1;
|
912
|
+
index.tokensToFunction = tokensToFunction_1;
|
913
|
+
index.tokensToRegExp = tokensToRegExp_1;
|
698
914
|
|
699
|
-
|
700
|
-
states = recognizeChar(states, path.charAt(i));
|
701
|
-
if (!states.length) {
|
702
|
-
break;
|
703
|
-
}
|
704
|
-
}
|
915
|
+
/* */
|
705
916
|
|
706
|
-
|
917
|
+
function createRouteMap (routes) {
|
918
|
+
var pathMap = Object.create(null)
|
919
|
+
var nameMap = Object.create(null)
|
707
920
|
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
solutions.push(states[i]);
|
712
|
-
}
|
713
|
-
}
|
921
|
+
routes.forEach(function (route) {
|
922
|
+
addRouteRecord(pathMap, nameMap, route)
|
923
|
+
})
|
714
924
|
|
715
|
-
|
925
|
+
return {
|
926
|
+
pathMap: pathMap,
|
927
|
+
nameMap: nameMap
|
928
|
+
}
|
929
|
+
}
|
930
|
+
|
931
|
+
function addRouteRecord (
|
932
|
+
pathMap,
|
933
|
+
nameMap,
|
934
|
+
route,
|
935
|
+
parent,
|
936
|
+
matchAs
|
937
|
+
) {
|
938
|
+
var path = route.path;
|
939
|
+
var name = route.name;
|
940
|
+
assert(path != null, "\"path\" is required in a route configuration.")
|
941
|
+
|
942
|
+
var record = {
|
943
|
+
path: normalizePath(path, parent),
|
944
|
+
components: route.components || { default: route.component },
|
945
|
+
instances: {},
|
946
|
+
name: name,
|
947
|
+
parent: parent,
|
948
|
+
matchAs: matchAs,
|
949
|
+
redirect: route.redirect,
|
950
|
+
beforeEnter: route.beforeEnter,
|
951
|
+
meta: route.meta || {}
|
952
|
+
}
|
716
953
|
|
717
|
-
|
954
|
+
if (route.children) {
|
955
|
+
// Warn if route is named and has a default child route.
|
956
|
+
// If users navigate to this route by name, the default child will
|
957
|
+
// not be rendered (GH Issue #629)
|
958
|
+
if ("production" !== 'production') {}
|
959
|
+
route.children.forEach(function (child) {
|
960
|
+
addRouteRecord(pathMap, nameMap, child, record)
|
961
|
+
})
|
962
|
+
}
|
718
963
|
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
}
|
964
|
+
if (route.alias) {
|
965
|
+
if (Array.isArray(route.alias)) {
|
966
|
+
route.alias.forEach(function (alias) {
|
967
|
+
addRouteRecord(pathMap, nameMap, { path: alias }, parent, record.path)
|
968
|
+
})
|
969
|
+
} else {
|
970
|
+
addRouteRecord(pathMap, nameMap, { path: route.alias }, parent, record.path)
|
727
971
|
}
|
728
|
-
}
|
972
|
+
}
|
729
973
|
|
730
|
-
|
974
|
+
pathMap[record.path] = record
|
975
|
+
if (name) { nameMap[name] = record }
|
976
|
+
}
|
731
977
|
|
732
|
-
|
978
|
+
function normalizePath (path, parent) {
|
979
|
+
path = path.replace(/\/$/, '')
|
980
|
+
if (path[0] === '/') { return path }
|
981
|
+
if (parent == null) { return path }
|
982
|
+
return cleanPath(((parent.path) + "/" + path))
|
983
|
+
}
|
733
984
|
|
734
|
-
|
735
|
-
var exports$1 = {};
|
736
|
-
/**
|
737
|
-
* Warn stuff.
|
738
|
-
*
|
739
|
-
* @param {String} msg
|
740
|
-
*/
|
985
|
+
/* */
|
741
986
|
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
987
|
+
var regexpCache = Object.create(null)
|
988
|
+
|
989
|
+
var regexpCompileCache = Object.create(null)
|
990
|
+
|
991
|
+
function createMatcher (routes) {
|
992
|
+
var ref = createRouteMap(routes);
|
993
|
+
var pathMap = ref.pathMap;
|
994
|
+
var nameMap = ref.nameMap;
|
995
|
+
|
996
|
+
function match (
|
997
|
+
raw,
|
998
|
+
currentRoute,
|
999
|
+
redirectedFrom
|
1000
|
+
) {
|
1001
|
+
var location = normalizeLocation(raw, currentRoute)
|
1002
|
+
var name = location.name;
|
1003
|
+
|
1004
|
+
if (name) {
|
1005
|
+
var record = nameMap[name]
|
1006
|
+
if (record) {
|
1007
|
+
location.path = fillParams(record.path, location.params, ("named route \"" + name + "\""))
|
1008
|
+
return _createRoute(record, location, redirectedFrom)
|
1009
|
+
}
|
1010
|
+
} else if (location.path) {
|
1011
|
+
location.params = {}
|
1012
|
+
for (var path in pathMap) {
|
1013
|
+
if (matchRoute(path, location.params, location.path)) {
|
1014
|
+
return _createRoute(pathMap[path], location, redirectedFrom)
|
1015
|
+
}
|
1016
|
+
}
|
746
1017
|
}
|
1018
|
+
// no match
|
1019
|
+
return _createRoute(null, location)
|
747
1020
|
}
|
748
1021
|
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
if (query) {
|
761
|
-
query = query[1];
|
762
|
-
base = base.slice(0, -query.length);
|
1022
|
+
function redirect (
|
1023
|
+
record,
|
1024
|
+
location
|
1025
|
+
) {
|
1026
|
+
var originalRedirect = record.redirect
|
1027
|
+
var redirect = typeof originalRedirect === 'function'
|
1028
|
+
? originalRedirect(createRoute(record, location))
|
1029
|
+
: originalRedirect
|
1030
|
+
|
1031
|
+
if (typeof redirect === 'string') {
|
1032
|
+
redirect = { path: redirect }
|
763
1033
|
}
|
764
|
-
|
765
|
-
if (
|
766
|
-
|
1034
|
+
|
1035
|
+
if (!redirect || typeof redirect !== 'object') {
|
1036
|
+
warn(false, ("invalid redirect option: " + (JSON.stringify(redirect))))
|
1037
|
+
return _createRoute(null, location)
|
767
1038
|
}
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
1039
|
+
|
1040
|
+
var re = redirect
|
1041
|
+
var name = re.name;
|
1042
|
+
var path = re.path;
|
1043
|
+
var query = location.query;
|
1044
|
+
var hash = location.hash;
|
1045
|
+
var params = location.params;
|
1046
|
+
query = re.hasOwnProperty('query') ? re.query : query
|
1047
|
+
hash = re.hasOwnProperty('hash') ? re.hash : hash
|
1048
|
+
params = re.hasOwnProperty('params') ? re.params : params
|
1049
|
+
|
1050
|
+
if (name) {
|
1051
|
+
// resolved named direct
|
1052
|
+
var targetRecord = nameMap[name]
|
1053
|
+
assert(targetRecord, ("redirect failed: named route \"" + name + "\" not found."))
|
1054
|
+
return match({
|
1055
|
+
_normalized: true,
|
1056
|
+
name: name,
|
1057
|
+
query: query,
|
1058
|
+
hash: hash,
|
1059
|
+
params: params
|
1060
|
+
}, undefined, location)
|
1061
|
+
} else if (path) {
|
1062
|
+
// 1. resolve relative redirect
|
1063
|
+
var rawPath = resolveRecordPath(path, record)
|
1064
|
+
// 2. resolve params
|
1065
|
+
var resolvedPath = fillParams(rawPath, params, ("redirect route with path \"" + rawPath + "\""))
|
1066
|
+
// 3. rematch with existing query and hash
|
1067
|
+
return match({
|
1068
|
+
_normalized: true,
|
1069
|
+
path: resolvedPath,
|
1070
|
+
query: query,
|
1071
|
+
hash: hash
|
1072
|
+
}, undefined, location)
|
1073
|
+
} else {
|
1074
|
+
warn(false, ("invalid redirect option: " + (JSON.stringify(redirect))))
|
1075
|
+
return _createRoute(null, location)
|
774
1076
|
}
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
1077
|
+
}
|
1078
|
+
|
1079
|
+
function alias (
|
1080
|
+
record,
|
1081
|
+
location,
|
1082
|
+
matchAs
|
1083
|
+
) {
|
1084
|
+
var aliasedPath = fillParams(matchAs, location.params, ("aliased route with path \"" + matchAs + "\""))
|
1085
|
+
var aliasedMatch = match({
|
1086
|
+
_normalized: true,
|
1087
|
+
path: aliasedPath
|
1088
|
+
})
|
1089
|
+
if (aliasedMatch) {
|
1090
|
+
var matched = aliasedMatch.matched
|
1091
|
+
var aliasedRecord = matched[matched.length - 1]
|
1092
|
+
location.params = aliasedMatch.params
|
1093
|
+
return _createRoute(aliasedRecord, location)
|
786
1094
|
}
|
787
|
-
|
788
|
-
|
789
|
-
|
1095
|
+
return _createRoute(null, location)
|
1096
|
+
}
|
1097
|
+
|
1098
|
+
function _createRoute (
|
1099
|
+
record,
|
1100
|
+
location,
|
1101
|
+
redirectedFrom
|
1102
|
+
) {
|
1103
|
+
if (record && record.redirect) {
|
1104
|
+
return redirect(record, redirectedFrom || location)
|
790
1105
|
}
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
/**
|
795
|
-
* Forgiving check for a promise
|
796
|
-
*
|
797
|
-
* @param {Object} p
|
798
|
-
* @return {Boolean}
|
799
|
-
*/
|
800
|
-
|
801
|
-
function isPromise(p) {
|
802
|
-
return p && typeof p.then === 'function';
|
803
|
-
}
|
804
|
-
|
805
|
-
/**
|
806
|
-
* Retrive a route config field from a component instance
|
807
|
-
* OR a component contructor.
|
808
|
-
*
|
809
|
-
* @param {Function|Vue} component
|
810
|
-
* @param {String} name
|
811
|
-
* @return {*}
|
812
|
-
*/
|
813
|
-
|
814
|
-
function getRouteConfig(component, name) {
|
815
|
-
var options = component && (component.$options || component.options);
|
816
|
-
return options && options.route && options.route[name];
|
817
|
-
}
|
818
|
-
|
819
|
-
/**
|
820
|
-
* Resolve an async component factory. Have to do a dirty
|
821
|
-
* mock here because of Vue core's internal API depends on
|
822
|
-
* an ID check.
|
823
|
-
*
|
824
|
-
* @param {Object} handler
|
825
|
-
* @param {Function} cb
|
826
|
-
*/
|
827
|
-
|
828
|
-
var resolver = undefined;
|
829
|
-
|
830
|
-
function resolveAsyncComponent(handler, cb) {
|
831
|
-
if (!resolver) {
|
832
|
-
resolver = {
|
833
|
-
resolve: exports$1.Vue.prototype._resolveComponent,
|
834
|
-
$options: {
|
835
|
-
components: {
|
836
|
-
_: handler.component
|
837
|
-
}
|
838
|
-
}
|
839
|
-
};
|
840
|
-
} else {
|
841
|
-
resolver.$options.components._ = handler.component;
|
1106
|
+
if (record && record.matchAs) {
|
1107
|
+
return alias(record, location, record.matchAs)
|
842
1108
|
}
|
843
|
-
|
844
|
-
handler.component = Component;
|
845
|
-
cb(Component);
|
846
|
-
});
|
847
|
-
}
|
848
|
-
|
849
|
-
/**
|
850
|
-
* Map the dynamic segments in a path to params.
|
851
|
-
*
|
852
|
-
* @param {String} path
|
853
|
-
* @param {Object} params
|
854
|
-
* @param {Object} query
|
855
|
-
*/
|
856
|
-
|
857
|
-
function mapParams(path, params, query) {
|
858
|
-
if (params === undefined) params = {};
|
859
|
-
|
860
|
-
path = path.replace(/:([^\/]+)/g, function (_, key) {
|
861
|
-
var val = params[key];
|
862
|
-
/* istanbul ignore if */
|
863
|
-
if (!val) {
|
864
|
-
warn$1('param "' + key + '" not found when generating ' + 'path for "' + path + '" with params ' + JSON.stringify(params));
|
865
|
-
}
|
866
|
-
return val || '';
|
867
|
-
});
|
868
|
-
if (query) {
|
869
|
-
path += genQuery(query);
|
870
|
-
}
|
871
|
-
return path;
|
1109
|
+
return createRoute(record, location, redirectedFrom)
|
872
1110
|
}
|
873
1111
|
|
874
|
-
|
1112
|
+
return match
|
1113
|
+
}
|
1114
|
+
|
1115
|
+
function matchRoute (
|
1116
|
+
path,
|
1117
|
+
params,
|
1118
|
+
pathname
|
1119
|
+
) {
|
1120
|
+
var keys, regexp
|
1121
|
+
var hit = regexpCache[path]
|
1122
|
+
if (hit) {
|
1123
|
+
keys = hit.keys
|
1124
|
+
regexp = hit.regexp
|
1125
|
+
} else {
|
1126
|
+
keys = []
|
1127
|
+
regexp = index(path, keys)
|
1128
|
+
regexpCache[path] = { keys: keys, regexp: regexp }
|
1129
|
+
}
|
1130
|
+
var m = pathname.match(regexp)
|
875
1131
|
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
1132
|
+
if (!m) {
|
1133
|
+
return false
|
1134
|
+
} else if (!params) {
|
1135
|
+
return true
|
1136
|
+
}
|
881
1137
|
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
// remove trailing slash
|
888
|
-
this.root = root.replace(/\/$/, '');
|
889
|
-
this.rootRE = new RegExp('^\\' + this.root);
|
890
|
-
} else {
|
891
|
-
this.root = null;
|
892
|
-
}
|
893
|
-
this.onChange = onChange;
|
894
|
-
// check base tag
|
895
|
-
var baseEl = document.querySelector('base');
|
896
|
-
this.base = baseEl && baseEl.getAttribute('href');
|
897
|
-
}
|
1138
|
+
for (var i = 1, len = m.length; i < len; ++i) {
|
1139
|
+
var key = keys[i - 1]
|
1140
|
+
var val = typeof m[i] === 'string' ? decodeURIComponent(m[i]) : m[i]
|
1141
|
+
if (key) { params[key.name] = val }
|
1142
|
+
}
|
898
1143
|
|
899
|
-
|
900
|
-
|
1144
|
+
return true
|
1145
|
+
}
|
1146
|
+
|
1147
|
+
function fillParams (
|
1148
|
+
path,
|
1149
|
+
params,
|
1150
|
+
routeMsg
|
1151
|
+
) {
|
1152
|
+
try {
|
1153
|
+
var filler =
|
1154
|
+
regexpCompileCache[path] ||
|
1155
|
+
(regexpCompileCache[path] = index.compile(path))
|
1156
|
+
return filler(params || {}, { pretty: true })
|
1157
|
+
} catch (e) {
|
1158
|
+
assert(false, ("missing param for " + routeMsg + ": " + (e.message)))
|
1159
|
+
return ''
|
1160
|
+
}
|
1161
|
+
}
|
901
1162
|
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
url = url.replace(_this.rootRE, '');
|
906
|
-
}
|
907
|
-
_this.onChange(url, e && e.state, location.hash);
|
908
|
-
};
|
909
|
-
window.addEventListener('popstate', this.listener);
|
910
|
-
this.listener();
|
911
|
-
};
|
912
|
-
|
913
|
-
HTML5History.prototype.stop = function stop() {
|
914
|
-
window.removeEventListener('popstate', this.listener);
|
915
|
-
};
|
916
|
-
|
917
|
-
HTML5History.prototype.go = function go(path, replace, append) {
|
918
|
-
var url = this.formatPath(path, append);
|
919
|
-
if (replace) {
|
920
|
-
history.replaceState({}, '', url);
|
921
|
-
} else {
|
922
|
-
// record scroll position by replacing current state
|
923
|
-
history.replaceState({
|
924
|
-
pos: {
|
925
|
-
x: window.pageXOffset,
|
926
|
-
y: window.pageYOffset
|
927
|
-
}
|
928
|
-
}, '', location.href);
|
929
|
-
// then push new state
|
930
|
-
history.pushState({}, '', url);
|
931
|
-
}
|
932
|
-
var hashMatch = path.match(hashRE);
|
933
|
-
var hash = hashMatch && hashMatch[0];
|
934
|
-
path = url
|
935
|
-
// strip hash so it doesn't mess up params
|
936
|
-
.replace(hashRE, '')
|
937
|
-
// remove root before matching
|
938
|
-
.replace(this.rootRE, '');
|
939
|
-
this.onChange(path, null, hash);
|
940
|
-
};
|
941
|
-
|
942
|
-
HTML5History.prototype.formatPath = function formatPath(path, append) {
|
943
|
-
return path.charAt(0) === '/'
|
944
|
-
// absolute path
|
945
|
-
? this.root ? this.root + '/' + path.replace(/^\//, '') : path : resolvePath(this.base || location.pathname, path, append);
|
946
|
-
};
|
947
|
-
|
948
|
-
return HTML5History;
|
949
|
-
})();
|
950
|
-
|
951
|
-
var HashHistory = (function () {
|
952
|
-
function HashHistory(_ref) {
|
953
|
-
var hashbang = _ref.hashbang;
|
954
|
-
var onChange = _ref.onChange;
|
955
|
-
babelHelpers.classCallCheck(this, HashHistory);
|
956
|
-
|
957
|
-
this.hashbang = hashbang;
|
958
|
-
this.onChange = onChange;
|
959
|
-
}
|
1163
|
+
function resolveRecordPath (path, record) {
|
1164
|
+
return resolvePath(path, record.parent ? record.parent.path : '/', true)
|
1165
|
+
}
|
960
1166
|
|
961
|
-
|
962
|
-
var self = this;
|
963
|
-
this.listener = function () {
|
964
|
-
var path = location.hash;
|
965
|
-
var raw = path.replace(/^#!?/, '');
|
966
|
-
// always
|
967
|
-
if (raw.charAt(0) !== '/') {
|
968
|
-
raw = '/' + raw;
|
969
|
-
}
|
970
|
-
var formattedPath = self.formatPath(raw);
|
971
|
-
if (formattedPath !== path) {
|
972
|
-
location.replace(formattedPath);
|
973
|
-
return;
|
974
|
-
}
|
975
|
-
// determine query
|
976
|
-
// note it's possible to have queries in both the actual URL
|
977
|
-
// and the hash fragment itself.
|
978
|
-
var query = location.search && path.indexOf('?') > -1 ? '&' + location.search.slice(1) : location.search;
|
979
|
-
self.onChange(path.replace(/^#!?/, '') + query);
|
980
|
-
};
|
981
|
-
window.addEventListener('hashchange', this.listener);
|
982
|
-
this.listener();
|
983
|
-
};
|
984
|
-
|
985
|
-
HashHistory.prototype.stop = function stop() {
|
986
|
-
window.removeEventListener('hashchange', this.listener);
|
987
|
-
};
|
988
|
-
|
989
|
-
HashHistory.prototype.go = function go(path, replace, append) {
|
990
|
-
path = this.formatPath(path, append);
|
991
|
-
if (replace) {
|
992
|
-
location.replace(path);
|
993
|
-
} else {
|
994
|
-
location.hash = path;
|
995
|
-
}
|
996
|
-
};
|
1167
|
+
/* */
|
997
1168
|
|
998
|
-
|
999
|
-
var isAbsoloute = path.charAt(0) === '/';
|
1000
|
-
var prefix = '#' + (this.hashbang ? '!' : '');
|
1001
|
-
return isAbsoloute ? prefix + path : prefix + resolvePath(location.hash.replace(/^#!?/, ''), path, append);
|
1002
|
-
};
|
1169
|
+
var inBrowser = typeof window !== 'undefined'
|
1003
1170
|
|
1004
|
-
|
1005
|
-
|
1171
|
+
var supportsHistory = inBrowser && (function () {
|
1172
|
+
var ua = window.navigator.userAgent
|
1006
1173
|
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1174
|
+
if (
|
1175
|
+
(ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) &&
|
1176
|
+
ua.indexOf('Mobile Safari') !== -1 &&
|
1177
|
+
ua.indexOf('Chrome') === -1 &&
|
1178
|
+
ua.indexOf('Windows Phone') === -1
|
1179
|
+
) {
|
1180
|
+
return false
|
1181
|
+
}
|
1011
1182
|
|
1012
|
-
|
1013
|
-
|
1014
|
-
}
|
1183
|
+
return window.history && 'pushState' in window.history
|
1184
|
+
})()
|
1015
1185
|
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
};
|
1023
|
-
|
1024
|
-
AbstractHistory.prototype.go = function go(path, replace, append) {
|
1025
|
-
path = this.currentPath = this.formatPath(path, append);
|
1026
|
-
this.onChange(path);
|
1027
|
-
};
|
1028
|
-
|
1029
|
-
AbstractHistory.prototype.formatPath = function formatPath(path, append) {
|
1030
|
-
return path.charAt(0) === '/' ? path : resolvePath(this.currentPath, path, append);
|
1031
|
-
};
|
1032
|
-
|
1033
|
-
return AbstractHistory;
|
1034
|
-
})();
|
1035
|
-
|
1036
|
-
/**
|
1037
|
-
* Determine the reusability of an existing router view.
|
1038
|
-
*
|
1039
|
-
* @param {Directive} view
|
1040
|
-
* @param {Object} handler
|
1041
|
-
* @param {Transition} transition
|
1042
|
-
*/
|
1043
|
-
|
1044
|
-
function canReuse(view, handler, transition) {
|
1045
|
-
var component = view.childVM;
|
1046
|
-
if (!component || !handler) {
|
1047
|
-
return false;
|
1048
|
-
}
|
1049
|
-
// important: check view.Component here because it may
|
1050
|
-
// have been changed in activate hook
|
1051
|
-
if (view.Component !== handler.component) {
|
1052
|
-
return false;
|
1053
|
-
}
|
1054
|
-
var canReuseFn = getRouteConfig(component, 'canReuse');
|
1055
|
-
return typeof canReuseFn === 'boolean' ? canReuseFn : canReuseFn ? canReuseFn.call(component, {
|
1056
|
-
to: transition.to,
|
1057
|
-
from: transition.from
|
1058
|
-
}) : true; // defaults to true
|
1059
|
-
}
|
1060
|
-
|
1061
|
-
/**
|
1062
|
-
* Check if a component can deactivate.
|
1063
|
-
*
|
1064
|
-
* @param {Directive} view
|
1065
|
-
* @param {Transition} transition
|
1066
|
-
* @param {Function} next
|
1067
|
-
*/
|
1068
|
-
|
1069
|
-
function canDeactivate(view, transition, next) {
|
1070
|
-
var fromComponent = view.childVM;
|
1071
|
-
var hook = getRouteConfig(fromComponent, 'canDeactivate');
|
1072
|
-
if (!hook) {
|
1073
|
-
next();
|
1186
|
+
/* */
|
1187
|
+
|
1188
|
+
function runQueue (queue, fn, cb) {
|
1189
|
+
var step = function (index) {
|
1190
|
+
if (index >= queue.length) {
|
1191
|
+
cb()
|
1074
1192
|
} else {
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1193
|
+
if (queue[index]) {
|
1194
|
+
fn(queue[index], function () {
|
1195
|
+
step(index + 1)
|
1196
|
+
})
|
1197
|
+
} else {
|
1198
|
+
step(index + 1)
|
1199
|
+
}
|
1078
1200
|
}
|
1079
1201
|
}
|
1202
|
+
step(0)
|
1203
|
+
}
|
1204
|
+
|
1205
|
+
/* */
|
1206
|
+
|
1207
|
+
|
1208
|
+
var History = function History (router, base) {
|
1209
|
+
this.router = router
|
1210
|
+
this.base = normalizeBase(base)
|
1211
|
+
// start with a route object that stands for "nowhere"
|
1212
|
+
this.current = START
|
1213
|
+
this.pending = null
|
1214
|
+
};
|
1215
|
+
|
1216
|
+
History.prototype.listen = function listen (cb) {
|
1217
|
+
this.cb = cb
|
1218
|
+
};
|
1219
|
+
|
1220
|
+
History.prototype.transitionTo = function transitionTo (location, cb) {
|
1221
|
+
var this$1 = this;
|
1222
|
+
|
1223
|
+
var route = this.router.match(location, this.current)
|
1224
|
+
this.confirmTransition(route, function () {
|
1225
|
+
this$1.updateRoute(route)
|
1226
|
+
cb && cb(route)
|
1227
|
+
this$1.ensureURL()
|
1228
|
+
})
|
1229
|
+
};
|
1230
|
+
|
1231
|
+
History.prototype.confirmTransition = function confirmTransition (route, cb) {
|
1232
|
+
var this$1 = this;
|
1233
|
+
|
1234
|
+
var current = this.current
|
1235
|
+
if (isSameRoute(route, current)) {
|
1236
|
+
this.ensureURL()
|
1237
|
+
return
|
1238
|
+
}
|
1080
1239
|
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1240
|
+
var ref = resolveQueue(this.current.matched, route.matched);
|
1241
|
+
var deactivated = ref.deactivated;
|
1242
|
+
var activated = ref.activated;
|
1243
|
+
|
1244
|
+
var queue = [].concat(
|
1245
|
+
// in-component leave guards
|
1246
|
+
extractLeaveGuards(deactivated),
|
1247
|
+
// global before hooks
|
1248
|
+
this.router.beforeHooks,
|
1249
|
+
// enter guards
|
1250
|
+
activated.map(function (m) { return m.beforeEnter; }),
|
1251
|
+
// async components
|
1252
|
+
resolveAsyncComponents(activated)
|
1253
|
+
)
|
1254
|
+
|
1255
|
+
this.pending = route
|
1256
|
+
var iterator = function (hook, next) {
|
1257
|
+
if (this$1.pending !== route) { return }
|
1258
|
+
hook(route, current, function (to) {
|
1259
|
+
if (to === false) {
|
1260
|
+
// next(false) -> abort navigation, ensure current URL
|
1261
|
+
this$1.ensureURL()
|
1262
|
+
} else if (typeof to === 'string' || typeof to === 'object') {
|
1263
|
+
// next('/') or next({ path: '/' }) -> redirect
|
1264
|
+
this$1.push(to)
|
1099
1265
|
} else {
|
1100
|
-
transition
|
1101
|
-
|
1102
|
-
});
|
1266
|
+
// confirm transition and pass on the value
|
1267
|
+
next(to)
|
1103
1268
|
}
|
1104
|
-
})
|
1105
|
-
}
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1269
|
+
})
|
1270
|
+
}
|
1271
|
+
|
1272
|
+
runQueue(queue, iterator, function () {
|
1273
|
+
var postEnterCbs = []
|
1274
|
+
// wait until async components are resolved before
|
1275
|
+
// extracting in-component enter guards
|
1276
|
+
runQueue(extractEnterGuards(activated, postEnterCbs), iterator, function () {
|
1277
|
+
if (this$1.pending === route) {
|
1278
|
+
this$1.pending = null
|
1279
|
+
cb(route)
|
1280
|
+
this$1.router.app.$nextTick(function () {
|
1281
|
+
postEnterCbs.forEach(function (cb) { return cb(); })
|
1282
|
+
})
|
1283
|
+
}
|
1284
|
+
})
|
1285
|
+
})
|
1286
|
+
};
|
1287
|
+
|
1288
|
+
History.prototype.updateRoute = function updateRoute (route) {
|
1289
|
+
var prev = this.current
|
1290
|
+
this.current = route
|
1291
|
+
this.cb && this.cb(route)
|
1292
|
+
this.router.afterHooks.forEach(function (hook) {
|
1293
|
+
hook && hook(route, prev)
|
1294
|
+
})
|
1295
|
+
};
|
1296
|
+
|
1297
|
+
function normalizeBase (base) {
|
1298
|
+
if (!base) {
|
1299
|
+
if (inBrowser) {
|
1300
|
+
// respect <base> tag
|
1301
|
+
var baseEl = document.querySelector('base')
|
1302
|
+
base = baseEl ? baseEl.getAttribute('href') : '/'
|
1120
1303
|
} else {
|
1121
|
-
|
1304
|
+
base = '/'
|
1122
1305
|
}
|
1123
1306
|
}
|
1307
|
+
// make sure there's the starting slash
|
1308
|
+
if (base.charAt(0) !== '/') {
|
1309
|
+
base = '/' + base
|
1310
|
+
}
|
1311
|
+
// remove trailing slash
|
1312
|
+
return base.replace(/\/$/, '')
|
1313
|
+
}
|
1314
|
+
|
1315
|
+
function resolveQueue (
|
1316
|
+
current,
|
1317
|
+
next
|
1318
|
+
) {
|
1319
|
+
var i
|
1320
|
+
var max = Math.max(current.length, next.length)
|
1321
|
+
for (i = 0; i < max; i++) {
|
1322
|
+
if (current[i] !== next[i]) {
|
1323
|
+
break
|
1324
|
+
}
|
1325
|
+
}
|
1326
|
+
return {
|
1327
|
+
activated: next.slice(i),
|
1328
|
+
deactivated: current.slice(i)
|
1329
|
+
}
|
1330
|
+
}
|
1124
1331
|
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
* @param {Function} [cb]
|
1132
|
-
*/
|
1133
|
-
|
1134
|
-
function activate(view, transition, depth, cb, reuse) {
|
1135
|
-
var handler = transition.activateQueue[depth];
|
1136
|
-
if (!handler) {
|
1137
|
-
saveChildView(view);
|
1138
|
-
if (view._bound) {
|
1139
|
-
view.setComponent(null);
|
1332
|
+
function extractLeaveGuards (matched) {
|
1333
|
+
return flatMapComponents(matched, function (def, instance) {
|
1334
|
+
var guard = def && def.beforeRouteLeave
|
1335
|
+
if (guard) {
|
1336
|
+
return function routeLeaveGuard () {
|
1337
|
+
return guard.apply(instance, arguments)
|
1140
1338
|
}
|
1141
|
-
cb && cb();
|
1142
|
-
return;
|
1143
1339
|
}
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
reuse = reuse && view.childVM && view.childVM.constructor === Component;
|
1161
|
-
|
1162
|
-
if (reuse) {
|
1163
|
-
// just reuse
|
1164
|
-
component = view.childVM;
|
1165
|
-
component.$loadingRouteData = loading;
|
1166
|
-
} else {
|
1167
|
-
saveChildView(view);
|
1168
|
-
|
1169
|
-
// unbuild current component. this step also destroys
|
1170
|
-
// and removes all nested child views.
|
1171
|
-
view.unbuild(true);
|
1172
|
-
|
1173
|
-
// build the new component. this will also create the
|
1174
|
-
// direct child view of the current one. it will register
|
1175
|
-
// itself as view.childView.
|
1176
|
-
component = view.build({
|
1177
|
-
_meta: {
|
1178
|
-
$loadingRouteData: loading
|
1179
|
-
},
|
1180
|
-
created: function created() {
|
1181
|
-
this._routerView = view;
|
1182
|
-
}
|
1183
|
-
});
|
1184
|
-
|
1185
|
-
// handle keep-alive.
|
1186
|
-
// when a kept-alive child vm is restored, we need to
|
1187
|
-
// add its cached child views into the router's view list,
|
1188
|
-
// and also properly update current view's child view.
|
1189
|
-
if (view.keepAlive) {
|
1190
|
-
component.$loadingRouteData = loading;
|
1191
|
-
var cachedChildView = component._keepAliveRouterView;
|
1192
|
-
if (cachedChildView) {
|
1193
|
-
view.childView = cachedChildView;
|
1194
|
-
component._keepAliveRouterView = null;
|
1195
|
-
}
|
1340
|
+
}).reverse()
|
1341
|
+
}
|
1342
|
+
|
1343
|
+
function extractEnterGuards (matched, cbs) {
|
1344
|
+
return flatMapComponents(matched, function (def, _, match, key) {
|
1345
|
+
var guard = def && def.beforeRouteEnter
|
1346
|
+
if (guard) {
|
1347
|
+
return function routeEnterGuard (to, from, next) {
|
1348
|
+
return guard(to, from, function (cb) {
|
1349
|
+
next(cb)
|
1350
|
+
if (typeof cb === 'function') {
|
1351
|
+
cbs.push(function () {
|
1352
|
+
cb(match.instances[key])
|
1353
|
+
})
|
1354
|
+
}
|
1355
|
+
})
|
1196
1356
|
}
|
1197
1357
|
}
|
1358
|
+
})
|
1359
|
+
}
|
1198
1360
|
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
//
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
var router = transition.router;
|
1212
|
-
if (router._rendered || router._transitionOnLoad) {
|
1213
|
-
view.transition(component);
|
1214
|
-
} else {
|
1215
|
-
// no transition on first render, manual transition
|
1216
|
-
/* istanbul ignore if */
|
1217
|
-
if (view.setCurrent) {
|
1218
|
-
// 0.12 compat
|
1219
|
-
view.setCurrent(component);
|
1220
|
-
} else {
|
1221
|
-
// 1.0
|
1222
|
-
view.childVM = component;
|
1361
|
+
function resolveAsyncComponents (matched) {
|
1362
|
+
return flatMapComponents(matched, function (def, _, match, key) {
|
1363
|
+
// if it's a function and doesn't have Vue options attached,
|
1364
|
+
// assume it's an async component resolve function.
|
1365
|
+
// we are not using Vue's default async resolving mechanism because
|
1366
|
+
// we want to halt the navigation until the incoming component has been
|
1367
|
+
// resolved.
|
1368
|
+
if (typeof def === 'function' && !def.options) {
|
1369
|
+
return function (to, from, next) {
|
1370
|
+
var resolve = function (resolvedDef) {
|
1371
|
+
match.components[key] = resolvedDef
|
1372
|
+
next()
|
1223
1373
|
}
|
1224
|
-
component.$before(view.anchor, null, false);
|
1225
|
-
}
|
1226
|
-
cb && cb();
|
1227
|
-
};
|
1228
1374
|
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
activate(view.childView, transition, depth + 1, null, reuse || view.keepAlive);
|
1233
|
-
}
|
1234
|
-
insert();
|
1235
|
-
};
|
1236
|
-
|
1237
|
-
// called after activation hook is resolved
|
1238
|
-
var afterActivate = function afterActivate() {
|
1239
|
-
view.activated = true;
|
1240
|
-
if (dataHook && waitForData) {
|
1241
|
-
// wait until data loaded to insert
|
1242
|
-
loadData(component, transition, dataHook, afterData, cleanup);
|
1243
|
-
} else {
|
1244
|
-
// load data and insert at the same time
|
1245
|
-
if (dataHook) {
|
1246
|
-
loadData(component, transition, dataHook);
|
1375
|
+
var reject = function (reason) {
|
1376
|
+
warn(false, ("Failed to resolve async component " + key + ": " + reason))
|
1377
|
+
next(false)
|
1247
1378
|
}
|
1248
|
-
afterData();
|
1249
|
-
}
|
1250
|
-
};
|
1251
1379
|
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
}
|
1257
|
-
} else {
|
1258
|
-
afterActivate();
|
1380
|
+
var res = def(resolve, reject)
|
1381
|
+
if (res && typeof res.then === 'function') {
|
1382
|
+
res.then(resolve, reject)
|
1383
|
+
}
|
1384
|
+
}
|
1259
1385
|
}
|
1386
|
+
})
|
1387
|
+
}
|
1388
|
+
|
1389
|
+
function flatMapComponents (
|
1390
|
+
matched,
|
1391
|
+
fn
|
1392
|
+
) {
|
1393
|
+
return Array.prototype.concat.apply([], matched.map(function (m) {
|
1394
|
+
return Object.keys(m.components).map(function (key) { return fn(
|
1395
|
+
m.components[key],
|
1396
|
+
m.instances[key],
|
1397
|
+
m, key
|
1398
|
+
); })
|
1399
|
+
}))
|
1400
|
+
}
|
1401
|
+
|
1402
|
+
/* */
|
1403
|
+
|
1404
|
+
function saveScrollPosition (key) {
|
1405
|
+
if (!key) { return }
|
1406
|
+
window.sessionStorage.setItem(key, JSON.stringify({
|
1407
|
+
x: window.pageXOffset,
|
1408
|
+
y: window.pageYOffset
|
1409
|
+
}))
|
1410
|
+
}
|
1411
|
+
|
1412
|
+
function getScrollPosition (key) {
|
1413
|
+
if (!key) { return }
|
1414
|
+
return JSON.parse(window.sessionStorage.getItem(key))
|
1415
|
+
}
|
1416
|
+
|
1417
|
+
function getElementPosition (el) {
|
1418
|
+
var docRect = document.documentElement.getBoundingClientRect()
|
1419
|
+
var elRect = el.getBoundingClientRect()
|
1420
|
+
return {
|
1421
|
+
x: elRect.left - docRect.left,
|
1422
|
+
y: elRect.top - docRect.top
|
1260
1423
|
}
|
1424
|
+
}
|
1261
1425
|
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
* @param {Directive} view
|
1266
|
-
* @param {Transition} transition
|
1267
|
-
*/
|
1426
|
+
function isValidPosition (obj) {
|
1427
|
+
return isNumber(obj.x) || isNumber(obj.y)
|
1428
|
+
}
|
1268
1429
|
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
loadData(component, transition, dataHook);
|
1274
|
-
}
|
1430
|
+
function normalizePosition (obj) {
|
1431
|
+
return {
|
1432
|
+
x: isNumber(obj.x) ? obj.x : window.pageXOffset,
|
1433
|
+
y: isNumber(obj.y) ? obj.y : window.pageYOffset
|
1275
1434
|
}
|
1435
|
+
}
|
1276
1436
|
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
* @param {Vue} component
|
1281
|
-
* @param {Transition} transition
|
1282
|
-
* @param {Function} hook
|
1283
|
-
* @param {Function} cb
|
1284
|
-
* @param {Function} cleanup
|
1285
|
-
*/
|
1286
|
-
|
1287
|
-
function loadData(component, transition, hook, cb, cleanup) {
|
1288
|
-
component.$loadingRouteData = true;
|
1289
|
-
transition.callHooks(hook, component, function () {
|
1290
|
-
component.$loadingRouteData = false;
|
1291
|
-
component.$emit('route-data-loaded', component);
|
1292
|
-
cb && cb();
|
1293
|
-
}, {
|
1294
|
-
cleanup: cleanup,
|
1295
|
-
postActivate: true,
|
1296
|
-
processData: function processData(data) {
|
1297
|
-
// handle promise sugar syntax
|
1298
|
-
var promises = [];
|
1299
|
-
if (isPlainObject(data)) {
|
1300
|
-
Object.keys(data).forEach(function (key) {
|
1301
|
-
var val = data[key];
|
1302
|
-
if (isPromise(val)) {
|
1303
|
-
promises.push(val.then(function (resolvedVal) {
|
1304
|
-
component.$set(key, resolvedVal);
|
1305
|
-
}));
|
1306
|
-
} else {
|
1307
|
-
component.$set(key, val);
|
1308
|
-
}
|
1309
|
-
});
|
1310
|
-
}
|
1311
|
-
if (promises.length) {
|
1312
|
-
return promises[0].constructor.all(promises);
|
1313
|
-
}
|
1314
|
-
}
|
1315
|
-
});
|
1316
|
-
}
|
1437
|
+
function isNumber (v) {
|
1438
|
+
return typeof v === 'number'
|
1439
|
+
}
|
1317
1440
|
|
1318
|
-
|
1319
|
-
* Save the child view for a kept-alive view so that
|
1320
|
-
* we can restore it when it is switched back to.
|
1321
|
-
*
|
1322
|
-
* @param {Directive} view
|
1323
|
-
*/
|
1441
|
+
/* */
|
1324
1442
|
|
1325
|
-
function saveChildView(view) {
|
1326
|
-
if (view.keepAlive && view.childVM && view.childView) {
|
1327
|
-
view.childVM._keepAliveRouterView = view.childView;
|
1328
|
-
}
|
1329
|
-
view.childView = null;
|
1330
|
-
}
|
1331
|
-
|
1332
|
-
/**
|
1333
|
-
* Check plain object.
|
1334
|
-
*
|
1335
|
-
* @param {*} val
|
1336
|
-
*/
|
1337
|
-
|
1338
|
-
function isPlainObject(val) {
|
1339
|
-
return Object.prototype.toString.call(val) === '[object Object]';
|
1340
|
-
}
|
1341
|
-
|
1342
|
-
/**
|
1343
|
-
* A RouteTransition object manages the pipeline of a
|
1344
|
-
* router-view switching process. This is also the object
|
1345
|
-
* passed into user route hooks.
|
1346
|
-
*
|
1347
|
-
* @param {Router} router
|
1348
|
-
* @param {Route} to
|
1349
|
-
* @param {Route} from
|
1350
|
-
*/
|
1351
|
-
|
1352
|
-
var RouteTransition = (function () {
|
1353
|
-
function RouteTransition(router, to, from) {
|
1354
|
-
babelHelpers.classCallCheck(this, RouteTransition);
|
1355
|
-
|
1356
|
-
this.router = router;
|
1357
|
-
this.to = to;
|
1358
|
-
this.from = from;
|
1359
|
-
this.next = null;
|
1360
|
-
this.aborted = false;
|
1361
|
-
this.done = false;
|
1362
|
-
}
|
1363
1443
|
|
1364
|
-
|
1365
|
-
|
1366
|
-
*/
|
1367
|
-
|
1368
|
-
RouteTransition.prototype.abort = function abort() {
|
1369
|
-
if (!this.aborted) {
|
1370
|
-
this.aborted = true;
|
1371
|
-
// if the root path throws an error during validation
|
1372
|
-
// on initial load, it gets caught in an infinite loop.
|
1373
|
-
var abortingOnLoad = !this.from.path && this.to.path === '/';
|
1374
|
-
if (!abortingOnLoad) {
|
1375
|
-
this.router.replace(this.from.path || '/');
|
1376
|
-
}
|
1377
|
-
}
|
1378
|
-
};
|
1379
|
-
|
1380
|
-
/**
|
1381
|
-
* Abort current transition and redirect to a new location.
|
1382
|
-
*
|
1383
|
-
* @param {String} path
|
1384
|
-
*/
|
1385
|
-
|
1386
|
-
RouteTransition.prototype.redirect = function redirect(path) {
|
1387
|
-
if (!this.aborted) {
|
1388
|
-
this.aborted = true;
|
1389
|
-
if (typeof path === 'string') {
|
1390
|
-
path = mapParams(path, this.to.params, this.to.query);
|
1391
|
-
} else {
|
1392
|
-
path.params = path.params || this.to.params;
|
1393
|
-
path.query = path.query || this.to.query;
|
1394
|
-
}
|
1395
|
-
this.router.replace(path);
|
1396
|
-
}
|
1397
|
-
};
|
1398
|
-
|
1399
|
-
/**
|
1400
|
-
* A router view transition's pipeline can be described as
|
1401
|
-
* follows, assuming we are transitioning from an existing
|
1402
|
-
* <router-view> chain [Component A, Component B] to a new
|
1403
|
-
* chain [Component A, Component C]:
|
1404
|
-
*
|
1405
|
-
* A A
|
1406
|
-
* | => |
|
1407
|
-
* B C
|
1408
|
-
*
|
1409
|
-
* 1. Reusablity phase:
|
1410
|
-
* -> canReuse(A, A)
|
1411
|
-
* -> canReuse(B, C)
|
1412
|
-
* -> determine new queues:
|
1413
|
-
* - deactivation: [B]
|
1414
|
-
* - activation: [C]
|
1415
|
-
*
|
1416
|
-
* 2. Validation phase:
|
1417
|
-
* -> canDeactivate(B)
|
1418
|
-
* -> canActivate(C)
|
1419
|
-
*
|
1420
|
-
* 3. Activation phase:
|
1421
|
-
* -> deactivate(B)
|
1422
|
-
* -> activate(C)
|
1423
|
-
*
|
1424
|
-
* Each of these steps can be asynchronous, and any
|
1425
|
-
* step can potentially abort the transition.
|
1426
|
-
*
|
1427
|
-
* @param {Function} cb
|
1428
|
-
*/
|
1429
|
-
|
1430
|
-
RouteTransition.prototype.start = function start(cb) {
|
1431
|
-
var transition = this;
|
1432
|
-
|
1433
|
-
// determine the queue of views to deactivate
|
1434
|
-
var deactivateQueue = [];
|
1435
|
-
var view = this.router._rootView;
|
1436
|
-
while (view) {
|
1437
|
-
deactivateQueue.unshift(view);
|
1438
|
-
view = view.childView;
|
1439
|
-
}
|
1440
|
-
var reverseDeactivateQueue = deactivateQueue.slice().reverse();
|
1441
|
-
|
1442
|
-
// determine the queue of route handlers to activate
|
1443
|
-
var activateQueue = this.activateQueue = toArray(this.to.matched).map(function (match) {
|
1444
|
-
return match.handler;
|
1445
|
-
});
|
1446
|
-
|
1447
|
-
// 1. Reusability phase
|
1448
|
-
var i = undefined,
|
1449
|
-
reuseQueue = undefined;
|
1450
|
-
for (i = 0; i < reverseDeactivateQueue.length; i++) {
|
1451
|
-
if (!canReuse(reverseDeactivateQueue[i], activateQueue[i], transition)) {
|
1452
|
-
break;
|
1453
|
-
}
|
1454
|
-
}
|
1455
|
-
if (i > 0) {
|
1456
|
-
reuseQueue = reverseDeactivateQueue.slice(0, i);
|
1457
|
-
deactivateQueue = reverseDeactivateQueue.slice(i).reverse();
|
1458
|
-
activateQueue = activateQueue.slice(i);
|
1459
|
-
}
|
1444
|
+
var genKey = function () { return String(Date.now()); }
|
1445
|
+
var _key = genKey()
|
1460
1446
|
|
1461
|
-
|
1462
|
-
|
1463
|
-
|
1464
|
-
transition.runQueue(deactivateQueue, deactivate, function () {
|
1465
|
-
// 3. Activation phase
|
1466
|
-
|
1467
|
-
// Update router current route
|
1468
|
-
transition.router._onTransitionValidated(transition);
|
1469
|
-
|
1470
|
-
// trigger reuse for all reused views
|
1471
|
-
reuseQueue && reuseQueue.forEach(function (view) {
|
1472
|
-
return reuse(view, transition);
|
1473
|
-
});
|
1474
|
-
|
1475
|
-
// the root of the chain that needs to be replaced
|
1476
|
-
// is the top-most non-reusable view.
|
1477
|
-
if (deactivateQueue.length) {
|
1478
|
-
var _view = deactivateQueue[deactivateQueue.length - 1];
|
1479
|
-
var depth = reuseQueue ? reuseQueue.length : 0;
|
1480
|
-
activate(_view, transition, depth, cb);
|
1481
|
-
} else {
|
1482
|
-
cb();
|
1483
|
-
}
|
1484
|
-
});
|
1485
|
-
});
|
1486
|
-
});
|
1487
|
-
};
|
1488
|
-
|
1489
|
-
/**
|
1490
|
-
* Asynchronously and sequentially apply a function to a
|
1491
|
-
* queue.
|
1492
|
-
*
|
1493
|
-
* @param {Array} queue
|
1494
|
-
* @param {Function} fn
|
1495
|
-
* @param {Function} cb
|
1496
|
-
*/
|
1497
|
-
|
1498
|
-
RouteTransition.prototype.runQueue = function runQueue(queue, fn, cb) {
|
1499
|
-
var transition = this;
|
1500
|
-
step(0);
|
1501
|
-
function step(index) {
|
1502
|
-
if (index >= queue.length) {
|
1503
|
-
cb();
|
1504
|
-
} else {
|
1505
|
-
fn(queue[index], transition, function () {
|
1506
|
-
step(index + 1);
|
1507
|
-
});
|
1508
|
-
}
|
1509
|
-
}
|
1510
|
-
};
|
1511
|
-
|
1512
|
-
/**
|
1513
|
-
* Call a user provided route transition hook and handle
|
1514
|
-
* the response (e.g. if the user returns a promise).
|
1515
|
-
*
|
1516
|
-
* If the user neither expects an argument nor returns a
|
1517
|
-
* promise, the hook is assumed to be synchronous.
|
1518
|
-
*
|
1519
|
-
* @param {Function} hook
|
1520
|
-
* @param {*} [context]
|
1521
|
-
* @param {Function} [cb]
|
1522
|
-
* @param {Object} [options]
|
1523
|
-
* - {Boolean} expectBoolean
|
1524
|
-
* - {Boolean} postActive
|
1525
|
-
* - {Function} processData
|
1526
|
-
* - {Function} cleanup
|
1527
|
-
*/
|
1528
|
-
|
1529
|
-
RouteTransition.prototype.callHook = function callHook(hook, context, cb) {
|
1530
|
-
var _ref = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3];
|
1531
|
-
|
1532
|
-
var _ref$expectBoolean = _ref.expectBoolean;
|
1533
|
-
var expectBoolean = _ref$expectBoolean === undefined ? false : _ref$expectBoolean;
|
1534
|
-
var _ref$postActivate = _ref.postActivate;
|
1535
|
-
var postActivate = _ref$postActivate === undefined ? false : _ref$postActivate;
|
1536
|
-
var processData = _ref.processData;
|
1537
|
-
var cleanup = _ref.cleanup;
|
1538
|
-
|
1539
|
-
var transition = this;
|
1540
|
-
var nextCalled = false;
|
1541
|
-
|
1542
|
-
// abort the transition
|
1543
|
-
var abort = function abort() {
|
1544
|
-
cleanup && cleanup();
|
1545
|
-
transition.abort();
|
1546
|
-
};
|
1547
|
-
|
1548
|
-
// handle errors
|
1549
|
-
var onError = function onError(err) {
|
1550
|
-
postActivate ? next() : abort();
|
1551
|
-
if (err && !transition.router._suppress) {
|
1552
|
-
warn$1('Uncaught error during transition: ');
|
1553
|
-
throw err instanceof Error ? err : new Error(err);
|
1554
|
-
}
|
1555
|
-
};
|
1556
|
-
|
1557
|
-
// since promise swallows errors, we have to
|
1558
|
-
// throw it in the next tick...
|
1559
|
-
var onPromiseError = function onPromiseError(err) {
|
1560
|
-
try {
|
1561
|
-
onError(err);
|
1562
|
-
} catch (e) {
|
1563
|
-
setTimeout(function () {
|
1564
|
-
throw e;
|
1565
|
-
}, 0);
|
1566
|
-
}
|
1567
|
-
};
|
1447
|
+
var HTML5History = (function (History) {
|
1448
|
+
function HTML5History (router, base) {
|
1449
|
+
var this$1 = this;
|
1568
1450
|
|
1569
|
-
|
1570
|
-
var next = function next() {
|
1571
|
-
if (nextCalled) {
|
1572
|
-
warn$1('transition.next() should be called only once.');
|
1573
|
-
return;
|
1574
|
-
}
|
1575
|
-
nextCalled = true;
|
1576
|
-
if (transition.aborted) {
|
1577
|
-
cleanup && cleanup();
|
1578
|
-
return;
|
1579
|
-
}
|
1580
|
-
cb && cb();
|
1581
|
-
};
|
1582
|
-
|
1583
|
-
var nextWithBoolean = function nextWithBoolean(res) {
|
1584
|
-
if (typeof res === 'boolean') {
|
1585
|
-
res ? next() : abort();
|
1586
|
-
} else if (isPromise(res)) {
|
1587
|
-
res.then(function (ok) {
|
1588
|
-
ok ? next() : abort();
|
1589
|
-
}, onPromiseError);
|
1590
|
-
} else if (!hook.length) {
|
1591
|
-
next();
|
1592
|
-
}
|
1593
|
-
};
|
1594
|
-
|
1595
|
-
var nextWithData = function nextWithData(data) {
|
1596
|
-
var res = undefined;
|
1597
|
-
try {
|
1598
|
-
res = processData(data);
|
1599
|
-
} catch (err) {
|
1600
|
-
return onError(err);
|
1601
|
-
}
|
1602
|
-
if (isPromise(res)) {
|
1603
|
-
res.then(next, onPromiseError);
|
1604
|
-
} else {
|
1605
|
-
next();
|
1606
|
-
}
|
1607
|
-
};
|
1608
|
-
|
1609
|
-
// expose a clone of the transition object, so that each
|
1610
|
-
// hook gets a clean copy and prevent the user from
|
1611
|
-
// messing with the internals.
|
1612
|
-
var exposed = {
|
1613
|
-
to: transition.to,
|
1614
|
-
from: transition.from,
|
1615
|
-
abort: abort,
|
1616
|
-
next: processData ? nextWithData : next,
|
1617
|
-
redirect: function redirect() {
|
1618
|
-
transition.redirect.apply(transition, arguments);
|
1619
|
-
}
|
1620
|
-
};
|
1621
|
-
|
1622
|
-
// actually call the hook
|
1623
|
-
var res = undefined;
|
1624
|
-
try {
|
1625
|
-
res = hook.call(context, exposed);
|
1626
|
-
} catch (err) {
|
1627
|
-
return onError(err);
|
1628
|
-
}
|
1451
|
+
History.call(this, router, base)
|
1629
1452
|
|
1630
|
-
|
1631
|
-
// boolean hooks
|
1632
|
-
nextWithBoolean(res);
|
1633
|
-
} else if (isPromise(res)) {
|
1634
|
-
// promise
|
1635
|
-
if (processData) {
|
1636
|
-
res.then(nextWithData, onPromiseError);
|
1637
|
-
} else {
|
1638
|
-
res.then(next, onPromiseError);
|
1639
|
-
}
|
1640
|
-
} else if (processData && isPlainOjbect(res)) {
|
1641
|
-
// data promise sugar
|
1642
|
-
nextWithData(res);
|
1643
|
-
} else if (!hook.length) {
|
1644
|
-
next();
|
1645
|
-
}
|
1646
|
-
};
|
1647
|
-
|
1648
|
-
/**
|
1649
|
-
* Call a single hook or an array of async hooks in series.
|
1650
|
-
*
|
1651
|
-
* @param {Array} hooks
|
1652
|
-
* @param {*} context
|
1653
|
-
* @param {Function} cb
|
1654
|
-
* @param {Object} [options]
|
1655
|
-
*/
|
1656
|
-
|
1657
|
-
RouteTransition.prototype.callHooks = function callHooks(hooks, context, cb, options) {
|
1658
|
-
var _this = this;
|
1659
|
-
|
1660
|
-
if (Array.isArray(hooks)) {
|
1661
|
-
this.runQueue(hooks, function (hook, _, next) {
|
1662
|
-
if (!_this.aborted) {
|
1663
|
-
_this.callHook(hook, context, next, options);
|
1664
|
-
}
|
1665
|
-
}, cb);
|
1666
|
-
} else {
|
1667
|
-
this.callHook(hooks, context, cb, options);
|
1668
|
-
}
|
1669
|
-
};
|
1453
|
+
this.transitionTo(getLocation(this.base))
|
1670
1454
|
|
1671
|
-
|
1672
|
-
|
1455
|
+
var expectScroll = router.options.scrollBehavior
|
1456
|
+
window.addEventListener('popstate', function (e) {
|
1457
|
+
_key = e.state && e.state.key
|
1458
|
+
var current = this$1.current
|
1459
|
+
this$1.transitionTo(getLocation(this$1.base), function (next) {
|
1460
|
+
if (expectScroll) {
|
1461
|
+
this$1.handleScroll(next, current, true)
|
1462
|
+
}
|
1463
|
+
})
|
1464
|
+
})
|
1673
1465
|
|
1674
|
-
|
1675
|
-
|
1466
|
+
if (expectScroll) {
|
1467
|
+
window.addEventListener('scroll', function () {
|
1468
|
+
saveScrollPosition(_key)
|
1469
|
+
})
|
1470
|
+
}
|
1676
1471
|
}
|
1677
1472
|
|
1678
|
-
|
1679
|
-
|
1680
|
-
|
1473
|
+
if ( History ) HTML5History.__proto__ = History;
|
1474
|
+
HTML5History.prototype = Object.create( History && History.prototype );
|
1475
|
+
HTML5History.prototype.constructor = HTML5History;
|
1681
1476
|
|
1682
|
-
|
1477
|
+
HTML5History.prototype.go = function go (n) {
|
1478
|
+
window.history.go(n)
|
1479
|
+
};
|
1683
1480
|
|
1684
|
-
|
1685
|
-
|
1686
|
-
*
|
1687
|
-
* @param {String} path
|
1688
|
-
* @param {Router} router
|
1689
|
-
*/
|
1481
|
+
HTML5History.prototype.push = function push (location) {
|
1482
|
+
var this$1 = this;
|
1690
1483
|
|
1691
|
-
|
1692
|
-
|
1484
|
+
var current = this.current
|
1485
|
+
this.transitionTo(location, function (route) {
|
1486
|
+
pushState(cleanPath(this$1.base + route.fullPath))
|
1487
|
+
this$1.handleScroll(route, current, false)
|
1488
|
+
})
|
1489
|
+
};
|
1693
1490
|
|
1694
|
-
|
1491
|
+
HTML5History.prototype.replace = function replace (location) {
|
1492
|
+
var this$1 = this;
|
1695
1493
|
|
1696
|
-
var
|
1697
|
-
|
1698
|
-
|
1699
|
-
|
1700
|
-
|
1701
|
-
|
1702
|
-
|
1703
|
-
|
1704
|
-
|
1705
|
-
|
1706
|
-
// set query and params
|
1707
|
-
this.query = matched.queryParams;
|
1708
|
-
this.params = [].reduce.call(matched, function (prev, cur) {
|
1709
|
-
if (cur.params) {
|
1710
|
-
for (var key in cur.params) {
|
1711
|
-
prev[key] = cur.params[key];
|
1712
|
-
}
|
1713
|
-
}
|
1714
|
-
return prev;
|
1715
|
-
}, {});
|
1494
|
+
var current = this.current
|
1495
|
+
this.transitionTo(location, function (route) {
|
1496
|
+
replaceState(cleanPath(this$1.base + route.fullPath))
|
1497
|
+
this$1.handleScroll(route, current, false)
|
1498
|
+
})
|
1499
|
+
};
|
1500
|
+
|
1501
|
+
HTML5History.prototype.ensureURL = function ensureURL () {
|
1502
|
+
if (getLocation(this.base) !== this.current.fullPath) {
|
1503
|
+
replaceState(cleanPath(this.base + this.current.fullPath))
|
1716
1504
|
}
|
1717
|
-
// expose path and router
|
1718
|
-
this.path = path;
|
1719
|
-
// for internal use
|
1720
|
-
this.matched = matched || router._notFoundHandler;
|
1721
|
-
// internal reference to router
|
1722
|
-
Object.defineProperty(this, 'router', {
|
1723
|
-
enumerable: false,
|
1724
|
-
value: router
|
1725
|
-
});
|
1726
|
-
// Important: freeze self to prevent observation
|
1727
|
-
Object.freeze(this);
|
1728
1505
|
};
|
1729
1506
|
|
1730
|
-
function
|
1731
|
-
var
|
1732
|
-
|
1733
|
-
|
1734
|
-
|
1735
|
-
|
1736
|
-
|
1737
|
-
|
1738
|
-
|
1739
|
-
|
1740
|
-
|
1741
|
-
|
1742
|
-
|
1743
|
-
|
1744
|
-
|
1745
|
-
|
1746
|
-
|
1747
|
-
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1751
|
-
|
1752
|
-
|
1753
|
-
|
1507
|
+
HTML5History.prototype.handleScroll = function handleScroll (to, from, isPop) {
|
1508
|
+
var router = this.router
|
1509
|
+
if (!router.app) {
|
1510
|
+
return
|
1511
|
+
}
|
1512
|
+
|
1513
|
+
var behavior = router.options.scrollBehavior
|
1514
|
+
if (!behavior) {
|
1515
|
+
return
|
1516
|
+
}
|
1517
|
+
assert(typeof behavior === 'function', "scrollBehavior must be a function")
|
1518
|
+
|
1519
|
+
// wait until re-render finishes before scrolling
|
1520
|
+
router.app.$nextTick(function () {
|
1521
|
+
var position = getScrollPosition(_key)
|
1522
|
+
var shouldScroll = behavior(to, from, isPop ? position : null)
|
1523
|
+
if (!shouldScroll) {
|
1524
|
+
return
|
1525
|
+
}
|
1526
|
+
var isObject = typeof shouldScroll === 'object'
|
1527
|
+
if (isObject && typeof shouldScroll.selector === 'string') {
|
1528
|
+
var el = document.querySelector(shouldScroll.selector)
|
1529
|
+
if (el) {
|
1530
|
+
position = getElementPosition(el)
|
1531
|
+
} else if (isValidPosition(shouldScroll)) {
|
1532
|
+
position = normalizePosition(shouldScroll)
|
1754
1533
|
}
|
1534
|
+
} else if (isObject && isValidPosition(shouldScroll)) {
|
1535
|
+
position = normalizePosition(shouldScroll)
|
1755
1536
|
}
|
1756
|
-
init.call(this, options);
|
1757
|
-
};
|
1758
1537
|
|
1759
|
-
|
1760
|
-
|
1761
|
-
if (!this._isBeingDestroyed && this.$router) {
|
1762
|
-
this.$router._children.$remove(this);
|
1538
|
+
if (position) {
|
1539
|
+
window.scrollTo(position.x, position.y)
|
1763
1540
|
}
|
1764
|
-
|
1765
|
-
|
1766
|
-
|
1767
|
-
|
1768
|
-
|
1769
|
-
|
1770
|
-
|
1771
|
-
|
1772
|
-
|
1773
|
-
|
1774
|
-
|
1775
|
-
|
1776
|
-
|
1777
|
-
|
1778
|
-
|
1779
|
-
|
1780
|
-
|
1781
|
-
|
1782
|
-
|
1783
|
-
|
1784
|
-
|
1785
|
-
|
1786
|
-
|
1787
|
-
|
1788
|
-
return ret;
|
1789
|
-
};
|
1541
|
+
})
|
1542
|
+
};
|
1543
|
+
|
1544
|
+
return HTML5History;
|
1545
|
+
}(History));
|
1546
|
+
|
1547
|
+
function getLocation (base) {
|
1548
|
+
var path = window.location.pathname
|
1549
|
+
if (base && path.indexOf(base) === 0) {
|
1550
|
+
path = path.slice(base.length)
|
1551
|
+
}
|
1552
|
+
return (path || '/') + window.location.search + window.location.hash
|
1553
|
+
}
|
1554
|
+
|
1555
|
+
function pushState (url, replace) {
|
1556
|
+
// try...catch the pushState call to get around Safari
|
1557
|
+
// DOM Exception 18 where it limits to 100 pushState calls
|
1558
|
+
var history = window.history
|
1559
|
+
try {
|
1560
|
+
if (replace) {
|
1561
|
+
history.replaceState({ key: _key }, '', url)
|
1562
|
+
} else {
|
1563
|
+
_key = genKey()
|
1564
|
+
history.pushState({ key: _key }, '', url)
|
1790
1565
|
}
|
1566
|
+
saveScrollPosition(_key)
|
1567
|
+
} catch (e) {
|
1568
|
+
window.location[replace ? 'assign' : 'replace'](url)
|
1791
1569
|
}
|
1570
|
+
}
|
1792
1571
|
|
1793
|
-
|
1572
|
+
function replaceState (url) {
|
1573
|
+
pushState(url, true)
|
1574
|
+
}
|
1794
1575
|
|
1795
|
-
|
1796
|
-
var componentDef =
|
1797
|
-
// 0.12
|
1798
|
-
Vue.directive('_component') ||
|
1799
|
-
// 1.0
|
1800
|
-
Vue.internalDirectives.component;
|
1801
|
-
// <router-view> extends the internal component directive
|
1802
|
-
var viewDef = _.extend({}, componentDef);
|
1576
|
+
/* */
|
1803
1577
|
|
1804
|
-
// with some overrides
|
1805
|
-
_.extend(viewDef, {
|
1806
1578
|
|
1807
|
-
|
1579
|
+
var HashHistory = (function (History) {
|
1580
|
+
function HashHistory (router, base, fallback) {
|
1581
|
+
var this$1 = this;
|
1808
1582
|
|
1809
|
-
|
1810
|
-
var route = this.vm.$route;
|
1811
|
-
/* istanbul ignore if */
|
1812
|
-
if (!route) {
|
1813
|
-
warn$1('<router-view> can only be used inside a ' + 'router-enabled app.');
|
1814
|
-
return;
|
1815
|
-
}
|
1816
|
-
// force dynamic directive so v-component doesn't
|
1817
|
-
// attempt to build right now
|
1818
|
-
this._isDynamicLiteral = true;
|
1819
|
-
// finally, init by delegating to v-component
|
1820
|
-
componentDef.bind.call(this);
|
1821
|
-
|
1822
|
-
// locate the parent view
|
1823
|
-
var parentView = undefined;
|
1824
|
-
var parent = this.vm;
|
1825
|
-
while (parent) {
|
1826
|
-
if (parent._routerView) {
|
1827
|
-
parentView = parent._routerView;
|
1828
|
-
break;
|
1829
|
-
}
|
1830
|
-
parent = parent.$parent;
|
1831
|
-
}
|
1832
|
-
if (parentView) {
|
1833
|
-
// register self as a child of the parent view,
|
1834
|
-
// instead of activating now. This is so that the
|
1835
|
-
// child's activate hook is called after the
|
1836
|
-
// parent's has resolved.
|
1837
|
-
this.parentView = parentView;
|
1838
|
-
parentView.childView = this;
|
1839
|
-
} else {
|
1840
|
-
// this is the root view!
|
1841
|
-
var router = route.router;
|
1842
|
-
router._rootView = this;
|
1843
|
-
}
|
1583
|
+
History.call(this, router, base)
|
1844
1584
|
|
1845
|
-
|
1846
|
-
|
1847
|
-
|
1848
|
-
|
1849
|
-
// 2. child view rendered after parent view has been
|
1850
|
-
// activated.
|
1851
|
-
var transition = route.router._currentTransition;
|
1852
|
-
if (!parentView && transition.done || parentView && parentView.activated) {
|
1853
|
-
var depth = parentView ? parentView.depth + 1 : 0;
|
1854
|
-
activate(this, transition, depth);
|
1855
|
-
}
|
1856
|
-
},
|
1585
|
+
// check history fallback deeplinking
|
1586
|
+
if (fallback && this.checkFallback()) {
|
1587
|
+
return
|
1588
|
+
}
|
1857
1589
|
|
1858
|
-
|
1859
|
-
|
1860
|
-
this.parentView.childView = null;
|
1861
|
-
}
|
1862
|
-
componentDef.unbind.call(this);
|
1863
|
-
}
|
1864
|
-
});
|
1865
|
-
|
1866
|
-
Vue.elementDirective('router-view', viewDef);
|
1867
|
-
}
|
1868
|
-
|
1869
|
-
var trailingSlashRE = /\/$/;
|
1870
|
-
var regexEscapeRE = /[-.*+?^${}()|[\]\/\\]/g;
|
1871
|
-
var queryStringRE = /\?.*$/;
|
1872
|
-
|
1873
|
-
// install v-link, which provides navigation support for
|
1874
|
-
// HTML5 history mode
|
1875
|
-
function Link (Vue) {
|
1876
|
-
var _Vue$util = Vue.util;
|
1877
|
-
var _bind = _Vue$util.bind;
|
1878
|
-
var isObject = _Vue$util.isObject;
|
1879
|
-
var addClass = _Vue$util.addClass;
|
1880
|
-
var removeClass = _Vue$util.removeClass;
|
1881
|
-
|
1882
|
-
var onPriority = Vue.directive('on').priority;
|
1883
|
-
var LINK_UPDATE = '__vue-router-link-update__';
|
1884
|
-
|
1885
|
-
var activeId = 0;
|
1886
|
-
|
1887
|
-
Vue.directive('link-active', {
|
1888
|
-
priority: 9999,
|
1889
|
-
bind: function bind() {
|
1890
|
-
var _this = this;
|
1891
|
-
|
1892
|
-
var id = String(activeId++);
|
1893
|
-
// collect v-links contained within this element.
|
1894
|
-
// we need do this here before the parent-child relationship
|
1895
|
-
// gets messed up by terminal directives (if, for, components)
|
1896
|
-
var childLinks = this.el.querySelectorAll('[v-link]');
|
1897
|
-
for (var i = 0, l = childLinks.length; i < l; i++) {
|
1898
|
-
var link = childLinks[i];
|
1899
|
-
var existingId = link.getAttribute(LINK_UPDATE);
|
1900
|
-
var value = existingId ? existingId + ',' + id : id;
|
1901
|
-
// leave a mark on the link element which can be persisted
|
1902
|
-
// through fragment clones.
|
1903
|
-
link.setAttribute(LINK_UPDATE, value);
|
1904
|
-
}
|
1905
|
-
this.vm.$on(LINK_UPDATE, this.cb = function (link, path) {
|
1906
|
-
if (link.activeIds.indexOf(id) > -1) {
|
1907
|
-
link.updateClasses(path, _this.el);
|
1908
|
-
}
|
1909
|
-
});
|
1910
|
-
},
|
1911
|
-
unbind: function unbind() {
|
1912
|
-
this.vm.$off(LINK_UPDATE, this.cb);
|
1913
|
-
}
|
1914
|
-
});
|
1590
|
+
ensureSlash()
|
1591
|
+
this.transitionTo(getHash())
|
1915
1592
|
|
1916
|
-
|
1917
|
-
|
1593
|
+
window.addEventListener('hashchange', function () {
|
1594
|
+
this$1.onHashChange()
|
1595
|
+
})
|
1596
|
+
}
|
1918
1597
|
|
1919
|
-
|
1920
|
-
|
1921
|
-
|
1922
|
-
|
1923
|
-
|
1924
|
-
|
1925
|
-
|
1926
|
-
|
1927
|
-
|
1928
|
-
|
1929
|
-
|
1930
|
-
|
1931
|
-
|
1932
|
-
this.el.removeAttribute(LINK_UPDATE);
|
1933
|
-
this.activeIds = activeIds.split(',');
|
1934
|
-
}
|
1935
|
-
// no need to handle click if link expects to be opened
|
1936
|
-
// in a new window/tab.
|
1937
|
-
/* istanbul ignore if */
|
1938
|
-
if (this.el.tagName === 'A' && this.el.getAttribute('target') === '_blank') {
|
1939
|
-
return;
|
1940
|
-
}
|
1941
|
-
// handle click
|
1942
|
-
this.handler = _bind(this.onClick, this);
|
1943
|
-
this.el.addEventListener('click', this.handler);
|
1944
|
-
},
|
1945
|
-
|
1946
|
-
update: function update(target) {
|
1947
|
-
this.target = target;
|
1948
|
-
if (isObject(target)) {
|
1949
|
-
this.append = target.append;
|
1950
|
-
this.exact = target.exact;
|
1951
|
-
this.prevActiveClass = this.activeClass;
|
1952
|
-
this.activeClass = target.activeClass;
|
1953
|
-
}
|
1954
|
-
this.onRouteUpdate(this.vm.$route);
|
1955
|
-
},
|
1956
|
-
|
1957
|
-
onClick: function onClick(e) {
|
1958
|
-
// don't redirect with control keys
|
1959
|
-
/* istanbul ignore if */
|
1960
|
-
if (e.metaKey || e.ctrlKey || e.shiftKey) return;
|
1961
|
-
// don't redirect when preventDefault called
|
1962
|
-
/* istanbul ignore if */
|
1963
|
-
if (e.defaultPrevented) return;
|
1964
|
-
// don't redirect on right click
|
1965
|
-
/* istanbul ignore if */
|
1966
|
-
if (e.button !== 0) return;
|
1967
|
-
|
1968
|
-
var target = this.target;
|
1969
|
-
if (target) {
|
1970
|
-
// v-link with expression, just go
|
1971
|
-
e.preventDefault();
|
1972
|
-
this.router.go(target);
|
1973
|
-
} else {
|
1974
|
-
// no expression, delegate for an <a> inside
|
1975
|
-
var el = e.target;
|
1976
|
-
while (el.tagName !== 'A' && el !== this.el) {
|
1977
|
-
el = el.parentNode;
|
1978
|
-
}
|
1979
|
-
if (el.tagName === 'A' && sameOrigin(el)) {
|
1980
|
-
e.preventDefault();
|
1981
|
-
var path = el.pathname;
|
1982
|
-
if (this.router.history.root) {
|
1983
|
-
path = path.replace(this.router.history.rootRE, '');
|
1984
|
-
}
|
1985
|
-
this.router.go({
|
1986
|
-
path: path,
|
1987
|
-
replace: target && target.replace,
|
1988
|
-
append: target && target.append
|
1989
|
-
});
|
1990
|
-
}
|
1991
|
-
}
|
1992
|
-
},
|
1993
|
-
|
1994
|
-
onRouteUpdate: function onRouteUpdate(route) {
|
1995
|
-
// router.stringifyPath is dependent on current route
|
1996
|
-
// and needs to be called again whenver route changes.
|
1997
|
-
var newPath = this.router.stringifyPath(this.target);
|
1998
|
-
if (this.path !== newPath) {
|
1999
|
-
this.path = newPath;
|
2000
|
-
this.updateActiveMatch();
|
2001
|
-
this.updateHref();
|
2002
|
-
}
|
2003
|
-
if (this.activeIds) {
|
2004
|
-
this.vm.$emit(LINK_UPDATE, this, route.path);
|
2005
|
-
} else {
|
2006
|
-
this.updateClasses(route.path, this.el);
|
2007
|
-
}
|
2008
|
-
},
|
1598
|
+
if ( History ) HashHistory.__proto__ = History;
|
1599
|
+
HashHistory.prototype = Object.create( History && History.prototype );
|
1600
|
+
HashHistory.prototype.constructor = HashHistory;
|
1601
|
+
|
1602
|
+
HashHistory.prototype.checkFallback = function checkFallback () {
|
1603
|
+
var location = getLocation(this.base)
|
1604
|
+
if (!/^\/#/.test(location)) {
|
1605
|
+
window.location.replace(
|
1606
|
+
cleanPath(this.base + '/#' + location)
|
1607
|
+
)
|
1608
|
+
return true
|
1609
|
+
}
|
1610
|
+
};
|
2009
1611
|
|
2010
|
-
|
2011
|
-
|
2012
|
-
|
1612
|
+
HashHistory.prototype.onHashChange = function onHashChange () {
|
1613
|
+
if (!ensureSlash()) {
|
1614
|
+
return
|
1615
|
+
}
|
1616
|
+
this.transitionTo(getHash(), function (route) {
|
1617
|
+
replaceHash(route.fullPath)
|
1618
|
+
})
|
1619
|
+
};
|
2013
1620
|
|
2014
|
-
|
2015
|
-
|
2016
|
-
|
2017
|
-
|
2018
|
-
|
2019
|
-
var router = this.router;
|
2020
|
-
var isAbsolute = path.charAt(0) === '/';
|
2021
|
-
// do not format non-hash relative paths
|
2022
|
-
var href = path && (router.mode === 'hash' || isAbsolute) ? router.history.formatPath(path, this.append) : path;
|
2023
|
-
if (href) {
|
2024
|
-
this.el.href = href;
|
2025
|
-
} else {
|
2026
|
-
this.el.removeAttribute('href');
|
2027
|
-
}
|
2028
|
-
},
|
1621
|
+
HashHistory.prototype.push = function push (location) {
|
1622
|
+
History.prototype.transitionTo.call(this, location, function (route) {
|
1623
|
+
pushHash(route.fullPath)
|
1624
|
+
})
|
1625
|
+
};
|
2029
1626
|
|
2030
|
-
|
2031
|
-
|
2032
|
-
|
2033
|
-
|
2034
|
-
|
2035
|
-
}
|
2036
|
-
// remove query string before matching
|
2037
|
-
var dest = this.path.replace(queryStringRE, '');
|
2038
|
-
path = path.replace(queryStringRE, '');
|
2039
|
-
// add new class
|
2040
|
-
if (this.exact) {
|
2041
|
-
if (dest === path ||
|
2042
|
-
// also allow additional trailing slash
|
2043
|
-
dest.charAt(dest.length - 1) !== '/' && dest === path.replace(trailingSlashRE, '')) {
|
2044
|
-
toggleClasses(el, activeClass, addClass);
|
2045
|
-
} else {
|
2046
|
-
toggleClasses(el, activeClass, removeClass);
|
2047
|
-
}
|
2048
|
-
} else {
|
2049
|
-
if (this.activeRE && this.activeRE.test(path)) {
|
2050
|
-
toggleClasses(el, activeClass, addClass);
|
2051
|
-
} else {
|
2052
|
-
toggleClasses(el, activeClass, removeClass);
|
2053
|
-
}
|
2054
|
-
}
|
2055
|
-
},
|
1627
|
+
HashHistory.prototype.replace = function replace (location) {
|
1628
|
+
History.prototype.transitionTo.call(this, location, function (route) {
|
1629
|
+
replaceHash(route.fullPath)
|
1630
|
+
})
|
1631
|
+
};
|
2056
1632
|
|
2057
|
-
|
2058
|
-
|
2059
|
-
|
2060
|
-
}
|
2061
|
-
});
|
1633
|
+
HashHistory.prototype.go = function go (n) {
|
1634
|
+
window.history.go(n)
|
1635
|
+
};
|
2062
1636
|
|
2063
|
-
|
2064
|
-
|
1637
|
+
HashHistory.prototype.ensureURL = function ensureURL () {
|
1638
|
+
if (getHash() !== this.current.fullPath) {
|
1639
|
+
replaceHash(this.current.fullPath)
|
2065
1640
|
}
|
1641
|
+
};
|
2066
1642
|
|
2067
|
-
|
2068
|
-
|
2069
|
-
|
2070
|
-
|
2071
|
-
|
2072
|
-
|
2073
|
-
|
2074
|
-
|
2075
|
-
|
2076
|
-
|
2077
|
-
|
2078
|
-
|
2079
|
-
|
1643
|
+
return HashHistory;
|
1644
|
+
}(History));
|
1645
|
+
|
1646
|
+
function ensureSlash () {
|
1647
|
+
var path = getHash()
|
1648
|
+
if (path.charAt(0) === '/') {
|
1649
|
+
return true
|
1650
|
+
}
|
1651
|
+
replaceHash('/' + path)
|
1652
|
+
return false
|
1653
|
+
}
|
1654
|
+
|
1655
|
+
function getHash () {
|
1656
|
+
// We can't use window.location.hash here because it's not
|
1657
|
+
// consistent across browsers - Firefox will pre-decode it!
|
1658
|
+
var href = window.location.href
|
1659
|
+
var index = href.indexOf('#')
|
1660
|
+
return index === -1 ? '' : href.slice(index + 1)
|
1661
|
+
}
|
1662
|
+
|
1663
|
+
function pushHash (path) {
|
1664
|
+
window.location.hash = path
|
1665
|
+
}
|
1666
|
+
|
1667
|
+
function replaceHash (path) {
|
1668
|
+
var i = window.location.href.indexOf('#')
|
1669
|
+
window.location.replace(
|
1670
|
+
window.location.href.slice(0, i >= 0 ? i : 0) + '#' + path
|
1671
|
+
)
|
1672
|
+
}
|
1673
|
+
|
1674
|
+
/* */
|
1675
|
+
|
1676
|
+
|
1677
|
+
var AbstractHistory = (function (History) {
|
1678
|
+
function AbstractHistory (router) {
|
1679
|
+
History.call(this, router)
|
1680
|
+
this.stack = []
|
1681
|
+
this.index = 0
|
2080
1682
|
}
|
2081
1683
|
|
2082
|
-
|
2083
|
-
|
2084
|
-
|
2085
|
-
|
1684
|
+
if ( History ) AbstractHistory.__proto__ = History;
|
1685
|
+
AbstractHistory.prototype = Object.create( History && History.prototype );
|
1686
|
+
AbstractHistory.prototype.constructor = AbstractHistory;
|
1687
|
+
|
1688
|
+
AbstractHistory.prototype.push = function push (location) {
|
1689
|
+
var this$1 = this;
|
1690
|
+
|
1691
|
+
History.prototype.transitionTo.call(this, location, function (route) {
|
1692
|
+
this$1.stack = this$1.stack.slice(0, this$1.index + 1).concat(route)
|
1693
|
+
this$1.index++
|
1694
|
+
})
|
2086
1695
|
};
|
2087
1696
|
|
2088
|
-
|
2089
|
-
|
2090
|
-
|
2091
|
-
/**
|
2092
|
-
* Router constructor
|
2093
|
-
*
|
2094
|
-
* @param {Object} [options]
|
2095
|
-
*/
|
2096
|
-
|
2097
|
-
var Router = (function () {
|
2098
|
-
function Router() {
|
2099
|
-
var _this = this;
|
2100
|
-
|
2101
|
-
var _ref = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
|
2102
|
-
|
2103
|
-
var _ref$hashbang = _ref.hashbang;
|
2104
|
-
var hashbang = _ref$hashbang === undefined ? true : _ref$hashbang;
|
2105
|
-
var _ref$abstract = _ref.abstract;
|
2106
|
-
var abstract = _ref$abstract === undefined ? false : _ref$abstract;
|
2107
|
-
var _ref$history = _ref.history;
|
2108
|
-
var history = _ref$history === undefined ? false : _ref$history;
|
2109
|
-
var _ref$saveScrollPosition = _ref.saveScrollPosition;
|
2110
|
-
var saveScrollPosition = _ref$saveScrollPosition === undefined ? false : _ref$saveScrollPosition;
|
2111
|
-
var _ref$transitionOnLoad = _ref.transitionOnLoad;
|
2112
|
-
var transitionOnLoad = _ref$transitionOnLoad === undefined ? false : _ref$transitionOnLoad;
|
2113
|
-
var _ref$suppressTransitionError = _ref.suppressTransitionError;
|
2114
|
-
var suppressTransitionError = _ref$suppressTransitionError === undefined ? false : _ref$suppressTransitionError;
|
2115
|
-
var _ref$root = _ref.root;
|
2116
|
-
var root = _ref$root === undefined ? null : _ref$root;
|
2117
|
-
var _ref$linkActiveClass = _ref.linkActiveClass;
|
2118
|
-
var linkActiveClass = _ref$linkActiveClass === undefined ? 'v-link-active' : _ref$linkActiveClass;
|
2119
|
-
babelHelpers.classCallCheck(this, Router);
|
2120
|
-
|
2121
|
-
/* istanbul ignore if */
|
2122
|
-
if (!Router.installed) {
|
2123
|
-
throw new Error('Please install the Router with Vue.use() before ' + 'creating an instance.');
|
2124
|
-
}
|
1697
|
+
AbstractHistory.prototype.replace = function replace (location) {
|
1698
|
+
var this$1 = this;
|
2125
1699
|
|
2126
|
-
|
2127
|
-
this.
|
2128
|
-
|
2129
|
-
|
2130
|
-
|
2131
|
-
|
2132
|
-
|
2133
|
-
|
2134
|
-
// state
|
2135
|
-
this._started = false;
|
2136
|
-
this._startCb = null;
|
2137
|
-
this._currentRoute = {};
|
2138
|
-
this._currentTransition = null;
|
2139
|
-
this._previousTransition = null;
|
2140
|
-
this._notFoundHandler = null;
|
2141
|
-
this._notFoundRedirect = null;
|
2142
|
-
this._beforeEachHooks = [];
|
2143
|
-
this._afterEachHooks = [];
|
2144
|
-
|
2145
|
-
// trigger transition on initial render?
|
2146
|
-
this._rendered = false;
|
2147
|
-
this._transitionOnLoad = transitionOnLoad;
|
2148
|
-
|
2149
|
-
// history mode
|
2150
|
-
this._root = root;
|
2151
|
-
this._abstract = abstract;
|
2152
|
-
this._hashbang = hashbang;
|
2153
|
-
|
2154
|
-
// check if HTML5 history is available
|
2155
|
-
var hasPushState = typeof window !== 'undefined' && window.history && window.history.pushState;
|
2156
|
-
this._history = history && hasPushState;
|
2157
|
-
this._historyFallback = history && !hasPushState;
|
2158
|
-
|
2159
|
-
// create history object
|
2160
|
-
var inBrowser = Vue.util.inBrowser;
|
2161
|
-
this.mode = !inBrowser || this._abstract ? 'abstract' : this._history ? 'html5' : 'hash';
|
2162
|
-
|
2163
|
-
var History = historyBackends[this.mode];
|
2164
|
-
this.history = new History({
|
2165
|
-
root: root,
|
2166
|
-
hashbang: this._hashbang,
|
2167
|
-
onChange: function onChange(path, state, anchor) {
|
2168
|
-
_this._match(path, state, anchor);
|
2169
|
-
}
|
2170
|
-
});
|
1700
|
+
History.prototype.transitionTo.call(this, location, function (route) {
|
1701
|
+
this$1.stack = this$1.stack.slice(0, this$1.index).concat(route)
|
1702
|
+
})
|
1703
|
+
};
|
1704
|
+
|
1705
|
+
AbstractHistory.prototype.go = function go (n) {
|
1706
|
+
var this$1 = this;
|
2171
1707
|
|
2172
|
-
|
2173
|
-
|
2174
|
-
|
2175
|
-
this._suppress = suppressTransitionError;
|
1708
|
+
var targetIndex = this.index + n
|
1709
|
+
if (targetIndex < 0 || targetIndex >= this.stack.length) {
|
1710
|
+
return
|
2176
1711
|
}
|
1712
|
+
var location = this.stack[targetIndex]
|
1713
|
+
this.confirmTransition(location, function () {
|
1714
|
+
this$1.index = targetIndex
|
1715
|
+
this$1.updateRoute(location)
|
1716
|
+
})
|
1717
|
+
};
|
2177
1718
|
|
2178
|
-
|
2179
|
-
|
2180
|
-
|
2181
|
-
*
|
2182
|
-
* @param {String} path
|
2183
|
-
* @param {Object} handler
|
2184
|
-
*/
|
2185
|
-
|
2186
|
-
// API ===================================================
|
2187
|
-
|
2188
|
-
/**
|
2189
|
-
* Register a map of top-level paths.
|
2190
|
-
*
|
2191
|
-
* @param {Object} map
|
2192
|
-
*/
|
2193
|
-
|
2194
|
-
Router.prototype.map = function map(_map) {
|
2195
|
-
for (var route in _map) {
|
2196
|
-
this.on(route, _map[route]);
|
2197
|
-
}
|
2198
|
-
return this;
|
2199
|
-
};
|
2200
|
-
|
2201
|
-
/**
|
2202
|
-
* Register a single root-level path
|
2203
|
-
*
|
2204
|
-
* @param {String} rootPath
|
2205
|
-
* @param {Object} handler
|
2206
|
-
* - {String} component
|
2207
|
-
* - {Object} [subRoutes]
|
2208
|
-
* - {Boolean} [forceRefresh]
|
2209
|
-
* - {Function} [before]
|
2210
|
-
* - {Function} [after]
|
2211
|
-
*/
|
2212
|
-
|
2213
|
-
Router.prototype.on = function on(rootPath, handler) {
|
2214
|
-
if (rootPath === '*') {
|
2215
|
-
this._notFound(handler);
|
2216
|
-
} else {
|
2217
|
-
this._addRoute(rootPath, handler, []);
|
2218
|
-
}
|
2219
|
-
return this;
|
2220
|
-
};
|
2221
|
-
|
2222
|
-
/**
|
2223
|
-
* Set redirects.
|
2224
|
-
*
|
2225
|
-
* @param {Object} map
|
2226
|
-
*/
|
2227
|
-
|
2228
|
-
Router.prototype.redirect = function redirect(map) {
|
2229
|
-
for (var path in map) {
|
2230
|
-
this._addRedirect(path, map[path]);
|
2231
|
-
}
|
2232
|
-
return this;
|
2233
|
-
};
|
2234
|
-
|
2235
|
-
/**
|
2236
|
-
* Set aliases.
|
2237
|
-
*
|
2238
|
-
* @param {Object} map
|
2239
|
-
*/
|
2240
|
-
|
2241
|
-
Router.prototype.alias = function alias(map) {
|
2242
|
-
for (var path in map) {
|
2243
|
-
this._addAlias(path, map[path]);
|
2244
|
-
}
|
2245
|
-
return this;
|
2246
|
-
};
|
2247
|
-
|
2248
|
-
/**
|
2249
|
-
* Set global before hook.
|
2250
|
-
*
|
2251
|
-
* @param {Function} fn
|
2252
|
-
*/
|
2253
|
-
|
2254
|
-
Router.prototype.beforeEach = function beforeEach(fn) {
|
2255
|
-
this._beforeEachHooks.push(fn);
|
2256
|
-
return this;
|
2257
|
-
};
|
2258
|
-
|
2259
|
-
/**
|
2260
|
-
* Set global after hook.
|
2261
|
-
*
|
2262
|
-
* @param {Function} fn
|
2263
|
-
*/
|
2264
|
-
|
2265
|
-
Router.prototype.afterEach = function afterEach(fn) {
|
2266
|
-
this._afterEachHooks.push(fn);
|
2267
|
-
return this;
|
2268
|
-
};
|
2269
|
-
|
2270
|
-
/**
|
2271
|
-
* Navigate to a given path.
|
2272
|
-
* The path can be an object describing a named path in
|
2273
|
-
* the format of { name: '...', params: {}, query: {}}
|
2274
|
-
* The path is assumed to be already decoded, and will
|
2275
|
-
* be resolved against root (if provided)
|
2276
|
-
*
|
2277
|
-
* @param {String|Object} path
|
2278
|
-
* @param {Boolean} [replace]
|
2279
|
-
*/
|
2280
|
-
|
2281
|
-
Router.prototype.go = function go(path) {
|
2282
|
-
var replace = false;
|
2283
|
-
var append = false;
|
2284
|
-
if (Vue.util.isObject(path)) {
|
2285
|
-
replace = path.replace;
|
2286
|
-
append = path.append;
|
2287
|
-
}
|
2288
|
-
path = this.stringifyPath(path);
|
2289
|
-
if (path) {
|
2290
|
-
this.history.go(path, replace, append);
|
2291
|
-
}
|
2292
|
-
};
|
1719
|
+
AbstractHistory.prototype.ensureURL = function ensureURL () {
|
1720
|
+
// noop
|
1721
|
+
};
|
2293
1722
|
|
2294
|
-
|
2295
|
-
|
2296
|
-
*
|
2297
|
-
* @param {String} path
|
2298
|
-
*/
|
1723
|
+
return AbstractHistory;
|
1724
|
+
}(History));
|
2299
1725
|
|
2300
|
-
|
2301
|
-
if (typeof path === 'string') {
|
2302
|
-
path = { path: path };
|
2303
|
-
}
|
2304
|
-
path.replace = true;
|
2305
|
-
this.go(path);
|
2306
|
-
};
|
2307
|
-
|
2308
|
-
/**
|
2309
|
-
* Start the router.
|
2310
|
-
*
|
2311
|
-
* @param {VueConstructor} App
|
2312
|
-
* @param {String|Element} container
|
2313
|
-
* @param {Function} [cb]
|
2314
|
-
*/
|
2315
|
-
|
2316
|
-
Router.prototype.start = function start(App, container, cb) {
|
2317
|
-
/* istanbul ignore if */
|
2318
|
-
if (this._started) {
|
2319
|
-
warn$1('already started.');
|
2320
|
-
return;
|
2321
|
-
}
|
2322
|
-
this._started = true;
|
2323
|
-
this._startCb = cb;
|
2324
|
-
if (!this.app) {
|
2325
|
-
/* istanbul ignore if */
|
2326
|
-
if (!App || !container) {
|
2327
|
-
throw new Error('Must start vue-router with a component and a ' + 'root container.');
|
2328
|
-
}
|
2329
|
-
/* istanbul ignore if */
|
2330
|
-
if (App instanceof Vue) {
|
2331
|
-
throw new Error('Must start vue-router with a component, not a ' + 'Vue instance.');
|
2332
|
-
}
|
2333
|
-
this._appContainer = container;
|
2334
|
-
var Ctor = this._appConstructor = typeof App === 'function' ? App : Vue.extend(App);
|
2335
|
-
// give it a name for better debugging
|
2336
|
-
Ctor.options.name = Ctor.options.name || 'RouterApp';
|
2337
|
-
}
|
1726
|
+
/* */
|
2338
1727
|
|
2339
|
-
|
2340
|
-
|
2341
|
-
if (this._historyFallback) {
|
2342
|
-
var _location = window.location;
|
2343
|
-
var _history = new HTML5History({ root: this._root });
|
2344
|
-
var path = _history.root ? _location.pathname.replace(_history.rootRE, '') : _location.pathname;
|
2345
|
-
if (path && path !== '/') {
|
2346
|
-
_location.assign((_history.root || '') + '/' + this.history.formatPath(path) + _location.search);
|
2347
|
-
return;
|
2348
|
-
}
|
2349
|
-
}
|
1728
|
+
var VueRouter = function VueRouter (options) {
|
1729
|
+
if ( options === void 0 ) options = {};
|
2350
1730
|
|
2351
|
-
|
2352
|
-
|
2353
|
-
|
2354
|
-
|
2355
|
-
|
2356
|
-
*/
|
2357
|
-
|
2358
|
-
Router.prototype.stop = function stop() {
|
2359
|
-
this.history.stop();
|
2360
|
-
this._started = false;
|
2361
|
-
};
|
2362
|
-
|
2363
|
-
/**
|
2364
|
-
* Normalize named route object / string paths into
|
2365
|
-
* a string.
|
2366
|
-
*
|
2367
|
-
* @param {Object|String|Number} path
|
2368
|
-
* @return {String}
|
2369
|
-
*/
|
2370
|
-
|
2371
|
-
Router.prototype.stringifyPath = function stringifyPath(path) {
|
2372
|
-
var generatedPath = '';
|
2373
|
-
if (path && typeof path === 'object') {
|
2374
|
-
if (path.name) {
|
2375
|
-
var extend = Vue.util.extend;
|
2376
|
-
var currentParams = this._currentTransition && this._currentTransition.to.params;
|
2377
|
-
var targetParams = path.params || {};
|
2378
|
-
var params = currentParams ? extend(extend({}, currentParams), targetParams) : targetParams;
|
2379
|
-
generatedPath = encodeURI(this._recognizer.generate(path.name, params));
|
2380
|
-
} else if (path.path) {
|
2381
|
-
generatedPath = encodeURI(path.path);
|
2382
|
-
}
|
2383
|
-
if (path.query) {
|
2384
|
-
// note: the generated query string is pre-URL-encoded by the recognizer
|
2385
|
-
var query = this._recognizer.generateQueryString(path.query);
|
2386
|
-
if (generatedPath.indexOf('?') > -1) {
|
2387
|
-
generatedPath += '&' + query.slice(1);
|
2388
|
-
} else {
|
2389
|
-
generatedPath += query;
|
2390
|
-
}
|
2391
|
-
}
|
2392
|
-
} else {
|
2393
|
-
generatedPath = encodeURI(path ? path + '' : '');
|
2394
|
-
}
|
2395
|
-
return generatedPath;
|
2396
|
-
};
|
2397
|
-
|
2398
|
-
// Internal methods ======================================
|
2399
|
-
|
2400
|
-
/**
|
2401
|
-
* Add a route containing a list of segments to the internal
|
2402
|
-
* route recognizer. Will be called recursively to add all
|
2403
|
-
* possible sub-routes.
|
2404
|
-
*
|
2405
|
-
* @param {String} path
|
2406
|
-
* @param {Object} handler
|
2407
|
-
* @param {Array} segments
|
2408
|
-
*/
|
2409
|
-
|
2410
|
-
Router.prototype._addRoute = function _addRoute(path, handler, segments) {
|
2411
|
-
guardComponent(path, handler);
|
2412
|
-
handler.path = path;
|
2413
|
-
handler.fullPath = (segments.reduce(function (path, segment) {
|
2414
|
-
return path + segment.path;
|
2415
|
-
}, '') + path).replace('//', '/');
|
2416
|
-
segments.push({
|
2417
|
-
path: path,
|
2418
|
-
handler: handler
|
2419
|
-
});
|
2420
|
-
this._recognizer.add(segments, {
|
2421
|
-
as: handler.name
|
2422
|
-
});
|
2423
|
-
// add sub routes
|
2424
|
-
if (handler.subRoutes) {
|
2425
|
-
for (var subPath in handler.subRoutes) {
|
2426
|
-
// recursively walk all sub routes
|
2427
|
-
this._addRoute(subPath, handler.subRoutes[subPath],
|
2428
|
-
// pass a copy in recursion to avoid mutating
|
2429
|
-
// across branches
|
2430
|
-
segments.slice());
|
2431
|
-
}
|
2432
|
-
}
|
2433
|
-
};
|
2434
|
-
|
2435
|
-
/**
|
2436
|
-
* Set the notFound route handler.
|
2437
|
-
*
|
2438
|
-
* @param {Object} handler
|
2439
|
-
*/
|
2440
|
-
|
2441
|
-
Router.prototype._notFound = function _notFound(handler) {
|
2442
|
-
guardComponent('*', handler);
|
2443
|
-
this._notFoundHandler = [{ handler: handler }];
|
2444
|
-
};
|
2445
|
-
|
2446
|
-
/**
|
2447
|
-
* Add a redirect record.
|
2448
|
-
*
|
2449
|
-
* @param {String} path
|
2450
|
-
* @param {String} redirectPath
|
2451
|
-
*/
|
2452
|
-
|
2453
|
-
Router.prototype._addRedirect = function _addRedirect(path, redirectPath) {
|
2454
|
-
if (path === '*') {
|
2455
|
-
this._notFoundRedirect = redirectPath;
|
2456
|
-
} else {
|
2457
|
-
this._addGuard(path, redirectPath, this.replace);
|
2458
|
-
}
|
2459
|
-
};
|
2460
|
-
|
2461
|
-
/**
|
2462
|
-
* Add an alias record.
|
2463
|
-
*
|
2464
|
-
* @param {String} path
|
2465
|
-
* @param {String} aliasPath
|
2466
|
-
*/
|
2467
|
-
|
2468
|
-
Router.prototype._addAlias = function _addAlias(path, aliasPath) {
|
2469
|
-
this._addGuard(path, aliasPath, this._match);
|
2470
|
-
};
|
2471
|
-
|
2472
|
-
/**
|
2473
|
-
* Add a path guard.
|
2474
|
-
*
|
2475
|
-
* @param {String} path
|
2476
|
-
* @param {String} mappedPath
|
2477
|
-
* @param {Function} handler
|
2478
|
-
*/
|
2479
|
-
|
2480
|
-
Router.prototype._addGuard = function _addGuard(path, mappedPath, _handler) {
|
2481
|
-
var _this2 = this;
|
2482
|
-
|
2483
|
-
this._guardRecognizer.add([{
|
2484
|
-
path: path,
|
2485
|
-
handler: function handler(match, query) {
|
2486
|
-
var realPath = mapParams(mappedPath, match.params, query);
|
2487
|
-
_handler.call(_this2, realPath);
|
2488
|
-
}
|
2489
|
-
}]);
|
2490
|
-
};
|
2491
|
-
|
2492
|
-
/**
|
2493
|
-
* Check if a path matches any redirect records.
|
2494
|
-
*
|
2495
|
-
* @param {String} path
|
2496
|
-
* @return {Boolean} - if true, will skip normal match.
|
2497
|
-
*/
|
2498
|
-
|
2499
|
-
Router.prototype._checkGuard = function _checkGuard(path) {
|
2500
|
-
var matched = this._guardRecognizer.recognize(path, true);
|
2501
|
-
if (matched) {
|
2502
|
-
matched[0].handler(matched[0], matched.queryParams);
|
2503
|
-
return true;
|
2504
|
-
} else if (this._notFoundRedirect) {
|
2505
|
-
matched = this._recognizer.recognize(path);
|
2506
|
-
if (!matched) {
|
2507
|
-
this.replace(this._notFoundRedirect);
|
2508
|
-
return true;
|
2509
|
-
}
|
2510
|
-
}
|
2511
|
-
};
|
2512
|
-
|
2513
|
-
/**
|
2514
|
-
* Match a URL path and set the route context on vm,
|
2515
|
-
* triggering view updates.
|
2516
|
-
*
|
2517
|
-
* @param {String} path
|
2518
|
-
* @param {Object} [state]
|
2519
|
-
* @param {String} [anchor]
|
2520
|
-
*/
|
2521
|
-
|
2522
|
-
Router.prototype._match = function _match(path, state, anchor) {
|
2523
|
-
var _this3 = this;
|
2524
|
-
|
2525
|
-
if (this._checkGuard(path)) {
|
2526
|
-
return;
|
2527
|
-
}
|
1731
|
+
this.app = null
|
1732
|
+
this.options = options
|
1733
|
+
this.beforeHooks = []
|
1734
|
+
this.afterHooks = []
|
1735
|
+
this.match = createMatcher(options.routes || [])
|
2528
1736
|
|
2529
|
-
|
2530
|
-
|
2531
|
-
|
2532
|
-
|
2533
|
-
|
2534
|
-
|
2535
|
-
|
2536
|
-
|
2537
|
-
|
2538
|
-
|
2539
|
-
|
2540
|
-
|
2541
|
-
|
2542
|
-
|
2543
|
-
|
2544
|
-
|
2545
|
-
|
2546
|
-
|
2547
|
-
|
1737
|
+
var mode = options.mode || 'hash'
|
1738
|
+
this.fallback = mode === 'history' && !supportsHistory
|
1739
|
+
if (this.fallback) {
|
1740
|
+
mode = 'hash'
|
1741
|
+
}
|
1742
|
+
if (!inBrowser) {
|
1743
|
+
mode = 'abstract'
|
1744
|
+
}
|
1745
|
+
this.mode = mode
|
1746
|
+
};
|
1747
|
+
|
1748
|
+
var prototypeAccessors = { currentRoute: {} };
|
1749
|
+
|
1750
|
+
prototypeAccessors.currentRoute.get = function () {
|
1751
|
+
return this.history && this.history.current
|
1752
|
+
};
|
1753
|
+
|
1754
|
+
VueRouter.prototype.init = function init (app /* Vue component instance */) {
|
1755
|
+
var this$1 = this;
|
1756
|
+
|
1757
|
+
assert(
|
1758
|
+
install.installed,
|
1759
|
+
"not installed. Make sure to call `Vue.use(VueRouter)` " +
|
1760
|
+
"before creating root instance."
|
1761
|
+
)
|
1762
|
+
|
1763
|
+
this.app = app
|
1764
|
+
|
1765
|
+
var ref = this;
|
1766
|
+
var mode = ref.mode;
|
1767
|
+
var options = ref.options;
|
1768
|
+
var fallback = ref.fallback;
|
1769
|
+
switch (mode) {
|
1770
|
+
case 'history':
|
1771
|
+
this.history = new HTML5History(this, options.base)
|
1772
|
+
break
|
1773
|
+
case 'hash':
|
1774
|
+
this.history = new HashHistory(this, options.base, fallback)
|
1775
|
+
break
|
1776
|
+
case 'abstract':
|
1777
|
+
this.history = new AbstractHistory(this)
|
1778
|
+
break
|
1779
|
+
default:
|
1780
|
+
assert(false, ("invalid mode: " + mode))
|
1781
|
+
}
|
2548
1782
|
|
2549
|
-
|
2550
|
-
|
2551
|
-
|
2552
|
-
|
2553
|
-
// current transition is updated right now.
|
2554
|
-
// however, current route will only be updated after the transition has
|
2555
|
-
// been validated.
|
2556
|
-
this._prevTransition = currentTransition;
|
2557
|
-
this._currentTransition = transition;
|
2558
|
-
|
2559
|
-
if (!this.app) {
|
2560
|
-
(function () {
|
2561
|
-
// initial render
|
2562
|
-
var router = _this3;
|
2563
|
-
_this3.app = new _this3._appConstructor({
|
2564
|
-
el: _this3._appContainer,
|
2565
|
-
created: function created() {
|
2566
|
-
this.$router = router;
|
2567
|
-
},
|
2568
|
-
_meta: {
|
2569
|
-
$route: route
|
2570
|
-
}
|
2571
|
-
});
|
2572
|
-
})();
|
2573
|
-
}
|
1783
|
+
this.history.listen(function (route) {
|
1784
|
+
this$1.app._route = route
|
1785
|
+
})
|
1786
|
+
};
|
2574
1787
|
|
2575
|
-
|
2576
|
-
|
2577
|
-
|
2578
|
-
transition.start(function () {
|
2579
|
-
_this3._postTransition(route, state, anchor);
|
2580
|
-
});
|
2581
|
-
};
|
2582
|
-
|
2583
|
-
if (beforeHooks.length) {
|
2584
|
-
transition.runQueue(beforeHooks, function (hook, _, next) {
|
2585
|
-
if (transition === _this3._currentTransition) {
|
2586
|
-
transition.callHook(hook, null, next, {
|
2587
|
-
expectBoolean: true
|
2588
|
-
});
|
2589
|
-
}
|
2590
|
-
}, startTransition);
|
2591
|
-
} else {
|
2592
|
-
startTransition();
|
2593
|
-
}
|
1788
|
+
VueRouter.prototype.beforeEach = function beforeEach (fn) {
|
1789
|
+
this.beforeHooks.push(fn)
|
1790
|
+
};
|
2594
1791
|
|
2595
|
-
|
2596
|
-
|
2597
|
-
|
1792
|
+
VueRouter.prototype.afterEach = function afterEach (fn) {
|
1793
|
+
this.afterHooks.push(fn)
|
1794
|
+
};
|
2598
1795
|
|
2599
|
-
|
2600
|
-
|
2601
|
-
|
2602
|
-
// whether it is the initial render.
|
2603
|
-
this._rendered = true;
|
2604
|
-
};
|
2605
|
-
|
2606
|
-
/**
|
2607
|
-
* Set current to the new transition.
|
2608
|
-
* This is called by the transition object when the
|
2609
|
-
* validation of a route has succeeded.
|
2610
|
-
*
|
2611
|
-
* @param {Transition} transition
|
2612
|
-
*/
|
2613
|
-
|
2614
|
-
Router.prototype._onTransitionValidated = function _onTransitionValidated(transition) {
|
2615
|
-
// set current route
|
2616
|
-
var route = this._currentRoute = transition.to;
|
2617
|
-
// update route context for all children
|
2618
|
-
if (this.app.$route !== route) {
|
2619
|
-
this.app.$route = route;
|
2620
|
-
this._children.forEach(function (child) {
|
2621
|
-
child.$route = route;
|
2622
|
-
});
|
2623
|
-
}
|
2624
|
-
// call global after hook
|
2625
|
-
if (this._afterEachHooks.length) {
|
2626
|
-
this._afterEachHooks.forEach(function (hook) {
|
2627
|
-
return hook.call(null, {
|
2628
|
-
to: transition.to,
|
2629
|
-
from: transition.from
|
2630
|
-
});
|
2631
|
-
});
|
2632
|
-
}
|
2633
|
-
this._currentTransition.done = true;
|
2634
|
-
};
|
2635
|
-
|
2636
|
-
/**
|
2637
|
-
* Handle stuff after the transition.
|
2638
|
-
*
|
2639
|
-
* @param {Route} route
|
2640
|
-
* @param {Object} [state]
|
2641
|
-
* @param {String} [anchor]
|
2642
|
-
*/
|
2643
|
-
|
2644
|
-
Router.prototype._postTransition = function _postTransition(route, state, anchor) {
|
2645
|
-
// handle scroll positions
|
2646
|
-
// saved scroll positions take priority
|
2647
|
-
// then we check if the path has an anchor
|
2648
|
-
var pos = state && state.pos;
|
2649
|
-
if (pos && this._saveScrollPosition) {
|
2650
|
-
Vue.nextTick(function () {
|
2651
|
-
window.scrollTo(pos.x, pos.y);
|
2652
|
-
});
|
2653
|
-
} else if (anchor) {
|
2654
|
-
Vue.nextTick(function () {
|
2655
|
-
var el = document.getElementById(anchor.slice(1));
|
2656
|
-
if (el) {
|
2657
|
-
window.scrollTo(window.scrollX, el.offsetTop);
|
2658
|
-
}
|
2659
|
-
});
|
2660
|
-
}
|
2661
|
-
};
|
1796
|
+
VueRouter.prototype.push = function push (location) {
|
1797
|
+
this.history.push(location)
|
1798
|
+
};
|
2662
1799
|
|
2663
|
-
|
2664
|
-
|
1800
|
+
VueRouter.prototype.replace = function replace (location) {
|
1801
|
+
this.history.replace(location)
|
1802
|
+
};
|
2665
1803
|
|
2666
|
-
|
2667
|
-
|
2668
|
-
|
2669
|
-
comp = handler.component = Vue.extend(comp);
|
2670
|
-
}
|
2671
|
-
/* istanbul ignore if */
|
2672
|
-
if (typeof comp !== 'function') {
|
2673
|
-
handler.component = null;
|
2674
|
-
warn$1('invalid component for route "' + path + '".');
|
2675
|
-
}
|
2676
|
-
}
|
1804
|
+
VueRouter.prototype.go = function go (n) {
|
1805
|
+
this.history.go(n)
|
1806
|
+
};
|
2677
1807
|
|
2678
|
-
|
1808
|
+
VueRouter.prototype.back = function back () {
|
1809
|
+
this.go(-1)
|
1810
|
+
};
|
2679
1811
|
|
2680
|
-
|
1812
|
+
VueRouter.prototype.forward = function forward () {
|
1813
|
+
this.go(1)
|
1814
|
+
};
|
2681
1815
|
|
2682
|
-
|
2683
|
-
|
2684
|
-
|
2685
|
-
|
1816
|
+
VueRouter.prototype.getMatchedComponents = function getMatchedComponents () {
|
1817
|
+
if (!this.currentRoute) {
|
1818
|
+
return []
|
1819
|
+
}
|
1820
|
+
return [].concat.apply([], this.currentRoute.matched.map(function (m) {
|
1821
|
+
return Object.keys(m.components).map(function (key) {
|
1822
|
+
return m.components[key]
|
1823
|
+
})
|
1824
|
+
}))
|
1825
|
+
};
|
2686
1826
|
|
2687
|
-
|
2688
|
-
/* istanbul ignore if */
|
2689
|
-
if (Router.installed) {
|
2690
|
-
warn$1('already installed.');
|
2691
|
-
return;
|
2692
|
-
}
|
2693
|
-
Vue = externalVue;
|
2694
|
-
applyOverride(Vue);
|
2695
|
-
View(Vue);
|
2696
|
-
Link(Vue);
|
2697
|
-
exports$1.Vue = Vue;
|
2698
|
-
Router.installed = true;
|
2699
|
-
};
|
1827
|
+
Object.defineProperties( VueRouter.prototype, prototypeAccessors );
|
2700
1828
|
|
2701
|
-
|
2702
|
-
|
2703
|
-
|
2704
|
-
|
2705
|
-
|
1829
|
+
VueRouter.install = install
|
1830
|
+
|
1831
|
+
if (inBrowser && window.Vue) {
|
1832
|
+
window.Vue.use(VueRouter)
|
1833
|
+
}
|
2706
1834
|
|
2707
|
-
|
1835
|
+
return VueRouter;
|
2708
1836
|
|
2709
|
-
}));
|
1837
|
+
})));
|