vue-rails 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 61f65e26d38612013d7699898c3971a32c35a274
4
+ data.tar.gz: 078a81995f3701e0c0da23a56f4c8b5d61d6e97d
5
+ SHA512:
6
+ metadata.gz: 37adf5af8a236db647fa6b2b5e02d1e91b42d9aa7ca454fdfd45027d9812ae748a2ecd073e7d88026e6032b8c31745b869fc5d3d675d4eb5511cd41d0769215c
7
+ data.tar.gz: 7cbedbb142186debffad0bcd7c36b336e1b811a1e451474916d6f7a95894872848a40b9d2f53c302ad68024ca30798a80de2304f8c225ab10ddb3bb78a8ee64d
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in vue-rails.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Marshall Shen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,21 @@
1
+ # vue-rails
2
+
3
+ ## About
4
+
5
+ Rails 4+ asset-pipeline gem to provide vue.js
6
+
7
+ ## Versions
8
+
9
+ - vue v2.0.1
10
+ - vue-router v2.0.0
11
+
12
+ ## Setup
13
+
14
+ Have in your Gemfile:
15
+
16
+ gem 'vue-rails'
17
+
18
+ And in your application.js manifest:
19
+
20
+ //= require vue
21
+ //= require vue-router (optional)
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
@@ -0,0 +1,10 @@
1
+ require "vuejs-rails/version"
2
+
3
+ module Vue
4
+ module Rails
5
+ if defined?(::Rails) and Gem::Requirement.new('>= 4.0').satisfied_by?(Gem::Version.new ::Rails.version)
6
+ class Rails::Engine < ::Rails::Engine
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ module Vue
2
+ module Rails
3
+ VERSION = '2.0.1'
4
+ end
5
+ end
@@ -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
+ })));