· 5 years ago · Aug 28, 2020, 08:32 AM
1/*!
2 * vue-router v3.1.6
3 * (c) 2020 Evan You
4 * @license MIT
5 */
6/* */
7
8function assert (condition, message) {
9 if (!condition) {
10 throw new Error(("[vue-router] " + message))
11 }
12}
13
14function warn (condition, message) {
15 if (process.env.NODE_ENV !== 'production' && !condition) {
16 typeof console !== 'undefined' && console.warn(("[vue-router] " + message));
17 }
18}
19
20function isError (err) {
21 return Object.prototype.toString.call(err).indexOf('Error') > -1
22}
23
24function isExtendedError (constructor, err) {
25 return (
26 err instanceof constructor ||
27 // _name is to support IE9 too
28 (err && (err.name === constructor.name || err._name === constructor._name))
29 )
30}
31
32function extend (a, b) {
33 for (var key in b) {
34 a[key] = b[key];
35 }
36 return a
37}
38
39var View = {
40 name: 'RouterView',
41 functional: true,
42 props: {
43 name: {
44 type: String,
45 default: 'default'
46 }
47 },
48 render: function render (_, ref) {
49 var props = ref.props;
50 var children = ref.children;
51 var parent = ref.parent;
52 var data = ref.data;
53
54 // used by devtools to display a router-view badge
55 data.routerView = true;
56
57 // directly use parent context's createElement() function
58 // so that components rendered by router-view can resolve named slots
59 var h = parent.$createElement;
60 var name = props.name;
61 var route = parent.$route;
62 var cache = parent._routerViewCache || (parent._routerViewCache = {});
63
64 // determine current view depth, also check to see if the tree
65 // has been toggled inactive but kept-alive.
66 var depth = 0;
67 var inactive = false;
68 while (parent && parent._routerRoot !== parent) {
69 var vnodeData = parent.$vnode ? parent.$vnode.data : {};
70 if (vnodeData.routerView) {
71 depth++;
72 }
73 if (vnodeData.keepAlive && parent._directInactive && parent._inactive) {
74 inactive = true;
75 }
76 parent = parent.$parent;
77 }
78 data.routerViewDepth = depth;
79
80 // render previous view if the tree is inactive and kept-alive
81 if (inactive) {
82 var cachedData = cache[name];
83 var cachedComponent = cachedData && cachedData.component;
84 if (cachedComponent) {
85 // #2301
86 // pass props
87 if (cachedData.configProps) {
88 fillPropsinData(cachedComponent, data, cachedData.route, cachedData.configProps);
89 }
90 return h(cachedComponent, data, children)
91 } else {
92 // render previous empty view
93 return h()
94 }
95 }
96
97 var matched = route.matched[depth];
98 var component = matched && matched.components[name];
99
100 // render empty node if no matched route or no config component
101 if (!matched || !component) {
102 cache[name] = null;
103 return h()
104 }
105
106 // cache component
107 cache[name] = { component: component };
108
109 // attach instance registration hook
110 // this will be called in the instance's injected lifecycle hooks
111 data.registerRouteInstance = function (vm, val) {
112 // val could be undefined for unregistration
113 var current = matched.instances[name];
114 if (
115 (val && current !== vm) ||
116 (!val && current === vm)
117 ) {
118 matched.instances[name] = val;
119 }
120 }
121
122 // also register instance in prepatch hook
123 // in case the same component instance is reused across different routes
124 ;(data.hook || (data.hook = {})).prepatch = function (_, vnode) {
125 matched.instances[name] = vnode.componentInstance;
126 };
127
128 // register instance in init hook
129 // in case kept-alive component be actived when routes changed
130 data.hook.init = function (vnode) {
131 if (vnode.data.keepAlive &&
132 vnode.componentInstance &&
133 vnode.componentInstance !== matched.instances[name]
134 ) {
135 matched.instances[name] = vnode.componentInstance;
136 }
137 };
138
139 var configProps = matched.props && matched.props[name];
140 // save route and configProps in cachce
141 if (configProps) {
142 extend(cache[name], {
143 route: route,
144 configProps: configProps
145 });
146 fillPropsinData(component, data, route, configProps);
147 }
148
149 return h(component, data, children)
150 }
151};
152
153function fillPropsinData (component, data, route, configProps) {
154 // resolve props
155 var propsToPass = data.props = resolveProps(route, configProps);
156 if (propsToPass) {
157 // clone to prevent mutation
158 propsToPass = data.props = extend({}, propsToPass);
159 // pass non-declared props as attrs
160 var attrs = data.attrs = data.attrs || {};
161 for (var key in propsToPass) {
162 if (!component.props || !(key in component.props)) {
163 attrs[key] = propsToPass[key];
164 delete propsToPass[key];
165 }
166 }
167 }
168}
169
170function resolveProps (route, config) {
171 switch (typeof config) {
172 case 'undefined':
173 return
174 case 'object':
175 return config
176 case 'function':
177 return config(route)
178 case 'boolean':
179 return config ? route.params : undefined
180 default:
181 if (process.env.NODE_ENV !== 'production') {
182 warn(
183 false,
184 "props in \"" + (route.path) + "\" is a " + (typeof config) + ", " +
185 "expecting an object, function or boolean."
186 );
187 }
188 }
189}
190
191/* */
192
193var encodeReserveRE = /[!'()*]/g;
194var encodeReserveReplacer = function (c) { return '%' + c.charCodeAt(0).toString(16); };
195var commaRE = /%2C/g;
196
197// fixed encodeURIComponent which is more conformant to RFC3986:
198// - escapes [!'()*]
199// - preserve commas
200var encode = function (str) { return encodeURIComponent(str)
201 .replace(encodeReserveRE, encodeReserveReplacer)
202 .replace(commaRE, ','); };
203
204var decode = decodeURIComponent;
205
206function resolveQuery (
207 query,
208 extraQuery,
209 _parseQuery
210) {
211 if ( extraQuery === void 0 ) extraQuery = {};
212
213 var parse = _parseQuery || parseQuery;
214 var parsedQuery;
215 try {
216 parsedQuery = parse(query || '');
217 } catch (e) {
218 process.env.NODE_ENV !== 'production' && warn(false, e.message);
219 parsedQuery = {};
220 }
221 for (var key in extraQuery) {
222 parsedQuery[key] = extraQuery[key];
223 }
224 return parsedQuery
225}
226
227function parseQuery (query) {
228 var res = {};
229
230 query = query.trim().replace(/^(\?|#|&)/, '');
231
232 if (!query) {
233 return res
234 }
235
236 query.split('&').forEach(function (param) {
237 var parts = param.replace(/\+/g, ' ').split('=');
238 var key = decode(parts.shift());
239 var val = parts.length > 0
240 ? decode(parts.join('='))
241 : null;
242
243 if (res[key] === undefined) {
244 res[key] = val;
245 } else if (Array.isArray(res[key])) {
246 res[key].push(val);
247 } else {
248 res[key] = [res[key], val];
249 }
250 });
251
252 return res
253}
254
255function stringifyQuery (obj) {
256 var res = obj ? Object.keys(obj).map(function (key) {
257 var val = obj[key];
258
259 if (val === undefined) {
260 return ''
261 }
262
263 if (val === null) {
264 return encode(key)
265 }
266
267 if (Array.isArray(val)) {
268 var result = [];
269 val.forEach(function (val2) {
270 if (val2 === undefined) {
271 return
272 }
273 if (val2 === null) {
274 result.push(encode(key));
275 } else {
276 result.push(encode(key) + '=' + encode(val2));
277 }
278 });
279 return result.join('&')
280 }
281
282 return encode(key) + '=' + encode(val)
283 }).filter(function (x) { return x.length > 0; }).join('&') : null;
284 return res ? ("?" + res) : ''
285}
286
287/* */
288
289var trailingSlashRE = /\/?$/;
290
291function createRoute (
292 record,
293 location,
294 redirectedFrom,
295 router
296) {
297 var stringifyQuery = router && router.options.stringifyQuery;
298
299 var query = location.query || {};
300 try {
301 query = clone(query);
302 } catch (e) {}
303
304 var route = {
305 name: location.name || (record && record.name),
306 meta: (record && record.meta) || {},
307 path: location.path || '/',
308 hash: location.hash || '',
309 query: query,
310 params: location.params || {},
311 fullPath: getFullPath(location, stringifyQuery),
312 matched: record ? formatMatch(record) : []
313 };
314 if (redirectedFrom) {
315 route.redirectedFrom = getFullPath(redirectedFrom, stringifyQuery);
316 }
317 return Object.freeze(route)
318}
319
320function clone (value) {
321 if (Array.isArray(value)) {
322 return value.map(clone)
323 } else if (value && typeof value === 'object') {
324 var res = {};
325 for (var key in value) {
326 res[key] = clone(value[key]);
327 }
328 return res
329 } else {
330 return value
331 }
332}
333
334// the starting route that represents the initial state
335var START = createRoute(null, {
336 path: '/'
337});
338
339function formatMatch (record) {
340 var res = [];
341 while (record) {
342 res.unshift(record);
343 record = record.parent;
344 }
345 return res
346}
347
348function getFullPath (
349 ref,
350 _stringifyQuery
351) {
352 var path = ref.path;
353 var query = ref.query; if ( query === void 0 ) query = {};
354 var hash = ref.hash; if ( hash === void 0 ) hash = '';
355
356 var stringify = _stringifyQuery || stringifyQuery;
357 return (path || '/') + stringify(query) + hash
358}
359
360function isSameRoute (a, b) {
361 if (b === START) {
362 return a === b
363 } else if (!b) {
364 return false
365 } else if (a.path && b.path) {
366 return (
367 a.path.replace(trailingSlashRE, '') === b.path.replace(trailingSlashRE, '') &&
368 a.hash === b.hash &&
369 isObjectEqual(a.query, b.query)
370 )
371 } else if (a.name && b.name) {
372 return (
373 a.name === b.name &&
374 a.hash === b.hash &&
375 isObjectEqual(a.query, b.query) &&
376 isObjectEqual(a.params, b.params)
377 )
378 } else {
379 return false
380 }
381}
382
383function isObjectEqual (a, b) {
384 if ( a === void 0 ) a = {};
385 if ( b === void 0 ) b = {};
386
387 // handle null value #1566
388 if (!a || !b) { return a === b }
389 var aKeys = Object.keys(a);
390 var bKeys = Object.keys(b);
391 if (aKeys.length !== bKeys.length) {
392 return false
393 }
394 return aKeys.every(function (key) {
395 var aVal = a[key];
396 var bVal = b[key];
397 // check nested equality
398 if (typeof aVal === 'object' && typeof bVal === 'object') {
399 return isObjectEqual(aVal, bVal)
400 }
401 return String(aVal) === String(bVal)
402 })
403}
404
405function isIncludedRoute (current, target) {
406 return (
407 current.path.replace(trailingSlashRE, '/').indexOf(
408 target.path.replace(trailingSlashRE, '/')
409 ) === 0 &&
410 (!target.hash || current.hash === target.hash) &&
411 queryIncludes(current.query, target.query)
412 )
413}
414
415function queryIncludes (current, target) {
416 for (var key in target) {
417 if (!(key in current)) {
418 return false
419 }
420 }
421 return true
422}
423
424/* */
425
426function resolvePath (
427 relative,
428 base,
429 append
430) {
431 var firstChar = relative.charAt(0);
432 if (firstChar === '/') {
433 return relative
434 }
435
436 if (firstChar === '?' || firstChar === '#') {
437 return base + relative
438 }
439
440 var stack = base.split('/');
441
442 // remove trailing segment if:
443 // - not appending
444 // - appending to trailing slash (last segment is empty)
445 if (!append || !stack[stack.length - 1]) {
446 stack.pop();
447 }
448
449 // resolve relative path
450 var segments = relative.replace(/^\//, '').split('/');
451 for (var i = 0; i < segments.length; i++) {
452 var segment = segments[i];
453 if (segment === '..') {
454 stack.pop();
455 } else if (segment !== '.') {
456 stack.push(segment);
457 }
458 }
459
460 // ensure leading slash
461 if (stack[0] !== '') {
462 stack.unshift('');
463 }
464
465 return stack.join('/')
466}
467
468function parsePath (path) {
469 var hash = '';
470 var query = '';
471
472 var hashIndex = path.indexOf('#');
473 if (hashIndex >= 0) {
474 hash = path.slice(hashIndex);
475 path = path.slice(0, hashIndex);
476 }
477
478 var queryIndex = path.indexOf('?');
479 if (queryIndex >= 0) {
480 query = path.slice(queryIndex + 1);
481 path = path.slice(0, queryIndex);
482 }
483
484 return {
485 path: path,
486 query: query,
487 hash: hash
488 }
489}
490
491function cleanPath (path) {
492 return path.replace(/\/\//g, '/')
493}
494
495var isarray = Array.isArray || function (arr) {
496 return Object.prototype.toString.call(arr) == '[object Array]';
497};
498
499/**
500 * Expose `pathToRegexp`.
501 */
502var pathToRegexp_1 = pathToRegexp;
503var parse_1 = parse;
504var compile_1 = compile;
505var tokensToFunction_1 = tokensToFunction;
506var tokensToRegExp_1 = tokensToRegExp;
507
508/**
509 * The main path matching regexp utility.
510 *
511 * @type {RegExp}
512 */
513var PATH_REGEXP = new RegExp([
514 // Match escaped characters that would otherwise appear in future matches.
515 // This allows the user to escape special characters that won't transform.
516 '(\\\\.)',
517 // Match Express-style parameters and un-named parameters with a prefix
518 // and optional suffixes. Matches appear as:
519 //
520 // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined]
521 // "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined, undefined]
522 // "/*" => ["/", undefined, undefined, undefined, undefined, "*"]
523 '([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))'
524].join('|'), 'g');
525
526/**
527 * Parse a string for the raw tokens.
528 *
529 * @param {string} str
530 * @param {Object=} options
531 * @return {!Array}
532 */
533function parse (str, options) {
534 var tokens = [];
535 var key = 0;
536 var index = 0;
537 var path = '';
538 var defaultDelimiter = options && options.delimiter || '/';
539 var res;
540
541 while ((res = PATH_REGEXP.exec(str)) != null) {
542 var m = res[0];
543 var escaped = res[1];
544 var offset = res.index;
545 path += str.slice(index, offset);
546 index = offset + m.length;
547
548 // Ignore already escaped sequences.
549 if (escaped) {
550 path += escaped[1];
551 continue
552 }
553
554 var next = str[index];
555 var prefix = res[2];
556 var name = res[3];
557 var capture = res[4];
558 var group = res[5];
559 var modifier = res[6];
560 var asterisk = res[7];
561
562 // Push the current path onto the tokens.
563 if (path) {
564 tokens.push(path);
565 path = '';
566 }
567
568 var partial = prefix != null && next != null && next !== prefix;
569 var repeat = modifier === '+' || modifier === '*';
570 var optional = modifier === '?' || modifier === '*';
571 var delimiter = res[2] || defaultDelimiter;
572 var pattern = capture || group;
573
574 tokens.push({
575 name: name || key++,
576 prefix: prefix || '',
577 delimiter: delimiter,
578 optional: optional,
579 repeat: repeat,
580 partial: partial,
581 asterisk: !!asterisk,
582 pattern: pattern ? escapeGroup(pattern) : (asterisk ? '.*' : '[^' + escapeString(delimiter) + ']+?')
583 });
584 }
585
586 // Match any characters still remaining.
587 if (index < str.length) {
588 path += str.substr(index);
589 }
590
591 // If the path exists, push it onto the end.
592 if (path) {
593 tokens.push(path);
594 }
595
596 return tokens
597}
598
599/**
600 * Compile a string to a template function for the path.
601 *
602 * @param {string} str
603 * @param {Object=} options
604 * @return {!function(Object=, Object=)}
605 */
606function compile (str, options) {
607 return tokensToFunction(parse(str, options))
608}
609
610/**
611 * Prettier encoding of URI path segments.
612 *
613 * @param {string}
614 * @return {string}
615 */
616function encodeURIComponentPretty (str) {
617 return encodeURI(str).replace(/[\/?#]/g, function (c) {
618 return '%' + c.charCodeAt(0).toString(16).toUpperCase()
619 })
620}
621
622/**
623 * Encode the asterisk parameter. Similar to `pretty`, but allows slashes.
624 *
625 * @param {string}
626 * @return {string}
627 */
628function encodeAsterisk (str) {
629 return encodeURI(str).replace(/[?#]/g, function (c) {
630 return '%' + c.charCodeAt(0).toString(16).toUpperCase()
631 })
632}
633
634/**
635 * Expose a method for transforming tokens into the path function.
636 */
637function tokensToFunction (tokens) {
638 // Compile all the tokens into regexps.
639 var matches = new Array(tokens.length);
640
641 // Compile all the patterns before compilation.
642 for (var i = 0; i < tokens.length; i++) {
643 if (typeof tokens[i] === 'object') {
644 matches[i] = new RegExp('^(?:' + tokens[i].pattern + ')$');
645 }
646 }
647
648 return function (obj, opts) {
649 var path = '';
650 var data = obj || {};
651 var options = opts || {};
652 var encode = options.pretty ? encodeURIComponentPretty : encodeURIComponent;
653
654 for (var i = 0; i < tokens.length; i++) {
655 var token = tokens[i];
656
657 if (typeof token === 'string') {
658 path += token;
659
660 continue
661 }
662
663 var value = data[token.name];
664 var segment;
665
666 if (value == null) {
667 if (token.optional) {
668 // Prepend partial segment prefixes.
669 if (token.partial) {
670 path += token.prefix;
671 }
672
673 continue
674 } else {
675 throw new TypeError('Expected "' + token.name + '" to be defined')
676 }
677 }
678
679 if (isarray(value)) {
680 if (!token.repeat) {
681 throw new TypeError('Expected "' + token.name + '" to not repeat, but received `' + JSON.stringify(value) + '`')
682 }
683
684 if (value.length === 0) {
685 if (token.optional) {
686 continue
687 } else {
688 throw new TypeError('Expected "' + token.name + '" to not be empty')
689 }
690 }
691
692 for (var j = 0; j < value.length; j++) {
693 segment = encode(value[j]);
694
695 if (!matches[i].test(segment)) {
696 throw new TypeError('Expected all "' + token.name + '" to match "' + token.pattern + '", but received `' + JSON.stringify(segment) + '`')
697 }
698
699 path += (j === 0 ? token.prefix : token.delimiter) + segment;
700 }
701
702 continue
703 }
704
705 segment = token.asterisk ? encodeAsterisk(value) : encode(value);
706
707 if (!matches[i].test(segment)) {
708 throw new TypeError('Expected "' + token.name + '" to match "' + token.pattern + '", but received "' + segment + '"')
709 }
710
711 path += token.prefix + segment;
712 }
713
714 return path
715 }
716}
717
718/**
719 * Escape a regular expression string.
720 *
721 * @param {string} str
722 * @return {string}
723 */
724function escapeString (str) {
725 return str.replace(/([.+*?=^!:${}()[\]|\/\\])/g, '\\$1')
726}
727
728/**
729 * Escape the capturing group by escaping special characters and meaning.
730 *
731 * @param {string} group
732 * @return {string}
733 */
734function escapeGroup (group) {
735 return group.replace(/([=!:$\/()])/g, '\\$1')
736}
737
738/**
739 * Attach the keys as a property of the regexp.
740 *
741 * @param {!RegExp} re
742 * @param {Array} keys
743 * @return {!RegExp}
744 */
745function attachKeys (re, keys) {
746 re.keys = keys;
747 return re
748}
749
750/**
751 * Get the flags for a regexp from the options.
752 *
753 * @param {Object} options
754 * @return {string}
755 */
756function flags (options) {
757 return options.sensitive ? '' : 'i'
758}
759
760/**
761 * Pull out keys from a regexp.
762 *
763 * @param {!RegExp} path
764 * @param {!Array} keys
765 * @return {!RegExp}
766 */
767function regexpToRegexp (path, keys) {
768 // Use a negative lookahead to match only capturing groups.
769 var groups = path.source.match(/\((?!\?)/g);
770
771 if (groups) {
772 for (var i = 0; i < groups.length; i++) {
773 keys.push({
774 name: i,
775 prefix: null,
776 delimiter: null,
777 optional: false,
778 repeat: false,
779 partial: false,
780 asterisk: false,
781 pattern: null
782 });
783 }
784 }
785
786 return attachKeys(path, keys)
787}
788
789/**
790 * Transform an array into a regexp.
791 *
792 * @param {!Array} path
793 * @param {Array} keys
794 * @param {!Object} options
795 * @return {!RegExp}
796 */
797function arrayToRegexp (path, keys, options) {
798 var parts = [];
799
800 for (var i = 0; i < path.length; i++) {
801 parts.push(pathToRegexp(path[i], keys, options).source);
802 }
803
804 var regexp = new RegExp('(?:' + parts.join('|') + ')', flags(options));
805
806 return attachKeys(regexp, keys)
807}
808
809/**
810 * Create a path regexp from string input.
811 *
812 * @param {string} path
813 * @param {!Array} keys
814 * @param {!Object} options
815 * @return {!RegExp}
816 */
817function stringToRegexp (path, keys, options) {
818 return tokensToRegExp(parse(path, options), keys, options)
819}
820
821/**
822 * Expose a function for taking tokens and returning a RegExp.
823 *
824 * @param {!Array} tokens
825 * @param {(Array|Object)=} keys
826 * @param {Object=} options
827 * @return {!RegExp}
828 */
829function tokensToRegExp (tokens, keys, options) {
830 if (!isarray(keys)) {
831 options = /** @type {!Object} */ (keys || options);
832 keys = [];
833 }
834
835 options = options || {};
836
837 var strict = options.strict;
838 var end = options.end !== false;
839 var route = '';
840
841 // Iterate over the tokens and create our regexp string.
842 for (var i = 0; i < tokens.length; i++) {
843 var token = tokens[i];
844
845 if (typeof token === 'string') {
846 route += escapeString(token);
847 } else {
848 var prefix = escapeString(token.prefix);
849 var capture = '(?:' + token.pattern + ')';
850
851 keys.push(token);
852
853 if (token.repeat) {
854 capture += '(?:' + prefix + capture + ')*';
855 }
856
857 if (token.optional) {
858 if (!token.partial) {
859 capture = '(?:' + prefix + '(' + capture + '))?';
860 } else {
861 capture = prefix + '(' + capture + ')?';
862 }
863 } else {
864 capture = prefix + '(' + capture + ')';
865 }
866
867 route += capture;
868 }
869 }
870
871 var delimiter = escapeString(options.delimiter || '/');
872 var endsWithDelimiter = route.slice(-delimiter.length) === delimiter;
873
874 // In non-strict mode we allow a slash at the end of match. If the path to
875 // match already ends with a slash, we remove it for consistency. The slash
876 // is valid at the end of a path match, not in the middle. This is important
877 // in non-ending mode, where "/test/" shouldn't match "/test//route".
878 if (!strict) {
879 route = (endsWithDelimiter ? route.slice(0, -delimiter.length) : route) + '(?:' + delimiter + '(?=$))?';
880 }
881
882 if (end) {
883 route += '$';
884 } else {
885 // In non-ending mode, we need the capturing groups to match as much as
886 // possible by using a positive lookahead to the end or next path segment.
887 route += strict && endsWithDelimiter ? '' : '(?=' + delimiter + '|$)';
888 }
889
890 return attachKeys(new RegExp('^' + route, flags(options)), keys)
891}
892
893/**
894 * Normalize the given path string, returning a regular expression.
895 *
896 * An empty array can be passed in for the keys, which will hold the
897 * placeholder key descriptions. For example, using `/user/:id`, `keys` will
898 * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.
899 *
900 * @param {(string|RegExp|Array)} path
901 * @param {(Array|Object)=} keys
902 * @param {Object=} options
903 * @return {!RegExp}
904 */
905function pathToRegexp (path, keys, options) {
906 if (!isarray(keys)) {
907 options = /** @type {!Object} */ (keys || options);
908 keys = [];
909 }
910
911 options = options || {};
912
913 if (path instanceof RegExp) {
914 return regexpToRegexp(path, /** @type {!Array} */ (keys))
915 }
916
917 if (isarray(path)) {
918 return arrayToRegexp(/** @type {!Array} */ (path), /** @type {!Array} */ (keys), options)
919 }
920
921 return stringToRegexp(/** @type {string} */ (path), /** @type {!Array} */ (keys), options)
922}
923pathToRegexp_1.parse = parse_1;
924pathToRegexp_1.compile = compile_1;
925pathToRegexp_1.tokensToFunction = tokensToFunction_1;
926pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
927
928/* */
929
930// $flow-disable-line
931var regexpCompileCache = Object.create(null);
932
933function fillParams (
934 path,
935 params,
936 routeMsg
937) {
938 params = params || {};
939 try {
940 var filler =
941 regexpCompileCache[path] ||
942 (regexpCompileCache[path] = pathToRegexp_1.compile(path));
943
944 // Fix #2505 resolving asterisk routes { name: 'not-found', params: { pathMatch: '/not-found' }}
945 // and fix #3106 so that you can work with location descriptor object having params.pathMatch equal to empty string
946 if (typeof params.pathMatch === 'string') { params[0] = params.pathMatch; }
947
948 return filler(params, { pretty: true })
949 } catch (e) {
950 if (process.env.NODE_ENV !== 'production') {
951 // Fix #3072 no warn if `pathMatch` is string
952 warn(typeof params.pathMatch === 'string', ("missing param for " + routeMsg + ": " + (e.message)));
953 }
954 return ''
955 } finally {
956 // delete the 0 if it was added
957 delete params[0];
958 }
959}
960
961/* */
962
963function normalizeLocation (
964 raw,
965 current,
966 append,
967 router
968) {
969 var next = typeof raw === 'string' ? { path: raw } : raw;
970 // named target
971 if (next._normalized) {
972 return next
973 } else if (next.name) {
974 next = extend({}, raw);
975 var params = next.params;
976 if (params && typeof params === 'object') {
977 next.params = extend({}, params);
978 }
979 return next
980 }
981
982 // relative params
983 if (!next.path && next.params && current) {
984 next = extend({}, next);
985 next._normalized = true;
986 var params$1 = extend(extend({}, current.params), next.params);
987 if (current.name) {
988 next.name = current.name;
989 next.params = params$1;
990 } else if (current.matched.length) {
991 var rawPath = current.matched[current.matched.length - 1].path;
992 next.path = fillParams(rawPath, params$1, ("path " + (current.path)));
993 } else if (process.env.NODE_ENV !== 'production') {
994 warn(false, "relative params navigation requires a current route.");
995 }
996 return next
997 }
998
999 var parsedPath = parsePath(next.path || '');
1000 var basePath = (current && current.path) || '/';
1001 var path = parsedPath.path
1002 ? resolvePath(parsedPath.path, basePath, append || next.append)
1003 : basePath;
1004
1005 var query = resolveQuery(
1006 parsedPath.query,
1007 next.query,
1008 router && router.options.parseQuery
1009 );
1010
1011 var hash = next.hash || parsedPath.hash;
1012 if (hash && hash.charAt(0) !== '#') {
1013 hash = "#" + hash;
1014 }
1015
1016 return {
1017 _normalized: true,
1018 path: path,
1019 query: query,
1020 hash: hash
1021 }
1022}
1023
1024/* */
1025
1026// work around weird flow bug
1027var toTypes = [String, Object];
1028var eventTypes = [String, Array];
1029
1030var noop = function () {};
1031
1032var Link = {
1033 name: 'RouterLink',
1034 props: {
1035 to: {
1036 type: toTypes,
1037 required: true
1038 },
1039 tag: {
1040 type: String,
1041 default: 'a'
1042 },
1043 exact: Boolean,
1044 append: Boolean,
1045 replace: Boolean,
1046 activeClass: String,
1047 exactActiveClass: String,
1048 event: {
1049 type: eventTypes,
1050 default: 'click'
1051 }
1052 },
1053 render: function render (h) {
1054 var this$1 = this;
1055
1056 var router = this.$router;
1057 var current = this.$route;
1058 var ref = router.resolve(
1059 this.to,
1060 current,
1061 this.append
1062 );
1063 var location = ref.location;
1064 var route = ref.route;
1065 var href = ref.href;
1066
1067 var classes = {};
1068 var globalActiveClass = router.options.linkActiveClass;
1069 var globalExactActiveClass = router.options.linkExactActiveClass;
1070 // Support global empty active class
1071 var activeClassFallback =
1072 globalActiveClass == null ? 'router-link-active' : globalActiveClass;
1073 var exactActiveClassFallback =
1074 globalExactActiveClass == null
1075 ? 'router-link-exact-active'
1076 : globalExactActiveClass;
1077 var activeClass =
1078 this.activeClass == null ? activeClassFallback : this.activeClass;
1079 var exactActiveClass =
1080 this.exactActiveClass == null
1081 ? exactActiveClassFallback
1082 : this.exactActiveClass;
1083
1084 var compareTarget = route.redirectedFrom
1085 ? createRoute(null, normalizeLocation(route.redirectedFrom), null, router)
1086 : route;
1087
1088 classes[exactActiveClass] = isSameRoute(current, compareTarget);
1089 classes[activeClass] = this.exact
1090 ? classes[exactActiveClass]
1091 : isIncludedRoute(current, compareTarget);
1092
1093 var handler = function (e) {
1094 if (guardEvent(e)) {
1095 if (this$1.replace) {
1096 router.replace(location, noop);
1097 } else {
1098 router.push(location, noop);
1099 }
1100 }
1101 };
1102
1103 var on = { click: guardEvent };
1104 if (Array.isArray(this.event)) {
1105 this.event.forEach(function (e) {
1106 on[e] = handler;
1107 });
1108 } else {
1109 on[this.event] = handler;
1110 }
1111
1112 var data = { class: classes };
1113
1114 var scopedSlot =
1115 !this.$scopedSlots.$hasNormal &&
1116 this.$scopedSlots.default &&
1117 this.$scopedSlots.default({
1118 href: href,
1119 route: route,
1120 navigate: handler,
1121 isActive: classes[activeClass],
1122 isExactActive: classes[exactActiveClass]
1123 });
1124
1125 if (scopedSlot) {
1126 if (scopedSlot.length === 1) {
1127 return scopedSlot[0]
1128 } else if (scopedSlot.length > 1 || !scopedSlot.length) {
1129 if (process.env.NODE_ENV !== 'production') {
1130 warn(
1131 false,
1132 ("RouterLink with to=\"" + (this.to) + "\" is trying to use a scoped slot but it didn't provide exactly one child. Wrapping the content with a span element.")
1133 );
1134 }
1135 return scopedSlot.length === 0 ? h() : h('span', {}, scopedSlot)
1136 }
1137 }
1138
1139 if (this.tag === 'a') {
1140 data.on = on;
1141 data.attrs = { href: href };
1142 } else {
1143 // find the first <a> child and apply listener and href
1144 var a = findAnchor(this.$slots.default);
1145 if (a) {
1146 // in case the <a> is a static node
1147 a.isStatic = false;
1148 var aData = (a.data = extend({}, a.data));
1149 aData.on = aData.on || {};
1150 // transform existing events in both objects into arrays so we can push later
1151 for (var event in aData.on) {
1152 var handler$1 = aData.on[event];
1153 if (event in on) {
1154 aData.on[event] = Array.isArray(handler$1) ? handler$1 : [handler$1];
1155 }
1156 }
1157 // append new listeners for router-link
1158 for (var event$1 in on) {
1159 if (event$1 in aData.on) {
1160 // on[event] is always a function
1161 aData.on[event$1].push(on[event$1]);
1162 } else {
1163 aData.on[event$1] = handler;
1164 }
1165 }
1166
1167 var aAttrs = (a.data.attrs = extend({}, a.data.attrs));
1168 aAttrs.href = href;
1169 } else {
1170 // doesn't have <a> child, apply listener to self
1171 data.on = on;
1172 }
1173 }
1174
1175 return h(this.tag, data, this.$slots.default)
1176 }
1177};
1178
1179function guardEvent (e) {
1180 // don't redirect with control keys
1181 if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) { return }
1182 // don't redirect when preventDefault called
1183 if (e.defaultPrevented) { return }
1184 // don't redirect on right click
1185 if (e.button !== undefined && e.button !== 0) { return }
1186 // don't redirect if `target="_blank"`
1187 if (e.currentTarget && e.currentTarget.getAttribute) {
1188 var target = e.currentTarget.getAttribute('target');
1189 if (/\b_blank\b/i.test(target)) { return }
1190 }
1191 // this may be a Weex event which doesn't have this method
1192 if (e.preventDefault) {
1193 e.preventDefault();
1194 }
1195 return true
1196}
1197
1198function findAnchor (children) {
1199 if (children) {
1200 var child;
1201 for (var i = 0; i < children.length; i++) {
1202 child = children[i];
1203 if (child.tag === 'a') {
1204 return child
1205 }
1206 if (child.children && (child = findAnchor(child.children))) {
1207 return child
1208 }
1209 }
1210 }
1211}
1212
1213var _Vue;
1214
1215function install (Vue) {
1216 if (install.installed && _Vue === Vue) { return }
1217 install.installed = true;
1218
1219 _Vue = Vue;
1220
1221 var isDef = function (v) { return v !== undefined; };
1222
1223 var registerInstance = function (vm, callVal) {
1224 var i = vm.$options._parentVnode;
1225 if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
1226 i(vm, callVal);
1227 }
1228 };
1229
1230 Vue.mixin({
1231 beforeCreate: function beforeCreate () {
1232 if (isDef(this.$options.router)) {
1233 this._routerRoot = this;
1234 this._router = this.$options.router;
1235 this._router.init(this);
1236 Vue.util.defineReactive(this, '_route', this._router.history.current);
1237 } else {
1238 this._routerRoot = (this.$parent && this.$parent._routerRoot) || this;
1239 }
1240 registerInstance(this, this);
1241 },
1242 destroyed: function destroyed () {
1243 registerInstance(this);
1244 }
1245 });
1246
1247 Object.defineProperty(Vue.prototype, '$router', {
1248 get: function get () { return this._routerRoot._router }
1249 });
1250
1251 Object.defineProperty(Vue.prototype, '$route', {
1252 get: function get () { return this._routerRoot._route }
1253 });
1254
1255 Vue.component('RouterView', View);
1256 Vue.component('RouterLink', Link);
1257
1258 var strats = Vue.config.optionMergeStrategies;
1259 // use the same hook merging strategy for route hooks
1260 strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created;
1261}
1262
1263/* */
1264
1265var inBrowser = typeof window !== 'undefined';
1266
1267/* */
1268
1269function createRouteMap (
1270 routes,
1271 oldPathList,
1272 oldPathMap,
1273 oldNameMap
1274) {
1275 // the path list is used to control path matching priority
1276 var pathList = oldPathList || [];
1277 // $flow-disable-line
1278 var pathMap = oldPathMap || Object.create(null);
1279 // $flow-disable-line
1280 var nameMap = oldNameMap || Object.create(null);
1281
1282 routes.forEach(function (route) {
1283 addRouteRecord(pathList, pathMap, nameMap, route);
1284 });
1285
1286 // ensure wildcard routes are always at the end
1287 for (var i = 0, l = pathList.length; i < l; i++) {
1288 if (pathList[i] === '*') {
1289 pathList.push(pathList.splice(i, 1)[0]);
1290 l--;
1291 i--;
1292 }
1293 }
1294
1295 if (process.env.NODE_ENV === 'development') {
1296 // warn if routes do not include leading slashes
1297 var found = pathList
1298 // check for missing leading slash
1299 .filter(function (path) { return path && path.charAt(0) !== '*' && path.charAt(0) !== '/'; });
1300
1301 if (found.length > 0) {
1302 var pathNames = found.map(function (path) { return ("- " + path); }).join('\n');
1303 warn(false, ("Non-nested routes must include a leading slash character. Fix the following routes: \n" + pathNames));
1304 }
1305 }
1306
1307 return {
1308 pathList: pathList,
1309 pathMap: pathMap,
1310 nameMap: nameMap
1311 }
1312}
1313
1314function addRouteRecord (
1315 pathList,
1316 pathMap,
1317 nameMap,
1318 route,
1319 parent,
1320 matchAs
1321) {
1322 var path = route.path;
1323 var name = route.name;
1324 if (process.env.NODE_ENV !== 'production') {
1325 assert(path != null, "\"path\" is required in a route configuration.");
1326 assert(
1327 typeof route.component !== 'string',
1328 "route config \"component\" for path: " + (String(
1329 path || name
1330 )) + " cannot be a " + "string id. Use an actual component instead."
1331 );
1332 }
1333
1334 var pathToRegexpOptions =
1335 route.pathToRegexpOptions || {};
1336 var normalizedPath = normalizePath(path, parent, pathToRegexpOptions.strict);
1337
1338 if (typeof route.caseSensitive === 'boolean') {
1339 pathToRegexpOptions.sensitive = route.caseSensitive;
1340 }
1341
1342 var record = {
1343 path: normalizedPath,
1344 regex: compileRouteRegex(normalizedPath, pathToRegexpOptions),
1345 components: route.components || { default: route.component },
1346 instances: {},
1347 name: name,
1348 parent: parent,
1349 matchAs: matchAs,
1350 redirect: route.redirect,
1351 beforeEnter: route.beforeEnter,
1352 meta: route.meta || {},
1353 props:
1354 route.props == null
1355 ? {}
1356 : route.components
1357 ? route.props
1358 : { default: route.props }
1359 };
1360
1361 if (route.children) {
1362 // Warn if route is named, does not redirect and has a default child route.
1363 // If users navigate to this route by name, the default child will
1364 // not be rendered (GH Issue #629)
1365 if (process.env.NODE_ENV !== 'production') {
1366 if (
1367 route.name &&
1368 !route.redirect &&
1369 route.children.some(function (child) { return /^\/?$/.test(child.path); })
1370 ) {
1371 warn(
1372 false,
1373 "Named Route '" + (route.name) + "' has a default child route. " +
1374 "When navigating to this named route (:to=\"{name: '" + (route.name) + "'\"), " +
1375 "the default child route will not be rendered. Remove the name from " +
1376 "this route and use the name of the default child route for named " +
1377 "links instead."
1378 );
1379 }
1380 }
1381 route.children.forEach(function (child) {
1382 var childMatchAs = matchAs
1383 ? cleanPath((matchAs + "/" + (child.path)))
1384 : undefined;
1385 addRouteRecord(pathList, pathMap, nameMap, child, record, childMatchAs);
1386 });
1387 }
1388
1389 if (!pathMap[record.path]) {
1390 pathList.push(record.path);
1391 pathMap[record.path] = record;
1392 }
1393
1394 if (route.alias !== undefined) {
1395 var aliases = Array.isArray(route.alias) ? route.alias : [route.alias];
1396 for (var i = 0; i < aliases.length; ++i) {
1397 var alias = aliases[i];
1398 if (process.env.NODE_ENV !== 'production' && alias === path) {
1399 warn(
1400 false,
1401 ("Found an alias with the same value as the path: \"" + path + "\". You have to remove that alias. It will be ignored in development.")
1402 );
1403 // skip in dev to make it work
1404 continue
1405 }
1406
1407 var aliasRoute = {
1408 path: alias,
1409 children: route.children
1410 };
1411 addRouteRecord(
1412 pathList,
1413 pathMap,
1414 nameMap,
1415 aliasRoute,
1416 parent,
1417 record.path || '/' // matchAs
1418 );
1419 }
1420 }
1421
1422 if (name) {
1423 if (!nameMap[name]) {
1424 nameMap[name] = record;
1425 } else if (process.env.NODE_ENV !== 'production' && !matchAs) {
1426 warn(
1427 false,
1428 "Duplicate named routes definition: " +
1429 "{ name: \"" + name + "\", path: \"" + (record.path) + "\" }"
1430 );
1431 }
1432 }
1433}
1434
1435function compileRouteRegex (
1436 path,
1437 pathToRegexpOptions
1438) {
1439 var regex = pathToRegexp_1(path, [], pathToRegexpOptions);
1440 if (process.env.NODE_ENV !== 'production') {
1441 var keys = Object.create(null);
1442 regex.keys.forEach(function (key) {
1443 warn(
1444 !keys[key.name],
1445 ("Duplicate param keys in route with path: \"" + path + "\"")
1446 );
1447 keys[key.name] = true;
1448 });
1449 }
1450 return regex
1451}
1452
1453function normalizePath (
1454 path,
1455 parent,
1456 strict
1457) {
1458 if (!strict) { path = path.replace(/\/$/, ''); }
1459 if (path[0] === '/') { return path }
1460 if (parent == null) { return path }
1461 return cleanPath(((parent.path) + "/" + path))
1462}
1463
1464/* */
1465
1466
1467
1468function createMatcher (
1469 routes,
1470 router
1471) {
1472 var ref = createRouteMap(routes);
1473 var pathList = ref.pathList;
1474 var pathMap = ref.pathMap;
1475 var nameMap = ref.nameMap;
1476
1477 function addRoutes (routes) {
1478 createRouteMap(routes, pathList, pathMap, nameMap);
1479 }
1480
1481 function match (
1482 raw,
1483 currentRoute,
1484 redirectedFrom
1485 ) {
1486 var location = normalizeLocation(raw, currentRoute, false, router);
1487 var name = location.name;
1488
1489 if (name) {
1490 var record = nameMap[name];
1491 if (process.env.NODE_ENV !== 'production') {
1492 warn(record, ("Route with name '" + name + "' does not exist"));
1493 }
1494 if (!record) { return _createRoute(null, location) }
1495 var paramNames = record.regex.keys
1496 .filter(function (key) { return !key.optional; })
1497 .map(function (key) { return key.name; });
1498
1499 if (typeof location.params !== 'object') {
1500 location.params = {};
1501 }
1502
1503 if (currentRoute && typeof currentRoute.params === 'object') {
1504 for (var key in currentRoute.params) {
1505 if (!(key in location.params) && paramNames.indexOf(key) > -1) {
1506 location.params[key] = currentRoute.params[key];
1507 }
1508 }
1509 }
1510
1511 location.path = fillParams(record.path, location.params, ("named route \"" + name + "\""));
1512 return _createRoute(record, location, redirectedFrom)
1513 } else if (location.path) {
1514 location.params = {};
1515 for (var i = 0; i < pathList.length; i++) {
1516 var path = pathList[i];
1517 var record$1 = pathMap[path];
1518 if (matchRoute(record$1.regex, location.path, location.params)) {
1519 return _createRoute(record$1, location, redirectedFrom)
1520 }
1521 }
1522 }
1523 // no match
1524 return _createRoute(null, location)
1525 }
1526
1527 function redirect (
1528 record,
1529 location
1530 ) {
1531 var originalRedirect = record.redirect;
1532 var redirect = typeof originalRedirect === 'function'
1533 ? originalRedirect(createRoute(record, location, null, router))
1534 : originalRedirect;
1535
1536 if (typeof redirect === 'string') {
1537 redirect = { path: redirect };
1538 }
1539
1540 if (!redirect || typeof redirect !== 'object') {
1541 if (process.env.NODE_ENV !== 'production') {
1542 warn(
1543 false, ("invalid redirect option: " + (JSON.stringify(redirect)))
1544 );
1545 }
1546 return _createRoute(null, location)
1547 }
1548
1549 var re = redirect;
1550 var name = re.name;
1551 var path = re.path;
1552 var query = location.query;
1553 var hash = location.hash;
1554 var params = location.params;
1555 query = re.hasOwnProperty('query') ? re.query : query;
1556 hash = re.hasOwnProperty('hash') ? re.hash : hash;
1557 params = re.hasOwnProperty('params') ? re.params : params;
1558
1559 if (name) {
1560 // resolved named direct
1561 var targetRecord = nameMap[name];
1562 if (process.env.NODE_ENV !== 'production') {
1563 assert(targetRecord, ("redirect failed: named route \"" + name + "\" not found."));
1564 }
1565 return match({
1566 _normalized: true,
1567 name: name,
1568 query: query,
1569 hash: hash,
1570 params: params
1571 }, undefined, location)
1572 } else if (path) {
1573 // 1. resolve relative redirect
1574 var rawPath = resolveRecordPath(path, record);
1575 // 2. resolve params
1576 var resolvedPath = fillParams(rawPath, params, ("redirect route with path \"" + rawPath + "\""));
1577 // 3. rematch with existing query and hash
1578 return match({
1579 _normalized: true,
1580 path: resolvedPath,
1581 query: query,
1582 hash: hash
1583 }, undefined, location)
1584 } else {
1585 if (process.env.NODE_ENV !== 'production') {
1586 warn(false, ("invalid redirect option: " + (JSON.stringify(redirect))));
1587 }
1588 return _createRoute(null, location)
1589 }
1590 }
1591
1592 function alias (
1593 record,
1594 location,
1595 matchAs
1596 ) {
1597 var aliasedPath = fillParams(matchAs, location.params, ("aliased route with path \"" + matchAs + "\""));
1598 var aliasedMatch = match({
1599 _normalized: true,
1600 path: aliasedPath
1601 });
1602 if (aliasedMatch) {
1603 var matched = aliasedMatch.matched;
1604 var aliasedRecord = matched[matched.length - 1];
1605 location.params = aliasedMatch.params;
1606 return _createRoute(aliasedRecord, location)
1607 }
1608 return _createRoute(null, location)
1609 }
1610
1611 function _createRoute (
1612 record,
1613 location,
1614 redirectedFrom
1615 ) {
1616 if (record && record.redirect) {
1617 return redirect(record, redirectedFrom || location)
1618 }
1619 if (record && record.matchAs) {
1620 return alias(record, location, record.matchAs)
1621 }
1622 return createRoute(record, location, redirectedFrom, router)
1623 }
1624
1625 return {
1626 match: match,
1627 addRoutes: addRoutes
1628 }
1629}
1630
1631function matchRoute (
1632 regex,
1633 path,
1634 params
1635) {
1636 var m = path.match(regex);
1637
1638 if (!m) {
1639 return false
1640 } else if (!params) {
1641 return true
1642 }
1643
1644 for (var i = 1, len = m.length; i < len; ++i) {
1645 var key = regex.keys[i - 1];
1646 var val = typeof m[i] === 'string' ? decodeURIComponent(m[i]) : m[i];
1647 if (key) {
1648 // Fix #1994: using * with props: true generates a param named 0
1649 params[key.name || 'pathMatch'] = val;
1650 }
1651 }
1652
1653 return true
1654}
1655
1656function resolveRecordPath (path, record) {
1657 return resolvePath(path, record.parent ? record.parent.path : '/', true)
1658}
1659
1660/* */
1661
1662// use User Timing api (if present) for more accurate key precision
1663var Time =
1664 inBrowser && window.performance && window.performance.now
1665 ? window.performance
1666 : Date;
1667
1668function genStateKey () {
1669 return Time.now().toFixed(3)
1670}
1671
1672var _key = genStateKey();
1673
1674function getStateKey () {
1675 return _key
1676}
1677
1678function setStateKey (key) {
1679 return (_key = key)
1680}
1681
1682/* */
1683
1684var positionStore = Object.create(null);
1685
1686function setupScroll () {
1687 // Fix for #1585 for Firefox
1688 // Fix for #2195 Add optional third attribute to workaround a bug in safari https://bugs.webkit.org/show_bug.cgi?id=182678
1689 // Fix for #2774 Support for apps loaded from Windows file shares not mapped to network drives: replaced location.origin with
1690 // window.location.protocol + '//' + window.location.host
1691 // location.host contains the port and location.hostname doesn't
1692 var protocolAndPath = window.location.protocol + '//' + window.location.host;
1693 var absolutePath = window.location.href.replace(protocolAndPath, '');
1694 // preserve existing history state as it could be overriden by the user
1695 var stateCopy = extend({}, window.history.state);
1696 stateCopy.key = getStateKey();
1697 window.history.replaceState(stateCopy, '', absolutePath);
1698 window.addEventListener('popstate', function (e) {
1699 saveScrollPosition();
1700 if (e.state && e.state.key) {
1701 setStateKey(e.state.key);
1702 }
1703 });
1704}
1705
1706function handleScroll (
1707 router,
1708 to,
1709 from,
1710 isPop
1711) {
1712 if (!router.app) {
1713 return
1714 }
1715
1716 var behavior = router.options.scrollBehavior;
1717 if (!behavior) {
1718 return
1719 }
1720
1721 if (process.env.NODE_ENV !== 'production') {
1722 assert(typeof behavior === 'function', "scrollBehavior must be a function");
1723 }
1724
1725 // wait until re-render finishes before scrolling
1726 router.app.$nextTick(function () {
1727 var position = getScrollPosition();
1728 var shouldScroll = behavior.call(
1729 router,
1730 to,
1731 from,
1732 isPop ? position : null
1733 );
1734
1735 if (!shouldScroll) {
1736 return
1737 }
1738
1739 if (typeof shouldScroll.then === 'function') {
1740 shouldScroll
1741 .then(function (shouldScroll) {
1742 scrollToPosition((shouldScroll), position);
1743 })
1744 .catch(function (err) {
1745 if (process.env.NODE_ENV !== 'production') {
1746 assert(false, err.toString());
1747 }
1748 });
1749 } else {
1750 scrollToPosition(shouldScroll, position);
1751 }
1752 });
1753}
1754
1755function saveScrollPosition () {
1756 var key = getStateKey();
1757 if (key) {
1758 positionStore[key] = {
1759 x: window.pageXOffset,
1760 y: window.pageYOffset
1761 };
1762 }
1763}
1764
1765function getScrollPosition () {
1766 var key = getStateKey();
1767 if (key) {
1768 return positionStore[key]
1769 }
1770}
1771
1772function getElementPosition (el, offset) {
1773 var docEl = document.documentElement;
1774 var docRect = docEl.getBoundingClientRect();
1775 var elRect = el.getBoundingClientRect();
1776 return {
1777 x: elRect.left - docRect.left - offset.x,
1778 y: elRect.top - docRect.top - offset.y
1779 }
1780}
1781
1782function isValidPosition (obj) {
1783 return isNumber(obj.x) || isNumber(obj.y)
1784}
1785
1786function normalizePosition (obj) {
1787 return {
1788 x: isNumber(obj.x) ? obj.x : window.pageXOffset,
1789 y: isNumber(obj.y) ? obj.y : window.pageYOffset
1790 }
1791}
1792
1793function normalizeOffset (obj) {
1794 return {
1795 x: isNumber(obj.x) ? obj.x : 0,
1796 y: isNumber(obj.y) ? obj.y : 0
1797 }
1798}
1799
1800function isNumber (v) {
1801 return typeof v === 'number'
1802}
1803
1804var hashStartsWithNumberRE = /^#\d/;
1805
1806function scrollToPosition (shouldScroll, position) {
1807 var isObject = typeof shouldScroll === 'object';
1808 if (isObject && typeof shouldScroll.selector === 'string') {
1809 // getElementById would still fail if the selector contains a more complicated query like #main[data-attr]
1810 // but at the same time, it doesn't make much sense to select an element with an id and an extra selector
1811 var el = hashStartsWithNumberRE.test(shouldScroll.selector) // $flow-disable-line
1812 ? document.getElementById(shouldScroll.selector.slice(1)) // $flow-disable-line
1813 : document.querySelector(shouldScroll.selector);
1814
1815 if (el) {
1816 var offset =
1817 shouldScroll.offset && typeof shouldScroll.offset === 'object'
1818 ? shouldScroll.offset
1819 : {};
1820 offset = normalizeOffset(offset);
1821 position = getElementPosition(el, offset);
1822 } else if (isValidPosition(shouldScroll)) {
1823 position = normalizePosition(shouldScroll);
1824 }
1825 } else if (isObject && isValidPosition(shouldScroll)) {
1826 position = normalizePosition(shouldScroll);
1827 }
1828
1829 if (position) {
1830 window.scrollTo(position.x, position.y);
1831 }
1832}
1833
1834/* */
1835
1836var supportsPushState =
1837 inBrowser &&
1838 (function () {
1839 var ua = window.navigator.userAgent;
1840
1841 if (
1842 (ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) &&
1843 ua.indexOf('Mobile Safari') !== -1 &&
1844 ua.indexOf('Chrome') === -1 &&
1845 ua.indexOf('Windows Phone') === -1
1846 ) {
1847 return false
1848 }
1849
1850 return window.history && 'pushState' in window.history
1851 })();
1852
1853function pushState (url, replace) {
1854 saveScrollPosition();
1855 // try...catch the pushState call to get around Safari
1856 // DOM Exception 18 where it limits to 100 pushState calls
1857 var history = window.history;
1858 try {
1859 if (replace) {
1860 // preserve existing history state as it could be overriden by the user
1861 var stateCopy = extend({}, history.state);
1862 stateCopy.key = getStateKey();
1863 history.replaceState(stateCopy, '', url);
1864 } else {
1865 history.pushState({ key: setStateKey(genStateKey()) }, '', url);
1866 }
1867 } catch (e) {
1868 window.location[replace ? 'replace' : 'assign'](url);
1869 }
1870}
1871
1872function replaceState (url) {
1873 pushState(url, true);
1874}
1875
1876/* */
1877
1878function runQueue (queue, fn, cb) {
1879 var step = function (index) {
1880 if (index >= queue.length) {
1881 cb();
1882 } else {
1883 if (queue[index]) {
1884 fn(queue[index], function () {
1885 step(index + 1);
1886 });
1887 } else {
1888 step(index + 1);
1889 }
1890 }
1891 };
1892 step(0);
1893}
1894
1895/* */
1896
1897function resolveAsyncComponents (matched) {
1898 return function (to, from, next) {
1899 var hasAsync = false;
1900 var pending = 0;
1901 var error = null;
1902
1903 flatMapComponents(matched, function (def, _, match, key) {
1904 // if it's a function and doesn't have cid attached,
1905 // assume it's an async component resolve function.
1906 // we are not using Vue's default async resolving mechanism because
1907 // we want to halt the navigation until the incoming component has been
1908 // resolved.
1909 if (typeof def === 'function' && def.cid === undefined) {
1910 hasAsync = true;
1911 pending++;
1912
1913 var resolve = once(function (resolvedDef) {
1914 if (isESModule(resolvedDef)) {
1915 resolvedDef = resolvedDef.default;
1916 }
1917 // save resolved on async factory in case it's used elsewhere
1918 def.resolved = typeof resolvedDef === 'function'
1919 ? resolvedDef
1920 : _Vue.extend(resolvedDef);
1921 match.components[key] = resolvedDef;
1922 pending--;
1923 if (pending <= 0) {
1924 next();
1925 }
1926 });
1927
1928 var reject = once(function (reason) {
1929 var msg = "Failed to resolve async component " + key + ": " + reason;
1930 process.env.NODE_ENV !== 'production' && warn(false, msg);
1931 if (!error) {
1932 error = isError(reason)
1933 ? reason
1934 : new Error(msg);
1935 next(error);
1936 }
1937 });
1938
1939 var res;
1940 try {
1941 res = def(resolve, reject);
1942 } catch (e) {
1943 reject(e);
1944 }
1945 if (res) {
1946 if (typeof res.then === 'function') {
1947 res.then(resolve, reject);
1948 } else {
1949 // new syntax in Vue 2.3
1950 var comp = res.component;
1951 if (comp && typeof comp.then === 'function') {
1952 comp.then(resolve, reject);
1953 }
1954 }
1955 }
1956 }
1957 });
1958
1959 if (!hasAsync) { next(); }
1960 }
1961}
1962
1963function flatMapComponents (
1964 matched,
1965 fn
1966) {
1967 return flatten(matched.map(function (m) {
1968 return Object.keys(m.components).map(function (key) { return fn(
1969 m.components[key],
1970 m.instances[key],
1971 m, key
1972 ); })
1973 }))
1974}
1975
1976function flatten (arr) {
1977 return Array.prototype.concat.apply([], arr)
1978}
1979
1980var hasSymbol =
1981 typeof Symbol === 'function' &&
1982 typeof Symbol.toStringTag === 'symbol';
1983
1984function isESModule (obj) {
1985 return obj.__esModule || (hasSymbol && obj[Symbol.toStringTag] === 'Module')
1986}
1987
1988// in Webpack 2, require.ensure now also returns a Promise
1989// so the resolve/reject functions may get called an extra time
1990// if the user uses an arrow function shorthand that happens to
1991// return that Promise.
1992function once (fn) {
1993 var called = false;
1994 return function () {
1995 var args = [], len = arguments.length;
1996 while ( len-- ) args[ len ] = arguments[ len ];
1997
1998 if (called) { return }
1999 called = true;
2000 return fn.apply(this, args)
2001 }
2002}
2003
2004var NavigationDuplicated = /*@__PURE__*/(function (Error) {
2005 function NavigationDuplicated (normalizedLocation) {
2006 Error.call(this);
2007 this.name = this._name = 'NavigationDuplicated';
2008 // passing the message to super() doesn't seem to work in the transpiled version
2009 this.message = "Navigating to current location (\"" + (normalizedLocation.fullPath) + "\") is not allowed";
2010 // add a stack property so services like Sentry can correctly display it
2011 Object.defineProperty(this, 'stack', {
2012 value: new Error().stack,
2013 writable: true,
2014 configurable: true
2015 });
2016 // we could also have used
2017 // Error.captureStackTrace(this, this.constructor)
2018 // but it only exists on node and chrome
2019 }
2020
2021 if ( Error ) NavigationDuplicated.__proto__ = Error;
2022 NavigationDuplicated.prototype = Object.create( Error && Error.prototype );
2023 NavigationDuplicated.prototype.constructor = NavigationDuplicated;
2024
2025 return NavigationDuplicated;
2026}(Error));
2027
2028// support IE9
2029NavigationDuplicated._name = 'NavigationDuplicated';
2030
2031/* */
2032
2033var History = function History (router, base) {
2034 this.router = router;
2035 this.base = normalizeBase(base);
2036 // start with a route object that stands for "nowhere"
2037 this.current = START;
2038 this.pending = null;
2039 this.ready = false;
2040 this.readyCbs = [];
2041 this.readyErrorCbs = [];
2042 this.errorCbs = [];
2043};
2044
2045History.prototype.listen = function listen (cb) {
2046 this.cb = cb;
2047};
2048
2049History.prototype.onReady = function onReady (cb, errorCb) {
2050 if (this.ready) {
2051 cb();
2052 } else {
2053 this.readyCbs.push(cb);
2054 if (errorCb) {
2055 this.readyErrorCbs.push(errorCb);
2056 }
2057 }
2058};
2059
2060History.prototype.onError = function onError (errorCb) {
2061 this.errorCbs.push(errorCb);
2062};
2063
2064History.prototype.transitionTo = function transitionTo (
2065 location,
2066 onComplete,
2067 onAbort
2068) {
2069 var this$1 = this;
2070
2071 var route = this.router.match(location, this.current);
2072 this.confirmTransition(
2073 route,
2074 function () {
2075 this$1.updateRoute(route);
2076 onComplete && onComplete(route);
2077 this$1.ensureURL();
2078
2079 // fire ready cbs once
2080 if (!this$1.ready) {
2081 this$1.ready = true;
2082 this$1.readyCbs.forEach(function (cb) {
2083 cb(route);
2084 });
2085 }
2086 },
2087 function (err) {
2088 if (onAbort) {
2089 onAbort(err);
2090 }
2091 if (err && !this$1.ready) {
2092 this$1.ready = true;
2093 this$1.readyErrorCbs.forEach(function (cb) {
2094 cb(err);
2095 });
2096 }
2097 }
2098 );
2099};
2100
2101History.prototype.confirmTransition = function confirmTransition (route, onComplete, onAbort) {
2102 var this$1 = this;
2103
2104 var current = this.current;
2105 var abort = function (err) {
2106 // after merging https://github.com/vuejs/vue-router/pull/2771 we
2107 // When the user navigates through history through back/forward buttons
2108 // we do not want to throw the error. We only throw it if directly calling
2109 // push/replace. That's why it's not included in isError
2110 if (!isExtendedError(NavigationDuplicated, err) && isError(err)) {
2111 if (this$1.errorCbs.length) {
2112 this$1.errorCbs.forEach(function (cb) {
2113 cb(err);
2114 });
2115 } else {
2116 warn(false, 'uncaught error during route navigation:');
2117 console.error(err);
2118 }
2119 }
2120 onAbort && onAbort(err);
2121 };
2122 if (
2123 isSameRoute(route, current) &&
2124 // in the case the route map has been dynamically appended to
2125 route.matched.length === current.matched.length
2126 ) {
2127 this.ensureURL();
2128 return abort(new NavigationDuplicated(route))
2129 }
2130
2131 var ref = resolveQueue(
2132 this.current.matched,
2133 route.matched
2134 );
2135 var updated = ref.updated;
2136 var deactivated = ref.deactivated;
2137 var activated = ref.activated;
2138
2139 var queue = [].concat(
2140 // in-component leave guards
2141 extractLeaveGuards(deactivated),
2142 // global before hooks
2143 this.router.beforeHooks,
2144 // in-component update hooks
2145 extractUpdateHooks(updated),
2146 // in-config enter guards
2147 activated.map(function (m) { return m.beforeEnter; }),
2148 // async components
2149 resolveAsyncComponents(activated)
2150 );
2151
2152 this.pending = route;
2153 var iterator = function (hook, next) {
2154 if (this$1.pending !== route) {
2155 return abort()
2156 }
2157 try {
2158 hook(route, current, function (to) {
2159 if (to === false || isError(to)) {
2160 // next(false) -> abort navigation, ensure current URL
2161 this$1.ensureURL(true);
2162 abort(to);
2163 } else if (
2164 typeof to === 'string' ||
2165 (typeof to === 'object' &&
2166 (typeof to.path === 'string' || typeof to.name === 'string'))
2167 ) {
2168 // next('/') or next({ path: '/' }) -> redirect
2169 abort();
2170 if (typeof to === 'object' && to.replace) {
2171 this$1.replace(to);
2172 } else {
2173 this$1.push(to);
2174 }
2175 } else {
2176 // confirm transition and pass on the value
2177 next(to);
2178 }
2179 });
2180 } catch (e) {
2181 abort(e);
2182 }
2183 };
2184
2185 runQueue(queue, iterator, function () {
2186 var postEnterCbs = [];
2187 var isValid = function () { return this$1.current === route; };
2188 // wait until async components are resolved before
2189 // extracting in-component enter guards
2190 var enterGuards = extractEnterGuards(activated, postEnterCbs, isValid);
2191 var queue = enterGuards.concat(this$1.router.resolveHooks);
2192 runQueue(queue, iterator, function () {
2193 if (this$1.pending !== route) {
2194 return abort()
2195 }
2196 this$1.pending = null;
2197 onComplete(route);
2198 if (this$1.router.app) {
2199 this$1.router.app.$nextTick(function () {
2200 postEnterCbs.forEach(function (cb) {
2201 cb();
2202 });
2203 });
2204 }
2205 });
2206 });
2207};
2208
2209History.prototype.updateRoute = function updateRoute (route) {
2210 var prev = this.current;
2211 this.current = route;
2212 this.cb && this.cb(route);
2213 this.router.afterHooks.forEach(function (hook) {
2214 hook && hook(route, prev);
2215 });
2216};
2217
2218function normalizeBase (base) {
2219 if (!base) {
2220 if (inBrowser) {
2221 // respect <base> tag
2222 var baseEl = document.querySelector('base');
2223 base = (baseEl && baseEl.getAttribute('href')) || '/';
2224 // strip full URL origin
2225 base = base.replace(/^https?:\/\/[^\/]+/, '');
2226 } else {
2227 base = '/';
2228 }
2229 }
2230 // make sure there's the starting slash
2231 if (base.charAt(0) !== '/') {
2232 base = '/' + base;
2233 }
2234 // remove trailing slash
2235 return base.replace(/\/$/, '')
2236}
2237
2238function resolveQueue (
2239 current,
2240 next
2241) {
2242 var i;
2243 var max = Math.max(current.length, next.length);
2244 for (i = 0; i < max; i++) {
2245 if (current[i] !== next[i]) {
2246 break
2247 }
2248 }
2249 return {
2250 updated: next.slice(0, i),
2251 activated: next.slice(i),
2252 deactivated: current.slice(i)
2253 }
2254}
2255
2256function extractGuards (
2257 records,
2258 name,
2259 bind,
2260 reverse
2261) {
2262 var guards = flatMapComponents(records, function (def, instance, match, key) {
2263 var guard = extractGuard(def, name);
2264 if (guard) {
2265 return Array.isArray(guard)
2266 ? guard.map(function (guard) { return bind(guard, instance, match, key); })
2267 : bind(guard, instance, match, key)
2268 }
2269 });
2270 return flatten(reverse ? guards.reverse() : guards)
2271}
2272
2273function extractGuard (
2274 def,
2275 key
2276) {
2277 if (typeof def !== 'function') {
2278 // extend now so that global mixins are applied.
2279 def = _Vue.extend(def);
2280 }
2281 return def.options[key]
2282}
2283
2284function extractLeaveGuards (deactivated) {
2285 return extractGuards(deactivated, 'beforeRouteLeave', bindGuard, true)
2286}
2287
2288function extractUpdateHooks (updated) {
2289 return extractGuards(updated, 'beforeRouteUpdate', bindGuard)
2290}
2291
2292function bindGuard (guard, instance) {
2293 if (instance) {
2294 return function boundRouteGuard () {
2295 return guard.apply(instance, arguments)
2296 }
2297 }
2298}
2299
2300function extractEnterGuards (
2301 activated,
2302 cbs,
2303 isValid
2304) {
2305 return extractGuards(
2306 activated,
2307 'beforeRouteEnter',
2308 function (guard, _, match, key) {
2309 return bindEnterGuard(guard, match, key, cbs, isValid)
2310 }
2311 )
2312}
2313
2314function bindEnterGuard (
2315 guard,
2316 match,
2317 key,
2318 cbs,
2319 isValid
2320) {
2321 return function routeEnterGuard (to, from, next) {
2322 return guard(to, from, function (cb) {
2323 if (typeof cb === 'function') {
2324 cbs.push(function () {
2325 // #750
2326 // if a router-view is wrapped with an out-in transition,
2327 // the instance may not have been registered at this time.
2328 // we will need to poll for registration until current route
2329 // is no longer valid.
2330 poll(cb, match.instances, key, isValid);
2331 });
2332 }
2333 next(cb);
2334 })
2335 }
2336}
2337
2338function poll (
2339 cb, // somehow flow cannot infer this is a function
2340 instances,
2341 key,
2342 isValid
2343) {
2344 if (
2345 instances[key] &&
2346 !instances[key]._isBeingDestroyed // do not reuse being destroyed instance
2347 ) {
2348 cb(instances[key]);
2349 } else if (isValid()) {
2350 setTimeout(function () {
2351 poll(cb, instances, key, isValid);
2352 }, 16);
2353 }
2354}
2355
2356/* */
2357
2358var HTML5History = /*@__PURE__*/(function (History) {
2359 function HTML5History (router, base) {
2360 var this$1 = this;
2361
2362 History.call(this, router, base);
2363
2364 var expectScroll = router.options.scrollBehavior;
2365 var supportsScroll = supportsPushState && expectScroll;
2366
2367 if (supportsScroll) {
2368 setupScroll();
2369 }
2370
2371 var initLocation = getLocation(this.base);
2372 window.addEventListener('popstate', function (e) {
2373 var current = this$1.current;
2374
2375 // Avoiding first `popstate` event dispatched in some browsers but first
2376 // history route not updated since async guard at the same time.
2377 var location = getLocation(this$1.base);
2378 if (this$1.current === START && location === initLocation) {
2379 return
2380 }
2381
2382 this$1.transitionTo(location, function (route) {
2383 if (supportsScroll) {
2384 handleScroll(router, route, current, true);
2385 }
2386 });
2387 });
2388 }
2389
2390 if ( History ) HTML5History.__proto__ = History;
2391 HTML5History.prototype = Object.create( History && History.prototype );
2392 HTML5History.prototype.constructor = HTML5History;
2393
2394 HTML5History.prototype.go = function go (n) {
2395 window.history.go(n);
2396 };
2397
2398 HTML5History.prototype.push = function push (location, onComplete, onAbort) {
2399 var this$1 = this;
2400
2401 var ref = this;
2402 var fromRoute = ref.current;
2403 this.transitionTo(location, function (route) {
2404 pushState(cleanPath(this$1.base + route.fullPath));
2405 handleScroll(this$1.router, route, fromRoute, false);
2406 onComplete && onComplete(route);
2407 }, onAbort);
2408 };
2409
2410 HTML5History.prototype.replace = function replace (location, onComplete, onAbort) {
2411 var this$1 = this;
2412
2413 var ref = this;
2414 var fromRoute = ref.current;
2415 this.transitionTo(location, function (route) {
2416 replaceState(cleanPath(this$1.base + route.fullPath));
2417 handleScroll(this$1.router, route, fromRoute, false);
2418 onComplete && onComplete(route);
2419 }, onAbort);
2420 };
2421
2422 HTML5History.prototype.ensureURL = function ensureURL (push) {
2423 if (getLocation(this.base) !== this.current.fullPath) {
2424 var current = cleanPath(this.base + this.current.fullPath);
2425 push ? pushState(current) : replaceState(current);
2426 }
2427 };
2428
2429 HTML5History.prototype.getCurrentLocation = function getCurrentLocation () {
2430 return getLocation(this.base)
2431 };
2432
2433 return HTML5History;
2434}(History));
2435
2436function getLocation (base) {
2437 var path = decodeURI(window.location.pathname);
2438 if (base && path.indexOf(base) === 0) {
2439 path = path.slice(base.length);
2440 }
2441 return (path || '/') + window.location.search + window.location.hash
2442}
2443
2444/* */
2445
2446var HashHistory = /*@__PURE__*/(function (History) {
2447 function HashHistory (router, base, fallback) {
2448 History.call(this, router, base);
2449 // check history fallback deeplinking
2450 if (fallback && checkFallback(this.base)) {
2451 return
2452 }
2453 ensureSlash();
2454 }
2455
2456 if ( History ) HashHistory.__proto__ = History;
2457 HashHistory.prototype = Object.create( History && History.prototype );
2458 HashHistory.prototype.constructor = HashHistory;
2459
2460 // this is delayed until the app mounts
2461 // to avoid the hashchange listener being fired too early
2462 HashHistory.prototype.setupListeners = function setupListeners () {
2463 var this$1 = this;
2464
2465 var router = this.router;
2466 var expectScroll = router.options.scrollBehavior;
2467 var supportsScroll = supportsPushState && expectScroll;
2468
2469 if (supportsScroll) {
2470 setupScroll();
2471 }
2472
2473 window.addEventListener(
2474 supportsPushState ? 'popstate' : 'hashchange',
2475 function () {
2476 var current = this$1.current;
2477 if (!ensureSlash()) {
2478 return
2479 }
2480 this$1.transitionTo(getHash(), function (route) {
2481 if (supportsScroll) {
2482 handleScroll(this$1.router, route, current, true);
2483 }
2484 if (!supportsPushState) {
2485 replaceHash(route.fullPath);
2486 }
2487 });
2488 }
2489 );
2490 };
2491
2492 HashHistory.prototype.push = function push (location, onComplete, onAbort) {
2493 var this$1 = this;
2494
2495 var ref = this;
2496 var fromRoute = ref.current;
2497 this.transitionTo(
2498 location,
2499 function (route) {
2500 pushHash(route.fullPath);
2501 handleScroll(this$1.router, route, fromRoute, false);
2502 onComplete && onComplete(route);
2503 },
2504 onAbort
2505 );
2506 };
2507
2508 HashHistory.prototype.replace = function replace (location, onComplete, onAbort) {
2509 var this$1 = this;
2510
2511 var ref = this;
2512 var fromRoute = ref.current;
2513 this.transitionTo(
2514 location,
2515 function (route) {
2516 replaceHash(route.fullPath);
2517 handleScroll(this$1.router, route, fromRoute, false);
2518 onComplete && onComplete(route);
2519 },
2520 onAbort
2521 );
2522 };
2523
2524 HashHistory.prototype.go = function go (n) {
2525 window.history.go(n);
2526 };
2527
2528 HashHistory.prototype.ensureURL = function ensureURL (push) {
2529 var current = this.current.fullPath;
2530 if (getHash() !== current) {
2531 push ? pushHash(current) : replaceHash(current);
2532 }
2533 };
2534
2535 HashHistory.prototype.getCurrentLocation = function getCurrentLocation () {
2536 return getHash()
2537 };
2538
2539 return HashHistory;
2540}(History));
2541
2542function checkFallback (base) {
2543 var location = getLocation(base);
2544 if (!/^\/#/.test(location)) {
2545 window.location.replace(cleanPath(base + '/#' + location));
2546 return true
2547 }
2548}
2549
2550function ensureSlash () {
2551 var path = getHash();
2552 if (path.charAt(0) === '/') {
2553 return true
2554 }
2555 replaceHash('/' + path);
2556 return false
2557}
2558
2559function getHash () {
2560 // We can't use window.location.hash here because it's not
2561 // consistent across browsers - Firefox will pre-decode it!
2562 var href = window.location.href;
2563 var index = href.indexOf('#');
2564 // empty path
2565 if (index < 0) { return '' }
2566
2567 href = href.slice(index + 1);
2568 // decode the hash but not the search or hash
2569 // as search(query) is already decoded
2570 // https://github.com/vuejs/vue-router/issues/2708
2571 var searchIndex = href.indexOf('?');
2572 if (searchIndex < 0) {
2573 var hashIndex = href.indexOf('#');
2574 if (hashIndex > -1) {
2575 href = decodeURI(href.slice(0, hashIndex)) + href.slice(hashIndex);
2576 } else { href = decodeURI(href); }
2577 } else {
2578 href = decodeURI(href.slice(0, searchIndex)) + href.slice(searchIndex);
2579 }
2580
2581 return href
2582}
2583
2584function getUrl (path) {
2585 var href = window.location.href;
2586 var i = href.indexOf('#');
2587 var base = i >= 0 ? href.slice(0, i) : href;
2588 return (base + "#" + path)
2589}
2590
2591function pushHash (path) {
2592 if (supportsPushState) {
2593 pushState(getUrl(path));
2594 } else {
2595 window.location.hash = path;
2596 }
2597}
2598
2599function replaceHash (path) {
2600 if (supportsPushState) {
2601 replaceState(getUrl(path));
2602 } else {
2603 window.location.replace(getUrl(path));
2604 }
2605}
2606
2607/* */
2608
2609var AbstractHistory = /*@__PURE__*/(function (History) {
2610 function AbstractHistory (router, base) {
2611 History.call(this, router, base);
2612 this.stack = [];
2613 this.index = -1;
2614 }
2615
2616 if ( History ) AbstractHistory.__proto__ = History;
2617 AbstractHistory.prototype = Object.create( History && History.prototype );
2618 AbstractHistory.prototype.constructor = AbstractHistory;
2619
2620 AbstractHistory.prototype.push = function push (location, onComplete, onAbort) {
2621 var this$1 = this;
2622
2623 this.transitionTo(
2624 location,
2625 function (route) {
2626 this$1.stack = this$1.stack.slice(0, this$1.index + 1).concat(route);
2627 this$1.index++;
2628 onComplete && onComplete(route);
2629 },
2630 onAbort
2631 );
2632 };
2633
2634 AbstractHistory.prototype.replace = function replace (location, onComplete, onAbort) {
2635 var this$1 = this;
2636
2637 this.transitionTo(
2638 location,
2639 function (route) {
2640 this$1.stack = this$1.stack.slice(0, this$1.index).concat(route);
2641 onComplete && onComplete(route);
2642 },
2643 onAbort
2644 );
2645 };
2646
2647 AbstractHistory.prototype.go = function go (n) {
2648 var this$1 = this;
2649
2650 var targetIndex = this.index + n;
2651 if (targetIndex < 0 || targetIndex >= this.stack.length) {
2652 return
2653 }
2654 var route = this.stack[targetIndex];
2655 this.confirmTransition(
2656 route,
2657 function () {
2658 this$1.index = targetIndex;
2659 this$1.updateRoute(route);
2660 },
2661 function (err) {
2662 if (isExtendedError(NavigationDuplicated, err)) {
2663 this$1.index = targetIndex;
2664 }
2665 }
2666 );
2667 };
2668
2669 AbstractHistory.prototype.getCurrentLocation = function getCurrentLocation () {
2670 var current = this.stack[this.stack.length - 1];
2671 return current ? current.fullPath : '/'
2672 };
2673
2674 AbstractHistory.prototype.ensureURL = function ensureURL () {
2675 // noop
2676 };
2677
2678 return AbstractHistory;
2679}(History));
2680
2681/* */
2682
2683
2684
2685var VueRouter = function VueRouter (options) {
2686 if ( options === void 0 ) options = {};
2687
2688 this.app = null;
2689 this.apps = [];
2690 this.options = options;
2691 this.beforeHooks = [];
2692 this.resolveHooks = [];
2693 this.afterHooks = [];
2694 this.matcher = createMatcher(options.routes || [], this);
2695
2696 var mode = options.mode || 'hash';
2697 this.fallback = mode === 'history' && !supportsPushState && options.fallback !== false;
2698 if (this.fallback) {
2699 mode = 'hash';
2700 }
2701 if (!inBrowser) {
2702 mode = 'abstract';
2703 }
2704 this.mode = mode;
2705
2706 switch (mode) {
2707 case 'history':
2708 this.history = new HTML5History(this, options.base);
2709 break
2710 case 'hash':
2711 this.history = new HashHistory(this, options.base, this.fallback);
2712 break
2713 case 'abstract':
2714 this.history = new AbstractHistory(this, options.base);
2715 break
2716 default:
2717 if (process.env.NODE_ENV !== 'production') {
2718 assert(false, ("invalid mode: " + mode));
2719 }
2720 }
2721};
2722
2723var prototypeAccessors = { currentRoute: { configurable: true } };
2724
2725VueRouter.prototype.match = function match (
2726 raw,
2727 current,
2728 redirectedFrom
2729) {
2730 return this.matcher.match(raw, current, redirectedFrom)
2731};
2732
2733prototypeAccessors.currentRoute.get = function () {
2734 return this.history && this.history.current
2735};
2736
2737VueRouter.prototype.init = function init (app /* Vue component instance */) {
2738 var this$1 = this;
2739
2740 process.env.NODE_ENV !== 'production' && assert(
2741 install.installed,
2742 "not installed. Make sure to call `Vue.use(VueRouter)` " +
2743 "before creating root instance."
2744 );
2745
2746 this.apps.push(app);
2747
2748 // set up app destroyed handler
2749 // https://github.com/vuejs/vue-router/issues/2639
2750 app.$once('hook:destroyed', function () {
2751 // clean out app from this.apps array once destroyed
2752 var index = this$1.apps.indexOf(app);
2753 if (index > -1) { this$1.apps.splice(index, 1); }
2754 // ensure we still have a main app or null if no apps
2755 // we do not release the router so it can be reused
2756 if (this$1.app === app) { this$1.app = this$1.apps[0] || null; }
2757 });
2758
2759 // main app previously initialized
2760 // return as we don't need to set up new history listener
2761 if (this.app) {
2762 return
2763 }
2764
2765 this.app = app;
2766
2767 var history = this.history;
2768
2769 if (history instanceof HTML5History) {
2770 history.transitionTo(history.getCurrentLocation());
2771 } else if (history instanceof HashHistory) {
2772 var setupHashListener = function () {
2773 history.setupListeners();
2774 };
2775 history.transitionTo(
2776 history.getCurrentLocation(),
2777 setupHashListener,
2778 setupHashListener
2779 );
2780 }
2781
2782 history.listen(function (route) {
2783 this$1.apps.forEach(function (app) {
2784 app._route = route;
2785 });
2786 });
2787};
2788
2789VueRouter.prototype.beforeEach = function beforeEach (fn) {
2790 return registerHook(this.beforeHooks, fn)
2791};
2792
2793VueRouter.prototype.beforeResolve = function beforeResolve (fn) {
2794 return registerHook(this.resolveHooks, fn)
2795};
2796
2797VueRouter.prototype.afterEach = function afterEach (fn) {
2798 return registerHook(this.afterHooks, fn)
2799};
2800
2801VueRouter.prototype.onReady = function onReady (cb, errorCb) {
2802 this.history.onReady(cb, errorCb);
2803};
2804
2805VueRouter.prototype.onError = function onError (errorCb) {
2806 this.history.onError(errorCb);
2807};
2808
2809VueRouter.prototype.push = function push (location, onComplete, onAbort) {
2810 var this$1 = this;
2811
2812 // $flow-disable-line
2813 if (!onComplete && !onAbort && typeof Promise !== 'undefined') {
2814 return new Promise(function (resolve, reject) {
2815 this$1.history.push(location, resolve, reject);
2816 })
2817 } else {
2818 this.history.push(location, onComplete, onAbort);
2819 }
2820};
2821
2822VueRouter.prototype.replace = function replace (location, onComplete, onAbort) {
2823 var this$1 = this;
2824
2825 // $flow-disable-line
2826 if (!onComplete && !onAbort && typeof Promise !== 'undefined') {
2827 return new Promise(function (resolve, reject) {
2828 this$1.history.replace(location, resolve, reject);
2829 })
2830 } else {
2831 this.history.replace(location, onComplete, onAbort);
2832 }
2833};
2834
2835VueRouter.prototype.go = function go (n) {
2836 this.history.go(n);
2837};
2838
2839VueRouter.prototype.back = function back () {
2840 this.go(-1);
2841};
2842
2843VueRouter.prototype.forward = function forward () {
2844 this.go(1);
2845};
2846
2847VueRouter.prototype.getMatchedComponents = function getMatchedComponents (to) {
2848 var route = to
2849 ? to.matched
2850 ? to
2851 : this.resolve(to).route
2852 : this.currentRoute;
2853 if (!route) {
2854 return []
2855 }
2856 return [].concat.apply([], route.matched.map(function (m) {
2857 return Object.keys(m.components).map(function (key) {
2858 return m.components[key]
2859 })
2860 }))
2861};
2862
2863VueRouter.prototype.resolve = function resolve (
2864 to,
2865 current,
2866 append
2867) {
2868 current = current || this.history.current;
2869 var location = normalizeLocation(
2870 to,
2871 current,
2872 append,
2873 this
2874 );
2875 var route = this.match(location, current);
2876 var fullPath = route.redirectedFrom || route.fullPath;
2877 var base = this.history.base;
2878 var href = createHref(base, fullPath, this.mode);
2879 return {
2880 location: location,
2881 route: route,
2882 href: href,
2883 // for backwards compat
2884 normalizedTo: location,
2885 resolved: route
2886 }
2887};
2888
2889VueRouter.prototype.addRoutes = function addRoutes (routes) {
2890 this.matcher.addRoutes(routes);
2891 if (this.history.current !== START) {
2892 this.history.transitionTo(this.history.getCurrentLocation());
2893 }
2894};
2895
2896Object.defineProperties( VueRouter.prototype, prototypeAccessors );
2897
2898function registerHook (list, fn) {
2899 list.push(fn);
2900 return function () {
2901 var i = list.indexOf(fn);
2902 if (i > -1) { list.splice(i, 1); }
2903 }
2904}
2905
2906function createHref (base, fullPath, mode) {
2907 var path = mode === 'hash' ? '#' + fullPath : fullPath;
2908 return base ? cleanPath(base + '/' + path) : path
2909}
2910
2911VueRouter.install = install;
2912VueRouter.version = '3.1.6';
2913
2914if (inBrowser && window.Vue) {
2915 window.Vue.use(VueRouter);
2916}
2917
2918export default VueRouter;
2919