| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847 | /*!  * vue-router v4.1.6  * (c) 2022 Eduardo San Martin Morote  * @license MIT  */'use strict';Object.defineProperty(exports, '__esModule', { value: true });var vue = require('vue');const isBrowser = typeof window !== 'undefined';function isESModule(obj) {    return obj.__esModule || obj[Symbol.toStringTag] === 'Module';}const assign = Object.assign;function applyToParams(fn, params) {    const newParams = {};    for (const key in params) {        const value = params[key];        newParams[key] = isArray(value)            ? value.map(fn)            : fn(value);    }    return newParams;}const noop = () => { };/** * Typesafe alternative to Array.isArray * https://github.com/microsoft/TypeScript/pull/48228 */const isArray = Array.isArray;const TRAILING_SLASH_RE = /\/$/;const removeTrailingSlash = (path) => path.replace(TRAILING_SLASH_RE, '');/** * Transforms a URI into a normalized history location * * @param parseQuery * @param location - URI to normalize * @param currentLocation - current absolute location. Allows resolving relative * paths. Must start with `/`. Defaults to `/` * @returns a normalized history location */function parseURL(parseQuery, location, currentLocation = '/') {    let path, query = {}, searchString = '', hash = '';    // Could use URL and URLSearchParams but IE 11 doesn't support it    // TODO: move to new URL()    const hashPos = location.indexOf('#');    let searchPos = location.indexOf('?');    // the hash appears before the search, so it's not part of the search string    if (hashPos < searchPos && hashPos >= 0) {        searchPos = -1;    }    if (searchPos > -1) {        path = location.slice(0, searchPos);        searchString = location.slice(searchPos + 1, hashPos > -1 ? hashPos : location.length);        query = parseQuery(searchString);    }    if (hashPos > -1) {        path = path || location.slice(0, hashPos);        // keep the # character        hash = location.slice(hashPos, location.length);    }    // no search and no query    path = resolveRelativePath(path != null ? path : location, currentLocation);    // empty path means a relative query or hash `?foo=f`, `#thing`    return {        fullPath: path + (searchString && '?') + searchString + hash,        path,        query,        hash,    };}/** * Stringifies a URL object * * @param stringifyQuery * @param location */function stringifyURL(stringifyQuery, location) {    const query = location.query ? stringifyQuery(location.query) : '';    return location.path + (query && '?') + query + (location.hash || '');}/** * Strips off the base from the beginning of a location.pathname in a non-case-sensitive way. * * @param pathname - location.pathname * @param base - base to strip off */function stripBase(pathname, base) {    // no base or base is not found at the beginning    if (!base || !pathname.toLowerCase().startsWith(base.toLowerCase()))        return pathname;    return pathname.slice(base.length) || '/';}/** * Checks if two RouteLocation are equal. This means that both locations are * pointing towards the same {@link RouteRecord} and that all `params`, `query` * parameters and `hash` are the same * * @param a - first {@link RouteLocation} * @param b - second {@link RouteLocation} */function isSameRouteLocation(stringifyQuery, a, b) {    const aLastIndex = a.matched.length - 1;    const bLastIndex = b.matched.length - 1;    return (aLastIndex > -1 &&        aLastIndex === bLastIndex &&        isSameRouteRecord(a.matched[aLastIndex], b.matched[bLastIndex]) &&        isSameRouteLocationParams(a.params, b.params) &&        stringifyQuery(a.query) === stringifyQuery(b.query) &&        a.hash === b.hash);}/** * Check if two `RouteRecords` are equal. Takes into account aliases: they are * considered equal to the `RouteRecord` they are aliasing. * * @param a - first {@link RouteRecord} * @param b - second {@link RouteRecord} */function isSameRouteRecord(a, b) {    // since the original record has an undefined value for aliasOf    // but all aliases point to the original record, this will always compare    // the original record    return (a.aliasOf || a) === (b.aliasOf || b);}function isSameRouteLocationParams(a, b) {    if (Object.keys(a).length !== Object.keys(b).length)        return false;    for (const key in a) {        if (!isSameRouteLocationParamsValue(a[key], b[key]))            return false;    }    return true;}function isSameRouteLocationParamsValue(a, b) {    return isArray(a)        ? isEquivalentArray(a, b)        : isArray(b)            ? isEquivalentArray(b, a)            : a === b;}/** * Check if two arrays are the same or if an array with one single entry is the * same as another primitive value. Used to check query and parameters * * @param a - array of values * @param b - array of values or a single value */function isEquivalentArray(a, b) {    return isArray(b)        ? a.length === b.length && a.every((value, i) => value === b[i])        : a.length === 1 && a[0] === b;}/** * Resolves a relative path that starts with `.`. * * @param to - path location we are resolving * @param from - currentLocation.path, should start with `/` */function resolveRelativePath(to, from) {    if (to.startsWith('/'))        return to;    if (!to)        return from;    const fromSegments = from.split('/');    const toSegments = to.split('/');    let position = fromSegments.length - 1;    let toPosition;    let segment;    for (toPosition = 0; toPosition < toSegments.length; toPosition++) {        segment = toSegments[toPosition];        // we stay on the same position        if (segment === '.')            continue;        // go up in the from array        if (segment === '..') {            // we can't go below zero, but we still need to increment toPosition            if (position > 1)                position--;            // continue        }        // we reached a non-relative path, we stop here        else            break;    }    return (fromSegments.slice(0, position).join('/') +        '/' +        toSegments            // ensure we use at least the last element in the toSegments            .slice(toPosition - (toPosition === toSegments.length ? 1 : 0))            .join('/'));}var NavigationType;(function (NavigationType) {    NavigationType["pop"] = "pop";    NavigationType["push"] = "push";})(NavigationType || (NavigationType = {}));var NavigationDirection;(function (NavigationDirection) {    NavigationDirection["back"] = "back";    NavigationDirection["forward"] = "forward";    NavigationDirection["unknown"] = "";})(NavigationDirection || (NavigationDirection = {}));/** * Starting location for Histories */const START = '';// Generic utils/** * Normalizes a base by removing any trailing slash and reading the base tag if * present. * * @param base - base to normalize */function normalizeBase(base) {    if (!base) {        if (isBrowser) {            // respect <base> tag            const baseEl = document.querySelector('base');            base = (baseEl && baseEl.getAttribute('href')) || '/';            // strip full URL origin            base = base.replace(/^\w+:\/\/[^\/]+/, '');        }        else {            base = '/';        }    }    // ensure leading slash when it was removed by the regex above avoid leading    // slash with hash because the file could be read from the disk like file://    // and the leading slash would cause problems    if (base[0] !== '/' && base[0] !== '#')        base = '/' + base;    // remove the trailing slash so all other method can just do `base + fullPath`    // to build an href    return removeTrailingSlash(base);}// remove any character before the hashconst BEFORE_HASH_RE = /^[^#]+#/;function createHref(base, location) {    return base.replace(BEFORE_HASH_RE, '#') + location;}function getElementPosition(el, offset) {    const docRect = document.documentElement.getBoundingClientRect();    const elRect = el.getBoundingClientRect();    return {        behavior: offset.behavior,        left: elRect.left - docRect.left - (offset.left || 0),        top: elRect.top - docRect.top - (offset.top || 0),    };}const computeScrollPosition = () => ({    left: window.pageXOffset,    top: window.pageYOffset,});function scrollToPosition(position) {    let scrollToOptions;    if ('el' in position) {        const positionEl = position.el;        const isIdSelector = typeof positionEl === 'string' && positionEl.startsWith('#');        const el = typeof positionEl === 'string'            ? isIdSelector                ? document.getElementById(positionEl.slice(1))                : document.querySelector(positionEl)            : positionEl;        if (!el) {            return;        }        scrollToOptions = getElementPosition(el, position);    }    else {        scrollToOptions = position;    }    if ('scrollBehavior' in document.documentElement.style)        window.scrollTo(scrollToOptions);    else {        window.scrollTo(scrollToOptions.left != null ? scrollToOptions.left : window.pageXOffset, scrollToOptions.top != null ? scrollToOptions.top : window.pageYOffset);    }}function getScrollKey(path, delta) {    const position = history.state ? history.state.position - delta : -1;    return position + path;}const scrollPositions = new Map();function saveScrollPosition(key, scrollPosition) {    scrollPositions.set(key, scrollPosition);}function getSavedScrollPosition(key) {    const scroll = scrollPositions.get(key);    // consume it so it's not used again    scrollPositions.delete(key);    return scroll;}// TODO: RFC about how to save scroll position/** * ScrollBehavior instance used by the router to compute and restore the scroll * position when navigating. */// export interface ScrollHandler<ScrollPositionEntry extends HistoryStateValue, ScrollPosition extends ScrollPositionEntry> {//   // returns a scroll position that can be saved in history//   compute(): ScrollPositionEntry//   // can take an extended ScrollPositionEntry//   scroll(position: ScrollPosition): void// }// export const scrollHandler: ScrollHandler<ScrollPosition> = {//   compute: computeScroll,//   scroll: scrollToPosition,// }let createBaseLocation = () => location.protocol + '//' + location.host;/** * Creates a normalized history location from a window.location object * @param location - */function createCurrentLocation(base, location) {    const { pathname, search, hash } = location;    // allows hash bases like #, /#, #/, #!, #!/, /#!/, or even /folder#end    const hashPos = base.indexOf('#');    if (hashPos > -1) {        let slicePos = hash.includes(base.slice(hashPos))            ? base.slice(hashPos).length            : 1;        let pathFromHash = hash.slice(slicePos);        // prepend the starting slash to hash so the url starts with /#        if (pathFromHash[0] !== '/')            pathFromHash = '/' + pathFromHash;        return stripBase(pathFromHash, '');    }    const path = stripBase(pathname, base);    return path + search + hash;}function useHistoryListeners(base, historyState, currentLocation, replace) {    let listeners = [];    let teardowns = [];    // TODO: should it be a stack? a Dict. Check if the popstate listener    // can trigger twice    let pauseState = null;    const popStateHandler = ({ state, }) => {        const to = createCurrentLocation(base, location);        const from = currentLocation.value;        const fromState = historyState.value;        let delta = 0;        if (state) {            currentLocation.value = to;            historyState.value = state;            // ignore the popstate and reset the pauseState            if (pauseState && pauseState === from) {                pauseState = null;                return;            }            delta = fromState ? state.position - fromState.position : 0;        }        else {            replace(to);        }        // console.log({ deltaFromCurrent })        // Here we could also revert the navigation by calling history.go(-delta)        // this listener will have to be adapted to not trigger again and to wait for the url        // to be updated before triggering the listeners. Some kind of validation function would also        // need to be passed to the listeners so the navigation can be accepted        // call all listeners        listeners.forEach(listener => {            listener(currentLocation.value, from, {                delta,                type: NavigationType.pop,                direction: delta                    ? delta > 0                        ? NavigationDirection.forward                        : NavigationDirection.back                    : NavigationDirection.unknown,            });        });    };    function pauseListeners() {        pauseState = currentLocation.value;    }    function listen(callback) {        // set up the listener and prepare teardown callbacks        listeners.push(callback);        const teardown = () => {            const index = listeners.indexOf(callback);            if (index > -1)                listeners.splice(index, 1);        };        teardowns.push(teardown);        return teardown;    }    function beforeUnloadListener() {        const { history } = window;        if (!history.state)            return;        history.replaceState(assign({}, history.state, { scroll: computeScrollPosition() }), '');    }    function destroy() {        for (const teardown of teardowns)            teardown();        teardowns = [];        window.removeEventListener('popstate', popStateHandler);        window.removeEventListener('beforeunload', beforeUnloadListener);    }    // set up the listeners and prepare teardown callbacks    window.addEventListener('popstate', popStateHandler);    window.addEventListener('beforeunload', beforeUnloadListener);    return {        pauseListeners,        listen,        destroy,    };}/** * Creates a state object */function buildState(back, current, forward, replaced = false, computeScroll = false) {    return {        back,        current,        forward,        replaced,        position: window.history.length,        scroll: computeScroll ? computeScrollPosition() : null,    };}function useHistoryStateNavigation(base) {    const { history, location } = window;    // private variables    const currentLocation = {        value: createCurrentLocation(base, location),    };    const historyState = { value: history.state };    // build current history entry as this is a fresh navigation    if (!historyState.value) {        changeLocation(currentLocation.value, {            back: null,            current: currentLocation.value,            forward: null,            // the length is off by one, we need to decrease it            position: history.length - 1,            replaced: true,            // don't add a scroll as the user may have an anchor, and we want            // scrollBehavior to be triggered without a saved position            scroll: null,        }, true);    }    function changeLocation(to, state, replace) {        /**         * if a base tag is provided, and we are on a normal domain, we have to         * respect the provided `base` attribute because pushState() will use it and         * potentially erase anything before the `#` like at         * https://github.com/vuejs/router/issues/685 where a base of         * `/folder/#` but a base of `/` would erase the `/folder/` section. If         * there is no host, the `<base>` tag makes no sense and if there isn't a         * base tag we can just use everything after the `#`.         */        const hashIndex = base.indexOf('#');        const url = hashIndex > -1            ? (location.host && document.querySelector('base')                ? base                : base.slice(hashIndex)) + to            : createBaseLocation() + base + to;        try {            // BROWSER QUIRK            // NOTE: Safari throws a SecurityError when calling this function 100 times in 30 seconds            history[replace ? 'replaceState' : 'pushState'](state, '', url);            historyState.value = state;        }        catch (err) {            {                console.error(err);            }            // Force the navigation, this also resets the call count            location[replace ? 'replace' : 'assign'](url);        }    }    function replace(to, data) {        const state = assign({}, history.state, buildState(historyState.value.back,         // keep back and forward entries but override current position        to, historyState.value.forward, true), data, { position: historyState.value.position });        changeLocation(to, state, true);        currentLocation.value = to;    }    function push(to, data) {        // Add to current entry the information of where we are going        // as well as saving the current position        const currentState = assign({},         // use current history state to gracefully handle a wrong call to        // history.replaceState        // https://github.com/vuejs/router/issues/366        historyState.value, history.state, {            forward: to,            scroll: computeScrollPosition(),        });        changeLocation(currentState.current, currentState, true);        const state = assign({}, buildState(currentLocation.value, to, null), { position: currentState.position + 1 }, data);        changeLocation(to, state, false);        currentLocation.value = to;    }    return {        location: currentLocation,        state: historyState,        push,        replace,    };}/** * Creates an HTML5 history. Most common history for single page applications. * * @param base - */function createWebHistory(base) {    base = normalizeBase(base);    const historyNavigation = useHistoryStateNavigation(base);    const historyListeners = useHistoryListeners(base, historyNavigation.state, historyNavigation.location, historyNavigation.replace);    function go(delta, triggerListeners = true) {        if (!triggerListeners)            historyListeners.pauseListeners();        history.go(delta);    }    const routerHistory = assign({        // it's overridden right after        location: '',        base,        go,        createHref: createHref.bind(null, base),    }, historyNavigation, historyListeners);    Object.defineProperty(routerHistory, 'location', {        enumerable: true,        get: () => historyNavigation.location.value,    });    Object.defineProperty(routerHistory, 'state', {        enumerable: true,        get: () => historyNavigation.state.value,    });    return routerHistory;}/** * Creates an in-memory based history. The main purpose of this history is to handle SSR. It starts in a special location that is nowhere. * It's up to the user to replace that location with the starter location by either calling `router.push` or `router.replace`. * * @param base - Base applied to all urls, defaults to '/' * @returns a history object that can be passed to the router constructor */function createMemoryHistory(base = '') {    let listeners = [];    let queue = [START];    let position = 0;    base = normalizeBase(base);    function setLocation(location) {        position++;        if (position === queue.length) {            // we are at the end, we can simply append a new entry            queue.push(location);        }        else {            // we are in the middle, we remove everything from here in the queue            queue.splice(position);            queue.push(location);        }    }    function triggerListeners(to, from, { direction, delta }) {        const info = {            direction,            delta,            type: NavigationType.pop,        };        for (const callback of listeners) {            callback(to, from, info);        }    }    const routerHistory = {        // rewritten by Object.defineProperty        location: START,        // TODO: should be kept in queue        state: {},        base,        createHref: createHref.bind(null, base),        replace(to) {            // remove current entry and decrement position            queue.splice(position--, 1);            setLocation(to);        },        push(to, data) {            setLocation(to);        },        listen(callback) {            listeners.push(callback);            return () => {                const index = listeners.indexOf(callback);                if (index > -1)                    listeners.splice(index, 1);            };        },        destroy() {            listeners = [];            queue = [START];            position = 0;        },        go(delta, shouldTrigger = true) {            const from = this.location;            const direction =             // we are considering delta === 0 going forward, but in abstract mode            // using 0 for the delta doesn't make sense like it does in html5 where            // it reloads the page            delta < 0 ? NavigationDirection.back : NavigationDirection.forward;            position = Math.max(0, Math.min(position + delta, queue.length - 1));            if (shouldTrigger) {                triggerListeners(this.location, from, {                    direction,                    delta,                });            }        },    };    Object.defineProperty(routerHistory, 'location', {        enumerable: true,        get: () => queue[position],    });    return routerHistory;}/** * Creates a hash history. Useful for web applications with no host (e.g. `file://`) or when configuring a server to * handle any URL is not possible. * * @param base - optional base to provide. Defaults to `location.pathname + location.search` If there is a `<base>` tag * in the `head`, its value will be ignored in favor of this parameter **but note it affects all the history.pushState() * calls**, meaning that if you use a `<base>` tag, it's `href` value **has to match this parameter** (ignoring anything * after the `#`). * * @example * ```js * // at https://example.com/folder * createWebHashHistory() // gives a url of `https://example.com/folder#` * createWebHashHistory('/folder/') // gives a url of `https://example.com/folder/#` * // if the `#` is provided in the base, it won't be added by `createWebHashHistory` * createWebHashHistory('/folder/#/app/') // gives a url of `https://example.com/folder/#/app/` * // you should avoid doing this because it changes the original url and breaks copying urls * createWebHashHistory('/other-folder/') // gives a url of `https://example.com/other-folder/#` * * // at file:///usr/etc/folder/index.html * // for locations with no `host`, the base is ignored * createWebHashHistory('/iAmIgnored') // gives a url of `file:///usr/etc/folder/index.html#` * ``` */function createWebHashHistory(base) {    // Make sure this implementation is fine in terms of encoding, specially for IE11    // for `file://`, directly use the pathname and ignore the base    // location.pathname contains an initial `/` even at the root: `https://example.com`    base = location.host ? base || location.pathname + location.search : '';    // allow the user to provide a `#` in the middle: `/base/#/app`    if (!base.includes('#'))        base += '#';    return createWebHistory(base);}function isRouteLocation(route) {    return typeof route === 'string' || (route && typeof route === 'object');}function isRouteName(name) {    return typeof name === 'string' || typeof name === 'symbol';}/** * Initial route location where the router is. Can be used in navigation guards * to differentiate the initial navigation. * * @example * ```js * import { START_LOCATION } from 'vue-router' * * router.beforeEach((to, from) => { *   if (from === START_LOCATION) { *     // initial navigation *   } * }) * ``` */const START_LOCATION_NORMALIZED = {    path: '/',    name: undefined,    params: {},    query: {},    hash: '',    fullPath: '/',    matched: [],    meta: {},    redirectedFrom: undefined,};const NavigationFailureSymbol = Symbol('');/** * Enumeration with all possible types for navigation failures. Can be passed to * {@link isNavigationFailure} to check for specific failures. */exports.NavigationFailureType = void 0;(function (NavigationFailureType) {    /**     * An aborted navigation is a navigation that failed because a navigation     * guard returned `false` or called `next(false)`     */    NavigationFailureType[NavigationFailureType["aborted"] = 4] = "aborted";    /**     * A cancelled navigation is a navigation that failed because a more recent     * navigation finished started (not necessarily finished).     */    NavigationFailureType[NavigationFailureType["cancelled"] = 8] = "cancelled";    /**     * A duplicated navigation is a navigation that failed because it was     * initiated while already being at the exact same location.     */    NavigationFailureType[NavigationFailureType["duplicated"] = 16] = "duplicated";})(exports.NavigationFailureType || (exports.NavigationFailureType = {}));// DEV only debug messagesconst ErrorTypeMessages = {    [1 /* ErrorTypes.MATCHER_NOT_FOUND */]({ location, currentLocation }) {        return `No match for\n ${JSON.stringify(location)}${currentLocation            ? '\nwhile being at\n' + JSON.stringify(currentLocation)            : ''}`;    },    [2 /* ErrorTypes.NAVIGATION_GUARD_REDIRECT */]({ from, to, }) {        return `Redirected from "${from.fullPath}" to "${stringifyRoute(to)}" via a navigation guard.`;    },    [4 /* ErrorTypes.NAVIGATION_ABORTED */]({ from, to }) {        return `Navigation aborted from "${from.fullPath}" to "${to.fullPath}" via a navigation guard.`;    },    [8 /* ErrorTypes.NAVIGATION_CANCELLED */]({ from, to }) {        return `Navigation cancelled from "${from.fullPath}" to "${to.fullPath}" with a new navigation.`;    },    [16 /* ErrorTypes.NAVIGATION_DUPLICATED */]({ from, to }) {        return `Avoided redundant navigation to current location: "${from.fullPath}".`;    },};function createRouterError(type, params) {    // keep full error messages in cjs versions    {        return assign(new Error(ErrorTypeMessages[type](params)), {            type,            [NavigationFailureSymbol]: true,        }, params);    }}function isNavigationFailure(error, type) {    return (error instanceof Error &&        NavigationFailureSymbol in error &&        (type == null || !!(error.type & type)));}const propertiesToLog = ['params', 'query', 'hash'];function stringifyRoute(to) {    if (typeof to === 'string')        return to;    if ('path' in to)        return to.path;    const location = {};    for (const key of propertiesToLog) {        if (key in to)            location[key] = to[key];    }    return JSON.stringify(location, null, 2);}// default pattern for a param: non-greedy everything but /const BASE_PARAM_PATTERN = '[^/]+?';const BASE_PATH_PARSER_OPTIONS = {    sensitive: false,    strict: false,    start: true,    end: true,};// Special Regex characters that must be escaped in static tokensconst REGEX_CHARS_RE = /[.+*?^${}()[\]/\\]/g;/** * Creates a path parser from an array of Segments (a segment is an array of Tokens) * * @param segments - array of segments returned by tokenizePath * @param extraOptions - optional options for the regexp * @returns a PathParser */function tokensToParser(segments, extraOptions) {    const options = assign({}, BASE_PATH_PARSER_OPTIONS, extraOptions);    // the amount of scores is the same as the length of segments except for the root segment "/"    const score = [];    // the regexp as a string    let pattern = options.start ? '^' : '';    // extracted keys    const keys = [];    for (const segment of segments) {        // the root segment needs special treatment        const segmentScores = segment.length ? [] : [90 /* PathScore.Root */];        // allow trailing slash        if (options.strict && !segment.length)            pattern += '/';        for (let tokenIndex = 0; tokenIndex < segment.length; tokenIndex++) {            const token = segment[tokenIndex];            // resets the score if we are inside a sub-segment /:a-other-:b            let subSegmentScore = 40 /* PathScore.Segment */ +                (options.sensitive ? 0.25 /* PathScore.BonusCaseSensitive */ : 0);            if (token.type === 0 /* TokenType.Static */) {                // prepend the slash if we are starting a new segment                if (!tokenIndex)                    pattern += '/';                pattern += token.value.replace(REGEX_CHARS_RE, '\\$&');                subSegmentScore += 40 /* PathScore.Static */;            }            else if (token.type === 1 /* TokenType.Param */) {                const { value, repeatable, optional, regexp } = token;                keys.push({                    name: value,                    repeatable,                    optional,                });                const re = regexp ? regexp : BASE_PARAM_PATTERN;                // the user provided a custom regexp /:id(\\d+)                if (re !== BASE_PARAM_PATTERN) {                    subSegmentScore += 10 /* PathScore.BonusCustomRegExp */;                    // make sure the regexp is valid before using it                    try {                        new RegExp(`(${re})`);                    }                    catch (err) {                        throw new Error(`Invalid custom RegExp for param "${value}" (${re}): ` +                            err.message);                    }                }                // when we repeat we must take care of the repeating leading slash                let subPattern = repeatable ? `((?:${re})(?:/(?:${re}))*)` : `(${re})`;                // prepend the slash if we are starting a new segment                if (!tokenIndex)                    subPattern =                        // avoid an optional / if there are more segments e.g. /:p?-static                        // or /:p?-:p2                        optional && segment.length < 2                            ? `(?:/${subPattern})`                            : '/' + subPattern;                if (optional)                    subPattern += '?';                pattern += subPattern;                subSegmentScore += 20 /* PathScore.Dynamic */;                if (optional)                    subSegmentScore += -8 /* PathScore.BonusOptional */;                if (repeatable)                    subSegmentScore += -20 /* PathScore.BonusRepeatable */;                if (re === '.*')                    subSegmentScore += -50 /* PathScore.BonusWildcard */;            }            segmentScores.push(subSegmentScore);        }        // an empty array like /home/ -> [[{home}], []]        // if (!segment.length) pattern += '/'        score.push(segmentScores);    }    // only apply the strict bonus to the last score    if (options.strict && options.end) {        const i = score.length - 1;        score[i][score[i].length - 1] += 0.7000000000000001 /* PathScore.BonusStrict */;    }    // TODO: dev only warn double trailing slash    if (!options.strict)        pattern += '/?';    if (options.end)        pattern += '$';    // allow paths like /dynamic to only match dynamic or dynamic/... but not dynamic_something_else    else if (options.strict)        pattern += '(?:/|$)';    const re = new RegExp(pattern, options.sensitive ? '' : 'i');    function parse(path) {        const match = path.match(re);        const params = {};        if (!match)            return null;        for (let i = 1; i < match.length; i++) {            const value = match[i] || '';            const key = keys[i - 1];            params[key.name] = value && key.repeatable ? value.split('/') : value;        }        return params;    }    function stringify(params) {        let path = '';        // for optional parameters to allow to be empty        let avoidDuplicatedSlash = false;        for (const segment of segments) {            if (!avoidDuplicatedSlash || !path.endsWith('/'))                path += '/';            avoidDuplicatedSlash = false;            for (const token of segment) {                if (token.type === 0 /* TokenType.Static */) {                    path += token.value;                }                else if (token.type === 1 /* TokenType.Param */) {                    const { value, repeatable, optional } = token;                    const param = value in params ? params[value] : '';                    if (isArray(param) && !repeatable) {                        throw new Error(`Provided param "${value}" is an array but it is not repeatable (* or + modifiers)`);                    }                    const text = isArray(param)                        ? param.join('/')                        : param;                    if (!text) {                        if (optional) {                            // if we have more than one optional param like /:a?-static we don't need to care about the optional param                            if (segment.length < 2) {                                // remove the last slash as we could be at the end                                if (path.endsWith('/'))                                    path = path.slice(0, -1);                                // do not append a slash on the next iteration                                else                                    avoidDuplicatedSlash = true;                            }                        }                        else                            throw new Error(`Missing required param "${value}"`);                    }                    path += text;                }            }        }        // avoid empty path when we have multiple optional params        return path || '/';    }    return {        re,        score,        keys,        parse,        stringify,    };}/** * Compares an array of numbers as used in PathParser.score and returns a * number. This function can be used to `sort` an array * * @param a - first array of numbers * @param b - second array of numbers * @returns 0 if both are equal, < 0 if a should be sorted first, > 0 if b * should be sorted first */function compareScoreArray(a, b) {    let i = 0;    while (i < a.length && i < b.length) {        const diff = b[i] - a[i];        // only keep going if diff === 0        if (diff)            return diff;        i++;    }    // if the last subsegment was Static, the shorter segments should be sorted first    // otherwise sort the longest segment first    if (a.length < b.length) {        return a.length === 1 && a[0] === 40 /* PathScore.Static */ + 40 /* PathScore.Segment */            ? -1            : 1;    }    else if (a.length > b.length) {        return b.length === 1 && b[0] === 40 /* PathScore.Static */ + 40 /* PathScore.Segment */            ? 1            : -1;    }    return 0;}/** * Compare function that can be used with `sort` to sort an array of PathParser * * @param a - first PathParser * @param b - second PathParser * @returns 0 if both are equal, < 0 if a should be sorted first, > 0 if b */function comparePathParserScore(a, b) {    let i = 0;    const aScore = a.score;    const bScore = b.score;    while (i < aScore.length && i < bScore.length) {        const comp = compareScoreArray(aScore[i], bScore[i]);        // do not return if both are equal        if (comp)            return comp;        i++;    }    if (Math.abs(bScore.length - aScore.length) === 1) {        if (isLastScoreNegative(aScore))            return 1;        if (isLastScoreNegative(bScore))            return -1;    }    // if a and b share the same score entries but b has more, sort b first    return bScore.length - aScore.length;    // this is the ternary version    // return aScore.length < bScore.length    //   ? 1    //   : aScore.length > bScore.length    //   ? -1    //   : 0}/** * This allows detecting splats at the end of a path: /home/:id(.*)* * * @param score - score to check * @returns true if the last entry is negative */function isLastScoreNegative(score) {    const last = score[score.length - 1];    return score.length > 0 && last[last.length - 1] < 0;}const ROOT_TOKEN = {    type: 0 /* TokenType.Static */,    value: '',};const VALID_PARAM_RE = /[a-zA-Z0-9_]/;// After some profiling, the cache seems to be unnecessary because tokenizePath// (the slowest part of adding a route) is very fast// const tokenCache = new Map<string, Token[][]>()function tokenizePath(path) {    if (!path)        return [[]];    if (path === '/')        return [[ROOT_TOKEN]];    if (!path.startsWith('/')) {        throw new Error(`Invalid path "${path}"`);    }    // if (tokenCache.has(path)) return tokenCache.get(path)!    function crash(message) {        throw new Error(`ERR (${state})/"${buffer}": ${message}`);    }    let state = 0 /* TokenizerState.Static */;    let previousState = state;    const tokens = [];    // the segment will always be valid because we get into the initial state    // with the leading /    let segment;    function finalizeSegment() {        if (segment)            tokens.push(segment);        segment = [];    }    // index on the path    let i = 0;    // char at index    let char;    // buffer of the value read    let buffer = '';    // custom regexp for a param    let customRe = '';    function consumeBuffer() {        if (!buffer)            return;        if (state === 0 /* TokenizerState.Static */) {            segment.push({                type: 0 /* TokenType.Static */,                value: buffer,            });        }        else if (state === 1 /* TokenizerState.Param */ ||            state === 2 /* TokenizerState.ParamRegExp */ ||            state === 3 /* TokenizerState.ParamRegExpEnd */) {            if (segment.length > 1 && (char === '*' || char === '+'))                crash(`A repeatable param (${buffer}) must be alone in its segment. eg: '/:ids+.`);            segment.push({                type: 1 /* TokenType.Param */,                value: buffer,                regexp: customRe,                repeatable: char === '*' || char === '+',                optional: char === '*' || char === '?',            });        }        else {            crash('Invalid state to consume buffer');        }        buffer = '';    }    function addCharToBuffer() {        buffer += char;    }    while (i < path.length) {        char = path[i++];        if (char === '\\' && state !== 2 /* TokenizerState.ParamRegExp */) {            previousState = state;            state = 4 /* TokenizerState.EscapeNext */;            continue;        }        switch (state) {            case 0 /* TokenizerState.Static */:                if (char === '/') {                    if (buffer) {                        consumeBuffer();                    }                    finalizeSegment();                }                else if (char === ':') {                    consumeBuffer();                    state = 1 /* TokenizerState.Param */;                }                else {                    addCharToBuffer();                }                break;            case 4 /* TokenizerState.EscapeNext */:                addCharToBuffer();                state = previousState;                break;            case 1 /* TokenizerState.Param */:                if (char === '(') {                    state = 2 /* TokenizerState.ParamRegExp */;                }                else if (VALID_PARAM_RE.test(char)) {                    addCharToBuffer();                }                else {                    consumeBuffer();                    state = 0 /* TokenizerState.Static */;                    // go back one character if we were not modifying                    if (char !== '*' && char !== '?' && char !== '+')                        i--;                }                break;            case 2 /* TokenizerState.ParamRegExp */:                // TODO: is it worth handling nested regexp? like :p(?:prefix_([^/]+)_suffix)                // it already works by escaping the closing )                // https://paths.esm.dev/?p=AAMeJbiAwQEcDKbAoAAkP60PG2R6QAvgNaA6AFACM2ABuQBB#                // is this really something people need since you can also write                // /prefix_:p()_suffix                if (char === ')') {                    // handle the escaped )                    if (customRe[customRe.length - 1] == '\\')                        customRe = customRe.slice(0, -1) + char;                    else                        state = 3 /* TokenizerState.ParamRegExpEnd */;                }                else {                    customRe += char;                }                break;            case 3 /* TokenizerState.ParamRegExpEnd */:                // same as finalizing a param                consumeBuffer();                state = 0 /* TokenizerState.Static */;                // go back one character if we were not modifying                if (char !== '*' && char !== '?' && char !== '+')                    i--;                customRe = '';                break;            default:                crash('Unknown state');                break;        }    }    if (state === 2 /* TokenizerState.ParamRegExp */)        crash(`Unfinished custom RegExp for param "${buffer}"`);    consumeBuffer();    finalizeSegment();    // tokenCache.set(path, tokens)    return tokens;}function createRouteRecordMatcher(record, parent, options) {    const parser = tokensToParser(tokenizePath(record.path), options);    const matcher = assign(parser, {        record,        parent,        // these needs to be populated by the parent        children: [],        alias: [],    });    if (parent) {        // both are aliases or both are not aliases        // we don't want to mix them because the order is used when        // passing originalRecord in Matcher.addRoute        if (!matcher.record.aliasOf === !parent.record.aliasOf)            parent.children.push(matcher);    }    return matcher;}/** * Creates a Router Matcher. * * @internal * @param routes - array of initial routes * @param globalOptions - global route options */function createRouterMatcher(routes, globalOptions) {    // normalized ordered array of matchers    const matchers = [];    const matcherMap = new Map();    globalOptions = mergeOptions({ strict: false, end: true, sensitive: false }, globalOptions);    function getRecordMatcher(name) {        return matcherMap.get(name);    }    function addRoute(record, parent, originalRecord) {        // used later on to remove by name        const isRootAdd = !originalRecord;        const mainNormalizedRecord = normalizeRouteRecord(record);        // we might be the child of an alias        mainNormalizedRecord.aliasOf = originalRecord && originalRecord.record;        const options = mergeOptions(globalOptions, record);        // generate an array of records to correctly handle aliases        const normalizedRecords = [            mainNormalizedRecord,        ];        if ('alias' in record) {            const aliases = typeof record.alias === 'string' ? [record.alias] : record.alias;            for (const alias of aliases) {                normalizedRecords.push(assign({}, mainNormalizedRecord, {                    // this allows us to hold a copy of the `components` option                    // so that async components cache is hold on the original record                    components: originalRecord                        ? originalRecord.record.components                        : mainNormalizedRecord.components,                    path: alias,                    // we might be the child of an alias                    aliasOf: originalRecord                        ? originalRecord.record                        : mainNormalizedRecord,                    // the aliases are always of the same kind as the original since they                    // are defined on the same record                }));            }        }        let matcher;        let originalMatcher;        for (const normalizedRecord of normalizedRecords) {            const { path } = normalizedRecord;            // Build up the path for nested routes if the child isn't an absolute            // route. Only add the / delimiter if the child path isn't empty and if the            // parent path doesn't have a trailing slash            if (parent && path[0] !== '/') {                const parentPath = parent.record.path;                const connectingSlash = parentPath[parentPath.length - 1] === '/' ? '' : '/';                normalizedRecord.path =                    parent.record.path + (path && connectingSlash + path);            }            // create the object beforehand, so it can be passed to children            matcher = createRouteRecordMatcher(normalizedRecord, parent, options);            // if we are an alias we must tell the original record that we exist,            // so we can be removed            if (originalRecord) {                originalRecord.alias.push(matcher);            }            else {                // otherwise, the first record is the original and others are aliases                originalMatcher = originalMatcher || matcher;                if (originalMatcher !== matcher)                    originalMatcher.alias.push(matcher);                // remove the route if named and only for the top record (avoid in nested calls)                // this works because the original record is the first one                if (isRootAdd && record.name && !isAliasRecord(matcher))                    removeRoute(record.name);            }            if (mainNormalizedRecord.children) {                const children = mainNormalizedRecord.children;                for (let i = 0; i < children.length; i++) {                    addRoute(children[i], matcher, originalRecord && originalRecord.children[i]);                }            }            // if there was no original record, then the first one was not an alias and all            // other aliases (if any) need to reference this record when adding children            originalRecord = originalRecord || matcher;            // TODO: add normalized records for more flexibility            // if (parent && isAliasRecord(originalRecord)) {            //   parent.children.push(originalRecord)            // }            // Avoid adding a record that doesn't display anything. This allows passing through records without a component to            // not be reached and pass through the catch all route            if ((matcher.record.components &&                Object.keys(matcher.record.components).length) ||                matcher.record.name ||                matcher.record.redirect) {                insertMatcher(matcher);            }        }        return originalMatcher            ? () => {                // since other matchers are aliases, they should be removed by the original matcher                removeRoute(originalMatcher);            }            : noop;    }    function removeRoute(matcherRef) {        if (isRouteName(matcherRef)) {            const matcher = matcherMap.get(matcherRef);            if (matcher) {                matcherMap.delete(matcherRef);                matchers.splice(matchers.indexOf(matcher), 1);                matcher.children.forEach(removeRoute);                matcher.alias.forEach(removeRoute);            }        }        else {            const index = matchers.indexOf(matcherRef);            if (index > -1) {                matchers.splice(index, 1);                if (matcherRef.record.name)                    matcherMap.delete(matcherRef.record.name);                matcherRef.children.forEach(removeRoute);                matcherRef.alias.forEach(removeRoute);            }        }    }    function getRoutes() {        return matchers;    }    function insertMatcher(matcher) {        let i = 0;        while (i < matchers.length &&            comparePathParserScore(matcher, matchers[i]) >= 0 &&            // Adding children with empty path should still appear before the parent            // https://github.com/vuejs/router/issues/1124            (matcher.record.path !== matchers[i].record.path ||                !isRecordChildOf(matcher, matchers[i])))            i++;        matchers.splice(i, 0, matcher);        // only add the original record to the name map        if (matcher.record.name && !isAliasRecord(matcher))            matcherMap.set(matcher.record.name, matcher);    }    function resolve(location, currentLocation) {        let matcher;        let params = {};        let path;        let name;        if ('name' in location && location.name) {            matcher = matcherMap.get(location.name);            if (!matcher)                throw createRouterError(1 /* ErrorTypes.MATCHER_NOT_FOUND */, {                    location,                });            name = matcher.record.name;            params = assign(            // paramsFromLocation is a new object            paramsFromLocation(currentLocation.params,             // only keep params that exist in the resolved location            // TODO: only keep optional params coming from a parent record            matcher.keys.filter(k => !k.optional).map(k => k.name)),             // discard any existing params in the current location that do not exist here            // #1497 this ensures better active/exact matching            location.params &&                paramsFromLocation(location.params, matcher.keys.map(k => k.name)));            // throws if cannot be stringified            path = matcher.stringify(params);        }        else if ('path' in location) {            // no need to resolve the path with the matcher as it was provided            // this also allows the user to control the encoding            path = location.path;            matcher = matchers.find(m => m.re.test(path));            // matcher should have a value after the loop            if (matcher) {                // we know the matcher works because we tested the regexp                params = matcher.parse(path);                name = matcher.record.name;            }            // location is a relative path        }        else {            // match by name or path of current route            matcher = currentLocation.name                ? matcherMap.get(currentLocation.name)                : matchers.find(m => m.re.test(currentLocation.path));            if (!matcher)                throw createRouterError(1 /* ErrorTypes.MATCHER_NOT_FOUND */, {                    location,                    currentLocation,                });            name = matcher.record.name;            // since we are navigating to the same location, we don't need to pick the            // params like when `name` is provided            params = assign({}, currentLocation.params, location.params);            path = matcher.stringify(params);        }        const matched = [];        let parentMatcher = matcher;        while (parentMatcher) {            // reversed order so parents are at the beginning            matched.unshift(parentMatcher.record);            parentMatcher = parentMatcher.parent;        }        return {            name,            path,            params,            matched,            meta: mergeMetaFields(matched),        };    }    // add initial routes    routes.forEach(route => addRoute(route));    return { addRoute, resolve, removeRoute, getRoutes, getRecordMatcher };}function paramsFromLocation(params, keys) {    const newParams = {};    for (const key of keys) {        if (key in params)            newParams[key] = params[key];    }    return newParams;}/** * Normalizes a RouteRecordRaw. Creates a copy * * @param record * @returns the normalized version */function normalizeRouteRecord(record) {    return {        path: record.path,        redirect: record.redirect,        name: record.name,        meta: record.meta || {},        aliasOf: undefined,        beforeEnter: record.beforeEnter,        props: normalizeRecordProps(record),        children: record.children || [],        instances: {},        leaveGuards: new Set(),        updateGuards: new Set(),        enterCallbacks: {},        components: 'components' in record            ? record.components || null            : record.component && { default: record.component },    };}/** * Normalize the optional `props` in a record to always be an object similar to * components. Also accept a boolean for components. * @param record */function normalizeRecordProps(record) {    const propsObject = {};    // props does not exist on redirect records, but we can set false directly    const props = record.props || false;    if ('component' in record) {        propsObject.default = props;    }    else {        // NOTE: we could also allow a function to be applied to every component.        // Would need user feedback for use cases        for (const name in record.components)            propsObject[name] = typeof props === 'boolean' ? props : props[name];    }    return propsObject;}/** * Checks if a record or any of its parent is an alias * @param record */function isAliasRecord(record) {    while (record) {        if (record.record.aliasOf)            return true;        record = record.parent;    }    return false;}/** * Merge meta fields of an array of records * * @param matched - array of matched records */function mergeMetaFields(matched) {    return matched.reduce((meta, record) => assign(meta, record.meta), {});}function mergeOptions(defaults, partialOptions) {    const options = {};    for (const key in defaults) {        options[key] = key in partialOptions ? partialOptions[key] : defaults[key];    }    return options;}function isRecordChildOf(record, parent) {    return parent.children.some(child => child === record || isRecordChildOf(record, child));}/** * Encoding Rules ␣ = Space Path: ␣ " < > # ? { } Query: ␣ " < > # & = Hash: ␣ " * < > ` * * On top of that, the RFC3986 (https://tools.ietf.org/html/rfc3986#section-2.2) * defines some extra characters to be encoded. Most browsers do not encode them * in encodeURI https://github.com/whatwg/url/issues/369, so it may be safer to * also encode `!'()*`. Leaving un-encoded only ASCII alphanumeric(`a-zA-Z0-9`) * plus `-._~`. This extra safety should be applied to query by patching the * string returned by encodeURIComponent encodeURI also encodes `[\]^`. `\` * should be encoded to avoid ambiguity. Browsers (IE, FF, C) transform a `\` * into a `/` if directly typed in. The _backtick_ (`````) should also be * encoded everywhere because some browsers like FF encode it when directly * written while others don't. Safari and IE don't encode ``"<>{}``` in hash. */// const EXTRA_RESERVED_RE = /[!'()*]/g// const encodeReservedReplacer = (c: string) => '%' + c.charCodeAt(0).toString(16)const HASH_RE = /#/g; // %23const AMPERSAND_RE = /&/g; // %26const SLASH_RE = /\//g; // %2Fconst EQUAL_RE = /=/g; // %3Dconst IM_RE = /\?/g; // %3Fconst PLUS_RE = /\+/g; // %2B/** * NOTE: It's not clear to me if we should encode the + symbol in queries, it * seems to be less flexible than not doing so and I can't find out the legacy * systems requiring this for regular requests like text/html. In the standard, * the encoding of the plus character is only mentioned for * application/x-www-form-urlencoded * (https://url.spec.whatwg.org/#urlencoded-parsing) and most browsers seems lo * leave the plus character as is in queries. To be more flexible, we allow the * plus character on the query, but it can also be manually encoded by the user. * * Resources: * - https://url.spec.whatwg.org/#urlencoded-parsing * - https://stackoverflow.com/questions/1634271/url-encoding-the-space-character-or-20 */const ENC_BRACKET_OPEN_RE = /%5B/g; // [const ENC_BRACKET_CLOSE_RE = /%5D/g; // ]const ENC_CARET_RE = /%5E/g; // ^const ENC_BACKTICK_RE = /%60/g; // `const ENC_CURLY_OPEN_RE = /%7B/g; // {const ENC_PIPE_RE = /%7C/g; // |const ENC_CURLY_CLOSE_RE = /%7D/g; // }const ENC_SPACE_RE = /%20/g; // }/** * Encode characters that need to be encoded on the path, search and hash * sections of the URL. * * @internal * @param text - string to encode * @returns encoded string */function commonEncode(text) {    return encodeURI('' + text)        .replace(ENC_PIPE_RE, '|')        .replace(ENC_BRACKET_OPEN_RE, '[')        .replace(ENC_BRACKET_CLOSE_RE, ']');}/** * Encode characters that need to be encoded on the hash section of the URL. * * @param text - string to encode * @returns encoded string */function encodeHash(text) {    return commonEncode(text)        .replace(ENC_CURLY_OPEN_RE, '{')        .replace(ENC_CURLY_CLOSE_RE, '}')        .replace(ENC_CARET_RE, '^');}/** * Encode characters that need to be encoded query values on the query * section of the URL. * * @param text - string to encode * @returns encoded string */function encodeQueryValue(text) {    return (commonEncode(text)        // Encode the space as +, encode the + to differentiate it from the space        .replace(PLUS_RE, '%2B')        .replace(ENC_SPACE_RE, '+')        .replace(HASH_RE, '%23')        .replace(AMPERSAND_RE, '%26')        .replace(ENC_BACKTICK_RE, '`')        .replace(ENC_CURLY_OPEN_RE, '{')        .replace(ENC_CURLY_CLOSE_RE, '}')        .replace(ENC_CARET_RE, '^'));}/** * Like `encodeQueryValue` but also encodes the `=` character. * * @param text - string to encode */function encodeQueryKey(text) {    return encodeQueryValue(text).replace(EQUAL_RE, '%3D');}/** * Encode characters that need to be encoded on the path section of the URL. * * @param text - string to encode * @returns encoded string */function encodePath(text) {    return commonEncode(text).replace(HASH_RE, '%23').replace(IM_RE, '%3F');}/** * Encode characters that need to be encoded on the path section of the URL as a * param. This function encodes everything {@link encodePath} does plus the * slash (`/`) character. If `text` is `null` or `undefined`, returns an empty * string instead. * * @param text - string to encode * @returns encoded string */function encodeParam(text) {    return text == null ? '' : encodePath(text).replace(SLASH_RE, '%2F');}/** * Decode text using `decodeURIComponent`. Returns the original text if it * fails. * * @param text - string to decode * @returns decoded string */function decode(text) {    try {        return decodeURIComponent('' + text);    }    catch (err) {    }    return '' + text;}/** * Transforms a queryString into a {@link LocationQuery} object. Accept both, a * version with the leading `?` and without Should work as URLSearchParams * @internal * * @param search - search string to parse * @returns a query object */function parseQuery(search) {    const query = {};    // avoid creating an object with an empty key and empty value    // because of split('&')    if (search === '' || search === '?')        return query;    const hasLeadingIM = search[0] === '?';    const searchParams = (hasLeadingIM ? search.slice(1) : search).split('&');    for (let i = 0; i < searchParams.length; ++i) {        // pre decode the + into space        const searchParam = searchParams[i].replace(PLUS_RE, ' ');        // allow the = character        const eqPos = searchParam.indexOf('=');        const key = decode(eqPos < 0 ? searchParam : searchParam.slice(0, eqPos));        const value = eqPos < 0 ? null : decode(searchParam.slice(eqPos + 1));        if (key in query) {            // an extra variable for ts types            let currentValue = query[key];            if (!isArray(currentValue)) {                currentValue = query[key] = [currentValue];            }            currentValue.push(value);        }        else {            query[key] = value;        }    }    return query;}/** * Stringifies a {@link LocationQueryRaw} object. Like `URLSearchParams`, it * doesn't prepend a `?` * * @internal * * @param query - query object to stringify * @returns string version of the query without the leading `?` */function stringifyQuery(query) {    let search = '';    for (let key in query) {        const value = query[key];        key = encodeQueryKey(key);        if (value == null) {            // only null adds the value            if (value !== undefined) {                search += (search.length ? '&' : '') + key;            }            continue;        }        // keep null values        const values = isArray(value)            ? value.map(v => v && encodeQueryValue(v))            : [value && encodeQueryValue(value)];        values.forEach(value => {            // skip undefined values in arrays as if they were not present            // smaller code than using filter            if (value !== undefined) {                // only append & with non-empty search                search += (search.length ? '&' : '') + key;                if (value != null)                    search += '=' + value;            }        });    }    return search;}/** * Transforms a {@link LocationQueryRaw} into a {@link LocationQuery} by casting * numbers into strings, removing keys with an undefined value and replacing * undefined with null in arrays * * @param query - query object to normalize * @returns a normalized query object */function normalizeQuery(query) {    const normalizedQuery = {};    for (const key in query) {        const value = query[key];        if (value !== undefined) {            normalizedQuery[key] = isArray(value)                ? value.map(v => (v == null ? null : '' + v))                : value == null                    ? value                    : '' + value;        }    }    return normalizedQuery;}/** * RouteRecord being rendered by the closest ancestor Router View. Used for * `onBeforeRouteUpdate` and `onBeforeRouteLeave`. rvlm stands for Router View * Location Matched * * @internal */const matchedRouteKey = Symbol('');/** * Allows overriding the router view depth to control which component in * `matched` is rendered. rvd stands for Router View Depth * * @internal */const viewDepthKey = Symbol('');/** * Allows overriding the router instance returned by `useRouter` in tests. r * stands for router * * @internal */const routerKey = Symbol('');/** * Allows overriding the current route returned by `useRoute` in tests. rl * stands for route location * * @internal */const routeLocationKey = Symbol('');/** * Allows overriding the current route used by router-view. Internally this is * used when the `route` prop is passed. * * @internal */const routerViewLocationKey = Symbol('');/** * Create a list of callbacks that can be reset. Used to create before and after navigation guards list */function useCallbacks() {    let handlers = [];    function add(handler) {        handlers.push(handler);        return () => {            const i = handlers.indexOf(handler);            if (i > -1)                handlers.splice(i, 1);        };    }    function reset() {        handlers = [];    }    return {        add,        list: () => handlers,        reset,    };}function registerGuard(record, name, guard) {    const removeFromList = () => {        record[name].delete(guard);    };    vue.onUnmounted(removeFromList);    vue.onDeactivated(removeFromList);    vue.onActivated(() => {        record[name].add(guard);    });    record[name].add(guard);}/** * Add a navigation guard that triggers whenever the component for the current * location is about to be left. Similar to {@link beforeRouteLeave} but can be * used in any component. The guard is removed when the component is unmounted. * * @param leaveGuard - {@link NavigationGuard} */function onBeforeRouteLeave(leaveGuard) {    const activeRecord = vue.inject(matchedRouteKey,     // to avoid warning    {}).value;    if (!activeRecord) {        return;    }    registerGuard(activeRecord, 'leaveGuards', leaveGuard);}/** * Add a navigation guard that triggers whenever the current location is about * to be updated. Similar to {@link beforeRouteUpdate} but can be used in any * component. The guard is removed when the component is unmounted. * * @param updateGuard - {@link NavigationGuard} */function onBeforeRouteUpdate(updateGuard) {    const activeRecord = vue.inject(matchedRouteKey,     // to avoid warning    {}).value;    if (!activeRecord) {        return;    }    registerGuard(activeRecord, 'updateGuards', updateGuard);}function guardToPromiseFn(guard, to, from, record, name) {    // keep a reference to the enterCallbackArray to prevent pushing callbacks if a new navigation took place    const enterCallbackArray = record &&        // name is defined if record is because of the function overload        (record.enterCallbacks[name] = record.enterCallbacks[name] || []);    return () => new Promise((resolve, reject) => {        const next = (valid) => {            if (valid === false) {                reject(createRouterError(4 /* ErrorTypes.NAVIGATION_ABORTED */, {                    from,                    to,                }));            }            else if (valid instanceof Error) {                reject(valid);            }            else if (isRouteLocation(valid)) {                reject(createRouterError(2 /* ErrorTypes.NAVIGATION_GUARD_REDIRECT */, {                    from: to,                    to: valid,                }));            }            else {                if (enterCallbackArray &&                    // since enterCallbackArray is truthy, both record and name also are                    record.enterCallbacks[name] === enterCallbackArray &&                    typeof valid === 'function') {                    enterCallbackArray.push(valid);                }                resolve();            }        };        // wrapping with Promise.resolve allows it to work with both async and sync guards        const guardReturn = guard.call(record && record.instances[name], to, from, next);        let guardCall = Promise.resolve(guardReturn);        if (guard.length < 3)            guardCall = guardCall.then(next);        guardCall.catch(err => reject(err));    });}function extractComponentsGuards(matched, guardType, to, from) {    const guards = [];    for (const record of matched) {        for (const name in record.components) {            let rawComponent = record.components[name];            // skip update and leave guards if the route component is not mounted            if (guardType !== 'beforeRouteEnter' && !record.instances[name])                continue;            if (isRouteComponent(rawComponent)) {                // __vccOpts is added by vue-class-component and contain the regular options                const options = rawComponent.__vccOpts || rawComponent;                const guard = options[guardType];                guard && guards.push(guardToPromiseFn(guard, to, from, record, name));            }            else {                // start requesting the chunk already                let componentPromise = rawComponent();                guards.push(() => componentPromise.then(resolved => {                    if (!resolved)                        return Promise.reject(new Error(`Couldn't resolve component "${name}" at "${record.path}"`));                    const resolvedComponent = isESModule(resolved)                        ? resolved.default                        : resolved;                    // replace the function with the resolved component                    // cannot be null or undefined because we went into the for loop                    record.components[name] = resolvedComponent;                    // __vccOpts is added by vue-class-component and contain the regular options                    const options = resolvedComponent.__vccOpts || resolvedComponent;                    const guard = options[guardType];                    return guard && guardToPromiseFn(guard, to, from, record, name)();                }));            }        }    }    return guards;}/** * Allows differentiating lazy components from functional components and vue-class-component * @internal * * @param component */function isRouteComponent(component) {    return (typeof component === 'object' ||        'displayName' in component ||        'props' in component ||        '__vccOpts' in component);}/** * Ensures a route is loaded, so it can be passed as o prop to `<RouterView>`. * * @param route - resolved route to load */function loadRouteLocation(route) {    return route.matched.every(record => record.redirect)        ? Promise.reject(new Error('Cannot load a route that redirects.'))        : Promise.all(route.matched.map(record => record.components &&            Promise.all(Object.keys(record.components).reduce((promises, name) => {                const rawComponent = record.components[name];                if (typeof rawComponent === 'function' &&                    !('displayName' in rawComponent)) {                    promises.push(rawComponent().then(resolved => {                        if (!resolved)                            return Promise.reject(new Error(`Couldn't resolve component "${name}" at "${record.path}". Ensure you passed a function that returns a promise.`));                        const resolvedComponent = isESModule(resolved)                            ? resolved.default                            : resolved;                        // replace the function with the resolved component                        // cannot be null or undefined because we went into the for loop                        record.components[name] = resolvedComponent;                        return;                    }));                }                return promises;            }, [])))).then(() => route);}// TODO: we could allow currentRoute as a prop to expose `isActive` and// `isExactActive` behavior should go through an RFCfunction useLink(props) {    const router = vue.inject(routerKey);    const currentRoute = vue.inject(routeLocationKey);    const route = vue.computed(() => router.resolve(vue.unref(props.to)));    const activeRecordIndex = vue.computed(() => {        const { matched } = route.value;        const { length } = matched;        const routeMatched = matched[length - 1];        const currentMatched = currentRoute.matched;        if (!routeMatched || !currentMatched.length)            return -1;        const index = currentMatched.findIndex(isSameRouteRecord.bind(null, routeMatched));        if (index > -1)            return index;        // possible parent record        const parentRecordPath = getOriginalPath(matched[length - 2]);        return (        // we are dealing with nested routes        length > 1 &&            // if the parent and matched route have the same path, this link is            // referring to the empty child. Or we currently are on a different            // child of the same parent            getOriginalPath(routeMatched) === parentRecordPath &&            // avoid comparing the child with its parent            currentMatched[currentMatched.length - 1].path !== parentRecordPath            ? currentMatched.findIndex(isSameRouteRecord.bind(null, matched[length - 2]))            : index);    });    const isActive = vue.computed(() => activeRecordIndex.value > -1 &&        includesParams(currentRoute.params, route.value.params));    const isExactActive = vue.computed(() => activeRecordIndex.value > -1 &&        activeRecordIndex.value === currentRoute.matched.length - 1 &&        isSameRouteLocationParams(currentRoute.params, route.value.params));    function navigate(e = {}) {        if (guardEvent(e)) {            return router[vue.unref(props.replace) ? 'replace' : 'push'](vue.unref(props.to)            // avoid uncaught errors are they are logged anyway            ).catch(noop);        }        return Promise.resolve();    }    /**     * NOTE: update {@link _RouterLinkI}'s `$slots` type when updating this     */    return {        route,        href: vue.computed(() => route.value.href),        isActive,        isExactActive,        navigate,    };}const RouterLinkImpl = /*#__PURE__*/ vue.defineComponent({    name: 'RouterLink',    compatConfig: { MODE: 3 },    props: {        to: {            type: [String, Object],            required: true,        },        replace: Boolean,        activeClass: String,        // inactiveClass: String,        exactActiveClass: String,        custom: Boolean,        ariaCurrentValue: {            type: String,            default: 'page',        },    },    useLink,    setup(props, { slots }) {        const link = vue.reactive(useLink(props));        const { options } = vue.inject(routerKey);        const elClass = vue.computed(() => ({            [getLinkClass(props.activeClass, options.linkActiveClass, 'router-link-active')]: link.isActive,            // [getLinkClass(            //   props.inactiveClass,            //   options.linkInactiveClass,            //   'router-link-inactive'            // )]: !link.isExactActive,            [getLinkClass(props.exactActiveClass, options.linkExactActiveClass, 'router-link-exact-active')]: link.isExactActive,        }));        return () => {            const children = slots.default && slots.default(link);            return props.custom                ? children                : vue.h('a', {                    'aria-current': link.isExactActive                        ? props.ariaCurrentValue                        : null,                    href: link.href,                    // this would override user added attrs but Vue will still add                    // the listener, so we end up triggering both                    onClick: link.navigate,                    class: elClass.value,                }, children);        };    },});// export the public type for h/tsx inference// also to avoid inline import() in generated d.ts files/** * Component to render a link that triggers a navigation on click. */const RouterLink = RouterLinkImpl;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"`    // @ts-expect-error getAttribute does exist    if (e.currentTarget && e.currentTarget.getAttribute) {        // @ts-expect-error getAttribute exists        const target = e.currentTarget.getAttribute('target');        if (/\b_blank\b/i.test(target))            return;    }    // this may be a Weex event which doesn't have this method    if (e.preventDefault)        e.preventDefault();    return true;}function includesParams(outer, inner) {    for (const key in inner) {        const innerValue = inner[key];        const outerValue = outer[key];        if (typeof innerValue === 'string') {            if (innerValue !== outerValue)                return false;        }        else {            if (!isArray(outerValue) ||                outerValue.length !== innerValue.length ||                innerValue.some((value, i) => value !== outerValue[i]))                return false;        }    }    return true;}/** * Get the original path value of a record by following its aliasOf * @param record */function getOriginalPath(record) {    return record ? (record.aliasOf ? record.aliasOf.path : record.path) : '';}/** * Utility class to get the active class based on defaults. * @param propClass * @param globalClass * @param defaultClass */const getLinkClass = (propClass, globalClass, defaultClass) => propClass != null    ? propClass    : globalClass != null        ? globalClass        : defaultClass;const RouterViewImpl = /*#__PURE__*/ vue.defineComponent({    name: 'RouterView',    // #674 we manually inherit them    inheritAttrs: false,    props: {        name: {            type: String,            default: 'default',        },        route: Object,    },    // Better compat for @vue/compat users    // https://github.com/vuejs/router/issues/1315    compatConfig: { MODE: 3 },    setup(props, { attrs, slots }) {        const injectedRoute = vue.inject(routerViewLocationKey);        const routeToDisplay = vue.computed(() => props.route || injectedRoute.value);        const injectedDepth = vue.inject(viewDepthKey, 0);        // The depth changes based on empty components option, which allows passthrough routes e.g. routes with children        // that are used to reuse the `path` property        const depth = vue.computed(() => {            let initialDepth = vue.unref(injectedDepth);            const { matched } = routeToDisplay.value;            let matchedRoute;            while ((matchedRoute = matched[initialDepth]) &&                !matchedRoute.components) {                initialDepth++;            }            return initialDepth;        });        const matchedRouteRef = vue.computed(() => routeToDisplay.value.matched[depth.value]);        vue.provide(viewDepthKey, vue.computed(() => depth.value + 1));        vue.provide(matchedRouteKey, matchedRouteRef);        vue.provide(routerViewLocationKey, routeToDisplay);        const viewRef = vue.ref();        // watch at the same time the component instance, the route record we are        // rendering, and the name        vue.watch(() => [viewRef.value, matchedRouteRef.value, props.name], ([instance, to, name], [oldInstance, from, oldName]) => {            // copy reused instances            if (to) {                // this will update the instance for new instances as well as reused                // instances when navigating to a new route                to.instances[name] = instance;                // the component instance is reused for a different route or name, so                // we copy any saved update or leave guards. With async setup, the                // mounting component will mount before the matchedRoute changes,                // making instance === oldInstance, so we check if guards have been                // added before. This works because we remove guards when                // unmounting/deactivating components                if (from && from !== to && instance && instance === oldInstance) {                    if (!to.leaveGuards.size) {                        to.leaveGuards = from.leaveGuards;                    }                    if (!to.updateGuards.size) {                        to.updateGuards = from.updateGuards;                    }                }            }            // trigger beforeRouteEnter next callbacks            if (instance &&                to &&                // if there is no instance but to and from are the same this might be                // the first visit                (!from || !isSameRouteRecord(to, from) || !oldInstance)) {                (to.enterCallbacks[name] || []).forEach(callback => callback(instance));            }        }, { flush: 'post' });        return () => {            const route = routeToDisplay.value;            // we need the value at the time we render because when we unmount, we            // navigated to a different location so the value is different            const currentName = props.name;            const matchedRoute = matchedRouteRef.value;            const ViewComponent = matchedRoute && matchedRoute.components[currentName];            if (!ViewComponent) {                return normalizeSlot(slots.default, { Component: ViewComponent, route });            }            // props from route configuration            const routePropsOption = matchedRoute.props[currentName];            const routeProps = routePropsOption                ? routePropsOption === true                    ? route.params                    : typeof routePropsOption === 'function'                        ? routePropsOption(route)                        : routePropsOption                : null;            const onVnodeUnmounted = vnode => {                // remove the instance reference to prevent leak                if (vnode.component.isUnmounted) {                    matchedRoute.instances[currentName] = null;                }            };            const component = vue.h(ViewComponent, assign({}, routeProps, attrs, {                onVnodeUnmounted,                ref: viewRef,            }));            return (            // pass the vnode to the slot as a prop.            // h and <component :is="..."> both accept vnodes            normalizeSlot(slots.default, { Component: component, route }) ||                component);        };    },});function normalizeSlot(slot, data) {    if (!slot)        return null;    const slotContent = slot(data);    return slotContent.length === 1 ? slotContent[0] : slotContent;}// export the public type for h/tsx inference// also to avoid inline import() in generated d.ts files/** * Component to display the current route the user is at. */const RouterView = RouterViewImpl;/** * Creates a Router instance that can be used by a Vue app. * * @param options - {@link RouterOptions} */function createRouter(options) {    const matcher = createRouterMatcher(options.routes, options);    const parseQuery$1 = options.parseQuery || parseQuery;    const stringifyQuery$1 = options.stringifyQuery || stringifyQuery;    const routerHistory = options.history;    const beforeGuards = useCallbacks();    const beforeResolveGuards = useCallbacks();    const afterGuards = useCallbacks();    const currentRoute = vue.shallowRef(START_LOCATION_NORMALIZED);    let pendingLocation = START_LOCATION_NORMALIZED;    // leave the scrollRestoration if no scrollBehavior is provided    if (isBrowser && options.scrollBehavior && 'scrollRestoration' in history) {        history.scrollRestoration = 'manual';    }    const normalizeParams = applyToParams.bind(null, paramValue => '' + paramValue);    const encodeParams = applyToParams.bind(null, encodeParam);    const decodeParams =     // @ts-expect-error: intentionally avoid the type check    applyToParams.bind(null, decode);    function addRoute(parentOrRoute, route) {        let parent;        let record;        if (isRouteName(parentOrRoute)) {            parent = matcher.getRecordMatcher(parentOrRoute);            record = route;        }        else {            record = parentOrRoute;        }        return matcher.addRoute(record, parent);    }    function removeRoute(name) {        const recordMatcher = matcher.getRecordMatcher(name);        if (recordMatcher) {            matcher.removeRoute(recordMatcher);        }    }    function getRoutes() {        return matcher.getRoutes().map(routeMatcher => routeMatcher.record);    }    function hasRoute(name) {        return !!matcher.getRecordMatcher(name);    }    function resolve(rawLocation, currentLocation) {        // const objectLocation = routerLocationAsObject(rawLocation)        // we create a copy to modify it later        currentLocation = assign({}, currentLocation || currentRoute.value);        if (typeof rawLocation === 'string') {            const locationNormalized = parseURL(parseQuery$1, rawLocation, currentLocation.path);            const matchedRoute = matcher.resolve({ path: locationNormalized.path }, currentLocation);            const href = routerHistory.createHref(locationNormalized.fullPath);            // locationNormalized is always a new object            return assign(locationNormalized, matchedRoute, {                params: decodeParams(matchedRoute.params),                hash: decode(locationNormalized.hash),                redirectedFrom: undefined,                href,            });        }        let matcherLocation;        // path could be relative in object as well        if ('path' in rawLocation) {            matcherLocation = assign({}, rawLocation, {                path: parseURL(parseQuery$1, rawLocation.path, currentLocation.path).path,            });        }        else {            // remove any nullish param            const targetParams = assign({}, rawLocation.params);            for (const key in targetParams) {                if (targetParams[key] == null) {                    delete targetParams[key];                }            }            // pass encoded values to the matcher, so it can produce encoded path and fullPath            matcherLocation = assign({}, rawLocation, {                params: encodeParams(rawLocation.params),            });            // current location params are decoded, we need to encode them in case the            // matcher merges the params            currentLocation.params = encodeParams(currentLocation.params);        }        const matchedRoute = matcher.resolve(matcherLocation, currentLocation);        const hash = rawLocation.hash || '';        // the matcher might have merged current location params, so        // we need to run the decoding again        matchedRoute.params = normalizeParams(decodeParams(matchedRoute.params));        const fullPath = stringifyURL(stringifyQuery$1, assign({}, rawLocation, {            hash: encodeHash(hash),            path: matchedRoute.path,        }));        const href = routerHistory.createHref(fullPath);        return assign({            fullPath,            // keep the hash encoded so fullPath is effectively path + encodedQuery +            // hash            hash,            query:             // if the user is using a custom query lib like qs, we might have            // nested objects, so we keep the query as is, meaning it can contain            // numbers at `$route.query`, but at the point, the user will have to            // use their own type anyway.            // https://github.com/vuejs/router/issues/328#issuecomment-649481567            stringifyQuery$1 === stringifyQuery                ? normalizeQuery(rawLocation.query)                : (rawLocation.query || {}),        }, matchedRoute, {            redirectedFrom: undefined,            href,        });    }    function locationAsObject(to) {        return typeof to === 'string'            ? parseURL(parseQuery$1, to, currentRoute.value.path)            : assign({}, to);    }    function checkCanceledNavigation(to, from) {        if (pendingLocation !== to) {            return createRouterError(8 /* ErrorTypes.NAVIGATION_CANCELLED */, {                from,                to,            });        }    }    function push(to) {        return pushWithRedirect(to);    }    function replace(to) {        return push(assign(locationAsObject(to), { replace: true }));    }    function handleRedirectRecord(to) {        const lastMatched = to.matched[to.matched.length - 1];        if (lastMatched && lastMatched.redirect) {            const { redirect } = lastMatched;            let newTargetLocation = typeof redirect === 'function' ? redirect(to) : redirect;            if (typeof newTargetLocation === 'string') {                newTargetLocation =                    newTargetLocation.includes('?') || newTargetLocation.includes('#')                        ? (newTargetLocation = locationAsObject(newTargetLocation))                        : // force empty params                            { path: newTargetLocation };                // @ts-expect-error: force empty params when a string is passed to let                // the router parse them again                newTargetLocation.params = {};            }            return assign({                query: to.query,                hash: to.hash,                // avoid transferring params if the redirect has a path                params: 'path' in newTargetLocation ? {} : to.params,            }, newTargetLocation);        }    }    function pushWithRedirect(to, redirectedFrom) {        const targetLocation = (pendingLocation = resolve(to));        const from = currentRoute.value;        const data = to.state;        const force = to.force;        // to could be a string where `replace` is a function        const replace = to.replace === true;        const shouldRedirect = handleRedirectRecord(targetLocation);        if (shouldRedirect)            return pushWithRedirect(assign(locationAsObject(shouldRedirect), {                state: typeof shouldRedirect === 'object'                    ? assign({}, data, shouldRedirect.state)                    : data,                force,                replace,            }),             // keep original redirectedFrom if it exists            redirectedFrom || targetLocation);        // if it was a redirect we already called `pushWithRedirect` above        const toLocation = targetLocation;        toLocation.redirectedFrom = redirectedFrom;        let failure;        if (!force && isSameRouteLocation(stringifyQuery$1, from, targetLocation)) {            failure = createRouterError(16 /* ErrorTypes.NAVIGATION_DUPLICATED */, { to: toLocation, from });            // trigger scroll to allow scrolling to the same anchor            handleScroll(from, from,             // this is a push, the only way for it to be triggered from a            // history.listen is with a redirect, which makes it become a push            true,             // This cannot be the first navigation because the initial location            // cannot be manually navigated to            false);        }        return (failure ? Promise.resolve(failure) : navigate(toLocation, from))            .catch((error) => isNavigationFailure(error)            ? // navigation redirects still mark the router as ready                isNavigationFailure(error, 2 /* ErrorTypes.NAVIGATION_GUARD_REDIRECT */)                    ? error                    : markAsReady(error) // also returns the error            : // reject any unknown error                triggerError(error, toLocation, from))            .then((failure) => {            if (failure) {                if (isNavigationFailure(failure, 2 /* ErrorTypes.NAVIGATION_GUARD_REDIRECT */)) {                    return pushWithRedirect(                    // keep options                    assign({                        // preserve an existing replacement but allow the redirect to override it                        replace,                    }, locationAsObject(failure.to), {                        state: typeof failure.to === 'object'                            ? assign({}, data, failure.to.state)                            : data,                        force,                    }),                     // preserve the original redirectedFrom if any                    redirectedFrom || toLocation);                }            }            else {                // if we fail we don't finalize the navigation                failure = finalizeNavigation(toLocation, from, true, replace, data);            }            triggerAfterEach(toLocation, from, failure);            return failure;        });    }    /**     * Helper to reject and skip all navigation guards if a new navigation happened     * @param to     * @param from     */    function checkCanceledNavigationAndReject(to, from) {        const error = checkCanceledNavigation(to, from);        return error ? Promise.reject(error) : Promise.resolve();    }    // TODO: refactor the whole before guards by internally using router.beforeEach    function navigate(to, from) {        let guards;        const [leavingRecords, updatingRecords, enteringRecords] = extractChangingRecords(to, from);        // all components here have been resolved once because we are leaving        guards = extractComponentsGuards(leavingRecords.reverse(), 'beforeRouteLeave', to, from);        // leavingRecords is already reversed        for (const record of leavingRecords) {            record.leaveGuards.forEach(guard => {                guards.push(guardToPromiseFn(guard, to, from));            });        }        const canceledNavigationCheck = checkCanceledNavigationAndReject.bind(null, to, from);        guards.push(canceledNavigationCheck);        // run the queue of per route beforeRouteLeave guards        return (runGuardQueue(guards)            .then(() => {            // check global guards beforeEach            guards = [];            for (const guard of beforeGuards.list()) {                guards.push(guardToPromiseFn(guard, to, from));            }            guards.push(canceledNavigationCheck);            return runGuardQueue(guards);        })            .then(() => {            // check in components beforeRouteUpdate            guards = extractComponentsGuards(updatingRecords, 'beforeRouteUpdate', to, from);            for (const record of updatingRecords) {                record.updateGuards.forEach(guard => {                    guards.push(guardToPromiseFn(guard, to, from));                });            }            guards.push(canceledNavigationCheck);            // run the queue of per route beforeEnter guards            return runGuardQueue(guards);        })            .then(() => {            // check the route beforeEnter            guards = [];            for (const record of to.matched) {                // do not trigger beforeEnter on reused views                if (record.beforeEnter && !from.matched.includes(record)) {                    if (isArray(record.beforeEnter)) {                        for (const beforeEnter of record.beforeEnter)                            guards.push(guardToPromiseFn(beforeEnter, to, from));                    }                    else {                        guards.push(guardToPromiseFn(record.beforeEnter, to, from));                    }                }            }            guards.push(canceledNavigationCheck);            // run the queue of per route beforeEnter guards            return runGuardQueue(guards);        })            .then(() => {            // NOTE: at this point to.matched is normalized and does not contain any () => Promise<Component>            // clear existing enterCallbacks, these are added by extractComponentsGuards            to.matched.forEach(record => (record.enterCallbacks = {}));            // check in-component beforeRouteEnter            guards = extractComponentsGuards(enteringRecords, 'beforeRouteEnter', to, from);            guards.push(canceledNavigationCheck);            // run the queue of per route beforeEnter guards            return runGuardQueue(guards);        })            .then(() => {            // check global guards beforeResolve            guards = [];            for (const guard of beforeResolveGuards.list()) {                guards.push(guardToPromiseFn(guard, to, from));            }            guards.push(canceledNavigationCheck);            return runGuardQueue(guards);        })            // catch any navigation canceled            .catch(err => isNavigationFailure(err, 8 /* ErrorTypes.NAVIGATION_CANCELLED */)            ? err            : Promise.reject(err)));    }    function triggerAfterEach(to, from, failure) {        // navigation is confirmed, call afterGuards        // TODO: wrap with error handlers        for (const guard of afterGuards.list())            guard(to, from, failure);    }    /**     * - Cleans up any navigation guards     * - Changes the url if necessary     * - Calls the scrollBehavior     */    function finalizeNavigation(toLocation, from, isPush, replace, data) {        // a more recent navigation took place        const error = checkCanceledNavigation(toLocation, from);        if (error)            return error;        // only consider as push if it's not the first navigation        const isFirstNavigation = from === START_LOCATION_NORMALIZED;        const state = !isBrowser ? {} : history.state;        // change URL only if the user did a push/replace and if it's not the initial navigation because        // it's just reflecting the url        if (isPush) {            // on the initial navigation, we want to reuse the scroll position from            // history state if it exists            if (replace || isFirstNavigation)                routerHistory.replace(toLocation.fullPath, assign({                    scroll: isFirstNavigation && state && state.scroll,                }, data));            else                routerHistory.push(toLocation.fullPath, data);        }        // accept current navigation        currentRoute.value = toLocation;        handleScroll(toLocation, from, isPush, isFirstNavigation);        markAsReady();    }    let removeHistoryListener;    // attach listener to history to trigger navigations    function setupListeners() {        // avoid setting up listeners twice due to an invalid first navigation        if (removeHistoryListener)            return;        removeHistoryListener = routerHistory.listen((to, _from, info) => {            if (!router.listening)                return;            // cannot be a redirect route because it was in history            const toLocation = resolve(to);            // due to dynamic routing, and to hash history with manual navigation            // (manually changing the url or calling history.hash = '#/somewhere'),            // there could be a redirect record in history            const shouldRedirect = handleRedirectRecord(toLocation);            if (shouldRedirect) {                pushWithRedirect(assign(shouldRedirect, { replace: true }), toLocation).catch(noop);                return;            }            pendingLocation = toLocation;            const from = currentRoute.value;            // TODO: should be moved to web history?            if (isBrowser) {                saveScrollPosition(getScrollKey(from.fullPath, info.delta), computeScrollPosition());            }            navigate(toLocation, from)                .catch((error) => {                if (isNavigationFailure(error, 4 /* ErrorTypes.NAVIGATION_ABORTED */ | 8 /* ErrorTypes.NAVIGATION_CANCELLED */)) {                    return error;                }                if (isNavigationFailure(error, 2 /* ErrorTypes.NAVIGATION_GUARD_REDIRECT */)) {                    // Here we could call if (info.delta) routerHistory.go(-info.delta,                    // false) but this is bug prone as we have no way to wait the                    // navigation to be finished before calling pushWithRedirect. Using                    // a setTimeout of 16ms seems to work but there is no guarantee for                    // it to work on every browser. So instead we do not restore the                    // history entry and trigger a new navigation as requested by the                    // navigation guard.                    // the error is already handled by router.push we just want to avoid                    // logging the error                    pushWithRedirect(error.to, toLocation                    // avoid an uncaught rejection, let push call triggerError                    )                        .then(failure => {                        // manual change in hash history #916 ending up in the URL not                        // changing, but it was changed by the manual url change, so we                        // need to manually change it ourselves                        if (isNavigationFailure(failure, 4 /* ErrorTypes.NAVIGATION_ABORTED */ |                            16 /* ErrorTypes.NAVIGATION_DUPLICATED */) &&                            !info.delta &&                            info.type === NavigationType.pop) {                            routerHistory.go(-1, false);                        }                    })                        .catch(noop);                    // avoid the then branch                    return Promise.reject();                }                // do not restore history on unknown direction                if (info.delta) {                    routerHistory.go(-info.delta, false);                }                // unrecognized error, transfer to the global handler                return triggerError(error, toLocation, from);            })                .then((failure) => {                failure =                    failure ||                        finalizeNavigation(                        // after navigation, all matched components are resolved                        toLocation, from, false);                // revert the navigation                if (failure) {                    if (info.delta &&                        // a new navigation has been triggered, so we do not want to revert, that will change the current history                        // entry while a different route is displayed                        !isNavigationFailure(failure, 8 /* ErrorTypes.NAVIGATION_CANCELLED */)) {                        routerHistory.go(-info.delta, false);                    }                    else if (info.type === NavigationType.pop &&                        isNavigationFailure(failure, 4 /* ErrorTypes.NAVIGATION_ABORTED */ | 16 /* ErrorTypes.NAVIGATION_DUPLICATED */)) {                        // manual change in hash history #916                        // it's like a push but lacks the information of the direction                        routerHistory.go(-1, false);                    }                }                triggerAfterEach(toLocation, from, failure);            })                .catch(noop);        });    }    // Initialization and Errors    let readyHandlers = useCallbacks();    let errorHandlers = useCallbacks();    let ready;    /**     * Trigger errorHandlers added via onError and throws the error as well     *     * @param error - error to throw     * @param to - location we were navigating to when the error happened     * @param from - location we were navigating from when the error happened     * @returns the error as a rejected promise     */    function triggerError(error, to, from) {        markAsReady(error);        const list = errorHandlers.list();        if (list.length) {            list.forEach(handler => handler(error, to, from));        }        else {            console.error(error);        }        return Promise.reject(error);    }    function isReady() {        if (ready && currentRoute.value !== START_LOCATION_NORMALIZED)            return Promise.resolve();        return new Promise((resolve, reject) => {            readyHandlers.add([resolve, reject]);        });    }    function markAsReady(err) {        if (!ready) {            // still not ready if an error happened            ready = !err;            setupListeners();            readyHandlers                .list()                .forEach(([resolve, reject]) => (err ? reject(err) : resolve()));            readyHandlers.reset();        }        return err;    }    // Scroll behavior    function handleScroll(to, from, isPush, isFirstNavigation) {        const { scrollBehavior } = options;        if (!isBrowser || !scrollBehavior)            return Promise.resolve();        const scrollPosition = (!isPush && getSavedScrollPosition(getScrollKey(to.fullPath, 0))) ||            ((isFirstNavigation || !isPush) &&                history.state &&                history.state.scroll) ||            null;        return vue.nextTick()            .then(() => scrollBehavior(to, from, scrollPosition))            .then(position => position && scrollToPosition(position))            .catch(err => triggerError(err, to, from));    }    const go = (delta) => routerHistory.go(delta);    let started;    const installedApps = new Set();    const router = {        currentRoute,        listening: true,        addRoute,        removeRoute,        hasRoute,        getRoutes,        resolve,        options,        push,        replace,        go,        back: () => go(-1),        forward: () => go(1),        beforeEach: beforeGuards.add,        beforeResolve: beforeResolveGuards.add,        afterEach: afterGuards.add,        onError: errorHandlers.add,        isReady,        install(app) {            const router = this;            app.component('RouterLink', RouterLink);            app.component('RouterView', RouterView);            app.config.globalProperties.$router = router;            Object.defineProperty(app.config.globalProperties, '$route', {                enumerable: true,                get: () => vue.unref(currentRoute),            });            // this initial navigation is only necessary on client, on server it doesn't            // make sense because it will create an extra unnecessary navigation and could            // lead to problems            if (isBrowser &&                // used for the initial navigation client side to avoid pushing                // multiple times when the router is used in multiple apps                !started &&                currentRoute.value === START_LOCATION_NORMALIZED) {                // see above                started = true;                push(routerHistory.location).catch(err => {                });            }            const reactiveRoute = {};            for (const key in START_LOCATION_NORMALIZED) {                // @ts-expect-error: the key matches                reactiveRoute[key] = vue.computed(() => currentRoute.value[key]);            }            app.provide(routerKey, router);            app.provide(routeLocationKey, vue.reactive(reactiveRoute));            app.provide(routerViewLocationKey, currentRoute);            const unmountApp = app.unmount;            installedApps.add(app);            app.unmount = function () {                installedApps.delete(app);                // the router is not attached to an app anymore                if (installedApps.size < 1) {                    // invalidate the current navigation                    pendingLocation = START_LOCATION_NORMALIZED;                    removeHistoryListener && removeHistoryListener();                    removeHistoryListener = null;                    currentRoute.value = START_LOCATION_NORMALIZED;                    started = false;                    ready = false;                }                unmountApp();            };        },    };    return router;}function runGuardQueue(guards) {    return guards.reduce((promise, guard) => promise.then(() => guard()), Promise.resolve());}function extractChangingRecords(to, from) {    const leavingRecords = [];    const updatingRecords = [];    const enteringRecords = [];    const len = Math.max(from.matched.length, to.matched.length);    for (let i = 0; i < len; i++) {        const recordFrom = from.matched[i];        if (recordFrom) {            if (to.matched.find(record => isSameRouteRecord(record, recordFrom)))                updatingRecords.push(recordFrom);            else                leavingRecords.push(recordFrom);        }        const recordTo = to.matched[i];        if (recordTo) {            // the type doesn't matter because we are comparing per reference            if (!from.matched.find(record => isSameRouteRecord(record, recordTo))) {                enteringRecords.push(recordTo);            }        }    }    return [leavingRecords, updatingRecords, enteringRecords];}/** * Returns the router instance. Equivalent to using `$router` inside * templates. */function useRouter() {    return vue.inject(routerKey);}/** * Returns the current route location. Equivalent to using `$route` inside * templates. */function useRoute() {    return vue.inject(routeLocationKey);}exports.RouterLink = RouterLink;exports.RouterView = RouterView;exports.START_LOCATION = START_LOCATION_NORMALIZED;exports.createMemoryHistory = createMemoryHistory;exports.createRouter = createRouter;exports.createRouterMatcher = createRouterMatcher;exports.createWebHashHistory = createWebHashHistory;exports.createWebHistory = createWebHistory;exports.isNavigationFailure = isNavigationFailure;exports.loadRouteLocation = loadRouteLocation;exports.matchedRouteKey = matchedRouteKey;exports.onBeforeRouteLeave = onBeforeRouteLeave;exports.onBeforeRouteUpdate = onBeforeRouteUpdate;exports.parseQuery = parseQuery;exports.routeLocationKey = routeLocationKey;exports.routerKey = routerKey;exports.routerViewLocationKey = routerViewLocationKey;exports.stringifyQuery = stringifyQuery;exports.useLink = useLink;exports.useRoute = useRoute;exports.useRouter = useRouter;exports.viewDepthKey = viewDepthKey;
 |