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