| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218 |
- /*!
- * vue-router v4.6.3
- * (c) 2025 Eduardo San Martin Morote
- * @license MIT
- */
- import { getCurrentInstance, inject, onActivated, onDeactivated, onUnmounted, watch } from "vue";
- import { setupDevtoolsPlugin } from "@vue/devtools-api";
- //#region src/utils/env.ts
- const isBrowser = typeof document !== "undefined";
- //#endregion
- //#region src/utils/index.ts
- /**
- * Identity function that returns the value as is.
- *
- * @param v - the value to return
- *
- * @internal
- */
- const identityFn = (v) => v;
- /**
- * 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;
- }
- function isESModule(obj) {
- return obj.__esModule || obj[Symbol.toStringTag] === "Module" || obj.default && isRouteComponent(obj.default);
- }
- 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;
- function mergeOptions(defaults, partialOptions) {
- const options = {};
- for (const key in defaults) options[key] = key in partialOptions ? partialOptions[key] : defaults[key];
- return options;
- }
- //#endregion
- //#region src/warning.ts
- function warn$1(msg) {
- const args = Array.from(arguments).slice(1);
- console.warn.apply(console, ["[Vue Router warn]: " + msg].concat(args));
- }
- //#endregion
- //#region src/encoding.ts
- /**
- * 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 HASH_RE = /#/g;
- const AMPERSAND_RE = /&/g;
- const SLASH_RE = /\//g;
- const EQUAL_RE = /=/g;
- const IM_RE = /\?/g;
- const PLUS_RE = /\+/g;
- /**
- * 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 text == null ? "" : 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).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 encodePath(text).replace(SLASH_RE, "%2F");
- }
- function decode(text) {
- if (text == null) return null;
- try {
- return decodeURIComponent("" + text);
- } catch (err) {
- process.env.NODE_ENV !== "production" && warn$1(`Error decoding "${text}". Using original value`);
- }
- return "" + text;
- }
- //#endregion
- //#region src/location.ts
- 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$1, location, currentLocation = "/") {
- let path, query = {}, searchString = "", hash = "";
- const hashPos = location.indexOf("#");
- let searchPos = location.indexOf("?");
- searchPos = hashPos >= 0 && searchPos > hashPos ? -1 : searchPos;
- if (searchPos >= 0) {
- path = location.slice(0, searchPos);
- searchString = location.slice(searchPos, hashPos > 0 ? hashPos : location.length);
- query = parseQuery$1(searchString.slice(1));
- }
- if (hashPos >= 0) {
- path = path || location.slice(0, hashPos);
- hash = location.slice(hashPos, location.length);
- }
- path = resolveRelativePath(path != null ? path : location, currentLocation);
- return {
- fullPath: path + searchString + hash,
- path,
- query,
- hash: decode(hash)
- };
- }
- function NEW_stringifyURL(stringifyQuery$1, path, query, hash = "") {
- const searchText = stringifyQuery$1(query);
- return path + (searchText && "?") + searchText + encodeHash(hash);
- }
- /**
- * Stringifies a URL object
- *
- * @param stringifyQuery
- * @param location
- */
- function stringifyURL(stringifyQuery$1, location) {
- const query = location.query ? stringifyQuery$1(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) {
- 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 stringifyQuery - A function that takes a query object of type LocationQueryRaw and returns a string representation of it.
- * @param a - first {@link RouteLocation}
- * @param b - second {@link RouteLocation}
- */
- function isSameRouteLocation(stringifyQuery$1, 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$1(a.query) === stringifyQuery$1(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) {
- 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 (process.env.NODE_ENV !== "production" && !from.startsWith("/")) {
- warn$1(`Cannot resolve a relative location without an absolute path. Trying to resolve "${to}" from "${from}". It should look like "/${from}".`);
- return to;
- }
- if (!to) return from;
- const fromSegments = from.split("/");
- const toSegments = to.split("/");
- const lastToSegment = toSegments[toSegments.length - 1];
- if (lastToSegment === ".." || lastToSegment === ".") toSegments.push("");
- let position = fromSegments.length - 1;
- let toPosition;
- let segment;
- for (toPosition = 0; toPosition < toSegments.length; toPosition++) {
- segment = toSegments[toPosition];
- if (segment === ".") continue;
- if (segment === "..") {
- if (position > 1) position--;
- } else break;
- }
- return fromSegments.slice(0, position).join("/") + "/" + toSegments.slice(toPosition).join("/");
- }
- /**
- * 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: void 0,
- params: {},
- query: {},
- hash: "",
- fullPath: "/",
- matched: [],
- meta: {},
- redirectedFrom: void 0
- };
- //#endregion
- //#region src/history/common.ts
- let NavigationType = /* @__PURE__ */ function(NavigationType$1) {
- NavigationType$1["pop"] = "pop";
- NavigationType$1["push"] = "push";
- return NavigationType$1;
- }({});
- let NavigationDirection = /* @__PURE__ */ function(NavigationDirection$1) {
- NavigationDirection$1["back"] = "back";
- NavigationDirection$1["forward"] = "forward";
- NavigationDirection$1["unknown"] = "";
- return NavigationDirection$1;
- }({});
- /**
- * Starting location for Histories
- */
- const START = "";
- /**
- * 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) {
- const baseEl = document.querySelector("base");
- base = baseEl && baseEl.getAttribute("href") || "/";
- base = base.replace(/^\w+:\/\/[^\/]+/, "");
- } else base = "/";
- if (base[0] !== "/" && base[0] !== "#") base = "/" + base;
- return removeTrailingSlash(base);
- }
- const BEFORE_HASH_RE = /^[^#]+#/;
- function createHref(base, location) {
- return base.replace(BEFORE_HASH_RE, "#") + location;
- }
- //#endregion
- //#region src/scrollBehavior.ts
- 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.scrollX,
- top: window.scrollY
- });
- function scrollToPosition(position) {
- let scrollToOptions;
- if ("el" in position) {
- const positionEl = position.el;
- const isIdSelector = typeof positionEl === "string" && positionEl.startsWith("#");
- /**
- * `id`s can accept pretty much any characters, including CSS combinators
- * like `>` or `~`. It's still possible to retrieve elements using
- * `document.getElementById('~')` but it needs to be escaped when using
- * `document.querySelector('#\\~')` for it to be valid. The only
- * requirements for `id`s are them to be unique on the page and to not be
- * empty (`id=""`). Because of that, when passing an id selector, it should
- * be properly escaped for it to work with `querySelector`. We could check
- * for the id selector to be simple (no CSS combinators `+ >~`) but that
- * would make things inconsistent since they are valid characters for an
- * `id` but would need to be escaped when using `querySelector`, breaking
- * their usage and ending up in no selector returned. Selectors need to be
- * escaped:
- *
- * - `#1-thing` becomes `#\31 -thing`
- * - `#with~symbols` becomes `#with\\~symbols`
- *
- * - More information about the topic can be found at
- * https://mathiasbynens.be/notes/html5-id-class.
- * - Practical example: https://mathiasbynens.be/demo/html5-id
- */
- if (process.env.NODE_ENV !== "production" && typeof position.el === "string") {
- if (!isIdSelector || !document.getElementById(position.el.slice(1))) try {
- const foundEl = document.querySelector(position.el);
- if (isIdSelector && foundEl) {
- warn$1(`The selector "${position.el}" should be passed as "el: document.querySelector('${position.el}')" because it starts with "#".`);
- return;
- }
- } catch (err) {
- warn$1(`The selector "${position.el}" is invalid. If you are using an id selector, make sure to escape it. You can find more information about escaping characters in selectors at https://mathiasbynens.be/notes/css-escapes or use CSS.escape (https://developer.mozilla.org/en-US/docs/Web/API/CSS/escape).`);
- return;
- }
- }
- const el = typeof positionEl === "string" ? isIdSelector ? document.getElementById(positionEl.slice(1)) : document.querySelector(positionEl) : positionEl;
- if (!el) {
- process.env.NODE_ENV !== "production" && warn$1(`Couldn't find element using selector "${position.el}" returned by scrollBehavior.`);
- 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.scrollX, scrollToOptions.top != null ? scrollToOptions.top : window.scrollY);
- }
- function getScrollKey(path, delta) {
- return (history.state ? history.state.position - delta : -1) + path;
- }
- const scrollPositions = /* @__PURE__ */ new Map();
- function saveScrollPosition(key, scrollPosition) {
- scrollPositions.set(key, scrollPosition);
- }
- function getSavedScrollPosition(key) {
- const scroll = scrollPositions.get(key);
- scrollPositions.delete(key);
- return scroll;
- }
- /**
- * ScrollBehavior instance used by the router to compute and restore the scroll
- * position when navigating.
- */
- //#endregion
- //#region src/types/typeGuards.ts
- function isRouteLocation(route) {
- return typeof route === "string" || route && typeof route === "object";
- }
- function isRouteName(name) {
- return typeof name === "string" || typeof name === "symbol";
- }
- //#endregion
- //#region src/errors.ts
- /**
- * Flags so we can combine them when checking for multiple errors. This is the internal version of
- * {@link NavigationFailureType}.
- *
- * @internal
- */
- let ErrorTypes = /* @__PURE__ */ function(ErrorTypes$1) {
- ErrorTypes$1[ErrorTypes$1["MATCHER_NOT_FOUND"] = 1] = "MATCHER_NOT_FOUND";
- ErrorTypes$1[ErrorTypes$1["NAVIGATION_GUARD_REDIRECT"] = 2] = "NAVIGATION_GUARD_REDIRECT";
- ErrorTypes$1[ErrorTypes$1["NAVIGATION_ABORTED"] = 4] = "NAVIGATION_ABORTED";
- ErrorTypes$1[ErrorTypes$1["NAVIGATION_CANCELLED"] = 8] = "NAVIGATION_CANCELLED";
- ErrorTypes$1[ErrorTypes$1["NAVIGATION_DUPLICATED"] = 16] = "NAVIGATION_DUPLICATED";
- return ErrorTypes$1;
- }({});
- const NavigationFailureSymbol = Symbol(process.env.NODE_ENV !== "production" ? "navigation failure" : "");
- /**
- * Enumeration with all possible types for navigation failures. Can be passed to
- * {@link isNavigationFailure} to check for specific failures.
- */
- let NavigationFailureType = /* @__PURE__ */ function(NavigationFailureType$1) {
- /**
- * An aborted navigation is a navigation that failed because a navigation
- * guard returned `false` or called `next(false)`
- */
- NavigationFailureType$1[NavigationFailureType$1["aborted"] = 4] = "aborted";
- /**
- * A cancelled navigation is a navigation that failed because a more recent
- * navigation finished started (not necessarily finished).
- */
- NavigationFailureType$1[NavigationFailureType$1["cancelled"] = 8] = "cancelled";
- /**
- * A duplicated navigation is a navigation that failed because it was
- * initiated while already being at the exact same location.
- */
- NavigationFailureType$1[NavigationFailureType$1["duplicated"] = 16] = "duplicated";
- return NavigationFailureType$1;
- }({});
- const ErrorTypeMessages = {
- [ErrorTypes.MATCHER_NOT_FOUND]({ location, currentLocation }) {
- return `No match for\n ${JSON.stringify(location)}${currentLocation ? "\nwhile being at\n" + JSON.stringify(currentLocation) : ""}`;
- },
- [ErrorTypes.NAVIGATION_GUARD_REDIRECT]({ from, to }) {
- return `Redirected from "${from.fullPath}" to "${stringifyRoute(to)}" via a navigation guard.`;
- },
- [ErrorTypes.NAVIGATION_ABORTED]({ from, to }) {
- return `Navigation aborted from "${from.fullPath}" to "${to.fullPath}" via a navigation guard.`;
- },
- [ErrorTypes.NAVIGATION_CANCELLED]({ from, to }) {
- return `Navigation cancelled from "${from.fullPath}" to "${to.fullPath}" with a new navigation.`;
- },
- [ErrorTypes.NAVIGATION_DUPLICATED]({ from, to }) {
- return `Avoided redundant navigation to current location: "${from.fullPath}".`;
- }
- };
- /**
- * Creates a typed NavigationFailure object.
- * @internal
- * @param type - NavigationFailureType
- * @param params - { from, to }
- */
- function createRouterError(type, params) {
- if (process.env.NODE_ENV !== "production" || false) return assign(new Error(ErrorTypeMessages[type](params)), {
- type,
- [NavigationFailureSymbol]: true
- }, params);
- else return assign(/* @__PURE__ */ new Error(), {
- 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 (to.path != null) return to.path;
- const location = {};
- for (const key of propertiesToLog) if (key in to) location[key] = to[key];
- return JSON.stringify(location, null, 2);
- }
- //#endregion
- //#region src/query.ts
- /**
- * 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 = {};
- if (search === "" || search === "?") return query;
- const searchParams = (search[0] === "?" ? search.slice(1) : search).split("&");
- for (let i = 0; i < searchParams.length; ++i) {
- const searchParam = searchParams[i].replace(PLUS_RE, " ");
- 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) {
- 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) {
- if (value !== void 0) search += (search.length ? "&" : "") + key;
- continue;
- }
- (isArray(value) ? value.map((v) => v && encodeQueryValue(v)) : [value && encodeQueryValue(value)]).forEach((value$1) => {
- if (value$1 !== void 0) {
- search += (search.length ? "&" : "") + key;
- if (value$1 != null) search += "=" + value$1;
- }
- });
- }
- 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 !== void 0) normalizedQuery[key] = isArray(value) ? value.map((v) => v == null ? null : "" + v) : value == null ? value : "" + value;
- }
- return normalizedQuery;
- }
- //#endregion
- //#region src/injectionSymbols.ts
- /**
- * 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(process.env.NODE_ENV !== "production" ? "router view location matched" : "");
- /**
- * Allows overriding the router view depth to control which component in
- * `matched` is rendered. rvd stands for Router View Depth
- *
- * @internal
- */
- const viewDepthKey = Symbol(process.env.NODE_ENV !== "production" ? "router view depth" : "");
- /**
- * Allows overriding the router instance returned by `useRouter` in tests. r
- * stands for router
- *
- * @internal
- */
- const routerKey = Symbol(process.env.NODE_ENV !== "production" ? "router" : "");
- /**
- * Allows overriding the current route returned by `useRoute` in tests. rl
- * stands for route location
- *
- * @internal
- */
- const routeLocationKey = Symbol(process.env.NODE_ENV !== "production" ? "route location" : "");
- /**
- * Allows overriding the current route used by router-view. Internally this is
- * used when the `route` prop is passed.
- *
- * @internal
- */
- const routerViewLocationKey = Symbol(process.env.NODE_ENV !== "production" ? "router view location" : "");
- //#endregion
- //#region src/utils/callbacks.ts
- /**
- * 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.slice(),
- reset
- };
- }
- //#endregion
- //#region src/navigationGuards.ts
- function registerGuard(record, name, guard) {
- const removeFromList = () => {
- record[name].delete(guard);
- };
- onUnmounted(removeFromList);
- onDeactivated(removeFromList);
- 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) {
- if (process.env.NODE_ENV !== "production" && !getCurrentInstance()) {
- warn$1("getCurrentInstance() returned null. onBeforeRouteLeave() must be called at the top of a setup function");
- return;
- }
- const activeRecord = inject(matchedRouteKey, {}).value;
- if (!activeRecord) {
- process.env.NODE_ENV !== "production" && warn$1("No active route record was found when calling `onBeforeRouteLeave()`. Make sure you call this function inside a component child of <router-view>. Maybe you called it inside of App.vue?");
- 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) {
- if (process.env.NODE_ENV !== "production" && !getCurrentInstance()) {
- warn$1("getCurrentInstance() returned null. onBeforeRouteUpdate() must be called at the top of a setup function");
- return;
- }
- const activeRecord = inject(matchedRouteKey, {}).value;
- if (!activeRecord) {
- process.env.NODE_ENV !== "production" && warn$1("No active route record was found when calling `onBeforeRouteUpdate()`. Make sure you call this function inside a component child of <router-view>. Maybe you called it inside of App.vue?");
- return;
- }
- registerGuard(activeRecord, "updateGuards", updateGuard);
- }
- function guardToPromiseFn(guard, to, from, record, name, runWithContext = (fn) => fn()) {
- const enterCallbackArray = record && (record.enterCallbacks[name] = record.enterCallbacks[name] || []);
- return () => new Promise((resolve, reject) => {
- const next = (valid) => {
- if (valid === false) reject(createRouterError(ErrorTypes.NAVIGATION_ABORTED, {
- from,
- to
- }));
- else if (valid instanceof Error) reject(valid);
- else if (isRouteLocation(valid)) reject(createRouterError(ErrorTypes.NAVIGATION_GUARD_REDIRECT, {
- from: to,
- to: valid
- }));
- else {
- if (enterCallbackArray && record.enterCallbacks[name] === enterCallbackArray && typeof valid === "function") enterCallbackArray.push(valid);
- resolve();
- }
- };
- const guardReturn = runWithContext(() => guard.call(record && record.instances[name], to, from, process.env.NODE_ENV !== "production" ? canOnlyBeCalledOnce(next, to, from) : next));
- let guardCall = Promise.resolve(guardReturn);
- if (guard.length < 3) guardCall = guardCall.then(next);
- if (process.env.NODE_ENV !== "production" && guard.length > 2) {
- const message = `The "next" callback was never called inside of ${guard.name ? "\"" + guard.name + "\"" : ""}:\n${guard.toString()}\n. If you are returning a value instead of calling "next", make sure to remove the "next" parameter from your function.`;
- if (typeof guardReturn === "object" && "then" in guardReturn) guardCall = guardCall.then((resolvedValue) => {
- if (!next._called) {
- warn$1(message);
- return Promise.reject(/* @__PURE__ */ new Error("Invalid navigation guard"));
- }
- return resolvedValue;
- });
- else if (guardReturn !== void 0) {
- if (!next._called) {
- warn$1(message);
- reject(/* @__PURE__ */ new Error("Invalid navigation guard"));
- return;
- }
- }
- }
- guardCall.catch((err) => reject(err));
- });
- }
- function canOnlyBeCalledOnce(next, to, from) {
- let called = 0;
- return function() {
- if (called++ === 1) warn$1(`The "next" callback was called more than once in one navigation guard when going from "${from.fullPath}" to "${to.fullPath}". It should be called exactly one time in each navigation guard. This will fail in production.`);
- next._called = true;
- if (called === 1) next.apply(null, arguments);
- };
- }
- function extractComponentsGuards(matched, guardType, to, from, runWithContext = (fn) => fn()) {
- const guards = [];
- for (const record of matched) {
- if (process.env.NODE_ENV !== "production" && !record.components && record.children && !record.children.length) warn$1(`Record with path "${record.path}" is either missing a "component(s)" or "children" property.`);
- for (const name in record.components) {
- let rawComponent = record.components[name];
- if (process.env.NODE_ENV !== "production") {
- if (!rawComponent || typeof rawComponent !== "object" && typeof rawComponent !== "function") {
- warn$1(`Component "${name}" in record with path "${record.path}" is not a valid component. Received "${String(rawComponent)}".`);
- throw new Error("Invalid route component");
- } else if ("then" in rawComponent) {
- warn$1(`Component "${name}" in record with path "${record.path}" is a Promise instead of a function that returns a Promise. Did you write "import('./MyPage.vue')" instead of "() => import('./MyPage.vue')" ? This will break in production if not fixed.`);
- const promise = rawComponent;
- rawComponent = () => promise;
- } else if (rawComponent.__asyncLoader && !rawComponent.__warnedDefineAsync) {
- rawComponent.__warnedDefineAsync = true;
- warn$1(`Component "${name}" in record with path "${record.path}" is defined using "defineAsyncComponent()". Write "() => import('./MyPage.vue')" instead of "defineAsyncComponent(() => import('./MyPage.vue'))".`);
- }
- }
- if (guardType !== "beforeRouteEnter" && !record.instances[name]) continue;
- if (isRouteComponent(rawComponent)) {
- const guard = (rawComponent.__vccOpts || rawComponent)[guardType];
- guard && guards.push(guardToPromiseFn(guard, to, from, record, name, runWithContext));
- } else {
- let componentPromise = rawComponent();
- if (process.env.NODE_ENV !== "production" && !("catch" in componentPromise)) {
- warn$1(`Component "${name}" in record with path "${record.path}" is a function that does not return a Promise. If you were passing a functional component, make sure to add a "displayName" to the component. This will break in production if not fixed.`);
- componentPromise = Promise.resolve(componentPromise);
- }
- guards.push(() => componentPromise.then((resolved) => {
- if (!resolved) throw new Error(`Couldn't resolve component "${name}" at "${record.path}"`);
- const resolvedComponent = isESModule(resolved) ? resolved.default : resolved;
- record.mods[name] = resolved;
- record.components[name] = resolvedComponent;
- const guard = (resolvedComponent.__vccOpts || resolvedComponent)[guardType];
- return guard && guardToPromiseFn(guard, to, from, record, name, runWithContext)();
- }));
- }
- }
- }
- return guards;
- }
- /**
- * 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(/* @__PURE__ */ 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(/* @__PURE__ */ 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;
- record.mods[name] = resolved;
- record.components[name] = resolvedComponent;
- }));
- return promises;
- }, [])))).then(() => route);
- }
- /**
- * Split the leaving, updating, and entering records.
- * @internal
- *
- * @param to - Location we are navigating to
- * @param from - Location we are navigating from
- */
- 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) {
- if (!from.matched.find((record) => isSameRouteRecord(record, recordTo))) enteringRecords.push(recordTo);
- }
- }
- return [
- leavingRecords,
- updatingRecords,
- enteringRecords
- ];
- }
- //#endregion
- //#region src/devtools.ts
- /**
- * Copies a route location and removes any problematic properties that cannot be shown in devtools (e.g. Vue instances).
- *
- * @param routeLocation - routeLocation to format
- * @param tooltip - optional tooltip
- * @returns a copy of the routeLocation
- */
- function formatRouteLocation(routeLocation, tooltip) {
- const copy = assign({}, routeLocation, { matched: routeLocation.matched.map((matched) => omit(matched, [
- "instances",
- "children",
- "aliasOf"
- ])) });
- return { _custom: {
- type: null,
- readOnly: true,
- display: routeLocation.fullPath,
- tooltip,
- value: copy
- } };
- }
- function formatDisplay(display) {
- return { _custom: { display } };
- }
- let routerId = 0;
- function addDevtools(app, router, matcher) {
- if (router.__hasDevtools) return;
- router.__hasDevtools = true;
- const id = routerId++;
- setupDevtoolsPlugin({
- id: "org.vuejs.router" + (id ? "." + id : ""),
- label: "Vue Router",
- packageName: "vue-router",
- homepage: "https://router.vuejs.org",
- logo: "https://router.vuejs.org/logo.png",
- componentStateTypes: ["Routing"],
- app
- }, (api) => {
- if (typeof api.now !== "function") warn$1("[Vue Router]: You seem to be using an outdated version of Vue Devtools. Are you still using the Beta release instead of the stable one? You can find the links at https://devtools.vuejs.org/guide/installation.html.");
- api.on.inspectComponent((payload, ctx) => {
- if (payload.instanceData) payload.instanceData.state.push({
- type: "Routing",
- key: "$route",
- editable: false,
- value: formatRouteLocation(router.currentRoute.value, "Current Route")
- });
- });
- api.on.visitComponentTree(({ treeNode: node, componentInstance }) => {
- if (componentInstance.__vrv_devtools) {
- const info = componentInstance.__vrv_devtools;
- node.tags.push({
- label: (info.name ? `${info.name.toString()}: ` : "") + info.path,
- textColor: 0,
- tooltip: "This component is rendered by <router-view>",
- backgroundColor: PINK_500
- });
- }
- if (isArray(componentInstance.__vrl_devtools)) {
- componentInstance.__devtoolsApi = api;
- componentInstance.__vrl_devtools.forEach((devtoolsData) => {
- let label = devtoolsData.route.path;
- let backgroundColor = ORANGE_400;
- let tooltip = "";
- let textColor = 0;
- if (devtoolsData.error) {
- label = devtoolsData.error;
- backgroundColor = RED_100;
- textColor = RED_700;
- } else if (devtoolsData.isExactActive) {
- backgroundColor = LIME_500;
- tooltip = "This is exactly active";
- } else if (devtoolsData.isActive) {
- backgroundColor = BLUE_600;
- tooltip = "This link is active";
- }
- node.tags.push({
- label,
- textColor,
- tooltip,
- backgroundColor
- });
- });
- }
- });
- watch(router.currentRoute, () => {
- refreshRoutesView();
- api.notifyComponentUpdate();
- api.sendInspectorTree(routerInspectorId);
- api.sendInspectorState(routerInspectorId);
- });
- const navigationsLayerId = "router:navigations:" + id;
- api.addTimelineLayer({
- id: navigationsLayerId,
- label: `Router${id ? " " + id : ""} Navigations`,
- color: 4237508
- });
- router.onError((error, to) => {
- api.addTimelineEvent({
- layerId: navigationsLayerId,
- event: {
- title: "Error during Navigation",
- subtitle: to.fullPath,
- logType: "error",
- time: api.now(),
- data: { error },
- groupId: to.meta.__navigationId
- }
- });
- });
- let navigationId = 0;
- router.beforeEach((to, from) => {
- const data = {
- guard: formatDisplay("beforeEach"),
- from: formatRouteLocation(from, "Current Location during this navigation"),
- to: formatRouteLocation(to, "Target location")
- };
- Object.defineProperty(to.meta, "__navigationId", { value: navigationId++ });
- api.addTimelineEvent({
- layerId: navigationsLayerId,
- event: {
- time: api.now(),
- title: "Start of navigation",
- subtitle: to.fullPath,
- data,
- groupId: to.meta.__navigationId
- }
- });
- });
- router.afterEach((to, from, failure) => {
- const data = { guard: formatDisplay("afterEach") };
- if (failure) {
- data.failure = { _custom: {
- type: Error,
- readOnly: true,
- display: failure ? failure.message : "",
- tooltip: "Navigation Failure",
- value: failure
- } };
- data.status = formatDisplay("❌");
- } else data.status = formatDisplay("✅");
- data.from = formatRouteLocation(from, "Current Location during this navigation");
- data.to = formatRouteLocation(to, "Target location");
- api.addTimelineEvent({
- layerId: navigationsLayerId,
- event: {
- title: "End of navigation",
- subtitle: to.fullPath,
- time: api.now(),
- data,
- logType: failure ? "warning" : "default",
- groupId: to.meta.__navigationId
- }
- });
- });
- /**
- * Inspector of Existing routes
- */
- const routerInspectorId = "router-inspector:" + id;
- api.addInspector({
- id: routerInspectorId,
- label: "Routes" + (id ? " " + id : ""),
- icon: "book",
- treeFilterPlaceholder: "Search routes"
- });
- function refreshRoutesView() {
- if (!activeRoutesPayload) return;
- const payload = activeRoutesPayload;
- let routes = matcher.getRoutes().filter((route) => !route.parent || !route.parent.record.components);
- routes.forEach(resetMatchStateOnRouteRecord);
- if (payload.filter) routes = routes.filter((route) => isRouteMatching(route, payload.filter.toLowerCase()));
- routes.forEach((route) => markRouteRecordActive(route, router.currentRoute.value));
- payload.rootNodes = routes.map(formatRouteRecordForInspector);
- }
- let activeRoutesPayload;
- api.on.getInspectorTree((payload) => {
- activeRoutesPayload = payload;
- if (payload.app === app && payload.inspectorId === routerInspectorId) refreshRoutesView();
- });
- /**
- * Display information about the currently selected route record
- */
- api.on.getInspectorState((payload) => {
- if (payload.app === app && payload.inspectorId === routerInspectorId) {
- const route = matcher.getRoutes().find((route$1) => route$1.record.__vd_id === payload.nodeId);
- if (route) payload.state = { options: formatRouteRecordMatcherForStateInspector(route) };
- }
- });
- api.sendInspectorTree(routerInspectorId);
- api.sendInspectorState(routerInspectorId);
- });
- }
- function modifierForKey(key) {
- if (key.optional) return key.repeatable ? "*" : "?";
- else return key.repeatable ? "+" : "";
- }
- function formatRouteRecordMatcherForStateInspector(route) {
- const { record } = route;
- const fields = [{
- editable: false,
- key: "path",
- value: record.path
- }];
- if (record.name != null) fields.push({
- editable: false,
- key: "name",
- value: record.name
- });
- fields.push({
- editable: false,
- key: "regexp",
- value: route.re
- });
- if (route.keys.length) fields.push({
- editable: false,
- key: "keys",
- value: { _custom: {
- type: null,
- readOnly: true,
- display: route.keys.map((key) => `${key.name}${modifierForKey(key)}`).join(" "),
- tooltip: "Param keys",
- value: route.keys
- } }
- });
- if (record.redirect != null) fields.push({
- editable: false,
- key: "redirect",
- value: record.redirect
- });
- if (route.alias.length) fields.push({
- editable: false,
- key: "aliases",
- value: route.alias.map((alias) => alias.record.path)
- });
- if (Object.keys(route.record.meta).length) fields.push({
- editable: false,
- key: "meta",
- value: route.record.meta
- });
- fields.push({
- key: "score",
- editable: false,
- value: { _custom: {
- type: null,
- readOnly: true,
- display: route.score.map((score) => score.join(", ")).join(" | "),
- tooltip: "Score used to sort routes",
- value: route.score
- } }
- });
- return fields;
- }
- /**
- * Extracted from tailwind palette
- */
- const PINK_500 = 15485081;
- const BLUE_600 = 2450411;
- const LIME_500 = 8702998;
- const CYAN_400 = 2282478;
- const ORANGE_400 = 16486972;
- const DARK = 6710886;
- const RED_100 = 16704226;
- const RED_700 = 12131356;
- function formatRouteRecordForInspector(route) {
- const tags = [];
- const { record } = route;
- if (record.name != null) tags.push({
- label: String(record.name),
- textColor: 0,
- backgroundColor: CYAN_400
- });
- if (record.aliasOf) tags.push({
- label: "alias",
- textColor: 0,
- backgroundColor: ORANGE_400
- });
- if (route.__vd_match) tags.push({
- label: "matches",
- textColor: 0,
- backgroundColor: PINK_500
- });
- if (route.__vd_exactActive) tags.push({
- label: "exact",
- textColor: 0,
- backgroundColor: LIME_500
- });
- if (route.__vd_active) tags.push({
- label: "active",
- textColor: 0,
- backgroundColor: BLUE_600
- });
- if (record.redirect) tags.push({
- label: typeof record.redirect === "string" ? `redirect: ${record.redirect}` : "redirects",
- textColor: 16777215,
- backgroundColor: DARK
- });
- let id = record.__vd_id;
- if (id == null) {
- id = String(routeRecordId++);
- record.__vd_id = id;
- }
- return {
- id,
- label: record.path,
- tags,
- children: route.children.map(formatRouteRecordForInspector)
- };
- }
- let routeRecordId = 0;
- const EXTRACT_REGEXP_RE = /^\/(.*)\/([a-z]*)$/;
- function markRouteRecordActive(route, currentRoute) {
- const isExactActive = currentRoute.matched.length && isSameRouteRecord(currentRoute.matched[currentRoute.matched.length - 1], route.record);
- route.__vd_exactActive = route.__vd_active = isExactActive;
- if (!isExactActive) route.__vd_active = currentRoute.matched.some((match) => isSameRouteRecord(match, route.record));
- route.children.forEach((childRoute) => markRouteRecordActive(childRoute, currentRoute));
- }
- function resetMatchStateOnRouteRecord(route) {
- route.__vd_match = false;
- route.children.forEach(resetMatchStateOnRouteRecord);
- }
- function isRouteMatching(route, filter) {
- const found = String(route.re).match(EXTRACT_REGEXP_RE);
- route.__vd_match = false;
- if (!found || found.length < 3) return false;
- if (new RegExp(found[1].replace(/\$$/, ""), found[2]).test(filter)) {
- route.children.forEach((child) => isRouteMatching(child, filter));
- if (route.record.path !== "/" || filter === "/") {
- route.__vd_match = route.re.test(filter);
- return true;
- }
- return false;
- }
- const path = route.record.path.toLowerCase();
- const decodedPath = decode(path);
- if (!filter.startsWith("/") && (decodedPath.includes(filter) || path.includes(filter))) return true;
- if (decodedPath.startsWith(filter) || path.startsWith(filter)) return true;
- if (route.record.name && String(route.record.name).includes(filter)) return true;
- return route.children.some((child) => isRouteMatching(child, filter));
- }
- function omit(obj, keys) {
- const ret = {};
- for (const key in obj) if (!keys.includes(key)) ret[key] = obj[key];
- return ret;
- }
- //#endregion
- export { ErrorTypes, NEW_stringifyURL, NavigationDirection, NavigationFailureType, NavigationType, START, START_LOCATION_NORMALIZED, addDevtools, applyToParams, assign, computeScrollPosition, createHref, createRouterError, decode, encodeHash, encodeParam, encodePath, extractChangingRecords, extractComponentsGuards, getSavedScrollPosition, getScrollKey, guardToPromiseFn, identityFn, isArray, isBrowser, isNavigationFailure, isRouteLocation, isRouteName, isSameRouteLocation, isSameRouteLocationParams, isSameRouteRecord, loadRouteLocation, matchedRouteKey, mergeOptions, noop, normalizeBase, normalizeQuery, onBeforeRouteLeave, onBeforeRouteUpdate, parseQuery, parseURL, resolveRelativePath, routeLocationKey, routerKey, routerViewLocationKey, saveScrollPosition, scrollToPosition, stringifyQuery, stringifyURL, stripBase, useCallbacks, viewDepthKey, warn$1 as warn };
|