PageSourceSearch

https://redator.ai/dependencies/vue-router.js

js redator.ai collected 2026-10-05 14:49:08 UTC 62,331 bytes, 2,513 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.