diff --git a/dist/www/lib/vue-router.common.js b/dist/www/lib/vue-router.common.js
new file mode 100644
index 0000000..c9eb5a1
--- /dev/null
+++ b/dist/www/lib/vue-router.common.js
@@ -0,0 +1,2625 @@
+/**
+ * vue-router v3.0.1
+ * (c) 2017 Evan You
+ * @license MIT
+ */
+'use strict';
+
+/* */
+
+function assert (condition, message) {
+ if (!condition) {
+ throw new Error(("[vue-router] " + message))
+ }
+}
+
+function warn (condition, message) {
+ if (process.env.NODE_ENV !== 'production' && !condition) {
+ typeof console !== 'undefined' && console.warn(("[vue-router] " + message));
+ }
+}
+
+function isError (err) {
+ return Object.prototype.toString.call(err).indexOf('Error') > -1
+}
+
+var View = {
+ name: 'router-view',
+ functional: true,
+ props: {
+ name: {
+ type: String,
+ default: 'default'
+ }
+ },
+ render: function render (_, ref) {
+ var props = ref.props;
+ var children = ref.children;
+ var parent = ref.parent;
+ var data = ref.data;
+
+ data.routerView = true;
+
+ // directly use parent context's createElement() function
+ // so that components rendered by router-view can resolve named slots
+ var h = parent.$createElement;
+ var name = props.name;
+ var route = parent.$route;
+ var cache = parent._routerViewCache || (parent._routerViewCache = {});
+
+ // determine current view depth, also check to see if the tree
+ // has been toggled inactive but kept-alive.
+ var depth = 0;
+ var inactive = false;
+ while (parent && parent._routerRoot !== parent) {
+ if (parent.$vnode && parent.$vnode.data.routerView) {
+ depth++;
+ }
+ if (parent._inactive) {
+ inactive = true;
+ }
+ parent = parent.$parent;
+ }
+ data.routerViewDepth = depth;
+
+ // render previous view if the tree is inactive and kept-alive
+ if (inactive) {
+ return h(cache[name], data, children)
+ }
+
+ var matched = route.matched[depth];
+ // render empty node if no matched route
+ if (!matched) {
+ cache[name] = null;
+ return h()
+ }
+
+ var component = cache[name] = matched.components[name];
+
+ // attach instance registration hook
+ // this will be called in the instance's injected lifecycle hooks
+ data.registerRouteInstance = function (vm, val) {
+ // val could be undefined for unregistration
+ var current = matched.instances[name];
+ if (
+ (val && current !== vm) ||
+ (!val && current === vm)
+ ) {
+ matched.instances[name] = val;
+ }
+ }
+
+ // also register instance in prepatch hook
+ // in case the same component instance is reused across different routes
+ ;(data.hook || (data.hook = {})).prepatch = function (_, vnode) {
+ matched.instances[name] = vnode.componentInstance;
+ };
+
+ // resolve props
+ var propsToPass = data.props = resolveProps(route, matched.props && matched.props[name]);
+ if (propsToPass) {
+ // clone to prevent mutation
+ propsToPass = data.props = extend({}, propsToPass);
+ // pass non-declared props as attrs
+ var attrs = data.attrs = data.attrs || {};
+ for (var key in propsToPass) {
+ if (!component.props || !(key in component.props)) {
+ attrs[key] = propsToPass[key];
+ delete propsToPass[key];
+ }
+ }
+ }
+
+ return h(component, data, children)
+ }
+};
+
+function resolveProps (route, config) {
+ switch (typeof config) {
+ case 'undefined':
+ return
+ case 'object':
+ return config
+ case 'function':
+ return config(route)
+ case 'boolean':
+ return config ? route.params : undefined
+ default:
+ if (process.env.NODE_ENV !== 'production') {
+ warn(
+ false,
+ "props in \"" + (route.path) + "\" is a " + (typeof config) + ", " +
+ "expecting an object, function or boolean."
+ );
+ }
+ }
+}
+
+function extend (to, from) {
+ for (var key in from) {
+ to[key] = from[key];
+ }
+ return to
+}
+
+/* */
+
+var encodeReserveRE = /[!'()*]/g;
+var encodeReserveReplacer = function (c) { return '%' + c.charCodeAt(0).toString(16); };
+var commaRE = /%2C/g;
+
+// fixed encodeURIComponent which is more conformant to RFC3986:
+// - escapes [!'()*]
+// - preserve commas
+var encode = function (str) { return encodeURIComponent(str)
+ .replace(encodeReserveRE, encodeReserveReplacer)
+ .replace(commaRE, ','); };
+
+var decode = decodeURIComponent;
+
+function resolveQuery (
+ query,
+ extraQuery,
+ _parseQuery
+) {
+ if ( extraQuery === void 0 ) extraQuery = {};
+
+ var parse = _parseQuery || parseQuery;
+ var parsedQuery;
+ try {
+ parsedQuery = parse(query || '');
+ } catch (e) {
+ process.env.NODE_ENV !== 'production' && warn(false, e.message);
+ parsedQuery = {};
+ }
+ for (var key in extraQuery) {
+ parsedQuery[key] = extraQuery[key];
+ }
+ return parsedQuery
+}
+
+function parseQuery (query) {
+ var res = {};
+
+ query = query.trim().replace(/^(\?|#|&)/, '');
+
+ if (!query) {
+ return res
+ }
+
+ query.split('&').forEach(function (param) {
+ var parts = param.replace(/\+/g, ' ').split('=');
+ var key = decode(parts.shift());
+ var val = parts.length > 0
+ ? decode(parts.join('='))
+ : null;
+
+ if (res[key] === undefined) {
+ res[key] = val;
+ } else if (Array.isArray(res[key])) {
+ res[key].push(val);
+ } else {
+ res[key] = [res[key], val];
+ }
+ });
+
+ return res
+}
+
+function stringifyQuery (obj) {
+ var res = obj ? Object.keys(obj).map(function (key) {
+ var val = obj[key];
+
+ if (val === undefined) {
+ return ''
+ }
+
+ if (val === null) {
+ return encode(key)
+ }
+
+ if (Array.isArray(val)) {
+ var result = [];
+ val.forEach(function (val2) {
+ if (val2 === undefined) {
+ return
+ }
+ if (val2 === null) {
+ result.push(encode(key));
+ } else {
+ result.push(encode(key) + '=' + encode(val2));
+ }
+ });
+ return result.join('&')
+ }
+
+ return encode(key) + '=' + encode(val)
+ }).filter(function (x) { return x.length > 0; }).join('&') : null;
+ return res ? ("?" + res) : ''
+}
+
+/* */
+
+
+var trailingSlashRE = /\/?$/;
+
+function createRoute (
+ record,
+ location,
+ redirectedFrom,
+ router
+) {
+ var stringifyQuery$$1 = router && router.options.stringifyQuery;
+
+ var query = location.query || {};
+ try {
+ query = clone(query);
+ } catch (e) {}
+
+ var route = {
+ name: location.name || (record && record.name),
+ meta: (record && record.meta) || {},
+ path: location.path || '/',
+ hash: location.hash || '',
+ query: query,
+ params: location.params || {},
+ fullPath: getFullPath(location, stringifyQuery$$1),
+ matched: record ? formatMatch(record) : []
+ };
+ if (redirectedFrom) {
+ route.redirectedFrom = getFullPath(redirectedFrom, stringifyQuery$$1);
+ }
+ return Object.freeze(route)
+}
+
+function clone (value) {
+ if (Array.isArray(value)) {
+ return value.map(clone)
+ } else if (value && typeof value === 'object') {
+ var res = {};
+ for (var key in value) {
+ res[key] = clone(value[key]);
+ }
+ return res
+ } else {
+ return value
+ }
+}
+
+// the starting route that represents the initial state
+var START = createRoute(null, {
+ path: '/'
+});
+
+function formatMatch (record) {
+ var res = [];
+ while (record) {
+ res.unshift(record);
+ record = record.parent;
+ }
+ return res
+}
+
+function getFullPath (
+ ref,
+ _stringifyQuery
+) {
+ var path = ref.path;
+ var query = ref.query; if ( query === void 0 ) query = {};
+ var hash = ref.hash; if ( hash === void 0 ) hash = '';
+
+ var stringify = _stringifyQuery || stringifyQuery;
+ return (path || '/') + stringify(query) + hash
+}
+
+function isSameRoute (a, b) {
+ if (b === START) {
+ return a === b
+ } else if (!b) {
+ return false
+ } else if (a.path && b.path) {
+ return (
+ a.path.replace(trailingSlashRE, '') === b.path.replace(trailingSlashRE, '') &&
+ a.hash === b.hash &&
+ isObjectEqual(a.query, b.query)
+ )
+ } else if (a.name && b.name) {
+ return (
+ a.name === b.name &&
+ a.hash === b.hash &&
+ isObjectEqual(a.query, b.query) &&
+ isObjectEqual(a.params, b.params)
+ )
+ } else {
+ return false
+ }
+}
+
+function isObjectEqual (a, b) {
+ if ( a === void 0 ) a = {};
+ if ( b === void 0 ) b = {};
+
+ // handle null value #1566
+ if (!a || !b) { return a === b }
+ var aKeys = Object.keys(a);
+ var bKeys = Object.keys(b);
+ if (aKeys.length !== bKeys.length) {
+ return false
+ }
+ return aKeys.every(function (key) {
+ var aVal = a[key];
+ var bVal = b[key];
+ // check nested equality
+ if (typeof aVal === 'object' && typeof bVal === 'object') {
+ return isObjectEqual(aVal, bVal)
+ }
+ return String(aVal) === String(bVal)
+ })
+}
+
+function isIncludedRoute (current, target) {
+ return (
+ current.path.replace(trailingSlashRE, '/').indexOf(
+ target.path.replace(trailingSlashRE, '/')
+ ) === 0 &&
+ (!target.hash || current.hash === target.hash) &&
+ queryIncludes(current.query, target.query)
+ )
+}
+
+function queryIncludes (current, target) {
+ for (var key in target) {
+ if (!(key in current)) {
+ return false
+ }
+ }
+ return true
+}
+
+/* */
+
+// work around weird flow bug
+var toTypes = [String, Object];
+var eventTypes = [String, Array];
+
+var Link = {
+ name: 'router-link',
+ props: {
+ to: {
+ type: toTypes,
+ required: true
+ },
+ tag: {
+ type: String,
+ default: 'a'
+ },
+ exact: Boolean,
+ append: Boolean,
+ replace: Boolean,
+ activeClass: String,
+ exactActiveClass: String,
+ event: {
+ type: eventTypes,
+ default: 'click'
+ }
+ },
+ render: function render (h) {
+ var this$1 = this;
+
+ var router = this.$router;
+ var current = this.$route;
+ var ref = router.resolve(this.to, current, this.append);
+ var location = ref.location;
+ var route = ref.route;
+ var href = ref.href;
+
+ var classes = {};
+ var globalActiveClass = router.options.linkActiveClass;
+ var globalExactActiveClass = router.options.linkExactActiveClass;
+ // Support global empty active class
+ var activeClassFallback = globalActiveClass == null
+ ? 'router-link-active'
+ : globalActiveClass;
+ var exactActiveClassFallback = globalExactActiveClass == null
+ ? 'router-link-exact-active'
+ : globalExactActiveClass;
+ var activeClass = this.activeClass == null
+ ? activeClassFallback
+ : this.activeClass;
+ var exactActiveClass = this.exactActiveClass == null
+ ? exactActiveClassFallback
+ : this.exactActiveClass;
+ var compareTarget = location.path
+ ? createRoute(null, location, null, router)
+ : route;
+
+ classes[exactActiveClass] = isSameRoute(current, compareTarget);
+ classes[activeClass] = this.exact
+ ? classes[exactActiveClass]
+ : isIncludedRoute(current, compareTarget);
+
+ var handler = function (e) {
+ if (guardEvent(e)) {
+ if (this$1.replace) {
+ router.replace(location);
+ } else {
+ router.push(location);
+ }
+ }
+ };
+
+ var on = { click: guardEvent };
+ if (Array.isArray(this.event)) {
+ this.event.forEach(function (e) { on[e] = handler; });
+ } else {
+ on[this.event] = handler;
+ }
+
+ var data = {
+ class: classes
+ };
+
+ if (this.tag === 'a') {
+ data.on = on;
+ data.attrs = { href: href };
+ } else {
+ // find the first child and apply listener and href
+ var a = findAnchor(this.$slots.default);
+ if (a) {
+ // in case the is a static node
+ a.isStatic = false;
+ var extend = _Vue.util.extend;
+ var aData = a.data = extend({}, a.data);
+ aData.on = on;
+ var aAttrs = a.data.attrs = extend({}, a.data.attrs);
+ aAttrs.href = href;
+ } else {
+ // doesn't have child, apply listener to self
+ data.on = on;
+ }
+ }
+
+ return h(this.tag, data, this.$slots.default)
+ }
+};
+
+function guardEvent (e) {
+ // don't redirect with control keys
+ if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) { return }
+ // don't redirect when preventDefault called
+ if (e.defaultPrevented) { return }
+ // don't redirect on right click
+ if (e.button !== undefined && e.button !== 0) { return }
+ // don't redirect if `target="_blank"`
+ if (e.currentTarget && e.currentTarget.getAttribute) {
+ var target = e.currentTarget.getAttribute('target');
+ if (/\b_blank\b/i.test(target)) { return }
+ }
+ // this may be a Weex event which doesn't have this method
+ if (e.preventDefault) {
+ e.preventDefault();
+ }
+ return true
+}
+
+function findAnchor (children) {
+ if (children) {
+ var child;
+ for (var i = 0; i < children.length; i++) {
+ child = children[i];
+ if (child.tag === 'a') {
+ return child
+ }
+ if (child.children && (child = findAnchor(child.children))) {
+ return child
+ }
+ }
+ }
+}
+
+var _Vue;
+
+function install (Vue) {
+ if (install.installed && _Vue === Vue) { return }
+ install.installed = true;
+
+ _Vue = Vue;
+
+ var isDef = function (v) { return v !== undefined; };
+
+ var registerInstance = function (vm, callVal) {
+ var i = vm.$options._parentVnode;
+ if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
+ i(vm, callVal);
+ }
+ };
+
+ Vue.mixin({
+ beforeCreate: function beforeCreate () {
+ if (isDef(this.$options.router)) {
+ this._routerRoot = this;
+ this._router = this.$options.router;
+ this._router.init(this);
+ Vue.util.defineReactive(this, '_route', this._router.history.current);
+ } else {
+ this._routerRoot = (this.$parent && this.$parent._routerRoot) || this;
+ }
+ registerInstance(this, this);
+ },
+ destroyed: function destroyed () {
+ registerInstance(this);
+ }
+ });
+
+ Object.defineProperty(Vue.prototype, '$router', {
+ get: function get () { return this._routerRoot._router }
+ });
+
+ Object.defineProperty(Vue.prototype, '$route', {
+ get: function get () { return this._routerRoot._route }
+ });
+
+ Vue.component('router-view', View);
+ Vue.component('router-link', Link);
+
+ var strats = Vue.config.optionMergeStrategies;
+ // use the same hook merging strategy for route hooks
+ strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created;
+}
+
+/* */
+
+var inBrowser = typeof window !== 'undefined';
+
+/* */
+
+function resolvePath (
+ relative,
+ base,
+ append
+) {
+ var firstChar = relative.charAt(0);
+ if (firstChar === '/') {
+ return relative
+ }
+
+ if (firstChar === '?' || firstChar === '#') {
+ return base + relative
+ }
+
+ var stack = base.split('/');
+
+ // remove trailing segment if:
+ // - not appending
+ // - appending to trailing slash (last segment is empty)
+ if (!append || !stack[stack.length - 1]) {
+ stack.pop();
+ }
+
+ // resolve relative path
+ var segments = relative.replace(/^\//, '').split('/');
+ for (var i = 0; i < segments.length; i++) {
+ var segment = segments[i];
+ if (segment === '..') {
+ stack.pop();
+ } else if (segment !== '.') {
+ stack.push(segment);
+ }
+ }
+
+ // ensure leading slash
+ if (stack[0] !== '') {
+ stack.unshift('');
+ }
+
+ return stack.join('/')
+}
+
+function parsePath (path) {
+ var hash = '';
+ var query = '';
+
+ var hashIndex = path.indexOf('#');
+ if (hashIndex >= 0) {
+ hash = path.slice(hashIndex);
+ path = path.slice(0, hashIndex);
+ }
+
+ var queryIndex = path.indexOf('?');
+ if (queryIndex >= 0) {
+ query = path.slice(queryIndex + 1);
+ path = path.slice(0, queryIndex);
+ }
+
+ return {
+ path: path,
+ query: query,
+ hash: hash
+ }
+}
+
+function cleanPath (path) {
+ return path.replace(/\/\//g, '/')
+}
+
+var isarray = Array.isArray || function (arr) {
+ return Object.prototype.toString.call(arr) == '[object Array]';
+};
+
+/**
+ * Expose `pathToRegexp`.
+ */
+var pathToRegexp_1 = pathToRegexp;
+var parse_1 = parse;
+var compile_1 = compile;
+var tokensToFunction_1 = tokensToFunction;
+var tokensToRegExp_1 = tokensToRegExp;
+
+/**
+ * The main path matching regexp utility.
+ *
+ * @type {RegExp}
+ */
+var PATH_REGEXP = new RegExp([
+ // Match escaped characters that would otherwise appear in future matches.
+ // This allows the user to escape special characters that won't transform.
+ '(\\\\.)',
+ // Match Express-style parameters and un-named parameters with a prefix
+ // and optional suffixes. Matches appear as:
+ //
+ // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined]
+ // "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined, undefined]
+ // "/*" => ["/", undefined, undefined, undefined, undefined, "*"]
+ '([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))'
+].join('|'), 'g');
+
+/**
+ * Parse a string for the raw tokens.
+ *
+ * @param {string} str
+ * @param {Object=} options
+ * @return {!Array}
+ */
+function parse (str, options) {
+ var tokens = [];
+ var key = 0;
+ var index = 0;
+ var path = '';
+ var defaultDelimiter = options && options.delimiter || '/';
+ var res;
+
+ while ((res = PATH_REGEXP.exec(str)) != null) {
+ var m = res[0];
+ var escaped = res[1];
+ var offset = res.index;
+ path += str.slice(index, offset);
+ index = offset + m.length;
+
+ // Ignore already escaped sequences.
+ if (escaped) {
+ path += escaped[1];
+ continue
+ }
+
+ var next = str[index];
+ var prefix = res[2];
+ var name = res[3];
+ var capture = res[4];
+ var group = res[5];
+ var modifier = res[6];
+ var asterisk = res[7];
+
+ // Push the current path onto the tokens.
+ if (path) {
+ tokens.push(path);
+ path = '';
+ }
+
+ var partial = prefix != null && next != null && next !== prefix;
+ var repeat = modifier === '+' || modifier === '*';
+ var optional = modifier === '?' || modifier === '*';
+ var delimiter = res[2] || defaultDelimiter;
+ var pattern = capture || group;
+
+ tokens.push({
+ name: name || key++,
+ prefix: prefix || '',
+ delimiter: delimiter,
+ optional: optional,
+ repeat: repeat,
+ partial: partial,
+ asterisk: !!asterisk,
+ pattern: pattern ? escapeGroup(pattern) : (asterisk ? '.*' : '[^' + escapeString(delimiter) + ']+?')
+ });
+ }
+
+ // Match any characters still remaining.
+ if (index < str.length) {
+ path += str.substr(index);
+ }
+
+ // If the path exists, push it onto the end.
+ if (path) {
+ tokens.push(path);
+ }
+
+ return tokens
+}
+
+/**
+ * Compile a string to a template function for the path.
+ *
+ * @param {string} str
+ * @param {Object=} options
+ * @return {!function(Object=, Object=)}
+ */
+function compile (str, options) {
+ return tokensToFunction(parse(str, options))
+}
+
+/**
+ * Prettier encoding of URI path segments.
+ *
+ * @param {string}
+ * @return {string}
+ */
+function encodeURIComponentPretty (str) {
+ return encodeURI(str).replace(/[\/?#]/g, function (c) {
+ return '%' + c.charCodeAt(0).toString(16).toUpperCase()
+ })
+}
+
+/**
+ * Encode the asterisk parameter. Similar to `pretty`, but allows slashes.
+ *
+ * @param {string}
+ * @return {string}
+ */
+function encodeAsterisk (str) {
+ return encodeURI(str).replace(/[?#]/g, function (c) {
+ return '%' + c.charCodeAt(0).toString(16).toUpperCase()
+ })
+}
+
+/**
+ * Expose a method for transforming tokens into the path function.
+ */
+function tokensToFunction (tokens) {
+ // Compile all the tokens into regexps.
+ var matches = new Array(tokens.length);
+
+ // Compile all the patterns before compilation.
+ for (var i = 0; i < tokens.length; i++) {
+ if (typeof tokens[i] === 'object') {
+ matches[i] = new RegExp('^(?:' + tokens[i].pattern + ')$');
+ }
+ }
+
+ return function (obj, opts) {
+ var path = '';
+ var data = obj || {};
+ var options = opts || {};
+ var encode = options.pretty ? encodeURIComponentPretty : encodeURIComponent;
+
+ for (var i = 0; i < tokens.length; i++) {
+ var token = tokens[i];
+
+ if (typeof token === 'string') {
+ path += token;
+
+ continue
+ }
+
+ var value = data[token.name];
+ var segment;
+
+ if (value == null) {
+ if (token.optional) {
+ // Prepend partial segment prefixes.
+ if (token.partial) {
+ path += token.prefix;
+ }
+
+ continue
+ } else {
+ throw new TypeError('Expected "' + token.name + '" to be defined')
+ }
+ }
+
+ if (isarray(value)) {
+ if (!token.repeat) {
+ throw new TypeError('Expected "' + token.name + '" to not repeat, but received `' + JSON.stringify(value) + '`')
+ }
+
+ if (value.length === 0) {
+ if (token.optional) {
+ continue
+ } else {
+ throw new TypeError('Expected "' + token.name + '" to not be empty')
+ }
+ }
+
+ for (var j = 0; j < value.length; j++) {
+ segment = encode(value[j]);
+
+ if (!matches[i].test(segment)) {
+ throw new TypeError('Expected all "' + token.name + '" to match "' + token.pattern + '", but received `' + JSON.stringify(segment) + '`')
+ }
+
+ path += (j === 0 ? token.prefix : token.delimiter) + segment;
+ }
+
+ continue
+ }
+
+ segment = token.asterisk ? encodeAsterisk(value) : encode(value);
+
+ if (!matches[i].test(segment)) {
+ throw new TypeError('Expected "' + token.name + '" to match "' + token.pattern + '", but received "' + segment + '"')
+ }
+
+ path += token.prefix + segment;
+ }
+
+ return path
+ }
+}
+
+/**
+ * Escape a regular expression string.
+ *
+ * @param {string} str
+ * @return {string}
+ */
+function escapeString (str) {
+ return str.replace(/([.+*?=^!:${}()[\]|\/\\])/g, '\\$1')
+}
+
+/**
+ * Escape the capturing group by escaping special characters and meaning.
+ *
+ * @param {string} group
+ * @return {string}
+ */
+function escapeGroup (group) {
+ return group.replace(/([=!:$\/()])/g, '\\$1')
+}
+
+/**
+ * Attach the keys as a property of the regexp.
+ *
+ * @param {!RegExp} re
+ * @param {Array} keys
+ * @return {!RegExp}
+ */
+function attachKeys (re, keys) {
+ re.keys = keys;
+ return re
+}
+
+/**
+ * Get the flags for a regexp from the options.
+ *
+ * @param {Object} options
+ * @return {string}
+ */
+function flags (options) {
+ return options.sensitive ? '' : 'i'
+}
+
+/**
+ * Pull out keys from a regexp.
+ *
+ * @param {!RegExp} path
+ * @param {!Array} keys
+ * @return {!RegExp}
+ */
+function regexpToRegexp (path, keys) {
+ // Use a negative lookahead to match only capturing groups.
+ var groups = path.source.match(/\((?!\?)/g);
+
+ if (groups) {
+ for (var i = 0; i < groups.length; i++) {
+ keys.push({
+ name: i,
+ prefix: null,
+ delimiter: null,
+ optional: false,
+ repeat: false,
+ partial: false,
+ asterisk: false,
+ pattern: null
+ });
+ }
+ }
+
+ return attachKeys(path, keys)
+}
+
+/**
+ * Transform an array into a regexp.
+ *
+ * @param {!Array} path
+ * @param {Array} keys
+ * @param {!Object} options
+ * @return {!RegExp}
+ */
+function arrayToRegexp (path, keys, options) {
+ var parts = [];
+
+ for (var i = 0; i < path.length; i++) {
+ parts.push(pathToRegexp(path[i], keys, options).source);
+ }
+
+ var regexp = new RegExp('(?:' + parts.join('|') + ')', flags(options));
+
+ return attachKeys(regexp, keys)
+}
+
+/**
+ * Create a path regexp from string input.
+ *
+ * @param {string} path
+ * @param {!Array} keys
+ * @param {!Object} options
+ * @return {!RegExp}
+ */
+function stringToRegexp (path, keys, options) {
+ return tokensToRegExp(parse(path, options), keys, options)
+}
+
+/**
+ * Expose a function for taking tokens and returning a RegExp.
+ *
+ * @param {!Array} tokens
+ * @param {(Array|Object)=} keys
+ * @param {Object=} options
+ * @return {!RegExp}
+ */
+function tokensToRegExp (tokens, keys, options) {
+ if (!isarray(keys)) {
+ options = /** @type {!Object} */ (keys || options);
+ keys = [];
+ }
+
+ options = options || {};
+
+ var strict = options.strict;
+ var end = options.end !== false;
+ var route = '';
+
+ // Iterate over the tokens and create our regexp string.
+ for (var i = 0; i < tokens.length; i++) {
+ var token = tokens[i];
+
+ if (typeof token === 'string') {
+ route += escapeString(token);
+ } else {
+ var prefix = escapeString(token.prefix);
+ var capture = '(?:' + token.pattern + ')';
+
+ keys.push(token);
+
+ if (token.repeat) {
+ capture += '(?:' + prefix + capture + ')*';
+ }
+
+ if (token.optional) {
+ if (!token.partial) {
+ capture = '(?:' + prefix + '(' + capture + '))?';
+ } else {
+ capture = prefix + '(' + capture + ')?';
+ }
+ } else {
+ capture = prefix + '(' + capture + ')';
+ }
+
+ route += capture;
+ }
+ }
+
+ var delimiter = escapeString(options.delimiter || '/');
+ var endsWithDelimiter = route.slice(-delimiter.length) === delimiter;
+
+ // In non-strict mode we allow a slash at the end of match. If the path to
+ // match already ends with a slash, we remove it for consistency. The slash
+ // is valid at the end of a path match, not in the middle. This is important
+ // in non-ending mode, where "/test/" shouldn't match "/test//route".
+ if (!strict) {
+ route = (endsWithDelimiter ? route.slice(0, -delimiter.length) : route) + '(?:' + delimiter + '(?=$))?';
+ }
+
+ if (end) {
+ route += '$';
+ } else {
+ // In non-ending mode, we need the capturing groups to match as much as
+ // possible by using a positive lookahead to the end or next path segment.
+ route += strict && endsWithDelimiter ? '' : '(?=' + delimiter + '|$)';
+ }
+
+ return attachKeys(new RegExp('^' + route, flags(options)), keys)
+}
+
+/**
+ * Normalize the given path string, returning a regular expression.
+ *
+ * An empty array can be passed in for the keys, which will hold the
+ * placeholder key descriptions. For example, using `/user/:id`, `keys` will
+ * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.
+ *
+ * @param {(string|RegExp|Array)} path
+ * @param {(Array|Object)=} keys
+ * @param {Object=} options
+ * @return {!RegExp}
+ */
+function pathToRegexp (path, keys, options) {
+ if (!isarray(keys)) {
+ options = /** @type {!Object} */ (keys || options);
+ keys = [];
+ }
+
+ options = options || {};
+
+ if (path instanceof RegExp) {
+ return regexpToRegexp(path, /** @type {!Array} */ (keys))
+ }
+
+ if (isarray(path)) {
+ return arrayToRegexp(/** @type {!Array} */ (path), /** @type {!Array} */ (keys), options)
+ }
+
+ return stringToRegexp(/** @type {string} */ (path), /** @type {!Array} */ (keys), options)
+}
+
+pathToRegexp_1.parse = parse_1;
+pathToRegexp_1.compile = compile_1;
+pathToRegexp_1.tokensToFunction = tokensToFunction_1;
+pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
+
+/* */
+
+// $flow-disable-line
+var regexpCompileCache = Object.create(null);
+
+function fillParams (
+ path,
+ params,
+ routeMsg
+) {
+ try {
+ var filler =
+ regexpCompileCache[path] ||
+ (regexpCompileCache[path] = pathToRegexp_1.compile(path));
+ return filler(params || {}, { pretty: true })
+ } catch (e) {
+ if (process.env.NODE_ENV !== 'production') {
+ warn(false, ("missing param for " + routeMsg + ": " + (e.message)));
+ }
+ return ''
+ }
+}
+
+/* */
+
+function createRouteMap (
+ routes,
+ oldPathList,
+ oldPathMap,
+ oldNameMap
+) {
+ // the path list is used to control path matching priority
+ var pathList = oldPathList || [];
+ // $flow-disable-line
+ var pathMap = oldPathMap || Object.create(null);
+ // $flow-disable-line
+ var nameMap = oldNameMap || Object.create(null);
+
+ routes.forEach(function (route) {
+ addRouteRecord(pathList, pathMap, nameMap, route);
+ });
+
+ // ensure wildcard routes are always at the end
+ for (var i = 0, l = pathList.length; i < l; i++) {
+ if (pathList[i] === '*') {
+ pathList.push(pathList.splice(i, 1)[0]);
+ l--;
+ i--;
+ }
+ }
+
+ return {
+ pathList: pathList,
+ pathMap: pathMap,
+ nameMap: nameMap
+ }
+}
+
+function addRouteRecord (
+ pathList,
+ pathMap,
+ nameMap,
+ route,
+ parent,
+ matchAs
+) {
+ var path = route.path;
+ var name = route.name;
+ if (process.env.NODE_ENV !== 'production') {
+ assert(path != null, "\"path\" is required in a route configuration.");
+ assert(
+ typeof route.component !== 'string',
+ "route config \"component\" for path: " + (String(path || name)) + " cannot be a " +
+ "string id. Use an actual component instead."
+ );
+ }
+
+ var pathToRegexpOptions = route.pathToRegexpOptions || {};
+ var normalizedPath = normalizePath(
+ path,
+ parent,
+ pathToRegexpOptions.strict
+ );
+
+ if (typeof route.caseSensitive === 'boolean') {
+ pathToRegexpOptions.sensitive = route.caseSensitive;
+ }
+
+ var record = {
+ path: normalizedPath,
+ regex: compileRouteRegex(normalizedPath, pathToRegexpOptions),
+ components: route.components || { default: route.component },
+ instances: {},
+ name: name,
+ parent: parent,
+ matchAs: matchAs,
+ redirect: route.redirect,
+ beforeEnter: route.beforeEnter,
+ meta: route.meta || {},
+ props: route.props == null
+ ? {}
+ : route.components
+ ? route.props
+ : { default: route.props }
+ };
+
+ if (route.children) {
+ // Warn if route is named, does not redirect and has a default child route.
+ // If users navigate to this route by name, the default child will
+ // not be rendered (GH Issue #629)
+ if (process.env.NODE_ENV !== 'production') {
+ if (route.name && !route.redirect && route.children.some(function (child) { return /^\/?$/.test(child.path); })) {
+ warn(
+ false,
+ "Named Route '" + (route.name) + "' has a default child route. " +
+ "When navigating to this named route (:to=\"{name: '" + (route.name) + "'\"), " +
+ "the default child route will not be rendered. Remove the name from " +
+ "this route and use the name of the default child route for named " +
+ "links instead."
+ );
+ }
+ }
+ route.children.forEach(function (child) {
+ var childMatchAs = matchAs
+ ? cleanPath((matchAs + "/" + (child.path)))
+ : undefined;
+ addRouteRecord(pathList, pathMap, nameMap, child, record, childMatchAs);
+ });
+ }
+
+ if (route.alias !== undefined) {
+ var aliases = Array.isArray(route.alias)
+ ? route.alias
+ : [route.alias];
+
+ aliases.forEach(function (alias) {
+ var aliasRoute = {
+ path: alias,
+ children: route.children
+ };
+ addRouteRecord(
+ pathList,
+ pathMap,
+ nameMap,
+ aliasRoute,
+ parent,
+ record.path || '/' // matchAs
+ );
+ });
+ }
+
+ if (!pathMap[record.path]) {
+ pathList.push(record.path);
+ pathMap[record.path] = record;
+ }
+
+ if (name) {
+ if (!nameMap[name]) {
+ nameMap[name] = record;
+ } else if (process.env.NODE_ENV !== 'production' && !matchAs) {
+ warn(
+ false,
+ "Duplicate named routes definition: " +
+ "{ name: \"" + name + "\", path: \"" + (record.path) + "\" }"
+ );
+ }
+ }
+}
+
+function compileRouteRegex (path, pathToRegexpOptions) {
+ var regex = pathToRegexp_1(path, [], pathToRegexpOptions);
+ if (process.env.NODE_ENV !== 'production') {
+ var keys = Object.create(null);
+ regex.keys.forEach(function (key) {
+ warn(!keys[key.name], ("Duplicate param keys in route with path: \"" + path + "\""));
+ keys[key.name] = true;
+ });
+ }
+ return regex
+}
+
+function normalizePath (path, parent, strict) {
+ if (!strict) { path = path.replace(/\/$/, ''); }
+ if (path[0] === '/') { return path }
+ if (parent == null) { return path }
+ return cleanPath(((parent.path) + "/" + path))
+}
+
+/* */
+
+
+function normalizeLocation (
+ raw,
+ current,
+ append,
+ router
+) {
+ var next = typeof raw === 'string' ? { path: raw } : raw;
+ // named target
+ if (next.name || next._normalized) {
+ return next
+ }
+
+ // relative params
+ if (!next.path && next.params && current) {
+ next = assign({}, next);
+ next._normalized = true;
+ var params = assign(assign({}, current.params), next.params);
+ if (current.name) {
+ next.name = current.name;
+ next.params = params;
+ } else if (current.matched.length) {
+ var rawPath = current.matched[current.matched.length - 1].path;
+ next.path = fillParams(rawPath, params, ("path " + (current.path)));
+ } else if (process.env.NODE_ENV !== 'production') {
+ warn(false, "relative params navigation requires a current route.");
+ }
+ return next
+ }
+
+ var parsedPath = parsePath(next.path || '');
+ var basePath = (current && current.path) || '/';
+ var path = parsedPath.path
+ ? resolvePath(parsedPath.path, basePath, append || next.append)
+ : basePath;
+
+ var query = resolveQuery(
+ parsedPath.query,
+ next.query,
+ router && router.options.parseQuery
+ );
+
+ var hash = next.hash || parsedPath.hash;
+ if (hash && hash.charAt(0) !== '#') {
+ hash = "#" + hash;
+ }
+
+ return {
+ _normalized: true,
+ path: path,
+ query: query,
+ hash: hash
+ }
+}
+
+function assign (a, b) {
+ for (var key in b) {
+ a[key] = b[key];
+ }
+ return a
+}
+
+/* */
+
+
+function createMatcher (
+ routes,
+ router
+) {
+ var ref = createRouteMap(routes);
+ var pathList = ref.pathList;
+ var pathMap = ref.pathMap;
+ var nameMap = ref.nameMap;
+
+ function addRoutes (routes) {
+ createRouteMap(routes, pathList, pathMap, nameMap);
+ }
+
+ function match (
+ raw,
+ currentRoute,
+ redirectedFrom
+ ) {
+ var location = normalizeLocation(raw, currentRoute, false, router);
+ var name = location.name;
+
+ if (name) {
+ var record = nameMap[name];
+ if (process.env.NODE_ENV !== 'production') {
+ warn(record, ("Route with name '" + name + "' does not exist"));
+ }
+ if (!record) { return _createRoute(null, location) }
+ var paramNames = record.regex.keys
+ .filter(function (key) { return !key.optional; })
+ .map(function (key) { return key.name; });
+
+ if (typeof location.params !== 'object') {
+ location.params = {};
+ }
+
+ if (currentRoute && typeof currentRoute.params === 'object') {
+ for (var key in currentRoute.params) {
+ if (!(key in location.params) && paramNames.indexOf(key) > -1) {
+ location.params[key] = currentRoute.params[key];
+ }
+ }
+ }
+
+ if (record) {
+ location.path = fillParams(record.path, location.params, ("named route \"" + name + "\""));
+ return _createRoute(record, location, redirectedFrom)
+ }
+ } else if (location.path) {
+ location.params = {};
+ for (var i = 0; i < pathList.length; i++) {
+ var path = pathList[i];
+ var record$1 = pathMap[path];
+ if (matchRoute(record$1.regex, location.path, location.params)) {
+ return _createRoute(record$1, location, redirectedFrom)
+ }
+ }
+ }
+ // no match
+ return _createRoute(null, location)
+ }
+
+ function redirect (
+ record,
+ location
+ ) {
+ var originalRedirect = record.redirect;
+ var redirect = typeof originalRedirect === 'function'
+ ? originalRedirect(createRoute(record, location, null, router))
+ : originalRedirect;
+
+ if (typeof redirect === 'string') {
+ redirect = { path: redirect };
+ }
+
+ if (!redirect || typeof redirect !== 'object') {
+ if (process.env.NODE_ENV !== 'production') {
+ warn(
+ false, ("invalid redirect option: " + (JSON.stringify(redirect)))
+ );
+ }
+ return _createRoute(null, location)
+ }
+
+ var re = redirect;
+ var name = re.name;
+ var path = re.path;
+ var query = location.query;
+ var hash = location.hash;
+ var params = location.params;
+ query = re.hasOwnProperty('query') ? re.query : query;
+ hash = re.hasOwnProperty('hash') ? re.hash : hash;
+ params = re.hasOwnProperty('params') ? re.params : params;
+
+ if (name) {
+ // resolved named direct
+ var targetRecord = nameMap[name];
+ if (process.env.NODE_ENV !== 'production') {
+ assert(targetRecord, ("redirect failed: named route \"" + name + "\" not found."));
+ }
+ return match({
+ _normalized: true,
+ name: name,
+ query: query,
+ hash: hash,
+ params: params
+ }, undefined, location)
+ } else if (path) {
+ // 1. resolve relative redirect
+ var rawPath = resolveRecordPath(path, record);
+ // 2. resolve params
+ var resolvedPath = fillParams(rawPath, params, ("redirect route with path \"" + rawPath + "\""));
+ // 3. rematch with existing query and hash
+ return match({
+ _normalized: true,
+ path: resolvedPath,
+ query: query,
+ hash: hash
+ }, undefined, location)
+ } else {
+ if (process.env.NODE_ENV !== 'production') {
+ warn(false, ("invalid redirect option: " + (JSON.stringify(redirect))));
+ }
+ return _createRoute(null, location)
+ }
+ }
+
+ function alias (
+ record,
+ location,
+ matchAs
+ ) {
+ var aliasedPath = fillParams(matchAs, location.params, ("aliased route with path \"" + matchAs + "\""));
+ var aliasedMatch = match({
+ _normalized: true,
+ path: aliasedPath
+ });
+ if (aliasedMatch) {
+ var matched = aliasedMatch.matched;
+ var aliasedRecord = matched[matched.length - 1];
+ location.params = aliasedMatch.params;
+ return _createRoute(aliasedRecord, location)
+ }
+ return _createRoute(null, location)
+ }
+
+ function _createRoute (
+ record,
+ location,
+ redirectedFrom
+ ) {
+ if (record && record.redirect) {
+ return redirect(record, redirectedFrom || location)
+ }
+ if (record && record.matchAs) {
+ return alias(record, location, record.matchAs)
+ }
+ return createRoute(record, location, redirectedFrom, router)
+ }
+
+ return {
+ match: match,
+ addRoutes: addRoutes
+ }
+}
+
+function matchRoute (
+ regex,
+ path,
+ params
+) {
+ var m = path.match(regex);
+
+ if (!m) {
+ return false
+ } else if (!params) {
+ return true
+ }
+
+ for (var i = 1, len = m.length; i < len; ++i) {
+ var key = regex.keys[i - 1];
+ var val = typeof m[i] === 'string' ? decodeURIComponent(m[i]) : m[i];
+ if (key) {
+ params[key.name] = val;
+ }
+ }
+
+ return true
+}
+
+function resolveRecordPath (path, record) {
+ return resolvePath(path, record.parent ? record.parent.path : '/', true)
+}
+
+/* */
+
+
+var positionStore = Object.create(null);
+
+function setupScroll () {
+ // Fix for #1585 for Firefox
+ window.history.replaceState({ key: getStateKey() }, '');
+ window.addEventListener('popstate', function (e) {
+ saveScrollPosition();
+ if (e.state && e.state.key) {
+ setStateKey(e.state.key);
+ }
+ });
+}
+
+function handleScroll (
+ router,
+ to,
+ from,
+ isPop
+) {
+ if (!router.app) {
+ return
+ }
+
+ var behavior = router.options.scrollBehavior;
+ if (!behavior) {
+ return
+ }
+
+ if (process.env.NODE_ENV !== 'production') {
+ assert(typeof behavior === 'function', "scrollBehavior must be a function");
+ }
+
+ // wait until re-render finishes before scrolling
+ router.app.$nextTick(function () {
+ var position = getScrollPosition();
+ var shouldScroll = behavior(to, from, isPop ? position : null);
+
+ if (!shouldScroll) {
+ return
+ }
+
+ if (typeof shouldScroll.then === 'function') {
+ shouldScroll.then(function (shouldScroll) {
+ scrollToPosition((shouldScroll), position);
+ }).catch(function (err) {
+ if (process.env.NODE_ENV !== 'production') {
+ assert(false, err.toString());
+ }
+ });
+ } else {
+ scrollToPosition(shouldScroll, position);
+ }
+ });
+}
+
+function saveScrollPosition () {
+ var key = getStateKey();
+ if (key) {
+ positionStore[key] = {
+ x: window.pageXOffset,
+ y: window.pageYOffset
+ };
+ }
+}
+
+function getScrollPosition () {
+ var key = getStateKey();
+ if (key) {
+ return positionStore[key]
+ }
+}
+
+function getElementPosition (el, offset) {
+ var docEl = document.documentElement;
+ var docRect = docEl.getBoundingClientRect();
+ var elRect = el.getBoundingClientRect();
+ return {
+ x: elRect.left - docRect.left - offset.x,
+ y: elRect.top - docRect.top - offset.y
+ }
+}
+
+function isValidPosition (obj) {
+ return isNumber(obj.x) || isNumber(obj.y)
+}
+
+function normalizePosition (obj) {
+ return {
+ x: isNumber(obj.x) ? obj.x : window.pageXOffset,
+ y: isNumber(obj.y) ? obj.y : window.pageYOffset
+ }
+}
+
+function normalizeOffset (obj) {
+ return {
+ x: isNumber(obj.x) ? obj.x : 0,
+ y: isNumber(obj.y) ? obj.y : 0
+ }
+}
+
+function isNumber (v) {
+ return typeof v === 'number'
+}
+
+function scrollToPosition (shouldScroll, position) {
+ var isObject = typeof shouldScroll === 'object';
+ if (isObject && typeof shouldScroll.selector === 'string') {
+ var el = document.querySelector(shouldScroll.selector);
+ if (el) {
+ var offset = shouldScroll.offset && typeof shouldScroll.offset === 'object' ? shouldScroll.offset : {};
+ offset = normalizeOffset(offset);
+ position = getElementPosition(el, offset);
+ } else if (isValidPosition(shouldScroll)) {
+ position = normalizePosition(shouldScroll);
+ }
+ } else if (isObject && isValidPosition(shouldScroll)) {
+ position = normalizePosition(shouldScroll);
+ }
+
+ if (position) {
+ window.scrollTo(position.x, position.y);
+ }
+}
+
+/* */
+
+var supportsPushState = inBrowser && (function () {
+ var ua = window.navigator.userAgent;
+
+ if (
+ (ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) &&
+ ua.indexOf('Mobile Safari') !== -1 &&
+ ua.indexOf('Chrome') === -1 &&
+ ua.indexOf('Windows Phone') === -1
+ ) {
+ return false
+ }
+
+ return window.history && 'pushState' in window.history
+})();
+
+// use User Timing api (if present) for more accurate key precision
+var Time = inBrowser && window.performance && window.performance.now
+ ? window.performance
+ : Date;
+
+var _key = genKey();
+
+function genKey () {
+ return Time.now().toFixed(3)
+}
+
+function getStateKey () {
+ return _key
+}
+
+function setStateKey (key) {
+ _key = key;
+}
+
+function pushState (url, replace) {
+ saveScrollPosition();
+ // try...catch the pushState call to get around Safari
+ // DOM Exception 18 where it limits to 100 pushState calls
+ var history = window.history;
+ try {
+ if (replace) {
+ history.replaceState({ key: _key }, '', url);
+ } else {
+ _key = genKey();
+ history.pushState({ key: _key }, '', url);
+ }
+ } catch (e) {
+ window.location[replace ? 'replace' : 'assign'](url);
+ }
+}
+
+function replaceState (url) {
+ pushState(url, true);
+}
+
+/* */
+
+function runQueue (queue, fn, cb) {
+ var step = function (index) {
+ if (index >= queue.length) {
+ cb();
+ } else {
+ if (queue[index]) {
+ fn(queue[index], function () {
+ step(index + 1);
+ });
+ } else {
+ step(index + 1);
+ }
+ }
+ };
+ step(0);
+}
+
+/* */
+
+function resolveAsyncComponents (matched) {
+ return function (to, from, next) {
+ var hasAsync = false;
+ var pending = 0;
+ var error = null;
+
+ flatMapComponents(matched, function (def, _, match, key) {
+ // if it's a function and doesn't have cid attached,
+ // assume it's an async component resolve function.
+ // we are not using Vue's default async resolving mechanism because
+ // we want to halt the navigation until the incoming component has been
+ // resolved.
+ if (typeof def === 'function' && def.cid === undefined) {
+ hasAsync = true;
+ pending++;
+
+ var resolve = once(function (resolvedDef) {
+ if (isESModule(resolvedDef)) {
+ resolvedDef = resolvedDef.default;
+ }
+ // save resolved on async factory in case it's used elsewhere
+ def.resolved = typeof resolvedDef === 'function'
+ ? resolvedDef
+ : _Vue.extend(resolvedDef);
+ match.components[key] = resolvedDef;
+ pending--;
+ if (pending <= 0) {
+ next();
+ }
+ });
+
+ var reject = once(function (reason) {
+ var msg = "Failed to resolve async component " + key + ": " + reason;
+ process.env.NODE_ENV !== 'production' && warn(false, msg);
+ if (!error) {
+ error = isError(reason)
+ ? reason
+ : new Error(msg);
+ next(error);
+ }
+ });
+
+ var res;
+ try {
+ res = def(resolve, reject);
+ } catch (e) {
+ reject(e);
+ }
+ if (res) {
+ if (typeof res.then === 'function') {
+ res.then(resolve, reject);
+ } else {
+ // new syntax in Vue 2.3
+ var comp = res.component;
+ if (comp && typeof comp.then === 'function') {
+ comp.then(resolve, reject);
+ }
+ }
+ }
+ }
+ });
+
+ if (!hasAsync) { next(); }
+ }
+}
+
+function flatMapComponents (
+ matched,
+ fn
+) {
+ return flatten(matched.map(function (m) {
+ return Object.keys(m.components).map(function (key) { return fn(
+ m.components[key],
+ m.instances[key],
+ m, key
+ ); })
+ }))
+}
+
+function flatten (arr) {
+ return Array.prototype.concat.apply([], arr)
+}
+
+var hasSymbol =
+ typeof Symbol === 'function' &&
+ typeof Symbol.toStringTag === 'symbol';
+
+function isESModule (obj) {
+ return obj.__esModule || (hasSymbol && obj[Symbol.toStringTag] === 'Module')
+}
+
+// in Webpack 2, require.ensure now also returns a Promise
+// so the resolve/reject functions may get called an extra time
+// if the user uses an arrow function shorthand that happens to
+// return that Promise.
+function once (fn) {
+ var called = false;
+ return function () {
+ var args = [], len = arguments.length;
+ while ( len-- ) args[ len ] = arguments[ len ];
+
+ if (called) { return }
+ called = true;
+ return fn.apply(this, args)
+ }
+}
+
+/* */
+
+var History = function History (router, base) {
+ this.router = router;
+ this.base = normalizeBase(base);
+ // start with a route object that stands for "nowhere"
+ this.current = START;
+ this.pending = null;
+ this.ready = false;
+ this.readyCbs = [];
+ this.readyErrorCbs = [];
+ this.errorCbs = [];
+};
+
+History.prototype.listen = function listen (cb) {
+ this.cb = cb;
+};
+
+History.prototype.onReady = function onReady (cb, errorCb) {
+ if (this.ready) {
+ cb();
+ } else {
+ this.readyCbs.push(cb);
+ if (errorCb) {
+ this.readyErrorCbs.push(errorCb);
+ }
+ }
+};
+
+History.prototype.onError = function onError (errorCb) {
+ this.errorCbs.push(errorCb);
+};
+
+History.prototype.transitionTo = function transitionTo (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ var route = this.router.match(location, this.current);
+ this.confirmTransition(route, function () {
+ this$1.updateRoute(route);
+ onComplete && onComplete(route);
+ this$1.ensureURL();
+
+ // fire ready cbs once
+ if (!this$1.ready) {
+ this$1.ready = true;
+ this$1.readyCbs.forEach(function (cb) { cb(route); });
+ }
+ }, function (err) {
+ if (onAbort) {
+ onAbort(err);
+ }
+ if (err && !this$1.ready) {
+ this$1.ready = true;
+ this$1.readyErrorCbs.forEach(function (cb) { cb(err); });
+ }
+ });
+};
+
+History.prototype.confirmTransition = function confirmTransition (route, onComplete, onAbort) {
+ var this$1 = this;
+
+ var current = this.current;
+ var abort = function (err) {
+ if (isError(err)) {
+ if (this$1.errorCbs.length) {
+ this$1.errorCbs.forEach(function (cb) { cb(err); });
+ } else {
+ warn(false, 'uncaught error during route navigation:');
+ console.error(err);
+ }
+ }
+ onAbort && onAbort(err);
+ };
+ if (
+ isSameRoute(route, current) &&
+ // in the case the route map has been dynamically appended to
+ route.matched.length === current.matched.length
+ ) {
+ this.ensureURL();
+ return abort()
+ }
+
+ var ref = resolveQueue(this.current.matched, route.matched);
+ var updated = ref.updated;
+ var deactivated = ref.deactivated;
+ var activated = ref.activated;
+
+ var queue = [].concat(
+ // in-component leave guards
+ extractLeaveGuards(deactivated),
+ // global before hooks
+ this.router.beforeHooks,
+ // in-component update hooks
+ extractUpdateHooks(updated),
+ // in-config enter guards
+ activated.map(function (m) { return m.beforeEnter; }),
+ // async components
+ resolveAsyncComponents(activated)
+ );
+
+ this.pending = route;
+ var iterator = function (hook, next) {
+ if (this$1.pending !== route) {
+ return abort()
+ }
+ try {
+ hook(route, current, function (to) {
+ if (to === false || isError(to)) {
+ // next(false) -> abort navigation, ensure current URL
+ this$1.ensureURL(true);
+ abort(to);
+ } else if (
+ typeof to === 'string' ||
+ (typeof to === 'object' && (
+ typeof to.path === 'string' ||
+ typeof to.name === 'string'
+ ))
+ ) {
+ // next('/') or next({ path: '/' }) -> redirect
+ abort();
+ if (typeof to === 'object' && to.replace) {
+ this$1.replace(to);
+ } else {
+ this$1.push(to);
+ }
+ } else {
+ // confirm transition and pass on the value
+ next(to);
+ }
+ });
+ } catch (e) {
+ abort(e);
+ }
+ };
+
+ runQueue(queue, iterator, function () {
+ var postEnterCbs = [];
+ var isValid = function () { return this$1.current === route; };
+ // wait until async components are resolved before
+ // extracting in-component enter guards
+ var enterGuards = extractEnterGuards(activated, postEnterCbs, isValid);
+ var queue = enterGuards.concat(this$1.router.resolveHooks);
+ runQueue(queue, iterator, function () {
+ if (this$1.pending !== route) {
+ return abort()
+ }
+ this$1.pending = null;
+ onComplete(route);
+ if (this$1.router.app) {
+ this$1.router.app.$nextTick(function () {
+ postEnterCbs.forEach(function (cb) { cb(); });
+ });
+ }
+ });
+ });
+};
+
+History.prototype.updateRoute = function updateRoute (route) {
+ var prev = this.current;
+ this.current = route;
+ this.cb && this.cb(route);
+ this.router.afterHooks.forEach(function (hook) {
+ hook && hook(route, prev);
+ });
+};
+
+function normalizeBase (base) {
+ if (!base) {
+ if (inBrowser) {
+ // respect tag
+ var baseEl = document.querySelector('base');
+ base = (baseEl && baseEl.getAttribute('href')) || '/';
+ // strip full URL origin
+ base = base.replace(/^https?:\/\/[^\/]+/, '');
+ } else {
+ base = '/';
+ }
+ }
+ // make sure there's the starting slash
+ if (base.charAt(0) !== '/') {
+ base = '/' + base;
+ }
+ // remove trailing slash
+ return base.replace(/\/$/, '')
+}
+
+function resolveQueue (
+ current,
+ next
+) {
+ var i;
+ var max = Math.max(current.length, next.length);
+ for (i = 0; i < max; i++) {
+ if (current[i] !== next[i]) {
+ break
+ }
+ }
+ return {
+ updated: next.slice(0, i),
+ activated: next.slice(i),
+ deactivated: current.slice(i)
+ }
+}
+
+function extractGuards (
+ records,
+ name,
+ bind,
+ reverse
+) {
+ var guards = flatMapComponents(records, function (def, instance, match, key) {
+ var guard = extractGuard(def, name);
+ if (guard) {
+ return Array.isArray(guard)
+ ? guard.map(function (guard) { return bind(guard, instance, match, key); })
+ : bind(guard, instance, match, key)
+ }
+ });
+ return flatten(reverse ? guards.reverse() : guards)
+}
+
+function extractGuard (
+ def,
+ key
+) {
+ if (typeof def !== 'function') {
+ // extend now so that global mixins are applied.
+ def = _Vue.extend(def);
+ }
+ return def.options[key]
+}
+
+function extractLeaveGuards (deactivated) {
+ return extractGuards(deactivated, 'beforeRouteLeave', bindGuard, true)
+}
+
+function extractUpdateHooks (updated) {
+ return extractGuards(updated, 'beforeRouteUpdate', bindGuard)
+}
+
+function bindGuard (guard, instance) {
+ if (instance) {
+ return function boundRouteGuard () {
+ return guard.apply(instance, arguments)
+ }
+ }
+}
+
+function extractEnterGuards (
+ activated,
+ cbs,
+ isValid
+) {
+ return extractGuards(activated, 'beforeRouteEnter', function (guard, _, match, key) {
+ return bindEnterGuard(guard, match, key, cbs, isValid)
+ })
+}
+
+function bindEnterGuard (
+ guard,
+ match,
+ key,
+ cbs,
+ isValid
+) {
+ return function routeEnterGuard (to, from, next) {
+ return guard(to, from, function (cb) {
+ next(cb);
+ if (typeof cb === 'function') {
+ cbs.push(function () {
+ // #750
+ // if a router-view is wrapped with an out-in transition,
+ // the instance may not have been registered at this time.
+ // we will need to poll for registration until current route
+ // is no longer valid.
+ poll(cb, match.instances, key, isValid);
+ });
+ }
+ })
+ }
+}
+
+function poll (
+ cb, // somehow flow cannot infer this is a function
+ instances,
+ key,
+ isValid
+) {
+ if (instances[key]) {
+ cb(instances[key]);
+ } else if (isValid()) {
+ setTimeout(function () {
+ poll(cb, instances, key, isValid);
+ }, 16);
+ }
+}
+
+/* */
+
+
+var HTML5History = (function (History$$1) {
+ function HTML5History (router, base) {
+ var this$1 = this;
+
+ History$$1.call(this, router, base);
+
+ var expectScroll = router.options.scrollBehavior;
+
+ if (expectScroll) {
+ setupScroll();
+ }
+
+ var initLocation = getLocation(this.base);
+ window.addEventListener('popstate', function (e) {
+ var current = this$1.current;
+
+ // Avoiding first `popstate` event dispatched in some browsers but first
+ // history route not updated since async guard at the same time.
+ var location = getLocation(this$1.base);
+ if (this$1.current === START && location === initLocation) {
+ return
+ }
+
+ this$1.transitionTo(location, function (route) {
+ if (expectScroll) {
+ handleScroll(router, route, current, true);
+ }
+ });
+ });
+ }
+
+ if ( History$$1 ) HTML5History.__proto__ = History$$1;
+ HTML5History.prototype = Object.create( History$$1 && History$$1.prototype );
+ HTML5History.prototype.constructor = HTML5History;
+
+ HTML5History.prototype.go = function go (n) {
+ window.history.go(n);
+ };
+
+ HTML5History.prototype.push = function push (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ var ref = this;
+ var fromRoute = ref.current;
+ this.transitionTo(location, function (route) {
+ pushState(cleanPath(this$1.base + route.fullPath));
+ handleScroll(this$1.router, route, fromRoute, false);
+ onComplete && onComplete(route);
+ }, onAbort);
+ };
+
+ HTML5History.prototype.replace = function replace (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ var ref = this;
+ var fromRoute = ref.current;
+ this.transitionTo(location, function (route) {
+ replaceState(cleanPath(this$1.base + route.fullPath));
+ handleScroll(this$1.router, route, fromRoute, false);
+ onComplete && onComplete(route);
+ }, onAbort);
+ };
+
+ HTML5History.prototype.ensureURL = function ensureURL (push) {
+ if (getLocation(this.base) !== this.current.fullPath) {
+ var current = cleanPath(this.base + this.current.fullPath);
+ push ? pushState(current) : replaceState(current);
+ }
+ };
+
+ HTML5History.prototype.getCurrentLocation = function getCurrentLocation () {
+ return getLocation(this.base)
+ };
+
+ return HTML5History;
+}(History));
+
+function getLocation (base) {
+ var path = window.location.pathname;
+ if (base && path.indexOf(base) === 0) {
+ path = path.slice(base.length);
+ }
+ return (path || '/') + window.location.search + window.location.hash
+}
+
+/* */
+
+
+var HashHistory = (function (History$$1) {
+ function HashHistory (router, base, fallback) {
+ History$$1.call(this, router, base);
+ // check history fallback deeplinking
+ if (fallback && checkFallback(this.base)) {
+ return
+ }
+ ensureSlash();
+ }
+
+ if ( History$$1 ) HashHistory.__proto__ = History$$1;
+ HashHistory.prototype = Object.create( History$$1 && History$$1.prototype );
+ HashHistory.prototype.constructor = HashHistory;
+
+ // this is delayed until the app mounts
+ // to avoid the hashchange listener being fired too early
+ HashHistory.prototype.setupListeners = function setupListeners () {
+ var this$1 = this;
+
+ var router = this.router;
+ var expectScroll = router.options.scrollBehavior;
+ var supportsScroll = supportsPushState && expectScroll;
+
+ if (supportsScroll) {
+ setupScroll();
+ }
+
+ window.addEventListener(supportsPushState ? 'popstate' : 'hashchange', function () {
+ var current = this$1.current;
+ if (!ensureSlash()) {
+ return
+ }
+ this$1.transitionTo(getHash(), function (route) {
+ if (supportsScroll) {
+ handleScroll(this$1.router, route, current, true);
+ }
+ if (!supportsPushState) {
+ replaceHash(route.fullPath);
+ }
+ });
+ });
+ };
+
+ HashHistory.prototype.push = function push (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ var ref = this;
+ var fromRoute = ref.current;
+ this.transitionTo(location, function (route) {
+ pushHash(route.fullPath);
+ handleScroll(this$1.router, route, fromRoute, false);
+ onComplete && onComplete(route);
+ }, onAbort);
+ };
+
+ HashHistory.prototype.replace = function replace (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ var ref = this;
+ var fromRoute = ref.current;
+ this.transitionTo(location, function (route) {
+ replaceHash(route.fullPath);
+ handleScroll(this$1.router, route, fromRoute, false);
+ onComplete && onComplete(route);
+ }, onAbort);
+ };
+
+ HashHistory.prototype.go = function go (n) {
+ window.history.go(n);
+ };
+
+ HashHistory.prototype.ensureURL = function ensureURL (push) {
+ var current = this.current.fullPath;
+ if (getHash() !== current) {
+ push ? pushHash(current) : replaceHash(current);
+ }
+ };
+
+ HashHistory.prototype.getCurrentLocation = function getCurrentLocation () {
+ return getHash()
+ };
+
+ return HashHistory;
+}(History));
+
+function checkFallback (base) {
+ var location = getLocation(base);
+ if (!/^\/#/.test(location)) {
+ window.location.replace(
+ cleanPath(base + '/#' + location)
+ );
+ return true
+ }
+}
+
+function ensureSlash () {
+ var path = getHash();
+ if (path.charAt(0) === '/') {
+ return true
+ }
+ replaceHash('/' + path);
+ return false
+}
+
+function getHash () {
+ // We can't use window.location.hash here because it's not
+ // consistent across browsers - Firefox will pre-decode it!
+ var href = window.location.href;
+ var index = href.indexOf('#');
+ return index === -1 ? '' : href.slice(index + 1)
+}
+
+function getUrl (path) {
+ var href = window.location.href;
+ var i = href.indexOf('#');
+ var base = i >= 0 ? href.slice(0, i) : href;
+ return (base + "#" + path)
+}
+
+function pushHash (path) {
+ if (supportsPushState) {
+ pushState(getUrl(path));
+ } else {
+ window.location.hash = path;
+ }
+}
+
+function replaceHash (path) {
+ if (supportsPushState) {
+ replaceState(getUrl(path));
+ } else {
+ window.location.replace(getUrl(path));
+ }
+}
+
+/* */
+
+
+var AbstractHistory = (function (History$$1) {
+ function AbstractHistory (router, base) {
+ History$$1.call(this, router, base);
+ this.stack = [];
+ this.index = -1;
+ }
+
+ if ( History$$1 ) AbstractHistory.__proto__ = History$$1;
+ AbstractHistory.prototype = Object.create( History$$1 && History$$1.prototype );
+ AbstractHistory.prototype.constructor = AbstractHistory;
+
+ AbstractHistory.prototype.push = function push (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ this.transitionTo(location, function (route) {
+ this$1.stack = this$1.stack.slice(0, this$1.index + 1).concat(route);
+ this$1.index++;
+ onComplete && onComplete(route);
+ }, onAbort);
+ };
+
+ AbstractHistory.prototype.replace = function replace (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ this.transitionTo(location, function (route) {
+ this$1.stack = this$1.stack.slice(0, this$1.index).concat(route);
+ onComplete && onComplete(route);
+ }, onAbort);
+ };
+
+ AbstractHistory.prototype.go = function go (n) {
+ var this$1 = this;
+
+ var targetIndex = this.index + n;
+ if (targetIndex < 0 || targetIndex >= this.stack.length) {
+ return
+ }
+ var route = this.stack[targetIndex];
+ this.confirmTransition(route, function () {
+ this$1.index = targetIndex;
+ this$1.updateRoute(route);
+ });
+ };
+
+ AbstractHistory.prototype.getCurrentLocation = function getCurrentLocation () {
+ var current = this.stack[this.stack.length - 1];
+ return current ? current.fullPath : '/'
+ };
+
+ AbstractHistory.prototype.ensureURL = function ensureURL () {
+ // noop
+ };
+
+ return AbstractHistory;
+}(History));
+
+/* */
+
+var VueRouter = function VueRouter (options) {
+ if ( options === void 0 ) options = {};
+
+ this.app = null;
+ this.apps = [];
+ this.options = options;
+ this.beforeHooks = [];
+ this.resolveHooks = [];
+ this.afterHooks = [];
+ this.matcher = createMatcher(options.routes || [], this);
+
+ var mode = options.mode || 'hash';
+ this.fallback = mode === 'history' && !supportsPushState && options.fallback !== false;
+ if (this.fallback) {
+ mode = 'hash';
+ }
+ if (!inBrowser) {
+ mode = 'abstract';
+ }
+ this.mode = mode;
+
+ switch (mode) {
+ case 'history':
+ this.history = new HTML5History(this, options.base);
+ break
+ case 'hash':
+ this.history = new HashHistory(this, options.base, this.fallback);
+ break
+ case 'abstract':
+ this.history = new AbstractHistory(this, options.base);
+ break
+ default:
+ if (process.env.NODE_ENV !== 'production') {
+ assert(false, ("invalid mode: " + mode));
+ }
+ }
+};
+
+var prototypeAccessors = { currentRoute: { configurable: true } };
+
+VueRouter.prototype.match = function match (
+ raw,
+ current,
+ redirectedFrom
+) {
+ return this.matcher.match(raw, current, redirectedFrom)
+};
+
+prototypeAccessors.currentRoute.get = function () {
+ return this.history && this.history.current
+};
+
+VueRouter.prototype.init = function init (app /* Vue component instance */) {
+ var this$1 = this;
+
+ process.env.NODE_ENV !== 'production' && assert(
+ install.installed,
+ "not installed. Make sure to call `Vue.use(VueRouter)` " +
+ "before creating root instance."
+ );
+
+ this.apps.push(app);
+
+ // main app already initialized.
+ if (this.app) {
+ return
+ }
+
+ this.app = app;
+
+ var history = this.history;
+
+ if (history instanceof HTML5History) {
+ history.transitionTo(history.getCurrentLocation());
+ } else if (history instanceof HashHistory) {
+ var setupHashListener = function () {
+ history.setupListeners();
+ };
+ history.transitionTo(
+ history.getCurrentLocation(),
+ setupHashListener,
+ setupHashListener
+ );
+ }
+
+ history.listen(function (route) {
+ this$1.apps.forEach(function (app) {
+ app._route = route;
+ });
+ });
+};
+
+VueRouter.prototype.beforeEach = function beforeEach (fn) {
+ return registerHook(this.beforeHooks, fn)
+};
+
+VueRouter.prototype.beforeResolve = function beforeResolve (fn) {
+ return registerHook(this.resolveHooks, fn)
+};
+
+VueRouter.prototype.afterEach = function afterEach (fn) {
+ return registerHook(this.afterHooks, fn)
+};
+
+VueRouter.prototype.onReady = function onReady (cb, errorCb) {
+ this.history.onReady(cb, errorCb);
+};
+
+VueRouter.prototype.onError = function onError (errorCb) {
+ this.history.onError(errorCb);
+};
+
+VueRouter.prototype.push = function push (location, onComplete, onAbort) {
+ this.history.push(location, onComplete, onAbort);
+};
+
+VueRouter.prototype.replace = function replace (location, onComplete, onAbort) {
+ this.history.replace(location, onComplete, onAbort);
+};
+
+VueRouter.prototype.go = function go (n) {
+ this.history.go(n);
+};
+
+VueRouter.prototype.back = function back () {
+ this.go(-1);
+};
+
+VueRouter.prototype.forward = function forward () {
+ this.go(1);
+};
+
+VueRouter.prototype.getMatchedComponents = function getMatchedComponents (to) {
+ var route = to
+ ? to.matched
+ ? to
+ : this.resolve(to).route
+ : this.currentRoute;
+ if (!route) {
+ return []
+ }
+ return [].concat.apply([], route.matched.map(function (m) {
+ return Object.keys(m.components).map(function (key) {
+ return m.components[key]
+ })
+ }))
+};
+
+VueRouter.prototype.resolve = function resolve (
+ to,
+ current,
+ append
+) {
+ var location = normalizeLocation(
+ to,
+ current || this.history.current,
+ append,
+ this
+ );
+ var route = this.match(location, current);
+ var fullPath = route.redirectedFrom || route.fullPath;
+ var base = this.history.base;
+ var href = createHref(base, fullPath, this.mode);
+ return {
+ location: location,
+ route: route,
+ href: href,
+ // for backwards compat
+ normalizedTo: location,
+ resolved: route
+ }
+};
+
+VueRouter.prototype.addRoutes = function addRoutes (routes) {
+ this.matcher.addRoutes(routes);
+ if (this.history.current !== START) {
+ this.history.transitionTo(this.history.getCurrentLocation());
+ }
+};
+
+Object.defineProperties( VueRouter.prototype, prototypeAccessors );
+
+function registerHook (list, fn) {
+ list.push(fn);
+ return function () {
+ var i = list.indexOf(fn);
+ if (i > -1) { list.splice(i, 1); }
+ }
+}
+
+function createHref (base, fullPath, mode) {
+ var path = mode === 'hash' ? '#' + fullPath : fullPath;
+ return base ? cleanPath(base + '/' + path) : path
+}
+
+VueRouter.install = install;
+VueRouter.version = '3.0.1';
+
+if (inBrowser && window.Vue) {
+ window.Vue.use(VueRouter);
+}
+
+module.exports = VueRouter;
diff --git a/dist/www/lib/vue-router.esm.js b/dist/www/lib/vue-router.esm.js
new file mode 100644
index 0000000..130c26b
--- /dev/null
+++ b/dist/www/lib/vue-router.esm.js
@@ -0,0 +1,2623 @@
+/**
+ * vue-router v3.0.1
+ * (c) 2017 Evan You
+ * @license MIT
+ */
+/* */
+
+function assert (condition, message) {
+ if (!condition) {
+ throw new Error(("[vue-router] " + message))
+ }
+}
+
+function warn (condition, message) {
+ if (process.env.NODE_ENV !== 'production' && !condition) {
+ typeof console !== 'undefined' && console.warn(("[vue-router] " + message));
+ }
+}
+
+function isError (err) {
+ return Object.prototype.toString.call(err).indexOf('Error') > -1
+}
+
+var View = {
+ name: 'router-view',
+ functional: true,
+ props: {
+ name: {
+ type: String,
+ default: 'default'
+ }
+ },
+ render: function render (_, ref) {
+ var props = ref.props;
+ var children = ref.children;
+ var parent = ref.parent;
+ var data = ref.data;
+
+ data.routerView = true;
+
+ // directly use parent context's createElement() function
+ // so that components rendered by router-view can resolve named slots
+ var h = parent.$createElement;
+ var name = props.name;
+ var route = parent.$route;
+ var cache = parent._routerViewCache || (parent._routerViewCache = {});
+
+ // determine current view depth, also check to see if the tree
+ // has been toggled inactive but kept-alive.
+ var depth = 0;
+ var inactive = false;
+ while (parent && parent._routerRoot !== parent) {
+ if (parent.$vnode && parent.$vnode.data.routerView) {
+ depth++;
+ }
+ if (parent._inactive) {
+ inactive = true;
+ }
+ parent = parent.$parent;
+ }
+ data.routerViewDepth = depth;
+
+ // render previous view if the tree is inactive and kept-alive
+ if (inactive) {
+ return h(cache[name], data, children)
+ }
+
+ var matched = route.matched[depth];
+ // render empty node if no matched route
+ if (!matched) {
+ cache[name] = null;
+ return h()
+ }
+
+ var component = cache[name] = matched.components[name];
+
+ // attach instance registration hook
+ // this will be called in the instance's injected lifecycle hooks
+ data.registerRouteInstance = function (vm, val) {
+ // val could be undefined for unregistration
+ var current = matched.instances[name];
+ if (
+ (val && current !== vm) ||
+ (!val && current === vm)
+ ) {
+ matched.instances[name] = val;
+ }
+ }
+
+ // also register instance in prepatch hook
+ // in case the same component instance is reused across different routes
+ ;(data.hook || (data.hook = {})).prepatch = function (_, vnode) {
+ matched.instances[name] = vnode.componentInstance;
+ };
+
+ // resolve props
+ var propsToPass = data.props = resolveProps(route, matched.props && matched.props[name]);
+ if (propsToPass) {
+ // clone to prevent mutation
+ propsToPass = data.props = extend({}, propsToPass);
+ // pass non-declared props as attrs
+ var attrs = data.attrs = data.attrs || {};
+ for (var key in propsToPass) {
+ if (!component.props || !(key in component.props)) {
+ attrs[key] = propsToPass[key];
+ delete propsToPass[key];
+ }
+ }
+ }
+
+ return h(component, data, children)
+ }
+};
+
+function resolveProps (route, config) {
+ switch (typeof config) {
+ case 'undefined':
+ return
+ case 'object':
+ return config
+ case 'function':
+ return config(route)
+ case 'boolean':
+ return config ? route.params : undefined
+ default:
+ if (process.env.NODE_ENV !== 'production') {
+ warn(
+ false,
+ "props in \"" + (route.path) + "\" is a " + (typeof config) + ", " +
+ "expecting an object, function or boolean."
+ );
+ }
+ }
+}
+
+function extend (to, from) {
+ for (var key in from) {
+ to[key] = from[key];
+ }
+ return to
+}
+
+/* */
+
+var encodeReserveRE = /[!'()*]/g;
+var encodeReserveReplacer = function (c) { return '%' + c.charCodeAt(0).toString(16); };
+var commaRE = /%2C/g;
+
+// fixed encodeURIComponent which is more conformant to RFC3986:
+// - escapes [!'()*]
+// - preserve commas
+var encode = function (str) { return encodeURIComponent(str)
+ .replace(encodeReserveRE, encodeReserveReplacer)
+ .replace(commaRE, ','); };
+
+var decode = decodeURIComponent;
+
+function resolveQuery (
+ query,
+ extraQuery,
+ _parseQuery
+) {
+ if ( extraQuery === void 0 ) extraQuery = {};
+
+ var parse = _parseQuery || parseQuery;
+ var parsedQuery;
+ try {
+ parsedQuery = parse(query || '');
+ } catch (e) {
+ process.env.NODE_ENV !== 'production' && warn(false, e.message);
+ parsedQuery = {};
+ }
+ for (var key in extraQuery) {
+ parsedQuery[key] = extraQuery[key];
+ }
+ return parsedQuery
+}
+
+function parseQuery (query) {
+ var res = {};
+
+ query = query.trim().replace(/^(\?|#|&)/, '');
+
+ if (!query) {
+ return res
+ }
+
+ query.split('&').forEach(function (param) {
+ var parts = param.replace(/\+/g, ' ').split('=');
+ var key = decode(parts.shift());
+ var val = parts.length > 0
+ ? decode(parts.join('='))
+ : null;
+
+ if (res[key] === undefined) {
+ res[key] = val;
+ } else if (Array.isArray(res[key])) {
+ res[key].push(val);
+ } else {
+ res[key] = [res[key], val];
+ }
+ });
+
+ return res
+}
+
+function stringifyQuery (obj) {
+ var res = obj ? Object.keys(obj).map(function (key) {
+ var val = obj[key];
+
+ if (val === undefined) {
+ return ''
+ }
+
+ if (val === null) {
+ return encode(key)
+ }
+
+ if (Array.isArray(val)) {
+ var result = [];
+ val.forEach(function (val2) {
+ if (val2 === undefined) {
+ return
+ }
+ if (val2 === null) {
+ result.push(encode(key));
+ } else {
+ result.push(encode(key) + '=' + encode(val2));
+ }
+ });
+ return result.join('&')
+ }
+
+ return encode(key) + '=' + encode(val)
+ }).filter(function (x) { return x.length > 0; }).join('&') : null;
+ return res ? ("?" + res) : ''
+}
+
+/* */
+
+
+var trailingSlashRE = /\/?$/;
+
+function createRoute (
+ record,
+ location,
+ redirectedFrom,
+ router
+) {
+ var stringifyQuery$$1 = router && router.options.stringifyQuery;
+
+ var query = location.query || {};
+ try {
+ query = clone(query);
+ } catch (e) {}
+
+ var route = {
+ name: location.name || (record && record.name),
+ meta: (record && record.meta) || {},
+ path: location.path || '/',
+ hash: location.hash || '',
+ query: query,
+ params: location.params || {},
+ fullPath: getFullPath(location, stringifyQuery$$1),
+ matched: record ? formatMatch(record) : []
+ };
+ if (redirectedFrom) {
+ route.redirectedFrom = getFullPath(redirectedFrom, stringifyQuery$$1);
+ }
+ return Object.freeze(route)
+}
+
+function clone (value) {
+ if (Array.isArray(value)) {
+ return value.map(clone)
+ } else if (value && typeof value === 'object') {
+ var res = {};
+ for (var key in value) {
+ res[key] = clone(value[key]);
+ }
+ return res
+ } else {
+ return value
+ }
+}
+
+// the starting route that represents the initial state
+var START = createRoute(null, {
+ path: '/'
+});
+
+function formatMatch (record) {
+ var res = [];
+ while (record) {
+ res.unshift(record);
+ record = record.parent;
+ }
+ return res
+}
+
+function getFullPath (
+ ref,
+ _stringifyQuery
+) {
+ var path = ref.path;
+ var query = ref.query; if ( query === void 0 ) query = {};
+ var hash = ref.hash; if ( hash === void 0 ) hash = '';
+
+ var stringify = _stringifyQuery || stringifyQuery;
+ return (path || '/') + stringify(query) + hash
+}
+
+function isSameRoute (a, b) {
+ if (b === START) {
+ return a === b
+ } else if (!b) {
+ return false
+ } else if (a.path && b.path) {
+ return (
+ a.path.replace(trailingSlashRE, '') === b.path.replace(trailingSlashRE, '') &&
+ a.hash === b.hash &&
+ isObjectEqual(a.query, b.query)
+ )
+ } else if (a.name && b.name) {
+ return (
+ a.name === b.name &&
+ a.hash === b.hash &&
+ isObjectEqual(a.query, b.query) &&
+ isObjectEqual(a.params, b.params)
+ )
+ } else {
+ return false
+ }
+}
+
+function isObjectEqual (a, b) {
+ if ( a === void 0 ) a = {};
+ if ( b === void 0 ) b = {};
+
+ // handle null value #1566
+ if (!a || !b) { return a === b }
+ var aKeys = Object.keys(a);
+ var bKeys = Object.keys(b);
+ if (aKeys.length !== bKeys.length) {
+ return false
+ }
+ return aKeys.every(function (key) {
+ var aVal = a[key];
+ var bVal = b[key];
+ // check nested equality
+ if (typeof aVal === 'object' && typeof bVal === 'object') {
+ return isObjectEqual(aVal, bVal)
+ }
+ return String(aVal) === String(bVal)
+ })
+}
+
+function isIncludedRoute (current, target) {
+ return (
+ current.path.replace(trailingSlashRE, '/').indexOf(
+ target.path.replace(trailingSlashRE, '/')
+ ) === 0 &&
+ (!target.hash || current.hash === target.hash) &&
+ queryIncludes(current.query, target.query)
+ )
+}
+
+function queryIncludes (current, target) {
+ for (var key in target) {
+ if (!(key in current)) {
+ return false
+ }
+ }
+ return true
+}
+
+/* */
+
+// work around weird flow bug
+var toTypes = [String, Object];
+var eventTypes = [String, Array];
+
+var Link = {
+ name: 'router-link',
+ props: {
+ to: {
+ type: toTypes,
+ required: true
+ },
+ tag: {
+ type: String,
+ default: 'a'
+ },
+ exact: Boolean,
+ append: Boolean,
+ replace: Boolean,
+ activeClass: String,
+ exactActiveClass: String,
+ event: {
+ type: eventTypes,
+ default: 'click'
+ }
+ },
+ render: function render (h) {
+ var this$1 = this;
+
+ var router = this.$router;
+ var current = this.$route;
+ var ref = router.resolve(this.to, current, this.append);
+ var location = ref.location;
+ var route = ref.route;
+ var href = ref.href;
+
+ var classes = {};
+ var globalActiveClass = router.options.linkActiveClass;
+ var globalExactActiveClass = router.options.linkExactActiveClass;
+ // Support global empty active class
+ var activeClassFallback = globalActiveClass == null
+ ? 'router-link-active'
+ : globalActiveClass;
+ var exactActiveClassFallback = globalExactActiveClass == null
+ ? 'router-link-exact-active'
+ : globalExactActiveClass;
+ var activeClass = this.activeClass == null
+ ? activeClassFallback
+ : this.activeClass;
+ var exactActiveClass = this.exactActiveClass == null
+ ? exactActiveClassFallback
+ : this.exactActiveClass;
+ var compareTarget = location.path
+ ? createRoute(null, location, null, router)
+ : route;
+
+ classes[exactActiveClass] = isSameRoute(current, compareTarget);
+ classes[activeClass] = this.exact
+ ? classes[exactActiveClass]
+ : isIncludedRoute(current, compareTarget);
+
+ var handler = function (e) {
+ if (guardEvent(e)) {
+ if (this$1.replace) {
+ router.replace(location);
+ } else {
+ router.push(location);
+ }
+ }
+ };
+
+ var on = { click: guardEvent };
+ if (Array.isArray(this.event)) {
+ this.event.forEach(function (e) { on[e] = handler; });
+ } else {
+ on[this.event] = handler;
+ }
+
+ var data = {
+ class: classes
+ };
+
+ if (this.tag === 'a') {
+ data.on = on;
+ data.attrs = { href: href };
+ } else {
+ // find the first child and apply listener and href
+ var a = findAnchor(this.$slots.default);
+ if (a) {
+ // in case the is a static node
+ a.isStatic = false;
+ var extend = _Vue.util.extend;
+ var aData = a.data = extend({}, a.data);
+ aData.on = on;
+ var aAttrs = a.data.attrs = extend({}, a.data.attrs);
+ aAttrs.href = href;
+ } else {
+ // doesn't have child, apply listener to self
+ data.on = on;
+ }
+ }
+
+ return h(this.tag, data, this.$slots.default)
+ }
+};
+
+function guardEvent (e) {
+ // don't redirect with control keys
+ if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) { return }
+ // don't redirect when preventDefault called
+ if (e.defaultPrevented) { return }
+ // don't redirect on right click
+ if (e.button !== undefined && e.button !== 0) { return }
+ // don't redirect if `target="_blank"`
+ if (e.currentTarget && e.currentTarget.getAttribute) {
+ var target = e.currentTarget.getAttribute('target');
+ if (/\b_blank\b/i.test(target)) { return }
+ }
+ // this may be a Weex event which doesn't have this method
+ if (e.preventDefault) {
+ e.preventDefault();
+ }
+ return true
+}
+
+function findAnchor (children) {
+ if (children) {
+ var child;
+ for (var i = 0; i < children.length; i++) {
+ child = children[i];
+ if (child.tag === 'a') {
+ return child
+ }
+ if (child.children && (child = findAnchor(child.children))) {
+ return child
+ }
+ }
+ }
+}
+
+var _Vue;
+
+function install (Vue) {
+ if (install.installed && _Vue === Vue) { return }
+ install.installed = true;
+
+ _Vue = Vue;
+
+ var isDef = function (v) { return v !== undefined; };
+
+ var registerInstance = function (vm, callVal) {
+ var i = vm.$options._parentVnode;
+ if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
+ i(vm, callVal);
+ }
+ };
+
+ Vue.mixin({
+ beforeCreate: function beforeCreate () {
+ if (isDef(this.$options.router)) {
+ this._routerRoot = this;
+ this._router = this.$options.router;
+ this._router.init(this);
+ Vue.util.defineReactive(this, '_route', this._router.history.current);
+ } else {
+ this._routerRoot = (this.$parent && this.$parent._routerRoot) || this;
+ }
+ registerInstance(this, this);
+ },
+ destroyed: function destroyed () {
+ registerInstance(this);
+ }
+ });
+
+ Object.defineProperty(Vue.prototype, '$router', {
+ get: function get () { return this._routerRoot._router }
+ });
+
+ Object.defineProperty(Vue.prototype, '$route', {
+ get: function get () { return this._routerRoot._route }
+ });
+
+ Vue.component('router-view', View);
+ Vue.component('router-link', Link);
+
+ var strats = Vue.config.optionMergeStrategies;
+ // use the same hook merging strategy for route hooks
+ strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created;
+}
+
+/* */
+
+var inBrowser = typeof window !== 'undefined';
+
+/* */
+
+function resolvePath (
+ relative,
+ base,
+ append
+) {
+ var firstChar = relative.charAt(0);
+ if (firstChar === '/') {
+ return relative
+ }
+
+ if (firstChar === '?' || firstChar === '#') {
+ return base + relative
+ }
+
+ var stack = base.split('/');
+
+ // remove trailing segment if:
+ // - not appending
+ // - appending to trailing slash (last segment is empty)
+ if (!append || !stack[stack.length - 1]) {
+ stack.pop();
+ }
+
+ // resolve relative path
+ var segments = relative.replace(/^\//, '').split('/');
+ for (var i = 0; i < segments.length; i++) {
+ var segment = segments[i];
+ if (segment === '..') {
+ stack.pop();
+ } else if (segment !== '.') {
+ stack.push(segment);
+ }
+ }
+
+ // ensure leading slash
+ if (stack[0] !== '') {
+ stack.unshift('');
+ }
+
+ return stack.join('/')
+}
+
+function parsePath (path) {
+ var hash = '';
+ var query = '';
+
+ var hashIndex = path.indexOf('#');
+ if (hashIndex >= 0) {
+ hash = path.slice(hashIndex);
+ path = path.slice(0, hashIndex);
+ }
+
+ var queryIndex = path.indexOf('?');
+ if (queryIndex >= 0) {
+ query = path.slice(queryIndex + 1);
+ path = path.slice(0, queryIndex);
+ }
+
+ return {
+ path: path,
+ query: query,
+ hash: hash
+ }
+}
+
+function cleanPath (path) {
+ return path.replace(/\/\//g, '/')
+}
+
+var isarray = Array.isArray || function (arr) {
+ return Object.prototype.toString.call(arr) == '[object Array]';
+};
+
+/**
+ * Expose `pathToRegexp`.
+ */
+var pathToRegexp_1 = pathToRegexp;
+var parse_1 = parse;
+var compile_1 = compile;
+var tokensToFunction_1 = tokensToFunction;
+var tokensToRegExp_1 = tokensToRegExp;
+
+/**
+ * The main path matching regexp utility.
+ *
+ * @type {RegExp}
+ */
+var PATH_REGEXP = new RegExp([
+ // Match escaped characters that would otherwise appear in future matches.
+ // This allows the user to escape special characters that won't transform.
+ '(\\\\.)',
+ // Match Express-style parameters and un-named parameters with a prefix
+ // and optional suffixes. Matches appear as:
+ //
+ // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined]
+ // "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined, undefined]
+ // "/*" => ["/", undefined, undefined, undefined, undefined, "*"]
+ '([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))'
+].join('|'), 'g');
+
+/**
+ * Parse a string for the raw tokens.
+ *
+ * @param {string} str
+ * @param {Object=} options
+ * @return {!Array}
+ */
+function parse (str, options) {
+ var tokens = [];
+ var key = 0;
+ var index = 0;
+ var path = '';
+ var defaultDelimiter = options && options.delimiter || '/';
+ var res;
+
+ while ((res = PATH_REGEXP.exec(str)) != null) {
+ var m = res[0];
+ var escaped = res[1];
+ var offset = res.index;
+ path += str.slice(index, offset);
+ index = offset + m.length;
+
+ // Ignore already escaped sequences.
+ if (escaped) {
+ path += escaped[1];
+ continue
+ }
+
+ var next = str[index];
+ var prefix = res[2];
+ var name = res[3];
+ var capture = res[4];
+ var group = res[5];
+ var modifier = res[6];
+ var asterisk = res[7];
+
+ // Push the current path onto the tokens.
+ if (path) {
+ tokens.push(path);
+ path = '';
+ }
+
+ var partial = prefix != null && next != null && next !== prefix;
+ var repeat = modifier === '+' || modifier === '*';
+ var optional = modifier === '?' || modifier === '*';
+ var delimiter = res[2] || defaultDelimiter;
+ var pattern = capture || group;
+
+ tokens.push({
+ name: name || key++,
+ prefix: prefix || '',
+ delimiter: delimiter,
+ optional: optional,
+ repeat: repeat,
+ partial: partial,
+ asterisk: !!asterisk,
+ pattern: pattern ? escapeGroup(pattern) : (asterisk ? '.*' : '[^' + escapeString(delimiter) + ']+?')
+ });
+ }
+
+ // Match any characters still remaining.
+ if (index < str.length) {
+ path += str.substr(index);
+ }
+
+ // If the path exists, push it onto the end.
+ if (path) {
+ tokens.push(path);
+ }
+
+ return tokens
+}
+
+/**
+ * Compile a string to a template function for the path.
+ *
+ * @param {string} str
+ * @param {Object=} options
+ * @return {!function(Object=, Object=)}
+ */
+function compile (str, options) {
+ return tokensToFunction(parse(str, options))
+}
+
+/**
+ * Prettier encoding of URI path segments.
+ *
+ * @param {string}
+ * @return {string}
+ */
+function encodeURIComponentPretty (str) {
+ return encodeURI(str).replace(/[\/?#]/g, function (c) {
+ return '%' + c.charCodeAt(0).toString(16).toUpperCase()
+ })
+}
+
+/**
+ * Encode the asterisk parameter. Similar to `pretty`, but allows slashes.
+ *
+ * @param {string}
+ * @return {string}
+ */
+function encodeAsterisk (str) {
+ return encodeURI(str).replace(/[?#]/g, function (c) {
+ return '%' + c.charCodeAt(0).toString(16).toUpperCase()
+ })
+}
+
+/**
+ * Expose a method for transforming tokens into the path function.
+ */
+function tokensToFunction (tokens) {
+ // Compile all the tokens into regexps.
+ var matches = new Array(tokens.length);
+
+ // Compile all the patterns before compilation.
+ for (var i = 0; i < tokens.length; i++) {
+ if (typeof tokens[i] === 'object') {
+ matches[i] = new RegExp('^(?:' + tokens[i].pattern + ')$');
+ }
+ }
+
+ return function (obj, opts) {
+ var path = '';
+ var data = obj || {};
+ var options = opts || {};
+ var encode = options.pretty ? encodeURIComponentPretty : encodeURIComponent;
+
+ for (var i = 0; i < tokens.length; i++) {
+ var token = tokens[i];
+
+ if (typeof token === 'string') {
+ path += token;
+
+ continue
+ }
+
+ var value = data[token.name];
+ var segment;
+
+ if (value == null) {
+ if (token.optional) {
+ // Prepend partial segment prefixes.
+ if (token.partial) {
+ path += token.prefix;
+ }
+
+ continue
+ } else {
+ throw new TypeError('Expected "' + token.name + '" to be defined')
+ }
+ }
+
+ if (isarray(value)) {
+ if (!token.repeat) {
+ throw new TypeError('Expected "' + token.name + '" to not repeat, but received `' + JSON.stringify(value) + '`')
+ }
+
+ if (value.length === 0) {
+ if (token.optional) {
+ continue
+ } else {
+ throw new TypeError('Expected "' + token.name + '" to not be empty')
+ }
+ }
+
+ for (var j = 0; j < value.length; j++) {
+ segment = encode(value[j]);
+
+ if (!matches[i].test(segment)) {
+ throw new TypeError('Expected all "' + token.name + '" to match "' + token.pattern + '", but received `' + JSON.stringify(segment) + '`')
+ }
+
+ path += (j === 0 ? token.prefix : token.delimiter) + segment;
+ }
+
+ continue
+ }
+
+ segment = token.asterisk ? encodeAsterisk(value) : encode(value);
+
+ if (!matches[i].test(segment)) {
+ throw new TypeError('Expected "' + token.name + '" to match "' + token.pattern + '", but received "' + segment + '"')
+ }
+
+ path += token.prefix + segment;
+ }
+
+ return path
+ }
+}
+
+/**
+ * Escape a regular expression string.
+ *
+ * @param {string} str
+ * @return {string}
+ */
+function escapeString (str) {
+ return str.replace(/([.+*?=^!:${}()[\]|\/\\])/g, '\\$1')
+}
+
+/**
+ * Escape the capturing group by escaping special characters and meaning.
+ *
+ * @param {string} group
+ * @return {string}
+ */
+function escapeGroup (group) {
+ return group.replace(/([=!:$\/()])/g, '\\$1')
+}
+
+/**
+ * Attach the keys as a property of the regexp.
+ *
+ * @param {!RegExp} re
+ * @param {Array} keys
+ * @return {!RegExp}
+ */
+function attachKeys (re, keys) {
+ re.keys = keys;
+ return re
+}
+
+/**
+ * Get the flags for a regexp from the options.
+ *
+ * @param {Object} options
+ * @return {string}
+ */
+function flags (options) {
+ return options.sensitive ? '' : 'i'
+}
+
+/**
+ * Pull out keys from a regexp.
+ *
+ * @param {!RegExp} path
+ * @param {!Array} keys
+ * @return {!RegExp}
+ */
+function regexpToRegexp (path, keys) {
+ // Use a negative lookahead to match only capturing groups.
+ var groups = path.source.match(/\((?!\?)/g);
+
+ if (groups) {
+ for (var i = 0; i < groups.length; i++) {
+ keys.push({
+ name: i,
+ prefix: null,
+ delimiter: null,
+ optional: false,
+ repeat: false,
+ partial: false,
+ asterisk: false,
+ pattern: null
+ });
+ }
+ }
+
+ return attachKeys(path, keys)
+}
+
+/**
+ * Transform an array into a regexp.
+ *
+ * @param {!Array} path
+ * @param {Array} keys
+ * @param {!Object} options
+ * @return {!RegExp}
+ */
+function arrayToRegexp (path, keys, options) {
+ var parts = [];
+
+ for (var i = 0; i < path.length; i++) {
+ parts.push(pathToRegexp(path[i], keys, options).source);
+ }
+
+ var regexp = new RegExp('(?:' + parts.join('|') + ')', flags(options));
+
+ return attachKeys(regexp, keys)
+}
+
+/**
+ * Create a path regexp from string input.
+ *
+ * @param {string} path
+ * @param {!Array} keys
+ * @param {!Object} options
+ * @return {!RegExp}
+ */
+function stringToRegexp (path, keys, options) {
+ return tokensToRegExp(parse(path, options), keys, options)
+}
+
+/**
+ * Expose a function for taking tokens and returning a RegExp.
+ *
+ * @param {!Array} tokens
+ * @param {(Array|Object)=} keys
+ * @param {Object=} options
+ * @return {!RegExp}
+ */
+function tokensToRegExp (tokens, keys, options) {
+ if (!isarray(keys)) {
+ options = /** @type {!Object} */ (keys || options);
+ keys = [];
+ }
+
+ options = options || {};
+
+ var strict = options.strict;
+ var end = options.end !== false;
+ var route = '';
+
+ // Iterate over the tokens and create our regexp string.
+ for (var i = 0; i < tokens.length; i++) {
+ var token = tokens[i];
+
+ if (typeof token === 'string') {
+ route += escapeString(token);
+ } else {
+ var prefix = escapeString(token.prefix);
+ var capture = '(?:' + token.pattern + ')';
+
+ keys.push(token);
+
+ if (token.repeat) {
+ capture += '(?:' + prefix + capture + ')*';
+ }
+
+ if (token.optional) {
+ if (!token.partial) {
+ capture = '(?:' + prefix + '(' + capture + '))?';
+ } else {
+ capture = prefix + '(' + capture + ')?';
+ }
+ } else {
+ capture = prefix + '(' + capture + ')';
+ }
+
+ route += capture;
+ }
+ }
+
+ var delimiter = escapeString(options.delimiter || '/');
+ var endsWithDelimiter = route.slice(-delimiter.length) === delimiter;
+
+ // In non-strict mode we allow a slash at the end of match. If the path to
+ // match already ends with a slash, we remove it for consistency. The slash
+ // is valid at the end of a path match, not in the middle. This is important
+ // in non-ending mode, where "/test/" shouldn't match "/test//route".
+ if (!strict) {
+ route = (endsWithDelimiter ? route.slice(0, -delimiter.length) : route) + '(?:' + delimiter + '(?=$))?';
+ }
+
+ if (end) {
+ route += '$';
+ } else {
+ // In non-ending mode, we need the capturing groups to match as much as
+ // possible by using a positive lookahead to the end or next path segment.
+ route += strict && endsWithDelimiter ? '' : '(?=' + delimiter + '|$)';
+ }
+
+ return attachKeys(new RegExp('^' + route, flags(options)), keys)
+}
+
+/**
+ * Normalize the given path string, returning a regular expression.
+ *
+ * An empty array can be passed in for the keys, which will hold the
+ * placeholder key descriptions. For example, using `/user/:id`, `keys` will
+ * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.
+ *
+ * @param {(string|RegExp|Array)} path
+ * @param {(Array|Object)=} keys
+ * @param {Object=} options
+ * @return {!RegExp}
+ */
+function pathToRegexp (path, keys, options) {
+ if (!isarray(keys)) {
+ options = /** @type {!Object} */ (keys || options);
+ keys = [];
+ }
+
+ options = options || {};
+
+ if (path instanceof RegExp) {
+ return regexpToRegexp(path, /** @type {!Array} */ (keys))
+ }
+
+ if (isarray(path)) {
+ return arrayToRegexp(/** @type {!Array} */ (path), /** @type {!Array} */ (keys), options)
+ }
+
+ return stringToRegexp(/** @type {string} */ (path), /** @type {!Array} */ (keys), options)
+}
+
+pathToRegexp_1.parse = parse_1;
+pathToRegexp_1.compile = compile_1;
+pathToRegexp_1.tokensToFunction = tokensToFunction_1;
+pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
+
+/* */
+
+// $flow-disable-line
+var regexpCompileCache = Object.create(null);
+
+function fillParams (
+ path,
+ params,
+ routeMsg
+) {
+ try {
+ var filler =
+ regexpCompileCache[path] ||
+ (regexpCompileCache[path] = pathToRegexp_1.compile(path));
+ return filler(params || {}, { pretty: true })
+ } catch (e) {
+ if (process.env.NODE_ENV !== 'production') {
+ warn(false, ("missing param for " + routeMsg + ": " + (e.message)));
+ }
+ return ''
+ }
+}
+
+/* */
+
+function createRouteMap (
+ routes,
+ oldPathList,
+ oldPathMap,
+ oldNameMap
+) {
+ // the path list is used to control path matching priority
+ var pathList = oldPathList || [];
+ // $flow-disable-line
+ var pathMap = oldPathMap || Object.create(null);
+ // $flow-disable-line
+ var nameMap = oldNameMap || Object.create(null);
+
+ routes.forEach(function (route) {
+ addRouteRecord(pathList, pathMap, nameMap, route);
+ });
+
+ // ensure wildcard routes are always at the end
+ for (var i = 0, l = pathList.length; i < l; i++) {
+ if (pathList[i] === '*') {
+ pathList.push(pathList.splice(i, 1)[0]);
+ l--;
+ i--;
+ }
+ }
+
+ return {
+ pathList: pathList,
+ pathMap: pathMap,
+ nameMap: nameMap
+ }
+}
+
+function addRouteRecord (
+ pathList,
+ pathMap,
+ nameMap,
+ route,
+ parent,
+ matchAs
+) {
+ var path = route.path;
+ var name = route.name;
+ if (process.env.NODE_ENV !== 'production') {
+ assert(path != null, "\"path\" is required in a route configuration.");
+ assert(
+ typeof route.component !== 'string',
+ "route config \"component\" for path: " + (String(path || name)) + " cannot be a " +
+ "string id. Use an actual component instead."
+ );
+ }
+
+ var pathToRegexpOptions = route.pathToRegexpOptions || {};
+ var normalizedPath = normalizePath(
+ path,
+ parent,
+ pathToRegexpOptions.strict
+ );
+
+ if (typeof route.caseSensitive === 'boolean') {
+ pathToRegexpOptions.sensitive = route.caseSensitive;
+ }
+
+ var record = {
+ path: normalizedPath,
+ regex: compileRouteRegex(normalizedPath, pathToRegexpOptions),
+ components: route.components || { default: route.component },
+ instances: {},
+ name: name,
+ parent: parent,
+ matchAs: matchAs,
+ redirect: route.redirect,
+ beforeEnter: route.beforeEnter,
+ meta: route.meta || {},
+ props: route.props == null
+ ? {}
+ : route.components
+ ? route.props
+ : { default: route.props }
+ };
+
+ if (route.children) {
+ // Warn if route is named, does not redirect and has a default child route.
+ // If users navigate to this route by name, the default child will
+ // not be rendered (GH Issue #629)
+ if (process.env.NODE_ENV !== 'production') {
+ if (route.name && !route.redirect && route.children.some(function (child) { return /^\/?$/.test(child.path); })) {
+ warn(
+ false,
+ "Named Route '" + (route.name) + "' has a default child route. " +
+ "When navigating to this named route (:to=\"{name: '" + (route.name) + "'\"), " +
+ "the default child route will not be rendered. Remove the name from " +
+ "this route and use the name of the default child route for named " +
+ "links instead."
+ );
+ }
+ }
+ route.children.forEach(function (child) {
+ var childMatchAs = matchAs
+ ? cleanPath((matchAs + "/" + (child.path)))
+ : undefined;
+ addRouteRecord(pathList, pathMap, nameMap, child, record, childMatchAs);
+ });
+ }
+
+ if (route.alias !== undefined) {
+ var aliases = Array.isArray(route.alias)
+ ? route.alias
+ : [route.alias];
+
+ aliases.forEach(function (alias) {
+ var aliasRoute = {
+ path: alias,
+ children: route.children
+ };
+ addRouteRecord(
+ pathList,
+ pathMap,
+ nameMap,
+ aliasRoute,
+ parent,
+ record.path || '/' // matchAs
+ );
+ });
+ }
+
+ if (!pathMap[record.path]) {
+ pathList.push(record.path);
+ pathMap[record.path] = record;
+ }
+
+ if (name) {
+ if (!nameMap[name]) {
+ nameMap[name] = record;
+ } else if (process.env.NODE_ENV !== 'production' && !matchAs) {
+ warn(
+ false,
+ "Duplicate named routes definition: " +
+ "{ name: \"" + name + "\", path: \"" + (record.path) + "\" }"
+ );
+ }
+ }
+}
+
+function compileRouteRegex (path, pathToRegexpOptions) {
+ var regex = pathToRegexp_1(path, [], pathToRegexpOptions);
+ if (process.env.NODE_ENV !== 'production') {
+ var keys = Object.create(null);
+ regex.keys.forEach(function (key) {
+ warn(!keys[key.name], ("Duplicate param keys in route with path: \"" + path + "\""));
+ keys[key.name] = true;
+ });
+ }
+ return regex
+}
+
+function normalizePath (path, parent, strict) {
+ if (!strict) { path = path.replace(/\/$/, ''); }
+ if (path[0] === '/') { return path }
+ if (parent == null) { return path }
+ return cleanPath(((parent.path) + "/" + path))
+}
+
+/* */
+
+
+function normalizeLocation (
+ raw,
+ current,
+ append,
+ router
+) {
+ var next = typeof raw === 'string' ? { path: raw } : raw;
+ // named target
+ if (next.name || next._normalized) {
+ return next
+ }
+
+ // relative params
+ if (!next.path && next.params && current) {
+ next = assign({}, next);
+ next._normalized = true;
+ var params = assign(assign({}, current.params), next.params);
+ if (current.name) {
+ next.name = current.name;
+ next.params = params;
+ } else if (current.matched.length) {
+ var rawPath = current.matched[current.matched.length - 1].path;
+ next.path = fillParams(rawPath, params, ("path " + (current.path)));
+ } else if (process.env.NODE_ENV !== 'production') {
+ warn(false, "relative params navigation requires a current route.");
+ }
+ return next
+ }
+
+ var parsedPath = parsePath(next.path || '');
+ var basePath = (current && current.path) || '/';
+ var path = parsedPath.path
+ ? resolvePath(parsedPath.path, basePath, append || next.append)
+ : basePath;
+
+ var query = resolveQuery(
+ parsedPath.query,
+ next.query,
+ router && router.options.parseQuery
+ );
+
+ var hash = next.hash || parsedPath.hash;
+ if (hash && hash.charAt(0) !== '#') {
+ hash = "#" + hash;
+ }
+
+ return {
+ _normalized: true,
+ path: path,
+ query: query,
+ hash: hash
+ }
+}
+
+function assign (a, b) {
+ for (var key in b) {
+ a[key] = b[key];
+ }
+ return a
+}
+
+/* */
+
+
+function createMatcher (
+ routes,
+ router
+) {
+ var ref = createRouteMap(routes);
+ var pathList = ref.pathList;
+ var pathMap = ref.pathMap;
+ var nameMap = ref.nameMap;
+
+ function addRoutes (routes) {
+ createRouteMap(routes, pathList, pathMap, nameMap);
+ }
+
+ function match (
+ raw,
+ currentRoute,
+ redirectedFrom
+ ) {
+ var location = normalizeLocation(raw, currentRoute, false, router);
+ var name = location.name;
+
+ if (name) {
+ var record = nameMap[name];
+ if (process.env.NODE_ENV !== 'production') {
+ warn(record, ("Route with name '" + name + "' does not exist"));
+ }
+ if (!record) { return _createRoute(null, location) }
+ var paramNames = record.regex.keys
+ .filter(function (key) { return !key.optional; })
+ .map(function (key) { return key.name; });
+
+ if (typeof location.params !== 'object') {
+ location.params = {};
+ }
+
+ if (currentRoute && typeof currentRoute.params === 'object') {
+ for (var key in currentRoute.params) {
+ if (!(key in location.params) && paramNames.indexOf(key) > -1) {
+ location.params[key] = currentRoute.params[key];
+ }
+ }
+ }
+
+ if (record) {
+ location.path = fillParams(record.path, location.params, ("named route \"" + name + "\""));
+ return _createRoute(record, location, redirectedFrom)
+ }
+ } else if (location.path) {
+ location.params = {};
+ for (var i = 0; i < pathList.length; i++) {
+ var path = pathList[i];
+ var record$1 = pathMap[path];
+ if (matchRoute(record$1.regex, location.path, location.params)) {
+ return _createRoute(record$1, location, redirectedFrom)
+ }
+ }
+ }
+ // no match
+ return _createRoute(null, location)
+ }
+
+ function redirect (
+ record,
+ location
+ ) {
+ var originalRedirect = record.redirect;
+ var redirect = typeof originalRedirect === 'function'
+ ? originalRedirect(createRoute(record, location, null, router))
+ : originalRedirect;
+
+ if (typeof redirect === 'string') {
+ redirect = { path: redirect };
+ }
+
+ if (!redirect || typeof redirect !== 'object') {
+ if (process.env.NODE_ENV !== 'production') {
+ warn(
+ false, ("invalid redirect option: " + (JSON.stringify(redirect)))
+ );
+ }
+ return _createRoute(null, location)
+ }
+
+ var re = redirect;
+ var name = re.name;
+ var path = re.path;
+ var query = location.query;
+ var hash = location.hash;
+ var params = location.params;
+ query = re.hasOwnProperty('query') ? re.query : query;
+ hash = re.hasOwnProperty('hash') ? re.hash : hash;
+ params = re.hasOwnProperty('params') ? re.params : params;
+
+ if (name) {
+ // resolved named direct
+ var targetRecord = nameMap[name];
+ if (process.env.NODE_ENV !== 'production') {
+ assert(targetRecord, ("redirect failed: named route \"" + name + "\" not found."));
+ }
+ return match({
+ _normalized: true,
+ name: name,
+ query: query,
+ hash: hash,
+ params: params
+ }, undefined, location)
+ } else if (path) {
+ // 1. resolve relative redirect
+ var rawPath = resolveRecordPath(path, record);
+ // 2. resolve params
+ var resolvedPath = fillParams(rawPath, params, ("redirect route with path \"" + rawPath + "\""));
+ // 3. rematch with existing query and hash
+ return match({
+ _normalized: true,
+ path: resolvedPath,
+ query: query,
+ hash: hash
+ }, undefined, location)
+ } else {
+ if (process.env.NODE_ENV !== 'production') {
+ warn(false, ("invalid redirect option: " + (JSON.stringify(redirect))));
+ }
+ return _createRoute(null, location)
+ }
+ }
+
+ function alias (
+ record,
+ location,
+ matchAs
+ ) {
+ var aliasedPath = fillParams(matchAs, location.params, ("aliased route with path \"" + matchAs + "\""));
+ var aliasedMatch = match({
+ _normalized: true,
+ path: aliasedPath
+ });
+ if (aliasedMatch) {
+ var matched = aliasedMatch.matched;
+ var aliasedRecord = matched[matched.length - 1];
+ location.params = aliasedMatch.params;
+ return _createRoute(aliasedRecord, location)
+ }
+ return _createRoute(null, location)
+ }
+
+ function _createRoute (
+ record,
+ location,
+ redirectedFrom
+ ) {
+ if (record && record.redirect) {
+ return redirect(record, redirectedFrom || location)
+ }
+ if (record && record.matchAs) {
+ return alias(record, location, record.matchAs)
+ }
+ return createRoute(record, location, redirectedFrom, router)
+ }
+
+ return {
+ match: match,
+ addRoutes: addRoutes
+ }
+}
+
+function matchRoute (
+ regex,
+ path,
+ params
+) {
+ var m = path.match(regex);
+
+ if (!m) {
+ return false
+ } else if (!params) {
+ return true
+ }
+
+ for (var i = 1, len = m.length; i < len; ++i) {
+ var key = regex.keys[i - 1];
+ var val = typeof m[i] === 'string' ? decodeURIComponent(m[i]) : m[i];
+ if (key) {
+ params[key.name] = val;
+ }
+ }
+
+ return true
+}
+
+function resolveRecordPath (path, record) {
+ return resolvePath(path, record.parent ? record.parent.path : '/', true)
+}
+
+/* */
+
+
+var positionStore = Object.create(null);
+
+function setupScroll () {
+ // Fix for #1585 for Firefox
+ window.history.replaceState({ key: getStateKey() }, '');
+ window.addEventListener('popstate', function (e) {
+ saveScrollPosition();
+ if (e.state && e.state.key) {
+ setStateKey(e.state.key);
+ }
+ });
+}
+
+function handleScroll (
+ router,
+ to,
+ from,
+ isPop
+) {
+ if (!router.app) {
+ return
+ }
+
+ var behavior = router.options.scrollBehavior;
+ if (!behavior) {
+ return
+ }
+
+ if (process.env.NODE_ENV !== 'production') {
+ assert(typeof behavior === 'function', "scrollBehavior must be a function");
+ }
+
+ // wait until re-render finishes before scrolling
+ router.app.$nextTick(function () {
+ var position = getScrollPosition();
+ var shouldScroll = behavior(to, from, isPop ? position : null);
+
+ if (!shouldScroll) {
+ return
+ }
+
+ if (typeof shouldScroll.then === 'function') {
+ shouldScroll.then(function (shouldScroll) {
+ scrollToPosition((shouldScroll), position);
+ }).catch(function (err) {
+ if (process.env.NODE_ENV !== 'production') {
+ assert(false, err.toString());
+ }
+ });
+ } else {
+ scrollToPosition(shouldScroll, position);
+ }
+ });
+}
+
+function saveScrollPosition () {
+ var key = getStateKey();
+ if (key) {
+ positionStore[key] = {
+ x: window.pageXOffset,
+ y: window.pageYOffset
+ };
+ }
+}
+
+function getScrollPosition () {
+ var key = getStateKey();
+ if (key) {
+ return positionStore[key]
+ }
+}
+
+function getElementPosition (el, offset) {
+ var docEl = document.documentElement;
+ var docRect = docEl.getBoundingClientRect();
+ var elRect = el.getBoundingClientRect();
+ return {
+ x: elRect.left - docRect.left - offset.x,
+ y: elRect.top - docRect.top - offset.y
+ }
+}
+
+function isValidPosition (obj) {
+ return isNumber(obj.x) || isNumber(obj.y)
+}
+
+function normalizePosition (obj) {
+ return {
+ x: isNumber(obj.x) ? obj.x : window.pageXOffset,
+ y: isNumber(obj.y) ? obj.y : window.pageYOffset
+ }
+}
+
+function normalizeOffset (obj) {
+ return {
+ x: isNumber(obj.x) ? obj.x : 0,
+ y: isNumber(obj.y) ? obj.y : 0
+ }
+}
+
+function isNumber (v) {
+ return typeof v === 'number'
+}
+
+function scrollToPosition (shouldScroll, position) {
+ var isObject = typeof shouldScroll === 'object';
+ if (isObject && typeof shouldScroll.selector === 'string') {
+ var el = document.querySelector(shouldScroll.selector);
+ if (el) {
+ var offset = shouldScroll.offset && typeof shouldScroll.offset === 'object' ? shouldScroll.offset : {};
+ offset = normalizeOffset(offset);
+ position = getElementPosition(el, offset);
+ } else if (isValidPosition(shouldScroll)) {
+ position = normalizePosition(shouldScroll);
+ }
+ } else if (isObject && isValidPosition(shouldScroll)) {
+ position = normalizePosition(shouldScroll);
+ }
+
+ if (position) {
+ window.scrollTo(position.x, position.y);
+ }
+}
+
+/* */
+
+var supportsPushState = inBrowser && (function () {
+ var ua = window.navigator.userAgent;
+
+ if (
+ (ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) &&
+ ua.indexOf('Mobile Safari') !== -1 &&
+ ua.indexOf('Chrome') === -1 &&
+ ua.indexOf('Windows Phone') === -1
+ ) {
+ return false
+ }
+
+ return window.history && 'pushState' in window.history
+})();
+
+// use User Timing api (if present) for more accurate key precision
+var Time = inBrowser && window.performance && window.performance.now
+ ? window.performance
+ : Date;
+
+var _key = genKey();
+
+function genKey () {
+ return Time.now().toFixed(3)
+}
+
+function getStateKey () {
+ return _key
+}
+
+function setStateKey (key) {
+ _key = key;
+}
+
+function pushState (url, replace) {
+ saveScrollPosition();
+ // try...catch the pushState call to get around Safari
+ // DOM Exception 18 where it limits to 100 pushState calls
+ var history = window.history;
+ try {
+ if (replace) {
+ history.replaceState({ key: _key }, '', url);
+ } else {
+ _key = genKey();
+ history.pushState({ key: _key }, '', url);
+ }
+ } catch (e) {
+ window.location[replace ? 'replace' : 'assign'](url);
+ }
+}
+
+function replaceState (url) {
+ pushState(url, true);
+}
+
+/* */
+
+function runQueue (queue, fn, cb) {
+ var step = function (index) {
+ if (index >= queue.length) {
+ cb();
+ } else {
+ if (queue[index]) {
+ fn(queue[index], function () {
+ step(index + 1);
+ });
+ } else {
+ step(index + 1);
+ }
+ }
+ };
+ step(0);
+}
+
+/* */
+
+function resolveAsyncComponents (matched) {
+ return function (to, from, next) {
+ var hasAsync = false;
+ var pending = 0;
+ var error = null;
+
+ flatMapComponents(matched, function (def, _, match, key) {
+ // if it's a function and doesn't have cid attached,
+ // assume it's an async component resolve function.
+ // we are not using Vue's default async resolving mechanism because
+ // we want to halt the navigation until the incoming component has been
+ // resolved.
+ if (typeof def === 'function' && def.cid === undefined) {
+ hasAsync = true;
+ pending++;
+
+ var resolve = once(function (resolvedDef) {
+ if (isESModule(resolvedDef)) {
+ resolvedDef = resolvedDef.default;
+ }
+ // save resolved on async factory in case it's used elsewhere
+ def.resolved = typeof resolvedDef === 'function'
+ ? resolvedDef
+ : _Vue.extend(resolvedDef);
+ match.components[key] = resolvedDef;
+ pending--;
+ if (pending <= 0) {
+ next();
+ }
+ });
+
+ var reject = once(function (reason) {
+ var msg = "Failed to resolve async component " + key + ": " + reason;
+ process.env.NODE_ENV !== 'production' && warn(false, msg);
+ if (!error) {
+ error = isError(reason)
+ ? reason
+ : new Error(msg);
+ next(error);
+ }
+ });
+
+ var res;
+ try {
+ res = def(resolve, reject);
+ } catch (e) {
+ reject(e);
+ }
+ if (res) {
+ if (typeof res.then === 'function') {
+ res.then(resolve, reject);
+ } else {
+ // new syntax in Vue 2.3
+ var comp = res.component;
+ if (comp && typeof comp.then === 'function') {
+ comp.then(resolve, reject);
+ }
+ }
+ }
+ }
+ });
+
+ if (!hasAsync) { next(); }
+ }
+}
+
+function flatMapComponents (
+ matched,
+ fn
+) {
+ return flatten(matched.map(function (m) {
+ return Object.keys(m.components).map(function (key) { return fn(
+ m.components[key],
+ m.instances[key],
+ m, key
+ ); })
+ }))
+}
+
+function flatten (arr) {
+ return Array.prototype.concat.apply([], arr)
+}
+
+var hasSymbol =
+ typeof Symbol === 'function' &&
+ typeof Symbol.toStringTag === 'symbol';
+
+function isESModule (obj) {
+ return obj.__esModule || (hasSymbol && obj[Symbol.toStringTag] === 'Module')
+}
+
+// in Webpack 2, require.ensure now also returns a Promise
+// so the resolve/reject functions may get called an extra time
+// if the user uses an arrow function shorthand that happens to
+// return that Promise.
+function once (fn) {
+ var called = false;
+ return function () {
+ var args = [], len = arguments.length;
+ while ( len-- ) args[ len ] = arguments[ len ];
+
+ if (called) { return }
+ called = true;
+ return fn.apply(this, args)
+ }
+}
+
+/* */
+
+var History = function History (router, base) {
+ this.router = router;
+ this.base = normalizeBase(base);
+ // start with a route object that stands for "nowhere"
+ this.current = START;
+ this.pending = null;
+ this.ready = false;
+ this.readyCbs = [];
+ this.readyErrorCbs = [];
+ this.errorCbs = [];
+};
+
+History.prototype.listen = function listen (cb) {
+ this.cb = cb;
+};
+
+History.prototype.onReady = function onReady (cb, errorCb) {
+ if (this.ready) {
+ cb();
+ } else {
+ this.readyCbs.push(cb);
+ if (errorCb) {
+ this.readyErrorCbs.push(errorCb);
+ }
+ }
+};
+
+History.prototype.onError = function onError (errorCb) {
+ this.errorCbs.push(errorCb);
+};
+
+History.prototype.transitionTo = function transitionTo (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ var route = this.router.match(location, this.current);
+ this.confirmTransition(route, function () {
+ this$1.updateRoute(route);
+ onComplete && onComplete(route);
+ this$1.ensureURL();
+
+ // fire ready cbs once
+ if (!this$1.ready) {
+ this$1.ready = true;
+ this$1.readyCbs.forEach(function (cb) { cb(route); });
+ }
+ }, function (err) {
+ if (onAbort) {
+ onAbort(err);
+ }
+ if (err && !this$1.ready) {
+ this$1.ready = true;
+ this$1.readyErrorCbs.forEach(function (cb) { cb(err); });
+ }
+ });
+};
+
+History.prototype.confirmTransition = function confirmTransition (route, onComplete, onAbort) {
+ var this$1 = this;
+
+ var current = this.current;
+ var abort = function (err) {
+ if (isError(err)) {
+ if (this$1.errorCbs.length) {
+ this$1.errorCbs.forEach(function (cb) { cb(err); });
+ } else {
+ warn(false, 'uncaught error during route navigation:');
+ console.error(err);
+ }
+ }
+ onAbort && onAbort(err);
+ };
+ if (
+ isSameRoute(route, current) &&
+ // in the case the route map has been dynamically appended to
+ route.matched.length === current.matched.length
+ ) {
+ this.ensureURL();
+ return abort()
+ }
+
+ var ref = resolveQueue(this.current.matched, route.matched);
+ var updated = ref.updated;
+ var deactivated = ref.deactivated;
+ var activated = ref.activated;
+
+ var queue = [].concat(
+ // in-component leave guards
+ extractLeaveGuards(deactivated),
+ // global before hooks
+ this.router.beforeHooks,
+ // in-component update hooks
+ extractUpdateHooks(updated),
+ // in-config enter guards
+ activated.map(function (m) { return m.beforeEnter; }),
+ // async components
+ resolveAsyncComponents(activated)
+ );
+
+ this.pending = route;
+ var iterator = function (hook, next) {
+ if (this$1.pending !== route) {
+ return abort()
+ }
+ try {
+ hook(route, current, function (to) {
+ if (to === false || isError(to)) {
+ // next(false) -> abort navigation, ensure current URL
+ this$1.ensureURL(true);
+ abort(to);
+ } else if (
+ typeof to === 'string' ||
+ (typeof to === 'object' && (
+ typeof to.path === 'string' ||
+ typeof to.name === 'string'
+ ))
+ ) {
+ // next('/') or next({ path: '/' }) -> redirect
+ abort();
+ if (typeof to === 'object' && to.replace) {
+ this$1.replace(to);
+ } else {
+ this$1.push(to);
+ }
+ } else {
+ // confirm transition and pass on the value
+ next(to);
+ }
+ });
+ } catch (e) {
+ abort(e);
+ }
+ };
+
+ runQueue(queue, iterator, function () {
+ var postEnterCbs = [];
+ var isValid = function () { return this$1.current === route; };
+ // wait until async components are resolved before
+ // extracting in-component enter guards
+ var enterGuards = extractEnterGuards(activated, postEnterCbs, isValid);
+ var queue = enterGuards.concat(this$1.router.resolveHooks);
+ runQueue(queue, iterator, function () {
+ if (this$1.pending !== route) {
+ return abort()
+ }
+ this$1.pending = null;
+ onComplete(route);
+ if (this$1.router.app) {
+ this$1.router.app.$nextTick(function () {
+ postEnterCbs.forEach(function (cb) { cb(); });
+ });
+ }
+ });
+ });
+};
+
+History.prototype.updateRoute = function updateRoute (route) {
+ var prev = this.current;
+ this.current = route;
+ this.cb && this.cb(route);
+ this.router.afterHooks.forEach(function (hook) {
+ hook && hook(route, prev);
+ });
+};
+
+function normalizeBase (base) {
+ if (!base) {
+ if (inBrowser) {
+ // respect tag
+ var baseEl = document.querySelector('base');
+ base = (baseEl && baseEl.getAttribute('href')) || '/';
+ // strip full URL origin
+ base = base.replace(/^https?:\/\/[^\/]+/, '');
+ } else {
+ base = '/';
+ }
+ }
+ // make sure there's the starting slash
+ if (base.charAt(0) !== '/') {
+ base = '/' + base;
+ }
+ // remove trailing slash
+ return base.replace(/\/$/, '')
+}
+
+function resolveQueue (
+ current,
+ next
+) {
+ var i;
+ var max = Math.max(current.length, next.length);
+ for (i = 0; i < max; i++) {
+ if (current[i] !== next[i]) {
+ break
+ }
+ }
+ return {
+ updated: next.slice(0, i),
+ activated: next.slice(i),
+ deactivated: current.slice(i)
+ }
+}
+
+function extractGuards (
+ records,
+ name,
+ bind,
+ reverse
+) {
+ var guards = flatMapComponents(records, function (def, instance, match, key) {
+ var guard = extractGuard(def, name);
+ if (guard) {
+ return Array.isArray(guard)
+ ? guard.map(function (guard) { return bind(guard, instance, match, key); })
+ : bind(guard, instance, match, key)
+ }
+ });
+ return flatten(reverse ? guards.reverse() : guards)
+}
+
+function extractGuard (
+ def,
+ key
+) {
+ if (typeof def !== 'function') {
+ // extend now so that global mixins are applied.
+ def = _Vue.extend(def);
+ }
+ return def.options[key]
+}
+
+function extractLeaveGuards (deactivated) {
+ return extractGuards(deactivated, 'beforeRouteLeave', bindGuard, true)
+}
+
+function extractUpdateHooks (updated) {
+ return extractGuards(updated, 'beforeRouteUpdate', bindGuard)
+}
+
+function bindGuard (guard, instance) {
+ if (instance) {
+ return function boundRouteGuard () {
+ return guard.apply(instance, arguments)
+ }
+ }
+}
+
+function extractEnterGuards (
+ activated,
+ cbs,
+ isValid
+) {
+ return extractGuards(activated, 'beforeRouteEnter', function (guard, _, match, key) {
+ return bindEnterGuard(guard, match, key, cbs, isValid)
+ })
+}
+
+function bindEnterGuard (
+ guard,
+ match,
+ key,
+ cbs,
+ isValid
+) {
+ return function routeEnterGuard (to, from, next) {
+ return guard(to, from, function (cb) {
+ next(cb);
+ if (typeof cb === 'function') {
+ cbs.push(function () {
+ // #750
+ // if a router-view is wrapped with an out-in transition,
+ // the instance may not have been registered at this time.
+ // we will need to poll for registration until current route
+ // is no longer valid.
+ poll(cb, match.instances, key, isValid);
+ });
+ }
+ })
+ }
+}
+
+function poll (
+ cb, // somehow flow cannot infer this is a function
+ instances,
+ key,
+ isValid
+) {
+ if (instances[key]) {
+ cb(instances[key]);
+ } else if (isValid()) {
+ setTimeout(function () {
+ poll(cb, instances, key, isValid);
+ }, 16);
+ }
+}
+
+/* */
+
+
+var HTML5History = (function (History$$1) {
+ function HTML5History (router, base) {
+ var this$1 = this;
+
+ History$$1.call(this, router, base);
+
+ var expectScroll = router.options.scrollBehavior;
+
+ if (expectScroll) {
+ setupScroll();
+ }
+
+ var initLocation = getLocation(this.base);
+ window.addEventListener('popstate', function (e) {
+ var current = this$1.current;
+
+ // Avoiding first `popstate` event dispatched in some browsers but first
+ // history route not updated since async guard at the same time.
+ var location = getLocation(this$1.base);
+ if (this$1.current === START && location === initLocation) {
+ return
+ }
+
+ this$1.transitionTo(location, function (route) {
+ if (expectScroll) {
+ handleScroll(router, route, current, true);
+ }
+ });
+ });
+ }
+
+ if ( History$$1 ) HTML5History.__proto__ = History$$1;
+ HTML5History.prototype = Object.create( History$$1 && History$$1.prototype );
+ HTML5History.prototype.constructor = HTML5History;
+
+ HTML5History.prototype.go = function go (n) {
+ window.history.go(n);
+ };
+
+ HTML5History.prototype.push = function push (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ var ref = this;
+ var fromRoute = ref.current;
+ this.transitionTo(location, function (route) {
+ pushState(cleanPath(this$1.base + route.fullPath));
+ handleScroll(this$1.router, route, fromRoute, false);
+ onComplete && onComplete(route);
+ }, onAbort);
+ };
+
+ HTML5History.prototype.replace = function replace (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ var ref = this;
+ var fromRoute = ref.current;
+ this.transitionTo(location, function (route) {
+ replaceState(cleanPath(this$1.base + route.fullPath));
+ handleScroll(this$1.router, route, fromRoute, false);
+ onComplete && onComplete(route);
+ }, onAbort);
+ };
+
+ HTML5History.prototype.ensureURL = function ensureURL (push) {
+ if (getLocation(this.base) !== this.current.fullPath) {
+ var current = cleanPath(this.base + this.current.fullPath);
+ push ? pushState(current) : replaceState(current);
+ }
+ };
+
+ HTML5History.prototype.getCurrentLocation = function getCurrentLocation () {
+ return getLocation(this.base)
+ };
+
+ return HTML5History;
+}(History));
+
+function getLocation (base) {
+ var path = window.location.pathname;
+ if (base && path.indexOf(base) === 0) {
+ path = path.slice(base.length);
+ }
+ return (path || '/') + window.location.search + window.location.hash
+}
+
+/* */
+
+
+var HashHistory = (function (History$$1) {
+ function HashHistory (router, base, fallback) {
+ History$$1.call(this, router, base);
+ // check history fallback deeplinking
+ if (fallback && checkFallback(this.base)) {
+ return
+ }
+ ensureSlash();
+ }
+
+ if ( History$$1 ) HashHistory.__proto__ = History$$1;
+ HashHistory.prototype = Object.create( History$$1 && History$$1.prototype );
+ HashHistory.prototype.constructor = HashHistory;
+
+ // this is delayed until the app mounts
+ // to avoid the hashchange listener being fired too early
+ HashHistory.prototype.setupListeners = function setupListeners () {
+ var this$1 = this;
+
+ var router = this.router;
+ var expectScroll = router.options.scrollBehavior;
+ var supportsScroll = supportsPushState && expectScroll;
+
+ if (supportsScroll) {
+ setupScroll();
+ }
+
+ window.addEventListener(supportsPushState ? 'popstate' : 'hashchange', function () {
+ var current = this$1.current;
+ if (!ensureSlash()) {
+ return
+ }
+ this$1.transitionTo(getHash(), function (route) {
+ if (supportsScroll) {
+ handleScroll(this$1.router, route, current, true);
+ }
+ if (!supportsPushState) {
+ replaceHash(route.fullPath);
+ }
+ });
+ });
+ };
+
+ HashHistory.prototype.push = function push (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ var ref = this;
+ var fromRoute = ref.current;
+ this.transitionTo(location, function (route) {
+ pushHash(route.fullPath);
+ handleScroll(this$1.router, route, fromRoute, false);
+ onComplete && onComplete(route);
+ }, onAbort);
+ };
+
+ HashHistory.prototype.replace = function replace (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ var ref = this;
+ var fromRoute = ref.current;
+ this.transitionTo(location, function (route) {
+ replaceHash(route.fullPath);
+ handleScroll(this$1.router, route, fromRoute, false);
+ onComplete && onComplete(route);
+ }, onAbort);
+ };
+
+ HashHistory.prototype.go = function go (n) {
+ window.history.go(n);
+ };
+
+ HashHistory.prototype.ensureURL = function ensureURL (push) {
+ var current = this.current.fullPath;
+ if (getHash() !== current) {
+ push ? pushHash(current) : replaceHash(current);
+ }
+ };
+
+ HashHistory.prototype.getCurrentLocation = function getCurrentLocation () {
+ return getHash()
+ };
+
+ return HashHistory;
+}(History));
+
+function checkFallback (base) {
+ var location = getLocation(base);
+ if (!/^\/#/.test(location)) {
+ window.location.replace(
+ cleanPath(base + '/#' + location)
+ );
+ return true
+ }
+}
+
+function ensureSlash () {
+ var path = getHash();
+ if (path.charAt(0) === '/') {
+ return true
+ }
+ replaceHash('/' + path);
+ return false
+}
+
+function getHash () {
+ // We can't use window.location.hash here because it's not
+ // consistent across browsers - Firefox will pre-decode it!
+ var href = window.location.href;
+ var index = href.indexOf('#');
+ return index === -1 ? '' : href.slice(index + 1)
+}
+
+function getUrl (path) {
+ var href = window.location.href;
+ var i = href.indexOf('#');
+ var base = i >= 0 ? href.slice(0, i) : href;
+ return (base + "#" + path)
+}
+
+function pushHash (path) {
+ if (supportsPushState) {
+ pushState(getUrl(path));
+ } else {
+ window.location.hash = path;
+ }
+}
+
+function replaceHash (path) {
+ if (supportsPushState) {
+ replaceState(getUrl(path));
+ } else {
+ window.location.replace(getUrl(path));
+ }
+}
+
+/* */
+
+
+var AbstractHistory = (function (History$$1) {
+ function AbstractHistory (router, base) {
+ History$$1.call(this, router, base);
+ this.stack = [];
+ this.index = -1;
+ }
+
+ if ( History$$1 ) AbstractHistory.__proto__ = History$$1;
+ AbstractHistory.prototype = Object.create( History$$1 && History$$1.prototype );
+ AbstractHistory.prototype.constructor = AbstractHistory;
+
+ AbstractHistory.prototype.push = function push (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ this.transitionTo(location, function (route) {
+ this$1.stack = this$1.stack.slice(0, this$1.index + 1).concat(route);
+ this$1.index++;
+ onComplete && onComplete(route);
+ }, onAbort);
+ };
+
+ AbstractHistory.prototype.replace = function replace (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ this.transitionTo(location, function (route) {
+ this$1.stack = this$1.stack.slice(0, this$1.index).concat(route);
+ onComplete && onComplete(route);
+ }, onAbort);
+ };
+
+ AbstractHistory.prototype.go = function go (n) {
+ var this$1 = this;
+
+ var targetIndex = this.index + n;
+ if (targetIndex < 0 || targetIndex >= this.stack.length) {
+ return
+ }
+ var route = this.stack[targetIndex];
+ this.confirmTransition(route, function () {
+ this$1.index = targetIndex;
+ this$1.updateRoute(route);
+ });
+ };
+
+ AbstractHistory.prototype.getCurrentLocation = function getCurrentLocation () {
+ var current = this.stack[this.stack.length - 1];
+ return current ? current.fullPath : '/'
+ };
+
+ AbstractHistory.prototype.ensureURL = function ensureURL () {
+ // noop
+ };
+
+ return AbstractHistory;
+}(History));
+
+/* */
+
+var VueRouter = function VueRouter (options) {
+ if ( options === void 0 ) options = {};
+
+ this.app = null;
+ this.apps = [];
+ this.options = options;
+ this.beforeHooks = [];
+ this.resolveHooks = [];
+ this.afterHooks = [];
+ this.matcher = createMatcher(options.routes || [], this);
+
+ var mode = options.mode || 'hash';
+ this.fallback = mode === 'history' && !supportsPushState && options.fallback !== false;
+ if (this.fallback) {
+ mode = 'hash';
+ }
+ if (!inBrowser) {
+ mode = 'abstract';
+ }
+ this.mode = mode;
+
+ switch (mode) {
+ case 'history':
+ this.history = new HTML5History(this, options.base);
+ break
+ case 'hash':
+ this.history = new HashHistory(this, options.base, this.fallback);
+ break
+ case 'abstract':
+ this.history = new AbstractHistory(this, options.base);
+ break
+ default:
+ if (process.env.NODE_ENV !== 'production') {
+ assert(false, ("invalid mode: " + mode));
+ }
+ }
+};
+
+var prototypeAccessors = { currentRoute: { configurable: true } };
+
+VueRouter.prototype.match = function match (
+ raw,
+ current,
+ redirectedFrom
+) {
+ return this.matcher.match(raw, current, redirectedFrom)
+};
+
+prototypeAccessors.currentRoute.get = function () {
+ return this.history && this.history.current
+};
+
+VueRouter.prototype.init = function init (app /* Vue component instance */) {
+ var this$1 = this;
+
+ process.env.NODE_ENV !== 'production' && assert(
+ install.installed,
+ "not installed. Make sure to call `Vue.use(VueRouter)` " +
+ "before creating root instance."
+ );
+
+ this.apps.push(app);
+
+ // main app already initialized.
+ if (this.app) {
+ return
+ }
+
+ this.app = app;
+
+ var history = this.history;
+
+ if (history instanceof HTML5History) {
+ history.transitionTo(history.getCurrentLocation());
+ } else if (history instanceof HashHistory) {
+ var setupHashListener = function () {
+ history.setupListeners();
+ };
+ history.transitionTo(
+ history.getCurrentLocation(),
+ setupHashListener,
+ setupHashListener
+ );
+ }
+
+ history.listen(function (route) {
+ this$1.apps.forEach(function (app) {
+ app._route = route;
+ });
+ });
+};
+
+VueRouter.prototype.beforeEach = function beforeEach (fn) {
+ return registerHook(this.beforeHooks, fn)
+};
+
+VueRouter.prototype.beforeResolve = function beforeResolve (fn) {
+ return registerHook(this.resolveHooks, fn)
+};
+
+VueRouter.prototype.afterEach = function afterEach (fn) {
+ return registerHook(this.afterHooks, fn)
+};
+
+VueRouter.prototype.onReady = function onReady (cb, errorCb) {
+ this.history.onReady(cb, errorCb);
+};
+
+VueRouter.prototype.onError = function onError (errorCb) {
+ this.history.onError(errorCb);
+};
+
+VueRouter.prototype.push = function push (location, onComplete, onAbort) {
+ this.history.push(location, onComplete, onAbort);
+};
+
+VueRouter.prototype.replace = function replace (location, onComplete, onAbort) {
+ this.history.replace(location, onComplete, onAbort);
+};
+
+VueRouter.prototype.go = function go (n) {
+ this.history.go(n);
+};
+
+VueRouter.prototype.back = function back () {
+ this.go(-1);
+};
+
+VueRouter.prototype.forward = function forward () {
+ this.go(1);
+};
+
+VueRouter.prototype.getMatchedComponents = function getMatchedComponents (to) {
+ var route = to
+ ? to.matched
+ ? to
+ : this.resolve(to).route
+ : this.currentRoute;
+ if (!route) {
+ return []
+ }
+ return [].concat.apply([], route.matched.map(function (m) {
+ return Object.keys(m.components).map(function (key) {
+ return m.components[key]
+ })
+ }))
+};
+
+VueRouter.prototype.resolve = function resolve (
+ to,
+ current,
+ append
+) {
+ var location = normalizeLocation(
+ to,
+ current || this.history.current,
+ append,
+ this
+ );
+ var route = this.match(location, current);
+ var fullPath = route.redirectedFrom || route.fullPath;
+ var base = this.history.base;
+ var href = createHref(base, fullPath, this.mode);
+ return {
+ location: location,
+ route: route,
+ href: href,
+ // for backwards compat
+ normalizedTo: location,
+ resolved: route
+ }
+};
+
+VueRouter.prototype.addRoutes = function addRoutes (routes) {
+ this.matcher.addRoutes(routes);
+ if (this.history.current !== START) {
+ this.history.transitionTo(this.history.getCurrentLocation());
+ }
+};
+
+Object.defineProperties( VueRouter.prototype, prototypeAccessors );
+
+function registerHook (list, fn) {
+ list.push(fn);
+ return function () {
+ var i = list.indexOf(fn);
+ if (i > -1) { list.splice(i, 1); }
+ }
+}
+
+function createHref (base, fullPath, mode) {
+ var path = mode === 'hash' ? '#' + fullPath : fullPath;
+ return base ? cleanPath(base + '/' + path) : path
+}
+
+VueRouter.install = install;
+VueRouter.version = '3.0.1';
+
+if (inBrowser && window.Vue) {
+ window.Vue.use(VueRouter);
+}
+
+export default VueRouter;
diff --git a/dist/www/lib/vue-router.js b/dist/www/lib/vue-router.js
new file mode 100644
index 0000000..3285a76
--- /dev/null
+++ b/dist/www/lib/vue-router.js
@@ -0,0 +1,2631 @@
+/**
+ * vue-router v3.0.1
+ * (c) 2017 Evan You
+ * @license MIT
+ */
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global.VueRouter = factory());
+}(this, (function () { 'use strict';
+
+/* */
+
+function assert (condition, message) {
+ if (!condition) {
+ throw new Error(("[vue-router] " + message))
+ }
+}
+
+function warn (condition, message) {
+ if ("development" !== 'production' && !condition) {
+ typeof console !== 'undefined' && console.warn(("[vue-router] " + message));
+ }
+}
+
+function isError (err) {
+ return Object.prototype.toString.call(err).indexOf('Error') > -1
+}
+
+var View = {
+ name: 'router-view',
+ functional: true,
+ props: {
+ name: {
+ type: String,
+ default: 'default'
+ }
+ },
+ render: function render (_, ref) {
+ var props = ref.props;
+ var children = ref.children;
+ var parent = ref.parent;
+ var data = ref.data;
+
+ data.routerView = true;
+
+ // directly use parent context's createElement() function
+ // so that components rendered by router-view can resolve named slots
+ var h = parent.$createElement;
+ var name = props.name;
+ var route = parent.$route;
+ var cache = parent._routerViewCache || (parent._routerViewCache = {});
+
+ // determine current view depth, also check to see if the tree
+ // has been toggled inactive but kept-alive.
+ var depth = 0;
+ var inactive = false;
+ while (parent && parent._routerRoot !== parent) {
+ if (parent.$vnode && parent.$vnode.data.routerView) {
+ depth++;
+ }
+ if (parent._inactive) {
+ inactive = true;
+ }
+ parent = parent.$parent;
+ }
+ data.routerViewDepth = depth;
+
+ // render previous view if the tree is inactive and kept-alive
+ if (inactive) {
+ return h(cache[name], data, children)
+ }
+
+ var matched = route.matched[depth];
+ // render empty node if no matched route
+ if (!matched) {
+ cache[name] = null;
+ return h()
+ }
+
+ var component = cache[name] = matched.components[name];
+
+ // attach instance registration hook
+ // this will be called in the instance's injected lifecycle hooks
+ data.registerRouteInstance = function (vm, val) {
+ // val could be undefined for unregistration
+ var current = matched.instances[name];
+ if (
+ (val && current !== vm) ||
+ (!val && current === vm)
+ ) {
+ matched.instances[name] = val;
+ }
+ }
+
+ // also register instance in prepatch hook
+ // in case the same component instance is reused across different routes
+ ;(data.hook || (data.hook = {})).prepatch = function (_, vnode) {
+ matched.instances[name] = vnode.componentInstance;
+ };
+
+ // resolve props
+ var propsToPass = data.props = resolveProps(route, matched.props && matched.props[name]);
+ if (propsToPass) {
+ // clone to prevent mutation
+ propsToPass = data.props = extend({}, propsToPass);
+ // pass non-declared props as attrs
+ var attrs = data.attrs = data.attrs || {};
+ for (var key in propsToPass) {
+ if (!component.props || !(key in component.props)) {
+ attrs[key] = propsToPass[key];
+ delete propsToPass[key];
+ }
+ }
+ }
+
+ return h(component, data, children)
+ }
+};
+
+function resolveProps (route, config) {
+ switch (typeof config) {
+ case 'undefined':
+ return
+ case 'object':
+ return config
+ case 'function':
+ return config(route)
+ case 'boolean':
+ return config ? route.params : undefined
+ default:
+ {
+ warn(
+ false,
+ "props in \"" + (route.path) + "\" is a " + (typeof config) + ", " +
+ "expecting an object, function or boolean."
+ );
+ }
+ }
+}
+
+function extend (to, from) {
+ for (var key in from) {
+ to[key] = from[key];
+ }
+ return to
+}
+
+/* */
+
+var encodeReserveRE = /[!'()*]/g;
+var encodeReserveReplacer = function (c) { return '%' + c.charCodeAt(0).toString(16); };
+var commaRE = /%2C/g;
+
+// fixed encodeURIComponent which is more conformant to RFC3986:
+// - escapes [!'()*]
+// - preserve commas
+var encode = function (str) { return encodeURIComponent(str)
+ .replace(encodeReserveRE, encodeReserveReplacer)
+ .replace(commaRE, ','); };
+
+var decode = decodeURIComponent;
+
+function resolveQuery (
+ query,
+ extraQuery,
+ _parseQuery
+) {
+ if ( extraQuery === void 0 ) extraQuery = {};
+
+ var parse = _parseQuery || parseQuery;
+ var parsedQuery;
+ try {
+ parsedQuery = parse(query || '');
+ } catch (e) {
+ "development" !== 'production' && warn(false, e.message);
+ parsedQuery = {};
+ }
+ for (var key in extraQuery) {
+ parsedQuery[key] = extraQuery[key];
+ }
+ return parsedQuery
+}
+
+function parseQuery (query) {
+ var res = {};
+
+ query = query.trim().replace(/^(\?|#|&)/, '');
+
+ if (!query) {
+ return res
+ }
+
+ query.split('&').forEach(function (param) {
+ var parts = param.replace(/\+/g, ' ').split('=');
+ var key = decode(parts.shift());
+ var val = parts.length > 0
+ ? decode(parts.join('='))
+ : null;
+
+ if (res[key] === undefined) {
+ res[key] = val;
+ } else if (Array.isArray(res[key])) {
+ res[key].push(val);
+ } else {
+ res[key] = [res[key], val];
+ }
+ });
+
+ return res
+}
+
+function stringifyQuery (obj) {
+ var res = obj ? Object.keys(obj).map(function (key) {
+ var val = obj[key];
+
+ if (val === undefined) {
+ return ''
+ }
+
+ if (val === null) {
+ return encode(key)
+ }
+
+ if (Array.isArray(val)) {
+ var result = [];
+ val.forEach(function (val2) {
+ if (val2 === undefined) {
+ return
+ }
+ if (val2 === null) {
+ result.push(encode(key));
+ } else {
+ result.push(encode(key) + '=' + encode(val2));
+ }
+ });
+ return result.join('&')
+ }
+
+ return encode(key) + '=' + encode(val)
+ }).filter(function (x) { return x.length > 0; }).join('&') : null;
+ return res ? ("?" + res) : ''
+}
+
+/* */
+
+
+var trailingSlashRE = /\/?$/;
+
+function createRoute (
+ record,
+ location,
+ redirectedFrom,
+ router
+) {
+ var stringifyQuery$$1 = router && router.options.stringifyQuery;
+
+ var query = location.query || {};
+ try {
+ query = clone(query);
+ } catch (e) {}
+
+ var route = {
+ name: location.name || (record && record.name),
+ meta: (record && record.meta) || {},
+ path: location.path || '/',
+ hash: location.hash || '',
+ query: query,
+ params: location.params || {},
+ fullPath: getFullPath(location, stringifyQuery$$1),
+ matched: record ? formatMatch(record) : []
+ };
+ if (redirectedFrom) {
+ route.redirectedFrom = getFullPath(redirectedFrom, stringifyQuery$$1);
+ }
+ return Object.freeze(route)
+}
+
+function clone (value) {
+ if (Array.isArray(value)) {
+ return value.map(clone)
+ } else if (value && typeof value === 'object') {
+ var res = {};
+ for (var key in value) {
+ res[key] = clone(value[key]);
+ }
+ return res
+ } else {
+ return value
+ }
+}
+
+// the starting route that represents the initial state
+var START = createRoute(null, {
+ path: '/'
+});
+
+function formatMatch (record) {
+ var res = [];
+ while (record) {
+ res.unshift(record);
+ record = record.parent;
+ }
+ return res
+}
+
+function getFullPath (
+ ref,
+ _stringifyQuery
+) {
+ var path = ref.path;
+ var query = ref.query; if ( query === void 0 ) query = {};
+ var hash = ref.hash; if ( hash === void 0 ) hash = '';
+
+ var stringify = _stringifyQuery || stringifyQuery;
+ return (path || '/') + stringify(query) + hash
+}
+
+function isSameRoute (a, b) {
+ if (b === START) {
+ return a === b
+ } else if (!b) {
+ return false
+ } else if (a.path && b.path) {
+ return (
+ a.path.replace(trailingSlashRE, '') === b.path.replace(trailingSlashRE, '') &&
+ a.hash === b.hash &&
+ isObjectEqual(a.query, b.query)
+ )
+ } else if (a.name && b.name) {
+ return (
+ a.name === b.name &&
+ a.hash === b.hash &&
+ isObjectEqual(a.query, b.query) &&
+ isObjectEqual(a.params, b.params)
+ )
+ } else {
+ return false
+ }
+}
+
+function isObjectEqual (a, b) {
+ if ( a === void 0 ) a = {};
+ if ( b === void 0 ) b = {};
+
+ // handle null value #1566
+ if (!a || !b) { return a === b }
+ var aKeys = Object.keys(a);
+ var bKeys = Object.keys(b);
+ if (aKeys.length !== bKeys.length) {
+ return false
+ }
+ return aKeys.every(function (key) {
+ var aVal = a[key];
+ var bVal = b[key];
+ // check nested equality
+ if (typeof aVal === 'object' && typeof bVal === 'object') {
+ return isObjectEqual(aVal, bVal)
+ }
+ return String(aVal) === String(bVal)
+ })
+}
+
+function isIncludedRoute (current, target) {
+ return (
+ current.path.replace(trailingSlashRE, '/').indexOf(
+ target.path.replace(trailingSlashRE, '/')
+ ) === 0 &&
+ (!target.hash || current.hash === target.hash) &&
+ queryIncludes(current.query, target.query)
+ )
+}
+
+function queryIncludes (current, target) {
+ for (var key in target) {
+ if (!(key in current)) {
+ return false
+ }
+ }
+ return true
+}
+
+/* */
+
+// work around weird flow bug
+var toTypes = [String, Object];
+var eventTypes = [String, Array];
+
+var Link = {
+ name: 'router-link',
+ props: {
+ to: {
+ type: toTypes,
+ required: true
+ },
+ tag: {
+ type: String,
+ default: 'a'
+ },
+ exact: Boolean,
+ append: Boolean,
+ replace: Boolean,
+ activeClass: String,
+ exactActiveClass: String,
+ event: {
+ type: eventTypes,
+ default: 'click'
+ }
+ },
+ render: function render (h) {
+ var this$1 = this;
+
+ var router = this.$router;
+ var current = this.$route;
+ var ref = router.resolve(this.to, current, this.append);
+ var location = ref.location;
+ var route = ref.route;
+ var href = ref.href;
+
+ var classes = {};
+ var globalActiveClass = router.options.linkActiveClass;
+ var globalExactActiveClass = router.options.linkExactActiveClass;
+ // Support global empty active class
+ var activeClassFallback = globalActiveClass == null
+ ? 'router-link-active'
+ : globalActiveClass;
+ var exactActiveClassFallback = globalExactActiveClass == null
+ ? 'router-link-exact-active'
+ : globalExactActiveClass;
+ var activeClass = this.activeClass == null
+ ? activeClassFallback
+ : this.activeClass;
+ var exactActiveClass = this.exactActiveClass == null
+ ? exactActiveClassFallback
+ : this.exactActiveClass;
+ var compareTarget = location.path
+ ? createRoute(null, location, null, router)
+ : route;
+
+ classes[exactActiveClass] = isSameRoute(current, compareTarget);
+ classes[activeClass] = this.exact
+ ? classes[exactActiveClass]
+ : isIncludedRoute(current, compareTarget);
+
+ var handler = function (e) {
+ if (guardEvent(e)) {
+ if (this$1.replace) {
+ router.replace(location);
+ } else {
+ router.push(location);
+ }
+ }
+ };
+
+ var on = { click: guardEvent };
+ if (Array.isArray(this.event)) {
+ this.event.forEach(function (e) { on[e] = handler; });
+ } else {
+ on[this.event] = handler;
+ }
+
+ var data = {
+ class: classes
+ };
+
+ if (this.tag === 'a') {
+ data.on = on;
+ data.attrs = { href: href };
+ } else {
+ // find the first child and apply listener and href
+ var a = findAnchor(this.$slots.default);
+ if (a) {
+ // in case the is a static node
+ a.isStatic = false;
+ var extend = _Vue.util.extend;
+ var aData = a.data = extend({}, a.data);
+ aData.on = on;
+ var aAttrs = a.data.attrs = extend({}, a.data.attrs);
+ aAttrs.href = href;
+ } else {
+ // doesn't have child, apply listener to self
+ data.on = on;
+ }
+ }
+
+ return h(this.tag, data, this.$slots.default)
+ }
+};
+
+function guardEvent (e) {
+ // don't redirect with control keys
+ if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) { return }
+ // don't redirect when preventDefault called
+ if (e.defaultPrevented) { return }
+ // don't redirect on right click
+ if (e.button !== undefined && e.button !== 0) { return }
+ // don't redirect if `target="_blank"`
+ if (e.currentTarget && e.currentTarget.getAttribute) {
+ var target = e.currentTarget.getAttribute('target');
+ if (/\b_blank\b/i.test(target)) { return }
+ }
+ // this may be a Weex event which doesn't have this method
+ if (e.preventDefault) {
+ e.preventDefault();
+ }
+ return true
+}
+
+function findAnchor (children) {
+ if (children) {
+ var child;
+ for (var i = 0; i < children.length; i++) {
+ child = children[i];
+ if (child.tag === 'a') {
+ return child
+ }
+ if (child.children && (child = findAnchor(child.children))) {
+ return child
+ }
+ }
+ }
+}
+
+var _Vue;
+
+function install (Vue) {
+ if (install.installed && _Vue === Vue) { return }
+ install.installed = true;
+
+ _Vue = Vue;
+
+ var isDef = function (v) { return v !== undefined; };
+
+ var registerInstance = function (vm, callVal) {
+ var i = vm.$options._parentVnode;
+ if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
+ i(vm, callVal);
+ }
+ };
+
+ Vue.mixin({
+ beforeCreate: function beforeCreate () {
+ if (isDef(this.$options.router)) {
+ this._routerRoot = this;
+ this._router = this.$options.router;
+ this._router.init(this);
+ Vue.util.defineReactive(this, '_route', this._router.history.current);
+ } else {
+ this._routerRoot = (this.$parent && this.$parent._routerRoot) || this;
+ }
+ registerInstance(this, this);
+ },
+ destroyed: function destroyed () {
+ registerInstance(this);
+ }
+ });
+
+ Object.defineProperty(Vue.prototype, '$router', {
+ get: function get () { return this._routerRoot._router }
+ });
+
+ Object.defineProperty(Vue.prototype, '$route', {
+ get: function get () { return this._routerRoot._route }
+ });
+
+ Vue.component('router-view', View);
+ Vue.component('router-link', Link);
+
+ var strats = Vue.config.optionMergeStrategies;
+ // use the same hook merging strategy for route hooks
+ strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created;
+}
+
+/* */
+
+var inBrowser = typeof window !== 'undefined';
+
+/* */
+
+function resolvePath (
+ relative,
+ base,
+ append
+) {
+ var firstChar = relative.charAt(0);
+ if (firstChar === '/') {
+ return relative
+ }
+
+ if (firstChar === '?' || firstChar === '#') {
+ return base + relative
+ }
+
+ var stack = base.split('/');
+
+ // remove trailing segment if:
+ // - not appending
+ // - appending to trailing slash (last segment is empty)
+ if (!append || !stack[stack.length - 1]) {
+ stack.pop();
+ }
+
+ // resolve relative path
+ var segments = relative.replace(/^\//, '').split('/');
+ for (var i = 0; i < segments.length; i++) {
+ var segment = segments[i];
+ if (segment === '..') {
+ stack.pop();
+ } else if (segment !== '.') {
+ stack.push(segment);
+ }
+ }
+
+ // ensure leading slash
+ if (stack[0] !== '') {
+ stack.unshift('');
+ }
+
+ return stack.join('/')
+}
+
+function parsePath (path) {
+ var hash = '';
+ var query = '';
+
+ var hashIndex = path.indexOf('#');
+ if (hashIndex >= 0) {
+ hash = path.slice(hashIndex);
+ path = path.slice(0, hashIndex);
+ }
+
+ var queryIndex = path.indexOf('?');
+ if (queryIndex >= 0) {
+ query = path.slice(queryIndex + 1);
+ path = path.slice(0, queryIndex);
+ }
+
+ return {
+ path: path,
+ query: query,
+ hash: hash
+ }
+}
+
+function cleanPath (path) {
+ return path.replace(/\/\//g, '/')
+}
+
+var isarray = Array.isArray || function (arr) {
+ return Object.prototype.toString.call(arr) == '[object Array]';
+};
+
+/**
+ * Expose `pathToRegexp`.
+ */
+var pathToRegexp_1 = pathToRegexp;
+var parse_1 = parse;
+var compile_1 = compile;
+var tokensToFunction_1 = tokensToFunction;
+var tokensToRegExp_1 = tokensToRegExp;
+
+/**
+ * The main path matching regexp utility.
+ *
+ * @type {RegExp}
+ */
+var PATH_REGEXP = new RegExp([
+ // Match escaped characters that would otherwise appear in future matches.
+ // This allows the user to escape special characters that won't transform.
+ '(\\\\.)',
+ // Match Express-style parameters and un-named parameters with a prefix
+ // and optional suffixes. Matches appear as:
+ //
+ // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined]
+ // "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined, undefined]
+ // "/*" => ["/", undefined, undefined, undefined, undefined, "*"]
+ '([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))'
+].join('|'), 'g');
+
+/**
+ * Parse a string for the raw tokens.
+ *
+ * @param {string} str
+ * @param {Object=} options
+ * @return {!Array}
+ */
+function parse (str, options) {
+ var tokens = [];
+ var key = 0;
+ var index = 0;
+ var path = '';
+ var defaultDelimiter = options && options.delimiter || '/';
+ var res;
+
+ while ((res = PATH_REGEXP.exec(str)) != null) {
+ var m = res[0];
+ var escaped = res[1];
+ var offset = res.index;
+ path += str.slice(index, offset);
+ index = offset + m.length;
+
+ // Ignore already escaped sequences.
+ if (escaped) {
+ path += escaped[1];
+ continue
+ }
+
+ var next = str[index];
+ var prefix = res[2];
+ var name = res[3];
+ var capture = res[4];
+ var group = res[5];
+ var modifier = res[6];
+ var asterisk = res[7];
+
+ // Push the current path onto the tokens.
+ if (path) {
+ tokens.push(path);
+ path = '';
+ }
+
+ var partial = prefix != null && next != null && next !== prefix;
+ var repeat = modifier === '+' || modifier === '*';
+ var optional = modifier === '?' || modifier === '*';
+ var delimiter = res[2] || defaultDelimiter;
+ var pattern = capture || group;
+
+ tokens.push({
+ name: name || key++,
+ prefix: prefix || '',
+ delimiter: delimiter,
+ optional: optional,
+ repeat: repeat,
+ partial: partial,
+ asterisk: !!asterisk,
+ pattern: pattern ? escapeGroup(pattern) : (asterisk ? '.*' : '[^' + escapeString(delimiter) + ']+?')
+ });
+ }
+
+ // Match any characters still remaining.
+ if (index < str.length) {
+ path += str.substr(index);
+ }
+
+ // If the path exists, push it onto the end.
+ if (path) {
+ tokens.push(path);
+ }
+
+ return tokens
+}
+
+/**
+ * Compile a string to a template function for the path.
+ *
+ * @param {string} str
+ * @param {Object=} options
+ * @return {!function(Object=, Object=)}
+ */
+function compile (str, options) {
+ return tokensToFunction(parse(str, options))
+}
+
+/**
+ * Prettier encoding of URI path segments.
+ *
+ * @param {string}
+ * @return {string}
+ */
+function encodeURIComponentPretty (str) {
+ return encodeURI(str).replace(/[\/?#]/g, function (c) {
+ return '%' + c.charCodeAt(0).toString(16).toUpperCase()
+ })
+}
+
+/**
+ * Encode the asterisk parameter. Similar to `pretty`, but allows slashes.
+ *
+ * @param {string}
+ * @return {string}
+ */
+function encodeAsterisk (str) {
+ return encodeURI(str).replace(/[?#]/g, function (c) {
+ return '%' + c.charCodeAt(0).toString(16).toUpperCase()
+ })
+}
+
+/**
+ * Expose a method for transforming tokens into the path function.
+ */
+function tokensToFunction (tokens) {
+ // Compile all the tokens into regexps.
+ var matches = new Array(tokens.length);
+
+ // Compile all the patterns before compilation.
+ for (var i = 0; i < tokens.length; i++) {
+ if (typeof tokens[i] === 'object') {
+ matches[i] = new RegExp('^(?:' + tokens[i].pattern + ')$');
+ }
+ }
+
+ return function (obj, opts) {
+ var path = '';
+ var data = obj || {};
+ var options = opts || {};
+ var encode = options.pretty ? encodeURIComponentPretty : encodeURIComponent;
+
+ for (var i = 0; i < tokens.length; i++) {
+ var token = tokens[i];
+
+ if (typeof token === 'string') {
+ path += token;
+
+ continue
+ }
+
+ var value = data[token.name];
+ var segment;
+
+ if (value == null) {
+ if (token.optional) {
+ // Prepend partial segment prefixes.
+ if (token.partial) {
+ path += token.prefix;
+ }
+
+ continue
+ } else {
+ throw new TypeError('Expected "' + token.name + '" to be defined')
+ }
+ }
+
+ if (isarray(value)) {
+ if (!token.repeat) {
+ throw new TypeError('Expected "' + token.name + '" to not repeat, but received `' + JSON.stringify(value) + '`')
+ }
+
+ if (value.length === 0) {
+ if (token.optional) {
+ continue
+ } else {
+ throw new TypeError('Expected "' + token.name + '" to not be empty')
+ }
+ }
+
+ for (var j = 0; j < value.length; j++) {
+ segment = encode(value[j]);
+
+ if (!matches[i].test(segment)) {
+ throw new TypeError('Expected all "' + token.name + '" to match "' + token.pattern + '", but received `' + JSON.stringify(segment) + '`')
+ }
+
+ path += (j === 0 ? token.prefix : token.delimiter) + segment;
+ }
+
+ continue
+ }
+
+ segment = token.asterisk ? encodeAsterisk(value) : encode(value);
+
+ if (!matches[i].test(segment)) {
+ throw new TypeError('Expected "' + token.name + '" to match "' + token.pattern + '", but received "' + segment + '"')
+ }
+
+ path += token.prefix + segment;
+ }
+
+ return path
+ }
+}
+
+/**
+ * Escape a regular expression string.
+ *
+ * @param {string} str
+ * @return {string}
+ */
+function escapeString (str) {
+ return str.replace(/([.+*?=^!:${}()[\]|\/\\])/g, '\\$1')
+}
+
+/**
+ * Escape the capturing group by escaping special characters and meaning.
+ *
+ * @param {string} group
+ * @return {string}
+ */
+function escapeGroup (group) {
+ return group.replace(/([=!:$\/()])/g, '\\$1')
+}
+
+/**
+ * Attach the keys as a property of the regexp.
+ *
+ * @param {!RegExp} re
+ * @param {Array} keys
+ * @return {!RegExp}
+ */
+function attachKeys (re, keys) {
+ re.keys = keys;
+ return re
+}
+
+/**
+ * Get the flags for a regexp from the options.
+ *
+ * @param {Object} options
+ * @return {string}
+ */
+function flags (options) {
+ return options.sensitive ? '' : 'i'
+}
+
+/**
+ * Pull out keys from a regexp.
+ *
+ * @param {!RegExp} path
+ * @param {!Array} keys
+ * @return {!RegExp}
+ */
+function regexpToRegexp (path, keys) {
+ // Use a negative lookahead to match only capturing groups.
+ var groups = path.source.match(/\((?!\?)/g);
+
+ if (groups) {
+ for (var i = 0; i < groups.length; i++) {
+ keys.push({
+ name: i,
+ prefix: null,
+ delimiter: null,
+ optional: false,
+ repeat: false,
+ partial: false,
+ asterisk: false,
+ pattern: null
+ });
+ }
+ }
+
+ return attachKeys(path, keys)
+}
+
+/**
+ * Transform an array into a regexp.
+ *
+ * @param {!Array} path
+ * @param {Array} keys
+ * @param {!Object} options
+ * @return {!RegExp}
+ */
+function arrayToRegexp (path, keys, options) {
+ var parts = [];
+
+ for (var i = 0; i < path.length; i++) {
+ parts.push(pathToRegexp(path[i], keys, options).source);
+ }
+
+ var regexp = new RegExp('(?:' + parts.join('|') + ')', flags(options));
+
+ return attachKeys(regexp, keys)
+}
+
+/**
+ * Create a path regexp from string input.
+ *
+ * @param {string} path
+ * @param {!Array} keys
+ * @param {!Object} options
+ * @return {!RegExp}
+ */
+function stringToRegexp (path, keys, options) {
+ return tokensToRegExp(parse(path, options), keys, options)
+}
+
+/**
+ * Expose a function for taking tokens and returning a RegExp.
+ *
+ * @param {!Array} tokens
+ * @param {(Array|Object)=} keys
+ * @param {Object=} options
+ * @return {!RegExp}
+ */
+function tokensToRegExp (tokens, keys, options) {
+ if (!isarray(keys)) {
+ options = /** @type {!Object} */ (keys || options);
+ keys = [];
+ }
+
+ options = options || {};
+
+ var strict = options.strict;
+ var end = options.end !== false;
+ var route = '';
+
+ // Iterate over the tokens and create our regexp string.
+ for (var i = 0; i < tokens.length; i++) {
+ var token = tokens[i];
+
+ if (typeof token === 'string') {
+ route += escapeString(token);
+ } else {
+ var prefix = escapeString(token.prefix);
+ var capture = '(?:' + token.pattern + ')';
+
+ keys.push(token);
+
+ if (token.repeat) {
+ capture += '(?:' + prefix + capture + ')*';
+ }
+
+ if (token.optional) {
+ if (!token.partial) {
+ capture = '(?:' + prefix + '(' + capture + '))?';
+ } else {
+ capture = prefix + '(' + capture + ')?';
+ }
+ } else {
+ capture = prefix + '(' + capture + ')';
+ }
+
+ route += capture;
+ }
+ }
+
+ var delimiter = escapeString(options.delimiter || '/');
+ var endsWithDelimiter = route.slice(-delimiter.length) === delimiter;
+
+ // In non-strict mode we allow a slash at the end of match. If the path to
+ // match already ends with a slash, we remove it for consistency. The slash
+ // is valid at the end of a path match, not in the middle. This is important
+ // in non-ending mode, where "/test/" shouldn't match "/test//route".
+ if (!strict) {
+ route = (endsWithDelimiter ? route.slice(0, -delimiter.length) : route) + '(?:' + delimiter + '(?=$))?';
+ }
+
+ if (end) {
+ route += '$';
+ } else {
+ // In non-ending mode, we need the capturing groups to match as much as
+ // possible by using a positive lookahead to the end or next path segment.
+ route += strict && endsWithDelimiter ? '' : '(?=' + delimiter + '|$)';
+ }
+
+ return attachKeys(new RegExp('^' + route, flags(options)), keys)
+}
+
+/**
+ * Normalize the given path string, returning a regular expression.
+ *
+ * An empty array can be passed in for the keys, which will hold the
+ * placeholder key descriptions. For example, using `/user/:id`, `keys` will
+ * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.
+ *
+ * @param {(string|RegExp|Array)} path
+ * @param {(Array|Object)=} keys
+ * @param {Object=} options
+ * @return {!RegExp}
+ */
+function pathToRegexp (path, keys, options) {
+ if (!isarray(keys)) {
+ options = /** @type {!Object} */ (keys || options);
+ keys = [];
+ }
+
+ options = options || {};
+
+ if (path instanceof RegExp) {
+ return regexpToRegexp(path, /** @type {!Array} */ (keys))
+ }
+
+ if (isarray(path)) {
+ return arrayToRegexp(/** @type {!Array} */ (path), /** @type {!Array} */ (keys), options)
+ }
+
+ return stringToRegexp(/** @type {string} */ (path), /** @type {!Array} */ (keys), options)
+}
+
+pathToRegexp_1.parse = parse_1;
+pathToRegexp_1.compile = compile_1;
+pathToRegexp_1.tokensToFunction = tokensToFunction_1;
+pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
+
+/* */
+
+// $flow-disable-line
+var regexpCompileCache = Object.create(null);
+
+function fillParams (
+ path,
+ params,
+ routeMsg
+) {
+ try {
+ var filler =
+ regexpCompileCache[path] ||
+ (regexpCompileCache[path] = pathToRegexp_1.compile(path));
+ return filler(params || {}, { pretty: true })
+ } catch (e) {
+ {
+ warn(false, ("missing param for " + routeMsg + ": " + (e.message)));
+ }
+ return ''
+ }
+}
+
+/* */
+
+function createRouteMap (
+ routes,
+ oldPathList,
+ oldPathMap,
+ oldNameMap
+) {
+ // the path list is used to control path matching priority
+ var pathList = oldPathList || [];
+ // $flow-disable-line
+ var pathMap = oldPathMap || Object.create(null);
+ // $flow-disable-line
+ var nameMap = oldNameMap || Object.create(null);
+
+ routes.forEach(function (route) {
+ addRouteRecord(pathList, pathMap, nameMap, route);
+ });
+
+ // ensure wildcard routes are always at the end
+ for (var i = 0, l = pathList.length; i < l; i++) {
+ if (pathList[i] === '*') {
+ pathList.push(pathList.splice(i, 1)[0]);
+ l--;
+ i--;
+ }
+ }
+
+ return {
+ pathList: pathList,
+ pathMap: pathMap,
+ nameMap: nameMap
+ }
+}
+
+function addRouteRecord (
+ pathList,
+ pathMap,
+ nameMap,
+ route,
+ parent,
+ matchAs
+) {
+ var path = route.path;
+ var name = route.name;
+ {
+ assert(path != null, "\"path\" is required in a route configuration.");
+ assert(
+ typeof route.component !== 'string',
+ "route config \"component\" for path: " + (String(path || name)) + " cannot be a " +
+ "string id. Use an actual component instead."
+ );
+ }
+
+ var pathToRegexpOptions = route.pathToRegexpOptions || {};
+ var normalizedPath = normalizePath(
+ path,
+ parent,
+ pathToRegexpOptions.strict
+ );
+
+ if (typeof route.caseSensitive === 'boolean') {
+ pathToRegexpOptions.sensitive = route.caseSensitive;
+ }
+
+ var record = {
+ path: normalizedPath,
+ regex: compileRouteRegex(normalizedPath, pathToRegexpOptions),
+ components: route.components || { default: route.component },
+ instances: {},
+ name: name,
+ parent: parent,
+ matchAs: matchAs,
+ redirect: route.redirect,
+ beforeEnter: route.beforeEnter,
+ meta: route.meta || {},
+ props: route.props == null
+ ? {}
+ : route.components
+ ? route.props
+ : { default: route.props }
+ };
+
+ if (route.children) {
+ // Warn if route is named, does not redirect and has a default child route.
+ // If users navigate to this route by name, the default child will
+ // not be rendered (GH Issue #629)
+ {
+ if (route.name && !route.redirect && route.children.some(function (child) { return /^\/?$/.test(child.path); })) {
+ warn(
+ false,
+ "Named Route '" + (route.name) + "' has a default child route. " +
+ "When navigating to this named route (:to=\"{name: '" + (route.name) + "'\"), " +
+ "the default child route will not be rendered. Remove the name from " +
+ "this route and use the name of the default child route for named " +
+ "links instead."
+ );
+ }
+ }
+ route.children.forEach(function (child) {
+ var childMatchAs = matchAs
+ ? cleanPath((matchAs + "/" + (child.path)))
+ : undefined;
+ addRouteRecord(pathList, pathMap, nameMap, child, record, childMatchAs);
+ });
+ }
+
+ if (route.alias !== undefined) {
+ var aliases = Array.isArray(route.alias)
+ ? route.alias
+ : [route.alias];
+
+ aliases.forEach(function (alias) {
+ var aliasRoute = {
+ path: alias,
+ children: route.children
+ };
+ addRouteRecord(
+ pathList,
+ pathMap,
+ nameMap,
+ aliasRoute,
+ parent,
+ record.path || '/' // matchAs
+ );
+ });
+ }
+
+ if (!pathMap[record.path]) {
+ pathList.push(record.path);
+ pathMap[record.path] = record;
+ }
+
+ if (name) {
+ if (!nameMap[name]) {
+ nameMap[name] = record;
+ } else if ("development" !== 'production' && !matchAs) {
+ warn(
+ false,
+ "Duplicate named routes definition: " +
+ "{ name: \"" + name + "\", path: \"" + (record.path) + "\" }"
+ );
+ }
+ }
+}
+
+function compileRouteRegex (path, pathToRegexpOptions) {
+ var regex = pathToRegexp_1(path, [], pathToRegexpOptions);
+ {
+ var keys = Object.create(null);
+ regex.keys.forEach(function (key) {
+ warn(!keys[key.name], ("Duplicate param keys in route with path: \"" + path + "\""));
+ keys[key.name] = true;
+ });
+ }
+ return regex
+}
+
+function normalizePath (path, parent, strict) {
+ if (!strict) { path = path.replace(/\/$/, ''); }
+ if (path[0] === '/') { return path }
+ if (parent == null) { return path }
+ return cleanPath(((parent.path) + "/" + path))
+}
+
+/* */
+
+
+function normalizeLocation (
+ raw,
+ current,
+ append,
+ router
+) {
+ var next = typeof raw === 'string' ? { path: raw } : raw;
+ // named target
+ if (next.name || next._normalized) {
+ return next
+ }
+
+ // relative params
+ if (!next.path && next.params && current) {
+ next = assign({}, next);
+ next._normalized = true;
+ var params = assign(assign({}, current.params), next.params);
+ if (current.name) {
+ next.name = current.name;
+ next.params = params;
+ } else if (current.matched.length) {
+ var rawPath = current.matched[current.matched.length - 1].path;
+ next.path = fillParams(rawPath, params, ("path " + (current.path)));
+ } else {
+ warn(false, "relative params navigation requires a current route.");
+ }
+ return next
+ }
+
+ var parsedPath = parsePath(next.path || '');
+ var basePath = (current && current.path) || '/';
+ var path = parsedPath.path
+ ? resolvePath(parsedPath.path, basePath, append || next.append)
+ : basePath;
+
+ var query = resolveQuery(
+ parsedPath.query,
+ next.query,
+ router && router.options.parseQuery
+ );
+
+ var hash = next.hash || parsedPath.hash;
+ if (hash && hash.charAt(0) !== '#') {
+ hash = "#" + hash;
+ }
+
+ return {
+ _normalized: true,
+ path: path,
+ query: query,
+ hash: hash
+ }
+}
+
+function assign (a, b) {
+ for (var key in b) {
+ a[key] = b[key];
+ }
+ return a
+}
+
+/* */
+
+
+function createMatcher (
+ routes,
+ router
+) {
+ var ref = createRouteMap(routes);
+ var pathList = ref.pathList;
+ var pathMap = ref.pathMap;
+ var nameMap = ref.nameMap;
+
+ function addRoutes (routes) {
+ createRouteMap(routes, pathList, pathMap, nameMap);
+ }
+
+ function match (
+ raw,
+ currentRoute,
+ redirectedFrom
+ ) {
+ var location = normalizeLocation(raw, currentRoute, false, router);
+ var name = location.name;
+
+ if (name) {
+ var record = nameMap[name];
+ {
+ warn(record, ("Route with name '" + name + "' does not exist"));
+ }
+ if (!record) { return _createRoute(null, location) }
+ var paramNames = record.regex.keys
+ .filter(function (key) { return !key.optional; })
+ .map(function (key) { return key.name; });
+
+ if (typeof location.params !== 'object') {
+ location.params = {};
+ }
+
+ if (currentRoute && typeof currentRoute.params === 'object') {
+ for (var key in currentRoute.params) {
+ if (!(key in location.params) && paramNames.indexOf(key) > -1) {
+ location.params[key] = currentRoute.params[key];
+ }
+ }
+ }
+
+ if (record) {
+ location.path = fillParams(record.path, location.params, ("named route \"" + name + "\""));
+ return _createRoute(record, location, redirectedFrom)
+ }
+ } else if (location.path) {
+ location.params = {};
+ for (var i = 0; i < pathList.length; i++) {
+ var path = pathList[i];
+ var record$1 = pathMap[path];
+ if (matchRoute(record$1.regex, location.path, location.params)) {
+ return _createRoute(record$1, location, redirectedFrom)
+ }
+ }
+ }
+ // no match
+ return _createRoute(null, location)
+ }
+
+ function redirect (
+ record,
+ location
+ ) {
+ var originalRedirect = record.redirect;
+ var redirect = typeof originalRedirect === 'function'
+ ? originalRedirect(createRoute(record, location, null, router))
+ : originalRedirect;
+
+ if (typeof redirect === 'string') {
+ redirect = { path: redirect };
+ }
+
+ if (!redirect || typeof redirect !== 'object') {
+ {
+ warn(
+ false, ("invalid redirect option: " + (JSON.stringify(redirect)))
+ );
+ }
+ return _createRoute(null, location)
+ }
+
+ var re = redirect;
+ var name = re.name;
+ var path = re.path;
+ var query = location.query;
+ var hash = location.hash;
+ var params = location.params;
+ query = re.hasOwnProperty('query') ? re.query : query;
+ hash = re.hasOwnProperty('hash') ? re.hash : hash;
+ params = re.hasOwnProperty('params') ? re.params : params;
+
+ if (name) {
+ // resolved named direct
+ var targetRecord = nameMap[name];
+ {
+ assert(targetRecord, ("redirect failed: named route \"" + name + "\" not found."));
+ }
+ return match({
+ _normalized: true,
+ name: name,
+ query: query,
+ hash: hash,
+ params: params
+ }, undefined, location)
+ } else if (path) {
+ // 1. resolve relative redirect
+ var rawPath = resolveRecordPath(path, record);
+ // 2. resolve params
+ var resolvedPath = fillParams(rawPath, params, ("redirect route with path \"" + rawPath + "\""));
+ // 3. rematch with existing query and hash
+ return match({
+ _normalized: true,
+ path: resolvedPath,
+ query: query,
+ hash: hash
+ }, undefined, location)
+ } else {
+ {
+ warn(false, ("invalid redirect option: " + (JSON.stringify(redirect))));
+ }
+ return _createRoute(null, location)
+ }
+ }
+
+ function alias (
+ record,
+ location,
+ matchAs
+ ) {
+ var aliasedPath = fillParams(matchAs, location.params, ("aliased route with path \"" + matchAs + "\""));
+ var aliasedMatch = match({
+ _normalized: true,
+ path: aliasedPath
+ });
+ if (aliasedMatch) {
+ var matched = aliasedMatch.matched;
+ var aliasedRecord = matched[matched.length - 1];
+ location.params = aliasedMatch.params;
+ return _createRoute(aliasedRecord, location)
+ }
+ return _createRoute(null, location)
+ }
+
+ function _createRoute (
+ record,
+ location,
+ redirectedFrom
+ ) {
+ if (record && record.redirect) {
+ return redirect(record, redirectedFrom || location)
+ }
+ if (record && record.matchAs) {
+ return alias(record, location, record.matchAs)
+ }
+ return createRoute(record, location, redirectedFrom, router)
+ }
+
+ return {
+ match: match,
+ addRoutes: addRoutes
+ }
+}
+
+function matchRoute (
+ regex,
+ path,
+ params
+) {
+ var m = path.match(regex);
+
+ if (!m) {
+ return false
+ } else if (!params) {
+ return true
+ }
+
+ for (var i = 1, len = m.length; i < len; ++i) {
+ var key = regex.keys[i - 1];
+ var val = typeof m[i] === 'string' ? decodeURIComponent(m[i]) : m[i];
+ if (key) {
+ params[key.name] = val;
+ }
+ }
+
+ return true
+}
+
+function resolveRecordPath (path, record) {
+ return resolvePath(path, record.parent ? record.parent.path : '/', true)
+}
+
+/* */
+
+
+var positionStore = Object.create(null);
+
+function setupScroll () {
+ // Fix for #1585 for Firefox
+ window.history.replaceState({ key: getStateKey() }, '');
+ window.addEventListener('popstate', function (e) {
+ saveScrollPosition();
+ if (e.state && e.state.key) {
+ setStateKey(e.state.key);
+ }
+ });
+}
+
+function handleScroll (
+ router,
+ to,
+ from,
+ isPop
+) {
+ if (!router.app) {
+ return
+ }
+
+ var behavior = router.options.scrollBehavior;
+ if (!behavior) {
+ return
+ }
+
+ {
+ assert(typeof behavior === 'function', "scrollBehavior must be a function");
+ }
+
+ // wait until re-render finishes before scrolling
+ router.app.$nextTick(function () {
+ var position = getScrollPosition();
+ var shouldScroll = behavior(to, from, isPop ? position : null);
+
+ if (!shouldScroll) {
+ return
+ }
+
+ if (typeof shouldScroll.then === 'function') {
+ shouldScroll.then(function (shouldScroll) {
+ scrollToPosition((shouldScroll), position);
+ }).catch(function (err) {
+ {
+ assert(false, err.toString());
+ }
+ });
+ } else {
+ scrollToPosition(shouldScroll, position);
+ }
+ });
+}
+
+function saveScrollPosition () {
+ var key = getStateKey();
+ if (key) {
+ positionStore[key] = {
+ x: window.pageXOffset,
+ y: window.pageYOffset
+ };
+ }
+}
+
+function getScrollPosition () {
+ var key = getStateKey();
+ if (key) {
+ return positionStore[key]
+ }
+}
+
+function getElementPosition (el, offset) {
+ var docEl = document.documentElement;
+ var docRect = docEl.getBoundingClientRect();
+ var elRect = el.getBoundingClientRect();
+ return {
+ x: elRect.left - docRect.left - offset.x,
+ y: elRect.top - docRect.top - offset.y
+ }
+}
+
+function isValidPosition (obj) {
+ return isNumber(obj.x) || isNumber(obj.y)
+}
+
+function normalizePosition (obj) {
+ return {
+ x: isNumber(obj.x) ? obj.x : window.pageXOffset,
+ y: isNumber(obj.y) ? obj.y : window.pageYOffset
+ }
+}
+
+function normalizeOffset (obj) {
+ return {
+ x: isNumber(obj.x) ? obj.x : 0,
+ y: isNumber(obj.y) ? obj.y : 0
+ }
+}
+
+function isNumber (v) {
+ return typeof v === 'number'
+}
+
+function scrollToPosition (shouldScroll, position) {
+ var isObject = typeof shouldScroll === 'object';
+ if (isObject && typeof shouldScroll.selector === 'string') {
+ var el = document.querySelector(shouldScroll.selector);
+ if (el) {
+ var offset = shouldScroll.offset && typeof shouldScroll.offset === 'object' ? shouldScroll.offset : {};
+ offset = normalizeOffset(offset);
+ position = getElementPosition(el, offset);
+ } else if (isValidPosition(shouldScroll)) {
+ position = normalizePosition(shouldScroll);
+ }
+ } else if (isObject && isValidPosition(shouldScroll)) {
+ position = normalizePosition(shouldScroll);
+ }
+
+ if (position) {
+ window.scrollTo(position.x, position.y);
+ }
+}
+
+/* */
+
+var supportsPushState = inBrowser && (function () {
+ var ua = window.navigator.userAgent;
+
+ if (
+ (ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) &&
+ ua.indexOf('Mobile Safari') !== -1 &&
+ ua.indexOf('Chrome') === -1 &&
+ ua.indexOf('Windows Phone') === -1
+ ) {
+ return false
+ }
+
+ return window.history && 'pushState' in window.history
+})();
+
+// use User Timing api (if present) for more accurate key precision
+var Time = inBrowser && window.performance && window.performance.now
+ ? window.performance
+ : Date;
+
+var _key = genKey();
+
+function genKey () {
+ return Time.now().toFixed(3)
+}
+
+function getStateKey () {
+ return _key
+}
+
+function setStateKey (key) {
+ _key = key;
+}
+
+function pushState (url, replace) {
+ saveScrollPosition();
+ // try...catch the pushState call to get around Safari
+ // DOM Exception 18 where it limits to 100 pushState calls
+ var history = window.history;
+ try {
+ if (replace) {
+ history.replaceState({ key: _key }, '', url);
+ } else {
+ _key = genKey();
+ history.pushState({ key: _key }, '', url);
+ }
+ } catch (e) {
+ window.location[replace ? 'replace' : 'assign'](url);
+ }
+}
+
+function replaceState (url) {
+ pushState(url, true);
+}
+
+/* */
+
+function runQueue (queue, fn, cb) {
+ var step = function (index) {
+ if (index >= queue.length) {
+ cb();
+ } else {
+ if (queue[index]) {
+ fn(queue[index], function () {
+ step(index + 1);
+ });
+ } else {
+ step(index + 1);
+ }
+ }
+ };
+ step(0);
+}
+
+/* */
+
+function resolveAsyncComponents (matched) {
+ return function (to, from, next) {
+ var hasAsync = false;
+ var pending = 0;
+ var error = null;
+
+ flatMapComponents(matched, function (def, _, match, key) {
+ // if it's a function and doesn't have cid attached,
+ // assume it's an async component resolve function.
+ // we are not using Vue's default async resolving mechanism because
+ // we want to halt the navigation until the incoming component has been
+ // resolved.
+ if (typeof def === 'function' && def.cid === undefined) {
+ hasAsync = true;
+ pending++;
+
+ var resolve = once(function (resolvedDef) {
+ if (isESModule(resolvedDef)) {
+ resolvedDef = resolvedDef.default;
+ }
+ // save resolved on async factory in case it's used elsewhere
+ def.resolved = typeof resolvedDef === 'function'
+ ? resolvedDef
+ : _Vue.extend(resolvedDef);
+ match.components[key] = resolvedDef;
+ pending--;
+ if (pending <= 0) {
+ next();
+ }
+ });
+
+ var reject = once(function (reason) {
+ var msg = "Failed to resolve async component " + key + ": " + reason;
+ "development" !== 'production' && warn(false, msg);
+ if (!error) {
+ error = isError(reason)
+ ? reason
+ : new Error(msg);
+ next(error);
+ }
+ });
+
+ var res;
+ try {
+ res = def(resolve, reject);
+ } catch (e) {
+ reject(e);
+ }
+ if (res) {
+ if (typeof res.then === 'function') {
+ res.then(resolve, reject);
+ } else {
+ // new syntax in Vue 2.3
+ var comp = res.component;
+ if (comp && typeof comp.then === 'function') {
+ comp.then(resolve, reject);
+ }
+ }
+ }
+ }
+ });
+
+ if (!hasAsync) { next(); }
+ }
+}
+
+function flatMapComponents (
+ matched,
+ fn
+) {
+ return flatten(matched.map(function (m) {
+ return Object.keys(m.components).map(function (key) { return fn(
+ m.components[key],
+ m.instances[key],
+ m, key
+ ); })
+ }))
+}
+
+function flatten (arr) {
+ return Array.prototype.concat.apply([], arr)
+}
+
+var hasSymbol =
+ typeof Symbol === 'function' &&
+ typeof Symbol.toStringTag === 'symbol';
+
+function isESModule (obj) {
+ return obj.__esModule || (hasSymbol && obj[Symbol.toStringTag] === 'Module')
+}
+
+// in Webpack 2, require.ensure now also returns a Promise
+// so the resolve/reject functions may get called an extra time
+// if the user uses an arrow function shorthand that happens to
+// return that Promise.
+function once (fn) {
+ var called = false;
+ return function () {
+ var args = [], len = arguments.length;
+ while ( len-- ) args[ len ] = arguments[ len ];
+
+ if (called) { return }
+ called = true;
+ return fn.apply(this, args)
+ }
+}
+
+/* */
+
+var History = function History (router, base) {
+ this.router = router;
+ this.base = normalizeBase(base);
+ // start with a route object that stands for "nowhere"
+ this.current = START;
+ this.pending = null;
+ this.ready = false;
+ this.readyCbs = [];
+ this.readyErrorCbs = [];
+ this.errorCbs = [];
+};
+
+History.prototype.listen = function listen (cb) {
+ this.cb = cb;
+};
+
+History.prototype.onReady = function onReady (cb, errorCb) {
+ if (this.ready) {
+ cb();
+ } else {
+ this.readyCbs.push(cb);
+ if (errorCb) {
+ this.readyErrorCbs.push(errorCb);
+ }
+ }
+};
+
+History.prototype.onError = function onError (errorCb) {
+ this.errorCbs.push(errorCb);
+};
+
+History.prototype.transitionTo = function transitionTo (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ var route = this.router.match(location, this.current);
+ this.confirmTransition(route, function () {
+ this$1.updateRoute(route);
+ onComplete && onComplete(route);
+ this$1.ensureURL();
+
+ // fire ready cbs once
+ if (!this$1.ready) {
+ this$1.ready = true;
+ this$1.readyCbs.forEach(function (cb) { cb(route); });
+ }
+ }, function (err) {
+ if (onAbort) {
+ onAbort(err);
+ }
+ if (err && !this$1.ready) {
+ this$1.ready = true;
+ this$1.readyErrorCbs.forEach(function (cb) { cb(err); });
+ }
+ });
+};
+
+History.prototype.confirmTransition = function confirmTransition (route, onComplete, onAbort) {
+ var this$1 = this;
+
+ var current = this.current;
+ var abort = function (err) {
+ if (isError(err)) {
+ if (this$1.errorCbs.length) {
+ this$1.errorCbs.forEach(function (cb) { cb(err); });
+ } else {
+ warn(false, 'uncaught error during route navigation:');
+ console.error(err);
+ }
+ }
+ onAbort && onAbort(err);
+ };
+ if (
+ isSameRoute(route, current) &&
+ // in the case the route map has been dynamically appended to
+ route.matched.length === current.matched.length
+ ) {
+ this.ensureURL();
+ return abort()
+ }
+
+ var ref = resolveQueue(this.current.matched, route.matched);
+ var updated = ref.updated;
+ var deactivated = ref.deactivated;
+ var activated = ref.activated;
+
+ var queue = [].concat(
+ // in-component leave guards
+ extractLeaveGuards(deactivated),
+ // global before hooks
+ this.router.beforeHooks,
+ // in-component update hooks
+ extractUpdateHooks(updated),
+ // in-config enter guards
+ activated.map(function (m) { return m.beforeEnter; }),
+ // async components
+ resolveAsyncComponents(activated)
+ );
+
+ this.pending = route;
+ var iterator = function (hook, next) {
+ if (this$1.pending !== route) {
+ return abort()
+ }
+ try {
+ hook(route, current, function (to) {
+ if (to === false || isError(to)) {
+ // next(false) -> abort navigation, ensure current URL
+ this$1.ensureURL(true);
+ abort(to);
+ } else if (
+ typeof to === 'string' ||
+ (typeof to === 'object' && (
+ typeof to.path === 'string' ||
+ typeof to.name === 'string'
+ ))
+ ) {
+ // next('/') or next({ path: '/' }) -> redirect
+ abort();
+ if (typeof to === 'object' && to.replace) {
+ this$1.replace(to);
+ } else {
+ this$1.push(to);
+ }
+ } else {
+ // confirm transition and pass on the value
+ next(to);
+ }
+ });
+ } catch (e) {
+ abort(e);
+ }
+ };
+
+ runQueue(queue, iterator, function () {
+ var postEnterCbs = [];
+ var isValid = function () { return this$1.current === route; };
+ // wait until async components are resolved before
+ // extracting in-component enter guards
+ var enterGuards = extractEnterGuards(activated, postEnterCbs, isValid);
+ var queue = enterGuards.concat(this$1.router.resolveHooks);
+ runQueue(queue, iterator, function () {
+ if (this$1.pending !== route) {
+ return abort()
+ }
+ this$1.pending = null;
+ onComplete(route);
+ if (this$1.router.app) {
+ this$1.router.app.$nextTick(function () {
+ postEnterCbs.forEach(function (cb) { cb(); });
+ });
+ }
+ });
+ });
+};
+
+History.prototype.updateRoute = function updateRoute (route) {
+ var prev = this.current;
+ this.current = route;
+ this.cb && this.cb(route);
+ this.router.afterHooks.forEach(function (hook) {
+ hook && hook(route, prev);
+ });
+};
+
+function normalizeBase (base) {
+ if (!base) {
+ if (inBrowser) {
+ // respect tag
+ var baseEl = document.querySelector('base');
+ base = (baseEl && baseEl.getAttribute('href')) || '/';
+ // strip full URL origin
+ base = base.replace(/^https?:\/\/[^\/]+/, '');
+ } else {
+ base = '/';
+ }
+ }
+ // make sure there's the starting slash
+ if (base.charAt(0) !== '/') {
+ base = '/' + base;
+ }
+ // remove trailing slash
+ return base.replace(/\/$/, '')
+}
+
+function resolveQueue (
+ current,
+ next
+) {
+ var i;
+ var max = Math.max(current.length, next.length);
+ for (i = 0; i < max; i++) {
+ if (current[i] !== next[i]) {
+ break
+ }
+ }
+ return {
+ updated: next.slice(0, i),
+ activated: next.slice(i),
+ deactivated: current.slice(i)
+ }
+}
+
+function extractGuards (
+ records,
+ name,
+ bind,
+ reverse
+) {
+ var guards = flatMapComponents(records, function (def, instance, match, key) {
+ var guard = extractGuard(def, name);
+ if (guard) {
+ return Array.isArray(guard)
+ ? guard.map(function (guard) { return bind(guard, instance, match, key); })
+ : bind(guard, instance, match, key)
+ }
+ });
+ return flatten(reverse ? guards.reverse() : guards)
+}
+
+function extractGuard (
+ def,
+ key
+) {
+ if (typeof def !== 'function') {
+ // extend now so that global mixins are applied.
+ def = _Vue.extend(def);
+ }
+ return def.options[key]
+}
+
+function extractLeaveGuards (deactivated) {
+ return extractGuards(deactivated, 'beforeRouteLeave', bindGuard, true)
+}
+
+function extractUpdateHooks (updated) {
+ return extractGuards(updated, 'beforeRouteUpdate', bindGuard)
+}
+
+function bindGuard (guard, instance) {
+ if (instance) {
+ return function boundRouteGuard () {
+ return guard.apply(instance, arguments)
+ }
+ }
+}
+
+function extractEnterGuards (
+ activated,
+ cbs,
+ isValid
+) {
+ return extractGuards(activated, 'beforeRouteEnter', function (guard, _, match, key) {
+ return bindEnterGuard(guard, match, key, cbs, isValid)
+ })
+}
+
+function bindEnterGuard (
+ guard,
+ match,
+ key,
+ cbs,
+ isValid
+) {
+ return function routeEnterGuard (to, from, next) {
+ return guard(to, from, function (cb) {
+ next(cb);
+ if (typeof cb === 'function') {
+ cbs.push(function () {
+ // #750
+ // if a router-view is wrapped with an out-in transition,
+ // the instance may not have been registered at this time.
+ // we will need to poll for registration until current route
+ // is no longer valid.
+ poll(cb, match.instances, key, isValid);
+ });
+ }
+ })
+ }
+}
+
+function poll (
+ cb, // somehow flow cannot infer this is a function
+ instances,
+ key,
+ isValid
+) {
+ if (instances[key]) {
+ cb(instances[key]);
+ } else if (isValid()) {
+ setTimeout(function () {
+ poll(cb, instances, key, isValid);
+ }, 16);
+ }
+}
+
+/* */
+
+
+var HTML5History = (function (History$$1) {
+ function HTML5History (router, base) {
+ var this$1 = this;
+
+ History$$1.call(this, router, base);
+
+ var expectScroll = router.options.scrollBehavior;
+
+ if (expectScroll) {
+ setupScroll();
+ }
+
+ var initLocation = getLocation(this.base);
+ window.addEventListener('popstate', function (e) {
+ var current = this$1.current;
+
+ // Avoiding first `popstate` event dispatched in some browsers but first
+ // history route not updated since async guard at the same time.
+ var location = getLocation(this$1.base);
+ if (this$1.current === START && location === initLocation) {
+ return
+ }
+
+ this$1.transitionTo(location, function (route) {
+ if (expectScroll) {
+ handleScroll(router, route, current, true);
+ }
+ });
+ });
+ }
+
+ if ( History$$1 ) HTML5History.__proto__ = History$$1;
+ HTML5History.prototype = Object.create( History$$1 && History$$1.prototype );
+ HTML5History.prototype.constructor = HTML5History;
+
+ HTML5History.prototype.go = function go (n) {
+ window.history.go(n);
+ };
+
+ HTML5History.prototype.push = function push (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ var ref = this;
+ var fromRoute = ref.current;
+ this.transitionTo(location, function (route) {
+ pushState(cleanPath(this$1.base + route.fullPath));
+ handleScroll(this$1.router, route, fromRoute, false);
+ onComplete && onComplete(route);
+ }, onAbort);
+ };
+
+ HTML5History.prototype.replace = function replace (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ var ref = this;
+ var fromRoute = ref.current;
+ this.transitionTo(location, function (route) {
+ replaceState(cleanPath(this$1.base + route.fullPath));
+ handleScroll(this$1.router, route, fromRoute, false);
+ onComplete && onComplete(route);
+ }, onAbort);
+ };
+
+ HTML5History.prototype.ensureURL = function ensureURL (push) {
+ if (getLocation(this.base) !== this.current.fullPath) {
+ var current = cleanPath(this.base + this.current.fullPath);
+ push ? pushState(current) : replaceState(current);
+ }
+ };
+
+ HTML5History.prototype.getCurrentLocation = function getCurrentLocation () {
+ return getLocation(this.base)
+ };
+
+ return HTML5History;
+}(History));
+
+function getLocation (base) {
+ var path = window.location.pathname;
+ if (base && path.indexOf(base) === 0) {
+ path = path.slice(base.length);
+ }
+ return (path || '/') + window.location.search + window.location.hash
+}
+
+/* */
+
+
+var HashHistory = (function (History$$1) {
+ function HashHistory (router, base, fallback) {
+ History$$1.call(this, router, base);
+ // check history fallback deeplinking
+ if (fallback && checkFallback(this.base)) {
+ return
+ }
+ ensureSlash();
+ }
+
+ if ( History$$1 ) HashHistory.__proto__ = History$$1;
+ HashHistory.prototype = Object.create( History$$1 && History$$1.prototype );
+ HashHistory.prototype.constructor = HashHistory;
+
+ // this is delayed until the app mounts
+ // to avoid the hashchange listener being fired too early
+ HashHistory.prototype.setupListeners = function setupListeners () {
+ var this$1 = this;
+
+ var router = this.router;
+ var expectScroll = router.options.scrollBehavior;
+ var supportsScroll = supportsPushState && expectScroll;
+
+ if (supportsScroll) {
+ setupScroll();
+ }
+
+ window.addEventListener(supportsPushState ? 'popstate' : 'hashchange', function () {
+ var current = this$1.current;
+ if (!ensureSlash()) {
+ return
+ }
+ this$1.transitionTo(getHash(), function (route) {
+ if (supportsScroll) {
+ handleScroll(this$1.router, route, current, true);
+ }
+ if (!supportsPushState) {
+ replaceHash(route.fullPath);
+ }
+ });
+ });
+ };
+
+ HashHistory.prototype.push = function push (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ var ref = this;
+ var fromRoute = ref.current;
+ this.transitionTo(location, function (route) {
+ pushHash(route.fullPath);
+ handleScroll(this$1.router, route, fromRoute, false);
+ onComplete && onComplete(route);
+ }, onAbort);
+ };
+
+ HashHistory.prototype.replace = function replace (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ var ref = this;
+ var fromRoute = ref.current;
+ this.transitionTo(location, function (route) {
+ replaceHash(route.fullPath);
+ handleScroll(this$1.router, route, fromRoute, false);
+ onComplete && onComplete(route);
+ }, onAbort);
+ };
+
+ HashHistory.prototype.go = function go (n) {
+ window.history.go(n);
+ };
+
+ HashHistory.prototype.ensureURL = function ensureURL (push) {
+ var current = this.current.fullPath;
+ if (getHash() !== current) {
+ push ? pushHash(current) : replaceHash(current);
+ }
+ };
+
+ HashHistory.prototype.getCurrentLocation = function getCurrentLocation () {
+ return getHash()
+ };
+
+ return HashHistory;
+}(History));
+
+function checkFallback (base) {
+ var location = getLocation(base);
+ if (!/^\/#/.test(location)) {
+ window.location.replace(
+ cleanPath(base + '/#' + location)
+ );
+ return true
+ }
+}
+
+function ensureSlash () {
+ var path = getHash();
+ if (path.charAt(0) === '/') {
+ return true
+ }
+ replaceHash('/' + path);
+ return false
+}
+
+function getHash () {
+ // We can't use window.location.hash here because it's not
+ // consistent across browsers - Firefox will pre-decode it!
+ var href = window.location.href;
+ var index = href.indexOf('#');
+ return index === -1 ? '' : href.slice(index + 1)
+}
+
+function getUrl (path) {
+ var href = window.location.href;
+ var i = href.indexOf('#');
+ var base = i >= 0 ? href.slice(0, i) : href;
+ return (base + "#" + path)
+}
+
+function pushHash (path) {
+ if (supportsPushState) {
+ pushState(getUrl(path));
+ } else {
+ window.location.hash = path;
+ }
+}
+
+function replaceHash (path) {
+ if (supportsPushState) {
+ replaceState(getUrl(path));
+ } else {
+ window.location.replace(getUrl(path));
+ }
+}
+
+/* */
+
+
+var AbstractHistory = (function (History$$1) {
+ function AbstractHistory (router, base) {
+ History$$1.call(this, router, base);
+ this.stack = [];
+ this.index = -1;
+ }
+
+ if ( History$$1 ) AbstractHistory.__proto__ = History$$1;
+ AbstractHistory.prototype = Object.create( History$$1 && History$$1.prototype );
+ AbstractHistory.prototype.constructor = AbstractHistory;
+
+ AbstractHistory.prototype.push = function push (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ this.transitionTo(location, function (route) {
+ this$1.stack = this$1.stack.slice(0, this$1.index + 1).concat(route);
+ this$1.index++;
+ onComplete && onComplete(route);
+ }, onAbort);
+ };
+
+ AbstractHistory.prototype.replace = function replace (location, onComplete, onAbort) {
+ var this$1 = this;
+
+ this.transitionTo(location, function (route) {
+ this$1.stack = this$1.stack.slice(0, this$1.index).concat(route);
+ onComplete && onComplete(route);
+ }, onAbort);
+ };
+
+ AbstractHistory.prototype.go = function go (n) {
+ var this$1 = this;
+
+ var targetIndex = this.index + n;
+ if (targetIndex < 0 || targetIndex >= this.stack.length) {
+ return
+ }
+ var route = this.stack[targetIndex];
+ this.confirmTransition(route, function () {
+ this$1.index = targetIndex;
+ this$1.updateRoute(route);
+ });
+ };
+
+ AbstractHistory.prototype.getCurrentLocation = function getCurrentLocation () {
+ var current = this.stack[this.stack.length - 1];
+ return current ? current.fullPath : '/'
+ };
+
+ AbstractHistory.prototype.ensureURL = function ensureURL () {
+ // noop
+ };
+
+ return AbstractHistory;
+}(History));
+
+/* */
+
+var VueRouter = function VueRouter (options) {
+ if ( options === void 0 ) options = {};
+
+ this.app = null;
+ this.apps = [];
+ this.options = options;
+ this.beforeHooks = [];
+ this.resolveHooks = [];
+ this.afterHooks = [];
+ this.matcher = createMatcher(options.routes || [], this);
+
+ var mode = options.mode || 'hash';
+ this.fallback = mode === 'history' && !supportsPushState && options.fallback !== false;
+ if (this.fallback) {
+ mode = 'hash';
+ }
+ if (!inBrowser) {
+ mode = 'abstract';
+ }
+ this.mode = mode;
+
+ switch (mode) {
+ case 'history':
+ this.history = new HTML5History(this, options.base);
+ break
+ case 'hash':
+ this.history = new HashHistory(this, options.base, this.fallback);
+ break
+ case 'abstract':
+ this.history = new AbstractHistory(this, options.base);
+ break
+ default:
+ {
+ assert(false, ("invalid mode: " + mode));
+ }
+ }
+};
+
+var prototypeAccessors = { currentRoute: { configurable: true } };
+
+VueRouter.prototype.match = function match (
+ raw,
+ current,
+ redirectedFrom
+) {
+ return this.matcher.match(raw, current, redirectedFrom)
+};
+
+prototypeAccessors.currentRoute.get = function () {
+ return this.history && this.history.current
+};
+
+VueRouter.prototype.init = function init (app /* Vue component instance */) {
+ var this$1 = this;
+
+ "development" !== 'production' && assert(
+ install.installed,
+ "not installed. Make sure to call `Vue.use(VueRouter)` " +
+ "before creating root instance."
+ );
+
+ this.apps.push(app);
+
+ // main app already initialized.
+ if (this.app) {
+ return
+ }
+
+ this.app = app;
+
+ var history = this.history;
+
+ if (history instanceof HTML5History) {
+ history.transitionTo(history.getCurrentLocation());
+ } else if (history instanceof HashHistory) {
+ var setupHashListener = function () {
+ history.setupListeners();
+ };
+ history.transitionTo(
+ history.getCurrentLocation(),
+ setupHashListener,
+ setupHashListener
+ );
+ }
+
+ history.listen(function (route) {
+ this$1.apps.forEach(function (app) {
+ app._route = route;
+ });
+ });
+};
+
+VueRouter.prototype.beforeEach = function beforeEach (fn) {
+ return registerHook(this.beforeHooks, fn)
+};
+
+VueRouter.prototype.beforeResolve = function beforeResolve (fn) {
+ return registerHook(this.resolveHooks, fn)
+};
+
+VueRouter.prototype.afterEach = function afterEach (fn) {
+ return registerHook(this.afterHooks, fn)
+};
+
+VueRouter.prototype.onReady = function onReady (cb, errorCb) {
+ this.history.onReady(cb, errorCb);
+};
+
+VueRouter.prototype.onError = function onError (errorCb) {
+ this.history.onError(errorCb);
+};
+
+VueRouter.prototype.push = function push (location, onComplete, onAbort) {
+ this.history.push(location, onComplete, onAbort);
+};
+
+VueRouter.prototype.replace = function replace (location, onComplete, onAbort) {
+ this.history.replace(location, onComplete, onAbort);
+};
+
+VueRouter.prototype.go = function go (n) {
+ this.history.go(n);
+};
+
+VueRouter.prototype.back = function back () {
+ this.go(-1);
+};
+
+VueRouter.prototype.forward = function forward () {
+ this.go(1);
+};
+
+VueRouter.prototype.getMatchedComponents = function getMatchedComponents (to) {
+ var route = to
+ ? to.matched
+ ? to
+ : this.resolve(to).route
+ : this.currentRoute;
+ if (!route) {
+ return []
+ }
+ return [].concat.apply([], route.matched.map(function (m) {
+ return Object.keys(m.components).map(function (key) {
+ return m.components[key]
+ })
+ }))
+};
+
+VueRouter.prototype.resolve = function resolve (
+ to,
+ current,
+ append
+) {
+ var location = normalizeLocation(
+ to,
+ current || this.history.current,
+ append,
+ this
+ );
+ var route = this.match(location, current);
+ var fullPath = route.redirectedFrom || route.fullPath;
+ var base = this.history.base;
+ var href = createHref(base, fullPath, this.mode);
+ return {
+ location: location,
+ route: route,
+ href: href,
+ // for backwards compat
+ normalizedTo: location,
+ resolved: route
+ }
+};
+
+VueRouter.prototype.addRoutes = function addRoutes (routes) {
+ this.matcher.addRoutes(routes);
+ if (this.history.current !== START) {
+ this.history.transitionTo(this.history.getCurrentLocation());
+ }
+};
+
+Object.defineProperties( VueRouter.prototype, prototypeAccessors );
+
+function registerHook (list, fn) {
+ list.push(fn);
+ return function () {
+ var i = list.indexOf(fn);
+ if (i > -1) { list.splice(i, 1); }
+ }
+}
+
+function createHref (base, fullPath, mode) {
+ var path = mode === 'hash' ? '#' + fullPath : fullPath;
+ return base ? cleanPath(base + '/' + path) : path
+}
+
+VueRouter.install = install;
+VueRouter.version = '3.0.1';
+
+if (inBrowser && window.Vue) {
+ window.Vue.use(VueRouter);
+}
+
+return VueRouter;
+
+})));
diff --git a/dist/www/lib/vue-router.min.js b/dist/www/lib/vue-router.min.js
new file mode 100644
index 0000000..867a978
--- /dev/null
+++ b/dist/www/lib/vue-router.min.js
@@ -0,0 +1,6 @@
+/**
+ * vue-router v3.0.1
+ * (c) 2017 Evan You
+ * @license MIT
+ */
+!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.VueRouter=e()}(this,function(){"use strict";function t(t,e){}function e(t){return Object.prototype.toString.call(t).indexOf("Error")>-1}function r(t,e){switch(typeof e){case"undefined":return;case"object":return e;case"function":return e(t);case"boolean":return e?t.params:void 0}}function n(t,e){for(var r in e)t[r]=e[r];return t}function o(t,e,r){void 0===e&&(e={});var n,o=r||i;try{n=o(t||"")}catch(t){n={}}for(var a in e)n[a]=e[a];return n}function i(t){var e={};return(t=t.trim().replace(/^(\?|#|&)/,""))?(t.split("&").forEach(function(t){var r=t.replace(/\+/g," ").split("="),n=Ut(r.shift()),o=r.length>0?Ut(r.join("=")):null;void 0===e[n]?e[n]=o:Array.isArray(e[n])?e[n].push(o):e[n]=[e[n],o]}),e):e}function a(t){var e=t?Object.keys(t).map(function(e){var r=t[e];if(void 0===r)return"";if(null===r)return Pt(e);if(Array.isArray(r)){var n=[];return r.forEach(function(t){void 0!==t&&(null===t?n.push(Pt(e)):n.push(Pt(e)+"="+Pt(t)))}),n.join("&")}return Pt(e)+"="+Pt(r)}).filter(function(t){return t.length>0}).join("&"):null;return e?"?"+e:""}function u(t,e,r,n){var o=n&&n.options.stringifyQuery,i=e.query||{};try{i=c(i)}catch(t){}var a={name:e.name||t&&t.name,meta:t&&t.meta||{},path:e.path||"/",hash:e.hash||"",query:i,params:e.params||{},fullPath:p(e,o),matched:t?s(t):[]};return r&&(a.redirectedFrom=p(r,o)),Object.freeze(a)}function c(t){if(Array.isArray(t))return t.map(c);if(t&&"object"==typeof t){var e={};for(var r in t)e[r]=c(t[r]);return e}return t}function s(t){for(var e=[];t;)e.unshift(t),t=t.parent;return e}function p(t,e){var r=t.path,n=t.query;void 0===n&&(n={});var o=t.hash;void 0===o&&(o="");var i=e||a;return(r||"/")+i(n)+o}function f(t,e){return e===Ht?t===e:!!e&&(t.path&&e.path?t.path.replace(Mt,"")===e.path.replace(Mt,"")&&t.hash===e.hash&&h(t.query,e.query):!(!t.name||!e.name)&&(t.name===e.name&&t.hash===e.hash&&h(t.query,e.query)&&h(t.params,e.params)))}function h(t,e){if(void 0===t&&(t={}),void 0===e&&(e={}),!t||!e)return t===e;var r=Object.keys(t),n=Object.keys(e);return r.length===n.length&&r.every(function(r){var n=t[r],o=e[r];return"object"==typeof n&&"object"==typeof o?h(n,o):String(n)===String(o)})}function l(t,e){return 0===t.path.replace(Mt,"/").indexOf(e.path.replace(Mt,"/"))&&(!e.hash||t.hash===e.hash)&&d(t.query,e.query)}function d(t,e){for(var r in e)if(!(r in t))return!1;return!0}function y(t){if(!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey||t.defaultPrevented||void 0!==t.button&&0!==t.button)){if(t.currentTarget&&t.currentTarget.getAttribute){var e=t.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(e))return}return t.preventDefault&&t.preventDefault(),!0}}function v(t){if(t)for(var e,r=0;r=0&&(e=t.slice(n),t=t.slice(0,n));var o=t.indexOf("?");return o>=0&&(r=t.slice(o+1),t=t.slice(0,o)),{path:t,query:r,hash:e}}function w(t){return t.replace(/\/\//g,"/")}function x(t,e){for(var r,n=[],o=0,i=0,a="",u=e&&e.delimiter||"/";null!=(r=Qt.exec(t));){var c=r[0],s=r[1],p=r.index;if(a+=t.slice(i,p),i=p+c.length,s)a+=s[1];else{var f=t[i],h=r[2],l=r[3],d=r[4],y=r[5],v=r[6],m=r[7];a&&(n.push(a),a="");var g=null!=h&&null!=f&&f!==h,b="+"===v||"*"===v,w="?"===v||"*"===v,x=r[2]||u,k=d||y;n.push({name:l||o++,prefix:h||"",delimiter:x,optional:w,repeat:b,partial:g,asterisk:!!m,pattern:k?C(k):m?".*":"[^"+O(x)+"]+?"})}}return i-1&&(o.params[h]=r.params[h]);if(u)return o.path=L(u.path,o.params,'named route "'+a+'"'),i(u,o,n)}else if(o.path){o.params={};for(var l=0;l=t.length?r():t[o]?e(t[o],function(){n(o+1)}):n(o+1)};n(0)}function at(t){return function(r,n,o){var i=!1,a=0,u=null;ut(t,function(t,r,n,c){if("function"==typeof t&&void 0===t.cid){i=!0,a++;var s,p=pt(function(e){st(e)&&(e=e.default),t.resolved="function"==typeof e?e:Tt.extend(e),n.components[c]=e,--a<=0&&o()}),f=pt(function(t){var r="Failed to resolve async component "+c+": "+t;u||(u=e(t)?t:new Error(r),o(u))});try{s=t(p,f)}catch(t){f(t)}if(s)if("function"==typeof s.then)s.then(p,f);else{var h=s.component;h&&"function"==typeof h.then&&h.then(p,f)}}}),i||o()}}function ut(t,e){return ct(t.map(function(t){return Object.keys(t.components).map(function(r){return e(t.components[r],t.instances[r],t,r)})}))}function ct(t){return Array.prototype.concat.apply([],t)}function st(t){return t.__esModule||te&&"Module"===t[Symbol.toStringTag]}function pt(t){var e=!1;return function(){for(var r=[],n=arguments.length;n--;)r[n]=arguments[n];if(!e)return e=!0,t.apply(this,r)}}function ft(t){if(!t)if(Bt){var e=document.querySelector("base");t=(t=e&&e.getAttribute("href")||"/").replace(/^https?:\/\/[^\/]+/,"")}else t="/";return"/"!==t.charAt(0)&&(t="/"+t),t.replace(/\/$/,"")}function ht(t,e){var r,n=Math.max(t.length,e.length);for(r=0;r=0?e.slice(0,r):e)+"#"+t}function Ct(t){Wt?nt(Ot(t)):window.location.hash=t}function jt(t){Wt?ot(Ot(t)):window.location.replace(Ot(t))}function At(t,e){return t.push(e),function(){var r=t.indexOf(e);r>-1&&t.splice(r,1)}}function _t(t,e,r){var n="hash"===r?"#"+e:e;return t?w(t+"/"+n):n}var Tt,St={name:"router-view",functional:!0,props:{name:{type:String,default:"default"}},render:function(t,e){var o=e.props,i=e.children,a=e.parent,u=e.data;u.routerView=!0;for(var c=a.$createElement,s=o.name,p=a.$route,f=a._routerViewCache||(a._routerViewCache={}),h=0,l=!1;a&&a._routerRoot!==a;)a.$vnode&&a.$vnode.data.routerView&&h++,a._inactive&&(l=!0),a=a.$parent;if(u.routerViewDepth=h,l)return c(f[s],u,i);var d=p.matched[h];if(!d)return f[s]=null,c();var y=f[s]=d.components[s];u.registerRouteInstance=function(t,e){var r=d.instances[s];(e&&r!==t||!e&&r===t)&&(d.instances[s]=e)},(u.hook||(u.hook={})).prepatch=function(t,e){d.instances[s]=e.componentInstance};var v=u.props=r(p,d.props&&d.props[s]);if(v){v=u.props=n({},v);var m=u.attrs=u.attrs||{};for(var g in v)y.props&&g in y.props||(m[g]=v[g],delete v[g])}return c(y,u,i)}},$t=/[!'()*]/g,qt=function(t){return"%"+t.charCodeAt(0).toString(16)},Lt=/%2C/g,Pt=function(t){return encodeURIComponent(t).replace($t,qt).replace(Lt,",")},Ut=decodeURIComponent,Mt=/\/?$/,Ht=u(null,{path:"/"}),It=[String,Object],Vt=[String,Array],zt={name:"router-link",props:{to:{type:It,required:!0},tag:{type:String,default:"a"},exact:Boolean,append:Boolean,replace:Boolean,activeClass:String,exactActiveClass:String,event:{type:Vt,default:"click"}},render:function(t){var e=this,r=this.$router,n=this.$route,o=r.resolve(this.to,n,this.append),i=o.location,a=o.route,c=o.href,s={},p=r.options.linkActiveClass,h=r.options.linkExactActiveClass,d=null==p?"router-link-active":p,m=null==h?"router-link-exact-active":h,g=null==this.activeClass?d:this.activeClass,b=null==this.exactActiveClass?m:this.exactActiveClass,w=i.path?u(null,i,null,r):a;s[b]=f(n,w),s[g]=this.exact?s[b]:l(n,w);var x=function(t){y(t)&&(e.replace?r.replace(i):r.push(i))},k={click:y};Array.isArray(this.event)?this.event.forEach(function(t){k[t]=x}):k[this.event]=x;var R={class:s};if("a"===this.tag)R.on=k,R.attrs={href:c};else{var E=v(this.$slots.default);if(E){E.isStatic=!1;var O=Tt.util.extend;(E.data=O({},E.data)).on=k,(E.data.attrs=O({},E.data.attrs)).href=c}else R.on=k}return t(this.tag,R,this.$slots.default)}},Bt="undefined"!=typeof window,Ft=Array.isArray||function(t){return"[object Array]"==Object.prototype.toString.call(t)},Dt=q,Kt=x,Jt=E,Nt=$,Qt=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");Dt.parse=Kt,Dt.compile=function(t,e){return E(x(t,e))},Dt.tokensToFunction=Jt,Dt.tokensToRegExp=Nt;var Xt=Object.create(null),Yt=Object.create(null),Wt=Bt&&function(){var t=window.navigator.userAgent;return(-1===t.indexOf("Android 2.")&&-1===t.indexOf("Android 4.0")||-1===t.indexOf("Mobile Safari")||-1!==t.indexOf("Chrome")||-1!==t.indexOf("Windows Phone"))&&(window.history&&"pushState"in window.history)}(),Gt=Bt&&window.performance&&window.performance.now?window.performance:Date,Zt=tt(),te="function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag,ee=function(t,e){this.router=t,this.base=ft(e),this.current=Ht,this.pending=null,this.ready=!1,this.readyCbs=[],this.readyErrorCbs=[],this.errorCbs=[]};ee.prototype.listen=function(t){this.cb=t},ee.prototype.onReady=function(t,e){this.ready?t():(this.readyCbs.push(t),e&&this.readyErrorCbs.push(e))},ee.prototype.onError=function(t){this.errorCbs.push(t)},ee.prototype.transitionTo=function(t,e,r){var n=this,o=this.router.match(t,this.current);this.confirmTransition(o,function(){n.updateRoute(o),e&&e(o),n.ensureURL(),n.ready||(n.ready=!0,n.readyCbs.forEach(function(t){t(o)}))},function(t){r&&r(t),t&&!n.ready&&(n.ready=!0,n.readyErrorCbs.forEach(function(e){e(t)}))})},ee.prototype.confirmTransition=function(r,n,o){var i=this,a=this.current,u=function(r){e(r)&&(i.errorCbs.length?i.errorCbs.forEach(function(t){t(r)}):(t(!1,"uncaught error during route navigation:"),console.error(r))),o&&o(r)};if(f(r,a)&&r.matched.length===a.matched.length)return this.ensureURL(),u();var c=ht(this.current.matched,r.matched),s=c.updated,p=c.deactivated,h=c.activated,l=[].concat(yt(p),this.router.beforeHooks,vt(s),h.map(function(t){return t.beforeEnter}),at(h));this.pending=r;var d=function(t,n){if(i.pending!==r)return u();try{t(r,a,function(t){!1===t||e(t)?(i.ensureURL(!0),u(t)):"string"==typeof t||"object"==typeof t&&("string"==typeof t.path||"string"==typeof t.name)?(u(),"object"==typeof t&&t.replace?i.replace(t):i.push(t)):n(t)})}catch(t){u(t)}};it(l,d,function(){var t=[];it(gt(h,t,function(){return i.current===r}).concat(i.router.resolveHooks),d,function(){if(i.pending!==r)return u();i.pending=null,n(r),i.router.app&&i.router.app.$nextTick(function(){t.forEach(function(t){t()})})})})},ee.prototype.updateRoute=function(t){var e=this.current;this.current=t,this.cb&&this.cb(t),this.router.afterHooks.forEach(function(r){r&&r(t,e)})};var re=function(t){function e(e,r){var n=this;t.call(this,e,r);var o=e.options.scrollBehavior;o&&D();var i=xt(this.base);window.addEventListener("popstate",function(t){var r=n.current,a=xt(n.base);n.current===Ht&&a===i||n.transitionTo(a,function(t){o&&K(e,t,r,!0)})})}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.go=function(t){window.history.go(t)},e.prototype.push=function(t,e,r){var n=this,o=this.current;this.transitionTo(t,function(t){nt(w(n.base+t.fullPath)),K(n.router,t,o,!1),e&&e(t)},r)},e.prototype.replace=function(t,e,r){var n=this,o=this.current;this.transitionTo(t,function(t){ot(w(n.base+t.fullPath)),K(n.router,t,o,!1),e&&e(t)},r)},e.prototype.ensureURL=function(t){if(xt(this.base)!==this.current.fullPath){var e=w(this.base+this.current.fullPath);t?nt(e):ot(e)}},e.prototype.getCurrentLocation=function(){return xt(this.base)},e}(ee),ne=function(t){function e(e,r,n){t.call(this,e,r),n&&kt(this.base)||Rt()}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.setupListeners=function(){var t=this,e=this.router.options.scrollBehavior,r=Wt&&e;r&&D(),window.addEventListener(Wt?"popstate":"hashchange",function(){var e=t.current;Rt()&&t.transitionTo(Et(),function(n){r&&K(t.router,n,e,!0),Wt||jt(n.fullPath)})})},e.prototype.push=function(t,e,r){var n=this,o=this.current;this.transitionTo(t,function(t){Ct(t.fullPath),K(n.router,t,o,!1),e&&e(t)},r)},e.prototype.replace=function(t,e,r){var n=this,o=this.current;this.transitionTo(t,function(t){jt(t.fullPath),K(n.router,t,o,!1),e&&e(t)},r)},e.prototype.go=function(t){window.history.go(t)},e.prototype.ensureURL=function(t){var e=this.current.fullPath;Et()!==e&&(t?Ct(e):jt(e))},e.prototype.getCurrentLocation=function(){return Et()},e}(ee),oe=function(t){function e(e,r){t.call(this,e,r),this.stack=[],this.index=-1}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.push=function(t,e,r){var n=this;this.transitionTo(t,function(t){n.stack=n.stack.slice(0,n.index+1).concat(t),n.index++,e&&e(t)},r)},e.prototype.replace=function(t,e,r){var n=this;this.transitionTo(t,function(t){n.stack=n.stack.slice(0,n.index).concat(t),e&&e(t)},r)},e.prototype.go=function(t){var e=this,r=this.index+t;if(!(r<0||r>=this.stack.length)){var n=this.stack[r];this.confirmTransition(n,function(){e.index=r,e.updateRoute(n)})}},e.prototype.getCurrentLocation=function(){var t=this.stack[this.stack.length-1];return t?t.fullPath:"/"},e.prototype.ensureURL=function(){},e}(ee),ie=function(t){void 0===t&&(t={}),this.app=null,this.apps=[],this.options=t,this.beforeHooks=[],this.resolveHooks=[],this.afterHooks=[],this.matcher=z(t.routes||[],this);var e=t.mode||"hash";switch(this.fallback="history"===e&&!Wt&&!1!==t.fallback,this.fallback&&(e="hash"),Bt||(e="abstract"),this.mode=e,e){case"history":this.history=new re(this,t.base);break;case"hash":this.history=new ne(this,t.base,this.fallback);break;case"abstract":this.history=new oe(this,t.base)}},ae={currentRoute:{configurable:!0}};return ie.prototype.match=function(t,e,r){return this.matcher.match(t,e,r)},ae.currentRoute.get=function(){return this.history&&this.history.current},ie.prototype.init=function(t){var e=this;if(this.apps.push(t),!this.app){this.app=t;var r=this.history;if(r instanceof re)r.transitionTo(r.getCurrentLocation());else if(r instanceof ne){var n=function(){r.setupListeners()};r.transitionTo(r.getCurrentLocation(),n,n)}r.listen(function(t){e.apps.forEach(function(e){e._route=t})})}},ie.prototype.beforeEach=function(t){return At(this.beforeHooks,t)},ie.prototype.beforeResolve=function(t){return At(this.resolveHooks,t)},ie.prototype.afterEach=function(t){return At(this.afterHooks,t)},ie.prototype.onReady=function(t,e){this.history.onReady(t,e)},ie.prototype.onError=function(t){this.history.onError(t)},ie.prototype.push=function(t,e,r){this.history.push(t,e,r)},ie.prototype.replace=function(t,e,r){this.history.replace(t,e,r)},ie.prototype.go=function(t){this.history.go(t)},ie.prototype.back=function(){this.go(-1)},ie.prototype.forward=function(){this.go(1)},ie.prototype.getMatchedComponents=function(t){var e=t?t.matched?t:this.resolve(t).route:this.currentRoute;return e?[].concat.apply([],e.matched.map(function(t){return Object.keys(t.components).map(function(e){return t.components[e]})})):[]},ie.prototype.resolve=function(t,e,r){var n=I(t,e||this.history.current,r,this),o=this.match(n,e),i=o.redirectedFrom||o.fullPath;return{location:n,route:o,href:_t(this.history.base,i,this.mode),normalizedTo:n,resolved:o}},ie.prototype.addRoutes=function(t){this.matcher.addRoutes(t),this.history.current!==Ht&&this.history.transitionTo(this.history.getCurrentLocation())},Object.defineProperties(ie.prototype,ae),ie.install=m,ie.version="3.0.1",Bt&&window.Vue&&window.Vue.use(ie),ie});
\ No newline at end of file
diff --git a/web_client/vueRouter.go b/web_client/vueRouter.go
new file mode 100644
index 0000000..06ab7d0
--- /dev/null
+++ b/web_client/vueRouter.go
@@ -0,0 +1 @@
+package main