2023-12-18 13:12:25 +08:00
/ * !
2024-01-16 21:26:16 +08:00
* vue - router v3 . 6.5
* ( c ) 2022 Evan You
2023-12-18 13:12:25 +08:00
* @ license MIT
* /
( function ( global , factory ) {
2024-01-16 21:26:16 +08:00
typeof exports === 'object' && typeof module !== 'undefined' ? module . exports = factory ( ) :
typeof define === 'function' && define . amd ? define ( factory ) :
( global = typeof globalThis !== 'undefined' ? globalThis : global || self , global . VueRouter = factory ( ) ) ;
} ) ( this , ( function ( ) { 'use strict' ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
/* */
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function assert ( condition , message ) {
if ( ! condition ) {
throw new Error ( ( "[vue-router] " + message ) )
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function warn ( condition , message ) {
if ( ! condition ) {
typeof console !== 'undefined' && console . warn ( ( "[vue-router] " + message ) ) ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function extend ( a , b ) {
for ( var key in b ) {
a [ key ] = b [ key ] ;
}
return a
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
/* */
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var encodeReserveRE = /[!'()*]/g ;
var encodeReserveReplacer = function ( c ) { return '%' + c . charCodeAt ( 0 ) . toString ( 16 ) ; } ;
var commaRE = /%2C/g ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
// fixed encodeURIComponent which is more conformant to RFC3986:
// - escapes [!'()*]
// - preserve commas
var encode = function ( str ) { return encodeURIComponent ( str )
. replace ( encodeReserveRE , encodeReserveReplacer )
. replace ( commaRE , ',' ) ; } ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function decode ( str ) {
try {
return decodeURIComponent ( str )
} catch ( err ) {
2023-12-18 13:12:25 +08:00
{
2024-01-16 21:26:16 +08:00
warn ( false , ( "Error decoding \"" + str + "\". Leaving it intact." ) ) ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
}
return str
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
function resolveQuery (
query ,
extraQuery ,
_parseQuery
) {
if ( extraQuery === void 0 ) extraQuery = { } ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var parse = _parseQuery || parseQuery ;
var parsedQuery ;
try {
parsedQuery = parse ( query || '' ) ;
} catch ( e ) {
warn ( false , e . message ) ;
parsedQuery = { } ;
}
for ( var key in extraQuery ) {
var value = extraQuery [ key ] ;
parsedQuery [ key ] = Array . isArray ( value )
? value . map ( castQueryParamValue )
: castQueryParamValue ( value ) ;
}
return parsedQuery
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var castQueryParamValue = function ( value ) { return ( value == null || typeof value === 'object' ? value : String ( value ) ) ; } ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function parseQuery ( query ) {
var res = { } ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
query = query . trim ( ) . replace ( /^(\?|#|&)/ , '' ) ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
if ( ! query ) {
return res
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
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 ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
if ( res [ key ] === undefined ) {
res [ key ] = val ;
} else if ( Array . isArray ( res [ key ] ) ) {
res [ key ] . push ( val ) ;
} else {
res [ key ] = [ res [ key ] , val ] ;
}
} ) ;
2023-12-18 13:12:25 +08:00
return res
}
2024-01-16 21:26:16 +08:00
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 ( '&' )
2023-12-18 13:12:25 +08:00
: null ;
2024-01-16 21:26:16 +08:00
return res ? ( "?" + res ) : ''
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
/* */
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var trailingSlashRE = /\/?$/ ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function createRoute (
record ,
location ,
redirectedFrom ,
router
) {
var stringifyQuery = router && router . options . stringifyQuery ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
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 ) ,
matched : record ? formatMatch ( record ) : [ ]
} ;
if ( redirectedFrom ) {
route . redirectedFrom = getFullPath ( redirectedFrom , stringifyQuery ) ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
return Object . freeze ( route )
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
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
2023-12-18 13:12:25 +08:00
}
}
2024-01-16 21:26:16 +08:00
// 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 ;
2023-12-18 13:12:25 +08:00
}
return res
}
2024-01-16 21:26:16 +08:00
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 = '' ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var stringify = _stringifyQuery || stringifyQuery ;
return ( path || '/' ) + stringify ( query ) + hash
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
function isSameRoute ( a , b , onlyPath ) {
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 , '' ) && ( onlyPath ||
a . hash === b . hash &&
isObjectEqual ( a . query , b . query ) )
} else if ( a . name && b . name ) {
return (
a . name === b . name &&
( onlyPath || (
a . hash === b . hash &&
isObjectEqual ( a . query , b . query ) &&
isObjectEqual ( a . params , b . params ) )
)
)
} else {
2023-12-18 13:12:25 +08:00
return false
}
}
2024-01-16 21:26:16 +08:00
function isObjectEqual ( a , b ) {
if ( a === void 0 ) a = { } ;
if ( b === void 0 ) b = { } ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
// handle null value #1566
if ( ! a || ! b ) { return a === b }
var aKeys = Object . keys ( a ) . sort ( ) ;
var bKeys = Object . keys ( b ) . sort ( ) ;
if ( aKeys . length !== bKeys . length ) {
return false
}
return aKeys . every ( function ( key , i ) {
var aVal = a [ key ] ;
var bKey = bKeys [ i ] ;
if ( bKey !== key ) { return false }
var bVal = b [ key ] ;
// query values can be null and undefined
if ( aVal == null || bVal == null ) { return aVal === bVal }
// check nested equality
if ( typeof aVal === 'object' && typeof bVal === 'object' ) {
return isObjectEqual ( aVal , bVal )
}
return String ( aVal ) === String ( bVal )
} )
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
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 )
)
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
function queryIncludes ( current , target ) {
for ( var key in target ) {
if ( ! ( key in current ) ) {
return false
}
}
return true
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
function handleRouteEntered ( route ) {
for ( var i = 0 ; i < route . matched . length ; i ++ ) {
var record = route . matched [ i ] ;
for ( var name in record . instances ) {
var instance = record . instances [ name ] ;
var cbs = record . enteredCbs [ name ] ;
if ( ! instance || ! cbs ) { continue }
delete record . enteredCbs [ name ] ;
for ( var i$1 = 0 ; i$1 < cbs . length ; i$1 ++ ) {
if ( ! instance . _isBeingDestroyed ) { cbs [ i$1 ] ( instance ) ; }
}
}
}
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
var View = {
name : 'RouterView' ,
functional : true ,
props : {
name : {
type : String ,
default : 'default'
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
} ,
render : function render ( _ , ref ) {
var props = ref . props ;
var children = ref . children ;
var parent = ref . parent ;
var data = ref . data ;
// used by devtools to display a router-view badge
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 ) {
var vnodeData = parent . $vnode ? parent . $vnode . data : { } ;
if ( vnodeData . routerView ) {
depth ++ ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
if ( vnodeData . keepAlive && parent . _directInactive && parent . _inactive ) {
inactive = true ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
parent = parent . $parent ;
}
data . routerViewDepth = depth ;
// render previous view if the tree is inactive and kept-alive
if ( inactive ) {
var cachedData = cache [ name ] ;
var cachedComponent = cachedData && cachedData . component ;
if ( cachedComponent ) {
// #2301
// pass props
if ( cachedData . configProps ) {
fillPropsinData ( cachedComponent , data , cachedData . route , cachedData . configProps ) ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
return h ( cachedComponent , data , children )
} else {
// render previous empty view
return h ( )
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var matched = route . matched [ depth ] ;
var component = matched && matched . components [ name ] ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
// render empty node if no matched route or no config component
if ( ! matched || ! component ) {
cache [ name ] = null ;
return h ( )
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
// cache component
cache [ name ] = { component : component } ;
// 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 ;
2023-12-18 13:12:25 +08:00
}
}
2024-01-16 21:26:16 +08:00
// 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 ;
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
// register instance in init hook
// in case kept-alive component be actived when routes changed
data . hook . init = function ( vnode ) {
if ( vnode . data . keepAlive &&
vnode . componentInstance &&
vnode . componentInstance !== matched . instances [ name ]
) {
matched . instances [ name ] = vnode . componentInstance ;
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
// if the route transition has already been confirmed then we weren't
// able to call the cbs during confirmation as the component was not
// registered yet, so we call it here.
handleRouteEntered ( route ) ;
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var configProps = matched . props && matched . props [ name ] ;
// save route and configProps in cache
if ( configProps ) {
extend ( cache [ name ] , {
route : route ,
configProps : configProps
} ) ;
fillPropsinData ( component , data , route , configProps ) ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
return h ( component , data , children )
}
} ;
function fillPropsinData ( component , data , route , configProps ) {
// resolve props
var propsToPass = data . props = resolveProps ( route , configProps ) ;
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 ] ;
2023-12-18 13:12:25 +08:00
}
}
}
}
2024-01-16 21:26:16 +08:00
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."
) ;
}
}
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
/* */
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function resolvePath (
relative ,
base ,
append
) {
var firstChar = relative . charAt ( 0 ) ;
if ( firstChar === '/' ) {
return relative
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
if ( firstChar === '?' || firstChar === '#' ) {
return base + relative
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var stack = base . split ( '/' ) ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
// remove trailing segment if:
// - not appending
// - appending to trailing slash (last segment is empty)
if ( ! append || ! stack [ stack . length - 1 ] ) {
stack . pop ( ) ;
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
// 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 ) ;
}
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
// ensure leading slash
if ( stack [ 0 ] !== '' ) {
stack . unshift ( '' ) ;
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
return stack . join ( '/' )
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function parsePath ( path ) {
var hash = '' ;
var query = '' ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var hashIndex = path . indexOf ( '#' ) ;
if ( hashIndex >= 0 ) {
hash = path . slice ( hashIndex ) ;
path = path . slice ( 0 , hashIndex ) ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
var queryIndex = path . indexOf ( '?' ) ;
if ( queryIndex >= 0 ) {
query = path . slice ( queryIndex + 1 ) ;
path = path . slice ( 0 , queryIndex ) ;
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
return {
path : path ,
query : query ,
hash : hash
}
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
function cleanPath ( path ) {
return path . replace ( /\/(?:\s*\/)+/g , '/' )
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
var isarray = Array . isArray || function ( arr ) {
return Object . prototype . toString . call ( arr ) == '[object Array]' ;
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
/ * *
* 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
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
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 = '' ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
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 ) + ']+?' )
2023-12-18 13:12:25 +08:00
} ) ;
}
2024-01-16 21:26:16 +08:00
// Match any characters still remaining.
if ( index < str . length ) {
path += str . substr ( index ) ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
// If the path exists, push it onto the end.
if ( path ) {
tokens . push ( path ) ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
return tokens
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
/ * *
* 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 ) , options )
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
/ * *
* 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 ( )
} )
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
/ * *
* 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 ( )
} )
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
/ * *
* Expose a method for transforming tokens into the path function .
* /
function tokensToFunction ( tokens , options ) {
// Compile all the tokens into regexps.
var matches = new Array ( tokens . length ) ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
// 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 + ')$' , flags ( options ) ) ;
2023-12-18 13:12:25 +08:00
}
}
2024-01-16 21:26:16 +08:00
return function ( obj , opts ) {
var path = '' ;
var data = obj || { } ;
var options = opts || { } ;
var encode = options . pretty ? encodeURIComponentPretty : encodeURIComponent ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
for ( var i = 0 ; i < tokens . length ; i ++ ) {
var token = tokens [ i ] ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
if ( typeof token === 'string' ) {
path += token ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
continue
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var value = data [ token . name ] ;
var segment ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
if ( value == null ) {
if ( token . optional ) {
// Prepend partial segment prefixes.
if ( token . partial ) {
path += token . prefix ;
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
continue
} else {
throw new TypeError ( 'Expected "' + token . name + '" to be defined' )
}
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
if ( isarray ( value ) ) {
if ( ! token . repeat ) {
throw new TypeError ( 'Expected "' + token . name + '" to not repeat, but received `' + JSON . stringify ( value ) + '`' )
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
if ( value . length === 0 ) {
if ( token . optional ) {
continue
} else {
throw new TypeError ( 'Expected "' + token . name + '" to not be empty' )
}
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
for ( var j = 0 ; j < value . length ; j ++ ) {
segment = encode ( value [ j ] ) ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
if ( ! matches [ i ] . test ( segment ) ) {
throw new TypeError ( 'Expected all "' + token . name + '" to match "' + token . pattern + '", but received `' + JSON . stringify ( segment ) + '`' )
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
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 && 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
} ) ;
2023-12-18 13:12:25 +08:00
}
}
2024-01-16 21:26:16 +08:00
return attachKeys ( path , keys )
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
/ * *
* 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 )
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
/ * *
* 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 ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
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 + '(?=$))?' ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
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 + '|$)' ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
return attachKeys ( new RegExp ( '^' + route , flags ( options ) ) , keys )
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
/ * *
* 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 || { } ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
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 ;
/* */
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
// $flow-disable-line
var regexpCompileCache = Object . create ( null ) ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function fillParams (
path ,
params ,
routeMsg
) {
params = params || { } ;
try {
var filler =
regexpCompileCache [ path ] ||
( regexpCompileCache [ path ] = pathToRegexp _1 . compile ( path ) ) ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
// Fix #2505 resolving asterisk routes { name: 'not-found', params: { pathMatch: '/not-found' }}
// and fix #3106 so that you can work with location descriptor object having params.pathMatch equal to empty string
if ( typeof params . pathMatch === 'string' ) { params [ 0 ] = params . pathMatch ; }
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
return filler ( params , { pretty : true } )
} catch ( e ) {
{
// Fix #3072 no warn if `pathMatch` is string
warn ( typeof params . pathMatch === 'string' , ( "missing param for " + routeMsg + ": " + ( e . message ) ) ) ;
}
return ''
} finally {
// delete the 0 if it was added
delete params [ 0 ] ;
}
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
/* */
function normalizeLocation (
2023-12-18 13:12:25 +08:00
raw ,
2024-01-16 21:26:16 +08:00
current ,
append ,
router
2023-12-18 13:12:25 +08:00
) {
2024-01-16 21:26:16 +08:00
var next = typeof raw === 'string' ? { path : raw } : raw ;
// named target
if ( next . _normalized ) {
return next
} else if ( next . name ) {
next = extend ( { } , raw ) ;
var params = next . params ;
if ( params && typeof params === 'object' ) {
next . params = extend ( { } , params ) ;
}
return next
}
// relative params
if ( ! next . path && next . params && current ) {
next = extend ( { } , next ) ;
next . _normalized = true ;
var params$1 = extend ( extend ( { } , current . params ) , next . params ) ;
if ( current . name ) {
next . name = current . name ;
next . params = params$1 ;
} else if ( current . matched . length ) {
var rawPath = current . matched [ current . matched . length - 1 ] . path ;
next . path = fillParams ( rawPath , params$1 , ( "path " + ( current . path ) ) ) ;
} else {
warn ( false , "relative params navigation requires a current route." ) ;
}
return next
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
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
}
}
/* */
// work around weird flow bug
var toTypes = [ String , Object ] ;
var eventTypes = [ String , Array ] ;
var noop = function ( ) { } ;
var warnedCustomSlot ;
var warnedTagProp ;
var warnedEventProp ;
var Link = {
name : 'RouterLink' ,
props : {
to : {
type : toTypes ,
required : true
} ,
tag : {
type : String ,
default : 'a'
} ,
custom : Boolean ,
exact : Boolean ,
exactPath : Boolean ,
append : Boolean ,
replace : Boolean ,
activeClass : String ,
exactActiveClass : String ,
ariaCurrentValue : {
type : String ,
default : 'page'
} ,
event : {
type : eventTypes ,
default : 'click'
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
} ,
render : function render ( h ) {
var this $1$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 = route . redirectedFrom
? createRoute ( null , normalizeLocation ( route . redirectedFrom ) , null , router )
: route ;
classes [ exactActiveClass ] = isSameRoute ( current , compareTarget , this . exactPath ) ;
classes [ activeClass ] = this . exact || this . exactPath
? classes [ exactActiveClass ]
: isIncludedRoute ( current , compareTarget ) ;
var ariaCurrentValue = classes [ exactActiveClass ] ? this . ariaCurrentValue : null ;
var handler = function ( e ) {
if ( guardEvent ( e ) ) {
if ( this $1$1 . replace ) {
router . replace ( location , noop ) ;
} else {
router . push ( location , noop ) ;
}
}
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var on = { click : guardEvent } ;
if ( Array . isArray ( this . event ) ) {
this . event . forEach ( function ( e ) {
on [ e ] = handler ;
} ) ;
} else {
on [ this . event ] = handler ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
var data = { class : classes } ;
var scopedSlot =
! this . $scopedSlots . $hasNormal &&
this . $scopedSlots . default &&
this . $scopedSlots . default ( {
href : href ,
route : route ,
navigate : handler ,
isActive : classes [ activeClass ] ,
isExactActive : classes [ exactActiveClass ]
} ) ;
if ( scopedSlot ) {
if ( ! this . custom ) {
! warnedCustomSlot && warn ( false , 'In Vue Router 4, the v-slot API will by default wrap its content with an <a> element. Use the custom prop to remove this warning:\n<router-link v-slot="{ navigate, href }" custom></router-link>\n' ) ;
warnedCustomSlot = true ;
}
if ( scopedSlot . length === 1 ) {
return scopedSlot [ 0 ]
} else if ( scopedSlot . length > 1 || ! scopedSlot . length ) {
{
warn (
false ,
( "<router-link> with to=\"" + ( this . to ) + "\" is trying to use a scoped slot but it didn't provide exactly one child. Wrapping the content with a span element." )
) ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
return scopedSlot . length === 0 ? h ( ) : h ( 'span' , { } , scopedSlot )
2023-12-18 13:12:25 +08:00
}
}
2024-01-16 21:26:16 +08:00
{
if ( 'tag' in this . $options . propsData && ! warnedTagProp ) {
warn (
false ,
"<router-link>'s tag prop is deprecated and has been removed in Vue Router 4. Use the v-slot API to remove this warning: https://next.router.vuejs.org/guide/migration/#removal-of-event-and-tag-props-in-router-link."
) ;
warnedTagProp = true ;
}
if ( 'event' in this . $options . propsData && ! warnedEventProp ) {
warn (
false ,
"<router-link>'s event prop is deprecated and has been removed in Vue Router 4. Use the v-slot API to remove this warning: https://next.router.vuejs.org/guide/migration/#removal-of-event-and-tag-props-in-router-link."
) ;
warnedEventProp = true ;
}
}
if ( this . tag === 'a' ) {
data . on = on ;
data . attrs = { href : href , 'aria-current' : ariaCurrentValue } ;
} else {
// find the first <a> child and apply listener and href
var a = findAnchor ( this . $slots . default ) ;
if ( a ) {
// in case the <a> is a static node
a . isStatic = false ;
var aData = ( a . data = extend ( { } , a . data ) ) ;
aData . on = aData . on || { } ;
// transform existing events in both objects into arrays so we can push later
for ( var event in aData . on ) {
var handler$1 = aData . on [ event ] ;
if ( event in on ) {
aData . on [ event ] = Array . isArray ( handler$1 ) ? handler$1 : [ handler$1 ] ;
}
}
// append new listeners for router-link
for ( var event$1 in on ) {
if ( event$1 in aData . on ) {
// on[event] is always a function
aData . on [ event$1 ] . push ( on [ event$1 ] ) ;
} else {
aData . on [ event$1 ] = handler ;
}
}
var aAttrs = ( a . data . attrs = extend ( { } , a . data . attrs ) ) ;
aAttrs . href = href ;
aAttrs [ 'aria-current' ] = ariaCurrentValue ;
} else {
// doesn't have <a> child, apply listener to self
data . on = on ;
2023-12-18 13:12:25 +08:00
}
}
2024-01-16 21:26:16 +08:00
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 ( ) ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
return true
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
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 ( 'RouterView' , View ) ;
Vue . component ( 'RouterLink' , 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 createRouteMap (
routes ,
oldPathList ,
oldPathMap ,
oldNameMap ,
parentRoute
2023-12-18 13:12:25 +08:00
) {
2024-01-16 21:26:16 +08:00
// 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 , parentRoute ) ;
} ) ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
// 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 -- ;
}
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
{
// warn if routes do not include leading slashes
var found = pathList
// check for missing leading slash
. filter ( function ( path ) { return path && path . charAt ( 0 ) !== '*' && path . charAt ( 0 ) !== '/' ; } ) ;
if ( found . length > 0 ) {
var pathNames = found . map ( function ( path ) { return ( "- " + path ) ; } ) . join ( '\n' ) ;
warn ( false , ( "Non-nested routes must include a leading slash character. Fix the following routes: \n" + pathNames ) ) ;
}
}
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."
) ;
warn (
// eslint-disable-next-line no-control-regex
! /[^\u0000-\u007F]+/ . test ( path ) ,
"Route with path \"" + path + "\" contains unencoded characters, make sure " +
"your path is correctly encoded before passing it to the router. Use " +
"encodeURI to encode static segments of your path."
) ;
}
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 } ,
alias : route . alias
? typeof route . alias === 'string'
? [ route . alias ]
: route . alias
: [ ] ,
instances : { } ,
enteredCbs : { } ,
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)
2023-12-18 13:12:25 +08:00
{
2024-01-16 21:26:16 +08:00
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 ( ! pathMap [ record . path ] ) {
pathList . push ( record . path ) ;
pathMap [ record . path ] = record ;
}
if ( route . alias !== undefined ) {
var aliases = Array . isArray ( route . alias ) ? route . alias : [ route . alias ] ;
for ( var i = 0 ; i < aliases . length ; ++ i ) {
var alias = aliases [ i ] ;
if ( alias === path ) {
warn (
false ,
( "Found an alias with the same value as the path: \"" + path + "\". You have to remove that alias. It will be ignored in development." )
) ;
// skip in dev to make it work
continue
}
var aliasRoute = {
path : alias ,
children : route . children
} ;
addRouteRecord (
pathList ,
pathMap ,
nameMap ,
aliasRoute ,
parent ,
record . path || '/' // matchAs
) ;
}
}
if ( name ) {
if ( ! nameMap [ name ] ) {
nameMap [ name ] = record ;
} else if ( ! matchAs ) {
2023-12-18 13:12:25 +08:00
warn (
2024-01-16 21:26:16 +08:00
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 + "\"" )
2023-12-18 13:12:25 +08:00
) ;
2024-01-16 21:26:16 +08:00
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 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 addRoute ( parentOrRoute , route ) {
var parent = ( typeof parentOrRoute !== 'object' ) ? nameMap [ parentOrRoute ] : undefined ;
// $flow-disable-line
createRouteMap ( [ route || parentOrRoute ] , pathList , pathMap , nameMap , parent ) ;
// add aliases of parent
if ( parent && parent . alias . length ) {
createRouteMap (
// $flow-disable-line route is defined if parent is
parent . alias . map ( function ( alias ) { return ( { path : alias , children : [ route ] } ) ; } ) ,
pathList ,
pathMap ,
nameMap ,
parent
) ;
}
}
function getRoutes ( ) {
return pathList . map ( function ( path ) { return pathMap [ path ] ; } )
}
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 ] ;
}
}
}
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 )
}
}
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
// no match
2023-12-18 13:12:25 +08:00
return _createRoute ( null , location )
}
2024-01-16 21:26:16 +08:00
function redirect (
record ,
location
) {
var originalRedirect = record . redirect ;
var redirect = typeof originalRedirect === 'function'
? originalRedirect ( createRoute ( record , location , null , router ) )
: originalRedirect ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
if ( typeof redirect === 'string' ) {
redirect = { path : redirect } ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
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 ( {
2023-12-18 13:12:25 +08:00
_normalized : true ,
2024-01-16 21:26:16 +08:00
path : aliasedPath
} ) ;
if ( aliasedMatch ) {
var matched = aliasedMatch . matched ;
var aliasedRecord = matched [ matched . length - 1 ] ;
location . params = aliasedMatch . params ;
return _createRoute ( aliasedRecord , location )
2023-12-18 13:12:25 +08:00
}
return _createRoute ( null , location )
}
2024-01-16 21:26:16 +08:00
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 ,
addRoute : addRoute ,
getRoutes : getRoutes ,
addRoutes : addRoutes
2023-12-18 13:12:25 +08:00
}
}
2024-01-16 21:26:16 +08:00
function matchRoute (
regex ,
path ,
params
2023-12-18 13:12:25 +08:00
) {
2024-01-16 21:26:16 +08:00
var m = path . match ( regex ) ;
if ( ! m ) {
return false
} else if ( ! params ) {
return true
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
for ( var i = 1 , len = m . length ; i < len ; ++ i ) {
var key = regex . keys [ i - 1 ] ;
if ( key ) {
// Fix #1994: using * with props: true generates a param named 0
params [ key . name || 'pathMatch' ] = typeof m [ i ] === 'string' ? decode ( m [ i ] ) : m [ i ] ;
}
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
return true
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
function resolveRecordPath ( path , record ) {
return resolvePath ( path , record . parent ? record . parent . path : '/' , true )
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
/* */
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
// use User Timing api (if present) for more accurate key precision
var Time =
inBrowser && window . performance && window . performance . now
? window . performance
: Date ;
function genStateKey ( ) {
return Time . now ( ) . toFixed ( 3 )
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
var _key = genStateKey ( ) ;
function getStateKey ( ) {
return _key
}
function setStateKey ( key ) {
return ( _key = key )
}
/* */
var positionStore = Object . create ( null ) ;
function setupScroll ( ) {
// Prevent browser scroll behavior on History popstate
if ( 'scrollRestoration' in window . history ) {
window . history . scrollRestoration = 'manual' ;
}
// Fix for #1585 for Firefox
// Fix for #2195 Add optional third attribute to workaround a bug in safari https://bugs.webkit.org/show_bug.cgi?id=182678
// Fix for #2774 Support for apps loaded from Windows file shares not mapped to network drives: replaced location.origin with
// window.location.protocol + '//' + window.location.host
// location.host contains the port and location.hostname doesn't
var protocolAndPath = window . location . protocol + '//' + window . location . host ;
var absolutePath = window . location . href . replace ( protocolAndPath , '' ) ;
// preserve existing history state as it could be overriden by the user
var stateCopy = extend ( { } , window . history . state ) ;
stateCopy . key = getStateKey ( ) ;
window . history . replaceState ( stateCopy , '' , absolutePath ) ;
window . addEventListener ( 'popstate' , handlePopState ) ;
return function ( ) {
window . removeEventListener ( 'popstate' , handlePopState ) ;
2023-12-18 13:12:25 +08:00
}
}
2024-01-16 21:26:16 +08:00
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 . call (
router ,
to ,
from ,
isPop ? position : null
) ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
if ( ! shouldScroll ) {
return
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
if ( typeof shouldScroll . then === 'function' ) {
shouldScroll
. then ( function ( shouldScroll ) {
scrollToPosition ( ( shouldScroll ) , position ) ;
} )
. catch ( function ( err ) {
{
assert ( false , err . toString ( ) ) ;
}
} ) ;
} else {
scrollToPosition ( shouldScroll , position ) ;
}
} ) ;
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function saveScrollPosition ( ) {
var key = getStateKey ( ) ;
if ( key ) {
positionStore [ key ] = {
x : window . pageXOffset ,
y : window . pageYOffset
} ;
}
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function handlePopState ( e ) {
2023-12-18 13:12:25 +08:00
saveScrollPosition ( ) ;
if ( e . state && e . state . key ) {
setStateKey ( e . state . key ) ;
}
2024-01-16 21:26:16 +08:00
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function getScrollPosition ( ) {
var key = getStateKey ( ) ;
if ( key ) {
return positionStore [ key ]
}
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
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
}
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
function isValidPosition ( obj ) {
return isNumber ( obj . x ) || isNumber ( obj . y )
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
function normalizePosition ( obj ) {
return {
x : isNumber ( obj . x ) ? obj . x : window . pageXOffset ,
y : isNumber ( obj . y ) ? obj . y : window . pageYOffset
}
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function normalizeOffset ( obj ) {
return {
x : isNumber ( obj . x ) ? obj . x : 0 ,
y : isNumber ( obj . y ) ? obj . y : 0
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function isNumber ( v ) {
return typeof v === 'number'
}
var hashStartsWithNumberRE = /^#\d/ ;
function scrollToPosition ( shouldScroll , position ) {
var isObject = typeof shouldScroll === 'object' ;
if ( isObject && typeof shouldScroll . selector === 'string' ) {
// getElementById would still fail if the selector contains a more complicated query like #main[data-attr]
// but at the same time, it doesn't make much sense to select an element with an id and an extra selector
var el = hashStartsWithNumberRE . test ( shouldScroll . selector ) // $flow-disable-line
? document . getElementById ( shouldScroll . selector . slice ( 1 ) ) // $flow-disable-line
: 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 ) {
// $flow-disable-line
if ( 'scrollBehavior' in document . documentElement . style ) {
window . scrollTo ( {
left : position . x ,
top : position . y ,
// $flow-disable-line
behavior : shouldScroll . behavior
2023-12-18 13:12:25 +08:00
} ) ;
2024-01-16 21:26:16 +08:00
} else {
window . scrollTo ( position . x , position . y ) ;
}
2023-12-18 13:12:25 +08:00
}
}
2024-01-16 21:26:16 +08:00
/* */
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 && typeof window . history . pushState === 'function'
} ) ( ) ;
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 ) {
// preserve existing history state as it could be overriden by the user
var stateCopy = extend ( { } , history . state ) ;
stateCopy . key = getStateKey ( ) ;
history . replaceState ( stateCopy , '' , url ) ;
} else {
history . pushState ( { key : setStateKey ( genStateKey ( ) ) } , '' , url ) ;
}
} catch ( e ) {
window . location [ replace ? 'replace' : 'assign' ] ( url ) ;
2023-12-18 13:12:25 +08:00
}
}
2024-01-16 21:26:16 +08:00
function replaceState ( url ) {
pushState ( url , true ) ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
// When changing thing, also edit router.d.ts
var NavigationFailureType = {
redirected : 2 ,
aborted : 4 ,
cancelled : 8 ,
duplicated : 16
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function createNavigationRedirectedError ( from , to ) {
return createRouterError (
from ,
to ,
NavigationFailureType . redirected ,
( "Redirected when going from \"" + ( from . fullPath ) + "\" to \"" + ( stringifyRoute (
to
) ) + "\" via a navigation guard." )
)
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function createNavigationDuplicatedError ( from , to ) {
var error = createRouterError (
from ,
to ,
NavigationFailureType . duplicated ,
( "Avoided redundant navigation to current location: \"" + ( from . fullPath ) + "\"." )
) ;
// backwards compatible with the first introduction of Errors
error . name = 'NavigationDuplicated' ;
return error
}
function createNavigationCancelledError ( from , to ) {
return createRouterError (
from ,
to ,
NavigationFailureType . cancelled ,
( "Navigation cancelled from \"" + ( from . fullPath ) + "\" to \"" + ( to . fullPath ) + "\" with a new navigation." )
)
}
function createNavigationAbortedError ( from , to ) {
return createRouterError (
from ,
to ,
NavigationFailureType . aborted ,
( "Navigation aborted from \"" + ( from . fullPath ) + "\" to \"" + ( to . fullPath ) + "\" via a navigation guard." )
)
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
function createRouterError ( from , to , type , message ) {
var error = new Error ( message ) ;
error . _isRouter = true ;
error . from = from ;
error . to = to ;
error . type = type ;
return error
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var propertiesToLog = [ 'params' , 'query' , 'hash' ] ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function stringifyRoute ( to ) {
if ( typeof to === 'string' ) { return to }
if ( 'path' in to ) { return to . path }
var location = { } ;
propertiesToLog . forEach ( function ( key ) {
if ( key in to ) { location [ key ] = to [ key ] ; }
} ) ;
return JSON . stringify ( location , null , 2 )
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function isError ( err ) {
return Object . prototype . toString . call ( err ) . indexOf ( 'Error' ) > - 1
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function isNavigationFailure ( err , errorType ) {
return (
isError ( err ) &&
err . _isRouter &&
( errorType == null || err . type === errorType )
)
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
/* */
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
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 ;
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 ( ) ; }
2023-12-18 13:12:25 +08:00
}
}
2024-01-16 21:26:16 +08:00
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 )
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var hasSymbol =
typeof Symbol === 'function' &&
typeof Symbol . toStringTag === 'symbol' ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
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 = [ ] ;
this . listeners = [ ] ;
} ;
History . prototype . listen = function listen ( cb ) {
this . cb = cb ;
} ;
History . prototype . onReady = function onReady ( cb , errorCb ) {
if ( this . ready ) {
2023-12-18 13:12:25 +08:00
cb ( ) ;
} else {
2024-01-16 21:26:16 +08:00
this . readyCbs . push ( cb ) ;
if ( errorCb ) {
this . readyErrorCbs . push ( errorCb ) ;
2023-12-18 13:12:25 +08:00
}
}
} ;
2024-01-16 21:26:16 +08:00
History . prototype . onError = function onError ( errorCb ) {
this . errorCbs . push ( errorCb ) ;
} ;
History . prototype . transitionTo = function transitionTo (
location ,
onComplete ,
onAbort
) {
var this $1$1 = this ;
var route ;
// catch redirect option https://github.com/vuejs/vue-router/issues/3201
try {
route = this . router . match ( location , this . current ) ;
} catch ( e ) {
this . errorCbs . forEach ( function ( cb ) {
cb ( e ) ;
} ) ;
// Exception should still be thrown
throw e
}
var prev = this . current ;
this . confirmTransition (
route ,
function ( ) {
this $1$1 . updateRoute ( route ) ;
onComplete && onComplete ( route ) ;
this $1$1 . ensureURL ( ) ;
this $1$1 . router . afterHooks . forEach ( function ( hook ) {
hook && hook ( route , prev ) ;
2023-12-18 13:12:25 +08:00
} ) ;
2024-01-16 21:26:16 +08:00
// fire ready cbs once
if ( ! this $1$1 . ready ) {
this $1$1 . ready = true ;
this $1$1 . readyCbs . forEach ( function ( cb ) {
cb ( route ) ;
} ) ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
} ,
function ( err ) {
if ( onAbort ) {
onAbort ( err ) ;
}
if ( err && ! this $1$1 . ready ) {
// Initial redirection should not mark the history as ready yet
// because it's triggered by the redirection instead
// https://github.com/vuejs/vue-router/issues/3225
// https://github.com/vuejs/vue-router/issues/3331
if ( ! isNavigationFailure ( err , NavigationFailureType . redirected ) || prev !== START ) {
this $1$1 . ready = true ;
this $1$1 . readyErrorCbs . forEach ( function ( cb ) {
cb ( err ) ;
} ) ;
2023-12-18 13:12:25 +08:00
}
}
}
2024-01-16 21:26:16 +08:00
) ;
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
History . prototype . confirmTransition = function confirmTransition ( route , onComplete , onAbort ) {
var this $1$1 = this ;
var current = this . current ;
this . pending = route ;
var abort = function ( err ) {
// changed after adding errors with
// https://github.com/vuejs/vue-router/pull/3047 before that change,
// redirect and aborted navigation would produce an err == null
if ( ! isNavigationFailure ( err ) && isError ( err ) ) {
if ( this $1$1 . errorCbs . length ) {
this $1$1 . errorCbs . forEach ( function ( cb ) {
cb ( err ) ;
} ) ;
} else {
{
warn ( false , 'uncaught error during route navigation:' ) ;
}
console . error ( err ) ;
}
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
onAbort && onAbort ( err ) ;
} ;
var lastRouteIndex = route . matched . length - 1 ;
var lastCurrentIndex = current . matched . length - 1 ;
if (
isSameRoute ( route , current ) &&
// in the case the route map has been dynamically appended to
lastRouteIndex === lastCurrentIndex &&
route . matched [ lastRouteIndex ] === current . matched [ lastCurrentIndex ]
) {
this . ensureURL ( ) ;
if ( route . hash ) {
handleScroll ( this . router , current , route , false ) ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
return abort ( createNavigationDuplicatedError ( current , route ) )
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
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 )
) ;
var iterator = function ( hook , next ) {
if ( this $1$1 . pending !== route ) {
return abort ( createNavigationCancelledError ( current , route ) )
}
try {
hook ( route , current , function ( to ) {
if ( to === false ) {
// next(false) -> abort navigation, ensure current URL
this $1$1 . ensureURL ( true ) ;
abort ( createNavigationAbortedError ( current , route ) ) ;
} else if ( isError ( to ) ) {
this $1$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 ( createNavigationRedirectedError ( current , route ) ) ;
if ( typeof to === 'object' && to . replace ) {
this $1$1 . replace ( to ) ;
} else {
this $1$1 . push ( to ) ;
}
} else {
// confirm transition and pass on the value
next ( to ) ;
}
} ) ;
} catch ( e ) {
abort ( e ) ;
}
} ;
runQueue ( queue , iterator , function ( ) {
// wait until async components are resolved before
// extracting in-component enter guards
var enterGuards = extractEnterGuards ( activated ) ;
var queue = enterGuards . concat ( this $1$1 . router . resolveHooks ) ;
runQueue ( queue , iterator , function ( ) {
if ( this $1$1 . pending !== route ) {
return abort ( createNavigationCancelledError ( current , route ) )
}
this $1$1 . pending = null ;
onComplete ( route ) ;
if ( this $1$1 . router . app ) {
this $1$1 . router . app . $nextTick ( function ( ) {
handleRouteEntered ( route ) ;
} ) ;
}
} ) ;
} ) ;
} ;
History . prototype . updateRoute = function updateRoute ( route ) {
this . current = route ;
this . cb && this . cb ( route ) ;
} ;
History . prototype . setupListeners = function setupListeners ( ) {
// Default implementation is empty
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
History . prototype . teardown = function teardown ( ) {
// clean up event listeners
// https://github.com/vuejs/vue-router/issues/2341
this . listeners . forEach ( function ( cleanupListener ) {
cleanupListener ( ) ;
} ) ;
this . listeners = [ ] ;
// reset current history route
// https://github.com/vuejs/vue-router/issues/3294
this . current = START ;
this . pending = null ;
} ;
function normalizeBase ( base ) {
if ( ! base ) {
if ( inBrowser ) {
// respect <base> tag
var baseEl = document . querySelector ( 'base' ) ;
base = ( baseEl && baseEl . getAttribute ( 'href' ) ) || '/' ;
// strip full URL origin
base = base . replace ( /^https?:\/\/[^\/]+/ , '' ) ;
2023-12-18 13:12:25 +08:00
} else {
2024-01-16 21:26:16 +08:00
base = '/' ;
2023-12-18 13:12:25 +08:00
}
}
2024-01-16 21:26:16 +08:00
// make sure there's the starting slash
if ( base . charAt ( 0 ) !== '/' ) {
base = '/' + base ;
}
// remove trailing slash
return base . replace ( /\/$/ , '' )
}
function resolveQueue (
current ,
next
2023-12-18 13:12:25 +08:00
) {
2024-01-16 21:26:16 +08:00
var i ;
var max = Math . max ( current . length , next . length ) ;
for ( i = 0 ; i < max ; i ++ ) {
if ( current [ i ] !== next [ i ] ) {
break
}
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
return {
updated : next . slice ( 0 , i ) ,
activated : next . slice ( i ) ,
deactivated : current . slice ( i )
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
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 )
2023-12-18 13:12:25 +08:00
}
} ) ;
2024-01-16 21:26:16 +08:00
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 ) ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
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 )
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
}
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
function extractEnterGuards (
activated
2023-12-18 13:12:25 +08:00
) {
2024-01-16 21:26:16 +08:00
return extractGuards (
activated ,
'beforeRouteEnter' ,
function ( guard , _ , match , key ) {
return bindEnterGuard ( guard , match , key )
}
)
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
function bindEnterGuard (
guard ,
match ,
key
) {
return function routeEnterGuard ( to , from , next ) {
return guard ( to , from , function ( cb ) {
if ( typeof cb === 'function' ) {
if ( ! match . enteredCbs [ key ] ) {
match . enteredCbs [ key ] = [ ] ;
}
match . enteredCbs [ key ] . push ( cb ) ;
}
next ( cb ) ;
} )
}
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
/* */
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var HTML5History = /*@__PURE__*/ ( function ( History ) {
function HTML5History ( router , base ) {
History . call ( this , router , base ) ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
this . _startLocation = getLocation ( this . base ) ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
if ( History ) HTML5History . _ _proto _ _ = History ;
HTML5History . prototype = Object . create ( History && History . prototype ) ;
HTML5History . prototype . constructor = HTML5History ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
HTML5History . prototype . setupListeners = function setupListeners ( ) {
var this $1$1 = this ;
if ( this . listeners . length > 0 ) {
2023-12-18 13:12:25 +08:00
return
}
2024-01-16 21:26:16 +08:00
var router = this . router ;
var expectScroll = router . options . scrollBehavior ;
var supportsScroll = supportsPushState && expectScroll ;
if ( supportsScroll ) {
this . listeners . push ( setupScroll ( ) ) ;
}
var handleRoutingEvent = function ( ) {
var current = this $1$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$1 . base ) ;
if ( this $1$1 . current === START && location === this $1$1 . _startLocation ) {
return
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
this $1$1 . transitionTo ( location , function ( route ) {
if ( supportsScroll ) {
handleScroll ( router , route , current , true ) ;
}
} ) ;
} ;
window . addEventListener ( 'popstate' , handleRoutingEvent ) ;
this . listeners . push ( function ( ) {
window . removeEventListener ( 'popstate' , handleRoutingEvent ) ;
} ) ;
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
HTML5History . prototype . go = function go ( n ) {
window . history . go ( n ) ;
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
HTML5History . prototype . push = function push ( location , onComplete , onAbort ) {
var this $1$1 = this ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var ref = this ;
var fromRoute = ref . current ;
this . transitionTo ( location , function ( route ) {
pushState ( cleanPath ( this $1$1 . base + route . fullPath ) ) ;
handleScroll ( this $1$1 . router , route , fromRoute , false ) ;
onComplete && onComplete ( route ) ;
} , onAbort ) ;
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
HTML5History . prototype . replace = function replace ( location , onComplete , onAbort ) {
var this $1$1 = this ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var ref = this ;
var fromRoute = ref . current ;
this . transitionTo ( location , function ( route ) {
replaceState ( cleanPath ( this $1$1 . base + route . fullPath ) ) ;
handleScroll ( this $1$1 . router , route , fromRoute , false ) ;
onComplete && onComplete ( route ) ;
} , onAbort ) ;
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
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 ) ;
}
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
HTML5History . prototype . getCurrentLocation = function getCurrentLocation ( ) {
return getLocation ( this . base )
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
return HTML5History ;
} ( History ) ) ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function getLocation ( base ) {
var path = window . location . pathname ;
var pathLowerCase = path . toLowerCase ( ) ;
var baseLowerCase = base . toLowerCase ( ) ;
// base="/a" shouldn't turn path="/app" into "/a/pp"
// https://github.com/vuejs/vue-router/issues/3555
// so we ensure the trailing slash in the base
if ( base && ( ( pathLowerCase === baseLowerCase ) ||
( pathLowerCase . indexOf ( cleanPath ( baseLowerCase + '/' ) ) === 0 ) ) ) {
path = path . slice ( base . length ) ;
}
return ( path || '/' ) + window . location . search + window . location . hash
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
/* */
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var HashHistory = /*@__PURE__*/ ( function ( History ) {
function HashHistory ( router , base , fallback ) {
History . call ( this , router , base ) ;
// check history fallback deeplinking
if ( fallback && checkFallback ( this . base ) ) {
return
}
ensureSlash ( ) ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
if ( History ) HashHistory . _ _proto _ _ = History ;
HashHistory . prototype = Object . create ( History && History . prototype ) ;
HashHistory . prototype . constructor = HashHistory ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
// this is delayed until the app mounts
// to avoid the hashchange listener being fired too early
HashHistory . prototype . setupListeners = function setupListeners ( ) {
var this $1$1 = this ;
if ( this . listeners . length > 0 ) {
return
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var router = this . router ;
var expectScroll = router . options . scrollBehavior ;
var supportsScroll = supportsPushState && expectScroll ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
if ( supportsScroll ) {
this . listeners . push ( setupScroll ( ) ) ;
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var handleRoutingEvent = function ( ) {
var current = this $1$1 . current ;
2023-12-18 13:12:25 +08:00
if ( ! ensureSlash ( ) ) {
return
}
2024-01-16 21:26:16 +08:00
this $1$1 . transitionTo ( getHash ( ) , function ( route ) {
2023-12-18 13:12:25 +08:00
if ( supportsScroll ) {
2024-01-16 21:26:16 +08:00
handleScroll ( this $1$1 . router , route , current , true ) ;
2023-12-18 13:12:25 +08:00
}
if ( ! supportsPushState ) {
replaceHash ( route . fullPath ) ;
}
} ) ;
2024-01-16 21:26:16 +08:00
} ;
var eventType = supportsPushState ? 'popstate' : 'hashchange' ;
window . addEventListener (
eventType ,
handleRoutingEvent
) ;
this . listeners . push ( function ( ) {
window . removeEventListener ( eventType , handleRoutingEvent ) ;
} ) ;
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
HashHistory . prototype . push = function push ( location , onComplete , onAbort ) {
var this $1$1 = this ;
var ref = this ;
var fromRoute = ref . current ;
this . transitionTo (
location ,
function ( route ) {
pushHash ( route . fullPath ) ;
handleScroll ( this $1$1 . router , route , fromRoute , false ) ;
onComplete && onComplete ( route ) ;
} ,
onAbort
) ;
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
HashHistory . prototype . replace = function replace ( location , onComplete , onAbort ) {
var this $1$1 = this ;
var ref = this ;
var fromRoute = ref . current ;
this . transitionTo (
location ,
function ( route ) {
replaceHash ( route . fullPath ) ;
handleScroll ( this $1$1 . router , route , fromRoute , false ) ;
onComplete && onComplete ( route ) ;
} ,
onAbort
) ;
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
HashHistory . prototype . go = function go ( n ) {
window . history . go ( n ) ;
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
HashHistory . prototype . ensureURL = function ensureURL ( push ) {
var current = this . current . fullPath ;
if ( getHash ( ) !== current ) {
push ? pushHash ( current ) : replaceHash ( current ) ;
}
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
HashHistory . prototype . getCurrentLocation = function getCurrentLocation ( ) {
return getHash ( )
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
return HashHistory ;
} ( History ) ) ;
function checkFallback ( base ) {
var location = getLocation ( base ) ;
if ( ! /^\/#/ . test ( location ) ) {
window . location . replace ( cleanPath ( base + '/#' + location ) ) ;
return true
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function ensureSlash ( ) {
var path = getHash ( ) ;
if ( path . charAt ( 0 ) === '/' ) {
return true
}
replaceHash ( '/' + path ) ;
return false
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
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 ( '#' ) ;
// empty path
if ( index < 0 ) { return '' }
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
href = href . slice ( index + 1 ) ;
return href
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
function getUrl ( path ) {
var href = window . location . href ;
var i = href . indexOf ( '#' ) ;
var base = i >= 0 ? href . slice ( 0 , i ) : href ;
return ( base + "#" + path )
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
function pushHash ( path ) {
if ( supportsPushState ) {
pushState ( getUrl ( path ) ) ;
} else {
window . location . hash = path ;
}
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function replaceHash ( path ) {
if ( supportsPushState ) {
replaceState ( getUrl ( path ) ) ;
} else {
window . location . replace ( getUrl ( path ) ) ;
}
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
/* */
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var AbstractHistory = /*@__PURE__*/ ( function ( History ) {
function AbstractHistory ( router , base ) {
History . call ( this , router , base ) ;
this . stack = [ ] ;
this . index = - 1 ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
if ( History ) AbstractHistory . _ _proto _ _ = History ;
AbstractHistory . prototype = Object . create ( History && History . prototype ) ;
AbstractHistory . prototype . constructor = AbstractHistory ;
AbstractHistory . prototype . push = function push ( location , onComplete , onAbort ) {
var this $1$1 = this ;
this . transitionTo (
location ,
function ( route ) {
this $1$1 . stack = this $1$1 . stack . slice ( 0 , this $1$1 . index + 1 ) . concat ( route ) ;
this $1$1 . index ++ ;
onComplete && onComplete ( route ) ;
} ,
onAbort
) ;
} ;
AbstractHistory . prototype . replace = function replace ( location , onComplete , onAbort ) {
var this $1$1 = this ;
this . transitionTo (
location ,
function ( route ) {
this $1$1 . stack = this $1$1 . stack . slice ( 0 , this $1$1 . index ) . concat ( route ) ;
onComplete && onComplete ( route ) ;
} ,
onAbort
) ;
} ;
AbstractHistory . prototype . go = function go ( n ) {
var this $1$1 = this ;
var targetIndex = this . index + n ;
if ( targetIndex < 0 || targetIndex >= this . stack . length ) {
return
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
var route = this . stack [ targetIndex ] ;
this . confirmTransition (
route ,
function ( ) {
var prev = this $1$1 . current ;
this $1$1 . index = targetIndex ;
this $1$1 . updateRoute ( route ) ;
this $1$1 . router . afterHooks . forEach ( function ( hook ) {
hook && hook ( route , prev ) ;
} ) ;
} ,
function ( err ) {
if ( isNavigationFailure ( err , NavigationFailureType . duplicated ) ) {
this $1$1 . index = targetIndex ;
}
}
) ;
} ;
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 = { } ;
{
warn ( this instanceof VueRouter , "Router must be called with the new operator." ) ;
}
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 ) ) ;
}
}
2023-12-18 13:12:25 +08:00
} ;
2024-01-16 21:26:16 +08:00
var prototypeAccessors = { currentRoute : { configurable : true } } ;
VueRouter . prototype . match = function match ( raw , current , redirectedFrom ) {
return this . matcher . match ( raw , current , redirectedFrom )
2023-12-18 13:12:25 +08:00
} ;
2024-01-16 21:26:16 +08:00
prototypeAccessors . currentRoute . get = function ( ) {
return this . history && this . history . current
2023-12-18 13:12:25 +08:00
} ;
2024-01-16 21:26:16 +08:00
VueRouter . prototype . init = function init ( app /* Vue component instance */ ) {
var this $1$1 = this ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
assert (
install . installed ,
"not installed. Make sure to call `Vue.use(VueRouter)` " +
"before creating root instance."
) ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
this . apps . push ( app ) ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
// set up app destroyed handler
// https://github.com/vuejs/vue-router/issues/2639
app . $once ( 'hook:destroyed' , function ( ) {
// clean out app from this.apps array once destroyed
var index = this $1$1 . apps . indexOf ( app ) ;
if ( index > - 1 ) { this $1$1 . apps . splice ( index , 1 ) ; }
// ensure we still have a main app or null if no apps
// we do not release the router so it can be reused
if ( this $1$1 . app === app ) { this $1$1 . app = this $1$1 . apps [ 0 ] || null ; }
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
if ( ! this $1$1 . app ) { this $1$1 . history . teardown ( ) ; }
} ) ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
// main app previously initialized
// return as we don't need to set up new history listener
if ( this . app ) {
return
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
this . app = app ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var history = this . history ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
if ( history instanceof HTML5History || history instanceof HashHistory ) {
var handleInitialScroll = function ( routeOrError ) {
var from = history . current ;
var expectScroll = this $1$1 . options . scrollBehavior ;
var supportsScroll = supportsPushState && expectScroll ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
if ( supportsScroll && 'fullPath' in routeOrError ) {
handleScroll ( this $1$1 , routeOrError , from , false ) ;
}
} ;
var setupListeners = function ( routeOrError ) {
history . setupListeners ( ) ;
handleInitialScroll ( routeOrError ) ;
} ;
history . transitionTo (
history . getCurrentLocation ( ) ,
setupListeners ,
setupListeners
) ;
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
history . listen ( function ( route ) {
this $1$1 . apps . forEach ( function ( app ) {
app . _route = route ;
} ) ;
} ) ;
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
VueRouter . prototype . beforeEach = function beforeEach ( fn ) {
return registerHook ( this . beforeHooks , fn )
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
VueRouter . prototype . beforeResolve = function beforeResolve ( fn ) {
return registerHook ( this . resolveHooks , fn )
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
VueRouter . prototype . afterEach = function afterEach ( fn ) {
return registerHook ( this . afterHooks , fn )
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
VueRouter . prototype . onReady = function onReady ( cb , errorCb ) {
this . history . onReady ( cb , errorCb ) ;
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
VueRouter . prototype . onError = function onError ( errorCb ) {
this . history . onError ( errorCb ) ;
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
VueRouter . prototype . push = function push ( location , onComplete , onAbort ) {
var this $1$1 = this ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
// $flow-disable-line
if ( ! onComplete && ! onAbort && typeof Promise !== 'undefined' ) {
return new Promise ( function ( resolve , reject ) {
this $1$1 . history . push ( location , resolve , reject ) ;
} )
} else {
this . history . push ( location , onComplete , onAbort ) ;
}
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
VueRouter . prototype . replace = function replace ( location , onComplete , onAbort ) {
var this $1$1 = this ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
// $flow-disable-line
if ( ! onComplete && ! onAbort && typeof Promise !== 'undefined' ) {
return new Promise ( function ( resolve , reject ) {
this $1$1 . history . replace ( location , resolve , reject ) ;
} )
} else {
this . history . replace ( location , onComplete , onAbort ) ;
}
} ;
VueRouter . prototype . go = function go ( n ) {
this . history . go ( n ) ;
} ;
VueRouter . prototype . back = function back ( ) {
this . go ( - 1 ) ;
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
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
) {
current = current || this . history . current ;
var location = normalizeLocation ( to , 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 . getRoutes = function getRoutes ( ) {
return this . matcher . getRoutes ( )
} ;
VueRouter . prototype . addRoute = function addRoute ( parentOrRoute , route ) {
this . matcher . addRoute ( parentOrRoute , route ) ;
if ( this . history . current !== START ) {
this . history . transitionTo ( this . history . getCurrentLocation ( ) ) ;
}
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
VueRouter . prototype . addRoutes = function addRoutes ( routes ) {
{
warn ( false , 'router.addRoutes() is deprecated and has been removed in Vue Router 4. Use router.addRoute() instead.' ) ;
}
this . matcher . addRoutes ( routes ) ;
if ( this . history . current !== START ) {
this . history . transitionTo ( this . history . getCurrentLocation ( ) ) ;
}
} ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
Object . defineProperties ( VueRouter . prototype , prototypeAccessors ) ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
var VueRouter$1 = VueRouter ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function registerHook ( list , fn ) {
list . push ( fn ) ;
return function ( ) {
var i = list . indexOf ( fn ) ;
if ( i > - 1 ) { list . splice ( i , 1 ) ; }
}
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
function createHref ( base , fullPath , mode ) {
var path = mode === 'hash' ? '#' + fullPath : fullPath ;
return base ? cleanPath ( base + '/' + path ) : path
}
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
// We cannot remove this as it would be a breaking change
VueRouter . install = install ;
VueRouter . version = '3.6.5' ;
VueRouter . isNavigationFailure = isNavigationFailure ;
VueRouter . NavigationFailureType = NavigationFailureType ;
VueRouter . START _LOCATION = START ;
if ( inBrowser && window . Vue ) {
window . Vue . use ( VueRouter ) ;
2023-12-18 13:12:25 +08:00
}
2024-01-16 21:26:16 +08:00
return VueRouter$1 ;
2023-12-18 13:12:25 +08:00
2024-01-16 21:26:16 +08:00
} ) ) ;