vuejs 1.0.27 → 1.0.28

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1837 @@
1
+ /**
2
+ * vue-router v2.0.0
3
+ * (c) 2016 Evan You
4
+ * @license MIT
5
+ */
6
+ (function (global, factory) {
7
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
8
+ typeof define === 'function' && define.amd ? define(factory) :
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'
19
+ }
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;
26
+
27
+ data.routerView = true
28
+
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
40
+ }
41
+ parent = parent.$parent
42
+ }
43
+
44
+ data.routerViewDepth = depth
45
+ var matched = route.matched[depth]
46
+ if (!matched) {
47
+ return h()
48
+ }
49
+
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
57
+ }
58
+ }
59
+
60
+ return h(component, data, children)
61
+ }
62
+ }
63
+
64
+ /* */
65
+
66
+ function resolvePath (
67
+ relative,
68
+ base,
69
+ append
70
+ ) {
71
+ if (relative.charAt(0) === '/') {
72
+ return relative
73
+ }
74
+
75
+ if (relative.charAt(0) === '?' || relative.charAt(0) === '#') {
76
+ return base + relative
77
+ }
78
+
79
+ var stack = base.split('/')
80
+
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()
86
+ }
87
+
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)
98
+ }
99
+ }
100
+
101
+ // ensure leading slash
102
+ if (stack[0] !== '') {
103
+ stack.unshift('')
104
+ }
105
+
106
+ return stack.join('/')
107
+ }
108
+
109
+ function parsePath (path) {
110
+ var hash = ''
111
+ var query = ''
112
+
113
+ var hashIndex = path.indexOf('#')
114
+ if (hashIndex >= 0) {
115
+ hash = path.slice(hashIndex)
116
+ path = path.slice(0, hashIndex)
117
+ }
118
+
119
+ var queryIndex = path.indexOf('?')
120
+ if (queryIndex >= 0) {
121
+ query = path.slice(queryIndex + 1)
122
+ path = path.slice(0, queryIndex)
123
+ }
124
+
125
+ return {
126
+ path: path,
127
+ query: query,
128
+ hash: hash
129
+ }
130
+ }
131
+
132
+ function cleanPath (path) {
133
+ return path.replace(/\/\//g, '/')
134
+ }
135
+
136
+ /* */
137
+
138
+ function assert (condition, message) {
139
+ if (!condition) {
140
+ throw new Error(("[vue-router] " + message))
141
+ }
142
+ }
143
+
144
+ function warn (condition, message) {
145
+ if (!condition) {
146
+ typeof console !== 'undefined' && console.warn(("[vue-router] " + message))
147
+ }
148
+ }
149
+
150
+ /* */
151
+
152
+ var encode = encodeURIComponent
153
+ var decode = decodeURIComponent
154
+
155
+ function resolveQuery (
156
+ query,
157
+ extraQuery
158
+ ) {
159
+ if ( extraQuery === void 0 ) extraQuery = {};
160
+
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
+
178
+ function parseQuery (query) {
179
+ var res = Object.create(null)
180
+
181
+ query = query.trim().replace(/^(\?|#|&)/, '')
182
+
183
+ if (!query) {
184
+ return res
185
+ }
186
+
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]
200
+ }
201
+ })
202
+
203
+ return res
204
+ }
205
+
206
+ function stringifyQuery (obj) {
207
+ var res = obj ? Object.keys(obj).sort().map(function (key) {
208
+ var val = obj[key]
209
+
210
+ if (val === undefined) {
211
+ return ''
212
+ }
213
+
214
+ if (val === null) {
215
+ return encode(key)
216
+ }
217
+
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('&')
231
+ }
232
+
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
+ }
306
+
307
+ function isObjectEqual (a, b) {
308
+ if ( a === void 0 ) a = {};
309
+ if ( b === void 0 ) b = {};
310
+
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
346
+ }
347
+
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
357
+ }
358
+
359
+ return {
360
+ _normalized: true,
361
+ path: path,
362
+ query: query,
363
+ hash: hash
364
+ }
365
+ }
366
+
367
+ /* */
368
+
369
+ // work around weird flow bug
370
+ var toTypes = [String, Object]
371
+
372
+ var Link = {
373
+ name: 'router-link',
374
+ props: {
375
+ to: {
376
+ type: toTypes,
377
+ required: true
378
+ },
379
+ tag: {
380
+ type: String,
381
+ default: 'a'
382
+ },
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)
412
+ }
413
+ }
414
+ }
415
+
416
+ var data = {
417
+ class: classes
418
+ }
419
+
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
+ }
432
+ }
433
+
434
+ return h(this.tag, data, this.$slots.default)
435
+ }
436
+ }
437
+
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
+ }
450
+ }
451
+ }
452
+
453
+ function install (Vue) {
454
+ if (install.installed) { return }
455
+ install.installed = true
456
+
457
+ Object.defineProperty(Vue.prototype, '$router', {
458
+ get: function get () { return this.$root._router }
459
+ })
460
+
461
+ Object.defineProperty(Vue.prototype, '$route', {
462
+ get: function get$1 () { return this.$root._route }
463
+ })
464
+
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
+ }
472
+ }
473
+ })
474
+
475
+ Vue.component('router-view', View)
476
+ Vue.component('router-link', Link)
477
+ }
478
+
479
+ var __moduleExports = Array.isArray || function (arr) {
480
+ return Object.prototype.toString.call(arr) == '[object Array]';
481
+ };
482
+
483
+ var isarray = __moduleExports
484
+
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
536
+ }
537
+
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
+ }
551
+
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
+ }
569
+
570
+ // Match any characters still remaining.
571
+ if (index < str.length) {
572
+ path += str.substr(index)
573
+ }
574
+
575
+ // If the path exists, push it onto the end.
576
+ if (path) {
577
+ tokens.push(path)
578
+ }
579
+
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
+ }
629
+ }
630
+
631
+ return function (obj, opts) {
632
+ var path = ''
633
+ var data = obj || {}
634
+ var options = opts || {}
635
+ var encode = options.pretty ? encodeURIComponentPretty : encodeURIComponent
636
+
637
+ for (var i = 0; i < tokens.length; i++) {
638
+ var token = tokens[i]
639
+
640
+ if (typeof token === 'string') {
641
+ path += token
642
+
643
+ continue
644
+ }
645
+
646
+ var value = data[token.name]
647
+ var segment
648
+
649
+ if (value == null) {
650
+ if (token.optional) {
651
+ // Prepend partial segment prefixes.
652
+ if (token.partial) {
653
+ path += token.prefix
654
+ }
655
+
656
+ continue
657
+ } else {
658
+ throw new TypeError('Expected "' + token.name + '" to be defined')
659
+ }
660
+ }
661
+
662
+ if (isarray(value)) {
663
+ if (!token.repeat) {
664
+ throw new TypeError('Expected "' + token.name + '" to not repeat, but received `' + JSON.stringify(value) + '`')
665
+ }
666
+
667
+ if (value.length === 0) {
668
+ if (token.optional) {
669
+ continue
670
+ } else {
671
+ throw new TypeError('Expected "' + token.name + '" to not be empty')
672
+ }
673
+ }
674
+
675
+ for (var j = 0; j < value.length; j++) {
676
+ segment = encode(value[j])
677
+
678
+ if (!matches[i].test(segment)) {
679
+ throw new TypeError('Expected all "' + token.name + '" to match "' + token.pattern + '", but received `' + JSON.stringify(segment) + '`')
680
+ }
681
+
682
+ path += (j === 0 ? token.prefix : token.delimiter) + segment
683
+ }
684
+
685
+ continue
686
+ }
687
+
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 + '"')
692
+ }
693
+
694
+ path += token.prefix + segment
695
+ }
696
+
697
+ return path
698
+ }
699
+ }
700
+
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
+ }
768
+
769
+ return attachKeys(path, keys)
770
+ }
771
+
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 = []
782
+
783
+ for (var i = 0; i < path.length; i++) {
784
+ parts.push(pathToRegexp(path[i], keys, options).source)
785
+ }
786
+
787
+ var regexp = new RegExp('(?:' + parts.join('|') + ')', flags(options))
788
+
789
+ return attachKeys(regexp, keys)
790
+ }
791
+
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
+ }
810
+
811
+ return attachKeys(re, keys)
812
+ }
813
+
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 || {}
823
+
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)
829
+
830
+ // Iterate over the tokens and create our regexp string.
831
+ for (var i = 0; i < tokens.length; i++) {
832
+ var token = tokens[i]
833
+
834
+ if (typeof token === 'string') {
835
+ route += escapeString(token)
836
+ } else {
837
+ var prefix = escapeString(token.prefix)
838
+ var capture = '(?:' + token.pattern + ')'
839
+
840
+ if (token.repeat) {
841
+ capture += '(?:' + prefix + capture + ')*'
842
+ }
843
+
844
+ if (token.optional) {
845
+ if (!token.partial) {
846
+ capture = '(?:' + prefix + '(' + capture + '))?'
847
+ } else {
848
+ capture = prefix + '(' + capture + ')?'
849
+ }
850
+ } else {
851
+ capture = prefix + '(' + capture + ')'
852
+ }
853
+
854
+ route += capture
855
+ }
856
+ }
857
+
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
+ }
865
+
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
+ }
873
+
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
+ }
898
+
899
+ if (path instanceof RegExp) {
900
+ return regexpToRegexp(path, /** @type {!Array} */ (keys))
901
+ }
902
+
903
+ if (isarray(path)) {
904
+ return arrayToRegexp(/** @type {!Array} */ (path), /** @type {!Array} */ (keys), options)
905
+ }
906
+
907
+ return stringToRegexp(/** @type {string} */ (path), /** @type {!Array} */ (keys), options)
908
+ }
909
+
910
+ index.parse = parse_1;
911
+ index.compile = compile_1;
912
+ index.tokensToFunction = tokensToFunction_1;
913
+ index.tokensToRegExp = tokensToRegExp_1;
914
+
915
+ /* */
916
+
917
+ function createRouteMap (routes) {
918
+ var pathMap = Object.create(null)
919
+ var nameMap = Object.create(null)
920
+
921
+ routes.forEach(function (route) {
922
+ addRouteRecord(pathMap, nameMap, route)
923
+ })
924
+
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
+ }
953
+
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
+ }
963
+
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)
971
+ }
972
+ }
973
+
974
+ pathMap[record.path] = record
975
+ if (name) { nameMap[name] = record }
976
+ }
977
+
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
+ }
984
+
985
+ /* */
986
+
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
+ }
1017
+ }
1018
+ // no match
1019
+ return _createRoute(null, location)
1020
+ }
1021
+
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 }
1033
+ }
1034
+
1035
+ if (!redirect || typeof redirect !== 'object') {
1036
+ warn(false, ("invalid redirect option: " + (JSON.stringify(redirect))))
1037
+ return _createRoute(null, location)
1038
+ }
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)
1076
+ }
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)
1094
+ }
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)
1105
+ }
1106
+ if (record && record.matchAs) {
1107
+ return alias(record, location, record.matchAs)
1108
+ }
1109
+ return createRoute(record, location, redirectedFrom)
1110
+ }
1111
+
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)
1131
+
1132
+ if (!m) {
1133
+ return false
1134
+ } else if (!params) {
1135
+ return true
1136
+ }
1137
+
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
+ }
1143
+
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
+ }
1162
+
1163
+ function resolveRecordPath (path, record) {
1164
+ return resolvePath(path, record.parent ? record.parent.path : '/', true)
1165
+ }
1166
+
1167
+ /* */
1168
+
1169
+ var inBrowser = typeof window !== 'undefined'
1170
+
1171
+ var supportsHistory = inBrowser && (function () {
1172
+ var ua = window.navigator.userAgent
1173
+
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
+ }
1182
+
1183
+ return window.history && 'pushState' in window.history
1184
+ })()
1185
+
1186
+ /* */
1187
+
1188
+ function runQueue (queue, fn, cb) {
1189
+ var step = function (index) {
1190
+ if (index >= queue.length) {
1191
+ cb()
1192
+ } else {
1193
+ if (queue[index]) {
1194
+ fn(queue[index], function () {
1195
+ step(index + 1)
1196
+ })
1197
+ } else {
1198
+ step(index + 1)
1199
+ }
1200
+ }
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
+ }
1239
+
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)
1265
+ } else {
1266
+ // confirm transition and pass on the value
1267
+ next(to)
1268
+ }
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') : '/'
1303
+ } else {
1304
+ base = '/'
1305
+ }
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
+ }
1331
+
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)
1338
+ }
1339
+ }
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
+ })
1356
+ }
1357
+ }
1358
+ })
1359
+ }
1360
+
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()
1373
+ }
1374
+
1375
+ var reject = function (reason) {
1376
+ warn(false, ("Failed to resolve async component " + key + ": " + reason))
1377
+ next(false)
1378
+ }
1379
+
1380
+ var res = def(resolve, reject)
1381
+ if (res && typeof res.then === 'function') {
1382
+ res.then(resolve, reject)
1383
+ }
1384
+ }
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
1423
+ }
1424
+ }
1425
+
1426
+ function isValidPosition (obj) {
1427
+ return isNumber(obj.x) || isNumber(obj.y)
1428
+ }
1429
+
1430
+ function normalizePosition (obj) {
1431
+ return {
1432
+ x: isNumber(obj.x) ? obj.x : window.pageXOffset,
1433
+ y: isNumber(obj.y) ? obj.y : window.pageYOffset
1434
+ }
1435
+ }
1436
+
1437
+ function isNumber (v) {
1438
+ return typeof v === 'number'
1439
+ }
1440
+
1441
+ /* */
1442
+
1443
+
1444
+ var genKey = function () { return String(Date.now()); }
1445
+ var _key = genKey()
1446
+
1447
+ var HTML5History = (function (History) {
1448
+ function HTML5History (router, base) {
1449
+ var this$1 = this;
1450
+
1451
+ History.call(this, router, base)
1452
+
1453
+ this.transitionTo(getLocation(this.base))
1454
+
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
+ })
1465
+
1466
+ if (expectScroll) {
1467
+ window.addEventListener('scroll', function () {
1468
+ saveScrollPosition(_key)
1469
+ })
1470
+ }
1471
+ }
1472
+
1473
+ if ( History ) HTML5History.__proto__ = History;
1474
+ HTML5History.prototype = Object.create( History && History.prototype );
1475
+ HTML5History.prototype.constructor = HTML5History;
1476
+
1477
+ HTML5History.prototype.go = function go (n) {
1478
+ window.history.go(n)
1479
+ };
1480
+
1481
+ HTML5History.prototype.push = function push (location) {
1482
+ var this$1 = this;
1483
+
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
+ };
1490
+
1491
+ HTML5History.prototype.replace = function replace (location) {
1492
+ var this$1 = this;
1493
+
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))
1504
+ }
1505
+ };
1506
+
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)
1533
+ }
1534
+ } else if (isObject && isValidPosition(shouldScroll)) {
1535
+ position = normalizePosition(shouldScroll)
1536
+ }
1537
+
1538
+ if (position) {
1539
+ window.scrollTo(position.x, position.y)
1540
+ }
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)
1565
+ }
1566
+ saveScrollPosition(_key)
1567
+ } catch (e) {
1568
+ window.location[replace ? 'assign' : 'replace'](url)
1569
+ }
1570
+ }
1571
+
1572
+ function replaceState (url) {
1573
+ pushState(url, true)
1574
+ }
1575
+
1576
+ /* */
1577
+
1578
+
1579
+ var HashHistory = (function (History) {
1580
+ function HashHistory (router, base, fallback) {
1581
+ var this$1 = this;
1582
+
1583
+ History.call(this, router, base)
1584
+
1585
+ // check history fallback deeplinking
1586
+ if (fallback && this.checkFallback()) {
1587
+ return
1588
+ }
1589
+
1590
+ ensureSlash()
1591
+ this.transitionTo(getHash())
1592
+
1593
+ window.addEventListener('hashchange', function () {
1594
+ this$1.onHashChange()
1595
+ })
1596
+ }
1597
+
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
+ };
1611
+
1612
+ HashHistory.prototype.onHashChange = function onHashChange () {
1613
+ if (!ensureSlash()) {
1614
+ return
1615
+ }
1616
+ this.transitionTo(getHash(), function (route) {
1617
+ replaceHash(route.fullPath)
1618
+ })
1619
+ };
1620
+
1621
+ HashHistory.prototype.push = function push (location) {
1622
+ History.prototype.transitionTo.call(this, location, function (route) {
1623
+ pushHash(route.fullPath)
1624
+ })
1625
+ };
1626
+
1627
+ HashHistory.prototype.replace = function replace (location) {
1628
+ History.prototype.transitionTo.call(this, location, function (route) {
1629
+ replaceHash(route.fullPath)
1630
+ })
1631
+ };
1632
+
1633
+ HashHistory.prototype.go = function go (n) {
1634
+ window.history.go(n)
1635
+ };
1636
+
1637
+ HashHistory.prototype.ensureURL = function ensureURL () {
1638
+ if (getHash() !== this.current.fullPath) {
1639
+ replaceHash(this.current.fullPath)
1640
+ }
1641
+ };
1642
+
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
1682
+ }
1683
+
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
+ })
1695
+ };
1696
+
1697
+ AbstractHistory.prototype.replace = function replace (location) {
1698
+ var this$1 = this;
1699
+
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;
1707
+
1708
+ var targetIndex = this.index + n
1709
+ if (targetIndex < 0 || targetIndex >= this.stack.length) {
1710
+ return
1711
+ }
1712
+ var location = this.stack[targetIndex]
1713
+ this.confirmTransition(location, function () {
1714
+ this$1.index = targetIndex
1715
+ this$1.updateRoute(location)
1716
+ })
1717
+ };
1718
+
1719
+ AbstractHistory.prototype.ensureURL = function ensureURL () {
1720
+ // noop
1721
+ };
1722
+
1723
+ return AbstractHistory;
1724
+ }(History));
1725
+
1726
+ /* */
1727
+
1728
+ var VueRouter = function VueRouter (options) {
1729
+ if ( options === void 0 ) options = {};
1730
+
1731
+ this.app = null
1732
+ this.options = options
1733
+ this.beforeHooks = []
1734
+ this.afterHooks = []
1735
+ this.match = createMatcher(options.routes || [])
1736
+
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
+ }
1782
+
1783
+ this.history.listen(function (route) {
1784
+ this$1.app._route = route
1785
+ })
1786
+ };
1787
+
1788
+ VueRouter.prototype.beforeEach = function beforeEach (fn) {
1789
+ this.beforeHooks.push(fn)
1790
+ };
1791
+
1792
+ VueRouter.prototype.afterEach = function afterEach (fn) {
1793
+ this.afterHooks.push(fn)
1794
+ };
1795
+
1796
+ VueRouter.prototype.push = function push (location) {
1797
+ this.history.push(location)
1798
+ };
1799
+
1800
+ VueRouter.prototype.replace = function replace (location) {
1801
+ this.history.replace(location)
1802
+ };
1803
+
1804
+ VueRouter.prototype.go = function go (n) {
1805
+ this.history.go(n)
1806
+ };
1807
+
1808
+ VueRouter.prototype.back = function back () {
1809
+ this.go(-1)
1810
+ };
1811
+
1812
+ VueRouter.prototype.forward = function forward () {
1813
+ this.go(1)
1814
+ };
1815
+
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
+ };
1826
+
1827
+ Object.defineProperties( VueRouter.prototype, prototypeAccessors );
1828
+
1829
+ VueRouter.install = install
1830
+
1831
+ if (inBrowser && window.Vue) {
1832
+ window.Vue.use(VueRouter)
1833
+ }
1834
+
1835
+ return VueRouter;
1836
+
1837
+ })));