From 59d14f8ad314e703119ef8bce1b6823647ad4fb7 Mon Sep 17 00:00:00 2001 From: P-Jhao <113034340+P-Jhao@users.noreply.github.com> Date: Thu, 17 Oct 2024 16:22:54 +0800 Subject: [PATCH] Add func --- .vscode/extensions.json | 3 + README.md | 5 + index.html | 13 + node_modules/.bin/esbuild | 16 + node_modules/.bin/esbuild.cmd | 17 + node_modules/.bin/esbuild.ps1 | 28 + node_modules/.bin/nanoid | 16 + node_modules/.bin/nanoid.cmd | 17 + node_modules/.bin/nanoid.ps1 | 28 + node_modules/.bin/parser | 16 + node_modules/.bin/parser.cmd | 17 + node_modules/.bin/parser.ps1 | 28 + node_modules/.bin/rollup | 16 + node_modules/.bin/rollup.cmd | 17 + node_modules/.bin/rollup.ps1 | 28 + node_modules/.bin/vite | 16 + node_modules/.bin/vite.cmd | 17 + node_modules/.bin/vite.ps1 | 28 + node_modules/.package-lock.json | 493 + node_modules/.vite/deps/_metadata.json | 25 + node_modules/.vite/deps/chunk-BLKX25ZG.js | 12476 +++ node_modules/.vite/deps/chunk-BLKX25ZG.js.map | 7 + node_modules/.vite/deps/package.json | 3 + node_modules/.vite/deps/vue-router.js | 2911 + node_modules/.vite/deps/vue-router.js.map | 7 + node_modules/.vite/deps/vue.js | 343 + node_modules/.vite/deps/vue.js.map | 7 + .../@babel/helper-string-parser/LICENSE | 22 + .../@babel/helper-string-parser/README.md | 19 + .../@babel/helper-string-parser/lib/index.js | 295 + .../helper-string-parser/lib/index.js.map | 1 + .../@babel/helper-string-parser/package.json | 31 + .../helper-validator-identifier/LICENSE | 22 + .../helper-validator-identifier/README.md | 19 + .../lib/identifier.js | 70 + .../lib/identifier.js.map | 1 + .../helper-validator-identifier/lib/index.js | 57 + .../lib/index.js.map | 1 + .../lib/keyword.js | 35 + .../lib/keyword.js.map | 1 + .../helper-validator-identifier/package.json | 31 + .../scripts/generate-identifier-regex.js | 73 + node_modules/@babel/parser/CHANGELOG.md | 1073 + node_modules/@babel/parser/LICENSE | 19 + node_modules/@babel/parser/README.md | 19 + .../@babel/parser/bin/babel-parser.js | 15 + node_modules/@babel/parser/index.cjs | 5 + node_modules/@babel/parser/lib/index.js | 14009 ++++ node_modules/@babel/parser/lib/index.js.map | 1 + node_modules/@babel/parser/package.json | 50 + .../@babel/parser/typings/babel-parser.d.ts | 253 + node_modules/@babel/types/LICENSE | 22 + node_modules/@babel/types/README.md | 19 + .../@babel/types/lib/asserts/assertNode.js | 16 + .../types/lib/asserts/assertNode.js.map | 1 + .../types/lib/asserts/generated/index.js | 1235 + .../types/lib/asserts/generated/index.js.map | 1 + .../types/lib/ast-types/generated/index.js | 3 + .../lib/ast-types/generated/index.js.map | 1 + .../lib/builders/flow/createFlowUnionType.js | 18 + .../builders/flow/createFlowUnionType.js.map | 1 + .../flow/createTypeAnnotationBasedOnTypeof.js | 31 + .../createTypeAnnotationBasedOnTypeof.js.map | 1 + .../types/lib/builders/generated/index.js | 1991 + .../types/lib/builders/generated/index.js.map | 1 + .../types/lib/builders/generated/uppercase.js | 1532 + .../lib/builders/generated/uppercase.js.map | 1 + .../@babel/types/lib/builders/productions.js | 12 + .../types/lib/builders/productions.js.map | 1 + .../types/lib/builders/react/buildChildren.js | 24 + .../lib/builders/react/buildChildren.js.map | 1 + .../builders/typescript/createTSUnionType.js | 22 + .../typescript/createTSUnionType.js.map | 1 + .../@babel/types/lib/builders/validateNode.js | 17 + .../types/lib/builders/validateNode.js.map | 1 + node_modules/@babel/types/lib/clone/clone.js | 12 + .../@babel/types/lib/clone/clone.js.map | 1 + .../@babel/types/lib/clone/cloneDeep.js | 12 + .../@babel/types/lib/clone/cloneDeep.js.map | 1 + .../types/lib/clone/cloneDeepWithoutLoc.js | 12 + .../lib/clone/cloneDeepWithoutLoc.js.map | 1 + .../@babel/types/lib/clone/cloneNode.js | 107 + .../@babel/types/lib/clone/cloneNode.js.map | 1 + .../@babel/types/lib/clone/cloneWithoutLoc.js | 12 + .../types/lib/clone/cloneWithoutLoc.js.map | 1 + .../@babel/types/lib/comments/addComment.js | 15 + .../types/lib/comments/addComment.js.map | 1 + .../@babel/types/lib/comments/addComments.js | 22 + .../types/lib/comments/addComments.js.map | 1 + .../lib/comments/inheritInnerComments.js | 12 + .../lib/comments/inheritInnerComments.js.map | 1 + .../lib/comments/inheritLeadingComments.js | 12 + .../comments/inheritLeadingComments.js.map | 1 + .../lib/comments/inheritTrailingComments.js | 12 + .../comments/inheritTrailingComments.js.map | 1 + .../types/lib/comments/inheritsComments.js | 17 + .../lib/comments/inheritsComments.js.map | 1 + .../types/lib/comments/removeComments.js | 15 + .../types/lib/comments/removeComments.js.map | 1 + .../types/lib/constants/generated/index.js | 59 + .../lib/constants/generated/index.js.map | 1 + .../@babel/types/lib/constants/index.js | 31 + .../@babel/types/lib/constants/index.js.map | 1 + .../types/lib/converters/ensureBlock.js | 14 + .../types/lib/converters/ensureBlock.js.map | 1 + .../converters/gatherSequenceExpressions.js | 66 + .../gatherSequenceExpressions.js.map | 1 + .../lib/converters/toBindingIdentifierName.js | 14 + .../converters/toBindingIdentifierName.js.map | 1 + .../@babel/types/lib/converters/toBlock.js | 29 + .../types/lib/converters/toBlock.js.map | 1 + .../types/lib/converters/toComputedKey.js | 14 + .../types/lib/converters/toComputedKey.js.map | 1 + .../types/lib/converters/toExpression.js | 27 + .../types/lib/converters/toExpression.js.map | 1 + .../types/lib/converters/toIdentifier.js | 25 + .../types/lib/converters/toIdentifier.js.map | 1 + .../@babel/types/lib/converters/toKeyAlias.js | 38 + .../types/lib/converters/toKeyAlias.js.map | 1 + .../lib/converters/toSequenceExpression.js | 20 + .../converters/toSequenceExpression.js.map | 1 + .../types/lib/converters/toStatement.js | 39 + .../types/lib/converters/toStatement.js.map | 1 + .../types/lib/converters/valueToNode.js | 76 + .../types/lib/converters/valueToNode.js.map | 1 + .../@babel/types/lib/definitions/core.js | 1691 + .../@babel/types/lib/definitions/core.js.map | 1 + .../lib/definitions/deprecated-aliases.js | 11 + .../lib/definitions/deprecated-aliases.js.map | 1 + .../types/lib/definitions/experimental.js | 134 + .../types/lib/definitions/experimental.js.map | 1 + .../@babel/types/lib/definitions/flow.js | 491 + .../@babel/types/lib/definitions/flow.js.map | 1 + .../@babel/types/lib/definitions/index.js | 96 + .../@babel/types/lib/definitions/index.js.map | 1 + .../@babel/types/lib/definitions/jsx.js | 158 + .../@babel/types/lib/definitions/jsx.js.map | 1 + .../@babel/types/lib/definitions/misc.js | 32 + .../@babel/types/lib/definitions/misc.js.map | 1 + .../types/lib/definitions/placeholders.js | 27 + .../types/lib/definitions/placeholders.js.map | 1 + .../types/lib/definitions/typescript.js | 495 + .../types/lib/definitions/typescript.js.map | 1 + .../@babel/types/lib/definitions/utils.js | 273 + .../@babel/types/lib/definitions/utils.js.map | 1 + .../@babel/types/lib/index-legacy.d.ts | 2758 + node_modules/@babel/types/lib/index.d.ts | 3251 + node_modules/@babel/types/lib/index.js | 592 + node_modules/@babel/types/lib/index.js.flow | 2612 + node_modules/@babel/types/lib/index.js.map | 1 + .../modifications/appendToMemberExpression.js | 15 + .../appendToMemberExpression.js.map | 1 + .../flow/removeTypeDuplicates.js | 65 + .../flow/removeTypeDuplicates.js.map | 1 + .../types/lib/modifications/inherits.js | 28 + .../types/lib/modifications/inherits.js.map | 1 + .../prependToMemberExpression.js | 17 + .../prependToMemberExpression.js.map | 1 + .../lib/modifications/removeProperties.js | 24 + .../lib/modifications/removeProperties.js.map | 1 + .../lib/modifications/removePropertiesDeep.js | 14 + .../modifications/removePropertiesDeep.js.map | 1 + .../typescript/removeTypeDuplicates.js | 65 + .../typescript/removeTypeDuplicates.js.map | 1 + .../retrievers/getAssignmentIdentifiers.js | 48 + .../getAssignmentIdentifiers.js.map | 1 + .../lib/retrievers/getBindingIdentifiers.js | 101 + .../retrievers/getBindingIdentifiers.js.map | 1 + .../types/lib/retrievers/getFunctionName.js | 63 + .../lib/retrievers/getFunctionName.js.map | 1 + .../retrievers/getOuterBindingIdentifiers.js | 13 + .../getOuterBindingIdentifiers.js.map | 1 + .../@babel/types/lib/traverse/traverse.js | 50 + .../@babel/types/lib/traverse/traverse.js.map | 1 + .../@babel/types/lib/traverse/traverseFast.js | 26 + .../types/lib/traverse/traverseFast.js.map | 1 + .../types/lib/utils/deprecationWarning.js | 44 + .../types/lib/utils/deprecationWarning.js.map | 1 + .../@babel/types/lib/utils/inherit.js | 13 + .../@babel/types/lib/utils/inherit.js.map | 1 + .../react/cleanJSXElementLiteralChild.js | 40 + .../react/cleanJSXElementLiteralChild.js.map | 1 + .../@babel/types/lib/utils/shallowEqual.js | 17 + .../types/lib/utils/shallowEqual.js.map | 1 + .../validators/buildMatchMemberExpression.js | 13 + .../buildMatchMemberExpression.js.map | 1 + .../types/lib/validators/generated/index.js | 2752 + .../lib/validators/generated/index.js.map | 1 + .../@babel/types/lib/validators/is.js | 27 + .../@babel/types/lib/validators/is.js.map | 1 + .../@babel/types/lib/validators/isBinding.js | 27 + .../types/lib/validators/isBinding.js.map | 1 + .../types/lib/validators/isBlockScoped.js | 13 + .../types/lib/validators/isBlockScoped.js.map | 1 + .../types/lib/validators/isImmutable.js | 21 + .../types/lib/validators/isImmutable.js.map | 1 + .../@babel/types/lib/validators/isLet.js | 13 + .../@babel/types/lib/validators/isLet.js.map | 1 + .../@babel/types/lib/validators/isNode.js | 12 + .../@babel/types/lib/validators/isNode.js.map | 1 + .../types/lib/validators/isNodesEquivalent.js | 57 + .../lib/validators/isNodesEquivalent.js.map | 1 + .../types/lib/validators/isPlaceholderType.js | 19 + .../lib/validators/isPlaceholderType.js.map | 1 + .../types/lib/validators/isReferenced.js | 96 + .../types/lib/validators/isReferenced.js.map | 1 + .../@babel/types/lib/validators/isScope.js | 18 + .../types/lib/validators/isScope.js.map | 1 + .../lib/validators/isSpecifierDefault.js | 14 + .../lib/validators/isSpecifierDefault.js.map | 1 + .../@babel/types/lib/validators/isType.js | 22 + .../@babel/types/lib/validators/isType.js.map | 1 + .../lib/validators/isValidES3Identifier.js | 13 + .../validators/isValidES3Identifier.js.map | 1 + .../types/lib/validators/isValidIdentifier.js | 18 + .../lib/validators/isValidIdentifier.js.map | 1 + .../@babel/types/lib/validators/isVar.js | 15 + .../@babel/types/lib/validators/isVar.js.map | 1 + .../types/lib/validators/matchesPattern.js | 36 + .../lib/validators/matchesPattern.js.map | 1 + .../types/lib/validators/react/isCompatTag.js | 11 + .../lib/validators/react/isCompatTag.js.map | 1 + .../lib/validators/react/isReactComponent.js | 11 + .../validators/react/isReactComponent.js.map | 1 + .../@babel/types/lib/validators/validate.js | 30 + .../types/lib/validators/validate.js.map | 1 + node_modules/@babel/types/package.json | 40 + node_modules/@babel/types/tsconfig.json | 20 + .../@babel/types/tsconfig.tsbuildinfo | 1 + node_modules/@esbuild/win32-x64/README.md | 3 + node_modules/@esbuild/win32-x64/esbuild.exe | Bin 0 -> 9913856 bytes node_modules/@esbuild/win32-x64/package.json | 20 + .../@jridgewell/sourcemap-codec/LICENSE | 21 + .../@jridgewell/sourcemap-codec/README.md | 264 + .../sourcemap-codec/dist/sourcemap-codec.mjs | 424 + .../dist/sourcemap-codec.mjs.map | 1 + .../dist/sourcemap-codec.umd.js | 439 + .../dist/sourcemap-codec.umd.js.map | 1 + .../sourcemap-codec/dist/types/scopes.d.ts | 49 + .../dist/types/sourcemap-codec.d.ts | 8 + .../sourcemap-codec/dist/types/strings.d.ts | 15 + .../sourcemap-codec/dist/types/vlq.d.ts | 6 + .../@jridgewell/sourcemap-codec/package.json | 75 + .../@rollup/rollup-win32-x64-msvc/README.md | 3 + .../rollup-win32-x64-msvc/package.json | 19 + .../rollup.win32-x64-msvc.node | Bin 0 -> 3272192 bytes node_modules/@types/estree/LICENSE | 21 + node_modules/@types/estree/README.md | 15 + node_modules/@types/estree/flow.d.ts | 167 + node_modules/@types/estree/index.d.ts | 683 + node_modules/@types/estree/package.json | 26 + node_modules/@vitejs/plugin-vue/LICENSE | 21 + node_modules/@vitejs/plugin-vue/README.md | 261 + .../@vitejs/plugin-vue/dist/index.cjs | 2988 + .../@vitejs/plugin-vue/dist/index.d.cts | 102 + .../@vitejs/plugin-vue/dist/index.d.mts | 102 + .../@vitejs/plugin-vue/dist/index.d.ts | 102 + .../@vitejs/plugin-vue/dist/index.mjs | 2974 + node_modules/@vitejs/plugin-vue/package.json | 50 + node_modules/@vue/compiler-core/LICENSE | 21 + node_modules/@vue/compiler-core/README.md | 1 + .../compiler-core/dist/compiler-core.cjs.js | 6795 ++ .../dist/compiler-core.cjs.prod.js | 6672 ++ .../compiler-core/dist/compiler-core.d.ts | 1090 + .../dist/compiler-core.esm-bundler.js | 5780 ++ node_modules/@vue/compiler-core/index.js | 7 + node_modules/@vue/compiler-core/package.json | 58 + node_modules/@vue/compiler-dom/LICENSE | 21 + node_modules/@vue/compiler-dom/README.md | 1 + .../compiler-dom/dist/compiler-dom.cjs.js | 928 + .../dist/compiler-dom.cjs.prod.js | 686 + .../@vue/compiler-dom/dist/compiler-dom.d.ts | 45 + .../dist/compiler-dom.esm-browser.js | 6587 ++ .../dist/compiler-dom.esm-browser.prod.js | 11 + .../dist/compiler-dom.esm-bundler.js | 687 + .../compiler-dom/dist/compiler-dom.global.js | 6751 ++ .../dist/compiler-dom.global.prod.js | 11 + node_modules/@vue/compiler-dom/index.js | 7 + node_modules/@vue/compiler-dom/package.json | 57 + node_modules/@vue/compiler-sfc/LICENSE | 21 + node_modules/@vue/compiler-sfc/README.md | 80 + .../compiler-sfc/dist/compiler-sfc.cjs.js | 20930 +++++ .../@vue/compiler-sfc/dist/compiler-sfc.d.ts | 483 + .../dist/compiler-sfc.esm-browser.js | 48939 ++++++++++++ node_modules/@vue/compiler-sfc/package.json | 67 + node_modules/@vue/compiler-ssr/LICENSE | 21 + node_modules/@vue/compiler-ssr/README.md | 1 + .../compiler-ssr/dist/compiler-ssr.cjs.js | 1397 + .../@vue/compiler-ssr/dist/compiler-ssr.d.ts | 4 + node_modules/@vue/compiler-ssr/package.json | 34 + .../@vue/devtools-api/lib/cjs/api/api.js | 2 + .../@vue/devtools-api/lib/cjs/api/app.js | 2 + .../devtools-api/lib/cjs/api/component.js | 2 + .../@vue/devtools-api/lib/cjs/api/context.js | 2 + .../@vue/devtools-api/lib/cjs/api/hooks.js | 2 + .../@vue/devtools-api/lib/cjs/api/index.js | 22 + .../@vue/devtools-api/lib/cjs/api/util.js | 2 + .../@vue/devtools-api/lib/cjs/const.js | 5 + node_modules/@vue/devtools-api/lib/cjs/env.js | 17 + .../@vue/devtools-api/lib/cjs/index.js | 45 + .../@vue/devtools-api/lib/cjs/plugin.js | 2 + .../@vue/devtools-api/lib/cjs/proxy.js | 111 + .../@vue/devtools-api/lib/cjs/time.js | 28 + .../@vue/devtools-api/lib/esm/api/api.d.ts | 108 + .../@vue/devtools-api/lib/esm/api/api.js | 1 + .../@vue/devtools-api/lib/esm/api/app.d.ts | 1 + .../@vue/devtools-api/lib/esm/api/app.js | 1 + .../devtools-api/lib/esm/api/component.d.ts | 78 + .../devtools-api/lib/esm/api/component.js | 1 + .../devtools-api/lib/esm/api/context.d.ts | 5 + .../@vue/devtools-api/lib/esm/api/context.js | 1 + .../@vue/devtools-api/lib/esm/api/hooks.d.ts | 180 + .../@vue/devtools-api/lib/esm/api/hooks.js | 1 + .../@vue/devtools-api/lib/esm/api/index.d.ts | 6 + .../@vue/devtools-api/lib/esm/api/index.js | 6 + .../@vue/devtools-api/lib/esm/api/util.d.ts | 4 + .../@vue/devtools-api/lib/esm/api/util.js | 1 + .../@vue/devtools-api/lib/esm/const.d.ts | 2 + .../@vue/devtools-api/lib/esm/const.js | 2 + .../@vue/devtools-api/lib/esm/env.d.ts | 15 + node_modules/@vue/devtools-api/lib/esm/env.js | 12 + .../@vue/devtools-api/lib/esm/index.d.ts | 18 + .../@vue/devtools-api/lib/esm/index.js | 27 + .../@vue/devtools-api/lib/esm/plugin.d.ts | 47 + .../@vue/devtools-api/lib/esm/plugin.js | 1 + .../@vue/devtools-api/lib/esm/proxy.d.ts | 20 + .../@vue/devtools-api/lib/esm/proxy.js | 107 + .../@vue/devtools-api/lib/esm/time.d.ts | 2 + .../@vue/devtools-api/lib/esm/time.js | 23 + node_modules/@vue/devtools-api/package.json | 37 + node_modules/@vue/reactivity/LICENSE | 21 + node_modules/@vue/reactivity/README.md | 19 + .../@vue/reactivity/dist/reactivity.cjs.js | 1960 + .../reactivity/dist/reactivity.cjs.prod.js | 1815 + .../@vue/reactivity/dist/reactivity.d.ts | 751 + .../reactivity/dist/reactivity.esm-browser.js | 1959 + .../dist/reactivity.esm-browser.prod.js | 5 + .../reactivity/dist/reactivity.esm-bundler.js | 1917 + .../@vue/reactivity/dist/reactivity.global.js | 2015 + .../reactivity/dist/reactivity.global.prod.js | 5 + node_modules/@vue/reactivity/index.js | 7 + node_modules/@vue/reactivity/package.json | 55 + node_modules/@vue/runtime-core/LICENSE | 21 + node_modules/@vue/runtime-core/README.md | 28 + .../runtime-core/dist/runtime-core.cjs.js | 8409 ++ .../dist/runtime-core.cjs.prod.js | 6578 ++ .../@vue/runtime-core/dist/runtime-core.d.ts | 1831 + .../dist/runtime-core.esm-bundler.js | 8335 ++ node_modules/@vue/runtime-core/index.js | 7 + node_modules/@vue/runtime-core/package.json | 52 + node_modules/@vue/runtime-dom/LICENSE | 21 + node_modules/@vue/runtime-dom/README.md | 13 + .../@vue/runtime-dom/dist/runtime-dom.cjs.js | 1811 + .../runtime-dom/dist/runtime-dom.cjs.prod.js | 1660 + .../@vue/runtime-dom/dist/runtime-dom.d.ts | 1395 + .../dist/runtime-dom.esm-browser.js | 12260 +++ .../dist/runtime-dom.esm-browser.prod.js | 5 + .../dist/runtime-dom.esm-bundler.js | 1850 + .../runtime-dom/dist/runtime-dom.global.js | 12317 +++ .../dist/runtime-dom.global.prod.js | 5 + node_modules/@vue/runtime-dom/index.js | 7 + node_modules/@vue/runtime-dom/package.json | 60 + node_modules/@vue/server-renderer/LICENSE | 21 + node_modules/@vue/server-renderer/README.md | 178 + .../dist/server-renderer.cjs.js | 1129 + .../dist/server-renderer.cjs.prod.js | 857 + .../server-renderer/dist/server-renderer.d.ts | 65 + .../dist/server-renderer.esm-browser.js | 8572 ++ .../dist/server-renderer.esm-browser.prod.js | 5 + .../dist/server-renderer.esm-bundler.js | 1203 + node_modules/@vue/server-renderer/index.js | 7 + .../@vue/server-renderer/package.json | 55 + node_modules/@vue/shared/LICENSE | 21 + node_modules/@vue/shared/README.md | 3 + node_modules/@vue/shared/dist/shared.cjs.js | 584 + .../@vue/shared/dist/shared.cjs.prod.js | 584 + node_modules/@vue/shared/dist/shared.d.ts | 322 + .../@vue/shared/dist/shared.esm-bundler.js | 511 + node_modules/@vue/shared/index.js | 7 + node_modules/@vue/shared/package.json | 47 + node_modules/csstype/LICENSE | 19 + node_modules/csstype/README.md | 277 + node_modules/csstype/index.d.ts | 21297 +++++ node_modules/csstype/index.js.flow | 6612 ++ node_modules/csstype/package.json | 66 + node_modules/entities/LICENSE | 11 + node_modules/entities/lib/decode.d.ts | 211 + node_modules/entities/lib/decode.d.ts.map | 1 + node_modules/entities/lib/decode.js | 536 + node_modules/entities/lib/decode.js.map | 1 + .../entities/lib/decode_codepoint.d.ts | 19 + .../entities/lib/decode_codepoint.d.ts.map | 1 + node_modules/entities/lib/decode_codepoint.js | 76 + .../entities/lib/decode_codepoint.js.map | 1 + node_modules/entities/lib/encode.d.ts | 22 + node_modules/entities/lib/encode.d.ts.map | 1 + node_modules/entities/lib/encode.js | 77 + node_modules/entities/lib/encode.js.map | 1 + node_modules/entities/lib/escape.d.ts | 43 + node_modules/entities/lib/escape.d.ts.map | 1 + node_modules/entities/lib/escape.js | 122 + node_modules/entities/lib/escape.js.map | 1 + node_modules/entities/lib/esm/decode.d.ts | 211 + node_modules/entities/lib/esm/decode.d.ts.map | 1 + node_modules/entities/lib/esm/decode.js | 496 + node_modules/entities/lib/esm/decode.js.map | 1 + .../entities/lib/esm/decode_codepoint.d.ts | 19 + .../lib/esm/decode_codepoint.d.ts.map | 1 + .../entities/lib/esm/decode_codepoint.js | 71 + .../entities/lib/esm/decode_codepoint.js.map | 1 + node_modules/entities/lib/esm/encode.d.ts | 22 + node_modules/entities/lib/esm/encode.d.ts.map | 1 + node_modules/entities/lib/esm/encode.js | 69 + node_modules/entities/lib/esm/encode.js.map | 1 + node_modules/entities/lib/esm/escape.d.ts | 43 + node_modules/entities/lib/esm/escape.d.ts.map | 1 + node_modules/entities/lib/esm/escape.js | 116 + node_modules/entities/lib/esm/escape.js.map | 1 + .../lib/esm/generated/decode-data-html.d.ts | 3 + .../esm/generated/decode-data-html.d.ts.map | 1 + .../lib/esm/generated/decode-data-html.js | 7 + .../lib/esm/generated/decode-data-html.js.map | 1 + .../lib/esm/generated/decode-data-xml.d.ts | 3 + .../esm/generated/decode-data-xml.d.ts.map | 1 + .../lib/esm/generated/decode-data-xml.js | 7 + .../lib/esm/generated/decode-data-xml.js.map | 1 + .../lib/esm/generated/encode-html.d.ts | 8 + .../lib/esm/generated/encode-html.d.ts.map | 1 + .../entities/lib/esm/generated/encode-html.js | 10 + .../lib/esm/generated/encode-html.js.map | 1 + node_modules/entities/lib/esm/index.d.ts | 96 + node_modules/entities/lib/esm/index.d.ts.map | 1 + node_modules/entities/lib/esm/index.js | 99 + node_modules/entities/lib/esm/index.js.map | 1 + node_modules/entities/lib/esm/package.json | 1 + .../lib/generated/decode-data-html.d.ts | 3 + .../lib/generated/decode-data-html.d.ts.map | 1 + .../lib/generated/decode-data-html.js | 9 + .../lib/generated/decode-data-html.js.map | 1 + .../lib/generated/decode-data-xml.d.ts | 3 + .../lib/generated/decode-data-xml.d.ts.map | 1 + .../entities/lib/generated/decode-data-xml.js | 9 + .../lib/generated/decode-data-xml.js.map | 1 + .../entities/lib/generated/encode-html.d.ts | 8 + .../lib/generated/encode-html.d.ts.map | 1 + .../entities/lib/generated/encode-html.js | 12 + .../entities/lib/generated/encode-html.js.map | 1 + node_modules/entities/lib/index.d.ts | 96 + node_modules/entities/lib/index.d.ts.map | 1 + node_modules/entities/lib/index.js | 126 + node_modules/entities/lib/index.js.map | 1 + node_modules/entities/package.json | 90 + node_modules/entities/readme.md | 122 + node_modules/esbuild/LICENSE.md | 21 + node_modules/esbuild/README.md | 3 + node_modules/esbuild/bin/esbuild | 220 + node_modules/esbuild/install.js | 285 + node_modules/esbuild/lib/main.d.ts | 705 + node_modules/esbuild/lib/main.js | 2239 + node_modules/esbuild/package.json | 46 + node_modules/estree-walker/CHANGELOG.md | 92 + node_modules/estree-walker/LICENSE | 7 + node_modules/estree-walker/README.md | 48 + .../estree-walker/dist/esm/estree-walker.js | 333 + .../estree-walker/dist/esm/package.json | 1 + .../estree-walker/dist/umd/estree-walker.js | 344 + node_modules/estree-walker/package.json | 37 + node_modules/estree-walker/src/async.js | 118 + node_modules/estree-walker/src/index.js | 35 + node_modules/estree-walker/src/package.json | 1 + node_modules/estree-walker/src/sync.js | 118 + node_modules/estree-walker/src/walker.js | 61 + node_modules/estree-walker/types/async.d.ts | 53 + node_modules/estree-walker/types/index.d.ts | 56 + node_modules/estree-walker/types/sync.d.ts | 53 + .../estree-walker/types/tsconfig.tsbuildinfo | 345 + node_modules/estree-walker/types/walker.d.ts | 37 + node_modules/magic-string/LICENSE | 7 + node_modules/magic-string/README.md | 304 + .../magic-string/dist/magic-string.cjs.d.ts | 268 + .../magic-string/dist/magic-string.cjs.js | 1555 + .../magic-string/dist/magic-string.cjs.js.map | 1 + .../magic-string/dist/magic-string.es.d.mts | 268 + .../magic-string/dist/magic-string.es.mjs | 1549 + .../magic-string/dist/magic-string.es.mjs.map | 1 + .../magic-string/dist/magic-string.umd.js | 1652 + .../magic-string/dist/magic-string.umd.js.map | 1 + node_modules/magic-string/package.json | 63 + node_modules/nanoid/LICENSE | 20 + node_modules/nanoid/README.md | 39 + node_modules/nanoid/async/index.browser.cjs | 34 + node_modules/nanoid/async/index.browser.js | 34 + node_modules/nanoid/async/index.cjs | 35 + node_modules/nanoid/async/index.d.ts | 56 + node_modules/nanoid/async/index.js | 35 + node_modules/nanoid/async/index.native.js | 26 + node_modules/nanoid/async/package.json | 12 + node_modules/nanoid/bin/nanoid.cjs | 55 + node_modules/nanoid/index.browser.cjs | 34 + node_modules/nanoid/index.browser.js | 34 + node_modules/nanoid/index.cjs | 45 + node_modules/nanoid/index.d.cts | 91 + node_modules/nanoid/index.d.ts | 91 + node_modules/nanoid/index.js | 45 + node_modules/nanoid/nanoid.js | 1 + node_modules/nanoid/non-secure/index.cjs | 21 + node_modules/nanoid/non-secure/index.d.ts | 33 + node_modules/nanoid/non-secure/index.js | 21 + node_modules/nanoid/non-secure/package.json | 6 + node_modules/nanoid/package.json | 88 + node_modules/nanoid/url-alphabet/index.cjs | 3 + node_modules/nanoid/url-alphabet/index.js | 3 + node_modules/nanoid/url-alphabet/package.json | 6 + node_modules/picocolors/LICENSE | 15 + node_modules/picocolors/README.md | 177 + node_modules/picocolors/package.json | 49 + node_modules/picocolors/picocolors.browser.js | 4 + node_modules/picocolors/picocolors.d.ts | 5 + node_modules/picocolors/picocolors.js | 85 + node_modules/picocolors/types.ts | 52 + node_modules/postcss/LICENSE | 20 + node_modules/postcss/README.md | 28 + node_modules/postcss/lib/at-rule.d.ts | 140 + node_modules/postcss/lib/at-rule.js | 25 + node_modules/postcss/lib/comment.d.ts | 68 + node_modules/postcss/lib/comment.js | 13 + node_modules/postcss/lib/container.d.ts | 483 + node_modules/postcss/lib/container.js | 445 + .../postcss/lib/css-syntax-error.d.ts | 248 + node_modules/postcss/lib/css-syntax-error.js | 133 + node_modules/postcss/lib/declaration.d.ts | 151 + node_modules/postcss/lib/declaration.js | 24 + node_modules/postcss/lib/document.d.ts | 69 + node_modules/postcss/lib/document.js | 33 + node_modules/postcss/lib/fromJSON.d.ts | 9 + node_modules/postcss/lib/fromJSON.js | 54 + node_modules/postcss/lib/input.d.ts | 197 + node_modules/postcss/lib/input.js | 248 + node_modules/postcss/lib/lazy-result.d.ts | 190 + node_modules/postcss/lib/lazy-result.js | 550 + node_modules/postcss/lib/list.d.ts | 60 + node_modules/postcss/lib/list.js | 58 + node_modules/postcss/lib/map-generator.js | 368 + node_modules/postcss/lib/no-work-result.d.ts | 46 + node_modules/postcss/lib/no-work-result.js | 138 + node_modules/postcss/lib/node.d.ts | 541 + node_modules/postcss/lib/node.js | 389 + node_modules/postcss/lib/parse.d.ts | 9 + node_modules/postcss/lib/parse.js | 42 + node_modules/postcss/lib/parser.js | 609 + node_modules/postcss/lib/postcss.d.mts | 69 + node_modules/postcss/lib/postcss.d.ts | 453 + node_modules/postcss/lib/postcss.js | 101 + node_modules/postcss/lib/postcss.mjs | 30 + node_modules/postcss/lib/previous-map.d.ts | 81 + node_modules/postcss/lib/previous-map.js | 144 + node_modules/postcss/lib/processor.d.ts | 115 + node_modules/postcss/lib/processor.js | 67 + node_modules/postcss/lib/result.d.ts | 205 + node_modules/postcss/lib/result.js | 42 + node_modules/postcss/lib/root.d.ts | 87 + node_modules/postcss/lib/root.js | 61 + node_modules/postcss/lib/rule.d.ts | 126 + node_modules/postcss/lib/rule.js | 27 + node_modules/postcss/lib/stringifier.d.ts | 46 + node_modules/postcss/lib/stringifier.js | 353 + node_modules/postcss/lib/stringify.d.ts | 9 + node_modules/postcss/lib/stringify.js | 11 + node_modules/postcss/lib/symbols.js | 5 + .../postcss/lib/terminal-highlight.js | 70 + node_modules/postcss/lib/tokenize.js | 266 + node_modules/postcss/lib/warn-once.js | 13 + node_modules/postcss/lib/warning.d.ts | 147 + node_modules/postcss/lib/warning.js | 37 + node_modules/postcss/package.json | 88 + node_modules/rollup/LICENSE.md | 653 + node_modules/rollup/README.md | 134 + node_modules/rollup/dist/bin/rollup | 1762 + node_modules/rollup/dist/es/getLogFilter.js | 64 + node_modules/rollup/dist/es/package.json | 1 + node_modules/rollup/dist/es/parseAst.js | 12 + node_modules/rollup/dist/es/rollup.js | 18 + .../rollup/dist/es/shared/node-entry.js | 21332 +++++ .../rollup/dist/es/shared/parseAst.js | 1926 + node_modules/rollup/dist/es/shared/watch.js | 4883 ++ node_modules/rollup/dist/getLogFilter.d.ts | 5 + node_modules/rollup/dist/getLogFilter.js | 69 + node_modules/rollup/dist/loadConfigFile.d.ts | 20 + node_modules/rollup/dist/loadConfigFile.js | 30 + node_modules/rollup/dist/native.js | 105 + node_modules/rollup/dist/parseAst.d.ts | 4 + node_modules/rollup/dist/parseAst.js | 22 + node_modules/rollup/dist/rollup.d.ts | 1014 + node_modules/rollup/dist/rollup.js | 100 + .../rollup/dist/shared/fsevents-importer.js | 37 + node_modules/rollup/dist/shared/index.js | 4590 ++ .../rollup/dist/shared/loadConfigFile.js | 553 + node_modules/rollup/dist/shared/parseAst.js | 2149 + node_modules/rollup/dist/shared/rollup.js | 21325 +++++ node_modules/rollup/dist/shared/watch-cli.js | 563 + node_modules/rollup/dist/shared/watch.js | 323 + node_modules/rollup/package.json | 260 + node_modules/source-map-js/LICENSE | 28 + node_modules/source-map-js/README.md | 765 + node_modules/source-map-js/lib/array-set.js | 121 + node_modules/source-map-js/lib/base64-vlq.js | 140 + node_modules/source-map-js/lib/base64.js | 67 + .../source-map-js/lib/binary-search.js | 111 + .../source-map-js/lib/mapping-list.js | 79 + node_modules/source-map-js/lib/quick-sort.js | 132 + .../lib/source-map-consumer.d.ts | 1 + .../source-map-js/lib/source-map-consumer.js | 1188 + .../lib/source-map-generator.d.ts | 1 + .../source-map-js/lib/source-map-generator.js | 444 + .../source-map-js/lib/source-node.d.ts | 1 + node_modules/source-map-js/lib/source-node.js | 413 + node_modules/source-map-js/lib/util.js | 594 + node_modules/source-map-js/package.json | 71 + node_modules/source-map-js/source-map.d.ts | 104 + node_modules/source-map-js/source-map.js | 8 + node_modules/to-fast-properties/index.js | 27 + node_modules/to-fast-properties/license | 10 + node_modules/to-fast-properties/package.json | 35 + node_modules/to-fast-properties/readme.md | 37 + node_modules/vite/LICENSE.md | 3423 + node_modules/vite/README.md | 20 + node_modules/vite/bin/openChrome.applescript | 95 + node_modules/vite/bin/vite.js | 61 + node_modules/vite/client.d.ts | 256 + node_modules/vite/dist/client/client.mjs | 825 + node_modules/vite/dist/client/env.mjs | 24 + .../vite/dist/node-cjs/publicUtils.cjs | 6165 ++ .../vite/dist/node/chunks/dep-BEPV0aRC.js | 993 + .../vite/dist/node/chunks/dep-CUvs3bbV.js | 66703 ++++++++++++++++ .../vite/dist/node/chunks/dep-D-7KCb9p.js | 7960 ++ .../vite/dist/node/chunks/dep-DdUJenm9.js | 6843 ++ .../vite/dist/node/chunks/dep-IQS-Za7F.js | 561 + node_modules/vite/dist/node/cli.js | 916 + node_modules/vite/dist/node/constants.js | 112 + node_modules/vite/dist/node/index.d.ts | 3578 + node_modules/vite/dist/node/index.js | 260 + node_modules/vite/dist/node/runtime.d.ts | 63 + node_modules/vite/dist/node/runtime.js | 1066 + .../vite/dist/node/types.d-aGj9QkWt.d.ts | 281 + node_modules/vite/index.cjs | 60 + node_modules/vite/index.d.cts | 6 + node_modules/vite/package.json | 191 + node_modules/vite/types/customEvent.d.ts | 39 + node_modules/vite/types/hmrPayload.d.ts | 65 + node_modules/vite/types/hot.d.ts | 36 + node_modules/vite/types/import-meta.d.ts | 5 + node_modules/vite/types/importGlob.d.ts | 75 + node_modules/vite/types/importMeta.d.ts | 22 + node_modules/vite/types/metadata.d.ts | 10 + node_modules/vite/types/package.json | 4 + node_modules/vue-router/LICENSE | 21 + node_modules/vue-router/README.md | 95 + node_modules/vue-router/dist/vue-router.cjs | 3764 + .../vue-router/dist/vue-router.cjs.js | 1 + .../vue-router/dist/vue-router.cjs.prod.js | 1 + node_modules/vue-router/dist/vue-router.d.ts | 1826 + .../vue-router/dist/vue-router.esm-browser.js | 3741 + .../vue-router/dist/vue-router.esm-bundler.js | 1 + .../vue-router/dist/vue-router.global.js | 3934 + .../vue-router/dist/vue-router.global.prod.js | 6 + node_modules/vue-router/dist/vue-router.mjs | 3759 + .../vue-router/dist/vue-router.node.mjs | 2 + .../vue-router/dist/vue-router.prod.cjs | 2953 + node_modules/vue-router/index.js | 7 + node_modules/vue-router/package.json | 153 + node_modules/vue-router/vetur/attributes.json | 32 + node_modules/vue-router/vetur/tags.json | 10 + .../vue-router/vue-router-auto-routes.d.ts | 4 + node_modules/vue-router/vue-router-auto.d.ts | 4 + node_modules/vue/LICENSE | 21 + node_modules/vue/README.md | 62 + .../vue/compiler-sfc/index.browser.js | 1 + .../vue/compiler-sfc/index.browser.mjs | 1 + node_modules/vue/compiler-sfc/index.d.mts | 1 + node_modules/vue/compiler-sfc/index.d.ts | 1 + node_modules/vue/compiler-sfc/index.js | 3 + node_modules/vue/compiler-sfc/index.mjs | 3 + node_modules/vue/compiler-sfc/package.json | 4 + node_modules/vue/compiler-sfc/register-ts.js | 3 + node_modules/vue/dist/vue.cjs.js | 89 + node_modules/vue/dist/vue.cjs.prod.js | 75 + node_modules/vue/dist/vue.d.mts | 7 + node_modules/vue/dist/vue.d.ts | 7 + node_modules/vue/dist/vue.esm-browser.js | 18137 +++++ node_modules/vue/dist/vue.esm-browser.prod.js | 9 + node_modules/vue/dist/vue.esm-bundler.js | 80 + node_modules/vue/dist/vue.global.js | 18023 +++++ node_modules/vue/dist/vue.global.prod.js | 9 + .../vue/dist/vue.runtime.esm-browser.js | 12283 +++ .../vue/dist/vue.runtime.esm-browser.prod.js | 5 + .../vue/dist/vue.runtime.esm-bundler.js | 26 + node_modules/vue/dist/vue.runtime.global.js | 12341 +++ .../vue/dist/vue.runtime.global.prod.js | 5 + node_modules/vue/index.js | 7 + node_modules/vue/index.mjs | 1 + node_modules/vue/jsx-runtime/index.d.ts | 25 + node_modules/vue/jsx-runtime/index.js | 15 + node_modules/vue/jsx-runtime/index.mjs | 12 + node_modules/vue/jsx-runtime/package.json | 5 + node_modules/vue/jsx.d.ts | 22 + node_modules/vue/package.json | 112 + node_modules/vue/server-renderer/index.d.mts | 1 + node_modules/vue/server-renderer/index.d.ts | 1 + node_modules/vue/server-renderer/index.js | 1 + node_modules/vue/server-renderer/index.mjs | 1 + node_modules/vue/server-renderer/package.json | 4 + package-lock.json | 1104 + package.json | 19 + public/vite.svg | 1 + src | 1 + vite.config.js | 7 + 716 files changed, 555689 insertions(+) create mode 100644 .vscode/extensions.json create mode 100644 README.md create mode 100644 index.html create mode 100644 node_modules/.bin/esbuild create mode 100644 node_modules/.bin/esbuild.cmd create mode 100644 node_modules/.bin/esbuild.ps1 create mode 100644 node_modules/.bin/nanoid create mode 100644 node_modules/.bin/nanoid.cmd create mode 100644 node_modules/.bin/nanoid.ps1 create mode 100644 node_modules/.bin/parser create mode 100644 node_modules/.bin/parser.cmd create mode 100644 node_modules/.bin/parser.ps1 create mode 100644 node_modules/.bin/rollup create mode 100644 node_modules/.bin/rollup.cmd create mode 100644 node_modules/.bin/rollup.ps1 create mode 100644 node_modules/.bin/vite create mode 100644 node_modules/.bin/vite.cmd create mode 100644 node_modules/.bin/vite.ps1 create mode 100644 node_modules/.package-lock.json create mode 100644 node_modules/.vite/deps/_metadata.json create mode 100644 node_modules/.vite/deps/chunk-BLKX25ZG.js create mode 100644 node_modules/.vite/deps/chunk-BLKX25ZG.js.map create mode 100644 node_modules/.vite/deps/package.json create mode 100644 node_modules/.vite/deps/vue-router.js create mode 100644 node_modules/.vite/deps/vue-router.js.map create mode 100644 node_modules/.vite/deps/vue.js create mode 100644 node_modules/.vite/deps/vue.js.map create mode 100644 node_modules/@babel/helper-string-parser/LICENSE create mode 100644 node_modules/@babel/helper-string-parser/README.md create mode 100644 node_modules/@babel/helper-string-parser/lib/index.js create mode 100644 node_modules/@babel/helper-string-parser/lib/index.js.map create mode 100644 node_modules/@babel/helper-string-parser/package.json create mode 100644 node_modules/@babel/helper-validator-identifier/LICENSE create mode 100644 node_modules/@babel/helper-validator-identifier/README.md create mode 100644 node_modules/@babel/helper-validator-identifier/lib/identifier.js create mode 100644 node_modules/@babel/helper-validator-identifier/lib/identifier.js.map create mode 100644 node_modules/@babel/helper-validator-identifier/lib/index.js create mode 100644 node_modules/@babel/helper-validator-identifier/lib/index.js.map create mode 100644 node_modules/@babel/helper-validator-identifier/lib/keyword.js create mode 100644 node_modules/@babel/helper-validator-identifier/lib/keyword.js.map create mode 100644 node_modules/@babel/helper-validator-identifier/package.json create mode 100644 node_modules/@babel/helper-validator-identifier/scripts/generate-identifier-regex.js create mode 100644 node_modules/@babel/parser/CHANGELOG.md create mode 100644 node_modules/@babel/parser/LICENSE create mode 100644 node_modules/@babel/parser/README.md create mode 100644 node_modules/@babel/parser/bin/babel-parser.js create mode 100644 node_modules/@babel/parser/index.cjs create mode 100644 node_modules/@babel/parser/lib/index.js create mode 100644 node_modules/@babel/parser/lib/index.js.map create mode 100644 node_modules/@babel/parser/package.json create mode 100644 node_modules/@babel/parser/typings/babel-parser.d.ts create mode 100644 node_modules/@babel/types/LICENSE create mode 100644 node_modules/@babel/types/README.md create mode 100644 node_modules/@babel/types/lib/asserts/assertNode.js create mode 100644 node_modules/@babel/types/lib/asserts/assertNode.js.map create mode 100644 node_modules/@babel/types/lib/asserts/generated/index.js create mode 100644 node_modules/@babel/types/lib/asserts/generated/index.js.map create mode 100644 node_modules/@babel/types/lib/ast-types/generated/index.js create mode 100644 node_modules/@babel/types/lib/ast-types/generated/index.js.map create mode 100644 node_modules/@babel/types/lib/builders/flow/createFlowUnionType.js create mode 100644 node_modules/@babel/types/lib/builders/flow/createFlowUnionType.js.map create mode 100644 node_modules/@babel/types/lib/builders/flow/createTypeAnnotationBasedOnTypeof.js create mode 100644 node_modules/@babel/types/lib/builders/flow/createTypeAnnotationBasedOnTypeof.js.map create mode 100644 node_modules/@babel/types/lib/builders/generated/index.js create mode 100644 node_modules/@babel/types/lib/builders/generated/index.js.map create mode 100644 node_modules/@babel/types/lib/builders/generated/uppercase.js create mode 100644 node_modules/@babel/types/lib/builders/generated/uppercase.js.map create mode 100644 node_modules/@babel/types/lib/builders/productions.js create mode 100644 node_modules/@babel/types/lib/builders/productions.js.map create mode 100644 node_modules/@babel/types/lib/builders/react/buildChildren.js create mode 100644 node_modules/@babel/types/lib/builders/react/buildChildren.js.map create mode 100644 node_modules/@babel/types/lib/builders/typescript/createTSUnionType.js create mode 100644 node_modules/@babel/types/lib/builders/typescript/createTSUnionType.js.map create mode 100644 node_modules/@babel/types/lib/builders/validateNode.js create mode 100644 node_modules/@babel/types/lib/builders/validateNode.js.map create mode 100644 node_modules/@babel/types/lib/clone/clone.js create mode 100644 node_modules/@babel/types/lib/clone/clone.js.map create mode 100644 node_modules/@babel/types/lib/clone/cloneDeep.js create mode 100644 node_modules/@babel/types/lib/clone/cloneDeep.js.map create mode 100644 node_modules/@babel/types/lib/clone/cloneDeepWithoutLoc.js create mode 100644 node_modules/@babel/types/lib/clone/cloneDeepWithoutLoc.js.map create mode 100644 node_modules/@babel/types/lib/clone/cloneNode.js create mode 100644 node_modules/@babel/types/lib/clone/cloneNode.js.map create mode 100644 node_modules/@babel/types/lib/clone/cloneWithoutLoc.js create mode 100644 node_modules/@babel/types/lib/clone/cloneWithoutLoc.js.map create mode 100644 node_modules/@babel/types/lib/comments/addComment.js create mode 100644 node_modules/@babel/types/lib/comments/addComment.js.map create mode 100644 node_modules/@babel/types/lib/comments/addComments.js create mode 100644 node_modules/@babel/types/lib/comments/addComments.js.map create mode 100644 node_modules/@babel/types/lib/comments/inheritInnerComments.js create mode 100644 node_modules/@babel/types/lib/comments/inheritInnerComments.js.map create mode 100644 node_modules/@babel/types/lib/comments/inheritLeadingComments.js create mode 100644 node_modules/@babel/types/lib/comments/inheritLeadingComments.js.map create mode 100644 node_modules/@babel/types/lib/comments/inheritTrailingComments.js create mode 100644 node_modules/@babel/types/lib/comments/inheritTrailingComments.js.map create mode 100644 node_modules/@babel/types/lib/comments/inheritsComments.js create mode 100644 node_modules/@babel/types/lib/comments/inheritsComments.js.map create mode 100644 node_modules/@babel/types/lib/comments/removeComments.js create mode 100644 node_modules/@babel/types/lib/comments/removeComments.js.map create mode 100644 node_modules/@babel/types/lib/constants/generated/index.js create mode 100644 node_modules/@babel/types/lib/constants/generated/index.js.map create mode 100644 node_modules/@babel/types/lib/constants/index.js create mode 100644 node_modules/@babel/types/lib/constants/index.js.map create mode 100644 node_modules/@babel/types/lib/converters/ensureBlock.js create mode 100644 node_modules/@babel/types/lib/converters/ensureBlock.js.map create mode 100644 node_modules/@babel/types/lib/converters/gatherSequenceExpressions.js create mode 100644 node_modules/@babel/types/lib/converters/gatherSequenceExpressions.js.map create mode 100644 node_modules/@babel/types/lib/converters/toBindingIdentifierName.js create mode 100644 node_modules/@babel/types/lib/converters/toBindingIdentifierName.js.map create mode 100644 node_modules/@babel/types/lib/converters/toBlock.js create mode 100644 node_modules/@babel/types/lib/converters/toBlock.js.map create mode 100644 node_modules/@babel/types/lib/converters/toComputedKey.js create mode 100644 node_modules/@babel/types/lib/converters/toComputedKey.js.map create mode 100644 node_modules/@babel/types/lib/converters/toExpression.js create mode 100644 node_modules/@babel/types/lib/converters/toExpression.js.map create mode 100644 node_modules/@babel/types/lib/converters/toIdentifier.js create mode 100644 node_modules/@babel/types/lib/converters/toIdentifier.js.map create mode 100644 node_modules/@babel/types/lib/converters/toKeyAlias.js create mode 100644 node_modules/@babel/types/lib/converters/toKeyAlias.js.map create mode 100644 node_modules/@babel/types/lib/converters/toSequenceExpression.js create mode 100644 node_modules/@babel/types/lib/converters/toSequenceExpression.js.map create mode 100644 node_modules/@babel/types/lib/converters/toStatement.js create mode 100644 node_modules/@babel/types/lib/converters/toStatement.js.map create mode 100644 node_modules/@babel/types/lib/converters/valueToNode.js create mode 100644 node_modules/@babel/types/lib/converters/valueToNode.js.map create mode 100644 node_modules/@babel/types/lib/definitions/core.js create mode 100644 node_modules/@babel/types/lib/definitions/core.js.map create mode 100644 node_modules/@babel/types/lib/definitions/deprecated-aliases.js create mode 100644 node_modules/@babel/types/lib/definitions/deprecated-aliases.js.map create mode 100644 node_modules/@babel/types/lib/definitions/experimental.js create mode 100644 node_modules/@babel/types/lib/definitions/experimental.js.map create mode 100644 node_modules/@babel/types/lib/definitions/flow.js create mode 100644 node_modules/@babel/types/lib/definitions/flow.js.map create mode 100644 node_modules/@babel/types/lib/definitions/index.js create mode 100644 node_modules/@babel/types/lib/definitions/index.js.map create mode 100644 node_modules/@babel/types/lib/definitions/jsx.js create mode 100644 node_modules/@babel/types/lib/definitions/jsx.js.map create mode 100644 node_modules/@babel/types/lib/definitions/misc.js create mode 100644 node_modules/@babel/types/lib/definitions/misc.js.map create mode 100644 node_modules/@babel/types/lib/definitions/placeholders.js create mode 100644 node_modules/@babel/types/lib/definitions/placeholders.js.map create mode 100644 node_modules/@babel/types/lib/definitions/typescript.js create mode 100644 node_modules/@babel/types/lib/definitions/typescript.js.map create mode 100644 node_modules/@babel/types/lib/definitions/utils.js create mode 100644 node_modules/@babel/types/lib/definitions/utils.js.map create mode 100644 node_modules/@babel/types/lib/index-legacy.d.ts create mode 100644 node_modules/@babel/types/lib/index.d.ts create mode 100644 node_modules/@babel/types/lib/index.js create mode 100644 node_modules/@babel/types/lib/index.js.flow create mode 100644 node_modules/@babel/types/lib/index.js.map create mode 100644 node_modules/@babel/types/lib/modifications/appendToMemberExpression.js create mode 100644 node_modules/@babel/types/lib/modifications/appendToMemberExpression.js.map create mode 100644 node_modules/@babel/types/lib/modifications/flow/removeTypeDuplicates.js create mode 100644 node_modules/@babel/types/lib/modifications/flow/removeTypeDuplicates.js.map create mode 100644 node_modules/@babel/types/lib/modifications/inherits.js create mode 100644 node_modules/@babel/types/lib/modifications/inherits.js.map create mode 100644 node_modules/@babel/types/lib/modifications/prependToMemberExpression.js create mode 100644 node_modules/@babel/types/lib/modifications/prependToMemberExpression.js.map create mode 100644 node_modules/@babel/types/lib/modifications/removeProperties.js create mode 100644 node_modules/@babel/types/lib/modifications/removeProperties.js.map create mode 100644 node_modules/@babel/types/lib/modifications/removePropertiesDeep.js create mode 100644 node_modules/@babel/types/lib/modifications/removePropertiesDeep.js.map create mode 100644 node_modules/@babel/types/lib/modifications/typescript/removeTypeDuplicates.js create mode 100644 node_modules/@babel/types/lib/modifications/typescript/removeTypeDuplicates.js.map create mode 100644 node_modules/@babel/types/lib/retrievers/getAssignmentIdentifiers.js create mode 100644 node_modules/@babel/types/lib/retrievers/getAssignmentIdentifiers.js.map create mode 100644 node_modules/@babel/types/lib/retrievers/getBindingIdentifiers.js create mode 100644 node_modules/@babel/types/lib/retrievers/getBindingIdentifiers.js.map create mode 100644 node_modules/@babel/types/lib/retrievers/getFunctionName.js create mode 100644 node_modules/@babel/types/lib/retrievers/getFunctionName.js.map create mode 100644 node_modules/@babel/types/lib/retrievers/getOuterBindingIdentifiers.js create mode 100644 node_modules/@babel/types/lib/retrievers/getOuterBindingIdentifiers.js.map create mode 100644 node_modules/@babel/types/lib/traverse/traverse.js create mode 100644 node_modules/@babel/types/lib/traverse/traverse.js.map create mode 100644 node_modules/@babel/types/lib/traverse/traverseFast.js create mode 100644 node_modules/@babel/types/lib/traverse/traverseFast.js.map create mode 100644 node_modules/@babel/types/lib/utils/deprecationWarning.js create mode 100644 node_modules/@babel/types/lib/utils/deprecationWarning.js.map create mode 100644 node_modules/@babel/types/lib/utils/inherit.js create mode 100644 node_modules/@babel/types/lib/utils/inherit.js.map create mode 100644 node_modules/@babel/types/lib/utils/react/cleanJSXElementLiteralChild.js create mode 100644 node_modules/@babel/types/lib/utils/react/cleanJSXElementLiteralChild.js.map create mode 100644 node_modules/@babel/types/lib/utils/shallowEqual.js create mode 100644 node_modules/@babel/types/lib/utils/shallowEqual.js.map create mode 100644 node_modules/@babel/types/lib/validators/buildMatchMemberExpression.js create mode 100644 node_modules/@babel/types/lib/validators/buildMatchMemberExpression.js.map create mode 100644 node_modules/@babel/types/lib/validators/generated/index.js create mode 100644 node_modules/@babel/types/lib/validators/generated/index.js.map create mode 100644 node_modules/@babel/types/lib/validators/is.js create mode 100644 node_modules/@babel/types/lib/validators/is.js.map create mode 100644 node_modules/@babel/types/lib/validators/isBinding.js create mode 100644 node_modules/@babel/types/lib/validators/isBinding.js.map create mode 100644 node_modules/@babel/types/lib/validators/isBlockScoped.js create mode 100644 node_modules/@babel/types/lib/validators/isBlockScoped.js.map create mode 100644 node_modules/@babel/types/lib/validators/isImmutable.js create mode 100644 node_modules/@babel/types/lib/validators/isImmutable.js.map create mode 100644 node_modules/@babel/types/lib/validators/isLet.js create mode 100644 node_modules/@babel/types/lib/validators/isLet.js.map create mode 100644 node_modules/@babel/types/lib/validators/isNode.js create mode 100644 node_modules/@babel/types/lib/validators/isNode.js.map create mode 100644 node_modules/@babel/types/lib/validators/isNodesEquivalent.js create mode 100644 node_modules/@babel/types/lib/validators/isNodesEquivalent.js.map create mode 100644 node_modules/@babel/types/lib/validators/isPlaceholderType.js create mode 100644 node_modules/@babel/types/lib/validators/isPlaceholderType.js.map create mode 100644 node_modules/@babel/types/lib/validators/isReferenced.js create mode 100644 node_modules/@babel/types/lib/validators/isReferenced.js.map create mode 100644 node_modules/@babel/types/lib/validators/isScope.js create mode 100644 node_modules/@babel/types/lib/validators/isScope.js.map create mode 100644 node_modules/@babel/types/lib/validators/isSpecifierDefault.js create mode 100644 node_modules/@babel/types/lib/validators/isSpecifierDefault.js.map create mode 100644 node_modules/@babel/types/lib/validators/isType.js create mode 100644 node_modules/@babel/types/lib/validators/isType.js.map create mode 100644 node_modules/@babel/types/lib/validators/isValidES3Identifier.js create mode 100644 node_modules/@babel/types/lib/validators/isValidES3Identifier.js.map create mode 100644 node_modules/@babel/types/lib/validators/isValidIdentifier.js create mode 100644 node_modules/@babel/types/lib/validators/isValidIdentifier.js.map create mode 100644 node_modules/@babel/types/lib/validators/isVar.js create mode 100644 node_modules/@babel/types/lib/validators/isVar.js.map create mode 100644 node_modules/@babel/types/lib/validators/matchesPattern.js create mode 100644 node_modules/@babel/types/lib/validators/matchesPattern.js.map create mode 100644 node_modules/@babel/types/lib/validators/react/isCompatTag.js create mode 100644 node_modules/@babel/types/lib/validators/react/isCompatTag.js.map create mode 100644 node_modules/@babel/types/lib/validators/react/isReactComponent.js create mode 100644 node_modules/@babel/types/lib/validators/react/isReactComponent.js.map create mode 100644 node_modules/@babel/types/lib/validators/validate.js create mode 100644 node_modules/@babel/types/lib/validators/validate.js.map create mode 100644 node_modules/@babel/types/package.json create mode 100644 node_modules/@babel/types/tsconfig.json create mode 100644 node_modules/@babel/types/tsconfig.tsbuildinfo create mode 100644 node_modules/@esbuild/win32-x64/README.md create mode 100644 node_modules/@esbuild/win32-x64/esbuild.exe create mode 100644 node_modules/@esbuild/win32-x64/package.json create mode 100644 node_modules/@jridgewell/sourcemap-codec/LICENSE create mode 100644 node_modules/@jridgewell/sourcemap-codec/README.md create mode 100644 node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs create mode 100644 node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs.map create mode 100644 node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.umd.js create mode 100644 node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.umd.js.map create mode 100644 node_modules/@jridgewell/sourcemap-codec/dist/types/scopes.d.ts create mode 100644 node_modules/@jridgewell/sourcemap-codec/dist/types/sourcemap-codec.d.ts create mode 100644 node_modules/@jridgewell/sourcemap-codec/dist/types/strings.d.ts create mode 100644 node_modules/@jridgewell/sourcemap-codec/dist/types/vlq.d.ts create mode 100644 node_modules/@jridgewell/sourcemap-codec/package.json create mode 100644 node_modules/@rollup/rollup-win32-x64-msvc/README.md create mode 100644 node_modules/@rollup/rollup-win32-x64-msvc/package.json create mode 100644 node_modules/@rollup/rollup-win32-x64-msvc/rollup.win32-x64-msvc.node create mode 100644 node_modules/@types/estree/LICENSE create mode 100644 node_modules/@types/estree/README.md create mode 100644 node_modules/@types/estree/flow.d.ts create mode 100644 node_modules/@types/estree/index.d.ts create mode 100644 node_modules/@types/estree/package.json create mode 100644 node_modules/@vitejs/plugin-vue/LICENSE create mode 100644 node_modules/@vitejs/plugin-vue/README.md create mode 100644 node_modules/@vitejs/plugin-vue/dist/index.cjs create mode 100644 node_modules/@vitejs/plugin-vue/dist/index.d.cts create mode 100644 node_modules/@vitejs/plugin-vue/dist/index.d.mts create mode 100644 node_modules/@vitejs/plugin-vue/dist/index.d.ts create mode 100644 node_modules/@vitejs/plugin-vue/dist/index.mjs create mode 100644 node_modules/@vitejs/plugin-vue/package.json create mode 100644 node_modules/@vue/compiler-core/LICENSE create mode 100644 node_modules/@vue/compiler-core/README.md create mode 100644 node_modules/@vue/compiler-core/dist/compiler-core.cjs.js create mode 100644 node_modules/@vue/compiler-core/dist/compiler-core.cjs.prod.js create mode 100644 node_modules/@vue/compiler-core/dist/compiler-core.d.ts create mode 100644 node_modules/@vue/compiler-core/dist/compiler-core.esm-bundler.js create mode 100644 node_modules/@vue/compiler-core/index.js create mode 100644 node_modules/@vue/compiler-core/package.json create mode 100644 node_modules/@vue/compiler-dom/LICENSE create mode 100644 node_modules/@vue/compiler-dom/README.md create mode 100644 node_modules/@vue/compiler-dom/dist/compiler-dom.cjs.js create mode 100644 node_modules/@vue/compiler-dom/dist/compiler-dom.cjs.prod.js create mode 100644 node_modules/@vue/compiler-dom/dist/compiler-dom.d.ts create mode 100644 node_modules/@vue/compiler-dom/dist/compiler-dom.esm-browser.js create mode 100644 node_modules/@vue/compiler-dom/dist/compiler-dom.esm-browser.prod.js create mode 100644 node_modules/@vue/compiler-dom/dist/compiler-dom.esm-bundler.js create mode 100644 node_modules/@vue/compiler-dom/dist/compiler-dom.global.js create mode 100644 node_modules/@vue/compiler-dom/dist/compiler-dom.global.prod.js create mode 100644 node_modules/@vue/compiler-dom/index.js create mode 100644 node_modules/@vue/compiler-dom/package.json create mode 100644 node_modules/@vue/compiler-sfc/LICENSE create mode 100644 node_modules/@vue/compiler-sfc/README.md create mode 100644 node_modules/@vue/compiler-sfc/dist/compiler-sfc.cjs.js create mode 100644 node_modules/@vue/compiler-sfc/dist/compiler-sfc.d.ts create mode 100644 node_modules/@vue/compiler-sfc/dist/compiler-sfc.esm-browser.js create mode 100644 node_modules/@vue/compiler-sfc/package.json create mode 100644 node_modules/@vue/compiler-ssr/LICENSE create mode 100644 node_modules/@vue/compiler-ssr/README.md create mode 100644 node_modules/@vue/compiler-ssr/dist/compiler-ssr.cjs.js create mode 100644 node_modules/@vue/compiler-ssr/dist/compiler-ssr.d.ts create mode 100644 node_modules/@vue/compiler-ssr/package.json create mode 100644 node_modules/@vue/devtools-api/lib/cjs/api/api.js create mode 100644 node_modules/@vue/devtools-api/lib/cjs/api/app.js create mode 100644 node_modules/@vue/devtools-api/lib/cjs/api/component.js create mode 100644 node_modules/@vue/devtools-api/lib/cjs/api/context.js create mode 100644 node_modules/@vue/devtools-api/lib/cjs/api/hooks.js create mode 100644 node_modules/@vue/devtools-api/lib/cjs/api/index.js create mode 100644 node_modules/@vue/devtools-api/lib/cjs/api/util.js create mode 100644 node_modules/@vue/devtools-api/lib/cjs/const.js create mode 100644 node_modules/@vue/devtools-api/lib/cjs/env.js create mode 100644 node_modules/@vue/devtools-api/lib/cjs/index.js create mode 100644 node_modules/@vue/devtools-api/lib/cjs/plugin.js create mode 100644 node_modules/@vue/devtools-api/lib/cjs/proxy.js create mode 100644 node_modules/@vue/devtools-api/lib/cjs/time.js create mode 100644 node_modules/@vue/devtools-api/lib/esm/api/api.d.ts create mode 100644 node_modules/@vue/devtools-api/lib/esm/api/api.js create mode 100644 node_modules/@vue/devtools-api/lib/esm/api/app.d.ts create mode 100644 node_modules/@vue/devtools-api/lib/esm/api/app.js create mode 100644 node_modules/@vue/devtools-api/lib/esm/api/component.d.ts create mode 100644 node_modules/@vue/devtools-api/lib/esm/api/component.js create mode 100644 node_modules/@vue/devtools-api/lib/esm/api/context.d.ts create mode 100644 node_modules/@vue/devtools-api/lib/esm/api/context.js create mode 100644 node_modules/@vue/devtools-api/lib/esm/api/hooks.d.ts create mode 100644 node_modules/@vue/devtools-api/lib/esm/api/hooks.js create mode 100644 node_modules/@vue/devtools-api/lib/esm/api/index.d.ts create mode 100644 node_modules/@vue/devtools-api/lib/esm/api/index.js create mode 100644 node_modules/@vue/devtools-api/lib/esm/api/util.d.ts create mode 100644 node_modules/@vue/devtools-api/lib/esm/api/util.js create mode 100644 node_modules/@vue/devtools-api/lib/esm/const.d.ts create mode 100644 node_modules/@vue/devtools-api/lib/esm/const.js create mode 100644 node_modules/@vue/devtools-api/lib/esm/env.d.ts create mode 100644 node_modules/@vue/devtools-api/lib/esm/env.js create mode 100644 node_modules/@vue/devtools-api/lib/esm/index.d.ts create mode 100644 node_modules/@vue/devtools-api/lib/esm/index.js create mode 100644 node_modules/@vue/devtools-api/lib/esm/plugin.d.ts create mode 100644 node_modules/@vue/devtools-api/lib/esm/plugin.js create mode 100644 node_modules/@vue/devtools-api/lib/esm/proxy.d.ts create mode 100644 node_modules/@vue/devtools-api/lib/esm/proxy.js create mode 100644 node_modules/@vue/devtools-api/lib/esm/time.d.ts create mode 100644 node_modules/@vue/devtools-api/lib/esm/time.js create mode 100644 node_modules/@vue/devtools-api/package.json create mode 100644 node_modules/@vue/reactivity/LICENSE create mode 100644 node_modules/@vue/reactivity/README.md create mode 100644 node_modules/@vue/reactivity/dist/reactivity.cjs.js create mode 100644 node_modules/@vue/reactivity/dist/reactivity.cjs.prod.js create mode 100644 node_modules/@vue/reactivity/dist/reactivity.d.ts create mode 100644 node_modules/@vue/reactivity/dist/reactivity.esm-browser.js create mode 100644 node_modules/@vue/reactivity/dist/reactivity.esm-browser.prod.js create mode 100644 node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js create mode 100644 node_modules/@vue/reactivity/dist/reactivity.global.js create mode 100644 node_modules/@vue/reactivity/dist/reactivity.global.prod.js create mode 100644 node_modules/@vue/reactivity/index.js create mode 100644 node_modules/@vue/reactivity/package.json create mode 100644 node_modules/@vue/runtime-core/LICENSE create mode 100644 node_modules/@vue/runtime-core/README.md create mode 100644 node_modules/@vue/runtime-core/dist/runtime-core.cjs.js create mode 100644 node_modules/@vue/runtime-core/dist/runtime-core.cjs.prod.js create mode 100644 node_modules/@vue/runtime-core/dist/runtime-core.d.ts create mode 100644 node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js create mode 100644 node_modules/@vue/runtime-core/index.js create mode 100644 node_modules/@vue/runtime-core/package.json create mode 100644 node_modules/@vue/runtime-dom/LICENSE create mode 100644 node_modules/@vue/runtime-dom/README.md create mode 100644 node_modules/@vue/runtime-dom/dist/runtime-dom.cjs.js create mode 100644 node_modules/@vue/runtime-dom/dist/runtime-dom.cjs.prod.js create mode 100644 node_modules/@vue/runtime-dom/dist/runtime-dom.d.ts create mode 100644 node_modules/@vue/runtime-dom/dist/runtime-dom.esm-browser.js create mode 100644 node_modules/@vue/runtime-dom/dist/runtime-dom.esm-browser.prod.js create mode 100644 node_modules/@vue/runtime-dom/dist/runtime-dom.esm-bundler.js create mode 100644 node_modules/@vue/runtime-dom/dist/runtime-dom.global.js create mode 100644 node_modules/@vue/runtime-dom/dist/runtime-dom.global.prod.js create mode 100644 node_modules/@vue/runtime-dom/index.js create mode 100644 node_modules/@vue/runtime-dom/package.json create mode 100644 node_modules/@vue/server-renderer/LICENSE create mode 100644 node_modules/@vue/server-renderer/README.md create mode 100644 node_modules/@vue/server-renderer/dist/server-renderer.cjs.js create mode 100644 node_modules/@vue/server-renderer/dist/server-renderer.cjs.prod.js create mode 100644 node_modules/@vue/server-renderer/dist/server-renderer.d.ts create mode 100644 node_modules/@vue/server-renderer/dist/server-renderer.esm-browser.js create mode 100644 node_modules/@vue/server-renderer/dist/server-renderer.esm-browser.prod.js create mode 100644 node_modules/@vue/server-renderer/dist/server-renderer.esm-bundler.js create mode 100644 node_modules/@vue/server-renderer/index.js create mode 100644 node_modules/@vue/server-renderer/package.json create mode 100644 node_modules/@vue/shared/LICENSE create mode 100644 node_modules/@vue/shared/README.md create mode 100644 node_modules/@vue/shared/dist/shared.cjs.js create mode 100644 node_modules/@vue/shared/dist/shared.cjs.prod.js create mode 100644 node_modules/@vue/shared/dist/shared.d.ts create mode 100644 node_modules/@vue/shared/dist/shared.esm-bundler.js create mode 100644 node_modules/@vue/shared/index.js create mode 100644 node_modules/@vue/shared/package.json create mode 100644 node_modules/csstype/LICENSE create mode 100644 node_modules/csstype/README.md create mode 100644 node_modules/csstype/index.d.ts create mode 100644 node_modules/csstype/index.js.flow create mode 100644 node_modules/csstype/package.json create mode 100644 node_modules/entities/LICENSE create mode 100644 node_modules/entities/lib/decode.d.ts create mode 100644 node_modules/entities/lib/decode.d.ts.map create mode 100644 node_modules/entities/lib/decode.js create mode 100644 node_modules/entities/lib/decode.js.map create mode 100644 node_modules/entities/lib/decode_codepoint.d.ts create mode 100644 node_modules/entities/lib/decode_codepoint.d.ts.map create mode 100644 node_modules/entities/lib/decode_codepoint.js create mode 100644 node_modules/entities/lib/decode_codepoint.js.map create mode 100644 node_modules/entities/lib/encode.d.ts create mode 100644 node_modules/entities/lib/encode.d.ts.map create mode 100644 node_modules/entities/lib/encode.js create mode 100644 node_modules/entities/lib/encode.js.map create mode 100644 node_modules/entities/lib/escape.d.ts create mode 100644 node_modules/entities/lib/escape.d.ts.map create mode 100644 node_modules/entities/lib/escape.js create mode 100644 node_modules/entities/lib/escape.js.map create mode 100644 node_modules/entities/lib/esm/decode.d.ts create mode 100644 node_modules/entities/lib/esm/decode.d.ts.map create mode 100644 node_modules/entities/lib/esm/decode.js create mode 100644 node_modules/entities/lib/esm/decode.js.map create mode 100644 node_modules/entities/lib/esm/decode_codepoint.d.ts create mode 100644 node_modules/entities/lib/esm/decode_codepoint.d.ts.map create mode 100644 node_modules/entities/lib/esm/decode_codepoint.js create mode 100644 node_modules/entities/lib/esm/decode_codepoint.js.map create mode 100644 node_modules/entities/lib/esm/encode.d.ts create mode 100644 node_modules/entities/lib/esm/encode.d.ts.map create mode 100644 node_modules/entities/lib/esm/encode.js create mode 100644 node_modules/entities/lib/esm/encode.js.map create mode 100644 node_modules/entities/lib/esm/escape.d.ts create mode 100644 node_modules/entities/lib/esm/escape.d.ts.map create mode 100644 node_modules/entities/lib/esm/escape.js create mode 100644 node_modules/entities/lib/esm/escape.js.map create mode 100644 node_modules/entities/lib/esm/generated/decode-data-html.d.ts create mode 100644 node_modules/entities/lib/esm/generated/decode-data-html.d.ts.map create mode 100644 node_modules/entities/lib/esm/generated/decode-data-html.js create mode 100644 node_modules/entities/lib/esm/generated/decode-data-html.js.map create mode 100644 node_modules/entities/lib/esm/generated/decode-data-xml.d.ts create mode 100644 node_modules/entities/lib/esm/generated/decode-data-xml.d.ts.map create mode 100644 node_modules/entities/lib/esm/generated/decode-data-xml.js create mode 100644 node_modules/entities/lib/esm/generated/decode-data-xml.js.map create mode 100644 node_modules/entities/lib/esm/generated/encode-html.d.ts create mode 100644 node_modules/entities/lib/esm/generated/encode-html.d.ts.map create mode 100644 node_modules/entities/lib/esm/generated/encode-html.js create mode 100644 node_modules/entities/lib/esm/generated/encode-html.js.map create mode 100644 node_modules/entities/lib/esm/index.d.ts create mode 100644 node_modules/entities/lib/esm/index.d.ts.map create mode 100644 node_modules/entities/lib/esm/index.js create mode 100644 node_modules/entities/lib/esm/index.js.map create mode 100644 node_modules/entities/lib/esm/package.json create mode 100644 node_modules/entities/lib/generated/decode-data-html.d.ts create mode 100644 node_modules/entities/lib/generated/decode-data-html.d.ts.map create mode 100644 node_modules/entities/lib/generated/decode-data-html.js create mode 100644 node_modules/entities/lib/generated/decode-data-html.js.map create mode 100644 node_modules/entities/lib/generated/decode-data-xml.d.ts create mode 100644 node_modules/entities/lib/generated/decode-data-xml.d.ts.map create mode 100644 node_modules/entities/lib/generated/decode-data-xml.js create mode 100644 node_modules/entities/lib/generated/decode-data-xml.js.map create mode 100644 node_modules/entities/lib/generated/encode-html.d.ts create mode 100644 node_modules/entities/lib/generated/encode-html.d.ts.map create mode 100644 node_modules/entities/lib/generated/encode-html.js create mode 100644 node_modules/entities/lib/generated/encode-html.js.map create mode 100644 node_modules/entities/lib/index.d.ts create mode 100644 node_modules/entities/lib/index.d.ts.map create mode 100644 node_modules/entities/lib/index.js create mode 100644 node_modules/entities/lib/index.js.map create mode 100644 node_modules/entities/package.json create mode 100644 node_modules/entities/readme.md create mode 100644 node_modules/esbuild/LICENSE.md create mode 100644 node_modules/esbuild/README.md create mode 100644 node_modules/esbuild/bin/esbuild create mode 100644 node_modules/esbuild/install.js create mode 100644 node_modules/esbuild/lib/main.d.ts create mode 100644 node_modules/esbuild/lib/main.js create mode 100644 node_modules/esbuild/package.json create mode 100644 node_modules/estree-walker/CHANGELOG.md create mode 100644 node_modules/estree-walker/LICENSE create mode 100644 node_modules/estree-walker/README.md create mode 100644 node_modules/estree-walker/dist/esm/estree-walker.js create mode 100644 node_modules/estree-walker/dist/esm/package.json create mode 100644 node_modules/estree-walker/dist/umd/estree-walker.js create mode 100644 node_modules/estree-walker/package.json create mode 100644 node_modules/estree-walker/src/async.js create mode 100644 node_modules/estree-walker/src/index.js create mode 100644 node_modules/estree-walker/src/package.json create mode 100644 node_modules/estree-walker/src/sync.js create mode 100644 node_modules/estree-walker/src/walker.js create mode 100644 node_modules/estree-walker/types/async.d.ts create mode 100644 node_modules/estree-walker/types/index.d.ts create mode 100644 node_modules/estree-walker/types/sync.d.ts create mode 100644 node_modules/estree-walker/types/tsconfig.tsbuildinfo create mode 100644 node_modules/estree-walker/types/walker.d.ts create mode 100644 node_modules/magic-string/LICENSE create mode 100644 node_modules/magic-string/README.md create mode 100644 node_modules/magic-string/dist/magic-string.cjs.d.ts create mode 100644 node_modules/magic-string/dist/magic-string.cjs.js create mode 100644 node_modules/magic-string/dist/magic-string.cjs.js.map create mode 100644 node_modules/magic-string/dist/magic-string.es.d.mts create mode 100644 node_modules/magic-string/dist/magic-string.es.mjs create mode 100644 node_modules/magic-string/dist/magic-string.es.mjs.map create mode 100644 node_modules/magic-string/dist/magic-string.umd.js create mode 100644 node_modules/magic-string/dist/magic-string.umd.js.map create mode 100644 node_modules/magic-string/package.json create mode 100644 node_modules/nanoid/LICENSE create mode 100644 node_modules/nanoid/README.md create mode 100644 node_modules/nanoid/async/index.browser.cjs create mode 100644 node_modules/nanoid/async/index.browser.js create mode 100644 node_modules/nanoid/async/index.cjs create mode 100644 node_modules/nanoid/async/index.d.ts create mode 100644 node_modules/nanoid/async/index.js create mode 100644 node_modules/nanoid/async/index.native.js create mode 100644 node_modules/nanoid/async/package.json create mode 100644 node_modules/nanoid/bin/nanoid.cjs create mode 100644 node_modules/nanoid/index.browser.cjs create mode 100644 node_modules/nanoid/index.browser.js create mode 100644 node_modules/nanoid/index.cjs create mode 100644 node_modules/nanoid/index.d.cts create mode 100644 node_modules/nanoid/index.d.ts create mode 100644 node_modules/nanoid/index.js create mode 100644 node_modules/nanoid/nanoid.js create mode 100644 node_modules/nanoid/non-secure/index.cjs create mode 100644 node_modules/nanoid/non-secure/index.d.ts create mode 100644 node_modules/nanoid/non-secure/index.js create mode 100644 node_modules/nanoid/non-secure/package.json create mode 100644 node_modules/nanoid/package.json create mode 100644 node_modules/nanoid/url-alphabet/index.cjs create mode 100644 node_modules/nanoid/url-alphabet/index.js create mode 100644 node_modules/nanoid/url-alphabet/package.json create mode 100644 node_modules/picocolors/LICENSE create mode 100644 node_modules/picocolors/README.md create mode 100644 node_modules/picocolors/package.json create mode 100644 node_modules/picocolors/picocolors.browser.js create mode 100644 node_modules/picocolors/picocolors.d.ts create mode 100644 node_modules/picocolors/picocolors.js create mode 100644 node_modules/picocolors/types.ts create mode 100644 node_modules/postcss/LICENSE create mode 100644 node_modules/postcss/README.md create mode 100644 node_modules/postcss/lib/at-rule.d.ts create mode 100644 node_modules/postcss/lib/at-rule.js create mode 100644 node_modules/postcss/lib/comment.d.ts create mode 100644 node_modules/postcss/lib/comment.js create mode 100644 node_modules/postcss/lib/container.d.ts create mode 100644 node_modules/postcss/lib/container.js create mode 100644 node_modules/postcss/lib/css-syntax-error.d.ts create mode 100644 node_modules/postcss/lib/css-syntax-error.js create mode 100644 node_modules/postcss/lib/declaration.d.ts create mode 100644 node_modules/postcss/lib/declaration.js create mode 100644 node_modules/postcss/lib/document.d.ts create mode 100644 node_modules/postcss/lib/document.js create mode 100644 node_modules/postcss/lib/fromJSON.d.ts create mode 100644 node_modules/postcss/lib/fromJSON.js create mode 100644 node_modules/postcss/lib/input.d.ts create mode 100644 node_modules/postcss/lib/input.js create mode 100644 node_modules/postcss/lib/lazy-result.d.ts create mode 100644 node_modules/postcss/lib/lazy-result.js create mode 100644 node_modules/postcss/lib/list.d.ts create mode 100644 node_modules/postcss/lib/list.js create mode 100644 node_modules/postcss/lib/map-generator.js create mode 100644 node_modules/postcss/lib/no-work-result.d.ts create mode 100644 node_modules/postcss/lib/no-work-result.js create mode 100644 node_modules/postcss/lib/node.d.ts create mode 100644 node_modules/postcss/lib/node.js create mode 100644 node_modules/postcss/lib/parse.d.ts create mode 100644 node_modules/postcss/lib/parse.js create mode 100644 node_modules/postcss/lib/parser.js create mode 100644 node_modules/postcss/lib/postcss.d.mts create mode 100644 node_modules/postcss/lib/postcss.d.ts create mode 100644 node_modules/postcss/lib/postcss.js create mode 100644 node_modules/postcss/lib/postcss.mjs create mode 100644 node_modules/postcss/lib/previous-map.d.ts create mode 100644 node_modules/postcss/lib/previous-map.js create mode 100644 node_modules/postcss/lib/processor.d.ts create mode 100644 node_modules/postcss/lib/processor.js create mode 100644 node_modules/postcss/lib/result.d.ts create mode 100644 node_modules/postcss/lib/result.js create mode 100644 node_modules/postcss/lib/root.d.ts create mode 100644 node_modules/postcss/lib/root.js create mode 100644 node_modules/postcss/lib/rule.d.ts create mode 100644 node_modules/postcss/lib/rule.js create mode 100644 node_modules/postcss/lib/stringifier.d.ts create mode 100644 node_modules/postcss/lib/stringifier.js create mode 100644 node_modules/postcss/lib/stringify.d.ts create mode 100644 node_modules/postcss/lib/stringify.js create mode 100644 node_modules/postcss/lib/symbols.js create mode 100644 node_modules/postcss/lib/terminal-highlight.js create mode 100644 node_modules/postcss/lib/tokenize.js create mode 100644 node_modules/postcss/lib/warn-once.js create mode 100644 node_modules/postcss/lib/warning.d.ts create mode 100644 node_modules/postcss/lib/warning.js create mode 100644 node_modules/postcss/package.json create mode 100644 node_modules/rollup/LICENSE.md create mode 100644 node_modules/rollup/README.md create mode 100644 node_modules/rollup/dist/bin/rollup create mode 100644 node_modules/rollup/dist/es/getLogFilter.js create mode 100644 node_modules/rollup/dist/es/package.json create mode 100644 node_modules/rollup/dist/es/parseAst.js create mode 100644 node_modules/rollup/dist/es/rollup.js create mode 100644 node_modules/rollup/dist/es/shared/node-entry.js create mode 100644 node_modules/rollup/dist/es/shared/parseAst.js create mode 100644 node_modules/rollup/dist/es/shared/watch.js create mode 100644 node_modules/rollup/dist/getLogFilter.d.ts create mode 100644 node_modules/rollup/dist/getLogFilter.js create mode 100644 node_modules/rollup/dist/loadConfigFile.d.ts create mode 100644 node_modules/rollup/dist/loadConfigFile.js create mode 100644 node_modules/rollup/dist/native.js create mode 100644 node_modules/rollup/dist/parseAst.d.ts create mode 100644 node_modules/rollup/dist/parseAst.js create mode 100644 node_modules/rollup/dist/rollup.d.ts create mode 100644 node_modules/rollup/dist/rollup.js create mode 100644 node_modules/rollup/dist/shared/fsevents-importer.js create mode 100644 node_modules/rollup/dist/shared/index.js create mode 100644 node_modules/rollup/dist/shared/loadConfigFile.js create mode 100644 node_modules/rollup/dist/shared/parseAst.js create mode 100644 node_modules/rollup/dist/shared/rollup.js create mode 100644 node_modules/rollup/dist/shared/watch-cli.js create mode 100644 node_modules/rollup/dist/shared/watch.js create mode 100644 node_modules/rollup/package.json create mode 100644 node_modules/source-map-js/LICENSE create mode 100644 node_modules/source-map-js/README.md create mode 100644 node_modules/source-map-js/lib/array-set.js create mode 100644 node_modules/source-map-js/lib/base64-vlq.js create mode 100644 node_modules/source-map-js/lib/base64.js create mode 100644 node_modules/source-map-js/lib/binary-search.js create mode 100644 node_modules/source-map-js/lib/mapping-list.js create mode 100644 node_modules/source-map-js/lib/quick-sort.js create mode 100644 node_modules/source-map-js/lib/source-map-consumer.d.ts create mode 100644 node_modules/source-map-js/lib/source-map-consumer.js create mode 100644 node_modules/source-map-js/lib/source-map-generator.d.ts create mode 100644 node_modules/source-map-js/lib/source-map-generator.js create mode 100644 node_modules/source-map-js/lib/source-node.d.ts create mode 100644 node_modules/source-map-js/lib/source-node.js create mode 100644 node_modules/source-map-js/lib/util.js create mode 100644 node_modules/source-map-js/package.json create mode 100644 node_modules/source-map-js/source-map.d.ts create mode 100644 node_modules/source-map-js/source-map.js create mode 100644 node_modules/to-fast-properties/index.js create mode 100644 node_modules/to-fast-properties/license create mode 100644 node_modules/to-fast-properties/package.json create mode 100644 node_modules/to-fast-properties/readme.md create mode 100644 node_modules/vite/LICENSE.md create mode 100644 node_modules/vite/README.md create mode 100644 node_modules/vite/bin/openChrome.applescript create mode 100644 node_modules/vite/bin/vite.js create mode 100644 node_modules/vite/client.d.ts create mode 100644 node_modules/vite/dist/client/client.mjs create mode 100644 node_modules/vite/dist/client/env.mjs create mode 100644 node_modules/vite/dist/node-cjs/publicUtils.cjs create mode 100644 node_modules/vite/dist/node/chunks/dep-BEPV0aRC.js create mode 100644 node_modules/vite/dist/node/chunks/dep-CUvs3bbV.js create mode 100644 node_modules/vite/dist/node/chunks/dep-D-7KCb9p.js create mode 100644 node_modules/vite/dist/node/chunks/dep-DdUJenm9.js create mode 100644 node_modules/vite/dist/node/chunks/dep-IQS-Za7F.js create mode 100644 node_modules/vite/dist/node/cli.js create mode 100644 node_modules/vite/dist/node/constants.js create mode 100644 node_modules/vite/dist/node/index.d.ts create mode 100644 node_modules/vite/dist/node/index.js create mode 100644 node_modules/vite/dist/node/runtime.d.ts create mode 100644 node_modules/vite/dist/node/runtime.js create mode 100644 node_modules/vite/dist/node/types.d-aGj9QkWt.d.ts create mode 100644 node_modules/vite/index.cjs create mode 100644 node_modules/vite/index.d.cts create mode 100644 node_modules/vite/package.json create mode 100644 node_modules/vite/types/customEvent.d.ts create mode 100644 node_modules/vite/types/hmrPayload.d.ts create mode 100644 node_modules/vite/types/hot.d.ts create mode 100644 node_modules/vite/types/import-meta.d.ts create mode 100644 node_modules/vite/types/importGlob.d.ts create mode 100644 node_modules/vite/types/importMeta.d.ts create mode 100644 node_modules/vite/types/metadata.d.ts create mode 100644 node_modules/vite/types/package.json create mode 100644 node_modules/vue-router/LICENSE create mode 100644 node_modules/vue-router/README.md create mode 100644 node_modules/vue-router/dist/vue-router.cjs create mode 100644 node_modules/vue-router/dist/vue-router.cjs.js create mode 100644 node_modules/vue-router/dist/vue-router.cjs.prod.js create mode 100644 node_modules/vue-router/dist/vue-router.d.ts create mode 100644 node_modules/vue-router/dist/vue-router.esm-browser.js create mode 100644 node_modules/vue-router/dist/vue-router.esm-bundler.js create mode 100644 node_modules/vue-router/dist/vue-router.global.js create mode 100644 node_modules/vue-router/dist/vue-router.global.prod.js create mode 100644 node_modules/vue-router/dist/vue-router.mjs create mode 100644 node_modules/vue-router/dist/vue-router.node.mjs create mode 100644 node_modules/vue-router/dist/vue-router.prod.cjs create mode 100644 node_modules/vue-router/index.js create mode 100644 node_modules/vue-router/package.json create mode 100644 node_modules/vue-router/vetur/attributes.json create mode 100644 node_modules/vue-router/vetur/tags.json create mode 100644 node_modules/vue-router/vue-router-auto-routes.d.ts create mode 100644 node_modules/vue-router/vue-router-auto.d.ts create mode 100644 node_modules/vue/LICENSE create mode 100644 node_modules/vue/README.md create mode 100644 node_modules/vue/compiler-sfc/index.browser.js create mode 100644 node_modules/vue/compiler-sfc/index.browser.mjs create mode 100644 node_modules/vue/compiler-sfc/index.d.mts create mode 100644 node_modules/vue/compiler-sfc/index.d.ts create mode 100644 node_modules/vue/compiler-sfc/index.js create mode 100644 node_modules/vue/compiler-sfc/index.mjs create mode 100644 node_modules/vue/compiler-sfc/package.json create mode 100644 node_modules/vue/compiler-sfc/register-ts.js create mode 100644 node_modules/vue/dist/vue.cjs.js create mode 100644 node_modules/vue/dist/vue.cjs.prod.js create mode 100644 node_modules/vue/dist/vue.d.mts create mode 100644 node_modules/vue/dist/vue.d.ts create mode 100644 node_modules/vue/dist/vue.esm-browser.js create mode 100644 node_modules/vue/dist/vue.esm-browser.prod.js create mode 100644 node_modules/vue/dist/vue.esm-bundler.js create mode 100644 node_modules/vue/dist/vue.global.js create mode 100644 node_modules/vue/dist/vue.global.prod.js create mode 100644 node_modules/vue/dist/vue.runtime.esm-browser.js create mode 100644 node_modules/vue/dist/vue.runtime.esm-browser.prod.js create mode 100644 node_modules/vue/dist/vue.runtime.esm-bundler.js create mode 100644 node_modules/vue/dist/vue.runtime.global.js create mode 100644 node_modules/vue/dist/vue.runtime.global.prod.js create mode 100644 node_modules/vue/index.js create mode 100644 node_modules/vue/index.mjs create mode 100644 node_modules/vue/jsx-runtime/index.d.ts create mode 100644 node_modules/vue/jsx-runtime/index.js create mode 100644 node_modules/vue/jsx-runtime/index.mjs create mode 100644 node_modules/vue/jsx-runtime/package.json create mode 100644 node_modules/vue/jsx.d.ts create mode 100644 node_modules/vue/package.json create mode 100644 node_modules/vue/server-renderer/index.d.mts create mode 100644 node_modules/vue/server-renderer/index.d.ts create mode 100644 node_modules/vue/server-renderer/index.js create mode 100644 node_modules/vue/server-renderer/index.mjs create mode 100644 node_modules/vue/server-renderer/package.json create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 public/vite.svg create mode 160000 src create mode 100644 vite.config.js diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..a7cea0b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["Vue.volar"] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..1511959 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Vue 3 + Vite + +This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 ` + + diff --git a/node_modules/.bin/esbuild b/node_modules/.bin/esbuild new file mode 100644 index 0000000..63bb6d4 --- /dev/null +++ b/node_modules/.bin/esbuild @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../esbuild/bin/esbuild" "$@" +else + exec node "$basedir/../esbuild/bin/esbuild" "$@" +fi diff --git a/node_modules/.bin/esbuild.cmd b/node_modules/.bin/esbuild.cmd new file mode 100644 index 0000000..cc920c5 --- /dev/null +++ b/node_modules/.bin/esbuild.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\esbuild\bin\esbuild" %* diff --git a/node_modules/.bin/esbuild.ps1 b/node_modules/.bin/esbuild.ps1 new file mode 100644 index 0000000..81ffbf9 --- /dev/null +++ b/node_modules/.bin/esbuild.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../esbuild/bin/esbuild" $args + } else { + & "$basedir/node$exe" "$basedir/../esbuild/bin/esbuild" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../esbuild/bin/esbuild" $args + } else { + & "node$exe" "$basedir/../esbuild/bin/esbuild" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/node_modules/.bin/nanoid b/node_modules/.bin/nanoid new file mode 100644 index 0000000..46220bd --- /dev/null +++ b/node_modules/.bin/nanoid @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../nanoid/bin/nanoid.cjs" "$@" +else + exec node "$basedir/../nanoid/bin/nanoid.cjs" "$@" +fi diff --git a/node_modules/.bin/nanoid.cmd b/node_modules/.bin/nanoid.cmd new file mode 100644 index 0000000..9c40107 --- /dev/null +++ b/node_modules/.bin/nanoid.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\nanoid\bin\nanoid.cjs" %* diff --git a/node_modules/.bin/nanoid.ps1 b/node_modules/.bin/nanoid.ps1 new file mode 100644 index 0000000..d8a4d7a --- /dev/null +++ b/node_modules/.bin/nanoid.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../nanoid/bin/nanoid.cjs" $args + } else { + & "$basedir/node$exe" "$basedir/../nanoid/bin/nanoid.cjs" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../nanoid/bin/nanoid.cjs" $args + } else { + & "node$exe" "$basedir/../nanoid/bin/nanoid.cjs" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/node_modules/.bin/parser b/node_modules/.bin/parser new file mode 100644 index 0000000..7696ad4 --- /dev/null +++ b/node_modules/.bin/parser @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../@babel/parser/bin/babel-parser.js" "$@" +else + exec node "$basedir/../@babel/parser/bin/babel-parser.js" "$@" +fi diff --git a/node_modules/.bin/parser.cmd b/node_modules/.bin/parser.cmd new file mode 100644 index 0000000..1ad5c81 --- /dev/null +++ b/node_modules/.bin/parser.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\@babel\parser\bin\babel-parser.js" %* diff --git a/node_modules/.bin/parser.ps1 b/node_modules/.bin/parser.ps1 new file mode 100644 index 0000000..8926517 --- /dev/null +++ b/node_modules/.bin/parser.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../@babel/parser/bin/babel-parser.js" $args + } else { + & "$basedir/node$exe" "$basedir/../@babel/parser/bin/babel-parser.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../@babel/parser/bin/babel-parser.js" $args + } else { + & "node$exe" "$basedir/../@babel/parser/bin/babel-parser.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/node_modules/.bin/rollup b/node_modules/.bin/rollup new file mode 100644 index 0000000..998fc16 --- /dev/null +++ b/node_modules/.bin/rollup @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../rollup/dist/bin/rollup" "$@" +else + exec node "$basedir/../rollup/dist/bin/rollup" "$@" +fi diff --git a/node_modules/.bin/rollup.cmd b/node_modules/.bin/rollup.cmd new file mode 100644 index 0000000..b3f110b --- /dev/null +++ b/node_modules/.bin/rollup.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\rollup\dist\bin\rollup" %* diff --git a/node_modules/.bin/rollup.ps1 b/node_modules/.bin/rollup.ps1 new file mode 100644 index 0000000..10f657d --- /dev/null +++ b/node_modules/.bin/rollup.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../rollup/dist/bin/rollup" $args + } else { + & "$basedir/node$exe" "$basedir/../rollup/dist/bin/rollup" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../rollup/dist/bin/rollup" $args + } else { + & "node$exe" "$basedir/../rollup/dist/bin/rollup" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/node_modules/.bin/vite b/node_modules/.bin/vite new file mode 100644 index 0000000..014463f --- /dev/null +++ b/node_modules/.bin/vite @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../vite/bin/vite.js" "$@" +else + exec node "$basedir/../vite/bin/vite.js" "$@" +fi diff --git a/node_modules/.bin/vite.cmd b/node_modules/.bin/vite.cmd new file mode 100644 index 0000000..f62e966 --- /dev/null +++ b/node_modules/.bin/vite.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\vite\bin\vite.js" %* diff --git a/node_modules/.bin/vite.ps1 b/node_modules/.bin/vite.ps1 new file mode 100644 index 0000000..a7759bc --- /dev/null +++ b/node_modules/.bin/vite.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../vite/bin/vite.js" $args + } else { + & "$basedir/node$exe" "$basedir/../vite/bin/vite.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../vite/bin/vite.js" $args + } else { + & "node$exe" "$basedir/../vite/bin/vite.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json new file mode 100644 index 0000000..bd2de9c --- /dev/null +++ b/node_modules/.package-lock.json @@ -0,0 +1,493 @@ +{ + "name": "my-vue-app", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.25.6", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.6" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.25.6", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.21.3", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.3.tgz", + "integrity": "sha512-fOvu7PCQjAj4eWDEuD8Xz5gpzFqXzGlxHZozHP4b9Jxv9APtdxL6STqztDzMLuRXEc4UpXGGhx029Xgm91QBeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.1.3", + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.1.3.tgz", + "integrity": "sha512-3xbWsKEKXYlmX82aOHufFQVnkbMC/v8fLpWwh6hWOUrK5fbbtBh9Q/WWse27BFgSy2/e2c0fz5Scgya9h2GLhw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.5", + "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.5.tgz", + "integrity": "sha512-ZrxcY8JMoV+kgDrmRwlDufz0SjDZ7jfoNZiIBluAACMBmgr55o/jTbxnyrccH6VSJXnFaDI4Ik1UFCiq9r8i7w==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/shared": "3.5.5", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.5", + "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.5.tgz", + "integrity": "sha512-HSvK5q1gmBbxRse3S0Wt34RcKuOyjDJKDDMuF3i7NC+QkDFrbAqw8NnrEm/z7zFDxWZa4/5eUwsBOMQzm1RHBA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.5", + "@vue/shared": "3.5.5" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.5", + "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.5.tgz", + "integrity": "sha512-MzBHDxwZhgQPHrwJ5tj92gdTYRCuPDSZr8PY3+JFv8cv2UD5/WayH5yo0kKCkKfrtJhc39jNSMityHrkMSbfnA==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/compiler-core": "3.5.5", + "@vue/compiler-dom": "3.5.5", + "@vue/compiler-ssr": "3.5.5", + "@vue/shared": "3.5.5", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.11", + "postcss": "^8.4.44", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.5", + "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.5.tgz", + "integrity": "sha512-oFasHnpv/upubjJEmqiTKQYb4qS3ziJddf4UVWuFw6ebk/QTrTUc+AUoTJdo39x9g+AOQBzhOU0ICCRuUjvkmw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.5", + "@vue/shared": "3.5.5" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/@vue/reactivity": { + "version": "3.5.5", + "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.5.tgz", + "integrity": "sha512-V4tTWElZQhT73PSK3Wnax9R9m4qvMX+LeKHnfylZc6SLh4Jc5/BPakp6e3zEhKWi5AN8TDzRkGnLkp8OqycYng==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.5" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.5", + "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.5.tgz", + "integrity": "sha512-2/CFaRN17jgsXy4MpigWFBCAMmLkXPb4CjaHrndglwYSra7ajvkH2cat21dscuXaH91G8fXAeg5gCyxWJ+wCRA==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.5", + "@vue/shared": "3.5.5" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.5", + "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.5.tgz", + "integrity": "sha512-0bQGgCuL+4Muz5PsCLgF4Ata9BTdhHi5VjsxtTDyI0Wy4MgoSvBGaA6bDc7W7CGgZOyirf9LNeetMYHQ05pgpw==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.5", + "@vue/runtime-core": "3.5.5", + "@vue/shared": "3.5.5", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.5", + "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.5.tgz", + "integrity": "sha512-XjRamLIq5f47cxgy+hiX7zUIY+4RHdPDVrPvvMDAUTdW5RJWX/S0ji/rCbm3LWTT/9Co9bvQME8ZI15ahL4/Qw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.5", + "@vue/shared": "3.5.5" + }, + "peerDependencies": { + "vue": "3.5.5" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.5", + "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.5.tgz", + "integrity": "sha512-0KyMXyEgnmFAs6rNUL+6eUHtUCqCaNrVd+AW3MX3LyA0Yry5SA0Km03CDKiOua1x1WWnIr+W9+S0GMFoSDWERQ==", + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.11", + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/picocolors": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "license": "ISC" + }, + "node_modules/postcss": { + "version": "8.4.45", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.45.tgz", + "integrity": "sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/rollup": { + "version": "4.21.3", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.21.3.tgz", + "integrity": "sha512-7sqRtBNnEbcBtMeRVc6VRsJMmpI+JU1z9VTvW8D4gXIYQFz0aLcsE6rRkyghZkLfEgUZgVvOG7A5CVz/VW5GIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.21.3", + "@rollup/rollup-android-arm64": "4.21.3", + "@rollup/rollup-darwin-arm64": "4.21.3", + "@rollup/rollup-darwin-x64": "4.21.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.21.3", + "@rollup/rollup-linux-arm-musleabihf": "4.21.3", + "@rollup/rollup-linux-arm64-gnu": "4.21.3", + "@rollup/rollup-linux-arm64-musl": "4.21.3", + "@rollup/rollup-linux-powerpc64le-gnu": "4.21.3", + "@rollup/rollup-linux-riscv64-gnu": "4.21.3", + "@rollup/rollup-linux-s390x-gnu": "4.21.3", + "@rollup/rollup-linux-x64-gnu": "4.21.3", + "@rollup/rollup-linux-x64-musl": "4.21.3", + "@rollup/rollup-win32-arm64-msvc": "4.21.3", + "@rollup/rollup-win32-ia32-msvc": "4.21.3", + "@rollup/rollup-win32-x64-msvc": "4.21.3", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/vite": { + "version": "5.4.5", + "resolved": "https://registry.npmmirror.com/vite/-/vite-5.4.5.tgz", + "integrity": "sha512-pXqR0qtb2bTwLkev4SE3r4abCNioP3GkjvIDLlzziPpXtHgiJIjuKl+1GN6ESOT3wMjG3JTeARopj2SwYaHTOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.5.5", + "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.5.tgz", + "integrity": "sha512-ybC+xn67K4+df1yVeov4UjBGyVcXM0a1g7JVZr+pWVUX3xF6ntXU0wIjkTkduZBUIpxTlsftJSxz2kwhsT7dgA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.5", + "@vue/compiler-sfc": "3.5.5", + "@vue/runtime-dom": "3.5.5", + "@vue/server-renderer": "3.5.5", + "@vue/shared": "3.5.5" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-router": { + "version": "4.4.5", + "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.4.5.tgz", + "integrity": "sha512-4fKZygS8cH1yCyuabAXGUAsyi1b2/o/OKgu/RUb+znIYOxPRxdkytJEx+0wGcpBE1pX6vUgh5jwWOKRGvuA/7Q==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + } + } +} diff --git a/node_modules/.vite/deps/_metadata.json b/node_modules/.vite/deps/_metadata.json new file mode 100644 index 0000000..3ef678d --- /dev/null +++ b/node_modules/.vite/deps/_metadata.json @@ -0,0 +1,25 @@ +{ + "hash": "ff672875", + "configHash": "a8961c6d", + "lockfileHash": "402c5c9f", + "browserHash": "1e975c66", + "optimized": { + "vue": { + "src": "../../vue/dist/vue.runtime.esm-bundler.js", + "file": "vue.js", + "fileHash": "74353ac6", + "needsInterop": false + }, + "vue-router": { + "src": "../../vue-router/dist/vue-router.mjs", + "file": "vue-router.js", + "fileHash": "491a421f", + "needsInterop": false + } + }, + "chunks": { + "chunk-BLKX25ZG": { + "file": "chunk-BLKX25ZG.js" + } + } +} \ No newline at end of file diff --git a/node_modules/.vite/deps/chunk-BLKX25ZG.js b/node_modules/.vite/deps/chunk-BLKX25ZG.js new file mode 100644 index 0000000..68a3e7c --- /dev/null +++ b/node_modules/.vite/deps/chunk-BLKX25ZG.js @@ -0,0 +1,12476 @@ +// node_modules/@vue/shared/dist/shared.esm-bundler.js +function makeMap(str) { + const map2 = /* @__PURE__ */ Object.create(null); + for (const key of str.split(",")) map2[key] = 1; + return (val) => val in map2; +} +var EMPTY_OBJ = true ? Object.freeze({}) : {}; +var EMPTY_ARR = true ? Object.freeze([]) : []; +var NOOP = () => { +}; +var NO = () => false; +var isOn = (key) => key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && // uppercase letter +(key.charCodeAt(2) > 122 || key.charCodeAt(2) < 97); +var isModelListener = (key) => key.startsWith("onUpdate:"); +var extend = Object.assign; +var remove = (arr, el) => { + const i = arr.indexOf(el); + if (i > -1) { + arr.splice(i, 1); + } +}; +var hasOwnProperty = Object.prototype.hasOwnProperty; +var hasOwn = (val, key) => hasOwnProperty.call(val, key); +var isArray = Array.isArray; +var isMap = (val) => toTypeString(val) === "[object Map]"; +var isSet = (val) => toTypeString(val) === "[object Set]"; +var isDate = (val) => toTypeString(val) === "[object Date]"; +var isRegExp = (val) => toTypeString(val) === "[object RegExp]"; +var isFunction = (val) => typeof val === "function"; +var isString = (val) => typeof val === "string"; +var isSymbol = (val) => typeof val === "symbol"; +var isObject = (val) => val !== null && typeof val === "object"; +var isPromise = (val) => { + return (isObject(val) || isFunction(val)) && isFunction(val.then) && isFunction(val.catch); +}; +var objectToString = Object.prototype.toString; +var toTypeString = (value) => objectToString.call(value); +var toRawType = (value) => { + return toTypeString(value).slice(8, -1); +}; +var isPlainObject = (val) => toTypeString(val) === "[object Object]"; +var isIntegerKey = (key) => isString(key) && key !== "NaN" && key[0] !== "-" && "" + parseInt(key, 10) === key; +var isReservedProp = makeMap( + // the leading comma is intentional so empty string "" is also included + ",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted" +); +var isBuiltInDirective = makeMap( + "bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo" +); +var cacheStringFunction = (fn) => { + const cache = /* @__PURE__ */ Object.create(null); + return (str) => { + const hit = cache[str]; + return hit || (cache[str] = fn(str)); + }; +}; +var camelizeRE = /-(\w)/g; +var camelize = cacheStringFunction( + (str) => { + return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : ""); + } +); +var hyphenateRE = /\B([A-Z])/g; +var hyphenate = cacheStringFunction( + (str) => str.replace(hyphenateRE, "-$1").toLowerCase() +); +var capitalize = cacheStringFunction((str) => { + return str.charAt(0).toUpperCase() + str.slice(1); +}); +var toHandlerKey = cacheStringFunction( + (str) => { + const s = str ? `on${capitalize(str)}` : ``; + return s; + } +); +var hasChanged = (value, oldValue) => !Object.is(value, oldValue); +var invokeArrayFns = (fns, ...arg) => { + for (let i = 0; i < fns.length; i++) { + fns[i](...arg); + } +}; +var def = (obj, key, value, writable = false) => { + Object.defineProperty(obj, key, { + configurable: true, + enumerable: false, + writable, + value + }); +}; +var looseToNumber = (val) => { + const n = parseFloat(val); + return isNaN(n) ? val : n; +}; +var toNumber = (val) => { + const n = isString(val) ? Number(val) : NaN; + return isNaN(n) ? val : n; +}; +var _globalThis; +var getGlobalThis = () => { + return _globalThis || (_globalThis = typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {}); +}; +var GLOBALS_ALLOWED = "Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,console,Error,Symbol"; +var isGloballyAllowed = makeMap(GLOBALS_ALLOWED); +function normalizeStyle(value) { + if (isArray(value)) { + const res = {}; + for (let i = 0; i < value.length; i++) { + const item = value[i]; + const normalized = isString(item) ? parseStringStyle(item) : normalizeStyle(item); + if (normalized) { + for (const key in normalized) { + res[key] = normalized[key]; + } + } + } + return res; + } else if (isString(value) || isObject(value)) { + return value; + } +} +var listDelimiterRE = /;(?![^(]*\))/g; +var propertyDelimiterRE = /:([^]+)/; +var styleCommentRE = /\/\*[^]*?\*\//g; +function parseStringStyle(cssText) { + const ret = {}; + cssText.replace(styleCommentRE, "").split(listDelimiterRE).forEach((item) => { + if (item) { + const tmp = item.split(propertyDelimiterRE); + tmp.length > 1 && (ret[tmp[0].trim()] = tmp[1].trim()); + } + }); + return ret; +} +function stringifyStyle(styles) { + let ret = ""; + if (!styles || isString(styles)) { + return ret; + } + for (const key in styles) { + const value = styles[key]; + if (isString(value) || typeof value === "number") { + const normalizedKey = key.startsWith(`--`) ? key : hyphenate(key); + ret += `${normalizedKey}:${value};`; + } + } + return ret; +} +function normalizeClass(value) { + let res = ""; + if (isString(value)) { + res = value; + } else if (isArray(value)) { + for (let i = 0; i < value.length; i++) { + const normalized = normalizeClass(value[i]); + if (normalized) { + res += normalized + " "; + } + } + } else if (isObject(value)) { + for (const name in value) { + if (value[name]) { + res += name + " "; + } + } + } + return res.trim(); +} +function normalizeProps(props) { + if (!props) return null; + let { class: klass, style } = props; + if (klass && !isString(klass)) { + props.class = normalizeClass(klass); + } + if (style) { + props.style = normalizeStyle(style); + } + return props; +} +var HTML_TAGS = "html,body,base,head,link,meta,style,title,address,article,aside,footer,header,hgroup,h1,h2,h3,h4,h5,h6,nav,section,div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,ruby,s,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,output,progress,select,textarea,details,dialog,menu,summary,template,blockquote,iframe,tfoot"; +var SVG_TAGS = "svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,defs,desc,discard,ellipse,feBlend,feColorMatrix,feComponentTransfer,feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,feDistantLight,feDropShadow,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,filter,foreignObject,g,hatch,hatchpath,image,line,linearGradient,marker,mask,mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,text,textPath,title,tspan,unknown,use,view"; +var MATH_TAGS = "annotation,annotation-xml,maction,maligngroup,malignmark,math,menclose,merror,mfenced,mfrac,mfraction,mglyph,mi,mlabeledtr,mlongdiv,mmultiscripts,mn,mo,mover,mpadded,mphantom,mprescripts,mroot,mrow,ms,mscarries,mscarry,msgroup,msline,mspace,msqrt,msrow,mstack,mstyle,msub,msubsup,msup,mtable,mtd,mtext,mtr,munder,munderover,none,semantics"; +var VOID_TAGS = "area,base,br,col,embed,hr,img,input,link,meta,param,source,track,wbr"; +var isHTMLTag = makeMap(HTML_TAGS); +var isSVGTag = makeMap(SVG_TAGS); +var isMathMLTag = makeMap(MATH_TAGS); +var isVoidTag = makeMap(VOID_TAGS); +var specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`; +var isSpecialBooleanAttr = makeMap(specialBooleanAttrs); +var isBooleanAttr = makeMap( + specialBooleanAttrs + `,async,autofocus,autoplay,controls,default,defer,disabled,hidden,inert,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected` +); +function includeBooleanAttr(value) { + return !!value || value === ""; +} +var isKnownHtmlAttr = makeMap( + `accept,accept-charset,accesskey,action,align,allow,alt,async,autocapitalize,autocomplete,autofocus,autoplay,background,bgcolor,border,buffered,capture,challenge,charset,checked,cite,class,code,codebase,color,cols,colspan,content,contenteditable,contextmenu,controls,coords,crossorigin,csp,data,datetime,decoding,default,defer,dir,dirname,disabled,download,draggable,dropzone,enctype,enterkeyhint,for,form,formaction,formenctype,formmethod,formnovalidate,formtarget,headers,height,hidden,high,href,hreflang,http-equiv,icon,id,importance,inert,integrity,ismap,itemprop,keytype,kind,label,lang,language,loading,list,loop,low,manifest,max,maxlength,minlength,media,min,multiple,muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,preload,radiogroup,readonly,referrerpolicy,rel,required,reversed,rows,rowspan,sandbox,scope,scoped,selected,shape,size,sizes,slot,span,spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,target,title,translate,type,usemap,value,width,wrap` +); +var isKnownSvgAttr = makeMap( + `xmlns,accent-height,accumulate,additive,alignment-baseline,alphabetic,amplitude,arabic-form,ascent,attributeName,attributeType,azimuth,baseFrequency,baseline-shift,baseProfile,bbox,begin,bias,by,calcMode,cap-height,class,clip,clipPathUnits,clip-path,clip-rule,color,color-interpolation,color-interpolation-filters,color-profile,color-rendering,contentScriptType,contentStyleType,crossorigin,cursor,cx,cy,d,decelerate,descent,diffuseConstant,direction,display,divisor,dominant-baseline,dur,dx,dy,edgeMode,elevation,enable-background,end,exponent,fill,fill-opacity,fill-rule,filter,filterRes,filterUnits,flood-color,flood-opacity,font-family,font-size,font-size-adjust,font-stretch,font-style,font-variant,font-weight,format,from,fr,fx,fy,g1,g2,glyph-name,glyph-orientation-horizontal,glyph-orientation-vertical,glyphRef,gradientTransform,gradientUnits,hanging,height,href,hreflang,horiz-adv-x,horiz-origin-x,id,ideographic,image-rendering,in,in2,intercept,k,k1,k2,k3,k4,kernelMatrix,kernelUnitLength,kerning,keyPoints,keySplines,keyTimes,lang,lengthAdjust,letter-spacing,lighting-color,limitingConeAngle,local,marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mask,maskContentUnits,maskUnits,mathematical,max,media,method,min,mode,name,numOctaves,offset,opacity,operator,order,orient,orientation,origin,overflow,overline-position,overline-thickness,panose-1,paint-order,path,pathLength,patternContentUnits,patternTransform,patternUnits,ping,pointer-events,points,pointsAtX,pointsAtY,pointsAtZ,preserveAlpha,preserveAspectRatio,primitiveUnits,r,radius,referrerPolicy,refX,refY,rel,rendering-intent,repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,result,rotate,rx,ry,scale,seed,shape-rendering,slope,spacing,specularConstant,specularExponent,speed,spreadMethod,startOffset,stdDeviation,stemh,stemv,stitchTiles,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,string,stroke,stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,stroke-width,style,surfaceScale,systemLanguage,tabindex,tableValues,target,targetX,targetY,text-anchor,text-decoration,text-rendering,textLength,to,transform,transform-origin,type,u1,u2,underline-position,underline-thickness,unicode,unicode-bidi,unicode-range,units-per-em,v-alphabetic,v-hanging,v-ideographic,v-mathematical,values,vector-effect,version,vert-adv-y,vert-origin-x,vert-origin-y,viewBox,viewTarget,visibility,width,widths,word-spacing,writing-mode,x,x-height,x1,x2,xChannelSelector,xlink:actuate,xlink:arcrole,xlink:href,xlink:role,xlink:show,xlink:title,xlink:type,xmlns:xlink,xml:base,xml:lang,xml:space,y,y1,y2,yChannelSelector,z,zoomAndPan` +); +function isRenderableAttrValue(value) { + if (value == null) { + return false; + } + const type = typeof value; + return type === "string" || type === "number" || type === "boolean"; +} +var cssVarNameEscapeSymbolsRE = /[ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g; +function getEscapedCssVarName(key, doubleEscape) { + return key.replace( + cssVarNameEscapeSymbolsRE, + (s) => doubleEscape ? s === '"' ? '\\\\\\"' : `\\\\${s}` : `\\${s}` + ); +} +function looseCompareArrays(a, b) { + if (a.length !== b.length) return false; + let equal = true; + for (let i = 0; equal && i < a.length; i++) { + equal = looseEqual(a[i], b[i]); + } + return equal; +} +function looseEqual(a, b) { + if (a === b) return true; + let aValidType = isDate(a); + let bValidType = isDate(b); + if (aValidType || bValidType) { + return aValidType && bValidType ? a.getTime() === b.getTime() : false; + } + aValidType = isSymbol(a); + bValidType = isSymbol(b); + if (aValidType || bValidType) { + return a === b; + } + aValidType = isArray(a); + bValidType = isArray(b); + if (aValidType || bValidType) { + return aValidType && bValidType ? looseCompareArrays(a, b) : false; + } + aValidType = isObject(a); + bValidType = isObject(b); + if (aValidType || bValidType) { + if (!aValidType || !bValidType) { + return false; + } + const aKeysCount = Object.keys(a).length; + const bKeysCount = Object.keys(b).length; + if (aKeysCount !== bKeysCount) { + return false; + } + for (const key in a) { + const aHasKey = a.hasOwnProperty(key); + const bHasKey = b.hasOwnProperty(key); + if (aHasKey && !bHasKey || !aHasKey && bHasKey || !looseEqual(a[key], b[key])) { + return false; + } + } + } + return String(a) === String(b); +} +function looseIndexOf(arr, val) { + return arr.findIndex((item) => looseEqual(item, val)); +} +var isRef = (val) => { + return !!(val && val["__v_isRef"] === true); +}; +var toDisplayString = (val) => { + return isString(val) ? val : val == null ? "" : isArray(val) || isObject(val) && (val.toString === objectToString || !isFunction(val.toString)) ? isRef(val) ? toDisplayString(val.value) : JSON.stringify(val, replacer, 2) : String(val); +}; +var replacer = (_key, val) => { + if (isRef(val)) { + return replacer(_key, val.value); + } else if (isMap(val)) { + return { + [`Map(${val.size})`]: [...val.entries()].reduce( + (entries, [key, val2], i) => { + entries[stringifySymbol(key, i) + " =>"] = val2; + return entries; + }, + {} + ) + }; + } else if (isSet(val)) { + return { + [`Set(${val.size})`]: [...val.values()].map((v) => stringifySymbol(v)) + }; + } else if (isSymbol(val)) { + return stringifySymbol(val); + } else if (isObject(val) && !isArray(val) && !isPlainObject(val)) { + return String(val); + } + return val; +}; +var stringifySymbol = (v, i = "") => { + var _a; + return ( + // Symbol.description in es2019+ so we need to cast here to pass + // the lib: es2016 check + isSymbol(v) ? `Symbol(${(_a = v.description) != null ? _a : i})` : v + ); +}; + +// node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js +function warn(msg, ...args) { + console.warn(`[Vue warn] ${msg}`, ...args); +} +var activeEffectScope; +var EffectScope = class { + constructor(detached = false) { + this.detached = detached; + this._active = true; + this.effects = []; + this.cleanups = []; + this._isPaused = false; + this.parent = activeEffectScope; + if (!detached && activeEffectScope) { + this.index = (activeEffectScope.scopes || (activeEffectScope.scopes = [])).push( + this + ) - 1; + } + } + get active() { + return this._active; + } + pause() { + if (this._active) { + this._isPaused = true; + let i, l; + if (this.scopes) { + for (i = 0, l = this.scopes.length; i < l; i++) { + this.scopes[i].pause(); + } + } + for (i = 0, l = this.effects.length; i < l; i++) { + this.effects[i].pause(); + } + } + } + /** + * Resumes the effect scope, including all child scopes and effects. + */ + resume() { + if (this._active) { + if (this._isPaused) { + this._isPaused = false; + let i, l; + if (this.scopes) { + for (i = 0, l = this.scopes.length; i < l; i++) { + this.scopes[i].resume(); + } + } + for (i = 0, l = this.effects.length; i < l; i++) { + this.effects[i].resume(); + } + } + } + } + run(fn) { + if (this._active) { + const currentEffectScope = activeEffectScope; + try { + activeEffectScope = this; + return fn(); + } finally { + activeEffectScope = currentEffectScope; + } + } else if (true) { + warn(`cannot run an inactive effect scope.`); + } + } + /** + * This should only be called on non-detached scopes + * @internal + */ + on() { + activeEffectScope = this; + } + /** + * This should only be called on non-detached scopes + * @internal + */ + off() { + activeEffectScope = this.parent; + } + stop(fromParent) { + if (this._active) { + let i, l; + for (i = 0, l = this.effects.length; i < l; i++) { + this.effects[i].stop(); + } + for (i = 0, l = this.cleanups.length; i < l; i++) { + this.cleanups[i](); + } + if (this.scopes) { + for (i = 0, l = this.scopes.length; i < l; i++) { + this.scopes[i].stop(true); + } + } + if (!this.detached && this.parent && !fromParent) { + const last = this.parent.scopes.pop(); + if (last && last !== this) { + this.parent.scopes[this.index] = last; + last.index = this.index; + } + } + this.parent = void 0; + this._active = false; + } + } +}; +function effectScope(detached) { + return new EffectScope(detached); +} +function getCurrentScope() { + return activeEffectScope; +} +function onScopeDispose(fn, failSilently = false) { + if (activeEffectScope) { + activeEffectScope.cleanups.push(fn); + } else if (!failSilently) { + warn( + `onScopeDispose() is called when there is no active effect scope to be associated with.` + ); + } +} +var activeSub; +var pausedQueueEffects = /* @__PURE__ */ new WeakSet(); +var ReactiveEffect = class { + constructor(fn) { + this.fn = fn; + this.deps = void 0; + this.depsTail = void 0; + this.flags = 1 | 4; + this.nextEffect = void 0; + this.cleanup = void 0; + this.scheduler = void 0; + if (activeEffectScope && activeEffectScope.active) { + activeEffectScope.effects.push(this); + } + } + pause() { + this.flags |= 64; + } + resume() { + if (this.flags & 64) { + this.flags &= ~64; + if (pausedQueueEffects.has(this)) { + pausedQueueEffects.delete(this); + this.trigger(); + } + } + } + /** + * @internal + */ + notify() { + if (this.flags & 2 && !(this.flags & 32)) { + return; + } + if (!(this.flags & 8)) { + this.flags |= 8; + this.nextEffect = batchedEffect; + batchedEffect = this; + } + } + run() { + if (!(this.flags & 1)) { + return this.fn(); + } + this.flags |= 2; + cleanupEffect(this); + prepareDeps(this); + const prevEffect = activeSub; + const prevShouldTrack = shouldTrack; + activeSub = this; + shouldTrack = true; + try { + return this.fn(); + } finally { + if (activeSub !== this) { + warn( + "Active effect was not restored correctly - this is likely a Vue internal bug." + ); + } + cleanupDeps(this); + activeSub = prevEffect; + shouldTrack = prevShouldTrack; + this.flags &= ~2; + } + } + stop() { + if (this.flags & 1) { + for (let link = this.deps; link; link = link.nextDep) { + removeSub(link); + } + this.deps = this.depsTail = void 0; + cleanupEffect(this); + this.onStop && this.onStop(); + this.flags &= ~1; + } + } + trigger() { + if (this.flags & 64) { + pausedQueueEffects.add(this); + } else if (this.scheduler) { + this.scheduler(); + } else { + this.runIfDirty(); + } + } + /** + * @internal + */ + runIfDirty() { + if (isDirty(this)) { + this.run(); + } + } + get dirty() { + return isDirty(this); + } +}; +var batchDepth = 0; +var batchedEffect; +function startBatch() { + batchDepth++; +} +function endBatch() { + if (--batchDepth > 0) { + return; + } + let error; + while (batchedEffect) { + let e = batchedEffect; + batchedEffect = void 0; + while (e) { + const next = e.nextEffect; + e.nextEffect = void 0; + e.flags &= ~8; + if (e.flags & 1) { + try { + e.trigger(); + } catch (err) { + if (!error) error = err; + } + } + e = next; + } + } + if (error) throw error; +} +function prepareDeps(sub) { + for (let link = sub.deps; link; link = link.nextDep) { + link.version = -1; + link.prevActiveLink = link.dep.activeLink; + link.dep.activeLink = link; + } +} +function cleanupDeps(sub) { + let head; + let tail = sub.depsTail; + let link = tail; + while (link) { + const prev = link.prevDep; + if (link.version === -1) { + if (link === tail) tail = prev; + removeSub(link); + removeDep(link); + } else { + head = link; + } + link.dep.activeLink = link.prevActiveLink; + link.prevActiveLink = void 0; + link = prev; + } + sub.deps = head; + sub.depsTail = tail; +} +function isDirty(sub) { + for (let link = sub.deps; link; link = link.nextDep) { + if (link.dep.version !== link.version || link.dep.computed && refreshComputed(link.dep.computed) || link.dep.version !== link.version) { + return true; + } + } + if (sub._dirty) { + return true; + } + return false; +} +function refreshComputed(computed3) { + if (computed3.flags & 4 && !(computed3.flags & 16)) { + return; + } + computed3.flags &= ~16; + if (computed3.globalVersion === globalVersion) { + return; + } + computed3.globalVersion = globalVersion; + const dep = computed3.dep; + computed3.flags |= 2; + if (dep.version > 0 && !computed3.isSSR && !isDirty(computed3)) { + computed3.flags &= ~2; + return; + } + const prevSub = activeSub; + const prevShouldTrack = shouldTrack; + activeSub = computed3; + shouldTrack = true; + try { + prepareDeps(computed3); + const value = computed3.fn(computed3._value); + if (dep.version === 0 || hasChanged(value, computed3._value)) { + computed3._value = value; + dep.version++; + } + } catch (err) { + dep.version++; + throw err; + } finally { + activeSub = prevSub; + shouldTrack = prevShouldTrack; + cleanupDeps(computed3); + computed3.flags &= ~2; + } +} +function removeSub(link) { + const { dep, prevSub, nextSub } = link; + if (prevSub) { + prevSub.nextSub = nextSub; + link.prevSub = void 0; + } + if (nextSub) { + nextSub.prevSub = prevSub; + link.nextSub = void 0; + } + if (dep.subs === link) { + dep.subs = prevSub; + } + if (!dep.subs && dep.computed) { + dep.computed.flags &= ~4; + for (let l = dep.computed.deps; l; l = l.nextDep) { + removeSub(l); + } + } +} +function removeDep(link) { + const { prevDep, nextDep } = link; + if (prevDep) { + prevDep.nextDep = nextDep; + link.prevDep = void 0; + } + if (nextDep) { + nextDep.prevDep = prevDep; + link.nextDep = void 0; + } +} +function effect(fn, options) { + if (fn.effect instanceof ReactiveEffect) { + fn = fn.effect.fn; + } + const e = new ReactiveEffect(fn); + if (options) { + extend(e, options); + } + try { + e.run(); + } catch (err) { + e.stop(); + throw err; + } + const runner = e.run.bind(e); + runner.effect = e; + return runner; +} +function stop(runner) { + runner.effect.stop(); +} +var shouldTrack = true; +var trackStack = []; +function pauseTracking() { + trackStack.push(shouldTrack); + shouldTrack = false; +} +function resetTracking() { + const last = trackStack.pop(); + shouldTrack = last === void 0 ? true : last; +} +function cleanupEffect(e) { + const { cleanup } = e; + e.cleanup = void 0; + if (cleanup) { + const prevSub = activeSub; + activeSub = void 0; + try { + cleanup(); + } finally { + activeSub = prevSub; + } + } +} +var globalVersion = 0; +var Link = class { + constructor(sub, dep) { + this.sub = sub; + this.dep = dep; + this.version = dep.version; + this.nextDep = this.prevDep = this.nextSub = this.prevSub = this.prevActiveLink = void 0; + } +}; +var Dep = class { + constructor(computed3) { + this.computed = computed3; + this.version = 0; + this.activeLink = void 0; + this.subs = void 0; + if (true) { + this.subsHead = void 0; + } + } + track(debugInfo) { + if (!activeSub || !shouldTrack || activeSub === this.computed) { + return; + } + let link = this.activeLink; + if (link === void 0 || link.sub !== activeSub) { + link = this.activeLink = new Link(activeSub, this); + if (!activeSub.deps) { + activeSub.deps = activeSub.depsTail = link; + } else { + link.prevDep = activeSub.depsTail; + activeSub.depsTail.nextDep = link; + activeSub.depsTail = link; + } + if (activeSub.flags & 4) { + addSub(link); + } + } else if (link.version === -1) { + link.version = this.version; + if (link.nextDep) { + const next = link.nextDep; + next.prevDep = link.prevDep; + if (link.prevDep) { + link.prevDep.nextDep = next; + } + link.prevDep = activeSub.depsTail; + link.nextDep = void 0; + activeSub.depsTail.nextDep = link; + activeSub.depsTail = link; + if (activeSub.deps === link) { + activeSub.deps = next; + } + } + } + if (activeSub.onTrack) { + activeSub.onTrack( + extend( + { + effect: activeSub + }, + debugInfo + ) + ); + } + return link; + } + trigger(debugInfo) { + this.version++; + globalVersion++; + this.notify(debugInfo); + } + notify(debugInfo) { + startBatch(); + try { + if (true) { + for (let head = this.subsHead; head; head = head.nextSub) { + if (head.sub.onTrigger && !(head.sub.flags & 8)) { + head.sub.onTrigger( + extend( + { + effect: head.sub + }, + debugInfo + ) + ); + } + } + } + for (let link = this.subs; link; link = link.prevSub) { + link.sub.notify(); + } + } finally { + endBatch(); + } + } +}; +function addSub(link) { + const computed3 = link.dep.computed; + if (computed3 && !link.dep.subs) { + computed3.flags |= 4 | 16; + for (let l = computed3.deps; l; l = l.nextDep) { + addSub(l); + } + } + const currentTail = link.dep.subs; + if (currentTail !== link) { + link.prevSub = currentTail; + if (currentTail) currentTail.nextSub = link; + } + if (link.dep.subsHead === void 0) { + link.dep.subsHead = link; + } + link.dep.subs = link; +} +var targetMap = /* @__PURE__ */ new WeakMap(); +var ITERATE_KEY = Symbol( + true ? "Object iterate" : "" +); +var MAP_KEY_ITERATE_KEY = Symbol( + true ? "Map keys iterate" : "" +); +var ARRAY_ITERATE_KEY = Symbol( + true ? "Array iterate" : "" +); +function track(target, type, key) { + if (shouldTrack && activeSub) { + let depsMap = targetMap.get(target); + if (!depsMap) { + targetMap.set(target, depsMap = /* @__PURE__ */ new Map()); + } + let dep = depsMap.get(key); + if (!dep) { + depsMap.set(key, dep = new Dep()); + } + if (true) { + dep.track({ + target, + type, + key + }); + } else { + dep.track(); + } + } +} +function trigger(target, type, key, newValue, oldValue, oldTarget) { + const depsMap = targetMap.get(target); + if (!depsMap) { + globalVersion++; + return; + } + const run = (dep) => { + if (dep) { + if (true) { + dep.trigger({ + target, + type, + key, + newValue, + oldValue, + oldTarget + }); + } else { + dep.trigger(); + } + } + }; + startBatch(); + if (type === "clear") { + depsMap.forEach(run); + } else { + const targetIsArray = isArray(target); + const isArrayIndex = targetIsArray && isIntegerKey(key); + if (targetIsArray && key === "length") { + const newLength = Number(newValue); + depsMap.forEach((dep, key2) => { + if (key2 === "length" || key2 === ARRAY_ITERATE_KEY || !isSymbol(key2) && key2 >= newLength) { + run(dep); + } + }); + } else { + if (key !== void 0) { + run(depsMap.get(key)); + } + if (isArrayIndex) { + run(depsMap.get(ARRAY_ITERATE_KEY)); + } + switch (type) { + case "add": + if (!targetIsArray) { + run(depsMap.get(ITERATE_KEY)); + if (isMap(target)) { + run(depsMap.get(MAP_KEY_ITERATE_KEY)); + } + } else if (isArrayIndex) { + run(depsMap.get("length")); + } + break; + case "delete": + if (!targetIsArray) { + run(depsMap.get(ITERATE_KEY)); + if (isMap(target)) { + run(depsMap.get(MAP_KEY_ITERATE_KEY)); + } + } + break; + case "set": + if (isMap(target)) { + run(depsMap.get(ITERATE_KEY)); + } + break; + } + } + } + endBatch(); +} +function getDepFromReactive(object, key) { + var _a; + return (_a = targetMap.get(object)) == null ? void 0 : _a.get(key); +} +function reactiveReadArray(array) { + const raw = toRaw(array); + if (raw === array) return raw; + track(raw, "iterate", ARRAY_ITERATE_KEY); + return isShallow(array) ? raw : raw.map(toReactive); +} +function shallowReadArray(arr) { + track(arr = toRaw(arr), "iterate", ARRAY_ITERATE_KEY); + return arr; +} +var arrayInstrumentations = { + __proto__: null, + [Symbol.iterator]() { + return iterator(this, Symbol.iterator, toReactive); + }, + concat(...args) { + return reactiveReadArray(this).concat( + ...args.map((x) => isArray(x) ? reactiveReadArray(x) : x) + ); + }, + entries() { + return iterator(this, "entries", (value) => { + value[1] = toReactive(value[1]); + return value; + }); + }, + every(fn, thisArg) { + return apply(this, "every", fn, thisArg, void 0, arguments); + }, + filter(fn, thisArg) { + return apply(this, "filter", fn, thisArg, (v) => v.map(toReactive), arguments); + }, + find(fn, thisArg) { + return apply(this, "find", fn, thisArg, toReactive, arguments); + }, + findIndex(fn, thisArg) { + return apply(this, "findIndex", fn, thisArg, void 0, arguments); + }, + findLast(fn, thisArg) { + return apply(this, "findLast", fn, thisArg, toReactive, arguments); + }, + findLastIndex(fn, thisArg) { + return apply(this, "findLastIndex", fn, thisArg, void 0, arguments); + }, + // flat, flatMap could benefit from ARRAY_ITERATE but are not straight-forward to implement + forEach(fn, thisArg) { + return apply(this, "forEach", fn, thisArg, void 0, arguments); + }, + includes(...args) { + return searchProxy(this, "includes", args); + }, + indexOf(...args) { + return searchProxy(this, "indexOf", args); + }, + join(separator) { + return reactiveReadArray(this).join(separator); + }, + // keys() iterator only reads `length`, no optimisation required + lastIndexOf(...args) { + return searchProxy(this, "lastIndexOf", args); + }, + map(fn, thisArg) { + return apply(this, "map", fn, thisArg, void 0, arguments); + }, + pop() { + return noTracking(this, "pop"); + }, + push(...args) { + return noTracking(this, "push", args); + }, + reduce(fn, ...args) { + return reduce(this, "reduce", fn, args); + }, + reduceRight(fn, ...args) { + return reduce(this, "reduceRight", fn, args); + }, + shift() { + return noTracking(this, "shift"); + }, + // slice could use ARRAY_ITERATE but also seems to beg for range tracking + some(fn, thisArg) { + return apply(this, "some", fn, thisArg, void 0, arguments); + }, + splice(...args) { + return noTracking(this, "splice", args); + }, + toReversed() { + return reactiveReadArray(this).toReversed(); + }, + toSorted(comparer) { + return reactiveReadArray(this).toSorted(comparer); + }, + toSpliced(...args) { + return reactiveReadArray(this).toSpliced(...args); + }, + unshift(...args) { + return noTracking(this, "unshift", args); + }, + values() { + return iterator(this, "values", toReactive); + } +}; +function iterator(self2, method, wrapValue) { + const arr = shallowReadArray(self2); + const iter = arr[method](); + if (arr !== self2 && !isShallow(self2)) { + iter._next = iter.next; + iter.next = () => { + const result = iter._next(); + if (result.value) { + result.value = wrapValue(result.value); + } + return result; + }; + } + return iter; +} +var arrayProto = Array.prototype; +function apply(self2, method, fn, thisArg, wrappedRetFn, args) { + const arr = shallowReadArray(self2); + const needsWrap = arr !== self2 && !isShallow(self2); + const methodFn = arr[method]; + if (methodFn !== arrayProto[method]) { + const result2 = methodFn.apply(self2, args); + return needsWrap ? toReactive(result2) : result2; + } + let wrappedFn = fn; + if (arr !== self2) { + if (needsWrap) { + wrappedFn = function(item, index) { + return fn.call(this, toReactive(item), index, self2); + }; + } else if (fn.length > 2) { + wrappedFn = function(item, index) { + return fn.call(this, item, index, self2); + }; + } + } + const result = methodFn.call(arr, wrappedFn, thisArg); + return needsWrap && wrappedRetFn ? wrappedRetFn(result) : result; +} +function reduce(self2, method, fn, args) { + const arr = shallowReadArray(self2); + let wrappedFn = fn; + if (arr !== self2) { + if (!isShallow(self2)) { + wrappedFn = function(acc, item, index) { + return fn.call(this, acc, toReactive(item), index, self2); + }; + } else if (fn.length > 3) { + wrappedFn = function(acc, item, index) { + return fn.call(this, acc, item, index, self2); + }; + } + } + return arr[method](wrappedFn, ...args); +} +function searchProxy(self2, method, args) { + const arr = toRaw(self2); + track(arr, "iterate", ARRAY_ITERATE_KEY); + const res = arr[method](...args); + if ((res === -1 || res === false) && isProxy(args[0])) { + args[0] = toRaw(args[0]); + return arr[method](...args); + } + return res; +} +function noTracking(self2, method, args = []) { + pauseTracking(); + startBatch(); + const res = toRaw(self2)[method].apply(self2, args); + endBatch(); + resetTracking(); + return res; +} +var isNonTrackableKeys = makeMap(`__proto__,__v_isRef,__isVue`); +var builtInSymbols = new Set( + Object.getOwnPropertyNames(Symbol).filter((key) => key !== "arguments" && key !== "caller").map((key) => Symbol[key]).filter(isSymbol) +); +function hasOwnProperty2(key) { + if (!isSymbol(key)) key = String(key); + const obj = toRaw(this); + track(obj, "has", key); + return obj.hasOwnProperty(key); +} +var BaseReactiveHandler = class { + constructor(_isReadonly = false, _isShallow = false) { + this._isReadonly = _isReadonly; + this._isShallow = _isShallow; + } + get(target, key, receiver) { + const isReadonly2 = this._isReadonly, isShallow2 = this._isShallow; + if (key === "__v_isReactive") { + return !isReadonly2; + } else if (key === "__v_isReadonly") { + return isReadonly2; + } else if (key === "__v_isShallow") { + return isShallow2; + } else if (key === "__v_raw") { + if (receiver === (isReadonly2 ? isShallow2 ? shallowReadonlyMap : readonlyMap : isShallow2 ? shallowReactiveMap : reactiveMap).get(target) || // receiver is not the reactive proxy, but has the same prototype + // this means the receiver is a user proxy of the reactive proxy + Object.getPrototypeOf(target) === Object.getPrototypeOf(receiver)) { + return target; + } + return; + } + const targetIsArray = isArray(target); + if (!isReadonly2) { + let fn; + if (targetIsArray && (fn = arrayInstrumentations[key])) { + return fn; + } + if (key === "hasOwnProperty") { + return hasOwnProperty2; + } + } + const res = Reflect.get( + target, + key, + // if this is a proxy wrapping a ref, return methods using the raw ref + // as receiver so that we don't have to call `toRaw` on the ref in all + // its class methods + isRef2(target) ? target : receiver + ); + if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) { + return res; + } + if (!isReadonly2) { + track(target, "get", key); + } + if (isShallow2) { + return res; + } + if (isRef2(res)) { + return targetIsArray && isIntegerKey(key) ? res : res.value; + } + if (isObject(res)) { + return isReadonly2 ? readonly(res) : reactive(res); + } + return res; + } +}; +var MutableReactiveHandler = class extends BaseReactiveHandler { + constructor(isShallow2 = false) { + super(false, isShallow2); + } + set(target, key, value, receiver) { + let oldValue = target[key]; + if (!this._isShallow) { + const isOldValueReadonly = isReadonly(oldValue); + if (!isShallow(value) && !isReadonly(value)) { + oldValue = toRaw(oldValue); + value = toRaw(value); + } + if (!isArray(target) && isRef2(oldValue) && !isRef2(value)) { + if (isOldValueReadonly) { + return false; + } else { + oldValue.value = value; + return true; + } + } + } + const hadKey = isArray(target) && isIntegerKey(key) ? Number(key) < target.length : hasOwn(target, key); + const result = Reflect.set( + target, + key, + value, + isRef2(target) ? target : receiver + ); + if (target === toRaw(receiver)) { + if (!hadKey) { + trigger(target, "add", key, value); + } else if (hasChanged(value, oldValue)) { + trigger(target, "set", key, value, oldValue); + } + } + return result; + } + deleteProperty(target, key) { + const hadKey = hasOwn(target, key); + const oldValue = target[key]; + const result = Reflect.deleteProperty(target, key); + if (result && hadKey) { + trigger(target, "delete", key, void 0, oldValue); + } + return result; + } + has(target, key) { + const result = Reflect.has(target, key); + if (!isSymbol(key) || !builtInSymbols.has(key)) { + track(target, "has", key); + } + return result; + } + ownKeys(target) { + track( + target, + "iterate", + isArray(target) ? "length" : ITERATE_KEY + ); + return Reflect.ownKeys(target); + } +}; +var ReadonlyReactiveHandler = class extends BaseReactiveHandler { + constructor(isShallow2 = false) { + super(true, isShallow2); + } + set(target, key) { + if (true) { + warn( + `Set operation on key "${String(key)}" failed: target is readonly.`, + target + ); + } + return true; + } + deleteProperty(target, key) { + if (true) { + warn( + `Delete operation on key "${String(key)}" failed: target is readonly.`, + target + ); + } + return true; + } +}; +var mutableHandlers = new MutableReactiveHandler(); +var readonlyHandlers = new ReadonlyReactiveHandler(); +var shallowReactiveHandlers = new MutableReactiveHandler(true); +var shallowReadonlyHandlers = new ReadonlyReactiveHandler(true); +var toShallow = (value) => value; +var getProto = (v) => Reflect.getPrototypeOf(v); +function get(target, key, isReadonly2 = false, isShallow2 = false) { + target = target["__v_raw"]; + const rawTarget = toRaw(target); + const rawKey = toRaw(key); + if (!isReadonly2) { + if (hasChanged(key, rawKey)) { + track(rawTarget, "get", key); + } + track(rawTarget, "get", rawKey); + } + const { has: has2 } = getProto(rawTarget); + const wrap = isShallow2 ? toShallow : isReadonly2 ? toReadonly : toReactive; + if (has2.call(rawTarget, key)) { + return wrap(target.get(key)); + } else if (has2.call(rawTarget, rawKey)) { + return wrap(target.get(rawKey)); + } else if (target !== rawTarget) { + target.get(key); + } +} +function has(key, isReadonly2 = false) { + const target = this["__v_raw"]; + const rawTarget = toRaw(target); + const rawKey = toRaw(key); + if (!isReadonly2) { + if (hasChanged(key, rawKey)) { + track(rawTarget, "has", key); + } + track(rawTarget, "has", rawKey); + } + return key === rawKey ? target.has(key) : target.has(key) || target.has(rawKey); +} +function size(target, isReadonly2 = false) { + target = target["__v_raw"]; + !isReadonly2 && track(toRaw(target), "iterate", ITERATE_KEY); + return Reflect.get(target, "size", target); +} +function add(value, _isShallow = false) { + if (!_isShallow && !isShallow(value) && !isReadonly(value)) { + value = toRaw(value); + } + const target = toRaw(this); + const proto = getProto(target); + const hadKey = proto.has.call(target, value); + if (!hadKey) { + target.add(value); + trigger(target, "add", value, value); + } + return this; +} +function set(key, value, _isShallow = false) { + if (!_isShallow && !isShallow(value) && !isReadonly(value)) { + value = toRaw(value); + } + const target = toRaw(this); + const { has: has2, get: get2 } = getProto(target); + let hadKey = has2.call(target, key); + if (!hadKey) { + key = toRaw(key); + hadKey = has2.call(target, key); + } else if (true) { + checkIdentityKeys(target, has2, key); + } + const oldValue = get2.call(target, key); + target.set(key, value); + if (!hadKey) { + trigger(target, "add", key, value); + } else if (hasChanged(value, oldValue)) { + trigger(target, "set", key, value, oldValue); + } + return this; +} +function deleteEntry(key) { + const target = toRaw(this); + const { has: has2, get: get2 } = getProto(target); + let hadKey = has2.call(target, key); + if (!hadKey) { + key = toRaw(key); + hadKey = has2.call(target, key); + } else if (true) { + checkIdentityKeys(target, has2, key); + } + const oldValue = get2 ? get2.call(target, key) : void 0; + const result = target.delete(key); + if (hadKey) { + trigger(target, "delete", key, void 0, oldValue); + } + return result; +} +function clear() { + const target = toRaw(this); + const hadItems = target.size !== 0; + const oldTarget = true ? isMap(target) ? new Map(target) : new Set(target) : void 0; + const result = target.clear(); + if (hadItems) { + trigger(target, "clear", void 0, void 0, oldTarget); + } + return result; +} +function createForEach(isReadonly2, isShallow2) { + return function forEach(callback, thisArg) { + const observed = this; + const target = observed["__v_raw"]; + const rawTarget = toRaw(target); + const wrap = isShallow2 ? toShallow : isReadonly2 ? toReadonly : toReactive; + !isReadonly2 && track(rawTarget, "iterate", ITERATE_KEY); + return target.forEach((value, key) => { + return callback.call(thisArg, wrap(value), wrap(key), observed); + }); + }; +} +function createIterableMethod(method, isReadonly2, isShallow2) { + return function(...args) { + const target = this["__v_raw"]; + const rawTarget = toRaw(target); + const targetIsMap = isMap(rawTarget); + const isPair = method === "entries" || method === Symbol.iterator && targetIsMap; + const isKeyOnly = method === "keys" && targetIsMap; + const innerIterator = target[method](...args); + const wrap = isShallow2 ? toShallow : isReadonly2 ? toReadonly : toReactive; + !isReadonly2 && track( + rawTarget, + "iterate", + isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY + ); + return { + // iterator protocol + next() { + const { value, done } = innerIterator.next(); + return done ? { value, done } : { + value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value), + done + }; + }, + // iterable protocol + [Symbol.iterator]() { + return this; + } + }; + }; +} +function createReadonlyMethod(type) { + return function(...args) { + if (true) { + const key = args[0] ? `on key "${args[0]}" ` : ``; + warn( + `${capitalize(type)} operation ${key}failed: target is readonly.`, + toRaw(this) + ); + } + return type === "delete" ? false : type === "clear" ? void 0 : this; + }; +} +function createInstrumentations() { + const mutableInstrumentations2 = { + get(key) { + return get(this, key); + }, + get size() { + return size(this); + }, + has, + add, + set, + delete: deleteEntry, + clear, + forEach: createForEach(false, false) + }; + const shallowInstrumentations2 = { + get(key) { + return get(this, key, false, true); + }, + get size() { + return size(this); + }, + has, + add(value) { + return add.call(this, value, true); + }, + set(key, value) { + return set.call(this, key, value, true); + }, + delete: deleteEntry, + clear, + forEach: createForEach(false, true) + }; + const readonlyInstrumentations2 = { + get(key) { + return get(this, key, true); + }, + get size() { + return size(this, true); + }, + has(key) { + return has.call(this, key, true); + }, + add: createReadonlyMethod("add"), + set: createReadonlyMethod("set"), + delete: createReadonlyMethod("delete"), + clear: createReadonlyMethod("clear"), + forEach: createForEach(true, false) + }; + const shallowReadonlyInstrumentations2 = { + get(key) { + return get(this, key, true, true); + }, + get size() { + return size(this, true); + }, + has(key) { + return has.call(this, key, true); + }, + add: createReadonlyMethod("add"), + set: createReadonlyMethod("set"), + delete: createReadonlyMethod("delete"), + clear: createReadonlyMethod("clear"), + forEach: createForEach(true, true) + }; + const iteratorMethods = [ + "keys", + "values", + "entries", + Symbol.iterator + ]; + iteratorMethods.forEach((method) => { + mutableInstrumentations2[method] = createIterableMethod(method, false, false); + readonlyInstrumentations2[method] = createIterableMethod(method, true, false); + shallowInstrumentations2[method] = createIterableMethod(method, false, true); + shallowReadonlyInstrumentations2[method] = createIterableMethod( + method, + true, + true + ); + }); + return [ + mutableInstrumentations2, + readonlyInstrumentations2, + shallowInstrumentations2, + shallowReadonlyInstrumentations2 + ]; +} +var [ + mutableInstrumentations, + readonlyInstrumentations, + shallowInstrumentations, + shallowReadonlyInstrumentations +] = createInstrumentations(); +function createInstrumentationGetter(isReadonly2, shallow) { + const instrumentations = shallow ? isReadonly2 ? shallowReadonlyInstrumentations : shallowInstrumentations : isReadonly2 ? readonlyInstrumentations : mutableInstrumentations; + return (target, key, receiver) => { + if (key === "__v_isReactive") { + return !isReadonly2; + } else if (key === "__v_isReadonly") { + return isReadonly2; + } else if (key === "__v_raw") { + return target; + } + return Reflect.get( + hasOwn(instrumentations, key) && key in target ? instrumentations : target, + key, + receiver + ); + }; +} +var mutableCollectionHandlers = { + get: createInstrumentationGetter(false, false) +}; +var shallowCollectionHandlers = { + get: createInstrumentationGetter(false, true) +}; +var readonlyCollectionHandlers = { + get: createInstrumentationGetter(true, false) +}; +var shallowReadonlyCollectionHandlers = { + get: createInstrumentationGetter(true, true) +}; +function checkIdentityKeys(target, has2, key) { + const rawKey = toRaw(key); + if (rawKey !== key && has2.call(target, rawKey)) { + const type = toRawType(target); + warn( + `Reactive ${type} contains both the raw and reactive versions of the same object${type === `Map` ? ` as keys` : ``}, which can lead to inconsistencies. Avoid differentiating between the raw and reactive versions of an object and only use the reactive version if possible.` + ); + } +} +var reactiveMap = /* @__PURE__ */ new WeakMap(); +var shallowReactiveMap = /* @__PURE__ */ new WeakMap(); +var readonlyMap = /* @__PURE__ */ new WeakMap(); +var shallowReadonlyMap = /* @__PURE__ */ new WeakMap(); +function targetTypeMap(rawType) { + switch (rawType) { + case "Object": + case "Array": + return 1; + case "Map": + case "Set": + case "WeakMap": + case "WeakSet": + return 2; + default: + return 0; + } +} +function getTargetType(value) { + return value["__v_skip"] || !Object.isExtensible(value) ? 0 : targetTypeMap(toRawType(value)); +} +function reactive(target) { + if (isReadonly(target)) { + return target; + } + return createReactiveObject( + target, + false, + mutableHandlers, + mutableCollectionHandlers, + reactiveMap + ); +} +function shallowReactive(target) { + return createReactiveObject( + target, + false, + shallowReactiveHandlers, + shallowCollectionHandlers, + shallowReactiveMap + ); +} +function readonly(target) { + return createReactiveObject( + target, + true, + readonlyHandlers, + readonlyCollectionHandlers, + readonlyMap + ); +} +function shallowReadonly(target) { + return createReactiveObject( + target, + true, + shallowReadonlyHandlers, + shallowReadonlyCollectionHandlers, + shallowReadonlyMap + ); +} +function createReactiveObject(target, isReadonly2, baseHandlers, collectionHandlers, proxyMap) { + if (!isObject(target)) { + if (true) { + warn( + `value cannot be made ${isReadonly2 ? "readonly" : "reactive"}: ${String( + target + )}` + ); + } + return target; + } + if (target["__v_raw"] && !(isReadonly2 && target["__v_isReactive"])) { + return target; + } + const existingProxy = proxyMap.get(target); + if (existingProxy) { + return existingProxy; + } + const targetType = getTargetType(target); + if (targetType === 0) { + return target; + } + const proxy = new Proxy( + target, + targetType === 2 ? collectionHandlers : baseHandlers + ); + proxyMap.set(target, proxy); + return proxy; +} +function isReactive(value) { + if (isReadonly(value)) { + return isReactive(value["__v_raw"]); + } + return !!(value && value["__v_isReactive"]); +} +function isReadonly(value) { + return !!(value && value["__v_isReadonly"]); +} +function isShallow(value) { + return !!(value && value["__v_isShallow"]); +} +function isProxy(value) { + return value ? !!value["__v_raw"] : false; +} +function toRaw(observed) { + const raw = observed && observed["__v_raw"]; + return raw ? toRaw(raw) : observed; +} +function markRaw(value) { + if (!hasOwn(value, "__v_skip") && Object.isExtensible(value)) { + def(value, "__v_skip", true); + } + return value; +} +var toReactive = (value) => isObject(value) ? reactive(value) : value; +var toReadonly = (value) => isObject(value) ? readonly(value) : value; +function isRef2(r) { + return r ? r["__v_isRef"] === true : false; +} +function ref(value) { + return createRef(value, false); +} +function shallowRef(value) { + return createRef(value, true); +} +function createRef(rawValue, shallow) { + if (isRef2(rawValue)) { + return rawValue; + } + return new RefImpl(rawValue, shallow); +} +var RefImpl = class { + constructor(value, isShallow2) { + this.dep = new Dep(); + this["__v_isRef"] = true; + this["__v_isShallow"] = false; + this._rawValue = isShallow2 ? value : toRaw(value); + this._value = isShallow2 ? value : toReactive(value); + this["__v_isShallow"] = isShallow2; + } + get value() { + if (true) { + this.dep.track({ + target: this, + type: "get", + key: "value" + }); + } else { + this.dep.track(); + } + return this._value; + } + set value(newValue) { + const oldValue = this._rawValue; + const useDirectValue = this["__v_isShallow"] || isShallow(newValue) || isReadonly(newValue); + newValue = useDirectValue ? newValue : toRaw(newValue); + if (hasChanged(newValue, oldValue)) { + this._rawValue = newValue; + this._value = useDirectValue ? newValue : toReactive(newValue); + if (true) { + this.dep.trigger({ + target: this, + type: "set", + key: "value", + newValue, + oldValue + }); + } else { + this.dep.trigger(); + } + } + } +}; +function triggerRef(ref2) { + if (true) { + ref2.dep.trigger({ + target: ref2, + type: "set", + key: "value", + newValue: ref2._value + }); + } else { + ref2.dep.trigger(); + } +} +function unref(ref2) { + return isRef2(ref2) ? ref2.value : ref2; +} +function toValue(source) { + return isFunction(source) ? source() : unref(source); +} +var shallowUnwrapHandlers = { + get: (target, key, receiver) => key === "__v_raw" ? target : unref(Reflect.get(target, key, receiver)), + set: (target, key, value, receiver) => { + const oldValue = target[key]; + if (isRef2(oldValue) && !isRef2(value)) { + oldValue.value = value; + return true; + } else { + return Reflect.set(target, key, value, receiver); + } + } +}; +function proxyRefs(objectWithRefs) { + return isReactive(objectWithRefs) ? objectWithRefs : new Proxy(objectWithRefs, shallowUnwrapHandlers); +} +var CustomRefImpl = class { + constructor(factory) { + this["__v_isRef"] = true; + this._value = void 0; + const dep = this.dep = new Dep(); + const { get: get2, set: set2 } = factory(dep.track.bind(dep), dep.trigger.bind(dep)); + this._get = get2; + this._set = set2; + } + get value() { + return this._value = this._get(); + } + set value(newVal) { + this._set(newVal); + } +}; +function customRef(factory) { + return new CustomRefImpl(factory); +} +function toRefs(object) { + if (!isProxy(object)) { + warn(`toRefs() expects a reactive object but received a plain one.`); + } + const ret = isArray(object) ? new Array(object.length) : {}; + for (const key in object) { + ret[key] = propertyToRef(object, key); + } + return ret; +} +var ObjectRefImpl = class { + constructor(_object, _key, _defaultValue) { + this._object = _object; + this._key = _key; + this._defaultValue = _defaultValue; + this["__v_isRef"] = true; + this._value = void 0; + } + get value() { + const val = this._object[this._key]; + return this._value = val === void 0 ? this._defaultValue : val; + } + set value(newVal) { + this._object[this._key] = newVal; + } + get dep() { + return getDepFromReactive(toRaw(this._object), this._key); + } +}; +var GetterRefImpl = class { + constructor(_getter) { + this._getter = _getter; + this["__v_isRef"] = true; + this["__v_isReadonly"] = true; + this._value = void 0; + } + get value() { + return this._value = this._getter(); + } +}; +function toRef(source, key, defaultValue) { + if (isRef2(source)) { + return source; + } else if (isFunction(source)) { + return new GetterRefImpl(source); + } else if (isObject(source) && arguments.length > 1) { + return propertyToRef(source, key, defaultValue); + } else { + return ref(source); + } +} +function propertyToRef(source, key, defaultValue) { + const val = source[key]; + return isRef2(val) ? val : new ObjectRefImpl(source, key, defaultValue); +} +var ComputedRefImpl = class { + constructor(fn, setter, isSSR) { + this.fn = fn; + this.setter = setter; + this._value = void 0; + this.dep = new Dep(this); + this.__v_isRef = true; + this.deps = void 0; + this.depsTail = void 0; + this.flags = 16; + this.globalVersion = globalVersion - 1; + this.effect = this; + this["__v_isReadonly"] = !setter; + this.isSSR = isSSR; + } + /** + * @internal + */ + notify() { + this.flags |= 16; + if (activeSub !== this) { + this.dep.notify(); + } else if (true) ; + } + get value() { + const link = true ? this.dep.track({ + target: this, + type: "get", + key: "value" + }) : this.dep.track(); + refreshComputed(this); + if (link) { + link.version = this.dep.version; + } + return this._value; + } + set value(newValue) { + if (this.setter) { + this.setter(newValue); + } else if (true) { + warn("Write operation failed: computed value is readonly"); + } + } +}; +function computed(getterOrOptions, debugOptions, isSSR = false) { + let getter; + let setter; + if (isFunction(getterOrOptions)) { + getter = getterOrOptions; + } else { + getter = getterOrOptions.get; + setter = getterOrOptions.set; + } + const cRef = new ComputedRefImpl(getter, setter, isSSR); + if (debugOptions && !isSSR) { + cRef.onTrack = debugOptions.onTrack; + cRef.onTrigger = debugOptions.onTrigger; + } + return cRef; +} +var TrackOpTypes = { + "GET": "get", + "HAS": "has", + "ITERATE": "iterate" +}; +var TriggerOpTypes = { + "SET": "set", + "ADD": "add", + "DELETE": "delete", + "CLEAR": "clear" +}; +var INITIAL_WATCHER_VALUE = {}; +var cleanupMap = /* @__PURE__ */ new WeakMap(); +var activeWatcher = void 0; +function getCurrentWatcher() { + return activeWatcher; +} +function onWatcherCleanup(cleanupFn, failSilently = false, owner = activeWatcher) { + if (owner) { + let cleanups = cleanupMap.get(owner); + if (!cleanups) cleanupMap.set(owner, cleanups = []); + cleanups.push(cleanupFn); + } else if (!failSilently) { + warn( + `onWatcherCleanup() was called when there was no active watcher to associate with.` + ); + } +} +function watch(source, cb, options = EMPTY_OBJ) { + const { immediate, deep, once, scheduler, augmentJob, call } = options; + const warnInvalidSource = (s) => { + (options.onWarn || warn)( + `Invalid watch source: `, + s, + `A watch source can only be a getter/effect function, a ref, a reactive object, or an array of these types.` + ); + }; + const reactiveGetter = (source2) => { + if (deep) return source2; + if (isShallow(source2) || deep === false || deep === 0) + return traverse(source2, 1); + return traverse(source2); + }; + let effect2; + let getter; + let cleanup; + let boundCleanup; + let forceTrigger = false; + let isMultiSource = false; + if (isRef2(source)) { + getter = () => source.value; + forceTrigger = isShallow(source); + } else if (isReactive(source)) { + getter = () => reactiveGetter(source); + forceTrigger = true; + } else if (isArray(source)) { + isMultiSource = true; + forceTrigger = source.some((s) => isReactive(s) || isShallow(s)); + getter = () => source.map((s) => { + if (isRef2(s)) { + return s.value; + } else if (isReactive(s)) { + return reactiveGetter(s); + } else if (isFunction(s)) { + return call ? call(s, 2) : s(); + } else { + warnInvalidSource(s); + } + }); + } else if (isFunction(source)) { + if (cb) { + getter = call ? () => call(source, 2) : source; + } else { + getter = () => { + if (cleanup) { + pauseTracking(); + try { + cleanup(); + } finally { + resetTracking(); + } + } + const currentEffect = activeWatcher; + activeWatcher = effect2; + try { + return call ? call(source, 3, [boundCleanup]) : source(boundCleanup); + } finally { + activeWatcher = currentEffect; + } + }; + } + } else { + getter = NOOP; + warnInvalidSource(source); + } + if (cb && deep) { + const baseGetter = getter; + const depth = deep === true ? Infinity : deep; + getter = () => traverse(baseGetter(), depth); + } + const scope = getCurrentScope(); + const watchHandle = () => { + effect2.stop(); + if (scope) { + remove(scope.effects, effect2); + } + }; + if (once) { + if (cb) { + const _cb = cb; + cb = (...args) => { + _cb(...args); + watchHandle(); + }; + } else { + const _getter = getter; + getter = () => { + _getter(); + watchHandle(); + }; + } + } + let oldValue = isMultiSource ? new Array(source.length).fill(INITIAL_WATCHER_VALUE) : INITIAL_WATCHER_VALUE; + const job = (immediateFirstRun) => { + if (!(effect2.flags & 1) || !effect2.dirty && !immediateFirstRun) { + return; + } + if (cb) { + const newValue = effect2.run(); + if (deep || forceTrigger || (isMultiSource ? newValue.some((v, i) => hasChanged(v, oldValue[i])) : hasChanged(newValue, oldValue))) { + if (cleanup) { + cleanup(); + } + const currentWatcher = activeWatcher; + activeWatcher = effect2; + try { + const args = [ + newValue, + // pass undefined as the old value when it's changed for the first time + oldValue === INITIAL_WATCHER_VALUE ? void 0 : isMultiSource && oldValue[0] === INITIAL_WATCHER_VALUE ? [] : oldValue, + boundCleanup + ]; + call ? call(cb, 3, args) : ( + // @ts-expect-error + cb(...args) + ); + oldValue = newValue; + } finally { + activeWatcher = currentWatcher; + } + } + } else { + effect2.run(); + } + }; + if (augmentJob) { + augmentJob(job); + } + effect2 = new ReactiveEffect(getter); + effect2.scheduler = scheduler ? () => scheduler(job, false) : job; + boundCleanup = (fn) => onWatcherCleanup(fn, false, effect2); + cleanup = effect2.onStop = () => { + const cleanups = cleanupMap.get(effect2); + if (cleanups) { + if (call) { + call(cleanups, 4); + } else { + for (const cleanup2 of cleanups) cleanup2(); + } + cleanupMap.delete(effect2); + } + }; + if (true) { + effect2.onTrack = options.onTrack; + effect2.onTrigger = options.onTrigger; + } + if (cb) { + if (immediate) { + job(true); + } else { + oldValue = effect2.run(); + } + } else if (scheduler) { + scheduler(job.bind(null, true), true); + } else { + effect2.run(); + } + watchHandle.pause = effect2.pause.bind(effect2); + watchHandle.resume = effect2.resume.bind(effect2); + watchHandle.stop = watchHandle; + return watchHandle; +} +function traverse(value, depth = Infinity, seen) { + if (depth <= 0 || !isObject(value) || value["__v_skip"]) { + return value; + } + seen = seen || /* @__PURE__ */ new Set(); + if (seen.has(value)) { + return value; + } + seen.add(value); + depth--; + if (isRef2(value)) { + traverse(value.value, depth, seen); + } else if (isArray(value)) { + for (let i = 0; i < value.length; i++) { + traverse(value[i], depth, seen); + } + } else if (isSet(value) || isMap(value)) { + value.forEach((v) => { + traverse(v, depth, seen); + }); + } else if (isPlainObject(value)) { + for (const key in value) { + traverse(value[key], depth, seen); + } + for (const key of Object.getOwnPropertySymbols(value)) { + if (Object.prototype.propertyIsEnumerable.call(value, key)) { + traverse(value[key], depth, seen); + } + } + } + return value; +} + +// node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js +var stack = []; +function pushWarningContext(vnode) { + stack.push(vnode); +} +function popWarningContext() { + stack.pop(); +} +var isWarning = false; +function warn$1(msg, ...args) { + if (isWarning) return; + isWarning = true; + pauseTracking(); + const instance = stack.length ? stack[stack.length - 1].component : null; + const appWarnHandler = instance && instance.appContext.config.warnHandler; + const trace = getComponentTrace(); + if (appWarnHandler) { + callWithErrorHandling( + appWarnHandler, + instance, + 11, + [ + // eslint-disable-next-line no-restricted-syntax + msg + args.map((a) => { + var _a, _b; + return (_b = (_a = a.toString) == null ? void 0 : _a.call(a)) != null ? _b : JSON.stringify(a); + }).join(""), + instance && instance.proxy, + trace.map( + ({ vnode }) => `at <${formatComponentName(instance, vnode.type)}>` + ).join("\n"), + trace + ] + ); + } else { + const warnArgs = [`[Vue warn]: ${msg}`, ...args]; + if (trace.length && // avoid spamming console during tests + true) { + warnArgs.push(` +`, ...formatTrace(trace)); + } + console.warn(...warnArgs); + } + resetTracking(); + isWarning = false; +} +function getComponentTrace() { + let currentVNode = stack[stack.length - 1]; + if (!currentVNode) { + return []; + } + const normalizedStack = []; + while (currentVNode) { + const last = normalizedStack[0]; + if (last && last.vnode === currentVNode) { + last.recurseCount++; + } else { + normalizedStack.push({ + vnode: currentVNode, + recurseCount: 0 + }); + } + const parentInstance = currentVNode.component && currentVNode.component.parent; + currentVNode = parentInstance && parentInstance.vnode; + } + return normalizedStack; +} +function formatTrace(trace) { + const logs = []; + trace.forEach((entry, i) => { + logs.push(...i === 0 ? [] : [` +`], ...formatTraceEntry(entry)); + }); + return logs; +} +function formatTraceEntry({ vnode, recurseCount }) { + const postfix = recurseCount > 0 ? `... (${recurseCount} recursive calls)` : ``; + const isRoot = vnode.component ? vnode.component.parent == null : false; + const open = ` at <${formatComponentName( + vnode.component, + vnode.type, + isRoot + )}`; + const close = `>` + postfix; + return vnode.props ? [open, ...formatProps(vnode.props), close] : [open + close]; +} +function formatProps(props) { + const res = []; + const keys = Object.keys(props); + keys.slice(0, 3).forEach((key) => { + res.push(...formatProp(key, props[key])); + }); + if (keys.length > 3) { + res.push(` ...`); + } + return res; +} +function formatProp(key, value, raw) { + if (isString(value)) { + value = JSON.stringify(value); + return raw ? value : [`${key}=${value}`]; + } else if (typeof value === "number" || typeof value === "boolean" || value == null) { + return raw ? value : [`${key}=${value}`]; + } else if (isRef2(value)) { + value = formatProp(key, toRaw(value.value), true); + return raw ? value : [`${key}=Ref<`, value, `>`]; + } else if (isFunction(value)) { + return [`${key}=fn${value.name ? `<${value.name}>` : ``}`]; + } else { + value = toRaw(value); + return raw ? value : [`${key}=`, value]; + } +} +function assertNumber(val, type) { + if (false) return; + if (val === void 0) { + return; + } else if (typeof val !== "number") { + warn$1(`${type} is not a valid number - got ${JSON.stringify(val)}.`); + } else if (isNaN(val)) { + warn$1(`${type} is NaN - the duration expression might be incorrect.`); + } +} +var ErrorCodes = { + "SETUP_FUNCTION": 0, + "0": "SETUP_FUNCTION", + "RENDER_FUNCTION": 1, + "1": "RENDER_FUNCTION", + "NATIVE_EVENT_HANDLER": 5, + "5": "NATIVE_EVENT_HANDLER", + "COMPONENT_EVENT_HANDLER": 6, + "6": "COMPONENT_EVENT_HANDLER", + "VNODE_HOOK": 7, + "7": "VNODE_HOOK", + "DIRECTIVE_HOOK": 8, + "8": "DIRECTIVE_HOOK", + "TRANSITION_HOOK": 9, + "9": "TRANSITION_HOOK", + "APP_ERROR_HANDLER": 10, + "10": "APP_ERROR_HANDLER", + "APP_WARN_HANDLER": 11, + "11": "APP_WARN_HANDLER", + "FUNCTION_REF": 12, + "12": "FUNCTION_REF", + "ASYNC_COMPONENT_LOADER": 13, + "13": "ASYNC_COMPONENT_LOADER", + "SCHEDULER": 14, + "14": "SCHEDULER", + "COMPONENT_UPDATE": 15, + "15": "COMPONENT_UPDATE", + "APP_UNMOUNT_CLEANUP": 16, + "16": "APP_UNMOUNT_CLEANUP" +}; +var ErrorTypeStrings$1 = { + ["sp"]: "serverPrefetch hook", + ["bc"]: "beforeCreate hook", + ["c"]: "created hook", + ["bm"]: "beforeMount hook", + ["m"]: "mounted hook", + ["bu"]: "beforeUpdate hook", + ["u"]: "updated", + ["bum"]: "beforeUnmount hook", + ["um"]: "unmounted hook", + ["a"]: "activated hook", + ["da"]: "deactivated hook", + ["ec"]: "errorCaptured hook", + ["rtc"]: "renderTracked hook", + ["rtg"]: "renderTriggered hook", + [0]: "setup function", + [1]: "render function", + [2]: "watcher getter", + [3]: "watcher callback", + [4]: "watcher cleanup function", + [5]: "native event handler", + [6]: "component event handler", + [7]: "vnode hook", + [8]: "directive hook", + [9]: "transition hook", + [10]: "app errorHandler", + [11]: "app warnHandler", + [12]: "ref function", + [13]: "async component loader", + [14]: "scheduler flush", + [15]: "component update", + [16]: "app unmount cleanup function" +}; +function callWithErrorHandling(fn, instance, type, args) { + try { + return args ? fn(...args) : fn(); + } catch (err) { + handleError(err, instance, type); + } +} +function callWithAsyncErrorHandling(fn, instance, type, args) { + if (isFunction(fn)) { + const res = callWithErrorHandling(fn, instance, type, args); + if (res && isPromise(res)) { + res.catch((err) => { + handleError(err, instance, type); + }); + } + return res; + } + if (isArray(fn)) { + const values = []; + for (let i = 0; i < fn.length; i++) { + values.push(callWithAsyncErrorHandling(fn[i], instance, type, args)); + } + return values; + } else if (true) { + warn$1( + `Invalid value type passed to callWithAsyncErrorHandling(): ${typeof fn}` + ); + } +} +function handleError(err, instance, type, throwInDev = true) { + const contextVNode = instance ? instance.vnode : null; + const { errorHandler, throwUnhandledErrorInProduction } = instance && instance.appContext.config || EMPTY_OBJ; + if (instance) { + let cur = instance.parent; + const exposedInstance = instance.proxy; + const errorInfo = true ? ErrorTypeStrings$1[type] : `https://vuejs.org/error-reference/#runtime-${type}`; + while (cur) { + const errorCapturedHooks = cur.ec; + if (errorCapturedHooks) { + for (let i = 0; i < errorCapturedHooks.length; i++) { + if (errorCapturedHooks[i](err, exposedInstance, errorInfo) === false) { + return; + } + } + } + cur = cur.parent; + } + if (errorHandler) { + pauseTracking(); + callWithErrorHandling(errorHandler, null, 10, [ + err, + exposedInstance, + errorInfo + ]); + resetTracking(); + return; + } + } + logError(err, type, contextVNode, throwInDev, throwUnhandledErrorInProduction); +} +function logError(err, type, contextVNode, throwInDev = true, throwInProd = false) { + if (true) { + const info = ErrorTypeStrings$1[type]; + if (contextVNode) { + pushWarningContext(contextVNode); + } + warn$1(`Unhandled error${info ? ` during execution of ${info}` : ``}`); + if (contextVNode) { + popWarningContext(); + } + if (throwInDev) { + throw err; + } else { + console.error(err); + } + } else if (throwInProd) { + throw err; + } else { + console.error(err); + } +} +var isFlushing = false; +var isFlushPending = false; +var queue = []; +var flushIndex = 0; +var pendingPostFlushCbs = []; +var activePostFlushCbs = null; +var postFlushIndex = 0; +var resolvedPromise = Promise.resolve(); +var currentFlushPromise = null; +var RECURSION_LIMIT = 100; +function nextTick(fn) { + const p2 = currentFlushPromise || resolvedPromise; + return fn ? p2.then(this ? fn.bind(this) : fn) : p2; +} +function findInsertionIndex(id) { + let start = isFlushing ? flushIndex + 1 : 0; + let end = queue.length; + while (start < end) { + const middle = start + end >>> 1; + const middleJob = queue[middle]; + const middleJobId = getId(middleJob); + if (middleJobId < id || middleJobId === id && middleJob.flags & 2) { + start = middle + 1; + } else { + end = middle; + } + } + return start; +} +function queueJob(job) { + if (!(job.flags & 1)) { + const jobId = getId(job); + const lastJob = queue[queue.length - 1]; + if (!lastJob || // fast path when the job id is larger than the tail + !(job.flags & 2) && jobId >= getId(lastJob)) { + queue.push(job); + } else { + queue.splice(findInsertionIndex(jobId), 0, job); + } + job.flags |= 1; + queueFlush(); + } +} +function queueFlush() { + if (!isFlushing && !isFlushPending) { + isFlushPending = true; + currentFlushPromise = resolvedPromise.then(flushJobs); + } +} +function queuePostFlushCb(cb) { + if (!isArray(cb)) { + if (activePostFlushCbs && cb.id === -1) { + activePostFlushCbs.splice(postFlushIndex + 1, 0, cb); + } else if (!(cb.flags & 1)) { + pendingPostFlushCbs.push(cb); + cb.flags |= 1; + } + } else { + pendingPostFlushCbs.push(...cb); + } + queueFlush(); +} +function flushPreFlushCbs(instance, seen, i = isFlushing ? flushIndex + 1 : 0) { + if (true) { + seen = seen || /* @__PURE__ */ new Map(); + } + for (; i < queue.length; i++) { + const cb = queue[i]; + if (cb && cb.flags & 2) { + if (instance && cb.id !== instance.uid) { + continue; + } + if (checkRecursiveUpdates(seen, cb)) { + continue; + } + queue.splice(i, 1); + i--; + if (cb.flags & 4) { + cb.flags &= ~1; + } + cb(); + cb.flags &= ~1; + } + } +} +function flushPostFlushCbs(seen) { + if (pendingPostFlushCbs.length) { + const deduped = [...new Set(pendingPostFlushCbs)].sort( + (a, b) => getId(a) - getId(b) + ); + pendingPostFlushCbs.length = 0; + if (activePostFlushCbs) { + activePostFlushCbs.push(...deduped); + return; + } + activePostFlushCbs = deduped; + if (true) { + seen = seen || /* @__PURE__ */ new Map(); + } + for (postFlushIndex = 0; postFlushIndex < activePostFlushCbs.length; postFlushIndex++) { + const cb = activePostFlushCbs[postFlushIndex]; + if (checkRecursiveUpdates(seen, cb)) { + continue; + } + if (cb.flags & 4) { + cb.flags &= ~1; + } + if (!(cb.flags & 8)) cb(); + cb.flags &= ~1; + } + activePostFlushCbs = null; + postFlushIndex = 0; + } +} +var getId = (job) => job.id == null ? job.flags & 2 ? -1 : Infinity : job.id; +function flushJobs(seen) { + isFlushPending = false; + isFlushing = true; + if (true) { + seen = seen || /* @__PURE__ */ new Map(); + } + const check = true ? (job) => checkRecursiveUpdates(seen, job) : NOOP; + try { + for (flushIndex = 0; flushIndex < queue.length; flushIndex++) { + const job = queue[flushIndex]; + if (job && !(job.flags & 8)) { + if (check(job)) { + continue; + } + if (job.flags & 4) { + job.flags &= ~1; + } + callWithErrorHandling( + job, + job.i, + job.i ? 15 : 14 + ); + job.flags &= ~1; + } + } + } finally { + for (; flushIndex < queue.length; flushIndex++) { + const job = queue[flushIndex]; + if (job) { + job.flags &= ~1; + } + } + flushIndex = 0; + queue.length = 0; + flushPostFlushCbs(seen); + isFlushing = false; + currentFlushPromise = null; + if (queue.length || pendingPostFlushCbs.length) { + flushJobs(seen); + } + } +} +function checkRecursiveUpdates(seen, fn) { + const count = seen.get(fn) || 0; + if (count > RECURSION_LIMIT) { + const instance = fn.i; + const componentName = instance && getComponentName(instance.type); + handleError( + `Maximum recursive updates exceeded${componentName ? ` in component <${componentName}>` : ``}. This means you have a reactive effect that is mutating its own dependencies and thus recursively triggering itself. Possible sources include component template, render function, updated hook or watcher source function.`, + null, + 10 + ); + return true; + } + seen.set(fn, count + 1); + return false; +} +var isHmrUpdating = false; +var hmrDirtyComponents = /* @__PURE__ */ new Map(); +if (true) { + getGlobalThis().__VUE_HMR_RUNTIME__ = { + createRecord: tryWrap(createRecord), + rerender: tryWrap(rerender), + reload: tryWrap(reload) + }; +} +var map = /* @__PURE__ */ new Map(); +function registerHMR(instance) { + const id = instance.type.__hmrId; + let record = map.get(id); + if (!record) { + createRecord(id, instance.type); + record = map.get(id); + } + record.instances.add(instance); +} +function unregisterHMR(instance) { + map.get(instance.type.__hmrId).instances.delete(instance); +} +function createRecord(id, initialDef) { + if (map.has(id)) { + return false; + } + map.set(id, { + initialDef: normalizeClassComponent(initialDef), + instances: /* @__PURE__ */ new Set() + }); + return true; +} +function normalizeClassComponent(component) { + return isClassComponent(component) ? component.__vccOpts : component; +} +function rerender(id, newRender) { + const record = map.get(id); + if (!record) { + return; + } + record.initialDef.render = newRender; + [...record.instances].forEach((instance) => { + if (newRender) { + instance.render = newRender; + normalizeClassComponent(instance.type).render = newRender; + } + instance.renderCache = []; + isHmrUpdating = true; + instance.update(); + isHmrUpdating = false; + }); +} +function reload(id, newComp) { + const record = map.get(id); + if (!record) return; + newComp = normalizeClassComponent(newComp); + updateComponentDef(record.initialDef, newComp); + const instances = [...record.instances]; + for (let i = 0; i < instances.length; i++) { + const instance = instances[i]; + const oldComp = normalizeClassComponent(instance.type); + let dirtyInstances = hmrDirtyComponents.get(oldComp); + if (!dirtyInstances) { + if (oldComp !== record.initialDef) { + updateComponentDef(oldComp, newComp); + } + hmrDirtyComponents.set(oldComp, dirtyInstances = /* @__PURE__ */ new Set()); + } + dirtyInstances.add(instance); + instance.appContext.propsCache.delete(instance.type); + instance.appContext.emitsCache.delete(instance.type); + instance.appContext.optionsCache.delete(instance.type); + if (instance.ceReload) { + dirtyInstances.add(instance); + instance.ceReload(newComp.styles); + dirtyInstances.delete(instance); + } else if (instance.parent) { + queueJob(() => { + isHmrUpdating = true; + instance.parent.update(); + isHmrUpdating = false; + dirtyInstances.delete(instance); + }); + } else if (instance.appContext.reload) { + instance.appContext.reload(); + } else if (typeof window !== "undefined") { + window.location.reload(); + } else { + console.warn( + "[HMR] Root or manually mounted instance modified. Full reload required." + ); + } + if (instance.root.ce && instance !== instance.root) { + instance.root.ce._removeChildStyle(oldComp); + } + } + queuePostFlushCb(() => { + hmrDirtyComponents.clear(); + }); +} +function updateComponentDef(oldComp, newComp) { + extend(oldComp, newComp); + for (const key in oldComp) { + if (key !== "__file" && !(key in newComp)) { + delete oldComp[key]; + } + } +} +function tryWrap(fn) { + return (id, arg) => { + try { + return fn(id, arg); + } catch (e) { + console.error(e); + console.warn( + `[HMR] Something went wrong during Vue component hot-reload. Full reload required.` + ); + } + }; +} +var devtools$1; +var buffer = []; +var devtoolsNotInstalled = false; +function emit$1(event, ...args) { + if (devtools$1) { + devtools$1.emit(event, ...args); + } else if (!devtoolsNotInstalled) { + buffer.push({ event, args }); + } +} +function setDevtoolsHook$1(hook, target) { + var _a, _b; + devtools$1 = hook; + if (devtools$1) { + devtools$1.enabled = true; + buffer.forEach(({ event, args }) => devtools$1.emit(event, ...args)); + buffer = []; + } else if ( + // handle late devtools injection - only do this if we are in an actual + // browser environment to avoid the timer handle stalling test runner exit + // (#4815) + typeof window !== "undefined" && // some envs mock window but not fully + window.HTMLElement && // also exclude jsdom + // eslint-disable-next-line no-restricted-syntax + !((_b = (_a = window.navigator) == null ? void 0 : _a.userAgent) == null ? void 0 : _b.includes("jsdom")) + ) { + const replay = target.__VUE_DEVTOOLS_HOOK_REPLAY__ = target.__VUE_DEVTOOLS_HOOK_REPLAY__ || []; + replay.push((newHook) => { + setDevtoolsHook$1(newHook, target); + }); + setTimeout(() => { + if (!devtools$1) { + target.__VUE_DEVTOOLS_HOOK_REPLAY__ = null; + devtoolsNotInstalled = true; + buffer = []; + } + }, 3e3); + } else { + devtoolsNotInstalled = true; + buffer = []; + } +} +function devtoolsInitApp(app, version2) { + emit$1("app:init", app, version2, { + Fragment, + Text, + Comment, + Static + }); +} +function devtoolsUnmountApp(app) { + emit$1("app:unmount", app); +} +var devtoolsComponentAdded = createDevtoolsComponentHook( + "component:added" + /* COMPONENT_ADDED */ +); +var devtoolsComponentUpdated = createDevtoolsComponentHook( + "component:updated" + /* COMPONENT_UPDATED */ +); +var _devtoolsComponentRemoved = createDevtoolsComponentHook( + "component:removed" + /* COMPONENT_REMOVED */ +); +var devtoolsComponentRemoved = (component) => { + if (devtools$1 && typeof devtools$1.cleanupBuffer === "function" && // remove the component if it wasn't buffered + !devtools$1.cleanupBuffer(component)) { + _devtoolsComponentRemoved(component); + } +}; +function createDevtoolsComponentHook(hook) { + return (component) => { + emit$1( + hook, + component.appContext.app, + component.uid, + component.parent ? component.parent.uid : void 0, + component + ); + }; +} +var devtoolsPerfStart = createDevtoolsPerformanceHook( + "perf:start" + /* PERFORMANCE_START */ +); +var devtoolsPerfEnd = createDevtoolsPerformanceHook( + "perf:end" + /* PERFORMANCE_END */ +); +function createDevtoolsPerformanceHook(hook) { + return (component, type, time) => { + emit$1(hook, component.appContext.app, component.uid, component, type, time); + }; +} +function devtoolsComponentEmit(component, event, params) { + emit$1( + "component:emit", + component.appContext.app, + component, + event, + params + ); +} +var currentRenderingInstance = null; +var currentScopeId = null; +function setCurrentRenderingInstance(instance) { + const prev = currentRenderingInstance; + currentRenderingInstance = instance; + currentScopeId = instance && instance.type.__scopeId || null; + return prev; +} +function pushScopeId(id) { + currentScopeId = id; +} +function popScopeId() { + currentScopeId = null; +} +var withScopeId = (_id) => withCtx; +function withCtx(fn, ctx = currentRenderingInstance, isNonScopedSlot) { + if (!ctx) return fn; + if (fn._n) { + return fn; + } + const renderFnWithContext = (...args) => { + if (renderFnWithContext._d) { + setBlockTracking(-1); + } + const prevInstance = setCurrentRenderingInstance(ctx); + let res; + try { + res = fn(...args); + } finally { + setCurrentRenderingInstance(prevInstance); + if (renderFnWithContext._d) { + setBlockTracking(1); + } + } + if (true) { + devtoolsComponentUpdated(ctx); + } + return res; + }; + renderFnWithContext._n = true; + renderFnWithContext._c = true; + renderFnWithContext._d = true; + return renderFnWithContext; +} +function validateDirectiveName(name) { + if (isBuiltInDirective(name)) { + warn$1("Do not use built-in directive ids as custom directive id: " + name); + } +} +function withDirectives(vnode, directives) { + if (currentRenderingInstance === null) { + warn$1(`withDirectives can only be used inside render functions.`); + return vnode; + } + const instance = getComponentPublicInstance(currentRenderingInstance); + const bindings = vnode.dirs || (vnode.dirs = []); + for (let i = 0; i < directives.length; i++) { + let [dir, value, arg, modifiers = EMPTY_OBJ] = directives[i]; + if (dir) { + if (isFunction(dir)) { + dir = { + mounted: dir, + updated: dir + }; + } + if (dir.deep) { + traverse(value); + } + bindings.push({ + dir, + instance, + value, + oldValue: void 0, + arg, + modifiers + }); + } + } + return vnode; +} +function invokeDirectiveHook(vnode, prevVNode, instance, name) { + const bindings = vnode.dirs; + const oldBindings = prevVNode && prevVNode.dirs; + for (let i = 0; i < bindings.length; i++) { + const binding = bindings[i]; + if (oldBindings) { + binding.oldValue = oldBindings[i].value; + } + let hook = binding.dir[name]; + if (hook) { + pauseTracking(); + callWithAsyncErrorHandling(hook, instance, 8, [ + vnode.el, + binding, + vnode, + prevVNode + ]); + resetTracking(); + } + } +} +var TeleportEndKey = Symbol("_vte"); +var isTeleport = (type) => type.__isTeleport; +var isTeleportDisabled = (props) => props && (props.disabled || props.disabled === ""); +var isTeleportDeferred = (props) => props && (props.defer || props.defer === ""); +var isTargetSVG = (target) => typeof SVGElement !== "undefined" && target instanceof SVGElement; +var isTargetMathML = (target) => typeof MathMLElement === "function" && target instanceof MathMLElement; +var resolveTarget = (props, select) => { + const targetSelector = props && props.to; + if (isString(targetSelector)) { + if (!select) { + warn$1( + `Current renderer does not support string target for Teleports. (missing querySelector renderer option)` + ); + return null; + } else { + const target = select(targetSelector); + if (!target && !isTeleportDisabled(props)) { + warn$1( + `Failed to locate Teleport target with selector "${targetSelector}". Note the target element must exist before the component is mounted - i.e. the target cannot be rendered by the component itself, and ideally should be outside of the entire Vue component tree.` + ); + } + return target; + } + } else { + if (!targetSelector && !isTeleportDisabled(props)) { + warn$1(`Invalid Teleport target: ${targetSelector}`); + } + return targetSelector; + } +}; +var TeleportImpl = { + name: "Teleport", + __isTeleport: true, + process(n1, n2, container, anchor, parentComponent, parentSuspense, namespace, slotScopeIds, optimized, internals) { + const { + mc: mountChildren, + pc: patchChildren, + pbc: patchBlockChildren, + o: { insert, querySelector, createText, createComment } + } = internals; + const disabled = isTeleportDisabled(n2.props); + let { shapeFlag, children, dynamicChildren } = n2; + if (isHmrUpdating) { + optimized = false; + dynamicChildren = null; + } + if (n1 == null) { + const placeholder = n2.el = true ? createComment("teleport start") : createText(""); + const mainAnchor = n2.anchor = true ? createComment("teleport end") : createText(""); + insert(placeholder, container, anchor); + insert(mainAnchor, container, anchor); + const mount = (container2, anchor2) => { + if (shapeFlag & 16) { + if (parentComponent && parentComponent.isCE) { + parentComponent.ce._teleportTarget = container2; + } + mountChildren( + children, + container2, + anchor2, + parentComponent, + parentSuspense, + namespace, + slotScopeIds, + optimized + ); + } + }; + const mountToTarget = () => { + const target = n2.target = resolveTarget(n2.props, querySelector); + const targetAnchor = prepareAnchor(target, n2, createText, insert); + if (target) { + if (namespace !== "svg" && isTargetSVG(target)) { + namespace = "svg"; + } else if (namespace !== "mathml" && isTargetMathML(target)) { + namespace = "mathml"; + } + if (!disabled) { + mount(target, targetAnchor); + updateCssVars(n2); + } + } else if (!disabled) { + warn$1( + "Invalid Teleport target on mount:", + target, + `(${typeof target})` + ); + } + }; + if (disabled) { + mount(container, mainAnchor); + updateCssVars(n2); + } + if (isTeleportDeferred(n2.props)) { + queuePostRenderEffect(mountToTarget, parentSuspense); + } else { + mountToTarget(); + } + } else { + n2.el = n1.el; + n2.targetStart = n1.targetStart; + const mainAnchor = n2.anchor = n1.anchor; + const target = n2.target = n1.target; + const targetAnchor = n2.targetAnchor = n1.targetAnchor; + const wasDisabled = isTeleportDisabled(n1.props); + const currentContainer = wasDisabled ? container : target; + const currentAnchor = wasDisabled ? mainAnchor : targetAnchor; + if (namespace === "svg" || isTargetSVG(target)) { + namespace = "svg"; + } else if (namespace === "mathml" || isTargetMathML(target)) { + namespace = "mathml"; + } + if (dynamicChildren) { + patchBlockChildren( + n1.dynamicChildren, + dynamicChildren, + currentContainer, + parentComponent, + parentSuspense, + namespace, + slotScopeIds + ); + traverseStaticChildren(n1, n2, true); + } else if (!optimized) { + patchChildren( + n1, + n2, + currentContainer, + currentAnchor, + parentComponent, + parentSuspense, + namespace, + slotScopeIds, + false + ); + } + if (disabled) { + if (!wasDisabled) { + moveTeleport( + n2, + container, + mainAnchor, + internals, + 1 + ); + } else { + if (n2.props && n1.props && n2.props.to !== n1.props.to) { + n2.props.to = n1.props.to; + } + } + } else { + if ((n2.props && n2.props.to) !== (n1.props && n1.props.to)) { + const nextTarget = n2.target = resolveTarget( + n2.props, + querySelector + ); + if (nextTarget) { + moveTeleport( + n2, + nextTarget, + null, + internals, + 0 + ); + } else if (true) { + warn$1( + "Invalid Teleport target on update:", + target, + `(${typeof target})` + ); + } + } else if (wasDisabled) { + moveTeleport( + n2, + target, + targetAnchor, + internals, + 1 + ); + } + } + updateCssVars(n2); + } + }, + remove(vnode, parentComponent, parentSuspense, { um: unmount, o: { remove: hostRemove } }, doRemove) { + const { + shapeFlag, + children, + anchor, + targetStart, + targetAnchor, + target, + props + } = vnode; + if (target) { + hostRemove(targetStart); + hostRemove(targetAnchor); + } + doRemove && hostRemove(anchor); + if (shapeFlag & 16) { + const shouldRemove = doRemove || !isTeleportDisabled(props); + for (let i = 0; i < children.length; i++) { + const child = children[i]; + unmount( + child, + parentComponent, + parentSuspense, + shouldRemove, + !!child.dynamicChildren + ); + } + } + }, + move: moveTeleport, + hydrate: hydrateTeleport +}; +function moveTeleport(vnode, container, parentAnchor, { o: { insert }, m: move }, moveType = 2) { + if (moveType === 0) { + insert(vnode.targetAnchor, container, parentAnchor); + } + const { el, anchor, shapeFlag, children, props } = vnode; + const isReorder = moveType === 2; + if (isReorder) { + insert(el, container, parentAnchor); + } + if (!isReorder || isTeleportDisabled(props)) { + if (shapeFlag & 16) { + for (let i = 0; i < children.length; i++) { + move( + children[i], + container, + parentAnchor, + 2 + ); + } + } + } + if (isReorder) { + insert(anchor, container, parentAnchor); + } +} +function hydrateTeleport(node, vnode, parentComponent, parentSuspense, slotScopeIds, optimized, { + o: { nextSibling, parentNode, querySelector, insert, createText } +}, hydrateChildren) { + const target = vnode.target = resolveTarget( + vnode.props, + querySelector + ); + if (target) { + const targetNode = target._lpa || target.firstChild; + if (vnode.shapeFlag & 16) { + if (isTeleportDisabled(vnode.props)) { + vnode.anchor = hydrateChildren( + nextSibling(node), + vnode, + parentNode(node), + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + vnode.targetStart = targetNode; + vnode.targetAnchor = targetNode && nextSibling(targetNode); + } else { + vnode.anchor = nextSibling(node); + let targetAnchor = targetNode; + while (targetAnchor) { + if (targetAnchor && targetAnchor.nodeType === 8) { + if (targetAnchor.data === "teleport start anchor") { + vnode.targetStart = targetAnchor; + } else if (targetAnchor.data === "teleport anchor") { + vnode.targetAnchor = targetAnchor; + target._lpa = vnode.targetAnchor && nextSibling(vnode.targetAnchor); + break; + } + } + targetAnchor = nextSibling(targetAnchor); + } + if (!vnode.targetAnchor) { + prepareAnchor(target, vnode, createText, insert); + } + hydrateChildren( + targetNode && nextSibling(targetNode), + vnode, + target, + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + } + } + updateCssVars(vnode); + } + return vnode.anchor && nextSibling(vnode.anchor); +} +var Teleport = TeleportImpl; +function updateCssVars(vnode) { + const ctx = vnode.ctx; + if (ctx && ctx.ut) { + let node = vnode.targetStart; + while (node && node !== vnode.targetAnchor) { + if (node.nodeType === 1) node.setAttribute("data-v-owner", ctx.uid); + node = node.nextSibling; + } + ctx.ut(); + } +} +function prepareAnchor(target, vnode, createText, insert) { + const targetStart = vnode.targetStart = createText(""); + const targetAnchor = vnode.targetAnchor = createText(""); + targetStart[TeleportEndKey] = targetAnchor; + if (target) { + insert(targetStart, target); + insert(targetAnchor, target); + } + return targetAnchor; +} +var leaveCbKey = Symbol("_leaveCb"); +var enterCbKey = Symbol("_enterCb"); +function useTransitionState() { + const state = { + isMounted: false, + isLeaving: false, + isUnmounting: false, + leavingVNodes: /* @__PURE__ */ new Map() + }; + onMounted(() => { + state.isMounted = true; + }); + onBeforeUnmount(() => { + state.isUnmounting = true; + }); + return state; +} +var TransitionHookValidator = [Function, Array]; +var BaseTransitionPropsValidators = { + mode: String, + appear: Boolean, + persisted: Boolean, + // enter + onBeforeEnter: TransitionHookValidator, + onEnter: TransitionHookValidator, + onAfterEnter: TransitionHookValidator, + onEnterCancelled: TransitionHookValidator, + // leave + onBeforeLeave: TransitionHookValidator, + onLeave: TransitionHookValidator, + onAfterLeave: TransitionHookValidator, + onLeaveCancelled: TransitionHookValidator, + // appear + onBeforeAppear: TransitionHookValidator, + onAppear: TransitionHookValidator, + onAfterAppear: TransitionHookValidator, + onAppearCancelled: TransitionHookValidator +}; +var recursiveGetSubtree = (instance) => { + const subTree = instance.subTree; + return subTree.component ? recursiveGetSubtree(subTree.component) : subTree; +}; +var BaseTransitionImpl = { + name: `BaseTransition`, + props: BaseTransitionPropsValidators, + setup(props, { slots }) { + const instance = getCurrentInstance(); + const state = useTransitionState(); + return () => { + const children = slots.default && getTransitionRawChildren(slots.default(), true); + if (!children || !children.length) { + return; + } + const child = findNonCommentChild(children); + const rawProps = toRaw(props); + const { mode } = rawProps; + if (mode && mode !== "in-out" && mode !== "out-in" && mode !== "default") { + warn$1(`invalid mode: ${mode}`); + } + if (state.isLeaving) { + return emptyPlaceholder(child); + } + const innerChild = getInnerChild$1(child); + if (!innerChild) { + return emptyPlaceholder(child); + } + let enterHooks = resolveTransitionHooks( + innerChild, + rawProps, + state, + instance, + // #11061, ensure enterHooks is fresh after clone + (hooks) => enterHooks = hooks + ); + if (innerChild.type !== Comment) { + setTransitionHooks(innerChild, enterHooks); + } + const oldChild = instance.subTree; + const oldInnerChild = oldChild && getInnerChild$1(oldChild); + if (oldInnerChild && oldInnerChild.type !== Comment && !isSameVNodeType(innerChild, oldInnerChild) && recursiveGetSubtree(instance).type !== Comment) { + const leavingHooks = resolveTransitionHooks( + oldInnerChild, + rawProps, + state, + instance + ); + setTransitionHooks(oldInnerChild, leavingHooks); + if (mode === "out-in" && innerChild.type !== Comment) { + state.isLeaving = true; + leavingHooks.afterLeave = () => { + state.isLeaving = false; + if (!(instance.job.flags & 8)) { + instance.update(); + } + delete leavingHooks.afterLeave; + }; + return emptyPlaceholder(child); + } else if (mode === "in-out" && innerChild.type !== Comment) { + leavingHooks.delayLeave = (el, earlyRemove, delayedLeave) => { + const leavingVNodesCache = getLeavingNodesForType( + state, + oldInnerChild + ); + leavingVNodesCache[String(oldInnerChild.key)] = oldInnerChild; + el[leaveCbKey] = () => { + earlyRemove(); + el[leaveCbKey] = void 0; + delete enterHooks.delayedLeave; + }; + enterHooks.delayedLeave = delayedLeave; + }; + } + } + return child; + }; + } +}; +function findNonCommentChild(children) { + let child = children[0]; + if (children.length > 1) { + let hasFound = false; + for (const c of children) { + if (c.type !== Comment) { + if (hasFound) { + warn$1( + " can only be used on a single element or component. Use for lists." + ); + break; + } + child = c; + hasFound = true; + if (false) break; + } + } + } + return child; +} +var BaseTransition = BaseTransitionImpl; +function getLeavingNodesForType(state, vnode) { + const { leavingVNodes } = state; + let leavingVNodesCache = leavingVNodes.get(vnode.type); + if (!leavingVNodesCache) { + leavingVNodesCache = /* @__PURE__ */ Object.create(null); + leavingVNodes.set(vnode.type, leavingVNodesCache); + } + return leavingVNodesCache; +} +function resolveTransitionHooks(vnode, props, state, instance, postClone) { + const { + appear, + mode, + persisted = false, + onBeforeEnter, + onEnter, + onAfterEnter, + onEnterCancelled, + onBeforeLeave, + onLeave, + onAfterLeave, + onLeaveCancelled, + onBeforeAppear, + onAppear, + onAfterAppear, + onAppearCancelled + } = props; + const key = String(vnode.key); + const leavingVNodesCache = getLeavingNodesForType(state, vnode); + const callHook3 = (hook, args) => { + hook && callWithAsyncErrorHandling( + hook, + instance, + 9, + args + ); + }; + const callAsyncHook = (hook, args) => { + const done = args[1]; + callHook3(hook, args); + if (isArray(hook)) { + if (hook.every((hook2) => hook2.length <= 1)) done(); + } else if (hook.length <= 1) { + done(); + } + }; + const hooks = { + mode, + persisted, + beforeEnter(el) { + let hook = onBeforeEnter; + if (!state.isMounted) { + if (appear) { + hook = onBeforeAppear || onBeforeEnter; + } else { + return; + } + } + if (el[leaveCbKey]) { + el[leaveCbKey]( + true + /* cancelled */ + ); + } + const leavingVNode = leavingVNodesCache[key]; + if (leavingVNode && isSameVNodeType(vnode, leavingVNode) && leavingVNode.el[leaveCbKey]) { + leavingVNode.el[leaveCbKey](); + } + callHook3(hook, [el]); + }, + enter(el) { + let hook = onEnter; + let afterHook = onAfterEnter; + let cancelHook = onEnterCancelled; + if (!state.isMounted) { + if (appear) { + hook = onAppear || onEnter; + afterHook = onAfterAppear || onAfterEnter; + cancelHook = onAppearCancelled || onEnterCancelled; + } else { + return; + } + } + let called = false; + const done = el[enterCbKey] = (cancelled) => { + if (called) return; + called = true; + if (cancelled) { + callHook3(cancelHook, [el]); + } else { + callHook3(afterHook, [el]); + } + if (hooks.delayedLeave) { + hooks.delayedLeave(); + } + el[enterCbKey] = void 0; + }; + if (hook) { + callAsyncHook(hook, [el, done]); + } else { + done(); + } + }, + leave(el, remove2) { + const key2 = String(vnode.key); + if (el[enterCbKey]) { + el[enterCbKey]( + true + /* cancelled */ + ); + } + if (state.isUnmounting) { + return remove2(); + } + callHook3(onBeforeLeave, [el]); + let called = false; + const done = el[leaveCbKey] = (cancelled) => { + if (called) return; + called = true; + remove2(); + if (cancelled) { + callHook3(onLeaveCancelled, [el]); + } else { + callHook3(onAfterLeave, [el]); + } + el[leaveCbKey] = void 0; + if (leavingVNodesCache[key2] === vnode) { + delete leavingVNodesCache[key2]; + } + }; + leavingVNodesCache[key2] = vnode; + if (onLeave) { + callAsyncHook(onLeave, [el, done]); + } else { + done(); + } + }, + clone(vnode2) { + const hooks2 = resolveTransitionHooks( + vnode2, + props, + state, + instance, + postClone + ); + if (postClone) postClone(hooks2); + return hooks2; + } + }; + return hooks; +} +function emptyPlaceholder(vnode) { + if (isKeepAlive(vnode)) { + vnode = cloneVNode(vnode); + vnode.children = null; + return vnode; + } +} +function getInnerChild$1(vnode) { + if (!isKeepAlive(vnode)) { + if (isTeleport(vnode.type) && vnode.children) { + return findNonCommentChild(vnode.children); + } + return vnode; + } + if (vnode.component) { + return vnode.component.subTree; + } + const { shapeFlag, children } = vnode; + if (children) { + if (shapeFlag & 16) { + return children[0]; + } + if (shapeFlag & 32 && isFunction(children.default)) { + return children.default(); + } + } +} +function setTransitionHooks(vnode, hooks) { + if (vnode.shapeFlag & 6 && vnode.component) { + vnode.transition = hooks; + setTransitionHooks(vnode.component.subTree, hooks); + } else if (vnode.shapeFlag & 128) { + vnode.ssContent.transition = hooks.clone(vnode.ssContent); + vnode.ssFallback.transition = hooks.clone(vnode.ssFallback); + } else { + vnode.transition = hooks; + } +} +function getTransitionRawChildren(children, keepComment = false, parentKey) { + let ret = []; + let keyedFragmentCount = 0; + for (let i = 0; i < children.length; i++) { + let child = children[i]; + const key = parentKey == null ? child.key : String(parentKey) + String(child.key != null ? child.key : i); + if (child.type === Fragment) { + if (child.patchFlag & 128) keyedFragmentCount++; + ret = ret.concat( + getTransitionRawChildren(child.children, keepComment, key) + ); + } else if (keepComment || child.type !== Comment) { + ret.push(key != null ? cloneVNode(child, { key }) : child); + } + } + if (keyedFragmentCount > 1) { + for (let i = 0; i < ret.length; i++) { + ret[i].patchFlag = -2; + } + } + return ret; +} +function defineComponent(options, extraOptions) { + return isFunction(options) ? ( + // #8236: extend call and options.name access are considered side-effects + // by Rollup, so we have to wrap it in a pure-annotated IIFE. + (() => extend({ name: options.name }, extraOptions, { setup: options }))() + ) : options; +} +function useId() { + const i = getCurrentInstance(); + if (i) { + return (i.appContext.config.idPrefix || "v") + "-" + i.ids[0] + i.ids[1]++; + } else if (true) { + warn$1( + `useId() is called when there is no active component instance to be associated with.` + ); + } +} +function markAsyncBoundary(instance) { + instance.ids = [instance.ids[0] + instance.ids[2]++ + "-", 0, 0]; +} +var knownTemplateRefs = /* @__PURE__ */ new WeakSet(); +function useTemplateRef(key) { + const i = getCurrentInstance(); + const r = shallowRef(null); + if (i) { + const refs = i.refs === EMPTY_OBJ ? i.refs = {} : i.refs; + let desc; + if ((desc = Object.getOwnPropertyDescriptor(refs, key)) && !desc.configurable) { + warn$1(`useTemplateRef('${key}') already exists.`); + } else { + Object.defineProperty(refs, key, { + enumerable: true, + get: () => r.value, + set: (val) => r.value = val + }); + } + } else if (true) { + warn$1( + `useTemplateRef() is called when there is no active component instance to be associated with.` + ); + } + const ret = true ? readonly(r) : r; + if (true) { + knownTemplateRefs.add(ret); + } + return ret; +} +function setRef(rawRef, oldRawRef, parentSuspense, vnode, isUnmount = false) { + if (isArray(rawRef)) { + rawRef.forEach( + (r, i) => setRef( + r, + oldRawRef && (isArray(oldRawRef) ? oldRawRef[i] : oldRawRef), + parentSuspense, + vnode, + isUnmount + ) + ); + return; + } + if (isAsyncWrapper(vnode) && !isUnmount) { + return; + } + const refValue = vnode.shapeFlag & 4 ? getComponentPublicInstance(vnode.component) : vnode.el; + const value = isUnmount ? null : refValue; + const { i: owner, r: ref2 } = rawRef; + if (!owner) { + warn$1( + `Missing ref owner context. ref cannot be used on hoisted vnodes. A vnode with ref must be created inside the render function.` + ); + return; + } + const oldRef = oldRawRef && oldRawRef.r; + const refs = owner.refs === EMPTY_OBJ ? owner.refs = {} : owner.refs; + const setupState = owner.setupState; + const rawSetupState = toRaw(setupState); + const canSetSetupRef = setupState === EMPTY_OBJ ? () => false : (key) => { + if (knownTemplateRefs.has(rawSetupState[key])) { + return false; + } + return hasOwn(rawSetupState, key); + }; + if (oldRef != null && oldRef !== ref2) { + if (isString(oldRef)) { + refs[oldRef] = null; + if (canSetSetupRef(oldRef)) { + setupState[oldRef] = null; + } + } else if (isRef2(oldRef)) { + oldRef.value = null; + } + } + if (isFunction(ref2)) { + callWithErrorHandling(ref2, owner, 12, [value, refs]); + } else { + const _isString = isString(ref2); + const _isRef = isRef2(ref2); + if (_isString || _isRef) { + const doSet = () => { + if (rawRef.f) { + const existing = _isString ? canSetSetupRef(ref2) ? setupState[ref2] : refs[ref2] : ref2.value; + if (isUnmount) { + isArray(existing) && remove(existing, refValue); + } else { + if (!isArray(existing)) { + if (_isString) { + refs[ref2] = [refValue]; + if (canSetSetupRef(ref2)) { + setupState[ref2] = refs[ref2]; + } + } else { + ref2.value = [refValue]; + if (rawRef.k) refs[rawRef.k] = ref2.value; + } + } else if (!existing.includes(refValue)) { + existing.push(refValue); + } + } + } else if (_isString) { + refs[ref2] = value; + if (canSetSetupRef(ref2)) { + setupState[ref2] = value; + } + } else if (_isRef) { + ref2.value = value; + if (rawRef.k) refs[rawRef.k] = value; + } else if (true) { + warn$1("Invalid template ref type:", ref2, `(${typeof ref2})`); + } + }; + if (value) { + doSet.id = -1; + queuePostRenderEffect(doSet, parentSuspense); + } else { + doSet(); + } + } else if (true) { + warn$1("Invalid template ref type:", ref2, `(${typeof ref2})`); + } + } +} +var hasLoggedMismatchError = false; +var logMismatchError = () => { + if (hasLoggedMismatchError) { + return; + } + console.error("Hydration completed but contains mismatches."); + hasLoggedMismatchError = true; +}; +var isSVGContainer = (container) => container.namespaceURI.includes("svg") && container.tagName !== "foreignObject"; +var isMathMLContainer = (container) => container.namespaceURI.includes("MathML"); +var getContainerType = (container) => { + if (container.nodeType !== 1) return void 0; + if (isSVGContainer(container)) return "svg"; + if (isMathMLContainer(container)) return "mathml"; + return void 0; +}; +var isComment = (node) => node.nodeType === 8; +function createHydrationFunctions(rendererInternals) { + const { + mt: mountComponent, + p: patch, + o: { + patchProp: patchProp2, + createText, + nextSibling, + parentNode, + remove: remove2, + insert, + createComment + } + } = rendererInternals; + const hydrate2 = (vnode, container) => { + if (!container.hasChildNodes()) { + warn$1( + `Attempting to hydrate existing markup but container is empty. Performing full mount instead.` + ); + patch(null, vnode, container); + flushPostFlushCbs(); + container._vnode = vnode; + return; + } + hydrateNode(container.firstChild, vnode, null, null, null); + flushPostFlushCbs(); + container._vnode = vnode; + }; + const hydrateNode = (node, vnode, parentComponent, parentSuspense, slotScopeIds, optimized = false) => { + optimized = optimized || !!vnode.dynamicChildren; + const isFragmentStart = isComment(node) && node.data === "["; + const onMismatch = () => handleMismatch( + node, + vnode, + parentComponent, + parentSuspense, + slotScopeIds, + isFragmentStart + ); + const { type, ref: ref2, shapeFlag, patchFlag } = vnode; + let domType = node.nodeType; + vnode.el = node; + if (true) { + def(node, "__vnode", vnode, true); + def(node, "__vueParentComponent", parentComponent, true); + } + if (patchFlag === -2) { + optimized = false; + vnode.dynamicChildren = null; + } + let nextNode = null; + switch (type) { + case Text: + if (domType !== 3) { + if (vnode.children === "") { + insert(vnode.el = createText(""), parentNode(node), node); + nextNode = node; + } else { + nextNode = onMismatch(); + } + } else { + if (node.data !== vnode.children) { + warn$1( + `Hydration text mismatch in`, + node.parentNode, + ` + - rendered on server: ${JSON.stringify( + node.data + )} + - expected on client: ${JSON.stringify(vnode.children)}` + ); + logMismatchError(); + node.data = vnode.children; + } + nextNode = nextSibling(node); + } + break; + case Comment: + if (isTemplateNode(node)) { + nextNode = nextSibling(node); + replaceNode( + vnode.el = node.content.firstChild, + node, + parentComponent + ); + } else if (domType !== 8 || isFragmentStart) { + nextNode = onMismatch(); + } else { + nextNode = nextSibling(node); + } + break; + case Static: + if (isFragmentStart) { + node = nextSibling(node); + domType = node.nodeType; + } + if (domType === 1 || domType === 3) { + nextNode = node; + const needToAdoptContent = !vnode.children.length; + for (let i = 0; i < vnode.staticCount; i++) { + if (needToAdoptContent) + vnode.children += nextNode.nodeType === 1 ? nextNode.outerHTML : nextNode.data; + if (i === vnode.staticCount - 1) { + vnode.anchor = nextNode; + } + nextNode = nextSibling(nextNode); + } + return isFragmentStart ? nextSibling(nextNode) : nextNode; + } else { + onMismatch(); + } + break; + case Fragment: + if (!isFragmentStart) { + nextNode = onMismatch(); + } else { + nextNode = hydrateFragment( + node, + vnode, + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + } + break; + default: + if (shapeFlag & 1) { + if ((domType !== 1 || vnode.type.toLowerCase() !== node.tagName.toLowerCase()) && !isTemplateNode(node)) { + nextNode = onMismatch(); + } else { + nextNode = hydrateElement( + node, + vnode, + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + } + } else if (shapeFlag & 6) { + vnode.slotScopeIds = slotScopeIds; + const container = parentNode(node); + if (isFragmentStart) { + nextNode = locateClosingAnchor(node); + } else if (isComment(node) && node.data === "teleport start") { + nextNode = locateClosingAnchor(node, node.data, "teleport end"); + } else { + nextNode = nextSibling(node); + } + mountComponent( + vnode, + container, + null, + parentComponent, + parentSuspense, + getContainerType(container), + optimized + ); + if (isAsyncWrapper(vnode)) { + let subTree; + if (isFragmentStart) { + subTree = createVNode(Fragment); + subTree.anchor = nextNode ? nextNode.previousSibling : container.lastChild; + } else { + subTree = node.nodeType === 3 ? createTextVNode("") : createVNode("div"); + } + subTree.el = node; + vnode.component.subTree = subTree; + } + } else if (shapeFlag & 64) { + if (domType !== 8) { + nextNode = onMismatch(); + } else { + nextNode = vnode.type.hydrate( + node, + vnode, + parentComponent, + parentSuspense, + slotScopeIds, + optimized, + rendererInternals, + hydrateChildren + ); + } + } else if (shapeFlag & 128) { + nextNode = vnode.type.hydrate( + node, + vnode, + parentComponent, + parentSuspense, + getContainerType(parentNode(node)), + slotScopeIds, + optimized, + rendererInternals, + hydrateNode + ); + } else if (true) { + warn$1("Invalid HostVNode type:", type, `(${typeof type})`); + } + } + if (ref2 != null) { + setRef(ref2, null, parentSuspense, vnode); + } + return nextNode; + }; + const hydrateElement = (el, vnode, parentComponent, parentSuspense, slotScopeIds, optimized) => { + optimized = optimized || !!vnode.dynamicChildren; + const { type, props, patchFlag, shapeFlag, dirs, transition } = vnode; + const forcePatch = type === "input" || type === "option"; + if (true) { + if (dirs) { + invokeDirectiveHook(vnode, null, parentComponent, "created"); + } + let needCallTransitionHooks = false; + if (isTemplateNode(el)) { + needCallTransitionHooks = needTransition(parentSuspense, transition) && parentComponent && parentComponent.vnode.props && parentComponent.vnode.props.appear; + const content = el.content.firstChild; + if (needCallTransitionHooks) { + transition.beforeEnter(content); + } + replaceNode(content, el, parentComponent); + vnode.el = el = content; + } + if (shapeFlag & 16 && // skip if element has innerHTML / textContent + !(props && (props.innerHTML || props.textContent))) { + let next = hydrateChildren( + el.firstChild, + vnode, + el, + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + let hasWarned2 = false; + while (next) { + if (!isMismatchAllowed( + el, + 1 + /* CHILDREN */ + )) { + if (!hasWarned2) { + warn$1( + `Hydration children mismatch on`, + el, + ` +Server rendered element contains more child nodes than client vdom.` + ); + hasWarned2 = true; + } + logMismatchError(); + } + const cur = next; + next = next.nextSibling; + remove2(cur); + } + } else if (shapeFlag & 8) { + let clientText = vnode.children; + if (clientText[0] === "\n" && (el.tagName === "PRE" || el.tagName === "TEXTAREA")) { + clientText = clientText.slice(1); + } + if (el.textContent !== clientText) { + if (!isMismatchAllowed( + el, + 0 + /* TEXT */ + )) { + warn$1( + `Hydration text content mismatch on`, + el, + ` + - rendered on server: ${el.textContent} + - expected on client: ${vnode.children}` + ); + logMismatchError(); + } + el.textContent = vnode.children; + } + } + if (props) { + if (true) { + const isCustomElement = el.tagName.includes("-"); + for (const key in props) { + if (// #11189 skip if this node has directives that have created hooks + // as it could have mutated the DOM in any possible way + !(dirs && dirs.some((d) => d.dir.created)) && propHasMismatch(el, key, props[key], vnode, parentComponent)) { + logMismatchError(); + } + if (forcePatch && (key.endsWith("value") || key === "indeterminate") || isOn(key) && !isReservedProp(key) || // force hydrate v-bind with .prop modifiers + key[0] === "." || isCustomElement) { + patchProp2(el, key, null, props[key], void 0, parentComponent); + } + } + } else if (props.onClick) { + patchProp2( + el, + "onClick", + null, + props.onClick, + void 0, + parentComponent + ); + } else if (patchFlag & 4 && isReactive(props.style)) { + for (const key in props.style) props.style[key]; + } + } + let vnodeHooks; + if (vnodeHooks = props && props.onVnodeBeforeMount) { + invokeVNodeHook(vnodeHooks, parentComponent, vnode); + } + if (dirs) { + invokeDirectiveHook(vnode, null, parentComponent, "beforeMount"); + } + if ((vnodeHooks = props && props.onVnodeMounted) || dirs || needCallTransitionHooks) { + queueEffectWithSuspense(() => { + vnodeHooks && invokeVNodeHook(vnodeHooks, parentComponent, vnode); + needCallTransitionHooks && transition.enter(el); + dirs && invokeDirectiveHook(vnode, null, parentComponent, "mounted"); + }, parentSuspense); + } + } + return el.nextSibling; + }; + const hydrateChildren = (node, parentVNode, container, parentComponent, parentSuspense, slotScopeIds, optimized) => { + optimized = optimized || !!parentVNode.dynamicChildren; + const children = parentVNode.children; + const l = children.length; + let hasWarned2 = false; + for (let i = 0; i < l; i++) { + const vnode = optimized ? children[i] : children[i] = normalizeVNode(children[i]); + const isText = vnode.type === Text; + if (node) { + if (isText && !optimized) { + if (i + 1 < l && normalizeVNode(children[i + 1]).type === Text) { + insert( + createText( + node.data.slice(vnode.children.length) + ), + container, + nextSibling(node) + ); + node.data = vnode.children; + } + } + node = hydrateNode( + node, + vnode, + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + } else if (isText && !vnode.children) { + insert(vnode.el = createText(""), container); + } else { + if (!isMismatchAllowed( + container, + 1 + /* CHILDREN */ + )) { + if (!hasWarned2) { + warn$1( + `Hydration children mismatch on`, + container, + ` +Server rendered element contains fewer child nodes than client vdom.` + ); + hasWarned2 = true; + } + logMismatchError(); + } + patch( + null, + vnode, + container, + null, + parentComponent, + parentSuspense, + getContainerType(container), + slotScopeIds + ); + } + } + return node; + }; + const hydrateFragment = (node, vnode, parentComponent, parentSuspense, slotScopeIds, optimized) => { + const { slotScopeIds: fragmentSlotScopeIds } = vnode; + if (fragmentSlotScopeIds) { + slotScopeIds = slotScopeIds ? slotScopeIds.concat(fragmentSlotScopeIds) : fragmentSlotScopeIds; + } + const container = parentNode(node); + const next = hydrateChildren( + nextSibling(node), + vnode, + container, + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + if (next && isComment(next) && next.data === "]") { + return nextSibling(vnode.anchor = next); + } else { + logMismatchError(); + insert(vnode.anchor = createComment(`]`), container, next); + return next; + } + }; + const handleMismatch = (node, vnode, parentComponent, parentSuspense, slotScopeIds, isFragment) => { + if (!isMismatchAllowed( + node.parentElement, + 1 + /* CHILDREN */ + )) { + warn$1( + `Hydration node mismatch: +- rendered on server:`, + node, + node.nodeType === 3 ? `(text)` : isComment(node) && node.data === "[" ? `(start of fragment)` : ``, + ` +- expected on client:`, + vnode.type + ); + logMismatchError(); + } + vnode.el = null; + if (isFragment) { + const end = locateClosingAnchor(node); + while (true) { + const next2 = nextSibling(node); + if (next2 && next2 !== end) { + remove2(next2); + } else { + break; + } + } + } + const next = nextSibling(node); + const container = parentNode(node); + remove2(node); + patch( + null, + vnode, + container, + next, + parentComponent, + parentSuspense, + getContainerType(container), + slotScopeIds + ); + return next; + }; + const locateClosingAnchor = (node, open = "[", close = "]") => { + let match = 0; + while (node) { + node = nextSibling(node); + if (node && isComment(node)) { + if (node.data === open) match++; + if (node.data === close) { + if (match === 0) { + return nextSibling(node); + } else { + match--; + } + } + } + } + return node; + }; + const replaceNode = (newNode, oldNode, parentComponent) => { + const parentNode2 = oldNode.parentNode; + if (parentNode2) { + parentNode2.replaceChild(newNode, oldNode); + } + let parent = parentComponent; + while (parent) { + if (parent.vnode.el === oldNode) { + parent.vnode.el = parent.subTree.el = newNode; + } + parent = parent.parent; + } + }; + const isTemplateNode = (node) => { + return node.nodeType === 1 && node.tagName === "TEMPLATE"; + }; + return [hydrate2, hydrateNode]; +} +function propHasMismatch(el, key, clientValue, vnode, instance) { + let mismatchType; + let mismatchKey; + let actual; + let expected; + if (key === "class") { + actual = el.getAttribute("class"); + expected = normalizeClass(clientValue); + if (!isSetEqual(toClassSet(actual || ""), toClassSet(expected))) { + mismatchType = 2; + mismatchKey = `class`; + } + } else if (key === "style") { + actual = el.getAttribute("style") || ""; + expected = isString(clientValue) ? clientValue : stringifyStyle(normalizeStyle(clientValue)); + const actualMap = toStyleMap(actual); + const expectedMap = toStyleMap(expected); + if (vnode.dirs) { + for (const { dir, value } of vnode.dirs) { + if (dir.name === "show" && !value) { + expectedMap.set("display", "none"); + } + } + } + if (instance) { + resolveCssVars(instance, vnode, expectedMap); + } + if (!isMapEqual(actualMap, expectedMap)) { + mismatchType = 3; + mismatchKey = "style"; + } + } else if (el instanceof SVGElement && isKnownSvgAttr(key) || el instanceof HTMLElement && (isBooleanAttr(key) || isKnownHtmlAttr(key))) { + if (isBooleanAttr(key)) { + actual = el.hasAttribute(key); + expected = includeBooleanAttr(clientValue); + } else if (clientValue == null) { + actual = el.hasAttribute(key); + expected = false; + } else { + if (el.hasAttribute(key)) { + actual = el.getAttribute(key); + } else if (key === "value" && el.tagName === "TEXTAREA") { + actual = el.value; + } else { + actual = false; + } + expected = isRenderableAttrValue(clientValue) ? String(clientValue) : false; + } + if (actual !== expected) { + mismatchType = 4; + mismatchKey = key; + } + } + if (mismatchType != null && !isMismatchAllowed(el, mismatchType)) { + const format = (v) => v === false ? `(not rendered)` : `${mismatchKey}="${v}"`; + const preSegment = `Hydration ${MismatchTypeString[mismatchType]} mismatch on`; + const postSegment = ` + - rendered on server: ${format(actual)} + - expected on client: ${format(expected)} + Note: this mismatch is check-only. The DOM will not be rectified in production due to performance overhead. + You should fix the source of the mismatch.`; + { + warn$1(preSegment, el, postSegment); + } + return true; + } + return false; +} +function toClassSet(str) { + return new Set(str.trim().split(/\s+/)); +} +function isSetEqual(a, b) { + if (a.size !== b.size) { + return false; + } + for (const s of a) { + if (!b.has(s)) { + return false; + } + } + return true; +} +function toStyleMap(str) { + const styleMap = /* @__PURE__ */ new Map(); + for (const item of str.split(";")) { + let [key, value] = item.split(":"); + key = key.trim(); + value = value && value.trim(); + if (key && value) { + styleMap.set(key, value); + } + } + return styleMap; +} +function isMapEqual(a, b) { + if (a.size !== b.size) { + return false; + } + for (const [key, value] of a) { + if (value !== b.get(key)) { + return false; + } + } + return true; +} +function resolveCssVars(instance, vnode, expectedMap) { + const root = instance.subTree; + if (instance.getCssVars && (vnode === root || root && root.type === Fragment && root.children.includes(vnode))) { + const cssVars = instance.getCssVars(); + for (const key in cssVars) { + expectedMap.set( + `--${getEscapedCssVarName(key, false)}`, + String(cssVars[key]) + ); + } + } + if (vnode === root && instance.parent) { + resolveCssVars(instance.parent, instance.vnode, expectedMap); + } +} +var allowMismatchAttr = "data-allow-mismatch"; +var MismatchTypeString = { + [ + 0 + /* TEXT */ + ]: "text", + [ + 1 + /* CHILDREN */ + ]: "children", + [ + 2 + /* CLASS */ + ]: "class", + [ + 3 + /* STYLE */ + ]: "style", + [ + 4 + /* ATTRIBUTE */ + ]: "attribute" +}; +function isMismatchAllowed(el, allowedType) { + if (allowedType === 0 || allowedType === 1) { + while (el && !el.hasAttribute(allowMismatchAttr)) { + el = el.parentElement; + } + } + const allowedAttr = el && el.getAttribute(allowMismatchAttr); + if (allowedAttr == null) { + return false; + } else if (allowedAttr === "") { + return true; + } else { + const list = allowedAttr.split(","); + if (allowedType === 0 && list.includes("children")) { + return true; + } + return allowedAttr.split(",").includes(MismatchTypeString[allowedType]); + } +} +var hydrateOnIdle = (timeout = 1e4) => (hydrate2) => { + const id = requestIdleCallback(hydrate2, { timeout }); + return () => cancelIdleCallback(id); +}; +var hydrateOnVisible = (opts) => (hydrate2, forEach) => { + const ob = new IntersectionObserver((entries) => { + for (const e of entries) { + if (!e.isIntersecting) continue; + ob.disconnect(); + hydrate2(); + break; + } + }, opts); + forEach((el) => ob.observe(el)); + return () => ob.disconnect(); +}; +var hydrateOnMediaQuery = (query) => (hydrate2) => { + if (query) { + const mql = matchMedia(query); + if (mql.matches) { + hydrate2(); + } else { + mql.addEventListener("change", hydrate2, { once: true }); + return () => mql.removeEventListener("change", hydrate2); + } + } +}; +var hydrateOnInteraction = (interactions = []) => (hydrate2, forEach) => { + if (isString(interactions)) interactions = [interactions]; + let hasHydrated = false; + const doHydrate = (e) => { + if (!hasHydrated) { + hasHydrated = true; + teardown(); + hydrate2(); + e.target.dispatchEvent(new e.constructor(e.type, e)); + } + }; + const teardown = () => { + forEach((el) => { + for (const i of interactions) { + el.removeEventListener(i, doHydrate); + } + }); + }; + forEach((el) => { + for (const i of interactions) { + el.addEventListener(i, doHydrate, { once: true }); + } + }); + return teardown; +}; +function forEachElement(node, cb) { + if (isComment(node) && node.data === "[") { + let depth = 1; + let next = node.nextSibling; + while (next) { + if (next.nodeType === 1) { + cb(next); + } else if (isComment(next)) { + if (next.data === "]") { + if (--depth === 0) break; + } else if (next.data === "[") { + depth++; + } + } + next = next.nextSibling; + } + } else { + cb(node); + } +} +var isAsyncWrapper = (i) => !!i.type.__asyncLoader; +function defineAsyncComponent(source) { + if (isFunction(source)) { + source = { loader: source }; + } + const { + loader, + loadingComponent, + errorComponent, + delay = 200, + hydrate: hydrateStrategy, + timeout, + // undefined = never times out + suspensible = true, + onError: userOnError + } = source; + let pendingRequest = null; + let resolvedComp; + let retries = 0; + const retry = () => { + retries++; + pendingRequest = null; + return load(); + }; + const load = () => { + let thisRequest; + return pendingRequest || (thisRequest = pendingRequest = loader().catch((err) => { + err = err instanceof Error ? err : new Error(String(err)); + if (userOnError) { + return new Promise((resolve2, reject) => { + const userRetry = () => resolve2(retry()); + const userFail = () => reject(err); + userOnError(err, userRetry, userFail, retries + 1); + }); + } else { + throw err; + } + }).then((comp) => { + if (thisRequest !== pendingRequest && pendingRequest) { + return pendingRequest; + } + if (!comp) { + warn$1( + `Async component loader resolved to undefined. If you are using retry(), make sure to return its return value.` + ); + } + if (comp && (comp.__esModule || comp[Symbol.toStringTag] === "Module")) { + comp = comp.default; + } + if (comp && !isObject(comp) && !isFunction(comp)) { + throw new Error(`Invalid async component load result: ${comp}`); + } + resolvedComp = comp; + return comp; + })); + }; + return defineComponent({ + name: "AsyncComponentWrapper", + __asyncLoader: load, + __asyncHydrate(el, instance, hydrate2) { + const doHydrate = hydrateStrategy ? () => { + const teardown = hydrateStrategy( + hydrate2, + (cb) => forEachElement(el, cb) + ); + if (teardown) { + (instance.bum || (instance.bum = [])).push(teardown); + } + } : hydrate2; + if (resolvedComp) { + doHydrate(); + } else { + load().then(() => !instance.isUnmounted && doHydrate()); + } + }, + get __asyncResolved() { + return resolvedComp; + }, + setup() { + const instance = currentInstance; + markAsyncBoundary(instance); + if (resolvedComp) { + return () => createInnerComp(resolvedComp, instance); + } + const onError = (err) => { + pendingRequest = null; + handleError( + err, + instance, + 13, + !errorComponent + ); + }; + if (suspensible && instance.suspense || isInSSRComponentSetup) { + return load().then((comp) => { + return () => createInnerComp(comp, instance); + }).catch((err) => { + onError(err); + return () => errorComponent ? createVNode(errorComponent, { + error: err + }) : null; + }); + } + const loaded = ref(false); + const error = ref(); + const delayed = ref(!!delay); + if (delay) { + setTimeout(() => { + delayed.value = false; + }, delay); + } + if (timeout != null) { + setTimeout(() => { + if (!loaded.value && !error.value) { + const err = new Error( + `Async component timed out after ${timeout}ms.` + ); + onError(err); + error.value = err; + } + }, timeout); + } + load().then(() => { + loaded.value = true; + if (instance.parent && isKeepAlive(instance.parent.vnode)) { + instance.parent.update(); + } + }).catch((err) => { + onError(err); + error.value = err; + }); + return () => { + if (loaded.value && resolvedComp) { + return createInnerComp(resolvedComp, instance); + } else if (error.value && errorComponent) { + return createVNode(errorComponent, { + error: error.value + }); + } else if (loadingComponent && !delayed.value) { + return createVNode(loadingComponent); + } + }; + } + }); +} +function createInnerComp(comp, parent) { + const { ref: ref2, props, children, ce } = parent.vnode; + const vnode = createVNode(comp, props, children); + vnode.ref = ref2; + vnode.ce = ce; + delete parent.vnode.ce; + return vnode; +} +var isKeepAlive = (vnode) => vnode.type.__isKeepAlive; +var KeepAliveImpl = { + name: `KeepAlive`, + // Marker for special handling inside the renderer. We are not using a === + // check directly on KeepAlive in the renderer, because importing it directly + // would prevent it from being tree-shaken. + __isKeepAlive: true, + props: { + include: [String, RegExp, Array], + exclude: [String, RegExp, Array], + max: [String, Number] + }, + setup(props, { slots }) { + const instance = getCurrentInstance(); + const sharedContext = instance.ctx; + if (!sharedContext.renderer) { + return () => { + const children = slots.default && slots.default(); + return children && children.length === 1 ? children[0] : children; + }; + } + const cache = /* @__PURE__ */ new Map(); + const keys = /* @__PURE__ */ new Set(); + let current = null; + if (true) { + instance.__v_cache = cache; + } + const parentSuspense = instance.suspense; + const { + renderer: { + p: patch, + m: move, + um: _unmount, + o: { createElement } + } + } = sharedContext; + const storageContainer = createElement("div"); + sharedContext.activate = (vnode, container, anchor, namespace, optimized) => { + const instance2 = vnode.component; + move(vnode, container, anchor, 0, parentSuspense); + patch( + instance2.vnode, + vnode, + container, + anchor, + instance2, + parentSuspense, + namespace, + vnode.slotScopeIds, + optimized + ); + queuePostRenderEffect(() => { + instance2.isDeactivated = false; + if (instance2.a) { + invokeArrayFns(instance2.a); + } + const vnodeHook = vnode.props && vnode.props.onVnodeMounted; + if (vnodeHook) { + invokeVNodeHook(vnodeHook, instance2.parent, vnode); + } + }, parentSuspense); + if (true) { + devtoolsComponentAdded(instance2); + } + }; + sharedContext.deactivate = (vnode) => { + const instance2 = vnode.component; + invalidateMount(instance2.m); + invalidateMount(instance2.a); + move(vnode, storageContainer, null, 1, parentSuspense); + queuePostRenderEffect(() => { + if (instance2.da) { + invokeArrayFns(instance2.da); + } + const vnodeHook = vnode.props && vnode.props.onVnodeUnmounted; + if (vnodeHook) { + invokeVNodeHook(vnodeHook, instance2.parent, vnode); + } + instance2.isDeactivated = true; + }, parentSuspense); + if (true) { + devtoolsComponentAdded(instance2); + } + }; + function unmount(vnode) { + resetShapeFlag(vnode); + _unmount(vnode, instance, parentSuspense, true); + } + function pruneCache(filter) { + cache.forEach((vnode, key) => { + const name = getComponentName(vnode.type); + if (name && !filter(name)) { + pruneCacheEntry(key); + } + }); + } + function pruneCacheEntry(key) { + const cached = cache.get(key); + if (cached && (!current || !isSameVNodeType(cached, current))) { + unmount(cached); + } else if (current) { + resetShapeFlag(current); + } + cache.delete(key); + keys.delete(key); + } + watch2( + () => [props.include, props.exclude], + ([include, exclude]) => { + include && pruneCache((name) => matches(include, name)); + exclude && pruneCache((name) => !matches(exclude, name)); + }, + // prune post-render after `current` has been updated + { flush: "post", deep: true } + ); + let pendingCacheKey = null; + const cacheSubtree = () => { + if (pendingCacheKey != null) { + if (isSuspense(instance.subTree.type)) { + queuePostRenderEffect(() => { + cache.set(pendingCacheKey, getInnerChild(instance.subTree)); + }, instance.subTree.suspense); + } else { + cache.set(pendingCacheKey, getInnerChild(instance.subTree)); + } + } + }; + onMounted(cacheSubtree); + onUpdated(cacheSubtree); + onBeforeUnmount(() => { + cache.forEach((cached) => { + const { subTree, suspense } = instance; + const vnode = getInnerChild(subTree); + if (cached.type === vnode.type && cached.key === vnode.key) { + resetShapeFlag(vnode); + const da = vnode.component.da; + da && queuePostRenderEffect(da, suspense); + return; + } + unmount(cached); + }); + }); + return () => { + pendingCacheKey = null; + if (!slots.default) { + return current = null; + } + const children = slots.default(); + const rawVNode = children[0]; + if (children.length > 1) { + if (true) { + warn$1(`KeepAlive should contain exactly one component child.`); + } + current = null; + return children; + } else if (!isVNode(rawVNode) || !(rawVNode.shapeFlag & 4) && !(rawVNode.shapeFlag & 128)) { + current = null; + return rawVNode; + } + let vnode = getInnerChild(rawVNode); + if (vnode.type === Comment) { + current = null; + return vnode; + } + const comp = vnode.type; + const name = getComponentName( + isAsyncWrapper(vnode) ? vnode.type.__asyncResolved || {} : comp + ); + const { include, exclude, max } = props; + if (include && (!name || !matches(include, name)) || exclude && name && matches(exclude, name)) { + vnode.shapeFlag &= ~256; + current = vnode; + return rawVNode; + } + const key = vnode.key == null ? comp : vnode.key; + const cachedVNode = cache.get(key); + if (vnode.el) { + vnode = cloneVNode(vnode); + if (rawVNode.shapeFlag & 128) { + rawVNode.ssContent = vnode; + } + } + pendingCacheKey = key; + if (cachedVNode) { + vnode.el = cachedVNode.el; + vnode.component = cachedVNode.component; + if (vnode.transition) { + setTransitionHooks(vnode, vnode.transition); + } + vnode.shapeFlag |= 512; + keys.delete(key); + keys.add(key); + } else { + keys.add(key); + if (max && keys.size > parseInt(max, 10)) { + pruneCacheEntry(keys.values().next().value); + } + } + vnode.shapeFlag |= 256; + current = vnode; + return isSuspense(rawVNode.type) ? rawVNode : vnode; + }; + } +}; +var KeepAlive = KeepAliveImpl; +function matches(pattern, name) { + if (isArray(pattern)) { + return pattern.some((p2) => matches(p2, name)); + } else if (isString(pattern)) { + return pattern.split(",").includes(name); + } else if (isRegExp(pattern)) { + pattern.lastIndex = 0; + return pattern.test(name); + } + return false; +} +function onActivated(hook, target) { + registerKeepAliveHook(hook, "a", target); +} +function onDeactivated(hook, target) { + registerKeepAliveHook(hook, "da", target); +} +function registerKeepAliveHook(hook, type, target = currentInstance) { + const wrappedHook = hook.__wdc || (hook.__wdc = () => { + let current = target; + while (current) { + if (current.isDeactivated) { + return; + } + current = current.parent; + } + return hook(); + }); + injectHook(type, wrappedHook, target); + if (target) { + let current = target.parent; + while (current && current.parent) { + if (isKeepAlive(current.parent.vnode)) { + injectToKeepAliveRoot(wrappedHook, type, target, current); + } + current = current.parent; + } + } +} +function injectToKeepAliveRoot(hook, type, target, keepAliveRoot) { + const injected = injectHook( + type, + hook, + keepAliveRoot, + true + /* prepend */ + ); + onUnmounted(() => { + remove(keepAliveRoot[type], injected); + }, target); +} +function resetShapeFlag(vnode) { + vnode.shapeFlag &= ~256; + vnode.shapeFlag &= ~512; +} +function getInnerChild(vnode) { + return vnode.shapeFlag & 128 ? vnode.ssContent : vnode; +} +function injectHook(type, hook, target = currentInstance, prepend = false) { + if (target) { + const hooks = target[type] || (target[type] = []); + const wrappedHook = hook.__weh || (hook.__weh = (...args) => { + pauseTracking(); + const reset = setCurrentInstance(target); + const res = callWithAsyncErrorHandling(hook, target, type, args); + reset(); + resetTracking(); + return res; + }); + if (prepend) { + hooks.unshift(wrappedHook); + } else { + hooks.push(wrappedHook); + } + return wrappedHook; + } else if (true) { + const apiName = toHandlerKey(ErrorTypeStrings$1[type].replace(/ hook$/, "")); + warn$1( + `${apiName} is called when there is no active component instance to be associated with. Lifecycle injection APIs can only be used during execution of setup(). If you are using async setup(), make sure to register lifecycle hooks before the first await statement.` + ); + } +} +var createHook = (lifecycle) => (hook, target = currentInstance) => { + if (!isInSSRComponentSetup || lifecycle === "sp") { + injectHook(lifecycle, (...args) => hook(...args), target); + } +}; +var onBeforeMount = createHook("bm"); +var onMounted = createHook("m"); +var onBeforeUpdate = createHook( + "bu" +); +var onUpdated = createHook("u"); +var onBeforeUnmount = createHook( + "bum" +); +var onUnmounted = createHook("um"); +var onServerPrefetch = createHook( + "sp" +); +var onRenderTriggered = createHook("rtg"); +var onRenderTracked = createHook("rtc"); +function onErrorCaptured(hook, target = currentInstance) { + injectHook("ec", hook, target); +} +var COMPONENTS = "components"; +var DIRECTIVES = "directives"; +function resolveComponent(name, maybeSelfReference) { + return resolveAsset(COMPONENTS, name, true, maybeSelfReference) || name; +} +var NULL_DYNAMIC_COMPONENT = Symbol.for("v-ndc"); +function resolveDynamicComponent(component) { + if (isString(component)) { + return resolveAsset(COMPONENTS, component, false) || component; + } else { + return component || NULL_DYNAMIC_COMPONENT; + } +} +function resolveDirective(name) { + return resolveAsset(DIRECTIVES, name); +} +function resolveAsset(type, name, warnMissing = true, maybeSelfReference = false) { + const instance = currentRenderingInstance || currentInstance; + if (instance) { + const Component = instance.type; + if (type === COMPONENTS) { + const selfName = getComponentName( + Component, + false + ); + if (selfName && (selfName === name || selfName === camelize(name) || selfName === capitalize(camelize(name)))) { + return Component; + } + } + const res = ( + // local registration + // check instance[type] first which is resolved for options API + resolve(instance[type] || Component[type], name) || // global registration + resolve(instance.appContext[type], name) + ); + if (!res && maybeSelfReference) { + return Component; + } + if (warnMissing && !res) { + const extra = type === COMPONENTS ? ` +If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.` : ``; + warn$1(`Failed to resolve ${type.slice(0, -1)}: ${name}${extra}`); + } + return res; + } else if (true) { + warn$1( + `resolve${capitalize(type.slice(0, -1))} can only be used in render() or setup().` + ); + } +} +function resolve(registry, name) { + return registry && (registry[name] || registry[camelize(name)] || registry[capitalize(camelize(name))]); +} +function renderList(source, renderItem, cache, index) { + let ret; + const cached = cache && cache[index]; + const sourceIsArray = isArray(source); + if (sourceIsArray || isString(source)) { + const sourceIsReactiveArray = sourceIsArray && isReactive(source); + let needsWrap = false; + if (sourceIsReactiveArray) { + needsWrap = !isShallow(source); + source = shallowReadArray(source); + } + ret = new Array(source.length); + for (let i = 0, l = source.length; i < l; i++) { + ret[i] = renderItem( + needsWrap ? toReactive(source[i]) : source[i], + i, + void 0, + cached && cached[i] + ); + } + } else if (typeof source === "number") { + if (!Number.isInteger(source)) { + warn$1(`The v-for range expect an integer value but got ${source}.`); + } + ret = new Array(source); + for (let i = 0; i < source; i++) { + ret[i] = renderItem(i + 1, i, void 0, cached && cached[i]); + } + } else if (isObject(source)) { + if (source[Symbol.iterator]) { + ret = Array.from( + source, + (item, i) => renderItem(item, i, void 0, cached && cached[i]) + ); + } else { + const keys = Object.keys(source); + ret = new Array(keys.length); + for (let i = 0, l = keys.length; i < l; i++) { + const key = keys[i]; + ret[i] = renderItem(source[key], key, i, cached && cached[i]); + } + } + } else { + ret = []; + } + if (cache) { + cache[index] = ret; + } + return ret; +} +function createSlots(slots, dynamicSlots) { + for (let i = 0; i < dynamicSlots.length; i++) { + const slot = dynamicSlots[i]; + if (isArray(slot)) { + for (let j = 0; j < slot.length; j++) { + slots[slot[j].name] = slot[j].fn; + } + } else if (slot) { + slots[slot.name] = slot.key ? (...args) => { + const res = slot.fn(...args); + if (res) res.key = slot.key; + return res; + } : slot.fn; + } + } + return slots; +} +function renderSlot(slots, name, props = {}, fallback, noSlotted) { + if (currentRenderingInstance.ce || currentRenderingInstance.parent && isAsyncWrapper(currentRenderingInstance.parent) && currentRenderingInstance.parent.ce) { + if (name !== "default") props.name = name; + return openBlock(), createBlock( + Fragment, + null, + [createVNode("slot", props, fallback && fallback())], + 64 + ); + } + let slot = slots[name]; + if (slot && slot.length > 1) { + warn$1( + `SSR-optimized slot function detected in a non-SSR-optimized render function. You need to mark this component with $dynamic-slots in the parent template.` + ); + slot = () => []; + } + if (slot && slot._c) { + slot._d = false; + } + openBlock(); + const validSlotContent = slot && ensureValidVNode(slot(props)); + const rendered = createBlock( + Fragment, + { + key: (props.key || // slot content array of a dynamic conditional slot may have a branch + // key attached in the `createSlots` helper, respect that + validSlotContent && validSlotContent.key || `_${name}`) + // #7256 force differentiate fallback content from actual content + (!validSlotContent && fallback ? "_fb" : "") + }, + validSlotContent || (fallback ? fallback() : []), + validSlotContent && slots._ === 1 ? 64 : -2 + ); + if (!noSlotted && rendered.scopeId) { + rendered.slotScopeIds = [rendered.scopeId + "-s"]; + } + if (slot && slot._c) { + slot._d = true; + } + return rendered; +} +function ensureValidVNode(vnodes) { + return vnodes.some((child) => { + if (!isVNode(child)) return true; + if (child.type === Comment) return false; + if (child.type === Fragment && !ensureValidVNode(child.children)) + return false; + return true; + }) ? vnodes : null; +} +function toHandlers(obj, preserveCaseIfNecessary) { + const ret = {}; + if (!isObject(obj)) { + warn$1(`v-on with no argument expects an object value.`); + return ret; + } + for (const key in obj) { + ret[preserveCaseIfNecessary && /[A-Z]/.test(key) ? `on:${key}` : toHandlerKey(key)] = obj[key]; + } + return ret; +} +var getPublicInstance = (i) => { + if (!i) return null; + if (isStatefulComponent(i)) return getComponentPublicInstance(i); + return getPublicInstance(i.parent); +}; +var publicPropertiesMap = ( + // Move PURE marker to new line to workaround compiler discarding it + // due to type annotation + extend(/* @__PURE__ */ Object.create(null), { + $: (i) => i, + $el: (i) => i.vnode.el, + $data: (i) => i.data, + $props: (i) => true ? shallowReadonly(i.props) : i.props, + $attrs: (i) => true ? shallowReadonly(i.attrs) : i.attrs, + $slots: (i) => true ? shallowReadonly(i.slots) : i.slots, + $refs: (i) => true ? shallowReadonly(i.refs) : i.refs, + $parent: (i) => getPublicInstance(i.parent), + $root: (i) => getPublicInstance(i.root), + $host: (i) => i.ce, + $emit: (i) => i.emit, + $options: (i) => __VUE_OPTIONS_API__ ? resolveMergedOptions(i) : i.type, + $forceUpdate: (i) => i.f || (i.f = () => { + queueJob(i.update); + }), + $nextTick: (i) => i.n || (i.n = nextTick.bind(i.proxy)), + $watch: (i) => __VUE_OPTIONS_API__ ? instanceWatch.bind(i) : NOOP + }) +); +var isReservedPrefix = (key) => key === "_" || key === "$"; +var hasSetupBinding = (state, key) => state !== EMPTY_OBJ && !state.__isScriptSetup && hasOwn(state, key); +var PublicInstanceProxyHandlers = { + get({ _: instance }, key) { + if (key === "__v_skip") { + return true; + } + const { ctx, setupState, data, props, accessCache, type, appContext } = instance; + if (key === "__isVue") { + return true; + } + let normalizedProps; + if (key[0] !== "$") { + const n = accessCache[key]; + if (n !== void 0) { + switch (n) { + case 1: + return setupState[key]; + case 2: + return data[key]; + case 4: + return ctx[key]; + case 3: + return props[key]; + } + } else if (hasSetupBinding(setupState, key)) { + accessCache[key] = 1; + return setupState[key]; + } else if (data !== EMPTY_OBJ && hasOwn(data, key)) { + accessCache[key] = 2; + return data[key]; + } else if ( + // only cache other properties when instance has declared (thus stable) + // props + (normalizedProps = instance.propsOptions[0]) && hasOwn(normalizedProps, key) + ) { + accessCache[key] = 3; + return props[key]; + } else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) { + accessCache[key] = 4; + return ctx[key]; + } else if (!__VUE_OPTIONS_API__ || shouldCacheAccess) { + accessCache[key] = 0; + } + } + const publicGetter = publicPropertiesMap[key]; + let cssModule, globalProperties; + if (publicGetter) { + if (key === "$attrs") { + track(instance.attrs, "get", ""); + markAttrsAccessed(); + } else if (key === "$slots") { + track(instance, "get", key); + } + return publicGetter(instance); + } else if ( + // css module (injected by vue-loader) + (cssModule = type.__cssModules) && (cssModule = cssModule[key]) + ) { + return cssModule; + } else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) { + accessCache[key] = 4; + return ctx[key]; + } else if ( + // global properties + globalProperties = appContext.config.globalProperties, hasOwn(globalProperties, key) + ) { + { + return globalProperties[key]; + } + } else if (currentRenderingInstance && (!isString(key) || // #1091 avoid internal isRef/isVNode checks on component instance leading + // to infinite warning loop + key.indexOf("__v") !== 0)) { + if (data !== EMPTY_OBJ && isReservedPrefix(key[0]) && hasOwn(data, key)) { + warn$1( + `Property ${JSON.stringify( + key + )} must be accessed via $data because it starts with a reserved character ("$" or "_") and is not proxied on the render context.` + ); + } else if (instance === currentRenderingInstance) { + warn$1( + `Property ${JSON.stringify(key)} was accessed during render but is not defined on instance.` + ); + } + } + }, + set({ _: instance }, key, value) { + const { data, setupState, ctx } = instance; + if (hasSetupBinding(setupState, key)) { + setupState[key] = value; + return true; + } else if (setupState.__isScriptSetup && hasOwn(setupState, key)) { + warn$1(`Cannot mutate + + +``` + +By default the following tag/attribute combinations are transformed, and can be configured using the `template.transformAssetUrls` option. + +```js +{ + video: ['src', 'poster'], + source: ['src'], + img: ['src'], + image: ['xlink:href', 'href'], + use: ['xlink:href', 'href'] +} +``` + +Note that only attribute values that are static strings are transformed. Otherwise, you'd need to import the asset manually, e.g. `import imgUrl from '../image.png'`. + +## Example for passing options to `vue/compiler-sfc`: + +```ts +import vue from '@vitejs/plugin-vue' + +export default { + plugins: [ + vue({ + template: { + compilerOptions: { + // ... + }, + transformAssetUrls: { + // ... + }, + }, + }), + ], +} +``` + +## Example for transforming custom blocks + +```ts +import vue from '@vitejs/plugin-vue' +import yaml from 'js-yaml' + +const vueI18nPlugin = { + name: 'vue-i18n', + transform(code, id) { + // if .vue file don't have block, just return + if (!/vue&type=i18n/.test(id)) { + return + } + // parse yaml + if (/\.ya?ml$/.test(id)) { + code = JSON.stringify(yaml.load(code.trim())) + } + // mount the value on the i18n property of the component instance + return `export default Comp => { + Comp.i18n = ${code} + }` + }, +} + +export default { + plugins: [vue(), vueI18nPlugin], +} +``` + +Create a file named `Demo.vue`, add `lang="yaml"` to the `` blocks, then you can use the syntax of `YAML`: + +```vue + + + +message: 'world' +fullWord: 'hello world' + +``` + +`message` is mounted on the i18n property of the component instance, you can use like this: + +```vue + + + +``` + +## Using Vue SFCs as Custom Elements + +> Requires `vue@^3.2.0` & `@vitejs/plugin-vue@^1.4.0` + +Vue 3.2 introduces the `defineCustomElement` method, which works with SFCs. By default, `' + * ) + * document.type //=> 'document' + * document.nodes.length //=> 2 + * ``` + */ +declare class Document_ extends Container { + nodes: Root[] + parent: undefined + type: 'document' + + constructor(defaults?: Document.DocumentProps) + + assign(overrides: Document.DocumentProps | object): this + clone(overrides?: Partial): this + cloneAfter(overrides?: Partial): this + cloneBefore(overrides?: Partial): this + + /** + * Returns a `Result` instance representing the document’s CSS roots. + * + * ```js + * const root1 = postcss.parse(css1, { from: 'a.css' }) + * const root2 = postcss.parse(css2, { from: 'b.css' }) + * const document = postcss.document() + * document.append(root1) + * document.append(root2) + * const result = document.toResult({ to: 'all.css', map: true }) + * ``` + * + * @param opts Options. + * @return Result with current document’s CSS. + */ + toResult(options?: ProcessOptions): Result +} + +declare class Document extends Document_ {} + +export = Document diff --git a/node_modules/postcss/lib/document.js b/node_modules/postcss/lib/document.js new file mode 100644 index 0000000..4468991 --- /dev/null +++ b/node_modules/postcss/lib/document.js @@ -0,0 +1,33 @@ +'use strict' + +let Container = require('./container') + +let LazyResult, Processor + +class Document extends Container { + constructor(defaults) { + // type needs to be passed to super, otherwise child roots won't be normalized correctly + super({ type: 'document', ...defaults }) + + if (!this.nodes) { + this.nodes = [] + } + } + + toResult(opts = {}) { + let lazy = new LazyResult(new Processor(), this, opts) + + return lazy.stringify() + } +} + +Document.registerLazyResult = dependant => { + LazyResult = dependant +} + +Document.registerProcessor = dependant => { + Processor = dependant +} + +module.exports = Document +Document.default = Document diff --git a/node_modules/postcss/lib/fromJSON.d.ts b/node_modules/postcss/lib/fromJSON.d.ts new file mode 100644 index 0000000..e1deedb --- /dev/null +++ b/node_modules/postcss/lib/fromJSON.d.ts @@ -0,0 +1,9 @@ +import { JSONHydrator } from './postcss.js' + +interface FromJSON extends JSONHydrator { + default: FromJSON +} + +declare const fromJSON: FromJSON + +export = fromJSON diff --git a/node_modules/postcss/lib/fromJSON.js b/node_modules/postcss/lib/fromJSON.js new file mode 100644 index 0000000..c9ac1a8 --- /dev/null +++ b/node_modules/postcss/lib/fromJSON.js @@ -0,0 +1,54 @@ +'use strict' + +let AtRule = require('./at-rule') +let Comment = require('./comment') +let Declaration = require('./declaration') +let Input = require('./input') +let PreviousMap = require('./previous-map') +let Root = require('./root') +let Rule = require('./rule') + +function fromJSON(json, inputs) { + if (Array.isArray(json)) return json.map(n => fromJSON(n)) + + let { inputs: ownInputs, ...defaults } = json + if (ownInputs) { + inputs = [] + for (let input of ownInputs) { + let inputHydrated = { ...input, __proto__: Input.prototype } + if (inputHydrated.map) { + inputHydrated.map = { + ...inputHydrated.map, + __proto__: PreviousMap.prototype + } + } + inputs.push(inputHydrated) + } + } + if (defaults.nodes) { + defaults.nodes = json.nodes.map(n => fromJSON(n, inputs)) + } + if (defaults.source) { + let { inputId, ...source } = defaults.source + defaults.source = source + if (inputId != null) { + defaults.source.input = inputs[inputId] + } + } + if (defaults.type === 'root') { + return new Root(defaults) + } else if (defaults.type === 'decl') { + return new Declaration(defaults) + } else if (defaults.type === 'rule') { + return new Rule(defaults) + } else if (defaults.type === 'comment') { + return new Comment(defaults) + } else if (defaults.type === 'atrule') { + return new AtRule(defaults) + } else { + throw new Error('Unknown node type: ' + json.type) + } +} + +module.exports = fromJSON +fromJSON.default = fromJSON diff --git a/node_modules/postcss/lib/input.d.ts b/node_modules/postcss/lib/input.d.ts new file mode 100644 index 0000000..46ded09 --- /dev/null +++ b/node_modules/postcss/lib/input.d.ts @@ -0,0 +1,197 @@ +import { CssSyntaxError, ProcessOptions } from './postcss.js' +import PreviousMap from './previous-map.js' + +declare namespace Input { + export interface FilePosition { + /** + * Column of inclusive start position in source file. + */ + column: number + + /** + * Column of exclusive end position in source file. + */ + endColumn?: number + + /** + * Line of exclusive end position in source file. + */ + endLine?: number + + /** + * Absolute path to the source file. + */ + file?: string + + /** + * Line of inclusive start position in source file. + */ + line: number + + /** + * Source code. + */ + source?: string + + /** + * URL for the source file. + */ + url: string + } + + // eslint-disable-next-line @typescript-eslint/no-use-before-define + export { Input_ as default } +} + +/** + * Represents the source CSS. + * + * ```js + * const root = postcss.parse(css, { from: file }) + * const input = root.source.input + * ``` + */ +declare class Input_ { + /** + * Input CSS source. + * + * ```js + * const input = postcss.parse('a{}', { from: file }).input + * input.css //=> "a{}" + * ``` + */ + css: string + + /** + * The absolute path to the CSS source file defined + * with the `from` option. + * + * ```js + * const root = postcss.parse(css, { from: 'a.css' }) + * root.source.input.file //=> '/home/ai/a.css' + * ``` + */ + file?: string + + /** + * The flag to indicate whether or not the source code has Unicode BOM. + */ + hasBOM: boolean + + /** + * The unique ID of the CSS source. It will be created if `from` option + * is not provided (because PostCSS does not know the file path). + * + * ```js + * const root = postcss.parse(css) + * root.source.input.file //=> undefined + * root.source.input.id //=> "" + * ``` + */ + id?: string + + /** + * The input source map passed from a compilation step before PostCSS + * (for example, from Sass compiler). + * + * ```js + * root.source.input.map.consumer().sources //=> ['a.sass'] + * ``` + */ + map: PreviousMap + + /** + * @param css Input CSS source. + * @param opts Process options. + */ + constructor(css: string, opts?: ProcessOptions) + + error( + message: string, + start: + | { + column: number + line: number + } + | { + offset: number + }, + end: + | { + column: number + line: number + } + | { + offset: number + }, + opts?: { plugin?: CssSyntaxError['plugin'] } + ): CssSyntaxError + + /** + * Returns `CssSyntaxError` with information about the error and its position. + */ + error( + message: string, + line: number, + column: number, + opts?: { plugin?: CssSyntaxError['plugin'] } + ): CssSyntaxError + + error( + message: string, + offset: number, + opts?: { plugin?: CssSyntaxError['plugin'] } + ): CssSyntaxError + + /** + * Converts source offset to line and column. + * + * @param offset Source offset. + */ + fromOffset(offset: number): { col: number; line: number } | null + /** + * Reads the input source map and returns a symbol position + * in the input source (e.g., in a Sass file that was compiled + * to CSS before being passed to PostCSS). Optionally takes an + * end position, exclusive. + * + * ```js + * root.source.input.origin(1, 1) //=> { file: 'a.css', line: 3, column: 1 } + * root.source.input.origin(1, 1, 1, 4) + * //=> { file: 'a.css', line: 3, column: 1, endLine: 3, endColumn: 4 } + * ``` + * + * @param line Line for inclusive start position in input CSS. + * @param column Column for inclusive start position in input CSS. + * @param endLine Line for exclusive end position in input CSS. + * @param endColumn Column for exclusive end position in input CSS. + * + * @return Position in input source. + */ + origin( + line: number, + column: number, + endLine?: number, + endColumn?: number + ): false | Input.FilePosition + /** Converts this to a JSON-friendly object representation. */ + toJSON(): object + + /** + * The CSS source identifier. Contains `Input#file` if the user + * set the `from` option, or `Input#id` if they did not. + * + * ```js + * const root = postcss.parse(css, { from: 'a.css' }) + * root.source.input.from //=> "/home/ai/a.css" + * + * const root = postcss.parse(css) + * root.source.input.from //=> "" + * ``` + */ + get from(): string +} + +declare class Input extends Input_ {} + +export = Input diff --git a/node_modules/postcss/lib/input.js b/node_modules/postcss/lib/input.js new file mode 100644 index 0000000..685bce7 --- /dev/null +++ b/node_modules/postcss/lib/input.js @@ -0,0 +1,248 @@ +'use strict' + +let { nanoid } = require('nanoid/non-secure') +let { isAbsolute, resolve } = require('path') +let { SourceMapConsumer, SourceMapGenerator } = require('source-map-js') +let { fileURLToPath, pathToFileURL } = require('url') + +let CssSyntaxError = require('./css-syntax-error') +let PreviousMap = require('./previous-map') +let terminalHighlight = require('./terminal-highlight') + +let fromOffsetCache = Symbol('fromOffsetCache') + +let sourceMapAvailable = Boolean(SourceMapConsumer && SourceMapGenerator) +let pathAvailable = Boolean(resolve && isAbsolute) + +class Input { + constructor(css, opts = {}) { + if ( + css === null || + typeof css === 'undefined' || + (typeof css === 'object' && !css.toString) + ) { + throw new Error(`PostCSS received ${css} instead of CSS string`) + } + + this.css = css.toString() + + if (this.css[0] === '\uFEFF' || this.css[0] === '\uFFFE') { + this.hasBOM = true + this.css = this.css.slice(1) + } else { + this.hasBOM = false + } + + if (opts.from) { + if ( + !pathAvailable || + /^\w+:\/\//.test(opts.from) || + isAbsolute(opts.from) + ) { + this.file = opts.from + } else { + this.file = resolve(opts.from) + } + } + + if (pathAvailable && sourceMapAvailable) { + let map = new PreviousMap(this.css, opts) + if (map.text) { + this.map = map + let file = map.consumer().file + if (!this.file && file) this.file = this.mapResolve(file) + } + } + + if (!this.file) { + this.id = '' + } + if (this.map) this.map.file = this.from + } + + error(message, line, column, opts = {}) { + let endColumn, endLine, result + + if (line && typeof line === 'object') { + let start = line + let end = column + if (typeof start.offset === 'number') { + let pos = this.fromOffset(start.offset) + line = pos.line + column = pos.col + } else { + line = start.line + column = start.column + } + if (typeof end.offset === 'number') { + let pos = this.fromOffset(end.offset) + endLine = pos.line + endColumn = pos.col + } else { + endLine = end.line + endColumn = end.column + } + } else if (!column) { + let pos = this.fromOffset(line) + line = pos.line + column = pos.col + } + + let origin = this.origin(line, column, endLine, endColumn) + if (origin) { + result = new CssSyntaxError( + message, + origin.endLine === undefined + ? origin.line + : { column: origin.column, line: origin.line }, + origin.endLine === undefined + ? origin.column + : { column: origin.endColumn, line: origin.endLine }, + origin.source, + origin.file, + opts.plugin + ) + } else { + result = new CssSyntaxError( + message, + endLine === undefined ? line : { column, line }, + endLine === undefined ? column : { column: endColumn, line: endLine }, + this.css, + this.file, + opts.plugin + ) + } + + result.input = { column, endColumn, endLine, line, source: this.css } + if (this.file) { + if (pathToFileURL) { + result.input.url = pathToFileURL(this.file).toString() + } + result.input.file = this.file + } + + return result + } + + fromOffset(offset) { + let lastLine, lineToIndex + if (!this[fromOffsetCache]) { + let lines = this.css.split('\n') + lineToIndex = new Array(lines.length) + let prevIndex = 0 + + for (let i = 0, l = lines.length; i < l; i++) { + lineToIndex[i] = prevIndex + prevIndex += lines[i].length + 1 + } + + this[fromOffsetCache] = lineToIndex + } else { + lineToIndex = this[fromOffsetCache] + } + lastLine = lineToIndex[lineToIndex.length - 1] + + let min = 0 + if (offset >= lastLine) { + min = lineToIndex.length - 1 + } else { + let max = lineToIndex.length - 2 + let mid + while (min < max) { + mid = min + ((max - min) >> 1) + if (offset < lineToIndex[mid]) { + max = mid - 1 + } else if (offset >= lineToIndex[mid + 1]) { + min = mid + 1 + } else { + min = mid + break + } + } + } + return { + col: offset - lineToIndex[min] + 1, + line: min + 1 + } + } + + mapResolve(file) { + if (/^\w+:\/\//.test(file)) { + return file + } + return resolve(this.map.consumer().sourceRoot || this.map.root || '.', file) + } + + origin(line, column, endLine, endColumn) { + if (!this.map) return false + let consumer = this.map.consumer() + + let from = consumer.originalPositionFor({ column, line }) + if (!from.source) return false + + let to + if (typeof endLine === 'number') { + to = consumer.originalPositionFor({ column: endColumn, line: endLine }) + } + + let fromUrl + + if (isAbsolute(from.source)) { + fromUrl = pathToFileURL(from.source) + } else { + fromUrl = new URL( + from.source, + this.map.consumer().sourceRoot || pathToFileURL(this.map.mapFile) + ) + } + + let result = { + column: from.column, + endColumn: to && to.column, + endLine: to && to.line, + line: from.line, + url: fromUrl.toString() + } + + if (fromUrl.protocol === 'file:') { + if (fileURLToPath) { + result.file = fileURLToPath(fromUrl) + } else { + /* c8 ignore next 2 */ + throw new Error(`file: protocol is not available in this PostCSS build`) + } + } + + let source = consumer.sourceContentFor(from.source) + if (source) result.source = source + + return result + } + + toJSON() { + let json = {} + for (let name of ['hasBOM', 'css', 'file', 'id']) { + if (this[name] != null) { + json[name] = this[name] + } + } + if (this.map) { + json.map = { ...this.map } + if (json.map.consumerCache) { + json.map.consumerCache = undefined + } + } + return json + } + + get from() { + return this.file || this.id + } +} + +module.exports = Input +Input.default = Input + +if (terminalHighlight && terminalHighlight.registerInput) { + terminalHighlight.registerInput(Input) +} diff --git a/node_modules/postcss/lib/lazy-result.d.ts b/node_modules/postcss/lib/lazy-result.d.ts new file mode 100644 index 0000000..dd291aa --- /dev/null +++ b/node_modules/postcss/lib/lazy-result.d.ts @@ -0,0 +1,190 @@ +import Document from './document.js' +import { SourceMap } from './postcss.js' +import Processor from './processor.js' +import Result, { Message, ResultOptions } from './result.js' +import Root from './root.js' +import Warning from './warning.js' + +declare namespace LazyResult { + // eslint-disable-next-line @typescript-eslint/no-use-before-define + export { LazyResult_ as default } +} + +/** + * A Promise proxy for the result of PostCSS transformations. + * + * A `LazyResult` instance is returned by `Processor#process`. + * + * ```js + * const lazy = postcss([autoprefixer]).process(css) + * ``` + */ +declare class LazyResult_ + implements PromiseLike> +{ + /** + * Processes input CSS through synchronous and asynchronous plugins + * and calls onRejected for each error thrown in any plugin. + * + * It implements standard Promise API. + * + * ```js + * postcss([autoprefixer]).process(css).then(result => { + * console.log(result.css) + * }).catch(error => { + * console.error(error) + * }) + * ``` + */ + catch: Promise>['catch'] + + /** + * Processes input CSS through synchronous and asynchronous plugins + * and calls onFinally on any error or when all plugins will finish work. + * + * It implements standard Promise API. + * + * ```js + * postcss([autoprefixer]).process(css).finally(() => { + * console.log('processing ended') + * }) + * ``` + */ + finally: Promise>['finally'] + + /** + * Processes input CSS through synchronous and asynchronous plugins + * and calls `onFulfilled` with a Result instance. If a plugin throws + * an error, the `onRejected` callback will be executed. + * + * It implements standard Promise API. + * + * ```js + * postcss([autoprefixer]).process(css, { from: cssPath }).then(result => { + * console.log(result.css) + * }) + * ``` + */ + then: Promise>['then'] + + /** + * @param processor Processor used for this transformation. + * @param css CSS to parse and transform. + * @param opts Options from the `Processor#process` or `Root#toResult`. + */ + constructor(processor: Processor, css: string, opts: ResultOptions) + + /** + * Run plugin in async way and return `Result`. + * + * @return Result with output content. + */ + async(): Promise> + + /** + * Run plugin in sync way and return `Result`. + * + * @return Result with output content. + */ + sync(): Result + + /** + * Alias for the `LazyResult#css` property. + * + * ```js + * lazy + '' === lazy.css + * ``` + * + * @return Output CSS. + */ + toString(): string + + /** + * Processes input CSS through synchronous plugins + * and calls `Result#warnings`. + * + * @return Warnings from plugins. + */ + warnings(): Warning[] + + /** + * An alias for the `css` property. Use it with syntaxes + * that generate non-CSS output. + * + * This property will only work with synchronous plugins. + * If the processor contains any asynchronous plugins + * it will throw an error. + * + * PostCSS runners should always use `LazyResult#then`. + */ + get content(): string + + /** + * Processes input CSS through synchronous plugins, converts `Root` + * to a CSS string and returns `Result#css`. + * + * This property will only work with synchronous plugins. + * If the processor contains any asynchronous plugins + * it will throw an error. + * + * PostCSS runners should always use `LazyResult#then`. + */ + get css(): string + + /** + * Processes input CSS through synchronous plugins + * and returns `Result#map`. + * + * This property will only work with synchronous plugins. + * If the processor contains any asynchronous plugins + * it will throw an error. + * + * PostCSS runners should always use `LazyResult#then`. + */ + get map(): SourceMap + + /** + * Processes input CSS through synchronous plugins + * and returns `Result#messages`. + * + * This property will only work with synchronous plugins. If the processor + * contains any asynchronous plugins it will throw an error. + * + * PostCSS runners should always use `LazyResult#then`. + */ + get messages(): Message[] + + /** + * Options from the `Processor#process` call. + */ + get opts(): ResultOptions + + /** + * Returns a `Processor` instance, which will be used + * for CSS transformations. + */ + get processor(): Processor + + /** + * Processes input CSS through synchronous plugins + * and returns `Result#root`. + * + * This property will only work with synchronous plugins. If the processor + * contains any asynchronous plugins it will throw an error. + * + * PostCSS runners should always use `LazyResult#then`. + */ + get root(): RootNode + + /** + * Returns the default string description of an object. + * Required to implement the Promise interface. + */ + get [Symbol.toStringTag](): string +} + +declare class LazyResult< + RootNode = Document | Root +> extends LazyResult_ {} + +export = LazyResult diff --git a/node_modules/postcss/lib/lazy-result.js b/node_modules/postcss/lib/lazy-result.js new file mode 100644 index 0000000..e27701d --- /dev/null +++ b/node_modules/postcss/lib/lazy-result.js @@ -0,0 +1,550 @@ +'use strict' + +let Container = require('./container') +let Document = require('./document') +let MapGenerator = require('./map-generator') +let parse = require('./parse') +let Result = require('./result') +let Root = require('./root') +let stringify = require('./stringify') +let { isClean, my } = require('./symbols') +let warnOnce = require('./warn-once') + +const TYPE_TO_CLASS_NAME = { + atrule: 'AtRule', + comment: 'Comment', + decl: 'Declaration', + document: 'Document', + root: 'Root', + rule: 'Rule' +} + +const PLUGIN_PROPS = { + AtRule: true, + AtRuleExit: true, + Comment: true, + CommentExit: true, + Declaration: true, + DeclarationExit: true, + Document: true, + DocumentExit: true, + Once: true, + OnceExit: true, + postcssPlugin: true, + prepare: true, + Root: true, + RootExit: true, + Rule: true, + RuleExit: true +} + +const NOT_VISITORS = { + Once: true, + postcssPlugin: true, + prepare: true +} + +const CHILDREN = 0 + +function isPromise(obj) { + return typeof obj === 'object' && typeof obj.then === 'function' +} + +function getEvents(node) { + let key = false + let type = TYPE_TO_CLASS_NAME[node.type] + if (node.type === 'decl') { + key = node.prop.toLowerCase() + } else if (node.type === 'atrule') { + key = node.name.toLowerCase() + } + + if (key && node.append) { + return [ + type, + type + '-' + key, + CHILDREN, + type + 'Exit', + type + 'Exit-' + key + ] + } else if (key) { + return [type, type + '-' + key, type + 'Exit', type + 'Exit-' + key] + } else if (node.append) { + return [type, CHILDREN, type + 'Exit'] + } else { + return [type, type + 'Exit'] + } +} + +function toStack(node) { + let events + if (node.type === 'document') { + events = ['Document', CHILDREN, 'DocumentExit'] + } else if (node.type === 'root') { + events = ['Root', CHILDREN, 'RootExit'] + } else { + events = getEvents(node) + } + + return { + eventIndex: 0, + events, + iterator: 0, + node, + visitorIndex: 0, + visitors: [] + } +} + +function cleanMarks(node) { + node[isClean] = false + if (node.nodes) node.nodes.forEach(i => cleanMarks(i)) + return node +} + +let postcss = {} + +class LazyResult { + constructor(processor, css, opts) { + this.stringified = false + this.processed = false + + let root + if ( + typeof css === 'object' && + css !== null && + (css.type === 'root' || css.type === 'document') + ) { + root = cleanMarks(css) + } else if (css instanceof LazyResult || css instanceof Result) { + root = cleanMarks(css.root) + if (css.map) { + if (typeof opts.map === 'undefined') opts.map = {} + if (!opts.map.inline) opts.map.inline = false + opts.map.prev = css.map + } + } else { + let parser = parse + if (opts.syntax) parser = opts.syntax.parse + if (opts.parser) parser = opts.parser + if (parser.parse) parser = parser.parse + + try { + root = parser(css, opts) + } catch (error) { + this.processed = true + this.error = error + } + + if (root && !root[my]) { + /* c8 ignore next 2 */ + Container.rebuild(root) + } + } + + this.result = new Result(processor, root, opts) + this.helpers = { ...postcss, postcss, result: this.result } + this.plugins = this.processor.plugins.map(plugin => { + if (typeof plugin === 'object' && plugin.prepare) { + return { ...plugin, ...plugin.prepare(this.result) } + } else { + return plugin + } + }) + } + + async() { + if (this.error) return Promise.reject(this.error) + if (this.processed) return Promise.resolve(this.result) + if (!this.processing) { + this.processing = this.runAsync() + } + return this.processing + } + + catch(onRejected) { + return this.async().catch(onRejected) + } + + finally(onFinally) { + return this.async().then(onFinally, onFinally) + } + + getAsyncError() { + throw new Error('Use process(css).then(cb) to work with async plugins') + } + + handleError(error, node) { + let plugin = this.result.lastPlugin + try { + if (node) node.addToError(error) + this.error = error + if (error.name === 'CssSyntaxError' && !error.plugin) { + error.plugin = plugin.postcssPlugin + error.setMessage() + } else if (plugin.postcssVersion) { + if (process.env.NODE_ENV !== 'production') { + let pluginName = plugin.postcssPlugin + let pluginVer = plugin.postcssVersion + let runtimeVer = this.result.processor.version + let a = pluginVer.split('.') + let b = runtimeVer.split('.') + + if (a[0] !== b[0] || parseInt(a[1]) > parseInt(b[1])) { + // eslint-disable-next-line no-console + console.error( + 'Unknown error from PostCSS plugin. Your current PostCSS ' + + 'version is ' + + runtimeVer + + ', but ' + + pluginName + + ' uses ' + + pluginVer + + '. Perhaps this is the source of the error below.' + ) + } + } + } + } catch (err) { + /* c8 ignore next 3 */ + // eslint-disable-next-line no-console + if (console && console.error) console.error(err) + } + return error + } + + prepareVisitors() { + this.listeners = {} + let add = (plugin, type, cb) => { + if (!this.listeners[type]) this.listeners[type] = [] + this.listeners[type].push([plugin, cb]) + } + for (let plugin of this.plugins) { + if (typeof plugin === 'object') { + for (let event in plugin) { + if (!PLUGIN_PROPS[event] && /^[A-Z]/.test(event)) { + throw new Error( + `Unknown event ${event} in ${plugin.postcssPlugin}. ` + + `Try to update PostCSS (${this.processor.version} now).` + ) + } + if (!NOT_VISITORS[event]) { + if (typeof plugin[event] === 'object') { + for (let filter in plugin[event]) { + if (filter === '*') { + add(plugin, event, plugin[event][filter]) + } else { + add( + plugin, + event + '-' + filter.toLowerCase(), + plugin[event][filter] + ) + } + } + } else if (typeof plugin[event] === 'function') { + add(plugin, event, plugin[event]) + } + } + } + } + } + this.hasListener = Object.keys(this.listeners).length > 0 + } + + async runAsync() { + this.plugin = 0 + for (let i = 0; i < this.plugins.length; i++) { + let plugin = this.plugins[i] + let promise = this.runOnRoot(plugin) + if (isPromise(promise)) { + try { + await promise + } catch (error) { + throw this.handleError(error) + } + } + } + + this.prepareVisitors() + if (this.hasListener) { + let root = this.result.root + while (!root[isClean]) { + root[isClean] = true + let stack = [toStack(root)] + while (stack.length > 0) { + let promise = this.visitTick(stack) + if (isPromise(promise)) { + try { + await promise + } catch (e) { + let node = stack[stack.length - 1].node + throw this.handleError(e, node) + } + } + } + } + + if (this.listeners.OnceExit) { + for (let [plugin, visitor] of this.listeners.OnceExit) { + this.result.lastPlugin = plugin + try { + if (root.type === 'document') { + let roots = root.nodes.map(subRoot => + visitor(subRoot, this.helpers) + ) + + await Promise.all(roots) + } else { + await visitor(root, this.helpers) + } + } catch (e) { + throw this.handleError(e) + } + } + } + } + + this.processed = true + return this.stringify() + } + + runOnRoot(plugin) { + this.result.lastPlugin = plugin + try { + if (typeof plugin === 'object' && plugin.Once) { + if (this.result.root.type === 'document') { + let roots = this.result.root.nodes.map(root => + plugin.Once(root, this.helpers) + ) + + if (isPromise(roots[0])) { + return Promise.all(roots) + } + + return roots + } + + return plugin.Once(this.result.root, this.helpers) + } else if (typeof plugin === 'function') { + return plugin(this.result.root, this.result) + } + } catch (error) { + throw this.handleError(error) + } + } + + stringify() { + if (this.error) throw this.error + if (this.stringified) return this.result + this.stringified = true + + this.sync() + + let opts = this.result.opts + let str = stringify + if (opts.syntax) str = opts.syntax.stringify + if (opts.stringifier) str = opts.stringifier + if (str.stringify) str = str.stringify + + let map = new MapGenerator(str, this.result.root, this.result.opts) + let data = map.generate() + this.result.css = data[0] + this.result.map = data[1] + + return this.result + } + + sync() { + if (this.error) throw this.error + if (this.processed) return this.result + this.processed = true + + if (this.processing) { + throw this.getAsyncError() + } + + for (let plugin of this.plugins) { + let promise = this.runOnRoot(plugin) + if (isPromise(promise)) { + throw this.getAsyncError() + } + } + + this.prepareVisitors() + if (this.hasListener) { + let root = this.result.root + while (!root[isClean]) { + root[isClean] = true + this.walkSync(root) + } + if (this.listeners.OnceExit) { + if (root.type === 'document') { + for (let subRoot of root.nodes) { + this.visitSync(this.listeners.OnceExit, subRoot) + } + } else { + this.visitSync(this.listeners.OnceExit, root) + } + } + } + + return this.result + } + + then(onFulfilled, onRejected) { + if (process.env.NODE_ENV !== 'production') { + if (!('from' in this.opts)) { + warnOnce( + 'Without `from` option PostCSS could generate wrong source map ' + + 'and will not find Browserslist config. Set it to CSS file path ' + + 'or to `undefined` to prevent this warning.' + ) + } + } + return this.async().then(onFulfilled, onRejected) + } + + toString() { + return this.css + } + + visitSync(visitors, node) { + for (let [plugin, visitor] of visitors) { + this.result.lastPlugin = plugin + let promise + try { + promise = visitor(node, this.helpers) + } catch (e) { + throw this.handleError(e, node.proxyOf) + } + if (node.type !== 'root' && node.type !== 'document' && !node.parent) { + return true + } + if (isPromise(promise)) { + throw this.getAsyncError() + } + } + } + + visitTick(stack) { + let visit = stack[stack.length - 1] + let { node, visitors } = visit + + if (node.type !== 'root' && node.type !== 'document' && !node.parent) { + stack.pop() + return + } + + if (visitors.length > 0 && visit.visitorIndex < visitors.length) { + let [plugin, visitor] = visitors[visit.visitorIndex] + visit.visitorIndex += 1 + if (visit.visitorIndex === visitors.length) { + visit.visitors = [] + visit.visitorIndex = 0 + } + this.result.lastPlugin = plugin + try { + return visitor(node.toProxy(), this.helpers) + } catch (e) { + throw this.handleError(e, node) + } + } + + if (visit.iterator !== 0) { + let iterator = visit.iterator + let child + while ((child = node.nodes[node.indexes[iterator]])) { + node.indexes[iterator] += 1 + if (!child[isClean]) { + child[isClean] = true + stack.push(toStack(child)) + return + } + } + visit.iterator = 0 + delete node.indexes[iterator] + } + + let events = visit.events + while (visit.eventIndex < events.length) { + let event = events[visit.eventIndex] + visit.eventIndex += 1 + if (event === CHILDREN) { + if (node.nodes && node.nodes.length) { + node[isClean] = true + visit.iterator = node.getIterator() + } + return + } else if (this.listeners[event]) { + visit.visitors = this.listeners[event] + return + } + } + stack.pop() + } + + walkSync(node) { + node[isClean] = true + let events = getEvents(node) + for (let event of events) { + if (event === CHILDREN) { + if (node.nodes) { + node.each(child => { + if (!child[isClean]) this.walkSync(child) + }) + } + } else { + let visitors = this.listeners[event] + if (visitors) { + if (this.visitSync(visitors, node.toProxy())) return + } + } + } + } + + warnings() { + return this.sync().warnings() + } + + get content() { + return this.stringify().content + } + + get css() { + return this.stringify().css + } + + get map() { + return this.stringify().map + } + + get messages() { + return this.sync().messages + } + + get opts() { + return this.result.opts + } + + get processor() { + return this.result.processor + } + + get root() { + return this.sync().root + } + + get [Symbol.toStringTag]() { + return 'LazyResult' + } +} + +LazyResult.registerPostcss = dependant => { + postcss = dependant +} + +module.exports = LazyResult +LazyResult.default = LazyResult + +Root.registerLazyResult(LazyResult) +Document.registerLazyResult(LazyResult) diff --git a/node_modules/postcss/lib/list.d.ts b/node_modules/postcss/lib/list.d.ts new file mode 100644 index 0000000..e262ad3 --- /dev/null +++ b/node_modules/postcss/lib/list.d.ts @@ -0,0 +1,60 @@ +declare namespace list { + type List = { + /** + * Safely splits comma-separated values (such as those for `transition-*` + * and `background` properties). + * + * ```js + * Once (root, { list }) { + * list.comma('black, linear-gradient(white, black)') + * //=> ['black', 'linear-gradient(white, black)'] + * } + * ``` + * + * @param str Comma-separated values. + * @return Split values. + */ + comma(str: string): string[] + + default: List + + /** + * Safely splits space-separated values (such as those for `background`, + * `border-radius`, and other shorthand properties). + * + * ```js + * Once (root, { list }) { + * list.space('1px calc(10% + 1px)') //=> ['1px', 'calc(10% + 1px)'] + * } + * ``` + * + * @param str Space-separated values. + * @return Split values. + */ + space(str: string): string[] + + /** + * Safely splits values. + * + * ```js + * Once (root, { list }) { + * list.split('1px calc(10% + 1px)', [' ', '\n', '\t']) //=> ['1px', 'calc(10% + 1px)'] + * } + * ``` + * + * @param string separated values. + * @param separators array of separators. + * @param last boolean indicator. + * @return Split values. + */ + split( + string: string, + separators: readonly string[], + last: boolean + ): string[] + } +} + +declare const list: list.List + +export = list diff --git a/node_modules/postcss/lib/list.js b/node_modules/postcss/lib/list.js new file mode 100644 index 0000000..1b31f98 --- /dev/null +++ b/node_modules/postcss/lib/list.js @@ -0,0 +1,58 @@ +'use strict' + +let list = { + comma(string) { + return list.split(string, [','], true) + }, + + space(string) { + let spaces = [' ', '\n', '\t'] + return list.split(string, spaces) + }, + + split(string, separators, last) { + let array = [] + let current = '' + let split = false + + let func = 0 + let inQuote = false + let prevQuote = '' + let escape = false + + for (let letter of string) { + if (escape) { + escape = false + } else if (letter === '\\') { + escape = true + } else if (inQuote) { + if (letter === prevQuote) { + inQuote = false + } + } else if (letter === '"' || letter === "'") { + inQuote = true + prevQuote = letter + } else if (letter === '(') { + func += 1 + } else if (letter === ')') { + if (func > 0) func -= 1 + } else if (func === 0) { + if (separators.includes(letter)) split = true + } + + if (split) { + if (current !== '') array.push(current.trim()) + current = '' + split = false + } else { + current += letter + } + } + + if (last || current !== '') array.push(current.trim()) + return array + } +} + +module.exports = list +list.default = list diff --git a/node_modules/postcss/lib/map-generator.js b/node_modules/postcss/lib/map-generator.js new file mode 100644 index 0000000..89069d3 --- /dev/null +++ b/node_modules/postcss/lib/map-generator.js @@ -0,0 +1,368 @@ +'use strict' + +let { dirname, relative, resolve, sep } = require('path') +let { SourceMapConsumer, SourceMapGenerator } = require('source-map-js') +let { pathToFileURL } = require('url') + +let Input = require('./input') + +let sourceMapAvailable = Boolean(SourceMapConsumer && SourceMapGenerator) +let pathAvailable = Boolean(dirname && resolve && relative && sep) + +class MapGenerator { + constructor(stringify, root, opts, cssString) { + this.stringify = stringify + this.mapOpts = opts.map || {} + this.root = root + this.opts = opts + this.css = cssString + this.originalCSS = cssString + this.usesFileUrls = !this.mapOpts.from && this.mapOpts.absolute + + this.memoizedFileURLs = new Map() + this.memoizedPaths = new Map() + this.memoizedURLs = new Map() + } + + addAnnotation() { + let content + + if (this.isInline()) { + content = + 'data:application/json;base64,' + this.toBase64(this.map.toString()) + } else if (typeof this.mapOpts.annotation === 'string') { + content = this.mapOpts.annotation + } else if (typeof this.mapOpts.annotation === 'function') { + content = this.mapOpts.annotation(this.opts.to, this.root) + } else { + content = this.outputFile() + '.map' + } + let eol = '\n' + if (this.css.includes('\r\n')) eol = '\r\n' + + this.css += eol + '/*# sourceMappingURL=' + content + ' */' + } + + applyPrevMaps() { + for (let prev of this.previous()) { + let from = this.toUrl(this.path(prev.file)) + let root = prev.root || dirname(prev.file) + let map + + if (this.mapOpts.sourcesContent === false) { + map = new SourceMapConsumer(prev.text) + if (map.sourcesContent) { + map.sourcesContent = null + } + } else { + map = prev.consumer() + } + + this.map.applySourceMap(map, from, this.toUrl(this.path(root))) + } + } + + clearAnnotation() { + if (this.mapOpts.annotation === false) return + + if (this.root) { + let node + for (let i = this.root.nodes.length - 1; i >= 0; i--) { + node = this.root.nodes[i] + if (node.type !== 'comment') continue + if (node.text.startsWith('# sourceMappingURL=')) { + this.root.removeChild(i) + } + } + } else if (this.css) { + this.css = this.css.replace(/\n*\/\*#[\S\s]*?\*\/$/gm, '') + } + } + + generate() { + this.clearAnnotation() + if (pathAvailable && sourceMapAvailable && this.isMap()) { + return this.generateMap() + } else { + let result = '' + this.stringify(this.root, i => { + result += i + }) + return [result] + } + } + + generateMap() { + if (this.root) { + this.generateString() + } else if (this.previous().length === 1) { + let prev = this.previous()[0].consumer() + prev.file = this.outputFile() + this.map = SourceMapGenerator.fromSourceMap(prev, { + ignoreInvalidMapping: true + }) + } else { + this.map = new SourceMapGenerator({ + file: this.outputFile(), + ignoreInvalidMapping: true + }) + this.map.addMapping({ + generated: { column: 0, line: 1 }, + original: { column: 0, line: 1 }, + source: this.opts.from + ? this.toUrl(this.path(this.opts.from)) + : '' + }) + } + + if (this.isSourcesContent()) this.setSourcesContent() + if (this.root && this.previous().length > 0) this.applyPrevMaps() + if (this.isAnnotation()) this.addAnnotation() + + if (this.isInline()) { + return [this.css] + } else { + return [this.css, this.map] + } + } + + generateString() { + this.css = '' + this.map = new SourceMapGenerator({ + file: this.outputFile(), + ignoreInvalidMapping: true + }) + + let line = 1 + let column = 1 + + let noSource = '' + let mapping = { + generated: { column: 0, line: 0 }, + original: { column: 0, line: 0 }, + source: '' + } + + let last, lines + this.stringify(this.root, (str, node, type) => { + this.css += str + + if (node && type !== 'end') { + mapping.generated.line = line + mapping.generated.column = column - 1 + if (node.source && node.source.start) { + mapping.source = this.sourcePath(node) + mapping.original.line = node.source.start.line + mapping.original.column = node.source.start.column - 1 + this.map.addMapping(mapping) + } else { + mapping.source = noSource + mapping.original.line = 1 + mapping.original.column = 0 + this.map.addMapping(mapping) + } + } + + lines = str.match(/\n/g) + if (lines) { + line += lines.length + last = str.lastIndexOf('\n') + column = str.length - last + } else { + column += str.length + } + + if (node && type !== 'start') { + let p = node.parent || { raws: {} } + let childless = + node.type === 'decl' || (node.type === 'atrule' && !node.nodes) + if (!childless || node !== p.last || p.raws.semicolon) { + if (node.source && node.source.end) { + mapping.source = this.sourcePath(node) + mapping.original.line = node.source.end.line + mapping.original.column = node.source.end.column - 1 + mapping.generated.line = line + mapping.generated.column = column - 2 + this.map.addMapping(mapping) + } else { + mapping.source = noSource + mapping.original.line = 1 + mapping.original.column = 0 + mapping.generated.line = line + mapping.generated.column = column - 1 + this.map.addMapping(mapping) + } + } + } + }) + } + + isAnnotation() { + if (this.isInline()) { + return true + } + if (typeof this.mapOpts.annotation !== 'undefined') { + return this.mapOpts.annotation + } + if (this.previous().length) { + return this.previous().some(i => i.annotation) + } + return true + } + + isInline() { + if (typeof this.mapOpts.inline !== 'undefined') { + return this.mapOpts.inline + } + + let annotation = this.mapOpts.annotation + if (typeof annotation !== 'undefined' && annotation !== true) { + return false + } + + if (this.previous().length) { + return this.previous().some(i => i.inline) + } + return true + } + + isMap() { + if (typeof this.opts.map !== 'undefined') { + return !!this.opts.map + } + return this.previous().length > 0 + } + + isSourcesContent() { + if (typeof this.mapOpts.sourcesContent !== 'undefined') { + return this.mapOpts.sourcesContent + } + if (this.previous().length) { + return this.previous().some(i => i.withContent()) + } + return true + } + + outputFile() { + if (this.opts.to) { + return this.path(this.opts.to) + } else if (this.opts.from) { + return this.path(this.opts.from) + } else { + return 'to.css' + } + } + + path(file) { + if (this.mapOpts.absolute) return file + if (file.charCodeAt(0) === 60 /* `<` */) return file + if (/^\w+:\/\//.test(file)) return file + let cached = this.memoizedPaths.get(file) + if (cached) return cached + + let from = this.opts.to ? dirname(this.opts.to) : '.' + + if (typeof this.mapOpts.annotation === 'string') { + from = dirname(resolve(from, this.mapOpts.annotation)) + } + + let path = relative(from, file) + this.memoizedPaths.set(file, path) + + return path + } + + previous() { + if (!this.previousMaps) { + this.previousMaps = [] + if (this.root) { + this.root.walk(node => { + if (node.source && node.source.input.map) { + let map = node.source.input.map + if (!this.previousMaps.includes(map)) { + this.previousMaps.push(map) + } + } + }) + } else { + let input = new Input(this.originalCSS, this.opts) + if (input.map) this.previousMaps.push(input.map) + } + } + + return this.previousMaps + } + + setSourcesContent() { + let already = {} + if (this.root) { + this.root.walk(node => { + if (node.source) { + let from = node.source.input.from + if (from && !already[from]) { + already[from] = true + let fromUrl = this.usesFileUrls + ? this.toFileUrl(from) + : this.toUrl(this.path(from)) + this.map.setSourceContent(fromUrl, node.source.input.css) + } + } + }) + } else if (this.css) { + let from = this.opts.from + ? this.toUrl(this.path(this.opts.from)) + : '' + this.map.setSourceContent(from, this.css) + } + } + + sourcePath(node) { + if (this.mapOpts.from) { + return this.toUrl(this.mapOpts.from) + } else if (this.usesFileUrls) { + return this.toFileUrl(node.source.input.from) + } else { + return this.toUrl(this.path(node.source.input.from)) + } + } + + toBase64(str) { + if (Buffer) { + return Buffer.from(str).toString('base64') + } else { + return window.btoa(unescape(encodeURIComponent(str))) + } + } + + toFileUrl(path) { + let cached = this.memoizedFileURLs.get(path) + if (cached) return cached + + if (pathToFileURL) { + let fileURL = pathToFileURL(path).toString() + this.memoizedFileURLs.set(path, fileURL) + + return fileURL + } else { + throw new Error( + '`map.absolute` option is not available in this PostCSS build' + ) + } + } + + toUrl(path) { + let cached = this.memoizedURLs.get(path) + if (cached) return cached + + if (sep === '\\') { + path = path.replace(/\\/g, '/') + } + + let url = encodeURI(path).replace(/[#?]/g, encodeURIComponent) + this.memoizedURLs.set(path, url) + + return url + } +} + +module.exports = MapGenerator diff --git a/node_modules/postcss/lib/no-work-result.d.ts b/node_modules/postcss/lib/no-work-result.d.ts new file mode 100644 index 0000000..8039076 --- /dev/null +++ b/node_modules/postcss/lib/no-work-result.d.ts @@ -0,0 +1,46 @@ +import LazyResult from './lazy-result.js' +import { SourceMap } from './postcss.js' +import Processor from './processor.js' +import Result, { Message, ResultOptions } from './result.js' +import Root from './root.js' +import Warning from './warning.js' + +declare namespace NoWorkResult { + // eslint-disable-next-line @typescript-eslint/no-use-before-define + export { NoWorkResult_ as default } +} + +/** + * A Promise proxy for the result of PostCSS transformations. + * This lazy result instance doesn't parse css unless `NoWorkResult#root` or `Result#root` + * are accessed. See the example below for details. + * A `NoWork` instance is returned by `Processor#process` ONLY when no plugins defined. + * + * ```js + * const noWorkResult = postcss().process(css) // No plugins are defined. + * // CSS is not parsed + * let root = noWorkResult.root // now css is parsed because we accessed the root + * ``` + */ +declare class NoWorkResult_ implements LazyResult { + catch: Promise>['catch'] + finally: Promise>['finally'] + then: Promise>['then'] + constructor(processor: Processor, css: string, opts: ResultOptions) + async(): Promise> + sync(): Result + toString(): string + warnings(): Warning[] + get content(): string + get css(): string + get map(): SourceMap + get messages(): Message[] + get opts(): ResultOptions + get processor(): Processor + get root(): Root + get [Symbol.toStringTag](): string +} + +declare class NoWorkResult extends NoWorkResult_ {} + +export = NoWorkResult diff --git a/node_modules/postcss/lib/no-work-result.js b/node_modules/postcss/lib/no-work-result.js new file mode 100644 index 0000000..a84d843 --- /dev/null +++ b/node_modules/postcss/lib/no-work-result.js @@ -0,0 +1,138 @@ +'use strict' + +let MapGenerator = require('./map-generator') +let parse = require('./parse') +const Result = require('./result') +let stringify = require('./stringify') +let warnOnce = require('./warn-once') + +class NoWorkResult { + constructor(processor, css, opts) { + css = css.toString() + this.stringified = false + + this._processor = processor + this._css = css + this._opts = opts + this._map = undefined + let root + + let str = stringify + this.result = new Result(this._processor, root, this._opts) + this.result.css = css + + let self = this + Object.defineProperty(this.result, 'root', { + get() { + return self.root + } + }) + + let map = new MapGenerator(str, root, this._opts, css) + if (map.isMap()) { + let [generatedCSS, generatedMap] = map.generate() + if (generatedCSS) { + this.result.css = generatedCSS + } + if (generatedMap) { + this.result.map = generatedMap + } + } else { + map.clearAnnotation() + this.result.css = map.css + } + } + + async() { + if (this.error) return Promise.reject(this.error) + return Promise.resolve(this.result) + } + + catch(onRejected) { + return this.async().catch(onRejected) + } + + finally(onFinally) { + return this.async().then(onFinally, onFinally) + } + + sync() { + if (this.error) throw this.error + return this.result + } + + then(onFulfilled, onRejected) { + if (process.env.NODE_ENV !== 'production') { + if (!('from' in this._opts)) { + warnOnce( + 'Without `from` option PostCSS could generate wrong source map ' + + 'and will not find Browserslist config. Set it to CSS file path ' + + 'or to `undefined` to prevent this warning.' + ) + } + } + + return this.async().then(onFulfilled, onRejected) + } + + toString() { + return this._css + } + + warnings() { + return [] + } + + get content() { + return this.result.css + } + + get css() { + return this.result.css + } + + get map() { + return this.result.map + } + + get messages() { + return [] + } + + get opts() { + return this.result.opts + } + + get processor() { + return this.result.processor + } + + get root() { + if (this._root) { + return this._root + } + + let root + let parser = parse + + try { + root = parser(this._css, this._opts) + } catch (error) { + this.error = error + } + + if (this.error) { + throw this.error + } else { + this._root = root + return root + } + } + + get [Symbol.toStringTag]() { + return 'NoWorkResult' + } +} + +module.exports = NoWorkResult +NoWorkResult.default = NoWorkResult diff --git a/node_modules/postcss/lib/node.d.ts b/node_modules/postcss/lib/node.d.ts new file mode 100644 index 0000000..3597670 --- /dev/null +++ b/node_modules/postcss/lib/node.d.ts @@ -0,0 +1,541 @@ +import AtRule = require('./at-rule.js') + +import { AtRuleProps } from './at-rule.js' +import Comment, { CommentProps } from './comment.js' +import Container, { NewChild } from './container.js' +import CssSyntaxError from './css-syntax-error.js' +import Declaration, { DeclarationProps } from './declaration.js' +import Document from './document.js' +import Input from './input.js' +import { Stringifier, Syntax } from './postcss.js' +import Result from './result.js' +import Root from './root.js' +import Rule, { RuleProps } from './rule.js' +import Warning, { WarningOptions } from './warning.js' + +declare namespace Node { + export type ChildNode = AtRule.default | Comment | Declaration | Rule + + export type AnyNode = + | AtRule.default + | Comment + | Declaration + | Document + | Root + | Rule + + export type ChildProps = + | AtRuleProps + | CommentProps + | DeclarationProps + | RuleProps + + export interface Position { + /** + * Source line in file. In contrast to `offset` it starts from 1. + */ + column: number + + /** + * Source column in file. + */ + line: number + + /** + * Source offset in file. It starts from 0. + */ + offset: number + } + + export interface Range { + /** + * End position, exclusive. + */ + end: Position + + /** + * Start position, inclusive. + */ + start: Position + } + + /** + * Source represents an interface for the {@link Node.source} property. + */ + export interface Source { + /** + * The inclusive ending position for the source + * code of a node. + */ + end?: Position + + /** + * The source file from where a node has originated. + */ + input: Input + + /** + * The inclusive starting position for the source + * code of a node. + */ + start?: Position + } + + /** + * Interface represents an interface for an object received + * as parameter by Node class constructor. + */ + export interface NodeProps { + source?: Source + } + + export interface NodeErrorOptions { + /** + * An ending index inside a node's string that should be highlighted as + * source of error. + */ + endIndex?: number + /** + * An index inside a node's string that should be highlighted as source + * of error. + */ + index?: number + /** + * Plugin name that created this error. PostCSS will set it automatically. + */ + plugin?: string + /** + * A word inside a node's string, that should be highlighted as source + * of error. + */ + word?: string + } + + // eslint-disable-next-line @typescript-eslint/no-shadow + class Node extends Node_ {} + export { Node as default } +} + +/** + * It represents an abstract class that handles common + * methods for other CSS abstract syntax tree nodes. + * + * Any node that represents CSS selector or value should + * not extend the `Node` class. + */ +declare abstract class Node_ { + /** + * It represents parent of the current node. + * + * ```js + * root.nodes[0].parent === root //=> true + * ``` + */ + parent: Container | Document | undefined + + /** + * It represents unnecessary whitespace and characters present + * in the css source code. + * + * Information to generate byte-to-byte equal node string as it was + * in the origin input. + * + * The properties of the raws object are decided by parser, + * the default parser uses the following properties: + * + * * `before`: the space symbols before the node. It also stores `*` + * and `_` symbols before the declaration (IE hack). + * * `after`: the space symbols after the last child of the node + * to the end of the node. + * * `between`: the symbols between the property and value + * for declarations, selector and `{` for rules, or last parameter + * and `{` for at-rules. + * * `semicolon`: contains true if the last child has + * an (optional) semicolon. + * * `afterName`: the space between the at-rule name and its parameters. + * * `left`: the space symbols between `/*` and the comment’s text. + * * `right`: the space symbols between the comment’s text + * and */. + * - `important`: the content of the important statement, + * if it is not just `!important`. + * + * PostCSS filters out the comments inside selectors, declaration values + * and at-rule parameters but it stores the origin content in raws. + * + * ```js + * const root = postcss.parse('a {\n color:black\n}') + * root.first.first.raws //=> { before: '\n ', between: ':' } + * ``` + */ + raws: any + + /** + * It represents information related to origin of a node and is required + * for generating source maps. + * + * The nodes that are created manually using the public APIs + * provided by PostCSS will have `source` undefined and + * will be absent in the source map. + * + * For this reason, the plugin developer should consider + * duplicating nodes as the duplicate node will have the + * same source as the original node by default or assign + * source to a node created manually. + * + * ```js + * decl.source.input.from //=> '/home/ai/source.css' + * decl.source.start //=> { line: 10, column: 2 } + * decl.source.end //=> { line: 10, column: 12 } + * ``` + * + * ```js + * // Incorrect method, source not specified! + * const prefixed = postcss.decl({ + * prop: '-moz-' + decl.prop, + * value: decl.value + * }) + * + * // Correct method, source is inherited when duplicating. + * const prefixed = decl.clone({ + * prop: '-moz-' + decl.prop + * }) + * ``` + * + * ```js + * if (atrule.name === 'add-link') { + * const rule = postcss.rule({ + * selector: 'a', + * source: atrule.source + * }) + * + * atrule.parent.insertBefore(atrule, rule) + * } + * ``` + */ + source?: Node.Source + + /** + * It represents type of a node in + * an abstract syntax tree. + * + * A type of node helps in identification of a node + * and perform operation based on it's type. + * + * ```js + * const declaration = new Declaration({ + * prop: 'color', + * value: 'black' + * }) + * + * declaration.type //=> 'decl' + * ``` + */ + type: string + + constructor(defaults?: object) + + /** + * If this node isn't already dirty, marks it and its ancestors as such. This + * indicates to the LazyResult processor that the {@link Root} has been + * modified by the current plugin and may need to be processed again by other + * plugins. + */ + protected markDirty(): void + + /** + * Insert new node after current node to current node’s parent. + * + * Just alias for `node.parent.insertAfter(node, add)`. + * + * ```js + * decl.after('color: black') + * ``` + * + * @param newNode New node. + * @return This node for methods chain. + */ + after( + newNode: Node | Node.ChildProps | readonly Node[] | string | undefined + ): this + + /** + * It assigns properties to an existing node instance. + * + * ```js + * decl.assign({ prop: 'word-wrap', value: 'break-word' }) + * ``` + * + * @param overrides New properties to override the node. + * + * @return `this` for method chaining. + */ + assign(overrides: object): this + + /** + * Insert new node before current node to current node’s parent. + * + * Just alias for `node.parent.insertBefore(node, add)`. + * + * ```js + * decl.before('content: ""') + * ``` + * + * @param newNode New node. + * @return This node for methods chain. + */ + before( + newNode: Node | Node.ChildProps | readonly Node[] | string | undefined + ): this + + /** + * Clear the code style properties for the node and its children. + * + * ```js + * node.raws.before //=> ' ' + * node.cleanRaws() + * node.raws.before //=> undefined + * ``` + * + * @param keepBetween Keep the `raws.between` symbols. + */ + cleanRaws(keepBetween?: boolean): void + + /** + * It creates clone of an existing node, which includes all the properties + * and their values, that includes `raws` but not `type`. + * + * ```js + * decl.raws.before //=> "\n " + * const cloned = decl.clone({ prop: '-moz-' + decl.prop }) + * cloned.raws.before //=> "\n " + * cloned.toString() //=> -moz-transform: scale(0) + * ``` + * + * @param overrides New properties to override in the clone. + * + * @return Duplicate of the node instance. + */ + clone(overrides?: object): this + + /** + * Shortcut to clone the node and insert the resulting cloned node + * after the current node. + * + * @param overrides New properties to override in the clone. + * @return New node. + */ + cloneAfter(overrides?: object): this + + /** + * Shortcut to clone the node and insert the resulting cloned node + * before the current node. + * + * ```js + * decl.cloneBefore({ prop: '-moz-' + decl.prop }) + * ``` + * + * @param overrides Mew properties to override in the clone. + * + * @return New node + */ + cloneBefore(overrides?: object): this + + /** + * It creates an instance of the class `CssSyntaxError` and parameters passed + * to this method are assigned to the error instance. + * + * The error instance will have description for the + * error, original position of the node in the + * source, showing line and column number. + * + * If any previous map is present, it would be used + * to get original position of the source. + * + * The Previous Map here is referred to the source map + * generated by previous compilation, example: Less, + * Stylus and Sass. + * + * This method returns the error instance instead of + * throwing it. + * + * ```js + * if (!variables[name]) { + * throw decl.error(`Unknown variable ${name}`, { word: name }) + * // CssSyntaxError: postcss-vars:a.sass:4:3: Unknown variable $black + * // color: $black + * // a + * // ^ + * // background: white + * } + * ``` + * + * @param message Description for the error instance. + * @param options Options for the error instance. + * + * @return Error instance is returned. + */ + error(message: string, options?: Node.NodeErrorOptions): CssSyntaxError + + /** + * Returns the next child of the node’s parent. + * Returns `undefined` if the current node is the last child. + * + * ```js + * if (comment.text === 'delete next') { + * const next = comment.next() + * if (next) { + * next.remove() + * } + * } + * ``` + * + * @return Next node. + */ + next(): Node.ChildNode | undefined + + /** + * Get the position for a word or an index inside the node. + * + * @param opts Options. + * @return Position. + */ + positionBy(opts?: Pick): Node.Position + + /** + * Convert string index to line/column. + * + * @param index The symbol number in the node’s string. + * @return Symbol position in file. + */ + positionInside(index: number): Node.Position + + /** + * Returns the previous child of the node’s parent. + * Returns `undefined` if the current node is the first child. + * + * ```js + * const annotation = decl.prev() + * if (annotation.type === 'comment') { + * readAnnotation(annotation.text) + * } + * ``` + * + * @return Previous node. + */ + prev(): Node.ChildNode | undefined + + /** + * Get the range for a word or start and end index inside the node. + * The start index is inclusive; the end index is exclusive. + * + * @param opts Options. + * @return Range. + */ + rangeBy( + opts?: Pick + ): Node.Range + + /** + * Returns a `raws` value. If the node is missing + * the code style property (because the node was manually built or cloned), + * PostCSS will try to autodetect the code style property by looking + * at other nodes in the tree. + * + * ```js + * const root = postcss.parse('a { background: white }') + * root.nodes[0].append({ prop: 'color', value: 'black' }) + * root.nodes[0].nodes[1].raws.before //=> undefined + * root.nodes[0].nodes[1].raw('before') //=> ' ' + * ``` + * + * @param prop Name of code style property. + * @param defaultType Name of default value, it can be missed + * if the value is the same as prop. + * @return {string} Code style value. + */ + raw(prop: string, defaultType?: string): string + + /** + * It removes the node from its parent and deletes its parent property. + * + * ```js + * if (decl.prop.match(/^-webkit-/)) { + * decl.remove() + * } + * ``` + * + * @return `this` for method chaining. + */ + remove(): this + + /** + * Inserts node(s) before the current node and removes the current node. + * + * ```js + * AtRule: { + * mixin: atrule => { + * atrule.replaceWith(mixinRules[atrule.params]) + * } + * } + * ``` + * + * @param nodes Mode(s) to replace current one. + * @return Current node to methods chain. + */ + replaceWith(...nodes: NewChild[]): this + + /** + * Finds the Root instance of the node’s tree. + * + * ```js + * root.nodes[0].nodes[0].root() === root + * ``` + * + * @return Root parent. + */ + root(): Root + + /** + * Fix circular links on `JSON.stringify()`. + * + * @return Cleaned object. + */ + toJSON(): object + + /** + * It compiles the node to browser readable cascading style sheets string + * depending on it's type. + * + * ```js + * new Rule({ selector: 'a' }).toString() //=> "a {}" + * ``` + * + * @param stringifier A syntax to use in string generation. + * @return CSS string of this node. + */ + toString(stringifier?: Stringifier | Syntax): string + + /** + * It is a wrapper for {@link Result#warn}, providing convenient + * way of generating warnings. + * + * ```js + * Declaration: { + * bad: (decl, { result }) => { + * decl.warn(result, 'Deprecated property: bad') + * } + * } + * ``` + * + * @param result The `Result` instance that will receive the warning. + * @param message Description for the warning. + * @param options Options for the warning. + * + * @return `Warning` instance is returned + */ + warn(result: Result, message: string, options?: WarningOptions): Warning +} + +declare class Node extends Node_ {} + +export = Node diff --git a/node_modules/postcss/lib/node.js b/node_modules/postcss/lib/node.js new file mode 100644 index 0000000..88f382a --- /dev/null +++ b/node_modules/postcss/lib/node.js @@ -0,0 +1,389 @@ +'use strict' + +let CssSyntaxError = require('./css-syntax-error') +let Stringifier = require('./stringifier') +let stringify = require('./stringify') +let { isClean, my } = require('./symbols') + +function cloneNode(obj, parent) { + let cloned = new obj.constructor() + + for (let i in obj) { + if (!Object.prototype.hasOwnProperty.call(obj, i)) { + /* c8 ignore next 2 */ + continue + } + if (i === 'proxyCache') continue + let value = obj[i] + let type = typeof value + + if (i === 'parent' && type === 'object') { + if (parent) cloned[i] = parent + } else if (i === 'source') { + cloned[i] = value + } else if (Array.isArray(value)) { + cloned[i] = value.map(j => cloneNode(j, cloned)) + } else { + if (type === 'object' && value !== null) value = cloneNode(value) + cloned[i] = value + } + } + + return cloned +} + +class Node { + constructor(defaults = {}) { + this.raws = {} + this[isClean] = false + this[my] = true + + for (let name in defaults) { + if (name === 'nodes') { + this.nodes = [] + for (let node of defaults[name]) { + if (typeof node.clone === 'function') { + this.append(node.clone()) + } else { + this.append(node) + } + } + } else { + this[name] = defaults[name] + } + } + } + + addToError(error) { + error.postcssNode = this + if (error.stack && this.source && /\n\s{4}at /.test(error.stack)) { + let s = this.source + error.stack = error.stack.replace( + /\n\s{4}at /, + `$&${s.input.from}:${s.start.line}:${s.start.column}$&` + ) + } + return error + } + + after(add) { + this.parent.insertAfter(this, add) + return this + } + + assign(overrides = {}) { + for (let name in overrides) { + this[name] = overrides[name] + } + return this + } + + before(add) { + this.parent.insertBefore(this, add) + return this + } + + cleanRaws(keepBetween) { + delete this.raws.before + delete this.raws.after + if (!keepBetween) delete this.raws.between + } + + clone(overrides = {}) { + let cloned = cloneNode(this) + for (let name in overrides) { + cloned[name] = overrides[name] + } + return cloned + } + + cloneAfter(overrides = {}) { + let cloned = this.clone(overrides) + this.parent.insertAfter(this, cloned) + return cloned + } + + cloneBefore(overrides = {}) { + let cloned = this.clone(overrides) + this.parent.insertBefore(this, cloned) + return cloned + } + + error(message, opts = {}) { + if (this.source) { + let { end, start } = this.rangeBy(opts) + return this.source.input.error( + message, + { column: start.column, line: start.line }, + { column: end.column, line: end.line }, + opts + ) + } + return new CssSyntaxError(message) + } + + getProxyProcessor() { + return { + get(node, prop) { + if (prop === 'proxyOf') { + return node + } else if (prop === 'root') { + return () => node.root().toProxy() + } else { + return node[prop] + } + }, + + set(node, prop, value) { + if (node[prop] === value) return true + node[prop] = value + if ( + prop === 'prop' || + prop === 'value' || + prop === 'name' || + prop === 'params' || + prop === 'important' || + /* c8 ignore next */ + prop === 'text' + ) { + node.markDirty() + } + return true + } + } + } + + /* c8 ignore next 3 */ + markClean() { + this[isClean] = true + } + + markDirty() { + if (this[isClean]) { + this[isClean] = false + let next = this + while ((next = next.parent)) { + next[isClean] = false + } + } + } + + next() { + if (!this.parent) return undefined + let index = this.parent.index(this) + return this.parent.nodes[index + 1] + } + + positionBy(opts, stringRepresentation) { + let pos = this.source.start + if (opts.index) { + pos = this.positionInside(opts.index, stringRepresentation) + } else if (opts.word) { + stringRepresentation = this.toString() + let index = stringRepresentation.indexOf(opts.word) + if (index !== -1) pos = this.positionInside(index, stringRepresentation) + } + return pos + } + + positionInside(index, stringRepresentation) { + let string = stringRepresentation || this.toString() + let column = this.source.start.column + let line = this.source.start.line + + for (let i = 0; i < index; i++) { + if (string[i] === '\n') { + column = 1 + line += 1 + } else { + column += 1 + } + } + + return { column, line } + } + + prev() { + if (!this.parent) return undefined + let index = this.parent.index(this) + return this.parent.nodes[index - 1] + } + + rangeBy(opts) { + let start = { + column: this.source.start.column, + line: this.source.start.line + } + let end = this.source.end + ? { + column: this.source.end.column + 1, + line: this.source.end.line + } + : { + column: start.column + 1, + line: start.line + } + + if (opts.word) { + let stringRepresentation = this.toString() + let index = stringRepresentation.indexOf(opts.word) + if (index !== -1) { + start = this.positionInside(index, stringRepresentation) + end = this.positionInside( + index + opts.word.length, + stringRepresentation + ) + } + } else { + if (opts.start) { + start = { + column: opts.start.column, + line: opts.start.line + } + } else if (opts.index) { + start = this.positionInside(opts.index) + } + + if (opts.end) { + end = { + column: opts.end.column, + line: opts.end.line + } + } else if (typeof opts.endIndex === 'number') { + end = this.positionInside(opts.endIndex) + } else if (opts.index) { + end = this.positionInside(opts.index + 1) + } + } + + if ( + end.line < start.line || + (end.line === start.line && end.column <= start.column) + ) { + end = { column: start.column + 1, line: start.line } + } + + return { end, start } + } + + raw(prop, defaultType) { + let str = new Stringifier() + return str.raw(this, prop, defaultType) + } + + remove() { + if (this.parent) { + this.parent.removeChild(this) + } + this.parent = undefined + return this + } + + replaceWith(...nodes) { + if (this.parent) { + let bookmark = this + let foundSelf = false + for (let node of nodes) { + if (node === this) { + foundSelf = true + } else if (foundSelf) { + this.parent.insertAfter(bookmark, node) + bookmark = node + } else { + this.parent.insertBefore(bookmark, node) + } + } + + if (!foundSelf) { + this.remove() + } + } + + return this + } + + root() { + let result = this + while (result.parent && result.parent.type !== 'document') { + result = result.parent + } + return result + } + + toJSON(_, inputs) { + let fixed = {} + let emitInputs = inputs == null + inputs = inputs || new Map() + let inputsNextIndex = 0 + + for (let name in this) { + if (!Object.prototype.hasOwnProperty.call(this, name)) { + /* c8 ignore next 2 */ + continue + } + if (name === 'parent' || name === 'proxyCache') continue + let value = this[name] + + if (Array.isArray(value)) { + fixed[name] = value.map(i => { + if (typeof i === 'object' && i.toJSON) { + return i.toJSON(null, inputs) + } else { + return i + } + }) + } else if (typeof value === 'object' && value.toJSON) { + fixed[name] = value.toJSON(null, inputs) + } else if (name === 'source') { + let inputId = inputs.get(value.input) + if (inputId == null) { + inputId = inputsNextIndex + inputs.set(value.input, inputsNextIndex) + inputsNextIndex++ + } + fixed[name] = { + end: value.end, + inputId, + start: value.start + } + } else { + fixed[name] = value + } + } + + if (emitInputs) { + fixed.inputs = [...inputs.keys()].map(input => input.toJSON()) + } + + return fixed + } + + toProxy() { + if (!this.proxyCache) { + this.proxyCache = new Proxy(this, this.getProxyProcessor()) + } + return this.proxyCache + } + + toString(stringifier = stringify) { + if (stringifier.stringify) stringifier = stringifier.stringify + let result = '' + stringifier(this, i => { + result += i + }) + return result + } + + warn(result, text, opts) { + let data = { node: this } + for (let i in opts) data[i] = opts[i] + return result.warn(text, data) + } + + get proxyOf() { + return this + } +} + +module.exports = Node +Node.default = Node diff --git a/node_modules/postcss/lib/parse.d.ts b/node_modules/postcss/lib/parse.d.ts new file mode 100644 index 0000000..4c943a4 --- /dev/null +++ b/node_modules/postcss/lib/parse.d.ts @@ -0,0 +1,9 @@ +import { Parser } from './postcss.js' + +interface Parse extends Parser { + default: Parse +} + +declare const parse: Parse + +export = parse diff --git a/node_modules/postcss/lib/parse.js b/node_modules/postcss/lib/parse.js new file mode 100644 index 0000000..00a1037 --- /dev/null +++ b/node_modules/postcss/lib/parse.js @@ -0,0 +1,42 @@ +'use strict' + +let Container = require('./container') +let Input = require('./input') +let Parser = require('./parser') + +function parse(css, opts) { + let input = new Input(css, opts) + let parser = new Parser(input) + try { + parser.parse() + } catch (e) { + if (process.env.NODE_ENV !== 'production') { + if (e.name === 'CssSyntaxError' && opts && opts.from) { + if (/\.scss$/i.test(opts.from)) { + e.message += + '\nYou tried to parse SCSS with ' + + 'the standard CSS parser; ' + + 'try again with the postcss-scss parser' + } else if (/\.sass/i.test(opts.from)) { + e.message += + '\nYou tried to parse Sass with ' + + 'the standard CSS parser; ' + + 'try again with the postcss-sass parser' + } else if (/\.less$/i.test(opts.from)) { + e.message += + '\nYou tried to parse Less with ' + + 'the standard CSS parser; ' + + 'try again with the postcss-less parser' + } + } + } + throw e + } + + return parser.root +} + +module.exports = parse +parse.default = parse + +Container.registerParse(parse) diff --git a/node_modules/postcss/lib/parser.js b/node_modules/postcss/lib/parser.js new file mode 100644 index 0000000..8a04411 --- /dev/null +++ b/node_modules/postcss/lib/parser.js @@ -0,0 +1,609 @@ +'use strict' + +let AtRule = require('./at-rule') +let Comment = require('./comment') +let Declaration = require('./declaration') +let Root = require('./root') +let Rule = require('./rule') +let tokenizer = require('./tokenize') + +const SAFE_COMMENT_NEIGHBOR = { + empty: true, + space: true +} + +function findLastWithPosition(tokens) { + for (let i = tokens.length - 1; i >= 0; i--) { + let token = tokens[i] + let pos = token[3] || token[2] + if (pos) return pos + } +} + +class Parser { + constructor(input) { + this.input = input + + this.root = new Root() + this.current = this.root + this.spaces = '' + this.semicolon = false + + this.createTokenizer() + this.root.source = { input, start: { column: 1, line: 1, offset: 0 } } + } + + atrule(token) { + let node = new AtRule() + node.name = token[1].slice(1) + if (node.name === '') { + this.unnamedAtrule(node, token) + } + this.init(node, token[2]) + + let type + let prev + let shift + let last = false + let open = false + let params = [] + let brackets = [] + + while (!this.tokenizer.endOfFile()) { + token = this.tokenizer.nextToken() + type = token[0] + + if (type === '(' || type === '[') { + brackets.push(type === '(' ? ')' : ']') + } else if (type === '{' && brackets.length > 0) { + brackets.push('}') + } else if (type === brackets[brackets.length - 1]) { + brackets.pop() + } + + if (brackets.length === 0) { + if (type === ';') { + node.source.end = this.getPosition(token[2]) + node.source.end.offset++ + this.semicolon = true + break + } else if (type === '{') { + open = true + break + } else if (type === '}') { + if (params.length > 0) { + shift = params.length - 1 + prev = params[shift] + while (prev && prev[0] === 'space') { + prev = params[--shift] + } + if (prev) { + node.source.end = this.getPosition(prev[3] || prev[2]) + node.source.end.offset++ + } + } + this.end(token) + break + } else { + params.push(token) + } + } else { + params.push(token) + } + + if (this.tokenizer.endOfFile()) { + last = true + break + } + } + + node.raws.between = this.spacesAndCommentsFromEnd(params) + if (params.length) { + node.raws.afterName = this.spacesAndCommentsFromStart(params) + this.raw(node, 'params', params) + if (last) { + token = params[params.length - 1] + node.source.end = this.getPosition(token[3] || token[2]) + node.source.end.offset++ + this.spaces = node.raws.between + node.raws.between = '' + } + } else { + node.raws.afterName = '' + node.params = '' + } + + if (open) { + node.nodes = [] + this.current = node + } + } + + checkMissedSemicolon(tokens) { + let colon = this.colon(tokens) + if (colon === false) return + + let founded = 0 + let token + for (let j = colon - 1; j >= 0; j--) { + token = tokens[j] + if (token[0] !== 'space') { + founded += 1 + if (founded === 2) break + } + } + // If the token is a word, e.g. `!important`, `red` or any other valid property's value. + // Then we need to return the colon after that word token. [3] is the "end" colon of that word. + // And because we need it after that one we do +1 to get the next one. + throw this.input.error( + 'Missed semicolon', + token[0] === 'word' ? token[3] + 1 : token[2] + ) + } + + colon(tokens) { + let brackets = 0 + let prev, token, type + for (let [i, element] of tokens.entries()) { + token = element + type = token[0] + + if (type === '(') { + brackets += 1 + } + if (type === ')') { + brackets -= 1 + } + if (brackets === 0 && type === ':') { + if (!prev) { + this.doubleColon(token) + } else if (prev[0] === 'word' && prev[1] === 'progid') { + continue + } else { + return i + } + } + + prev = token + } + return false + } + + comment(token) { + let node = new Comment() + this.init(node, token[2]) + node.source.end = this.getPosition(token[3] || token[2]) + node.source.end.offset++ + + let text = token[1].slice(2, -2) + if (/^\s*$/.test(text)) { + node.text = '' + node.raws.left = text + node.raws.right = '' + } else { + let match = text.match(/^(\s*)([^]*\S)(\s*)$/) + node.text = match[2] + node.raws.left = match[1] + node.raws.right = match[3] + } + } + + createTokenizer() { + this.tokenizer = tokenizer(this.input) + } + + decl(tokens, customProperty) { + let node = new Declaration() + this.init(node, tokens[0][2]) + + let last = tokens[tokens.length - 1] + if (last[0] === ';') { + this.semicolon = true + tokens.pop() + } + + node.source.end = this.getPosition( + last[3] || last[2] || findLastWithPosition(tokens) + ) + node.source.end.offset++ + + while (tokens[0][0] !== 'word') { + if (tokens.length === 1) this.unknownWord(tokens) + node.raws.before += tokens.shift()[1] + } + node.source.start = this.getPosition(tokens[0][2]) + + node.prop = '' + while (tokens.length) { + let type = tokens[0][0] + if (type === ':' || type === 'space' || type === 'comment') { + break + } + node.prop += tokens.shift()[1] + } + + node.raws.between = '' + + let token + while (tokens.length) { + token = tokens.shift() + + if (token[0] === ':') { + node.raws.between += token[1] + break + } else { + if (token[0] === 'word' && /\w/.test(token[1])) { + this.unknownWord([token]) + } + node.raws.between += token[1] + } + } + + if (node.prop[0] === '_' || node.prop[0] === '*') { + node.raws.before += node.prop[0] + node.prop = node.prop.slice(1) + } + + let firstSpaces = [] + let next + while (tokens.length) { + next = tokens[0][0] + if (next !== 'space' && next !== 'comment') break + firstSpaces.push(tokens.shift()) + } + + this.precheckMissedSemicolon(tokens) + + for (let i = tokens.length - 1; i >= 0; i--) { + token = tokens[i] + if (token[1].toLowerCase() === '!important') { + node.important = true + let string = this.stringFrom(tokens, i) + string = this.spacesFromEnd(tokens) + string + if (string !== ' !important') node.raws.important = string + break + } else if (token[1].toLowerCase() === 'important') { + let cache = tokens.slice(0) + let str = '' + for (let j = i; j > 0; j--) { + let type = cache[j][0] + if (str.trim().startsWith('!') && type !== 'space') { + break + } + str = cache.pop()[1] + str + } + if (str.trim().startsWith('!')) { + node.important = true + node.raws.important = str + tokens = cache + } + } + + if (token[0] !== 'space' && token[0] !== 'comment') { + break + } + } + + let hasWord = tokens.some(i => i[0] !== 'space' && i[0] !== 'comment') + + if (hasWord) { + node.raws.between += firstSpaces.map(i => i[1]).join('') + firstSpaces = [] + } + this.raw(node, 'value', firstSpaces.concat(tokens), customProperty) + + if (node.value.includes(':') && !customProperty) { + this.checkMissedSemicolon(tokens) + } + } + + doubleColon(token) { + throw this.input.error( + 'Double colon', + { offset: token[2] }, + { offset: token[2] + token[1].length } + ) + } + + emptyRule(token) { + let node = new Rule() + this.init(node, token[2]) + node.selector = '' + node.raws.between = '' + this.current = node + } + + end(token) { + if (this.current.nodes && this.current.nodes.length) { + this.current.raws.semicolon = this.semicolon + } + this.semicolon = false + + this.current.raws.after = (this.current.raws.after || '') + this.spaces + this.spaces = '' + + if (this.current.parent) { + this.current.source.end = this.getPosition(token[2]) + this.current.source.end.offset++ + this.current = this.current.parent + } else { + this.unexpectedClose(token) + } + } + + endFile() { + if (this.current.parent) this.unclosedBlock() + if (this.current.nodes && this.current.nodes.length) { + this.current.raws.semicolon = this.semicolon + } + this.current.raws.after = (this.current.raws.after || '') + this.spaces + this.root.source.end = this.getPosition(this.tokenizer.position()) + } + + freeSemicolon(token) { + this.spaces += token[1] + if (this.current.nodes) { + let prev = this.current.nodes[this.current.nodes.length - 1] + if (prev && prev.type === 'rule' && !prev.raws.ownSemicolon) { + prev.raws.ownSemicolon = this.spaces + this.spaces = '' + } + } + } + + // Helpers + + getPosition(offset) { + let pos = this.input.fromOffset(offset) + return { + column: pos.col, + line: pos.line, + offset + } + } + + init(node, offset) { + this.current.push(node) + node.source = { + input: this.input, + start: this.getPosition(offset) + } + node.raws.before = this.spaces + this.spaces = '' + if (node.type !== 'comment') this.semicolon = false + } + + other(start) { + let end = false + let type = null + let colon = false + let bracket = null + let brackets = [] + let customProperty = start[1].startsWith('--') + + let tokens = [] + let token = start + while (token) { + type = token[0] + tokens.push(token) + + if (type === '(' || type === '[') { + if (!bracket) bracket = token + brackets.push(type === '(' ? ')' : ']') + } else if (customProperty && colon && type === '{') { + if (!bracket) bracket = token + brackets.push('}') + } else if (brackets.length === 0) { + if (type === ';') { + if (colon) { + this.decl(tokens, customProperty) + return + } else { + break + } + } else if (type === '{') { + this.rule(tokens) + return + } else if (type === '}') { + this.tokenizer.back(tokens.pop()) + end = true + break + } else if (type === ':') { + colon = true + } + } else if (type === brackets[brackets.length - 1]) { + brackets.pop() + if (brackets.length === 0) bracket = null + } + + token = this.tokenizer.nextToken() + } + + if (this.tokenizer.endOfFile()) end = true + if (brackets.length > 0) this.unclosedBracket(bracket) + + if (end && colon) { + if (!customProperty) { + while (tokens.length) { + token = tokens[tokens.length - 1][0] + if (token !== 'space' && token !== 'comment') break + this.tokenizer.back(tokens.pop()) + } + } + this.decl(tokens, customProperty) + } else { + this.unknownWord(tokens) + } + } + + parse() { + let token + while (!this.tokenizer.endOfFile()) { + token = this.tokenizer.nextToken() + + switch (token[0]) { + case 'space': + this.spaces += token[1] + break + + case ';': + this.freeSemicolon(token) + break + + case '}': + this.end(token) + break + + case 'comment': + this.comment(token) + break + + case 'at-word': + this.atrule(token) + break + + case '{': + this.emptyRule(token) + break + + default: + this.other(token) + break + } + } + this.endFile() + } + + precheckMissedSemicolon(/* tokens */) { + // Hook for Safe Parser + } + + raw(node, prop, tokens, customProperty) { + let token, type + let length = tokens.length + let value = '' + let clean = true + let next, prev + + for (let i = 0; i < length; i += 1) { + token = tokens[i] + type = token[0] + if (type === 'space' && i === length - 1 && !customProperty) { + clean = false + } else if (type === 'comment') { + prev = tokens[i - 1] ? tokens[i - 1][0] : 'empty' + next = tokens[i + 1] ? tokens[i + 1][0] : 'empty' + if (!SAFE_COMMENT_NEIGHBOR[prev] && !SAFE_COMMENT_NEIGHBOR[next]) { + if (value.slice(-1) === ',') { + clean = false + } else { + value += token[1] + } + } else { + clean = false + } + } else { + value += token[1] + } + } + if (!clean) { + let raw = tokens.reduce((all, i) => all + i[1], '') + node.raws[prop] = { raw, value } + } + node[prop] = value + } + + rule(tokens) { + tokens.pop() + + let node = new Rule() + this.init(node, tokens[0][2]) + + node.raws.between = this.spacesAndCommentsFromEnd(tokens) + this.raw(node, 'selector', tokens) + this.current = node + } + + spacesAndCommentsFromEnd(tokens) { + let lastTokenType + let spaces = '' + while (tokens.length) { + lastTokenType = tokens[tokens.length - 1][0] + if (lastTokenType !== 'space' && lastTokenType !== 'comment') break + spaces = tokens.pop()[1] + spaces + } + return spaces + } + + // Errors + + spacesAndCommentsFromStart(tokens) { + let next + let spaces = '' + while (tokens.length) { + next = tokens[0][0] + if (next !== 'space' && next !== 'comment') break + spaces += tokens.shift()[1] + } + return spaces + } + + spacesFromEnd(tokens) { + let lastTokenType + let spaces = '' + while (tokens.length) { + lastTokenType = tokens[tokens.length - 1][0] + if (lastTokenType !== 'space') break + spaces = tokens.pop()[1] + spaces + } + return spaces + } + + stringFrom(tokens, from) { + let result = '' + for (let i = from; i < tokens.length; i++) { + result += tokens[i][1] + } + tokens.splice(from, tokens.length - from) + return result + } + + unclosedBlock() { + let pos = this.current.source.start + throw this.input.error('Unclosed block', pos.line, pos.column) + } + + unclosedBracket(bracket) { + throw this.input.error( + 'Unclosed bracket', + { offset: bracket[2] }, + { offset: bracket[2] + 1 } + ) + } + + unexpectedClose(token) { + throw this.input.error( + 'Unexpected }', + { offset: token[2] }, + { offset: token[2] + 1 } + ) + } + + unknownWord(tokens) { + throw this.input.error( + 'Unknown word', + { offset: tokens[0][2] }, + { offset: tokens[0][2] + tokens[0][1].length } + ) + } + + unnamedAtrule(node, token) { + throw this.input.error( + 'At-rule without name', + { offset: token[2] }, + { offset: token[2] + token[1].length } + ) + } +} + +module.exports = Parser diff --git a/node_modules/postcss/lib/postcss.d.mts b/node_modules/postcss/lib/postcss.d.mts new file mode 100644 index 0000000..4cf5b49 --- /dev/null +++ b/node_modules/postcss/lib/postcss.d.mts @@ -0,0 +1,69 @@ +export { + // postcss function / namespace + default, + + // Value exports from postcss.mjs + stringify, + fromJSON, + // @ts-expect-error This value exists, but it’s untyped. + plugin, + parse, + list, + document, + comment, + atRule, + rule, + decl, + root, + CssSyntaxError, + Declaration, + Container, + Processor, + Document, + Comment, + Warning, + AtRule, + Result, + Input, + Rule, + Root, + Node, + + // Type-only exports + AcceptedPlugin, + AnyNode, + AtRuleProps, + Builder, + ChildNode, + ChildProps, + CommentProps, + ContainerProps, + DeclarationProps, + DocumentProps, + FilePosition, + Helpers, + JSONHydrator, + Message, + NodeErrorOptions, + NodeProps, + OldPlugin, + Parser, + Plugin, + PluginCreator, + Position, + Postcss, + ProcessOptions, + RootProps, + RuleProps, + Source, + SourceMap, + SourceMapOptions, + Stringifier, + Syntax, + TransformCallback, + Transformer, + WarningOptions, + + // This is a class, but it’s not re-exported. That’s why it’s exported as type-only here. + type LazyResult +} from './postcss.js' diff --git a/node_modules/postcss/lib/postcss.d.ts b/node_modules/postcss/lib/postcss.d.ts new file mode 100644 index 0000000..d0b8b53 --- /dev/null +++ b/node_modules/postcss/lib/postcss.d.ts @@ -0,0 +1,453 @@ +import { RawSourceMap, SourceMapGenerator } from 'source-map-js' + +import AtRule, { AtRuleProps } from './at-rule.js' +import Comment, { CommentProps } from './comment.js' +import Container, { ContainerProps, NewChild } from './container.js' +import CssSyntaxError from './css-syntax-error.js' +import Declaration, { DeclarationProps } from './declaration.js' +import Document, { DocumentProps } from './document.js' +import Input, { FilePosition } from './input.js' +import LazyResult from './lazy-result.js' +import list from './list.js' +import Node, { + AnyNode, + ChildNode, + ChildProps, + NodeErrorOptions, + NodeProps, + Position, + Source +} from './node.js' +import Processor from './processor.js' +import Result, { Message } from './result.js' +import Root, { RootProps } from './root.js' +import Rule, { RuleProps } from './rule.js' +import Warning, { WarningOptions } from './warning.js' + +type DocumentProcessor = ( + document: Document, + helper: postcss.Helpers +) => Promise | void +type RootProcessor = ( + root: Root, + helper: postcss.Helpers +) => Promise | void +type DeclarationProcessor = ( + decl: Declaration, + helper: postcss.Helpers +) => Promise | void +type RuleProcessor = ( + rule: Rule, + helper: postcss.Helpers +) => Promise | void +type AtRuleProcessor = ( + atRule: AtRule, + helper: postcss.Helpers +) => Promise | void +type CommentProcessor = ( + comment: Comment, + helper: postcss.Helpers +) => Promise | void + +interface Processors { + /** + * Will be called on all`AtRule` nodes. + * + * Will be called again on node or children changes. + */ + AtRule?: { [name: string]: AtRuleProcessor } | AtRuleProcessor + + /** + * Will be called on all `AtRule` nodes, when all children will be processed. + * + * Will be called again on node or children changes. + */ + AtRuleExit?: { [name: string]: AtRuleProcessor } | AtRuleProcessor + + /** + * Will be called on all `Comment` nodes. + * + * Will be called again on node or children changes. + */ + Comment?: CommentProcessor + + /** + * Will be called on all `Comment` nodes after listeners + * for `Comment` event. + * + * Will be called again on node or children changes. + */ + CommentExit?: CommentProcessor + + /** + * Will be called on all `Declaration` nodes after listeners + * for `Declaration` event. + * + * Will be called again on node or children changes. + */ + Declaration?: { [prop: string]: DeclarationProcessor } | DeclarationProcessor + + /** + * Will be called on all `Declaration` nodes. + * + * Will be called again on node or children changes. + */ + DeclarationExit?: + | { [prop: string]: DeclarationProcessor } + | DeclarationProcessor + + /** + * Will be called on `Document` node. + * + * Will be called again on children changes. + */ + Document?: DocumentProcessor + + /** + * Will be called on `Document` node, when all children will be processed. + * + * Will be called again on children changes. + */ + DocumentExit?: DocumentProcessor + + /** + * Will be called on `Root` node once. + */ + Once?: RootProcessor + + /** + * Will be called on `Root` node once, when all children will be processed. + */ + OnceExit?: RootProcessor + + /** + * Will be called on `Root` node. + * + * Will be called again on children changes. + */ + Root?: RootProcessor + + /** + * Will be called on `Root` node, when all children will be processed. + * + * Will be called again on children changes. + */ + RootExit?: RootProcessor + + /** + * Will be called on all `Rule` nodes. + * + * Will be called again on node or children changes. + */ + Rule?: RuleProcessor + + /** + * Will be called on all `Rule` nodes, when all children will be processed. + * + * Will be called again on node or children changes. + */ + RuleExit?: RuleProcessor +} + +declare namespace postcss { + export { + AnyNode, + AtRule, + AtRuleProps, + ChildNode, + ChildProps, + Comment, + CommentProps, + Container, + ContainerProps, + CssSyntaxError, + Declaration, + DeclarationProps, + Document, + DocumentProps, + FilePosition, + Input, + LazyResult, + list, + Message, + NewChild, + Node, + NodeErrorOptions, + NodeProps, + Position, + Processor, + Result, + Root, + RootProps, + Rule, + RuleProps, + Source, + Warning, + WarningOptions + } + + export type SourceMap = { + toJSON(): RawSourceMap + } & SourceMapGenerator + + export type Helpers = { postcss: Postcss; result: Result } & Postcss + + export interface Plugin extends Processors { + postcssPlugin: string + prepare?: (result: Result) => Processors + } + + export interface PluginCreator { + (opts?: PluginOptions): Plugin | Processor + postcss: true + } + + export interface Transformer extends TransformCallback { + postcssPlugin: string + postcssVersion: string + } + + export interface TransformCallback { + (root: Root, result: Result): Promise | void + } + + export interface OldPlugin extends Transformer { + (opts?: T): Transformer + postcss: Transformer + } + + export type AcceptedPlugin = + | { + postcss: Processor | TransformCallback + } + | OldPlugin + | Plugin + | PluginCreator + | Processor + | TransformCallback + + export interface Parser { + ( + css: { toString(): string } | string, + opts?: Pick + ): RootNode + } + + export interface Builder { + (part: string, node?: AnyNode, type?: 'end' | 'start'): void + } + + export interface Stringifier { + (node: AnyNode, builder: Builder): void + } + + export interface JSONHydrator { + (data: object): Node + (data: object[]): Node[] + } + + export interface Syntax { + /** + * Function to generate AST by string. + */ + parse?: Parser + + /** + * Class to generate string by AST. + */ + stringify?: Stringifier + } + + export interface SourceMapOptions { + /** + * Use absolute path in generated source map. + */ + absolute?: boolean + + /** + * Indicates that PostCSS should add annotation comments to the CSS. + * By default, PostCSS will always add a comment with a path + * to the source map. PostCSS will not add annotations to CSS files + * that do not contain any comments. + * + * By default, PostCSS presumes that you want to save the source map as + * `opts.to + '.map'` and will use this path in the annotation comment. + * A different path can be set by providing a string value for annotation. + * + * If you have set `inline: true`, annotation cannot be disabled. + */ + annotation?: ((file: string, root: Root) => string) | boolean | string + + /** + * Override `from` in map’s sources. + */ + from?: string + + /** + * Indicates that the source map should be embedded in the output CSS + * as a Base64-encoded comment. By default, it is `true`. + * But if all previous maps are external, not inline, PostCSS will not embed + * the map even if you do not set this option. + * + * If you have an inline source map, the result.map property will be empty, + * as the source map will be contained within the text of `result.css`. + */ + inline?: boolean + + /** + * Source map content from a previous processing step (e.g., Sass). + * + * PostCSS will try to read the previous source map + * automatically (based on comments within the source CSS), but you can use + * this option to identify it manually. + * + * If desired, you can omit the previous map with prev: `false`. + */ + prev?: ((file: string) => string) | boolean | object | string + + /** + * Indicates that PostCSS should set the origin content (e.g., Sass source) + * of the source map. By default, it is true. But if all previous maps do not + * contain sources content, PostCSS will also leave it out even if you + * do not set this option. + */ + sourcesContent?: boolean + } + + export interface ProcessOptions { + /** + * The path of the CSS source file. You should always set `from`, + * because it is used in source map generation and syntax error messages. + */ + from?: string | undefined + + /** + * Source map options + */ + map?: boolean | SourceMapOptions + + /** + * Function to generate AST by string. + */ + parser?: Parser | Syntax + + /** + * Class to generate string by AST. + */ + stringifier?: Stringifier | Syntax + + /** + * Object with parse and stringify. + */ + syntax?: Syntax + + /** + * The path where you'll put the output CSS file. You should always set `to` + * to generate correct source maps. + */ + to?: string + } + + export type Postcss = typeof postcss + + /** + * Default function to convert a node tree into a CSS string. + */ + export let stringify: Stringifier + + /** + * Parses source css and returns a new `Root` or `Document` node, + * which contains the source CSS nodes. + * + * ```js + * // Simple CSS concatenation with source map support + * const root1 = postcss.parse(css1, { from: file1 }) + * const root2 = postcss.parse(css2, { from: file2 }) + * root1.append(root2).toResult().css + * ``` + */ + export let parse: Parser + + /** + * Rehydrate a JSON AST (from `Node#toJSON`) back into the AST classes. + * + * ```js + * const json = root.toJSON() + * // save to file, send by network, etc + * const root2 = postcss.fromJSON(json) + * ``` + */ + export let fromJSON: JSONHydrator + + /** + * Creates a new `Comment` node. + * + * @param defaults Properties for the new node. + * @return New comment node + */ + export function comment(defaults?: CommentProps): Comment + + /** + * Creates a new `AtRule` node. + * + * @param defaults Properties for the new node. + * @return New at-rule node. + */ + export function atRule(defaults?: AtRuleProps): AtRule + + /** + * Creates a new `Declaration` node. + * + * @param defaults Properties for the new node. + * @return New declaration node. + */ + export function decl(defaults?: DeclarationProps): Declaration + + /** + * Creates a new `Rule` node. + * + * @param default Properties for the new node. + * @return New rule node. + */ + export function rule(defaults?: RuleProps): Rule + + /** + * Creates a new `Root` node. + * + * @param defaults Properties for the new node. + * @return New root node. + */ + export function root(defaults?: RootProps): Root + + /** + * Creates a new `Document` node. + * + * @param defaults Properties for the new node. + * @return New document node. + */ + export function document(defaults?: DocumentProps): Document + + export { postcss as default } +} + +/** + * Create a new `Processor` instance that will apply `plugins` + * as CSS processors. + * + * ```js + * let postcss = require('postcss') + * + * postcss(plugins).process(css, { from, to }).then(result => { + * console.log(result.css) + * }) + * ``` + * + * @param plugins PostCSS plugins. + * @return Processor to process multiple CSS. + */ +declare function postcss( + plugins?: readonly postcss.AcceptedPlugin[] +): Processor +declare function postcss(...plugins: postcss.AcceptedPlugin[]): Processor + +export = postcss diff --git a/node_modules/postcss/lib/postcss.js b/node_modules/postcss/lib/postcss.js new file mode 100644 index 0000000..8f0773b --- /dev/null +++ b/node_modules/postcss/lib/postcss.js @@ -0,0 +1,101 @@ +'use strict' + +let AtRule = require('./at-rule') +let Comment = require('./comment') +let Container = require('./container') +let CssSyntaxError = require('./css-syntax-error') +let Declaration = require('./declaration') +let Document = require('./document') +let fromJSON = require('./fromJSON') +let Input = require('./input') +let LazyResult = require('./lazy-result') +let list = require('./list') +let Node = require('./node') +let parse = require('./parse') +let Processor = require('./processor') +let Result = require('./result.js') +let Root = require('./root') +let Rule = require('./rule') +let stringify = require('./stringify') +let Warning = require('./warning') + +function postcss(...plugins) { + if (plugins.length === 1 && Array.isArray(plugins[0])) { + plugins = plugins[0] + } + return new Processor(plugins) +} + +postcss.plugin = function plugin(name, initializer) { + let warningPrinted = false + function creator(...args) { + // eslint-disable-next-line no-console + if (console && console.warn && !warningPrinted) { + warningPrinted = true + // eslint-disable-next-line no-console + console.warn( + name + + ': postcss.plugin was deprecated. Migration guide:\n' + + 'https://evilmartians.com/chronicles/postcss-8-plugin-migration' + ) + if (process.env.LANG && process.env.LANG.startsWith('cn')) { + /* c8 ignore next 7 */ + // eslint-disable-next-line no-console + console.warn( + name + + ': 里面 postcss.plugin 被弃用. 迁移指南:\n' + + 'https://www.w3ctech.com/topic/2226' + ) + } + } + let transformer = initializer(...args) + transformer.postcssPlugin = name + transformer.postcssVersion = new Processor().version + return transformer + } + + let cache + Object.defineProperty(creator, 'postcss', { + get() { + if (!cache) cache = creator() + return cache + } + }) + + creator.process = function (css, processOpts, pluginOpts) { + return postcss([creator(pluginOpts)]).process(css, processOpts) + } + + return creator +} + +postcss.stringify = stringify +postcss.parse = parse +postcss.fromJSON = fromJSON +postcss.list = list + +postcss.comment = defaults => new Comment(defaults) +postcss.atRule = defaults => new AtRule(defaults) +postcss.decl = defaults => new Declaration(defaults) +postcss.rule = defaults => new Rule(defaults) +postcss.root = defaults => new Root(defaults) +postcss.document = defaults => new Document(defaults) + +postcss.CssSyntaxError = CssSyntaxError +postcss.Declaration = Declaration +postcss.Container = Container +postcss.Processor = Processor +postcss.Document = Document +postcss.Comment = Comment +postcss.Warning = Warning +postcss.AtRule = AtRule +postcss.Result = Result +postcss.Input = Input +postcss.Rule = Rule +postcss.Root = Root +postcss.Node = Node + +LazyResult.registerPostcss(postcss) + +module.exports = postcss +postcss.default = postcss diff --git a/node_modules/postcss/lib/postcss.mjs b/node_modules/postcss/lib/postcss.mjs new file mode 100644 index 0000000..3507598 --- /dev/null +++ b/node_modules/postcss/lib/postcss.mjs @@ -0,0 +1,30 @@ +import postcss from './postcss.js' + +export default postcss + +export const stringify = postcss.stringify +export const fromJSON = postcss.fromJSON +export const plugin = postcss.plugin +export const parse = postcss.parse +export const list = postcss.list + +export const document = postcss.document +export const comment = postcss.comment +export const atRule = postcss.atRule +export const rule = postcss.rule +export const decl = postcss.decl +export const root = postcss.root + +export const CssSyntaxError = postcss.CssSyntaxError +export const Declaration = postcss.Declaration +export const Container = postcss.Container +export const Processor = postcss.Processor +export const Document = postcss.Document +export const Comment = postcss.Comment +export const Warning = postcss.Warning +export const AtRule = postcss.AtRule +export const Result = postcss.Result +export const Input = postcss.Input +export const Rule = postcss.Rule +export const Root = postcss.Root +export const Node = postcss.Node diff --git a/node_modules/postcss/lib/previous-map.d.ts b/node_modules/postcss/lib/previous-map.d.ts new file mode 100644 index 0000000..23edeb5 --- /dev/null +++ b/node_modules/postcss/lib/previous-map.d.ts @@ -0,0 +1,81 @@ +import { SourceMapConsumer } from 'source-map-js' + +import { ProcessOptions } from './postcss.js' + +declare namespace PreviousMap { + // eslint-disable-next-line @typescript-eslint/no-use-before-define + export { PreviousMap_ as default } +} + +/** + * Source map information from input CSS. + * For example, source map after Sass compiler. + * + * This class will automatically find source map in input CSS or in file system + * near input file (according `from` option). + * + * ```js + * const root = parse(css, { from: 'a.sass.css' }) + * root.input.map //=> PreviousMap + * ``` + */ +declare class PreviousMap_ { + /** + * `sourceMappingURL` content. + */ + annotation?: string + + /** + * The CSS source identifier. Contains `Input#file` if the user + * set the `from` option, or `Input#id` if they did not. + */ + file?: string + + /** + * Was source map inlined by data-uri to input CSS. + */ + inline: boolean + + /** + * Path to source map file. + */ + mapFile?: string + + /** + * The directory with source map file, if source map is in separated file. + */ + root?: string + + /** + * Source map file content. + */ + text?: string + + /** + * @param css Input CSS source. + * @param opts Process options. + */ + constructor(css: string, opts?: ProcessOptions) + + /** + * Create a instance of `SourceMapGenerator` class + * from the `source-map` library to work with source map information. + * + * It is lazy method, so it will create object only on first call + * and then it will use cache. + * + * @return Object with source map information. + */ + consumer(): SourceMapConsumer + + /** + * Does source map contains `sourcesContent` with input source text. + * + * @return Is `sourcesContent` present. + */ + withContent(): boolean +} + +declare class PreviousMap extends PreviousMap_ {} + +export = PreviousMap diff --git a/node_modules/postcss/lib/previous-map.js b/node_modules/postcss/lib/previous-map.js new file mode 100644 index 0000000..b123dcd --- /dev/null +++ b/node_modules/postcss/lib/previous-map.js @@ -0,0 +1,144 @@ +'use strict' + +let { existsSync, readFileSync } = require('fs') +let { dirname, join } = require('path') +let { SourceMapConsumer, SourceMapGenerator } = require('source-map-js') + +function fromBase64(str) { + if (Buffer) { + return Buffer.from(str, 'base64').toString() + } else { + /* c8 ignore next 2 */ + return window.atob(str) + } +} + +class PreviousMap { + constructor(css, opts) { + if (opts.map === false) return + this.loadAnnotation(css) + this.inline = this.startWith(this.annotation, 'data:') + + let prev = opts.map ? opts.map.prev : undefined + let text = this.loadMap(opts.from, prev) + if (!this.mapFile && opts.from) { + this.mapFile = opts.from + } + if (this.mapFile) this.root = dirname(this.mapFile) + if (text) this.text = text + } + + consumer() { + if (!this.consumerCache) { + this.consumerCache = new SourceMapConsumer(this.text) + } + return this.consumerCache + } + + decodeInline(text) { + let baseCharsetUri = /^data:application\/json;charset=utf-?8;base64,/ + let baseUri = /^data:application\/json;base64,/ + let charsetUri = /^data:application\/json;charset=utf-?8,/ + let uri = /^data:application\/json,/ + + let uriMatch = text.match(charsetUri) || text.match(uri) + if (uriMatch) { + return decodeURIComponent(text.substr(uriMatch[0].length)) + } + + let baseUriMatch = text.match(baseCharsetUri) || text.match(baseUri) + if (baseUriMatch) { + return fromBase64(text.substr(baseUriMatch[0].length)) + } + + let encoding = text.match(/data:application\/json;([^,]+),/)[1] + throw new Error('Unsupported source map encoding ' + encoding) + } + + getAnnotationURL(sourceMapString) { + return sourceMapString.replace(/^\/\*\s*# sourceMappingURL=/, '').trim() + } + + isMap(map) { + if (typeof map !== 'object') return false + return ( + typeof map.mappings === 'string' || + typeof map._mappings === 'string' || + Array.isArray(map.sections) + ) + } + + loadAnnotation(css) { + let comments = css.match(/\/\*\s*# sourceMappingURL=/g) + if (!comments) return + + // sourceMappingURLs from comments, strings, etc. + let start = css.lastIndexOf(comments.pop()) + let end = css.indexOf('*/', start) + + if (start > -1 && end > -1) { + // Locate the last sourceMappingURL to avoid pickin + this.annotation = this.getAnnotationURL(css.substring(start, end)) + } + } + + loadFile(path) { + this.root = dirname(path) + if (existsSync(path)) { + this.mapFile = path + return readFileSync(path, 'utf-8').toString().trim() + } + } + + loadMap(file, prev) { + if (prev === false) return false + + if (prev) { + if (typeof prev === 'string') { + return prev + } else if (typeof prev === 'function') { + let prevPath = prev(file) + if (prevPath) { + let map = this.loadFile(prevPath) + if (!map) { + throw new Error( + 'Unable to load previous source map: ' + prevPath.toString() + ) + } + return map + } + } else if (prev instanceof SourceMapConsumer) { + return SourceMapGenerator.fromSourceMap(prev).toString() + } else if (prev instanceof SourceMapGenerator) { + return prev.toString() + } else if (this.isMap(prev)) { + return JSON.stringify(prev) + } else { + throw new Error( + 'Unsupported previous source map format: ' + prev.toString() + ) + } + } else if (this.inline) { + return this.decodeInline(this.annotation) + } else if (this.annotation) { + let map = this.annotation + if (file) map = join(dirname(file), map) + return this.loadFile(map) + } + } + + startWith(string, start) { + if (!string) return false + return string.substr(0, start.length) === start + } + + withContent() { + return !!( + this.consumer().sourcesContent && + this.consumer().sourcesContent.length > 0 + ) + } +} + +module.exports = PreviousMap +PreviousMap.default = PreviousMap diff --git a/node_modules/postcss/lib/processor.d.ts b/node_modules/postcss/lib/processor.d.ts new file mode 100644 index 0000000..aa2942c --- /dev/null +++ b/node_modules/postcss/lib/processor.d.ts @@ -0,0 +1,115 @@ +import Document from './document.js' +import LazyResult from './lazy-result.js' +import NoWorkResult from './no-work-result.js' +import { + AcceptedPlugin, + Plugin, + ProcessOptions, + TransformCallback, + Transformer +} from './postcss.js' +import Result from './result.js' +import Root from './root.js' + +declare namespace Processor { + // eslint-disable-next-line @typescript-eslint/no-use-before-define + export { Processor_ as default } +} + +/** + * Contains plugins to process CSS. Create one `Processor` instance, + * initialize its plugins, and then use that instance on numerous CSS files. + * + * ```js + * const processor = postcss([autoprefixer, postcssNested]) + * processor.process(css1).then(result => console.log(result.css)) + * processor.process(css2).then(result => console.log(result.css)) + * ``` + */ +declare class Processor_ { + /** + * Plugins added to this processor. + * + * ```js + * const processor = postcss([autoprefixer, postcssNested]) + * processor.plugins.length //=> 2 + * ``` + */ + plugins: (Plugin | TransformCallback | Transformer)[] + + /** + * Current PostCSS version. + * + * ```js + * if (result.processor.version.split('.')[0] !== '6') { + * throw new Error('This plugin works only with PostCSS 6') + * } + * ``` + */ + version: string + + /** + * @param plugins PostCSS plugins + */ + constructor(plugins?: readonly AcceptedPlugin[]) + + /** + * Parses source CSS and returns a `LazyResult` Promise proxy. + * Because some plugins can be asynchronous it doesn’t make + * any transformations. Transformations will be applied + * in the `LazyResult` methods. + * + * ```js + * processor.process(css, { from: 'a.css', to: 'a.out.css' }) + * .then(result => { + * console.log(result.css) + * }) + * ``` + * + * @param css String with input CSS or any object with a `toString()` method, + * like a Buffer. Optionally, send a `Result` instance + * and the processor will take the `Root` from it. + * @param opts Options. + * @return Promise proxy. + */ + process( + css: { toString(): string } | LazyResult | Result | Root | string + ): LazyResult | NoWorkResult + process( + css: { toString(): string } | LazyResult | Result | Root | string, + options: ProcessOptions + ): LazyResult + + /** + * Adds a plugin to be used as a CSS processor. + * + * PostCSS plugin can be in 4 formats: + * * A plugin in `Plugin` format. + * * A plugin creator function with `pluginCreator.postcss = true`. + * PostCSS will call this function without argument to get plugin. + * * A function. PostCSS will pass the function a {@link Root} + * as the first argument and current `Result` instance + * as the second. + * * Another `Processor` instance. PostCSS will copy plugins + * from that instance into this one. + * + * Plugins can also be added by passing them as arguments when creating + * a `postcss` instance (see [`postcss(plugins)`]). + * + * Asynchronous plugins should return a `Promise` instance. + * + * ```js + * const processor = postcss() + * .use(autoprefixer) + * .use(postcssNested) + * ``` + * + * @param plugin PostCSS plugin or `Processor` with plugins. + * @return Current processor to make methods chain. + */ + use(plugin: AcceptedPlugin): this +} + +declare class Processor extends Processor_ {} + +export = Processor diff --git a/node_modules/postcss/lib/processor.js b/node_modules/postcss/lib/processor.js new file mode 100644 index 0000000..6010b8b --- /dev/null +++ b/node_modules/postcss/lib/processor.js @@ -0,0 +1,67 @@ +'use strict' + +let Document = require('./document') +let LazyResult = require('./lazy-result') +let NoWorkResult = require('./no-work-result') +let Root = require('./root') + +class Processor { + constructor(plugins = []) { + this.version = '8.4.45' + this.plugins = this.normalize(plugins) + } + + normalize(plugins) { + let normalized = [] + for (let i of plugins) { + if (i.postcss === true) { + i = i() + } else if (i.postcss) { + i = i.postcss + } + + if (typeof i === 'object' && Array.isArray(i.plugins)) { + normalized = normalized.concat(i.plugins) + } else if (typeof i === 'object' && i.postcssPlugin) { + normalized.push(i) + } else if (typeof i === 'function') { + normalized.push(i) + } else if (typeof i === 'object' && (i.parse || i.stringify)) { + if (process.env.NODE_ENV !== 'production') { + throw new Error( + 'PostCSS syntaxes cannot be used as plugins. Instead, please use ' + + 'one of the syntax/parser/stringifier options as outlined ' + + 'in your PostCSS runner documentation.' + ) + } + } else { + throw new Error(i + ' is not a PostCSS plugin') + } + } + return normalized + } + + process(css, opts = {}) { + if ( + !this.plugins.length && + !opts.parser && + !opts.stringifier && + !opts.syntax + ) { + return new NoWorkResult(this, css, opts) + } else { + return new LazyResult(this, css, opts) + } + } + + use(plugin) { + this.plugins = this.plugins.concat(this.normalize([plugin])) + return this + } +} + +module.exports = Processor +Processor.default = Processor + +Root.registerProcessor(Processor) +Document.registerProcessor(Processor) diff --git a/node_modules/postcss/lib/result.d.ts b/node_modules/postcss/lib/result.d.ts new file mode 100644 index 0000000..40e086f --- /dev/null +++ b/node_modules/postcss/lib/result.d.ts @@ -0,0 +1,205 @@ +import { + Document, + Node, + Plugin, + ProcessOptions, + Root, + SourceMap, + TransformCallback, + Warning, + WarningOptions +} from './postcss.js' +import Processor from './processor.js' + +declare namespace Result { + export interface Message { + [others: string]: any + + /** + * Source PostCSS plugin name. + */ + plugin?: string + + /** + * Message type. + */ + type: string + } + + export interface ResultOptions extends ProcessOptions { + /** + * The CSS node that was the source of the warning. + */ + node?: Node + + /** + * Name of plugin that created this warning. `Result#warn` will fill it + * automatically with `Plugin#postcssPlugin` value. + */ + plugin?: string + } + + // eslint-disable-next-line @typescript-eslint/no-use-before-define + export { Result_ as default } +} + +/** + * Provides the result of the PostCSS transformations. + * + * A Result instance is returned by `LazyResult#then` + * or `Root#toResult` methods. + * + * ```js + * postcss([autoprefixer]).process(css).then(result => { + * console.log(result.css) + * }) + * ``` + * + * ```js + * const result2 = postcss.parse(css).toResult() + * ``` + */ +declare class Result_ { + /** + * A CSS string representing of `Result#root`. + * + * ```js + * postcss.parse('a{}').toResult().css //=> "a{}" + * ``` + */ + css: string + + /** + * Last runned PostCSS plugin. + */ + lastPlugin: Plugin | TransformCallback + + /** + * An instance of `SourceMapGenerator` class from the `source-map` library, + * representing changes to the `Result#root` instance. + * + * ```js + * result.map.toJSON() //=> { version: 3, file: 'a.css', … } + * ``` + * + * ```js + * if (result.map) { + * fs.writeFileSync(result.opts.to + '.map', result.map.toString()) + * } + * ``` + */ + map: SourceMap + + /** + * Contains messages from plugins (e.g., warnings or custom messages). + * Each message should have type and plugin properties. + * + * ```js + * AtRule: { + * import: (atRule, { result }) { + * const importedFile = parseImport(atRule) + * result.messages.push({ + * type: 'dependency', + * plugin: 'postcss-import', + * file: importedFile, + * parent: result.opts.from + * }) + * } + * } + * ``` + */ + messages: Result.Message[] + + /** + * Options from the `Processor#process` or `Root#toResult` call + * that produced this Result instance.] + * + * ```js + * root.toResult(opts).opts === opts + * ``` + */ + opts: Result.ResultOptions + + /** + * The Processor instance used for this transformation. + * + * ```js + * for (const plugin of result.processor.plugins) { + * if (plugin.postcssPlugin === 'postcss-bad') { + * throw 'postcss-good is incompatible with postcss-bad' + * } + * }) + * ``` + */ + processor: Processor + + /** + * Root node after all transformations. + * + * ```js + * root.toResult().root === root + * ``` + */ + root: RootNode + + /** + * @param processor Processor used for this transformation. + * @param root Root node after all transformations. + * @param opts Options from the `Processor#process` or `Root#toResult`. + */ + constructor(processor: Processor, root: RootNode, opts: Result.ResultOptions) + + /** + * Returns for `Result#css` content. + * + * ```js + * result + '' === result.css + * ``` + * + * @return String representing of `Result#root`. + */ + toString(): string + + /** + * Creates an instance of `Warning` and adds it to `Result#messages`. + * + * ```js + * if (decl.important) { + * result.warn('Avoid !important', { node: decl, word: '!important' }) + * } + * ``` + * + * @param text Warning message. + * @param opts Warning options. + * @return Created warning. + */ + warn(message: string, options?: WarningOptions): Warning + + /** + * Returns warnings from plugins. Filters `Warning` instances + * from `Result#messages`. + * + * ```js + * result.warnings().forEach(warn => { + * console.warn(warn.toString()) + * }) + * ``` + * + * @return Warnings from plugins. + */ + warnings(): Warning[] + + /** + * An alias for the `Result#css` property. + * Use it with syntaxes that generate non-CSS output. + * + * ```js + * result.css === result.content + * ``` + */ + get content(): string +} + +declare class Result extends Result_ {} + +export = Result diff --git a/node_modules/postcss/lib/result.js b/node_modules/postcss/lib/result.js new file mode 100644 index 0000000..a39751d --- /dev/null +++ b/node_modules/postcss/lib/result.js @@ -0,0 +1,42 @@ +'use strict' + +let Warning = require('./warning') + +class Result { + constructor(processor, root, opts) { + this.processor = processor + this.messages = [] + this.root = root + this.opts = opts + this.css = undefined + this.map = undefined + } + + toString() { + return this.css + } + + warn(text, opts = {}) { + if (!opts.plugin) { + if (this.lastPlugin && this.lastPlugin.postcssPlugin) { + opts.plugin = this.lastPlugin.postcssPlugin + } + } + + let warning = new Warning(text, opts) + this.messages.push(warning) + + return warning + } + + warnings() { + return this.messages.filter(i => i.type === 'warning') + } + + get content() { + return this.css + } +} + +module.exports = Result +Result.default = Result diff --git a/node_modules/postcss/lib/root.d.ts b/node_modules/postcss/lib/root.d.ts new file mode 100644 index 0000000..5c91139 --- /dev/null +++ b/node_modules/postcss/lib/root.d.ts @@ -0,0 +1,87 @@ +import Container, { ContainerProps } from './container.js' +import Document from './document.js' +import { ProcessOptions } from './postcss.js' +import Result from './result.js' + +declare namespace Root { + export interface RootRaws extends Record { + /** + * The space symbols after the last child to the end of file. + */ + after?: string + + /** + * Non-CSS code after `Root`, when `Root` is inside `Document`. + * + * **Experimental:** some aspects of this node could change within minor + * or patch version releases. + */ + codeAfter?: string + + /** + * Non-CSS code before `Root`, when `Root` is inside `Document`. + * + * **Experimental:** some aspects of this node could change within minor + * or patch version releases. + */ + codeBefore?: string + + /** + * Is the last child has an (optional) semicolon. + */ + semicolon?: boolean + } + + export interface RootProps extends ContainerProps { + /** + * Information used to generate byte-to-byte equal node string + * as it was in the origin input. + * */ + raws?: RootRaws + } + + // eslint-disable-next-line @typescript-eslint/no-use-before-define + export { Root_ as default } +} + +/** + * Represents a CSS file and contains all its parsed nodes. + * + * ```js + * const root = postcss.parse('a{color:black} b{z-index:2}') + * root.type //=> 'root' + * root.nodes.length //=> 2 + * ``` + */ +declare class Root_ extends Container { + nodes: NonNullable + parent: Document | undefined + raws: Root.RootRaws + type: 'root' + + constructor(defaults?: Root.RootProps) + + assign(overrides: object | Root.RootProps): this + clone(overrides?: Partial): this + cloneAfter(overrides?: Partial): this + cloneBefore(overrides?: Partial): this + + /** + * Returns a `Result` instance representing the root’s CSS. + * + * ```js + * const root1 = postcss.parse(css1, { from: 'a.css' }) + * const root2 = postcss.parse(css2, { from: 'b.css' }) + * root1.append(root2) + * const result = root1.toResult({ to: 'all.css', map: true }) + * ``` + * + * @param options Options. + * @return Result with current root’s CSS. + */ + toResult(options?: ProcessOptions): Result +} + +declare class Root extends Root_ {} + +export = Root diff --git a/node_modules/postcss/lib/root.js b/node_modules/postcss/lib/root.js new file mode 100644 index 0000000..ea574ed --- /dev/null +++ b/node_modules/postcss/lib/root.js @@ -0,0 +1,61 @@ +'use strict' + +let Container = require('./container') + +let LazyResult, Processor + +class Root extends Container { + constructor(defaults) { + super(defaults) + this.type = 'root' + if (!this.nodes) this.nodes = [] + } + + normalize(child, sample, type) { + let nodes = super.normalize(child) + + if (sample) { + if (type === 'prepend') { + if (this.nodes.length > 1) { + sample.raws.before = this.nodes[1].raws.before + } else { + delete sample.raws.before + } + } else if (this.first !== sample) { + for (let node of nodes) { + node.raws.before = sample.raws.before + } + } + } + + return nodes + } + + removeChild(child, ignore) { + let index = this.index(child) + + if (!ignore && index === 0 && this.nodes.length > 1) { + this.nodes[1].raws.before = this.nodes[index].raws.before + } + + return super.removeChild(child) + } + + toResult(opts = {}) { + let lazy = new LazyResult(new Processor(), this, opts) + return lazy.stringify() + } +} + +Root.registerLazyResult = dependant => { + LazyResult = dependant +} + +Root.registerProcessor = dependant => { + Processor = dependant +} + +module.exports = Root +Root.default = Root + +Container.registerRoot(Root) diff --git a/node_modules/postcss/lib/rule.d.ts b/node_modules/postcss/lib/rule.d.ts new file mode 100644 index 0000000..da8aae7 --- /dev/null +++ b/node_modules/postcss/lib/rule.d.ts @@ -0,0 +1,126 @@ +import Container, { + ContainerProps, + ContainerWithChildren +} from './container.js' + +declare namespace Rule { + export interface RuleRaws extends Record { + /** + * The space symbols after the last child of the node to the end of the node. + */ + after?: string + + /** + * The space symbols before the node. It also stores `*` + * and `_` symbols before the declaration (IE hack). + */ + before?: string + + /** + * The symbols between the selector and `{` for rules. + */ + between?: string + + /** + * Contains `true` if there is semicolon after rule. + */ + ownSemicolon?: string + + /** + * The rule’s selector with comments. + */ + selector?: { + raw: string + value: string + } + + /** + * Contains `true` if the last child has an (optional) semicolon. + */ + semicolon?: boolean + } + + export type RuleProps = { + /** Information used to generate byte-to-byte equal node string as it was in the origin input. */ + raws?: RuleRaws + } & ( + | { + /** Selector or selectors of the rule. */ + selector: string + selectors?: never + } + | { + selector?: never + /** Selectors of the rule represented as an array of strings. */ + selectors: readonly string[] + } + ) & ContainerProps + + // eslint-disable-next-line @typescript-eslint/no-use-before-define + export { Rule_ as default } +} + +/** + * Represents a CSS rule: a selector followed by a declaration block. + * + * ```js + * Once (root, { Rule }) { + * let a = new Rule({ selector: 'a' }) + * a.append(…) + * root.append(a) + * } + * ``` + * + * ```js + * const root = postcss.parse('a{}') + * const rule = root.first + * rule.type //=> 'rule' + * rule.toString() //=> 'a{}' + * ``` + */ +declare class Rule_ extends Container { + nodes: NonNullable + parent: ContainerWithChildren | undefined + raws: Rule.RuleRaws + type: 'rule' + constructor(defaults?: Rule.RuleProps) + + assign(overrides: object | Rule.RuleProps): this + clone(overrides?: Partial): this + + cloneAfter(overrides?: Partial): this + + cloneBefore(overrides?: Partial): this + /** + * The rule’s full selector represented as a string. + * + * ```js + * const root = postcss.parse('a, b { }') + * const rule = root.first + * rule.selector //=> 'a, b' + * ``` + */ + get selector(): string + set selector(value: string) + /** + * An array containing the rule’s individual selectors. + * Groups of selectors are split at commas. + * + * ```js + * const root = postcss.parse('a, b { }') + * const rule = root.first + * + * rule.selector //=> 'a, b' + * rule.selectors //=> ['a', 'b'] + * + * rule.selectors = ['a', 'strong'] + * rule.selector //=> 'a, strong' + * ``` + */ + get selectors(): string[] + set selectors(values: string[]) +} + +declare class Rule extends Rule_ {} + +export = Rule diff --git a/node_modules/postcss/lib/rule.js b/node_modules/postcss/lib/rule.js new file mode 100644 index 0000000..a93ab25 --- /dev/null +++ b/node_modules/postcss/lib/rule.js @@ -0,0 +1,27 @@ +'use strict' + +let Container = require('./container') +let list = require('./list') + +class Rule extends Container { + constructor(defaults) { + super(defaults) + this.type = 'rule' + if (!this.nodes) this.nodes = [] + } + + get selectors() { + return list.comma(this.selector) + } + + set selectors(values) { + let match = this.selector ? this.selector.match(/,\s*/) : null + let sep = match ? match[0] : ',' + this.raw('between', 'beforeOpen') + this.selector = values.join(sep) + } +} + +module.exports = Rule +Rule.default = Rule + +Container.registerRule(Rule) diff --git a/node_modules/postcss/lib/stringifier.d.ts b/node_modules/postcss/lib/stringifier.d.ts new file mode 100644 index 0000000..f707a6a --- /dev/null +++ b/node_modules/postcss/lib/stringifier.d.ts @@ -0,0 +1,46 @@ +import { + AnyNode, + AtRule, + Builder, + Comment, + Container, + Declaration, + Document, + Root, + Rule +} from './postcss.js' + +declare namespace Stringifier { + // eslint-disable-next-line @typescript-eslint/no-use-before-define + export { Stringifier_ as default } +} + +declare class Stringifier_ { + builder: Builder + constructor(builder: Builder) + atrule(node: AtRule, semicolon?: boolean): void + beforeAfter(node: AnyNode, detect: 'after' | 'before'): string + block(node: AnyNode, start: string): void + body(node: Container): void + comment(node: Comment): void + decl(node: Declaration, semicolon?: boolean): void + document(node: Document): void + raw(node: AnyNode, own: null | string, detect?: string): string + rawBeforeClose(root: Root): string | undefined + rawBeforeComment(root: Root, node: Comment): string | undefined + rawBeforeDecl(root: Root, node: Declaration): string | undefined + rawBeforeOpen(root: Root): string | undefined + rawBeforeRule(root: Root): string | undefined + rawColon(root: Root): string | undefined + rawEmptyBody(root: Root): string | undefined + rawIndent(root: Root): string | undefined + rawSemicolon(root: Root): boolean | undefined + rawValue(node: AnyNode, prop: string): string + root(node: Root): void + rule(node: Rule): void + stringify(node: AnyNode, semicolon?: boolean): void +} + +declare class Stringifier extends Stringifier_ {} + +export = Stringifier diff --git a/node_modules/postcss/lib/stringifier.js b/node_modules/postcss/lib/stringifier.js new file mode 100644 index 0000000..e07ad12 --- /dev/null +++ b/node_modules/postcss/lib/stringifier.js @@ -0,0 +1,353 @@ +'use strict' + +const DEFAULT_RAW = { + after: '\n', + beforeClose: '\n', + beforeComment: '\n', + beforeDecl: '\n', + beforeOpen: ' ', + beforeRule: '\n', + colon: ': ', + commentLeft: ' ', + commentRight: ' ', + emptyBody: '', + indent: ' ', + semicolon: false +} + +function capitalize(str) { + return str[0].toUpperCase() + str.slice(1) +} + +class Stringifier { + constructor(builder) { + this.builder = builder + } + + atrule(node, semicolon) { + let name = '@' + node.name + let params = node.params ? this.rawValue(node, 'params') : '' + + if (typeof node.raws.afterName !== 'undefined') { + name += node.raws.afterName + } else if (params) { + name += ' ' + } + + if (node.nodes) { + this.block(node, name + params) + } else { + let end = (node.raws.between || '') + (semicolon ? ';' : '') + this.builder(name + params + end, node) + } + } + + beforeAfter(node, detect) { + let value + if (node.type === 'decl') { + value = this.raw(node, null, 'beforeDecl') + } else if (node.type === 'comment') { + value = this.raw(node, null, 'beforeComment') + } else if (detect === 'before') { + value = this.raw(node, null, 'beforeRule') + } else { + value = this.raw(node, null, 'beforeClose') + } + + let buf = node.parent + let depth = 0 + while (buf && buf.type !== 'root') { + depth += 1 + buf = buf.parent + } + + if (value.includes('\n')) { + let indent = this.raw(node, null, 'indent') + if (indent.length) { + for (let step = 0; step < depth; step++) value += indent + } + } + + return value + } + + block(node, start) { + let between = this.raw(node, 'between', 'beforeOpen') + this.builder(start + between + '{', node, 'start') + + let after + if (node.nodes && node.nodes.length) { + this.body(node) + after = this.raw(node, 'after') + } else { + after = this.raw(node, 'after', 'emptyBody') + } + + if (after) this.builder(after) + this.builder('}', node, 'end') + } + + body(node) { + let last = node.nodes.length - 1 + while (last > 0) { + if (node.nodes[last].type !== 'comment') break + last -= 1 + } + + let semicolon = this.raw(node, 'semicolon') + for (let i = 0; i < node.nodes.length; i++) { + let child = node.nodes[i] + let before = this.raw(child, 'before') + if (before) this.builder(before) + this.stringify(child, last !== i || semicolon) + } + } + + comment(node) { + let left = this.raw(node, 'left', 'commentLeft') + let right = this.raw(node, 'right', 'commentRight') + this.builder('/*' + left + node.text + right + '*/', node) + } + + decl(node, semicolon) { + let between = this.raw(node, 'between', 'colon') + let string = node.prop + between + this.rawValue(node, 'value') + + if (node.important) { + string += node.raws.important || ' !important' + } + + if (semicolon) string += ';' + this.builder(string, node) + } + + document(node) { + this.body(node) + } + + raw(node, own, detect) { + let value + if (!detect) detect = own + + // Already had + if (own) { + value = node.raws[own] + if (typeof value !== 'undefined') return value + } + + let parent = node.parent + + if (detect === 'before') { + // Hack for first rule in CSS + if (!parent || (parent.type === 'root' && parent.first === node)) { + return '' + } + + // `root` nodes in `document` should use only their own raws + if (parent && parent.type === 'document') { + return '' + } + } + + // Floating child without parent + if (!parent) return DEFAULT_RAW[detect] + + // Detect style by other nodes + let root = node.root() + if (!root.rawCache) root.rawCache = {} + if (typeof root.rawCache[detect] !== 'undefined') { + return root.rawCache[detect] + } + + if (detect === 'before' || detect === 'after') { + return this.beforeAfter(node, detect) + } else { + let method = 'raw' + capitalize(detect) + if (this[method]) { + value = this[method](root, node) + } else { + root.walk(i => { + value = i.raws[own] + if (typeof value !== 'undefined') return false + }) + } + } + + if (typeof value === 'undefined') value = DEFAULT_RAW[detect] + + root.rawCache[detect] = value + return value + } + + rawBeforeClose(root) { + let value + root.walk(i => { + if (i.nodes && i.nodes.length > 0) { + if (typeof i.raws.after !== 'undefined') { + value = i.raws.after + if (value.includes('\n')) { + value = value.replace(/[^\n]+$/, '') + } + return false + } + } + }) + if (value) value = value.replace(/\S/g, '') + return value + } + + rawBeforeComment(root, node) { + let value + root.walkComments(i => { + if (typeof i.raws.before !== 'undefined') { + value = i.raws.before + if (value.includes('\n')) { + value = value.replace(/[^\n]+$/, '') + } + return false + } + }) + if (typeof value === 'undefined') { + value = this.raw(node, null, 'beforeDecl') + } else if (value) { + value = value.replace(/\S/g, '') + } + return value + } + + rawBeforeDecl(root, node) { + let value + root.walkDecls(i => { + if (typeof i.raws.before !== 'undefined') { + value = i.raws.before + if (value.includes('\n')) { + value = value.replace(/[^\n]+$/, '') + } + return false + } + }) + if (typeof value === 'undefined') { + value = this.raw(node, null, 'beforeRule') + } else if (value) { + value = value.replace(/\S/g, '') + } + return value + } + + rawBeforeOpen(root) { + let value + root.walk(i => { + if (i.type !== 'decl') { + value = i.raws.between + if (typeof value !== 'undefined') return false + } + }) + return value + } + + rawBeforeRule(root) { + let value + root.walk(i => { + if (i.nodes && (i.parent !== root || root.first !== i)) { + if (typeof i.raws.before !== 'undefined') { + value = i.raws.before + if (value.includes('\n')) { + value = value.replace(/[^\n]+$/, '') + } + return false + } + } + }) + if (value) value = value.replace(/\S/g, '') + return value + } + + rawColon(root) { + let value + root.walkDecls(i => { + if (typeof i.raws.between !== 'undefined') { + value = i.raws.between.replace(/[^\s:]/g, '') + return false + } + }) + return value + } + + rawEmptyBody(root) { + let value + root.walk(i => { + if (i.nodes && i.nodes.length === 0) { + value = i.raws.after + if (typeof value !== 'undefined') return false + } + }) + return value + } + + rawIndent(root) { + if (root.raws.indent) return root.raws.indent + let value + root.walk(i => { + let p = i.parent + if (p && p !== root && p.parent && p.parent === root) { + if (typeof i.raws.before !== 'undefined') { + let parts = i.raws.before.split('\n') + value = parts[parts.length - 1] + value = value.replace(/\S/g, '') + return false + } + } + }) + return value + } + + rawSemicolon(root) { + let value + root.walk(i => { + if (i.nodes && i.nodes.length && i.last.type === 'decl') { + value = i.raws.semicolon + if (typeof value !== 'undefined') return false + } + }) + return value + } + + rawValue(node, prop) { + let value = node[prop] + let raw = node.raws[prop] + if (raw && raw.value === value) { + return raw.raw + } + + return value + } + + root(node) { + this.body(node) + if (node.raws.after) this.builder(node.raws.after) + } + + rule(node) { + this.block(node, this.rawValue(node, 'selector')) + if (node.raws.ownSemicolon) { + this.builder(node.raws.ownSemicolon, node, 'end') + } + } + + stringify(node, semicolon) { + /* c8 ignore start */ + if (!this[node.type]) { + throw new Error( + 'Unknown AST node type ' + + node.type + + '. ' + + 'Maybe you need to change PostCSS stringifier.' + ) + } + /* c8 ignore stop */ + this[node.type](node, semicolon) + } +} + +module.exports = Stringifier +Stringifier.default = Stringifier diff --git a/node_modules/postcss/lib/stringify.d.ts b/node_modules/postcss/lib/stringify.d.ts new file mode 100644 index 0000000..06ad0b4 --- /dev/null +++ b/node_modules/postcss/lib/stringify.d.ts @@ -0,0 +1,9 @@ +import { Stringifier } from './postcss.js' + +interface Stringify extends Stringifier { + default: Stringify +} + +declare const stringify: Stringify + +export = stringify diff --git a/node_modules/postcss/lib/stringify.js b/node_modules/postcss/lib/stringify.js new file mode 100644 index 0000000..77bd017 --- /dev/null +++ b/node_modules/postcss/lib/stringify.js @@ -0,0 +1,11 @@ +'use strict' + +let Stringifier = require('./stringifier') + +function stringify(node, builder) { + let str = new Stringifier(builder) + str.stringify(node) +} + +module.exports = stringify +stringify.default = stringify diff --git a/node_modules/postcss/lib/symbols.js b/node_modules/postcss/lib/symbols.js new file mode 100644 index 0000000..a142c26 --- /dev/null +++ b/node_modules/postcss/lib/symbols.js @@ -0,0 +1,5 @@ +'use strict' + +module.exports.isClean = Symbol('isClean') + +module.exports.my = Symbol('my') diff --git a/node_modules/postcss/lib/terminal-highlight.js b/node_modules/postcss/lib/terminal-highlight.js new file mode 100644 index 0000000..6196c9d --- /dev/null +++ b/node_modules/postcss/lib/terminal-highlight.js @@ -0,0 +1,70 @@ +'use strict' + +let pico = require('picocolors') + +let tokenizer = require('./tokenize') + +let Input + +function registerInput(dependant) { + Input = dependant +} + +const HIGHLIGHT_THEME = { + ';': pico.yellow, + ':': pico.yellow, + '(': pico.cyan, + ')': pico.cyan, + '[': pico.yellow, + ']': pico.yellow, + '{': pico.yellow, + '}': pico.yellow, + 'at-word': pico.cyan, + 'brackets': pico.cyan, + 'call': pico.cyan, + 'class': pico.yellow, + 'comment': pico.gray, + 'hash': pico.magenta, + 'string': pico.green +} + +function getTokenType([type, value], processor) { + if (type === 'word') { + if (value[0] === '.') { + return 'class' + } + if (value[0] === '#') { + return 'hash' + } + } + + if (!processor.endOfFile()) { + let next = processor.nextToken() + processor.back(next) + if (next[0] === 'brackets' || next[0] === '(') return 'call' + } + + return type +} + +function terminalHighlight(css) { + let processor = tokenizer(new Input(css), { ignoreErrors: true }) + let result = '' + while (!processor.endOfFile()) { + let token = processor.nextToken() + let color = HIGHLIGHT_THEME[getTokenType(token, processor)] + if (color) { + result += token[1] + .split(/\r?\n/) + .map(i => color(i)) + .join('\n') + } else { + result += token[1] + } + } + return result +} + +terminalHighlight.registerInput = registerInput + +module.exports = terminalHighlight diff --git a/node_modules/postcss/lib/tokenize.js b/node_modules/postcss/lib/tokenize.js new file mode 100644 index 0000000..1d41284 --- /dev/null +++ b/node_modules/postcss/lib/tokenize.js @@ -0,0 +1,266 @@ +'use strict' + +const SINGLE_QUOTE = "'".charCodeAt(0) +const DOUBLE_QUOTE = '"'.charCodeAt(0) +const BACKSLASH = '\\'.charCodeAt(0) +const SLASH = '/'.charCodeAt(0) +const NEWLINE = '\n'.charCodeAt(0) +const SPACE = ' '.charCodeAt(0) +const FEED = '\f'.charCodeAt(0) +const TAB = '\t'.charCodeAt(0) +const CR = '\r'.charCodeAt(0) +const OPEN_SQUARE = '['.charCodeAt(0) +const CLOSE_SQUARE = ']'.charCodeAt(0) +const OPEN_PARENTHESES = '('.charCodeAt(0) +const CLOSE_PARENTHESES = ')'.charCodeAt(0) +const OPEN_CURLY = '{'.charCodeAt(0) +const CLOSE_CURLY = '}'.charCodeAt(0) +const SEMICOLON = ';'.charCodeAt(0) +const ASTERISK = '*'.charCodeAt(0) +const COLON = ':'.charCodeAt(0) +const AT = '@'.charCodeAt(0) + +const RE_AT_END = /[\t\n\f\r "#'()/;[\\\]{}]/g +const RE_WORD_END = /[\t\n\f\r !"#'():;@[\\\]{}]|\/(?=\*)/g +const RE_BAD_BRACKET = /.[\r\n"'(/\\]/ +const RE_HEX_ESCAPE = /[\da-f]/i + +module.exports = function tokenizer(input, options = {}) { + let css = input.css.valueOf() + let ignore = options.ignoreErrors + + let code, content, escape, next, quote + let currentToken, escaped, escapePos, n, prev + + let length = css.length + let pos = 0 + let buffer = [] + let returned = [] + + function position() { + return pos + } + + function unclosed(what) { + throw input.error('Unclosed ' + what, pos) + } + + function endOfFile() { + return returned.length === 0 && pos >= length + } + + function nextToken(opts) { + if (returned.length) return returned.pop() + if (pos >= length) return + + let ignoreUnclosed = opts ? opts.ignoreUnclosed : false + + code = css.charCodeAt(pos) + + switch (code) { + case NEWLINE: + case SPACE: + case TAB: + case CR: + case FEED: { + next = pos + do { + next += 1 + code = css.charCodeAt(next) + } while ( + code === SPACE || + code === NEWLINE || + code === TAB || + code === CR || + code === FEED + ) + + currentToken = ['space', css.slice(pos, next)] + pos = next - 1 + break + } + + case OPEN_SQUARE: + case CLOSE_SQUARE: + case OPEN_CURLY: + case CLOSE_CURLY: + case COLON: + case SEMICOLON: + case CLOSE_PARENTHESES: { + let controlChar = String.fromCharCode(code) + currentToken = [controlChar, controlChar, pos] + break + } + + case OPEN_PARENTHESES: { + prev = buffer.length ? buffer.pop()[1] : '' + n = css.charCodeAt(pos + 1) + if ( + prev === 'url' && + n !== SINGLE_QUOTE && + n !== DOUBLE_QUOTE && + n !== SPACE && + n !== NEWLINE && + n !== TAB && + n !== FEED && + n !== CR + ) { + next = pos + do { + escaped = false + next = css.indexOf(')', next + 1) + if (next === -1) { + if (ignore || ignoreUnclosed) { + next = pos + break + } else { + unclosed('bracket') + } + } + escapePos = next + while (css.charCodeAt(escapePos - 1) === BACKSLASH) { + escapePos -= 1 + escaped = !escaped + } + } while (escaped) + + currentToken = ['brackets', css.slice(pos, next + 1), pos, next] + + pos = next + } else { + next = css.indexOf(')', pos + 1) + content = css.slice(pos, next + 1) + + if (next === -1 || RE_BAD_BRACKET.test(content)) { + currentToken = ['(', '(', pos] + } else { + currentToken = ['brackets', content, pos, next] + pos = next + } + } + + break + } + + case SINGLE_QUOTE: + case DOUBLE_QUOTE: { + quote = code === SINGLE_QUOTE ? "'" : '"' + next = pos + do { + escaped = false + next = css.indexOf(quote, next + 1) + if (next === -1) { + if (ignore || ignoreUnclosed) { + next = pos + 1 + break + } else { + unclosed('string') + } + } + escapePos = next + while (css.charCodeAt(escapePos - 1) === BACKSLASH) { + escapePos -= 1 + escaped = !escaped + } + } while (escaped) + + currentToken = ['string', css.slice(pos, next + 1), pos, next] + pos = next + break + } + + case AT: { + RE_AT_END.lastIndex = pos + 1 + RE_AT_END.test(css) + if (RE_AT_END.lastIndex === 0) { + next = css.length - 1 + } else { + next = RE_AT_END.lastIndex - 2 + } + + currentToken = ['at-word', css.slice(pos, next + 1), pos, next] + + pos = next + break + } + + case BACKSLASH: { + next = pos + escape = true + while (css.charCodeAt(next + 1) === BACKSLASH) { + next += 1 + escape = !escape + } + code = css.charCodeAt(next + 1) + if ( + escape && + code !== SLASH && + code !== SPACE && + code !== NEWLINE && + code !== TAB && + code !== CR && + code !== FEED + ) { + next += 1 + if (RE_HEX_ESCAPE.test(css.charAt(next))) { + while (RE_HEX_ESCAPE.test(css.charAt(next + 1))) { + next += 1 + } + if (css.charCodeAt(next + 1) === SPACE) { + next += 1 + } + } + } + + currentToken = ['word', css.slice(pos, next + 1), pos, next] + + pos = next + break + } + + default: { + if (code === SLASH && css.charCodeAt(pos + 1) === ASTERISK) { + next = css.indexOf('*/', pos + 2) + 1 + if (next === 0) { + if (ignore || ignoreUnclosed) { + next = css.length + } else { + unclosed('comment') + } + } + + currentToken = ['comment', css.slice(pos, next + 1), pos, next] + pos = next + } else { + RE_WORD_END.lastIndex = pos + 1 + RE_WORD_END.test(css) + if (RE_WORD_END.lastIndex === 0) { + next = css.length - 1 + } else { + next = RE_WORD_END.lastIndex - 2 + } + + currentToken = ['word', css.slice(pos, next + 1), pos, next] + buffer.push(currentToken) + pos = next + } + + break + } + } + + pos++ + return currentToken + } + + function back(token) { + returned.push(token) + } + + return { + back, + endOfFile, + nextToken, + position + } +} diff --git a/node_modules/postcss/lib/warn-once.js b/node_modules/postcss/lib/warn-once.js new file mode 100644 index 0000000..316e1cf --- /dev/null +++ b/node_modules/postcss/lib/warn-once.js @@ -0,0 +1,13 @@ +/* eslint-disable no-console */ +'use strict' + +let printed = {} + +module.exports = function warnOnce(message) { + if (printed[message]) return + printed[message] = true + + if (typeof console !== 'undefined' && console.warn) { + console.warn(message) + } +} diff --git a/node_modules/postcss/lib/warning.d.ts b/node_modules/postcss/lib/warning.d.ts new file mode 100644 index 0000000..b25bba8 --- /dev/null +++ b/node_modules/postcss/lib/warning.d.ts @@ -0,0 +1,147 @@ +import { RangePosition } from './css-syntax-error.js' +import Node from './node.js' + +declare namespace Warning { + export interface WarningOptions { + /** + * End position, exclusive, in CSS node string that caused the warning. + */ + end?: RangePosition + + /** + * End index, exclusive, in CSS node string that caused the warning. + */ + endIndex?: number + + /** + * Start index, inclusive, in CSS node string that caused the warning. + */ + index?: number + + /** + * CSS node that caused the warning. + */ + node?: Node + + /** + * Name of the plugin that created this warning. `Result#warn` fills + * this property automatically. + */ + plugin?: string + + /** + * Start position, inclusive, in CSS node string that caused the warning. + */ + start?: RangePosition + + /** + * Word in CSS source that caused the warning. + */ + word?: string + } + + // eslint-disable-next-line @typescript-eslint/no-use-before-define + export { Warning_ as default } +} + +/** + * Represents a plugin’s warning. It can be created using `Node#warn`. + * + * ```js + * if (decl.important) { + * decl.warn(result, 'Avoid !important', { word: '!important' }) + * } + * ``` + */ +declare class Warning_ { + /** + * Column for inclusive start position in the input file with this warning’s source. + * + * ```js + * warning.column //=> 6 + * ``` + */ + column: number + + /** + * Column for exclusive end position in the input file with this warning’s source. + * + * ```js + * warning.endColumn //=> 4 + * ``` + */ + endColumn?: number + + /** + * Line for exclusive end position in the input file with this warning’s source. + * + * ```js + * warning.endLine //=> 6 + * ``` + */ + endLine?: number + + /** + * Line for inclusive start position in the input file with this warning’s source. + * + * ```js + * warning.line //=> 5 + * ``` + */ + line: number + + /** + * Contains the CSS node that caused the warning. + * + * ```js + * warning.node.toString() //=> 'color: white !important' + * ``` + */ + node: Node + + /** + * The name of the plugin that created this warning. + * When you call `Node#warn` it will fill this property automatically. + * + * ```js + * warning.plugin //=> 'postcss-important' + * ``` + */ + plugin: string + + /** + * The warning message. + * + * ```js + * warning.text //=> 'Try to avoid !important' + * ``` + */ + text: string + + /** + * Type to filter warnings from `Result#messages`. + * Always equal to `"warning"`. + */ + type: 'warning' + + /** + * @param text Warning message. + * @param opts Warning options. + */ + constructor(text: string, opts?: Warning.WarningOptions) + + /** + * Returns a warning position and message. + * + * ```js + * warning.toString() //=> 'postcss-lint:a.css:10:14: Avoid !important' + * ``` + * + * @return Warning position and message. + */ + toString(): string +} + +declare class Warning extends Warning_ {} + +export = Warning diff --git a/node_modules/postcss/lib/warning.js b/node_modules/postcss/lib/warning.js new file mode 100644 index 0000000..3a3d79c --- /dev/null +++ b/node_modules/postcss/lib/warning.js @@ -0,0 +1,37 @@ +'use strict' + +class Warning { + constructor(text, opts = {}) { + this.type = 'warning' + this.text = text + + if (opts.node && opts.node.source) { + let range = opts.node.rangeBy(opts) + this.line = range.start.line + this.column = range.start.column + this.endLine = range.end.line + this.endColumn = range.end.column + } + + for (let opt in opts) this[opt] = opts[opt] + } + + toString() { + if (this.node) { + return this.node.error(this.text, { + index: this.index, + plugin: this.plugin, + word: this.word + }).message + } + + if (this.plugin) { + return this.plugin + ': ' + this.text + } + + return this.text + } +} + +module.exports = Warning +Warning.default = Warning diff --git a/node_modules/postcss/package.json b/node_modules/postcss/package.json new file mode 100644 index 0000000..25170ba --- /dev/null +++ b/node_modules/postcss/package.json @@ -0,0 +1,88 @@ +{ + "name": "postcss", + "version": "8.4.45", + "description": "Tool for transforming styles with JS plugins", + "engines": { + "node": "^10 || ^12 || >=14" + }, + "exports": { + ".": { + "require": "./lib/postcss.js", + "import": "./lib/postcss.mjs" + }, + "./lib/at-rule": "./lib/at-rule.js", + "./lib/comment": "./lib/comment.js", + "./lib/container": "./lib/container.js", + "./lib/css-syntax-error": "./lib/css-syntax-error.js", + "./lib/declaration": "./lib/declaration.js", + "./lib/fromJSON": "./lib/fromJSON.js", + "./lib/input": "./lib/input.js", + "./lib/lazy-result": "./lib/lazy-result.js", + "./lib/no-work-result": "./lib/no-work-result.js", + "./lib/list": "./lib/list.js", + "./lib/map-generator": "./lib/map-generator.js", + "./lib/node": "./lib/node.js", + "./lib/parse": "./lib/parse.js", + "./lib/parser": "./lib/parser.js", + "./lib/postcss": "./lib/postcss.js", + "./lib/previous-map": "./lib/previous-map.js", + "./lib/processor": "./lib/processor.js", + "./lib/result": "./lib/result.js", + "./lib/root": "./lib/root.js", + "./lib/rule": "./lib/rule.js", + "./lib/stringifier": "./lib/stringifier.js", + "./lib/stringify": "./lib/stringify.js", + "./lib/symbols": "./lib/symbols.js", + "./lib/terminal-highlight": "./lib/terminal-highlight.js", + "./lib/tokenize": "./lib/tokenize.js", + "./lib/warn-once": "./lib/warn-once.js", + "./lib/warning": "./lib/warning.js", + "./package.json": "./package.json" + }, + "main": "./lib/postcss.js", + "types": "./lib/postcss.d.ts", + "keywords": [ + "css", + "postcss", + "rework", + "preprocessor", + "parser", + "source map", + "transform", + "manipulation", + "transpiler" + ], + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "author": "Andrey Sitnik ", + "license": "MIT", + "homepage": "https://postcss.org/", + "repository": "postcss/postcss", + "bugs": { + "url": "https://github.com/postcss/postcss/issues" + }, + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" + }, + "browser": { + "./lib/terminal-highlight": false, + "source-map-js": false, + "path": false, + "url": false, + "fs": false + } +} diff --git a/node_modules/rollup/LICENSE.md b/node_modules/rollup/LICENSE.md new file mode 100644 index 0000000..ce44fa2 --- /dev/null +++ b/node_modules/rollup/LICENSE.md @@ -0,0 +1,653 @@ +# Rollup core license +Rollup is released under the MIT license: + +The MIT License (MIT) + +Copyright (c) 2017 [these people](https://github.com/rollup/rollup/graphs/contributors) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# Licenses of bundled dependencies +The published Rollup artifact additionally contains code with the following licenses: +MIT, ISC + +# Bundled dependencies: +## @jridgewell/sourcemap-codec +License: MIT +By: Rich Harris +Repository: git+https://github.com/jridgewell/sourcemap-codec.git + +> The MIT License +> +> Copyright (c) 2015 Rich Harris +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. + +--------------------------------------- + +## @rollup/pluginutils +License: MIT +By: Rich Harris +Repository: rollup/plugins + +> The MIT License (MIT) +> +> Copyright (c) 2019 RollupJS Plugin Contributors (https://github.com/rollup/plugins/graphs/contributors) +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. + +--------------------------------------- + +## anymatch +License: ISC +By: Elan Shanker +Repository: https://github.com/micromatch/anymatch + +> The ISC License +> +> Copyright (c) 2019 Elan Shanker, Paul Miller (https://paulmillr.com) +> +> Permission to use, copy, modify, and/or distribute this software for any +> purpose with or without fee is hereby granted, provided that the above +> copyright notice and this permission notice appear in all copies. +> +> THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +> WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +> MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +> ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +> WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +> ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +> IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +--------------------------------------- + +## binary-extensions +License: MIT +By: Sindre Sorhus +Repository: sindresorhus/binary-extensions + +> MIT License +> +> Copyright (c) Sindre Sorhus (https://sindresorhus.com) +> Copyright (c) Paul Miller (https://paulmillr.com) +> +> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------- + +## braces +License: MIT +By: Jon Schlinkert, Brian Woodward, Elan Shanker, Eugene Sharygin, hemanth.hm +Repository: micromatch/braces + +> The MIT License (MIT) +> +> Copyright (c) 2014-present, Jon Schlinkert. +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. + +--------------------------------------- + +## builtin-modules +License: MIT +By: Sindre Sorhus +Repository: sindresorhus/builtin-modules + +> MIT License +> +> Copyright (c) Sindre Sorhus (https://sindresorhus.com) +> +> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------- + +## chokidar +License: MIT +By: Paul Miller, Elan Shanker +Repository: git+https://github.com/paulmillr/chokidar.git + +> The MIT License (MIT) +> +> Copyright (c) 2012-2019 Paul Miller (https://paulmillr.com), Elan Shanker +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the “Software”), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. + +--------------------------------------- + +## colorette +License: MIT +By: Jorge Bucaran +Repository: jorgebucaran/colorette + +> Copyright © Jorge Bucaran <> +> +> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------- + +## date-time +License: MIT +By: Sindre Sorhus +Repository: sindresorhus/date-time + +> MIT License +> +> Copyright (c) Sindre Sorhus (https://sindresorhus.com) +> +> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------- + +## fill-range +License: MIT +By: Jon Schlinkert, Edo Rivai, Paul Miller, Rouven Weßling +Repository: jonschlinkert/fill-range + +> The MIT License (MIT) +> +> Copyright (c) 2014-present, Jon Schlinkert. +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. + +--------------------------------------- + +## flru +License: MIT +By: Luke Edwards +Repository: lukeed/flru + +> MIT License +> +> Copyright (c) Luke Edwards (lukeed.com) +> +> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------- + +## glob-parent +License: ISC +By: Gulp Team, Elan Shanker, Blaine Bublitz +Repository: gulpjs/glob-parent + +> The ISC License +> +> Copyright (c) 2015, 2019 Elan Shanker +> +> Permission to use, copy, modify, and/or distribute this software for any +> purpose with or without fee is hereby granted, provided that the above +> copyright notice and this permission notice appear in all copies. +> +> THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +> WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +> MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +> ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +> WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +> ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +> IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +--------------------------------------- + +## is-binary-path +License: MIT +By: Sindre Sorhus +Repository: sindresorhus/is-binary-path + +> MIT License +> +> Copyright (c) 2019 Sindre Sorhus (https://sindresorhus.com), Paul Miller (https://paulmillr.com) +> +> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------- + +## is-extglob +License: MIT +By: Jon Schlinkert +Repository: jonschlinkert/is-extglob + +> The MIT License (MIT) +> +> Copyright (c) 2014-2016, Jon Schlinkert +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. + +--------------------------------------- + +## is-glob +License: MIT +By: Jon Schlinkert, Brian Woodward, Daniel Perez +Repository: micromatch/is-glob + +> The MIT License (MIT) +> +> Copyright (c) 2014-2017, Jon Schlinkert. +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. + +--------------------------------------- + +## is-number +License: MIT +By: Jon Schlinkert, Olsten Larck, Rouven Weßling +Repository: jonschlinkert/is-number + +> The MIT License (MIT) +> +> Copyright (c) 2014-present, Jon Schlinkert. +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. + +--------------------------------------- + +## is-reference +License: MIT +By: Rich Harris +Repository: git+https://github.com/Rich-Harris/is-reference.git + +--------------------------------------- + +## locate-character +License: MIT +By: Rich Harris +Repository: git+https://gitlab.com/Rich-Harris/locate-character.git + +--------------------------------------- + +## magic-string +License: MIT +By: Rich Harris +Repository: https://github.com/rich-harris/magic-string + +> Copyright 2018 Rich Harris +> +> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------- + +## normalize-path +License: MIT +By: Jon Schlinkert, Blaine Bublitz +Repository: jonschlinkert/normalize-path + +> The MIT License (MIT) +> +> Copyright (c) 2014-2018, Jon Schlinkert. +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. + +--------------------------------------- + +## parse-ms +License: MIT +By: Sindre Sorhus +Repository: sindresorhus/parse-ms + +> MIT License +> +> Copyright (c) Sindre Sorhus (https://sindresorhus.com) +> +> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------- + +## picomatch +License: MIT +By: Jon Schlinkert +Repository: micromatch/picomatch + +> The MIT License (MIT) +> +> Copyright (c) 2017-present, Jon Schlinkert. +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. + +--------------------------------------- + +## pretty-bytes +License: MIT +By: Sindre Sorhus +Repository: sindresorhus/pretty-bytes + +> MIT License +> +> Copyright (c) Sindre Sorhus (https://sindresorhus.com) +> +> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------- + +## pretty-ms +License: MIT +By: Sindre Sorhus +Repository: sindresorhus/pretty-ms + +> MIT License +> +> Copyright (c) Sindre Sorhus (https://sindresorhus.com) +> +> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------- + +## readdirp +License: MIT +By: Thorsten Lorenz, Paul Miller +Repository: git://github.com/paulmillr/readdirp.git + +> MIT License +> +> Copyright (c) 2012-2019 Thorsten Lorenz, Paul Miller (https://paulmillr.com) +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all +> copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +> SOFTWARE. + +--------------------------------------- + +## signal-exit +License: ISC +By: Ben Coe +Repository: https://github.com/tapjs/signal-exit.git + +> The ISC License +> +> Copyright (c) 2015-2023 Benjamin Coe, Isaac Z. Schlueter, and Contributors +> +> Permission to use, copy, modify, and/or distribute this software +> for any purpose with or without fee is hereby granted, provided +> that the above copyright notice and this permission notice +> appear in all copies. +> +> THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +> WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +> OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE +> LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +> OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +> WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +> ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +--------------------------------------- + +## time-zone +License: MIT +By: Sindre Sorhus +Repository: sindresorhus/time-zone + +> MIT License +> +> Copyright (c) Sindre Sorhus (https://sindresorhus.com) +> +> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------- + +## to-regex-range +License: MIT +By: Jon Schlinkert, Rouven Weßling +Repository: micromatch/to-regex-range + +> The MIT License (MIT) +> +> Copyright (c) 2015-present, Jon Schlinkert. +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. + +--------------------------------------- + +## yargs-parser +License: ISC +By: Ben Coe +Repository: https://github.com/yargs/yargs-parser.git + +> Copyright (c) 2016, Contributors +> +> Permission to use, copy, modify, and/or distribute this software +> for any purpose with or without fee is hereby granted, provided +> that the above copyright notice and this permission notice +> appear in all copies. +> +> THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +> WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +> OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE +> LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +> OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +> WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +> ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/node_modules/rollup/README.md b/node_modules/rollup/README.md new file mode 100644 index 0000000..a1b6b9e --- /dev/null +++ b/node_modules/rollup/README.md @@ -0,0 +1,134 @@ +

+ +

+ +

+ + npm version + + + node compatibility + + + install size + + + code coverage + + + backers + + + sponsors + + + license + + + Join the chat at https://is.gd/rollup_chat + +

+ +

Rollup

+ +## Overview + +Rollup is a module bundler for JavaScript which compiles small pieces of code into something larger and more complex, such as a library or application. It uses the standardized ES module format for code, instead of previous idiosyncratic solutions such as CommonJS and AMD. ES modules let you freely and seamlessly combine the most useful individual functions from your favorite libraries. Rollup can optimize ES modules for faster native loading in modern browsers, or output a legacy module format allowing ES module workflows today. + +## Quick Start Guide + +Install with `npm install --global rollup`. Rollup can be used either through a [command line interface](https://rollupjs.org/command-line-interface/) with an optional configuration file or else through its [JavaScript API](https://rollupjs.org/javascript-api/). Run `rollup --help` to see the available options and parameters. The starter project templates, [rollup-starter-lib](https://github.com/rollup/rollup-starter-lib) and [rollup-starter-app](https://github.com/rollup/rollup-starter-app), demonstrate common configuration options, and more detailed instructions are available throughout the [user guide](https://rollupjs.org/introduction/). + +### Commands + +These commands assume the entry point to your application is named main.js, and that you'd like all imports compiled into a single file named bundle.js. + +For browsers: + +```bash +# compile to a ` +- In-browser playground on [CodeSandbox](https://codesandbox.io/s/vue-router-4-reproduction-hb9lh) +- Add it to an existing Vue Project: + + ```bash + npm install vue-router@4 + ``` + +## Changes from Vue Router 3 + +Please consult the [Migration Guide](https://router.vuejs.org/guide/migration/). + +## Contributing + +See [Contributing Guide](https://github.com/vuejs/router/blob/main/.github/contributing.md). + +## Special Thanks + + + BrowserStack Logo + + +Special thanks to [BrowserStack](https://www.browserstack.com) for letting the maintainers use their service to debug browser specific issues. diff --git a/node_modules/vue-router/dist/vue-router.cjs b/node_modules/vue-router/dist/vue-router.cjs new file mode 100644 index 0000000..824f9e1 --- /dev/null +++ b/node_modules/vue-router/dist/vue-router.cjs @@ -0,0 +1,3764 @@ +/*! + * vue-router v4.4.5 + * (c) 2024 Eduardo San Martin Morote + * @license MIT + */ +'use strict'; + +var vue = require('vue'); +var devtoolsApi = require('@vue/devtools-api'); + +const isBrowser = typeof document !== 'undefined'; + +/** + * 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' || + // support CF with dynamic imports that do not + // add the Module string tag + (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 warn(msg) { + // avoid using ...args as it breaks in older Edge builds + const args = Array.from(arguments).slice(1); + console.warn.apply(console, ['[Vue Router warn]: ' + msg].concat(args)); +} + +/** + * 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; // %23 +const AMPERSAND_RE = /&/g; // %26 +const SLASH_RE = /\//g; // %2F +const EQUAL_RE = /=/g; // %3D +const IM_RE = /\?/g; // %3F +const 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) { + warn(`Error decoding "${text}". Using original value`); + } + return '' + text; +} + +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: decode(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 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, 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 (!from.startsWith('/')) { + warn(`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]; + // make . and ./ the same (../ === .., ../../ === ../..) + // this is the same behavior as new URL() + if (lastToSegment === '..' || lastToSegment === '.') { + toSegments.push(''); + } + 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.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: '/', + // TODO: could we use a symbol in the future? + name: undefined, + params: {}, + query: {}, + hash: '', + fullPath: '/', + matched: [], + meta: {}, + redirectedFrom: undefined, +}; + +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 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 hash +const 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.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 (typeof position.el === 'string') { + if (!isIdSelector || !document.getElementById(position.el.slice(1))) { + try { + const foundEl = document.querySelector(position.el); + if (isIdSelector && foundEl) { + warn(`The selector "${position.el}" should be passed as "el: document.querySelector('${position.el}')" because it starts with "#".`); + // return to avoid other warnings + return; + } + } + catch (err) { + warn(`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 to avoid other warnings + return; + } + } + } + const el = typeof positionEl === 'string' + ? isIdSelector + ? document.getElementById(positionEl.slice(1)) + : document.querySelector(positionEl) + : positionEl; + if (!el) { + warn(`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) { + 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 { +// // 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 = { +// compute: computeScroll, +// scroll: scrollToPosition, +// } + +let createBaseLocation = () => location.protocol + '//' + location.host; +/** + * Creates a normalized history location from a window.location object + * @param base - The base path + * @param location - The window.location object + */ +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); + } + // 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); + // TODO: could we use 'pagehide' or 'visibilitychange' instead? + // https://developer.chrome.com/blog/page-lifecycle-api/ + window.addEventListener('beforeunload', beforeUnloadListener, { + passive: true, + }); + 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 `` 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) { + { + warn('Error with push/replace State', 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(), + }); + if (!history.state) { + warn(`history.state seems to have been manually replaced without preserving the necessary values. Make sure to preserve existing history state if you are manually calling history.replaceState:\n\n` + + `history.replaceState(history.state, '', url)\n\n` + + `You can find more information at https://router.vuejs.org/guide/migration/#Usage-of-history-state`); + } + 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 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 `` 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 `` 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 += '#'; + if (!base.endsWith('#/') && !base.endsWith('#')) { + warn(`A hash base must end with a "#":\n"${base}" should be "${base.replace(/#.*$/, '#')}".`); + } + return createWebHistory(base); +} + +function isRouteLocation(route) { + return typeof route === 'string' || (route && typeof route === 'object'); +} +function isRouteName(name) { + return typeof name === 'string' || typeof name === 'symbol'; +} + +const NavigationFailureSymbol = Symbol('navigation failure' ); +/** + * 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 messages +const 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}".`; + }, +}; +/** + * Creates a typed NavigationFailure object. + * @internal + * @param type - NavigationFailureType + * @param params - { from, to } + */ +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 (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); +} + +// 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 tokens +const 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() +function tokenizePath(path) { + if (!path) + return [[]]; + if (path === '/') + return [[ROOT_TOKEN]]; + if (!path.startsWith('/')) { + throw new Error(`Route paths should start with a "/": "${path}" should be "/${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); + // warn against params with the same name + { + const existingKeys = new Set(); + for (const key of parser.keys) { + if (existingKeys.has(key.name)) + warn(`Found duplicated params with name "${key.name}" for path "${record.path}". Only the last one will be available on "$route.params".`); + existingKeys.add(key.name); + } + } + 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); + { + checkChildMissingNameWithEmptyPath(mainNormalizedRecord, parent); + } + // 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( + // we need to normalize again to ensure the `mods` property + // being non enumerable + normalizeRouteRecord(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); + } + if (normalizedRecord.path === '*') { + throw new Error('Catch all routes ("*") must now be defined using a param with a custom regexp.\n' + + 'See more at https://router.vuejs.org/guide/migration/#Removed-star-or-catch-all-routes.'); + } + // create the object beforehand, so it can be passed to children + matcher = createRouteRecordMatcher(normalizedRecord, parent, options); + if (parent && path[0] === '/') + checkMissingParamsInAbsolutePath(matcher, parent); + // 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); + { + checkSameParams(originalRecord, 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); + } + // 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 (isMatchable(matcher)) { + insertMatcher(matcher); + } + 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) + // } + } + 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) { + const index = findInsertionIndex(matcher, matchers); + matchers.splice(index, 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, + }); + // warn if the user is passing invalid params so they can debug it better when they get removed + { + const invalidParams = Object.keys(location.params || {}).filter(paramName => !matcher.keys.find(k => k.name === paramName)); + if (invalidParams.length) { + warn(`Discarded invalid param(s) "${invalidParams.join('", "')}" when navigating. See https://github.com/vuejs/router/blob/main/packages/router/CHANGELOG.md#414-2022-08-22 for more details.`); + } + } + name = matcher.record.name; + params = assign( + // paramsFromLocation is a new object + paramsFromLocation(currentLocation.params, + // only keep params that exist in the resolved location + // only keep optional params coming from a parent record + matcher.keys + .filter(k => !k.optional) + .concat(matcher.parent ? matcher.parent.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 (location.path != null) { + // 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; + if (!path.startsWith('/')) { + warn(`The Matcher cannot resolve relative paths but received "${path}". Unless you directly called \`matcher.resolve("${path}")\`, this is probably a bug in vue-router. Please open an issue at https://github.com/vuejs/router/issues/new/choose.`); + } + 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)); + function clearRoutes() { + matchers.length = 0; + matcherMap.clear(); + } + return { + addRoute, + resolve, + removeRoute, + clearRoutes, + 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) { + const normalized = { + path: record.path, + redirect: record.redirect, + name: record.name, + meta: record.meta || {}, + aliasOf: record.aliasOf, + beforeEnter: record.beforeEnter, + props: normalizeRecordProps(record), + children: record.children || [], + instances: {}, + leaveGuards: new Set(), + updateGuards: new Set(), + enterCallbacks: {}, + // must be declared afterwards + // mods: {}, + components: 'components' in record + ? record.components || null + : record.component && { default: record.component }, + }; + // mods contain modules and shouldn't be copied, + // logged or anything. It's just used for internal + // advanced use cases like data loaders + Object.defineProperty(normalized, 'mods', { + value: {}, + }); + return normalized; +} +/** + * 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 === 'object' ? props[name] : props; + } + 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 isSameParam(a, b) { + return (a.name === b.name && + a.optional === b.optional && + a.repeatable === b.repeatable); +} +/** + * Check if a path and its alias have the same required params + * + * @param a - original record + * @param b - alias record + */ +function checkSameParams(a, b) { + for (const key of a.keys) { + if (!key.optional && !b.keys.find(isSameParam.bind(null, key))) + return warn(`Alias "${b.record.path}" and the original record: "${a.record.path}" must have the exact same param named "${key.name}"`); + } + for (const key of b.keys) { + if (!key.optional && !a.keys.find(isSameParam.bind(null, key))) + return warn(`Alias "${b.record.path}" and the original record: "${a.record.path}" must have the exact same param named "${key.name}"`); + } +} +/** + * A route with a name and a child with an empty path without a name should warn when adding the route + * + * @param mainNormalizedRecord - RouteRecordNormalized + * @param parent - RouteRecordMatcher + */ +function checkChildMissingNameWithEmptyPath(mainNormalizedRecord, parent) { + if (parent && + parent.record.name && + !mainNormalizedRecord.name && + !mainNormalizedRecord.path) { + warn(`The route named "${String(parent.record.name)}" has a child without a name and an empty path. Using that name won't render the empty path child so you probably want to move the name to the child instead. If this is intentional, add a name to the child route to remove the warning.`); + } +} +function checkMissingParamsInAbsolutePath(record, parent) { + for (const key of parent.keys) { + if (!record.keys.find(isSameParam.bind(null, key))) + return warn(`Absolute path "${record.record.path}" must have the exact same param named "${key.name}" as its parent "${parent.record.path}".`); + } +} +/** + * Performs a binary search to find the correct insertion index for a new matcher. + * + * Matchers are primarily sorted by their score. If scores are tied then we also consider parent/child relationships, + * with descendants coming before ancestors. If there's still a tie, new routes are inserted after existing routes. + * + * @param matcher - new matcher to be inserted + * @param matchers - existing matchers + */ +function findInsertionIndex(matcher, matchers) { + // First phase: binary search based on score + let lower = 0; + let upper = matchers.length; + while (lower !== upper) { + const mid = (lower + upper) >> 1; + const sortOrder = comparePathParserScore(matcher, matchers[mid]); + if (sortOrder < 0) { + upper = mid; + } + else { + lower = mid + 1; + } + } + // Second phase: check for an ancestor with the same score + const insertionAncestor = getInsertionAncestor(matcher); + if (insertionAncestor) { + upper = matchers.lastIndexOf(insertionAncestor, upper - 1); + if (upper < 0) { + // This should never happen + warn(`Finding ancestor route "${insertionAncestor.record.path}" failed for "${matcher.record.path}"`); + } + } + return upper; +} +function getInsertionAncestor(matcher) { + let ancestor = matcher; + while ((ancestor = ancestor.parent)) { + if (isMatchable(ancestor) && + comparePathParserScore(matcher, ancestor) === 0) { + return ancestor; + } + } + return; +} +/** + * Checks if a matcher can be reachable. This means if it's possible to reach it as a route. For example, routes without + * a component, or name, or redirect, are just used to group other routes. + * @param matcher + * @param matcher.record record of the matcher + * @returns + */ +function isMatchable({ record }) { + return !!(record.name || + (record.components && Object.keys(record.components).length) || + record.redirect); +} + +/** + * 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('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('router view depth' ); +/** + * Allows overriding the router instance returned by `useRouter` in tests. r + * stands for router + * + * @internal + */ +const routerKey = Symbol('router' ); +/** + * Allows overriding the current route returned by `useRoute` in tests. rl + * stands for route location + * + * @internal + */ +const routeLocationKey = Symbol('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('router view location' ); + +/** + * 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, + }; +} + +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) { + if (!vue.getCurrentInstance()) { + warn('getCurrentInstance() returned null. onBeforeRouteLeave() must be called at the top of a setup function'); + return; + } + const activeRecord = vue.inject(matchedRouteKey, + // to avoid warning + {}).value; + if (!activeRecord) { + warn('No active route record was found when calling `onBeforeRouteLeave()`. Make sure you call this function inside a component child of . 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 (!vue.getCurrentInstance()) { + warn('getCurrentInstance() returned null. onBeforeRouteUpdate() must be called at the top of a setup function'); + return; + } + const activeRecord = vue.inject(matchedRouteKey, + // to avoid warning + {}).value; + if (!activeRecord) { + warn('No active route record was found when calling `onBeforeRouteUpdate()`. Make sure you call this function inside a component child of . Maybe you called it inside of App.vue?'); + return; + } + registerGuard(activeRecord, 'updateGuards', updateGuard); +} +function guardToPromiseFn(guard, to, from, record, name, runWithContext = fn => fn()) { + // 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 = runWithContext(() => guard.call(record && record.instances[name], to, from, canOnlyBeCalledOnce(next, to, from) )); + let guardCall = Promise.resolve(guardReturn); + if (guard.length < 3) + guardCall = guardCall.then(next); + if (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 => { + // @ts-expect-error: _called is added at canOnlyBeCalledOnce + if (!next._called) { + warn(message); + return Promise.reject(new Error('Invalid navigation guard')); + } + return resolvedValue; + }); + } + else if (guardReturn !== undefined) { + // @ts-expect-error: _called is added at canOnlyBeCalledOnce + if (!next._called) { + warn(message); + reject(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(`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.`); + // @ts-expect-error: we put it in the original one because it's easier to check + 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 (!record.components && !record.children.length) { + warn(`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 (!rawComponent || + (typeof rawComponent !== 'object' && + typeof rawComponent !== 'function')) { + warn(`Component "${name}" in record with path "${record.path}" is not` + + ` a valid component. Received "${String(rawComponent)}".`); + // throw to ensure we stop here but warn to ensure the message isn't + // missed by the user + throw new Error('Invalid route component'); + } + else if ('then' in rawComponent) { + // warn if user wrote import('/component.vue') instead of () => + // import('./component.vue') + warn(`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 && + // warn only once per component + !rawComponent.__warnedDefineAsync) { + rawComponent.__warnedDefineAsync = true; + warn(`Component "${name}" in record with path "${record.path}" is defined ` + + `using "defineAsyncComponent()". ` + + `Write "() => import('./MyPage.vue')" instead of ` + + `"defineAsyncComponent(() => import('./MyPage.vue'))".`); + } + } + // 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, runWithContext)); + } + else { + // start requesting the chunk already + let componentPromise = rawComponent(); + if (!('catch' in componentPromise)) { + warn(`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; + // keep the resolved module for plugins like data loaders + record.mods[name] = 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, runWithContext)()); + })); + } + } + } + return guards; +} +/** + * Ensures a route is loaded, so it can be passed as o prop to ``. + * + * @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; + // keep the resolved module for plugins like data loaders + record.mods[name] = 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 RFC +/** + * Returns the internal behavior of a {@link RouterLink} without the rendering part. + * + * @param props - a `to` location and an optional `replace` flag + */ +function useLink(props) { + const router = vue.inject(routerKey); + const currentRoute = vue.inject(routeLocationKey); + let hasPrevious = false; + let previousTo = null; + const route = vue.computed(() => { + const to = vue.unref(props.to); + if ((!hasPrevious || to !== previousTo)) { + if (!isRouteLocation(to)) { + if (hasPrevious) { + warn(`Invalid value for prop "to" in useLink()\n- to:`, to, `\n- previous to:`, previousTo, `\n- props:`, props); + } + else { + warn(`Invalid value for prop "to" in useLink()\n- to:`, to, `\n- props:`, props); + } + } + previousTo = to; + hasPrevious = true; + } + return router.resolve(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(); + } + // devtools only + if (isBrowser) { + const instance = vue.getCurrentInstance(); + if (instance) { + const linkContextDevtools = { + route: route.value, + isActive: isActive.value, + isExactActive: isExactActive.value, + error: null, + }; + // @ts-expect-error: this is internal + instance.__vrl_devtools = instance.__vrl_devtools || []; + // @ts-expect-error: this is internal + instance.__vrl_devtools.push(linkContextDevtools); + vue.watchEffect(() => { + linkContextDevtools.route = route.value; + linkContextDevtools.isActive = isActive.value; + linkContextDevtools.isExactActive = isExactActive.value; + linkContextDevtools.error = isRouteLocation(vue.unref(props.to)) + ? null + : 'Invalid "to" value'; + }, { flush: 'post' }); + } + } + /** + * 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 }) { + warnDeprecatedUsage(); + 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, + })); + if (isBrowser && + component.ref) { + // TODO: can display if it's an alias, its props + const info = { + depth: depth.value, + name: matchedRoute.name, + path: matchedRoute.path, + meta: matchedRoute.meta, + }; + const internalInstances = isArray(component.ref) + ? component.ref.map(r => r.i) + : [component.ref.i]; + internalInstances.forEach(instance => { + // @ts-expect-error + instance.__vrv_devtools = info; + }); + } + return ( + // pass the vnode to the slot as a prop. + // h and 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; +// warn against deprecated usage with & +// due to functional component being no longer eager in Vue 3 +function warnDeprecatedUsage() { + const instance = vue.getCurrentInstance(); + const parentName = instance.parent && instance.parent.type.name; + const parentSubTreeType = instance.parent && instance.parent.subTree && instance.parent.subTree.type; + if (parentName && + (parentName === 'KeepAlive' || parentName.includes('Transition')) && + typeof parentSubTreeType === 'object' && + parentSubTreeType.name === 'RouterView') { + const comp = parentName === 'KeepAlive' ? 'keep-alive' : 'transition'; + warn(` can no longer be used directly inside or .\n` + + `Use slot props instead:\n\n` + + `\n` + + ` <${comp}>\n` + + ` \n` + + ` \n` + + ``); + } +} + +/** + * 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, { + // remove variables that can contain vue instances + 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, + }, + }; +} +// to support multiple router instances +let routerId = 0; +function addDevtools(app, router, matcher) { + // Take over router.beforeEach and afterEach + // make sure we are not registering the devtool twice + if (router.__hasDevtools) + return; + router.__hasDevtools = true; + // increment to support multiple router instances + const id = routerId++; + devtoolsApi.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') { + console.warn('[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.'); + } + // display state added by the router + 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'), + }); + } + }); + // mark router-link as active and display tags on router views + 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 multiple useLink are used + 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, + }); + }); + } + }); + vue.watch(router.currentRoute, () => { + // refresh active state + refreshRoutesView(); + api.notifyComponentUpdate(); + api.sendInspectorTree(routerInspectorId); + api.sendInspectorState(routerInspectorId); + }); + const navigationsLayerId = 'router:navigations:' + id; + api.addTimelineLayer({ + id: navigationsLayerId, + label: `Router${id ? ' ' + id : ''} Navigations`, + color: 0x40a8c4, + }); + // const errorsLayerId = 'router:errors' + // api.addTimelineLayer({ + // id: errorsLayerId, + // label: 'Router Errors', + // color: 0xea5455, + // }) + 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, + }, + }); + }); + // attached to `meta` and used to group events + 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'), + }; + // Used to group navigations together, hide from devtools + 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('✅'); + } + // we set here to have the right order + 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() { + // the routes view isn't active + if (!activeRoutesPayload) + return; + const payload = activeRoutesPayload; + // children routes will appear as nested + let routes = matcher.getRoutes().filter(route => !route.parent || + // these routes have a parent with no component which will not appear in the view + // therefore we still need to include them + !route.parent.record.components); + // reset match state to false + routes.forEach(resetMatchStateOnRouteRecord); + // apply a match state if there is a payload + if (payload.filter) { + routes = routes.filter(route => + // save matches state based on the payload + isRouteMatching(route, payload.filter.toLowerCase())); + } + // mark active routes + 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 routes = matcher.getRoutes(); + const route = routes.find(route => route.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 = 0xec4899; +const BLUE_600 = 0x2563eb; +const LIME_500 = 0x84cc16; +const CYAN_400 = 0x22d3ee; +const ORANGE_400 = 0xfb923c; +// const GRAY_100 = 0xf4f4f5 +const DARK = 0x666666; +const RED_100 = 0xfee2e2; +const RED_700 = 0xb91c1c; +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: 0xffffff, + backgroundColor: DARK, + }); + } + // add an id to be able to select it. Using the `path` is not possible because + // empty path children would collide with their parents + 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), + }; +} +// incremental id for route records and inspector state +let routeRecordId = 0; +const EXTRACT_REGEXP_RE = /^\/(.*)\/([a-z]*)$/; +function markRouteRecordActive(route, currentRoute) { + // no route will be active if matched is empty + // reset the matching state + 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; + } + // use a regexp without $ at the end to match nested routes better + const nonEndingRE = new RegExp(found[1].replace(/\$$/, ''), found[2]); + if (nonEndingRE.test(filter)) { + // mark children as matches + route.children.forEach(child => isRouteMatching(child, filter)); + // exception case: `/` + if (route.record.path !== '/' || filter === '/') { + route.__vd_match = route.re.test(filter); + return true; + } + // hide the / route + return false; + } + const path = route.record.path.toLowerCase(); + const decodedPath = decode(path); + // also allow partial matching on the 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)) { + // @ts-expect-error + ret[key] = obj[key]; + } + } + return ret; +} + +/** + * 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; + if (!routerHistory) + throw new Error('Provide the "history" option when calling "createRouter()":' + + ' https://router.vuejs.org/api/interfaces/RouterOptions.html#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); + if (!parent) { + warn(`Parent route "${String(parentOrRoute)}" not found when adding child route`, route); + } + record = route; + } + else { + record = parentOrRoute; + } + return matcher.addRoute(record, parent); + } + function removeRoute(name) { + const recordMatcher = matcher.getRecordMatcher(name); + if (recordMatcher) { + matcher.removeRoute(recordMatcher); + } + else { + warn(`Cannot remove non-existent route "${String(name)}"`); + } + } + function getRoutes() { + return matcher.getRoutes().map(routeMatcher => routeMatcher.record); + } + function hasRoute(name) { + return !!matcher.getRecordMatcher(name); + } + function resolve(rawLocation, currentLocation) { + // const resolve: Router['resolve'] = (rawLocation: RouteLocationRaw, 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); + { + if (href.startsWith('//')) + warn(`Location "${rawLocation}" resolved to "${href}". A resolved location cannot start with multiple slashes.`); + else if (!matchedRoute.matched.length) { + warn(`No match found for location with path "${rawLocation}"`); + } + } + // locationNormalized is always a new object + return assign(locationNormalized, matchedRoute, { + params: decodeParams(matchedRoute.params), + hash: decode(locationNormalized.hash), + redirectedFrom: undefined, + href, + }); + } + if (!isRouteLocation(rawLocation)) { + warn(`router.resolve() was passed an invalid location. This will fail in production.\n- Location:`, rawLocation); + return resolve({}); + } + let matcherLocation; + // path could be relative in object as well + if (rawLocation.path != null) { + if ('params' in rawLocation && + !('name' in rawLocation) && + // @ts-expect-error: the type is never + Object.keys(rawLocation.params).length) { + warn(`Path "${rawLocation.path}" was passed with params but they will be ignored. Use a named route alongside params instead.`); + } + 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(targetParams), + }); + // 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 || ''; + if (hash && !hash.startsWith('#')) { + warn(`A \`hash\` should always start with the character "#". Replace "${hash}" with "#${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); + { + if (href.startsWith('//')) { + warn(`Location "${rawLocation}" resolved to "${href}". A resolved location cannot start with multiple slashes.`); + } + else if (!matchedRoute.matched.length) { + warn(`No match found for location with path "${rawLocation.path != null ? rawLocation.path : rawLocation}"`); + } + } + 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 = {}; + } + if (newTargetLocation.path == null && + !('name' in newTargetLocation)) { + warn(`Invalid redirect found:\n${JSON.stringify(newTargetLocation, null, 2)}\n when navigating to "${to.fullPath}". A redirect must contain a name or path. This will break in production.`); + throw new Error('Invalid redirect'); + } + return assign({ + query: to.query, + hash: to.hash, + // avoid transferring params if the redirect has a path + params: newTargetLocation.path != null ? {} : 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 */)) { + if (// we are redirecting to the same location we were already at + isSameRouteLocation(stringifyQuery$1, resolve(failure.to), toLocation) && + // and we have done it a couple of times + redirectedFrom && + // @ts-expect-error: added only in dev + (redirectedFrom._count = redirectedFrom._count + ? // @ts-expect-error + redirectedFrom._count + 1 + : 1) > 30) { + warn(`Detected a possibly infinite redirection in a navigation guard when going from "${from.fullPath}" to "${toLocation.fullPath}". Aborting to avoid a Stack Overflow.\n Are you always returning a new location within a navigation guard? That would lead to this error. Only return when redirecting or aborting, that should fix this. This might break in production if not fixed.`); + return Promise.reject(new Error('Infinite redirect in navigation guard')); + } + 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(); + } + function runWithContext(fn) { + const app = installedApps.values().next().value; + // support Vue < 3.3 + return app && typeof app.runWithContext === 'function' + ? app.runWithContext(fn) + : fn(); + } + // 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 enteringRecords) { + // do not trigger beforeEnter on reused views + if (record.beforeEnter) { + 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 + // clear existing enterCallbacks, these are added by extractComponentsGuards + to.matched.forEach(record => (record.enterCallbacks = {})); + // check in-component beforeRouteEnter + guards = extractComponentsGuards(enteringRecords, 'beforeRouteEnter', to, from, runWithContext); + 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 + afterGuards + .list() + .forEach(guard => runWithContext(() => 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); + }) + // avoid warnings in the console about uncaught rejections, they are logged by triggerErrors + .catch(noop); + }); + } + // Initialization and Errors + let readyHandlers = useCallbacks(); + let errorListeners = useCallbacks(); + let ready; + /** + * Trigger errorListeners 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 = errorListeners.list(); + if (list.length) { + list.forEach(handler => handler(error, to, from)); + } + else { + { + warn('uncaught error during route navigation:'); + } + console.error(error); + } + // reject the error no matter there were error listeners or not + 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, + clearRoutes: matcher.clearRoutes, + hasRoute, + getRoutes, + resolve, + options, + push, + replace, + go, + back: () => go(-1), + forward: () => go(1), + beforeEach: beforeGuards.add, + beforeResolve: beforeResolveGuards.add, + afterEach: afterGuards.add, + onError: errorListeners.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 => { + warn('Unexpected error when starting the router:', err); + }); + } + const reactiveRoute = {}; + for (const key in START_LOCATION_NORMALIZED) { + Object.defineProperty(reactiveRoute, key, { + get: () => currentRoute.value[key], + enumerable: true, + }); + } + app.provide(routerKey, router); + app.provide(routeLocationKey, vue.shallowReactive(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(); + }; + // TODO: this probably needs to be updated so it can be used by vue-termui + if (isBrowser) { + addDevtools(app, router, matcher); + } + }, + }; + // TODO: type this as NavigationGuardReturn or similar instead of any + function runGuardQueue(guards) { + return guards.reduce((promise, guard) => promise.then(() => runWithContext(guard)), Promise.resolve()); + } + return router; +} +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(_name) { + 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; diff --git a/node_modules/vue-router/dist/vue-router.cjs.js b/node_modules/vue-router/dist/vue-router.cjs.js new file mode 100644 index 0000000..3937c61 --- /dev/null +++ b/node_modules/vue-router/dist/vue-router.cjs.js @@ -0,0 +1 @@ +module.exports = require('../dist/vue-router.cjs') \ No newline at end of file diff --git a/node_modules/vue-router/dist/vue-router.cjs.prod.js b/node_modules/vue-router/dist/vue-router.cjs.prod.js new file mode 100644 index 0000000..b6d8d59 --- /dev/null +++ b/node_modules/vue-router/dist/vue-router.cjs.prod.js @@ -0,0 +1 @@ +module.exports = require('../dist/vue-router.prod.cjs') \ No newline at end of file diff --git a/node_modules/vue-router/dist/vue-router.d.ts b/node_modules/vue-router/dist/vue-router.d.ts new file mode 100644 index 0000000..3893ef8 --- /dev/null +++ b/node_modules/vue-router/dist/vue-router.d.ts @@ -0,0 +1,1826 @@ +import { AllowedComponentProps } from 'vue'; +import { App } from 'vue'; +import type { Component } from 'vue'; +import { ComponentCustomProps } from 'vue'; +import { ComponentPublicInstance } from 'vue'; +import { ComputedRef } from 'vue'; +import type { DefineComponent } from 'vue'; +import type { InjectionKey } from 'vue'; +import { MaybeRef } from 'vue'; +import { Ref } from 'vue'; +import { UnwrapRef } from 'vue'; +import { VNode } from 'vue'; +import { VNodeProps } from 'vue'; + +declare type Awaitable = T | Promise; + +/** + * Maybe a promise maybe not + * @internal + */ +export declare type _Awaitable = T | PromiseLike; + +/** + * 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 + */ +export declare function createMemoryHistory(base?: string): RouterHistory; + +/** + * Creates a Router instance that can be used by a Vue app. + * + * @param options - {@link RouterOptions} + */ +export declare function createRouter(options: RouterOptions): Router; + +/** + * Creates a Router Matcher. + * + * @internal + * @param routes - array of initial routes + * @param globalOptions - global route options + */ +export declare function createRouterMatcher(routes: Readonly, globalOptions: PathParserOptions): RouterMatcher; + +/** + * 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 `` 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 `` 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#` + * ``` + */ +export declare function createWebHashHistory(base?: string): RouterHistory; + +/** + * Creates an HTML5 history. Most common history for single page applications. + * + * @param base - + */ +export declare function createWebHistory(base?: string): RouterHistory; + +/** + * Internal type to define an ErrorHandler + * + * @param error - error thrown + * @param to - location we were navigating to when the error happened + * @param from - location we were navigating from when the error happened + * @internal + */ +declare interface _ErrorListener { + (error: any, to: RouteLocationNormalized, from: RouteLocationNormalizedLoaded): any; +} + +/** + * Flags so we can combine them when checking for multiple errors. This is the internal version of + * {@link NavigationFailureType}. + * + * @internal + */ +export declare const enum ErrorTypes { + MATCHER_NOT_FOUND = 1, + NAVIGATION_GUARD_REDIRECT = 2, + NAVIGATION_ABORTED = 4, + NAVIGATION_CANCELLED = 8, + NAVIGATION_DUPLICATED = 16 +} + +declare type HistoryLocation = string; + +/** + * Allowed HTML history.state + */ +export declare interface HistoryState { + [x: number]: HistoryStateValue; + [x: string]: HistoryStateValue; +} + +/** + * Allowed arrays for history.state. + * + * @internal + */ +declare interface HistoryStateArray extends Array { +} + +/** + * Allowed variables in HTML5 history state. Note that pushState clones the state + * passed and does not accept everything: e.g.: it doesn't accept symbols, nor + * functions as values. It also ignores Symbols as keys. + * + * @internal + */ +declare type HistoryStateValue = string | number | boolean | null | undefined | HistoryState | HistoryStateArray; + +/** + * Check if an object is a {@link NavigationFailure}. + * + * @param error - possible {@link NavigationFailure} + * @param type - optional types to check for + * + * @example + * ```js + * import { isNavigationFailure, NavigationFailureType } from 'vue-router' + * + * router.afterEach((to, from, failure) => { + * // Any kind of navigation failure + * if (isNavigationFailure(failure)) { + * // ... + * } + * // Only duplicated navigations + * if (isNavigationFailure(failure, NavigationFailureType.duplicated)) { + * // ... + * } + * // Aborted or canceled navigations + * if (isNavigationFailure(failure, NavigationFailureType.aborted | NavigationFailureType.canceled)) { + * // ... + * } + * }) + * ``` + */ +export declare function isNavigationFailure(error: any, type?: ErrorTypes.NAVIGATION_GUARD_REDIRECT): error is NavigationRedirectError; + +export declare function isNavigationFailure(error: any, type?: ErrorTypes | NavigationFailureType): error is NavigationFailure; + +declare type Lazy = () => Promise; + +/** + * Creates a union type that still allows autocompletion for strings. + * @internal + */ +declare type _LiteralUnion = LiteralType | (BaseType & Record); + +/** + * Ensures a route is loaded, so it can be passed as o prop to ``. + * + * @param route - resolved route to load + */ +export declare function loadRouteLocation(route: RouteLocation | RouteLocationNormalized): Promise; + +/** + * @internal + */ +export declare interface LocationAsRelativeRaw { + name?: RouteRecordNameGeneric; + /** + * Ignored path property since we are dealing with a relative location. Only `undefined` is allowed. + */ + path?: undefined; + params?: RouteParamsRawGeneric; +} + +/** + * Normalized query object that appears in {@link RouteLocationNormalized} + * + * @public + */ +export declare type LocationQuery = Record; + +/** + * Loose {@link LocationQuery} object that can be passed to functions like + * {@link Router.push} and {@link Router.replace} or anywhere when creating a + * {@link RouteLocationRaw} + * + * @public + */ +export declare type LocationQueryRaw = Record; + +/** + * Possible values in normalized {@link LocationQuery}. `null` renders the query + * param but without an `=`. + * + * @example + * ``` + * ?isNull&isEmpty=&other=other + * gives + * `{ isNull: null, isEmpty: '', other: 'other' }`. + * ``` + * + * @internal + */ +export declare type LocationQueryValue = string | null; + +/** + * Possible values when defining a query. + * + * @internal + */ +export declare type LocationQueryValueRaw = LocationQueryValue | number | undefined; + +/** + * RouteRecord being rendered by the closest ancestor Router View. Used for + * `onBeforeRouteUpdate` and `onBeforeRouteLeave`. rvlm stands for Router View + * Location Matched + * + * @internal + */ +export declare const matchedRouteKey: InjectionKey>; + +/** + * Normalized/resolved Route location that returned by the matcher. + */ +export declare interface MatcherLocation { + /** + * Name of the matched record + */ + name: RouteRecordNameGeneric | null | undefined; + /** + * Percentage encoded pathname section of the URL. + */ + path: string; + /** + * Object of decoded params extracted from the `path`. + */ + params: RouteParamsGeneric; + /** + * Merged `meta` properties from all the matched route records. + */ + meta: RouteMeta; + /** + * Array of {@link RouteRecord} containing components as they were + * passed when adding records. It can also contain redirect records. This + * can't be used directly + */ + matched: RouteRecord[]; +} + +/** + * @internal + */ +declare interface MatcherLocationAsName { + name: RouteRecordNameGeneric; + /** + * Ignored path property since we are dealing with a relative location. Only `undefined` is allowed. + */ + path?: undefined; + params?: RouteParamsGeneric; +} + +/** + * @internal + */ +export declare interface MatcherLocationAsPath { + path: string; +} + +/** + * @internal + */ +declare interface MatcherLocationAsRelative { + /** + * Ignored path property since we are dealing with a relative location. Only `undefined` is allowed. + */ + path?: undefined; + params?: RouteParamsGeneric; +} + +/** + * Route location that can be passed to the matcher. + */ +declare type MatcherLocationRaw = MatcherLocationAsPath | MatcherLocationAsName | MatcherLocationAsRelative; + +declare interface NavigationCallback { + (to: HistoryLocation, from: HistoryLocation, information: NavigationInformation): void; +} + +declare enum NavigationDirection { + back = "back", + forward = "forward", + unknown = "" +} + +/** + * Extended Error that contains extra information regarding a failed navigation. + */ +export declare interface NavigationFailure extends Error { + /** + * Type of the navigation. One of {@link NavigationFailureType} + */ + type: ErrorTypes.NAVIGATION_CANCELLED | ErrorTypes.NAVIGATION_ABORTED | ErrorTypes.NAVIGATION_DUPLICATED; + /** + * Route location we were navigating from + */ + from: RouteLocationNormalized; + /** + * Route location we were navigating to + */ + to: RouteLocationNormalized; +} + +/** + * Enumeration with all possible types for navigation failures. Can be passed to + * {@link isNavigationFailure} to check for specific failures. + */ +export declare enum NavigationFailureType { + /** + * An aborted navigation is a navigation that failed because a navigation + * guard returned `false` or called `next(false)` + */ + aborted = 4, + /** + * A cancelled navigation is a navigation that failed because a more recent + * navigation finished started (not necessarily finished). + */ + cancelled = 8, + /** + * A duplicated navigation is a navigation that failed because it was + * initiated while already being at the exact same location. + */ + duplicated = 16 +} + +/** + * Navigation Guard. + */ +export declare interface NavigationGuard { + (to: RouteLocationNormalized, from: RouteLocationNormalizedLoaded, next: NavigationGuardNext): _Awaitable; +} + +/** + * `next()` callback passed to navigation guards. + */ +export declare interface NavigationGuardNext { + (): void; + (error: Error): void; + (location: RouteLocationRaw): void; + (valid: boolean | undefined): void; + (cb: NavigationGuardNextCallback): void; +} + +/** + * Callback that can be passed to `next()` in `beforeRouteEnter()` guards. + */ +export declare type NavigationGuardNextCallback = (vm: ComponentPublicInstance) => unknown; + +/** + * Return types for a Navigation Guard. Based on `TypesConfig` + * + * @see {@link TypesConfig} + */ +export declare type NavigationGuardReturn = void | Error | boolean | RouteLocationRaw; + +/** + * Navigation Guard with a type parameter for `this`. + * @see {@link TypesConfig} + */ +export declare interface NavigationGuardWithThis { + (this: T, to: RouteLocationNormalized, from: RouteLocationNormalizedLoaded, next: NavigationGuardNext): _Awaitable; +} + +/** + * Navigation hook triggered after a navigation is settled. + */ +export declare interface NavigationHookAfter { + (to: RouteLocationNormalized, from: RouteLocationNormalizedLoaded, failure?: NavigationFailure | void): unknown; +} + +declare interface NavigationInformation { + type: NavigationType; + direction: NavigationDirection; + delta: number; +} + +/** + * Internal error used to detect a redirection. + * + * @internal + */ +export declare interface NavigationRedirectError extends Omit { + type: ErrorTypes.NAVIGATION_GUARD_REDIRECT; + to: RouteLocationRaw; +} + +declare enum NavigationType { + pop = "pop", + push = "push" +} + +/** + * 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} + */ +export declare function onBeforeRouteLeave(leaveGuard: NavigationGuard): void; + +/** + * 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} + */ +export declare function onBeforeRouteUpdate(updateGuard: NavigationGuard): void; + +/** + * Utility type for raw and non raw params like :id + * + */ +export declare type ParamValue = true extends isRaw ? string | number : string; + +/** + * Utility type for raw and non raw params like :id+ + * + */ +export declare type ParamValueOneOrMore = [ +ParamValue, +...ParamValue[] +]; + +/** + * Utility type for raw and non raw params like :id* + * + */ +export declare type ParamValueZeroOrMore = true extends isRaw ? ParamValue[] | undefined | null : ParamValue[] | undefined; + +/** + * Utility type for raw and non raw params like :id? + * + */ +export declare type ParamValueZeroOrOne = true extends isRaw ? string | number | null | undefined : string; + +/** + * 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 + */ +export declare function parseQuery(search: string): LocationQuery; + +declare type PathParams = Record; + +declare interface PathParser { + /** + * The regexp used to match a url + */ + re: RegExp; + /** + * The score of the parser + */ + score: Array; + /** + * Keys that appeared in the path + */ + keys: PathParserParamKey[]; + /** + * Parses a url and returns the matched params or null if it doesn't match. An + * optional param that isn't preset will be an empty string. A repeatable + * param will be an array if there is at least one value. + * + * @param path - url to parse + * @returns a Params object, empty if there are no params. `null` if there is + * no match + */ + parse(path: string): PathParams | null; + /** + * Creates a string version of the url + * + * @param params - object of params + * @returns a url + */ + stringify(params: PathParams): string; +} + +export declare type PathParserOptions = Pick<_PathParserOptions, 'end' | 'sensitive' | 'strict'>; + +/** + * @internal + */ +export declare interface _PathParserOptions { + /** + * Makes the RegExp case-sensitive. + * + * @defaultValue `false` + */ + sensitive?: boolean; + /** + * Whether to disallow a trailing slash or not. + * + * @defaultValue `false` + */ + strict?: boolean; + /** + * Should the RegExp match from the beginning by prepending a `^` to it. + * @internal + * + * @defaultValue `true` + */ + start?: boolean; + /** + * Should the RegExp match until the end by appending a `$` to it. + * + * @defaultValue `true` + */ + end?: boolean; +} + +/** + * A param in a url like `/users/:id` + */ +declare interface PathParserParamKey { + name: string; + repeatable: boolean; + optional: boolean; +} + +/** + * Allowed Component definitions in route records provided by the user + */ +declare type RawRouteComponent = RouteComponent | Lazy; + +/** + * Allowed Component in {@link RouteLocationMatched} + */ +export declare type RouteComponent = Component | DefineComponent; + +/** + * Type safe versions of types that are exposed by vue-router. We have to use a generic check to allow for names to be `undefined` when no `RouteMap` is provided. + */ +/** + * {@link RouteLocationRaw} resolved using the matcher + */ +export declare type RouteLocation = RouteMapGeneric extends RouteMap ? RouteLocationGeneric : RouteLocationTypedList[Name]; + +/** + * Route location as an object with a `path` property. + */ +export declare type RouteLocationAsPath = RouteMapGeneric extends RouteMap ? RouteLocationAsPathGeneric : RouteLocationAsPathTypedList[Name]; + +/** + * Generic version of {@link RouteLocationAsPath}. It is used when no {@link RouteMap} is provided. + */ +export declare interface RouteLocationAsPathGeneric extends RouteQueryAndHash, RouteLocationOptions { + /** + * Percentage encoded pathname section of the URL. + */ + path: string; +} + +/** + * Helper to generate a type safe version of the {@link RouteLocationAsPath} type. + */ +export declare interface RouteLocationAsPathTyped extends RouteLocationAsPathGeneric { + path: _LiteralUnion; +} + +/** + * List of all possible {@link RouteLocationAsPath} indexed by the route name. + * @internal + */ +export declare type RouteLocationAsPathTypedList = { + [N in keyof RouteMap]: RouteLocationAsPathTyped; +}; + +/** + * Route location relative to the current location. It accepts other properties than `path` like `params`, `query` and + * `hash` to conveniently change them. + */ +export declare type RouteLocationAsRelative = RouteMapGeneric extends RouteMap ? RouteLocationAsRelativeGeneric : RouteLocationAsRelativeTypedList[Name]; + +/** + * Generic version of {@link RouteLocationAsRelative}. It is used when no {@link RouteMap} is provided. + */ +export declare interface RouteLocationAsRelativeGeneric extends RouteQueryAndHash, RouteLocationOptions { + name?: RouteRecordNameGeneric; + params?: RouteParamsRawGeneric; + /** + * A relative path to the current location. This property should be removed + */ + path?: undefined; +} + +/** + * Helper to generate a type safe version of the {@link RouteLocationAsRelative} type. + */ +export declare interface RouteLocationAsRelativeTyped extends RouteLocationAsRelativeGeneric { + name?: Extract; + params?: RouteMap[Name]['paramsRaw']; +} + +/** + * List of all possible {@link RouteLocationAsRelative} indexed by the route name. + * @internal + */ +export declare type RouteLocationAsRelativeTypedList = { + [N in keyof RouteMap]: RouteLocationAsRelativeTyped; +}; + +/** + * Same as {@link RouteLocationAsPath} but as a string literal. + */ +export declare type RouteLocationAsString = RouteMapGeneric extends RouteMap ? string : _LiteralUnion[Name], string>; + +/** + * Helper to generate a type safe version of the {@link RouteLocationAsString} type. + */ +export declare type RouteLocationAsStringTyped = RouteMap[Name]['path']; + +/** + * List of all possible {@link RouteLocationAsString} indexed by the route name. + * @internal + */ +export declare type RouteLocationAsStringTypedList = { + [N in keyof RouteMap]: RouteLocationAsStringTyped; +}; + +/** + * Base properties for a normalized route location. + * + * @internal + */ +export declare interface _RouteLocationBase extends Pick { + /** + * The whole location including the `search` and `hash`. This string is + * percentage encoded. + */ + fullPath: string; + /** + * Object representation of the `search` property of the current location. + */ + query: LocationQuery; + /** + * Hash of the current location. If present, starts with a `#`. + */ + hash: string; + /** + * Contains the location we were initially trying to access before ending up + * on the current location. + */ + redirectedFrom: RouteLocation | undefined; +} + +/** + * Generic version of {@link RouteLocation}. It is used when no {@link RouteMap} is provided. + */ +export declare interface RouteLocationGeneric extends _RouteLocationBase { + /** + * Array of {@link RouteRecord} containing components as they were + * passed when adding records. It can also contain redirect records. This + * can't be used directly. **This property is non-enumerable**. + */ + matched: RouteRecord[]; +} + +/** + * Allows overriding the current route returned by `useRoute` in tests. rl + * stands for route location + * + * @internal + */ +export declare const routeLocationKey: InjectionKey; + +export declare interface RouteLocationMatched extends RouteRecordNormalized { + components: Record | null | undefined; +} + +/** + * Route Location that can infer the necessary params based on the name. + * + * @internal + */ +export declare interface RouteLocationNamedRaw extends RouteQueryAndHash, LocationAsRelativeRaw, RouteLocationOptions { +} + +/** + * Similar to {@link RouteLocation} but its + * {@link RouteLocationNormalizedTyped.matched | `matched` property} cannot contain redirect records + */ +export declare type RouteLocationNormalized = RouteMapGeneric extends RouteMap ? RouteLocationNormalizedGeneric : RouteLocationNormalizedTypedList[Name]; + +/** + * Generic version of {@link RouteLocationNormalized} that is used when no {@link RouteMap} is provided. + */ +export declare interface RouteLocationNormalizedGeneric extends _RouteLocationBase { + name: RouteRecordNameGeneric; + params: RouteParamsGeneric; + /** + * Array of {@link RouteRecordNormalized} + */ + matched: RouteRecordNormalized[]; +} + +/** + * Similar to {@link RouteLocationNormalized} but its `components` do not contain any function to lazy load components. + * In other words, it's ready to be rendered by ``. + */ +export declare type RouteLocationNormalizedLoaded = RouteMapGeneric extends RouteMap ? RouteLocationNormalizedLoadedGeneric : RouteLocationNormalizedLoadedTypedList[Name]; + +/** + * Generic version of {@link RouteLocationNormalizedLoaded} that is used when no {@link RouteMap} is provided. + */ +export declare interface RouteLocationNormalizedLoadedGeneric extends RouteLocationNormalizedGeneric { + /** + * Array of {@link RouteLocationMatched} containing only plain components (any + * lazy-loaded components have been loaded and were replaced inside the + * `components` object) so it can be directly used to display routes. It + * cannot contain redirect records either. **This property is non-enumerable**. + */ + matched: RouteLocationMatched[]; +} + +/** + * Helper to generate a type safe version of the {@link RouteLocationNormalizedLoaded} type. + */ +export declare interface RouteLocationNormalizedLoadedTyped extends RouteLocationNormalizedLoadedGeneric { + name: Extract; + params: RouteMap[Name]['params']; +} + +/** + * List of all possible {@link RouteLocationNormalizedLoaded} indexed by the route name. + * @internal + */ +export declare type RouteLocationNormalizedLoadedTypedList = { + [N in keyof RouteMap]: RouteLocationNormalizedLoadedTyped; +}; + +/** + * Helper to generate a type safe version of the {@link RouteLocationNormalized} type. + */ +export declare interface RouteLocationNormalizedTyped extends RouteLocationNormalizedGeneric { + name: Extract; + params: RouteMap[Name]['params']; + /** + * Array of {@link RouteRecordNormalized} + */ + matched: RouteRecordNormalized[]; +} + +/** + * List of all possible {@link RouteLocationNormalized} indexed by the route name. + * @internal + */ +export declare type RouteLocationNormalizedTypedList = { + [N in keyof RouteMap]: RouteLocationNormalizedTyped; +}; + +/** + * Common options for all navigation methods. + */ +export declare interface RouteLocationOptions { + /** + * Replace the entry in the history instead of pushing a new entry + */ + replace?: boolean; + /** + * Triggers the navigation even if the location is the same as the current one. + * Note this will also add a new entry to the history unless `replace: true` + * is passed. + */ + force?: boolean; + /** + * State to save using the History API. This cannot contain any reactive + * values and some primitives like Symbols are forbidden. More info at + * https://developer.mozilla.org/en-US/docs/Web/API/History/state + */ + state?: HistoryState; +} + +/** + * Route Location that can infer the possible paths. + * + * @internal + */ +export declare interface RouteLocationPathRaw extends RouteQueryAndHash, MatcherLocationAsPath, RouteLocationOptions { +} + +/** + * Route location that can be passed to `router.push()` and other user-facing APIs. + */ +export declare type RouteLocationRaw = RouteMapGeneric extends RouteMap ? RouteLocationAsString | RouteLocationAsRelativeGeneric | RouteLocationAsPathGeneric : _LiteralUnion[Name], string> | RouteLocationAsRelativeTypedList[Name] | RouteLocationAsPathTypedList[Name]; + +/** + * Route location resolved with {@link Router | `router.resolve()`}. + */ +export declare type RouteLocationResolved = RouteMapGeneric extends RouteMap ? RouteLocationResolvedGeneric : RouteLocationResolvedTypedList[Name]; + +/** + * Generic version of {@link RouteLocationResolved}. It is used when no {@link RouteMap} is provided. + */ +export declare interface RouteLocationResolvedGeneric extends RouteLocationGeneric { + /** + * Resolved `href` for the route location that will be set on the ``. + */ + href: string; +} + +/** + * Helper to generate a type safe version of the {@link RouteLocationResolved} type. + */ +export declare interface RouteLocationResolvedTyped extends RouteLocationTyped { + /** + * Resolved `href` for the route location that will be set on the ``. + */ + href: string; +} + +/** + * List of all possible {@link RouteLocationResolved} indexed by the route name. + * @internal + */ +export declare type RouteLocationResolvedTypedList = { + [N in keyof RouteMap]: RouteLocationResolvedTyped; +}; + +/** + * Helper to generate a type safe version of the {@link RouteLocation} type. + */ +export declare interface RouteLocationTyped extends RouteLocationGeneric { + name: Extract; + params: RouteMap[Name]['params']; +} + +/** + * List of all possible {@link RouteLocation} indexed by the route name. + * @internal + */ +export declare type RouteLocationTypedList = { + [N in keyof RouteMap]: RouteLocationTyped; +}; + +/** + * Convenience type to get the typed RouteMap or a generic one if not provided. It is extracted from the {@link TypesConfig} if it exists, it becomes {@link RouteMapGeneric} otherwise. + */ +export declare type RouteMap = TypesConfig extends Record<'RouteNamedMap', infer RouteNamedMap> ? RouteNamedMap : RouteMapGeneric; + +/** + * Generic version of the `RouteMap`. + */ +export declare type RouteMapGeneric = Record; + +/** + * Interface to type `meta` fields in route records. + * + * @example + * + * ```ts + * // typings.d.ts or router.ts + * import 'vue-router'; + * + * declare module 'vue-router' { + * interface RouteMeta { + * requiresAuth?: boolean + * } + * } + * ``` + */ +export declare interface RouteMeta extends Record { +} + +/** + * Generate a type safe params for a route location. Requires the name of the route to be passed as a generic. + * @see {@link RouteParamsGeneric} + */ +export declare type RouteParams = RouteMap[Name]['params']; + +export declare type RouteParamsGeneric = Record; + +/** + * Generate a type safe raw params for a route location. Requires the name of the route to be passed as a generic. + * @see {@link RouteParamsRaw} + */ +export declare type RouteParamsRaw = RouteMap[Name]['paramsRaw']; + +export declare type RouteParamsRawGeneric = Record[]>; + +/** + * @internal + */ +export declare type RouteParamValue = string; + +/** + * @internal + */ +export declare type RouteParamValueRaw = RouteParamValue | number | null | undefined; + +/** + * @internal + */ +export declare interface RouteQueryAndHash { + query?: LocationQueryRaw; + hash?: string; +} + +/** + * Router instance. + */ +export declare interface Router { + /** + * @internal + */ + /** + * Current {@link RouteLocationNormalized} + */ + readonly currentRoute: Ref; + /** + * Original options object passed to create the Router + */ + readonly options: RouterOptions; + /** + * Allows turning off the listening of history events. This is a low level api for micro-frontend. + */ + listening: boolean; + /** + * Add a new {@link RouteRecordRaw | route record} as the child of an existing route. + * + * @param parentName - Parent Route Record where `route` should be appended at + * @param route - Route Record to add + */ + addRoute(parentName: NonNullable, route: RouteRecordRaw): () => void; + /** + * Add a new {@link RouteRecordRaw | route record} to the router. + * + * @param route - Route Record to add + */ + addRoute(route: RouteRecordRaw): () => void; + /** + * Remove an existing route by its name. + * + * @param name - Name of the route to remove + */ + removeRoute(name: NonNullable): void; + /** + * Checks if a route with a given name exists + * + * @param name - Name of the route to check + */ + hasRoute(name: NonNullable): boolean; + /** + * Get a full list of all the {@link RouteRecord | route records}. + */ + getRoutes(): RouteRecord[]; + /** + * Delete all routes from the router matcher. + */ + clearRoutes(): void; + /** + * Returns the {@link RouteLocation | normalized version} of a + * {@link RouteLocationRaw | route location}. Also includes an `href` property + * that includes any existing `base`. By default, the `currentLocation` used is + * `router.currentRoute` and should only be overridden in advanced use cases. + * + * @param to - Raw route location to resolve + * @param currentLocation - Optional current location to resolve against + */ + resolve(to: RouteLocationAsRelativeTyped, currentLocation?: RouteLocationNormalizedLoaded): RouteLocationResolved; + resolve(to: RouteLocationAsString | RouteLocationAsRelative | RouteLocationAsPath, currentLocation?: RouteLocationNormalizedLoaded): RouteLocationResolved; + /** + * Programmatically navigate to a new URL by pushing an entry in the history + * stack. + * + * @param to - Route location to navigate to + */ + push(to: RouteLocationRaw): Promise; + /** + * Programmatically navigate to a new URL by replacing the current entry in + * the history stack. + * + * @param to - Route location to navigate to + */ + replace(to: RouteLocationRaw): Promise; + /** + * Go back in history if possible by calling `history.back()`. Equivalent to + * `router.go(-1)`. + */ + back(): ReturnType; + /** + * Go forward in history if possible by calling `history.forward()`. + * Equivalent to `router.go(1)`. + */ + forward(): ReturnType; + /** + * Allows you to move forward or backward through the history. Calls + * `history.go()`. + * + * @param delta - The position in the history to which you want to move, + * relative to the current page + */ + go(delta: number): void; + /** + * Add a navigation guard that executes before any navigation. Returns a + * function that removes the registered guard. + * + * @param guard - navigation guard to add + */ + beforeEach(guard: NavigationGuardWithThis): () => void; + /** + * Add a navigation guard that executes before navigation is about to be + * resolved. At this state all component have been fetched and other + * navigation guards have been successful. Returns a function that removes the + * registered guard. + * + * @param guard - navigation guard to add + * @returns a function that removes the registered guard + * + * @example + * ```js + * router.beforeResolve(to => { + * if (to.meta.requiresAuth && !isAuthenticated) return false + * }) + * ``` + * + */ + beforeResolve(guard: NavigationGuardWithThis): () => void; + /** + * Add a navigation hook that is executed after every navigation. Returns a + * function that removes the registered hook. + * + * @param guard - navigation hook to add + * @returns a function that removes the registered hook + * + * @example + * ```js + * router.afterEach((to, from, failure) => { + * if (isNavigationFailure(failure)) { + * console.log('failed navigation', failure) + * } + * }) + * ``` + */ + afterEach(guard: NavigationHookAfter): () => void; + /** + * Adds an error handler that is called every time a non caught error happens + * during navigation. This includes errors thrown synchronously and + * asynchronously, errors returned or passed to `next` in any navigation + * guard, and errors occurred when trying to resolve an async component that + * is required to render a route. + * + * @param handler - error handler to register + */ + onError(handler: _ErrorListener): () => void; + /** + * Returns a Promise that resolves when the router has completed the initial + * navigation, which means it has resolved all async enter hooks and async + * components that are associated with the initial route. If the initial + * navigation already happened, the promise resolves immediately. + * + * This is useful in server-side rendering to ensure consistent output on both + * the server and the client. Note that on server side, you need to manually + * push the initial location while on client side, the router automatically + * picks it up from the URL. + */ + isReady(): Promise; + /** + * Called automatically by `app.use(router)`. Should not be called manually by + * the user. This will trigger the initial navigation when on client side. + * + * @internal + * @param app - Application that uses the router + */ + install(app: App): void; +} + +/** + * {@inheritDoc RouteRecordNormalized} + */ +export declare type RouteRecord = RouteRecordNormalized; + +/** + * Internal type for common properties among all kind of {@link RouteRecordRaw}. + */ +export declare interface _RouteRecordBase extends PathParserOptions { + /** + * Path of the record. Should start with `/` unless the record is the child of + * another record. + * + * @example `/users/:id` matches `/users/1` as well as `/users/posva`. + */ + path: string; + /** + * Where to redirect if the route is directly matched. The redirection happens + * before any navigation guard and triggers a new navigation with the new + * target location. + */ + redirect?: RouteRecordRedirectOption; + /** + * Aliases for the record. Allows defining extra paths that will behave like a + * copy of the record. Allows having paths shorthands like `/users/:id` and + * `/u/:id`. All `alias` and `path` values must share the same params. + */ + alias?: string | string[]; + /** + * Name for the route record. Must be unique. + */ + name?: RouteRecordNameGeneric; + /** + * Before Enter guard specific to this record. Note `beforeEnter` has no + * effect if the record has a `redirect` property. + */ + beforeEnter?: NavigationGuardWithThis | NavigationGuardWithThis[]; + /** + * Arbitrary data attached to the record. + */ + meta?: RouteMeta; + /** + * Array of nested routes. + */ + children?: RouteRecordRaw[]; + /** + * Allow passing down params as props to the component rendered by `router-view`. + */ + props?: _RouteRecordProps | Record; +} + +/** + * Helper type to define a Typed `RouteRecord` + * @see {@link RouteRecord} + */ +export declare interface RouteRecordInfo { + name: Name; + path: Path; + paramsRaw: ParamsRaw; + params: Params; + meta: Meta; +} + +declare interface RouteRecordMatcher extends PathParser { + record: RouteRecord; + parent: RouteRecordMatcher | undefined; + children: RouteRecordMatcher[]; + alias: RouteRecordMatcher[]; +} + +/** + * Route Record defining multiple named components with the `components` option. + */ +export declare interface RouteRecordMultipleViews extends _RouteRecordBase { + /** + * Components to display when the URL matches this route. Allow using named views. + */ + components: Record; + component?: never; + children?: never; + redirect?: never; + /** + * Allow passing down params as props to the component rendered by + * `router-view`. Should be an object with the same keys as `components` or a + * boolean to be applied to every component. + */ + props?: Record | boolean; +} + +/** + * Route Record defining multiple named components with the `components` option and children. + */ +export declare interface RouteRecordMultipleViewsWithChildren extends _RouteRecordBase { + /** + * Components to display when the URL matches this route. Allow using named views. + */ + components?: Record | null | undefined; + component?: never; + children: RouteRecordRaw[]; + /** + * Allow passing down params as props to the component rendered by + * `router-view`. Should be an object with the same keys as `components` or a + * boolean to be applied to every component. + */ + props?: Record | boolean; +} + +/** + * Possible values for a route record **after normalization** + * + * NOTE: since `RouteRecordName` is a type, it evaluates too early and it's often the generic version {@link RouteRecordNameGeneric}. If you need a typed version of all of the names of routes, use {@link RouteMap | `keyof RouteMap`} + */ +export declare type RouteRecordName = RouteMapGeneric extends RouteMap ? RouteRecordNameGeneric : keyof RouteMap; + +/** + * Generic version of {@link RouteRecordName}. + */ +export declare type RouteRecordNameGeneric = string | symbol | undefined; + +/** + * Normalized version of a {@link RouteRecord | route record}. + */ +export declare interface RouteRecordNormalized { + /** + * {@inheritDoc _RouteRecordBase.path} + */ + path: _RouteRecordBase['path']; + /** + * {@inheritDoc _RouteRecordBase.redirect} + */ + redirect: _RouteRecordBase['redirect'] | undefined; + /** + * {@inheritDoc _RouteRecordBase.name} + */ + name: _RouteRecordBase['name']; + /** + * {@inheritDoc RouteRecordMultipleViews.components} + */ + components: RouteRecordMultipleViews['components'] | null | undefined; + /** + * Contains the original modules for lazy loaded components. + * @internal + */ + mods: Record; + /** + * Nested route records. + */ + children: RouteRecordRaw[]; + /** + * {@inheritDoc _RouteRecordBase.meta} + */ + meta: Exclude<_RouteRecordBase['meta'], void>; + /** + * {@inheritDoc RouteRecordMultipleViews.props} + */ + props: Record; + /** + * Registered beforeEnter guards + */ + beforeEnter: _RouteRecordBase['beforeEnter']; + /** + * Registered leave guards + * + * @internal + */ + leaveGuards: Set; + /** + * Registered update guards + * + * @internal + */ + updateGuards: Set; + /** + * Registered beforeRouteEnter callbacks passed to `next` or returned in guards + * + * @internal + */ + enterCallbacks: Record; + /** + * Mounted route component instances + * Having the instances on the record mean beforeRouteUpdate and + * beforeRouteLeave guards can only be invoked with the latest mounted app + * instance if there are multiple application instances rendering the same + * view, basically duplicating the content on the page, which shouldn't happen + * in practice. It will work if multiple apps are rendering different named + * views. + */ + instances: Record; + /** + * Defines if this record is the alias of another one. This property is + * `undefined` if the record is the original one. + */ + aliasOf: RouteRecordNormalized | undefined; +} + +/** + * @internal + */ +export declare type _RouteRecordProps = boolean | Record | ((to: RouteLocationNormalized) => Record); + +export declare type RouteRecordRaw = RouteRecordSingleView | RouteRecordSingleViewWithChildren | RouteRecordMultipleViews | RouteRecordMultipleViewsWithChildren | RouteRecordRedirect; + +/** + * Route Record that defines a redirect. Cannot have `component` or `components` + * as it is never rendered. + */ +export declare interface RouteRecordRedirect extends _RouteRecordBase { + redirect: RouteRecordRedirectOption; + component?: never; + components?: never; + props?: never; +} + +/** + * @internal + */ +export declare type RouteRecordRedirectOption = RouteLocationRaw | ((to: RouteLocation) => RouteLocationRaw); + +/** + * Route Record defining one single component with the `component` option. + */ +export declare interface RouteRecordSingleView extends _RouteRecordBase { + /** + * Component to display when the URL matches this route. + */ + component: RawRouteComponent; + components?: never; + children?: never; + redirect?: never; + /** + * Allow passing down params as props to the component rendered by `router-view`. + */ + props?: _RouteRecordProps; +} + +/** + * Route Record defining one single component with a nested view. + */ +export declare interface RouteRecordSingleViewWithChildren extends _RouteRecordBase { + /** + * Component to display when the URL matches this route. + */ + component?: RawRouteComponent | null | undefined; + components?: never; + children: RouteRecordRaw[]; + /** + * Allow passing down params as props to the component rendered by `router-view`. + */ + props?: _RouteRecordProps; +} + +/** + * Interface implemented by History implementations that can be passed to the + * router as {@link Router.history} + * + * @alpha + */ +export declare interface RouterHistory { + /** + * Base path that is prepended to every url. This allows hosting an SPA at a + * sub-folder of a domain like `example.com/sub-folder` by having a `base` of + * `/sub-folder` + */ + readonly base: string; + /** + * Current History location + */ + readonly location: HistoryLocation; + /** + * Current History state + */ + readonly state: HistoryState; + /** + * Navigates to a location. In the case of an HTML5 History implementation, + * this will call `history.pushState` to effectively change the URL. + * + * @param to - location to push + * @param data - optional {@link HistoryState} to be associated with the + * navigation entry + */ + push(to: HistoryLocation, data?: HistoryState): void; + /** + * Same as {@link RouterHistory.push} but performs a `history.replaceState` + * instead of `history.pushState` + * + * @param to - location to set + * @param data - optional {@link HistoryState} to be associated with the + * navigation entry + */ + replace(to: HistoryLocation, data?: HistoryState): void; + /** + * Traverses history in a given direction. + * + * @example + * ```js + * myHistory.go(-1) // equivalent to window.history.back() + * myHistory.go(1) // equivalent to window.history.forward() + * ``` + * + * @param delta - distance to travel. If delta is \< 0, it will go back, + * if it's \> 0, it will go forward by that amount of entries. + * @param triggerListeners - whether this should trigger listeners attached to + * the history + */ + go(delta: number, triggerListeners?: boolean): void; + /** + * Attach a listener to the History implementation that is triggered when the + * navigation is triggered from outside (like the Browser back and forward + * buttons) or when passing `true` to {@link RouterHistory.back} and + * {@link RouterHistory.forward} + * + * @param callback - listener to attach + * @returns a callback to remove the listener + */ + listen(callback: NavigationCallback): () => void; + /** + * Generates the corresponding href to be used in an anchor tag. + * + * @param location - history location that should create an href + */ + createHref(location: HistoryLocation): string; + /** + * Clears any event listener attached by the history implementation. + */ + destroy(): void; +} + +/** + * Allows overriding the router instance returned by `useRouter` in tests. r + * stands for router + * + * @internal + */ +export declare const routerKey: InjectionKey; + +/** + * Component to render a link that triggers a navigation on click. + */ +export declare const RouterLink: _RouterLinkI; + +/** + * Typed version of the `RouterLink` component. Its generic defaults to the typed router, so it can be inferred + * automatically for JSX. + * + * @internal + */ +export declare interface _RouterLinkI { + new (): { + $props: AllowedComponentProps & ComponentCustomProps & VNodeProps & RouterLinkProps; + $slots: { + default?: ({ route, href, isActive, isExactActive, navigate, }: UnwrapRef) => VNode[]; + }; + }; + /** + * Access to `useLink()` without depending on using vue-router + * + * @internal + */ + useLink: typeof useLink; +} + +declare interface RouterLinkOptions { + /** + * Route Location the link should navigate to when clicked on. + */ + to: RouteLocationRaw; + /** + * Calls `router.replace` instead of `router.push`. + */ + replace?: boolean; +} + +export declare interface RouterLinkProps extends RouterLinkOptions { + /** + * Whether RouterLink should not wrap its content in an `a` tag. Useful when + * using `v-slot` to create a custom RouterLink + */ + custom?: boolean; + /** + * Class to apply when the link is active + */ + activeClass?: string; + /** + * Class to apply when the link is exact active + */ + exactActiveClass?: string; + /** + * Value passed to the attribute `aria-current` when the link is exact active. + * + * @defaultValue `'page'` + */ + ariaCurrentValue?: 'page' | 'step' | 'location' | 'date' | 'time' | 'true' | 'false'; +} + +/** + * Internal RouterMatcher + * + * @internal + */ +export declare interface RouterMatcher { + addRoute: (record: RouteRecordRaw, parent?: RouteRecordMatcher) => () => void; + removeRoute(matcher: RouteRecordMatcher): void; + removeRoute(name: NonNullable): void; + clearRoutes: () => void; + getRoutes: () => RouteRecordMatcher[]; + getRecordMatcher: (name: NonNullable) => RouteRecordMatcher | undefined; + /** + * Resolves a location. Gives access to the route record that corresponds to the actual path as well as filling the corresponding params objects + * + * @param location - MatcherLocationRaw to resolve to a url + * @param currentLocation - MatcherLocation of the current location + */ + resolve: (location: MatcherLocationRaw, currentLocation: MatcherLocation) => MatcherLocation; +} + +/** + * Options to initialize a {@link Router} instance. + */ +export declare interface RouterOptions extends PathParserOptions { + /** + * History implementation used by the router. Most web applications should use + * `createWebHistory` but it requires the server to be properly configured. + * You can also use a _hash_ based history with `createWebHashHistory` that + * does not require any configuration on the server but isn't handled at all + * by search engines and does poorly on SEO. + * + * @example + * ```js + * createRouter({ + * history: createWebHistory(), + * // other options... + * }) + * ``` + */ + history: RouterHistory; + /** + * Initial list of routes that should be added to the router. + */ + routes: Readonly; + /** + * Function to control scrolling when navigating between pages. Can return a + * Promise to delay scrolling. Check {@link ScrollBehavior}. + * + * @example + * ```js + * function scrollBehavior(to, from, savedPosition) { + * // `to` and `from` are both route locations + * // `savedPosition` can be null if there isn't one + * } + * ``` + */ + scrollBehavior?: RouterScrollBehavior; + /** + * Custom implementation to parse a query. See its counterpart, + * {@link RouterOptions.stringifyQuery}. + * + * @example + * Let's say you want to use the [qs package](https://github.com/ljharb/qs) + * to parse queries, you can provide both `parseQuery` and `stringifyQuery`: + * ```js + * import qs from 'qs' + * + * createRouter({ + * // other options... + * parseQuery: qs.parse, + * stringifyQuery: qs.stringify, + * }) + * ``` + */ + parseQuery?: typeof parseQuery; + /** + * Custom implementation to stringify a query object. Should not prepend a leading `?`. + * {@link RouterOptions.parseQuery | parseQuery} counterpart to handle query parsing. + */ + stringifyQuery?: typeof stringifyQuery; + /** + * Default class applied to active {@link RouterLink}. If none is provided, + * `router-link-active` will be applied. + */ + linkActiveClass?: string; + /** + * Default class applied to exact active {@link RouterLink}. If none is provided, + * `router-link-exact-active` will be applied. + */ + linkExactActiveClass?: string; +} + +/** + * Type of the `scrollBehavior` option that can be passed to `createRouter`. + */ +export declare interface RouterScrollBehavior { + /** + * @param to - Route location where we are navigating to + * @param from - Route location where we are navigating from + * @param savedPosition - saved position if it exists, `null` otherwise + */ + (to: RouteLocationNormalized, from: RouteLocationNormalizedLoaded, savedPosition: _ScrollPositionNormalized | null): Awaitable; +} + +/** + * Component to display the current route the user is at. + */ +export declare const RouterView: new () => { + $props: AllowedComponentProps & ComponentCustomProps & VNodeProps & RouterViewProps; + $slots: { + default?: (({ Component, route, }: { + Component: VNode; + route: RouteLocationNormalizedLoaded; + }) => VNode[]) | undefined; + }; +}; + +/** + * Allows overriding the current route used by router-view. Internally this is + * used when the `route` prop is passed. + * + * @internal + */ +export declare const routerViewLocationKey: InjectionKey>; + +export declare interface RouterViewProps { + name?: string; + route?: RouteLocationNormalized; +} + +declare type ScrollPosition = ScrollPositionCoordinates | ScrollPositionElement; + +/** + * Scroll position similar to + * {@link https://developer.mozilla.org/en-US/docs/Web/API/ScrollToOptions | `ScrollToOptions`}. + * Note that not all browsers support `behavior`. + */ +declare type ScrollPositionCoordinates = { + behavior?: ScrollOptions['behavior']; + left?: number; + top?: number; +}; + +declare interface ScrollPositionElement extends ScrollToOptions { + /** + * A valid CSS selector. Note some characters must be escaped in id selectors (https://mathiasbynens.be/notes/css-escapes). + * @example + * Here are a few examples: + * + * - `.title` + * - `.content:first-child` + * - `#marker` + * - `#marker\~with\~symbols` + * - `#marker.with.dot`: selects `class="with dot" id="marker"`, not `id="marker.with.dot"` + * + */ + el: string | Element; +} + +/** + * Internal normalized version of {@link ScrollPositionCoordinates} that always + * has `left` and `top` coordinates. Must be a type to be assignable to HistoryStateValue. + * + * @internal + */ +declare type _ScrollPositionNormalized = { + behavior?: ScrollOptions['behavior']; + left: number; + top: number; +}; + +/** + * 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 + * } + * }) + * ``` + */ +export declare const START_LOCATION: RouteLocationNormalizedLoaded; + +/** + * 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 `?` + */ +export declare function stringifyQuery(query: LocationQueryRaw): string; + +/** + * Allows customizing existing types of the router that are used globally like `$router`, ``, etc. **ONLY FOR INTERNAL USAGE**. + * + * - `$router` - the router instance + * - `$route` - the current route location + * - `beforeRouteEnter` - Page component option + * - `beforeRouteUpdate` - Page component option + * - `beforeRouteLeave` - Page component option + * - `RouterLink` - RouterLink Component + * - `RouterView` - RouterView Component + * + * @internal + */ +export declare interface TypesConfig { +} + +/** + * Returns the internal behavior of a {@link RouterLink} without the rendering part. + * + * @param props - a `to` location and an optional `replace` flag + */ +export declare function useLink(props: UseLinkOptions): UseLinkReturn; + +/** + * Options passed to {@link useLink}. + */ +export declare interface UseLinkOptions { + to: MaybeRef | RouteLocationAsPath | RouteLocationRaw>; + replace?: MaybeRef; +} + +/** + * Return type of {@link useLink}. + * @internal + */ +export declare interface UseLinkReturn { + route: ComputedRef>; + href: ComputedRef; + isActive: ComputedRef; + isExactActive: ComputedRef; + navigate(e?: MouseEvent): Promise; +} + +/** + * Returns the current route location. Equivalent to using `$route` inside + * templates. + */ +export declare function useRoute(_name?: Name): RouteLocationNormalizedLoaded; + +/** + * Returns the router instance. Equivalent to using `$router` inside + * templates. + */ +export declare function useRouter(): Router; + +/** + * Allows overriding the router view depth to control which component in + * `matched` is rendered. rvd stands for Router View Depth + * + * @internal + */ +export declare const viewDepthKey: InjectionKey>; + +export { } + +/** + * NOTE: this used to be `@vue/runtime-core` but it should have been `vue` for a long time. Using both declaration at + * the same time breaks so using only one everywhere is the preferred way. + */ +declare module 'vue' { + export interface ComponentCustomOptions { + /** + * Guard called when the router is navigating to the route that is rendering + * this component from a different route. Differently from `beforeRouteUpdate` + * and `beforeRouteLeave`, `beforeRouteEnter` does not have access to the + * component instance through `this` because it triggers before the component + * is even mounted. + * + * @param to - RouteLocationRaw we are navigating to + * @param from - RouteLocationRaw we are navigating from + * @param next - function to validate, cancel or modify (by redirecting) the + * navigation + */ + beforeRouteEnter?: TypesConfig extends Record<'beforeRouteEnter', infer T> + ? T + : NavigationGuardWithThis + + /** + * Guard called whenever the route that renders this component has changed, but + * it is reused for the new route. This allows you to guard for changes in + * params, the query or the hash. + * + * @param to - RouteLocationRaw we are navigating to + * @param from - RouteLocationRaw we are navigating from + * @param next - function to validate, cancel or modify (by redirecting) the + * navigation + */ + beforeRouteUpdate?: TypesConfig extends Record<'beforeRouteUpdate', infer T> + ? T + : NavigationGuard + + /** + * Guard called when the router is navigating away from the current route that + * is rendering this component. + * + * @param to - RouteLocationRaw we are navigating to + * @param from - RouteLocationRaw we are navigating from + * @param next - function to validate, cancel or modify (by redirecting) the + * navigation + */ + beforeRouteLeave?: TypesConfig extends Record<'beforeRouteLeave', infer T> + ? T + : NavigationGuard + } + + export interface ComponentCustomProperties { + /** + * Normalized current location. See {@link RouteLocationNormalizedLoaded}. + */ + $route: TypesConfig extends Record<'$route', infer T> + ? T + : RouteLocationNormalizedLoaded + /** + * {@link Router} instance used by the application. + */ + $router: TypesConfig extends Record<'$router', infer T> ? T : Router + } + + export interface GlobalComponents { + RouterView: TypesConfig extends Record<'RouterView', infer T> + ? T + : typeof RouterView + RouterLink: TypesConfig extends Record<'RouterLink', infer T> + ? T + : typeof RouterLink + } +} diff --git a/node_modules/vue-router/dist/vue-router.esm-browser.js b/node_modules/vue-router/dist/vue-router.esm-browser.js new file mode 100644 index 0000000..0120651 --- /dev/null +++ b/node_modules/vue-router/dist/vue-router.esm-browser.js @@ -0,0 +1,3741 @@ +/*! + * vue-router v4.4.5 + * (c) 2024 Eduardo San Martin Morote + * @license MIT + */ +import { getCurrentInstance, inject, onUnmounted, onDeactivated, onActivated, computed, unref, watchEffect, defineComponent, reactive, h, provide, ref, watch, shallowRef, shallowReactive, nextTick } from 'vue'; +import { setupDevtoolsPlugin } from '@vue/devtools-api'; + +const isBrowser = typeof document !== 'undefined'; + +/** + * 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' || + // support CF with dynamic imports that do not + // add the Module string tag + (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 warn(msg) { + // avoid using ...args as it breaks in older Edge builds + const args = Array.from(arguments).slice(1); + console.warn.apply(console, ['[Vue Router warn]: ' + msg].concat(args)); +} + +/** + * 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; // %23 +const AMPERSAND_RE = /&/g; // %26 +const SLASH_RE = /\//g; // %2F +const EQUAL_RE = /=/g; // %3D +const IM_RE = /\?/g; // %3F +const 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) { + warn(`Error decoding "${text}". Using original value`); + } + return '' + text; +} + +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: decode(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 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, 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 (!from.startsWith('/')) { + warn(`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]; + // make . and ./ the same (../ === .., ../../ === ../..) + // this is the same behavior as new URL() + if (lastToSegment === '..' || lastToSegment === '.') { + toSegments.push(''); + } + 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.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: '/', + // TODO: could we use a symbol in the future? + name: undefined, + params: {}, + query: {}, + hash: '', + fullPath: '/', + matched: [], + meta: {}, + redirectedFrom: undefined, +}; + +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 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 hash +const 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.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 (typeof position.el === 'string') { + if (!isIdSelector || !document.getElementById(position.el.slice(1))) { + try { + const foundEl = document.querySelector(position.el); + if (isIdSelector && foundEl) { + warn(`The selector "${position.el}" should be passed as "el: document.querySelector('${position.el}')" because it starts with "#".`); + // return to avoid other warnings + return; + } + } + catch (err) { + warn(`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 to avoid other warnings + return; + } + } + } + const el = typeof positionEl === 'string' + ? isIdSelector + ? document.getElementById(positionEl.slice(1)) + : document.querySelector(positionEl) + : positionEl; + if (!el) { + warn(`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) { + 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 { +// // 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 = { +// compute: computeScroll, +// scroll: scrollToPosition, +// } + +let createBaseLocation = () => location.protocol + '//' + location.host; +/** + * Creates a normalized history location from a window.location object + * @param base - The base path + * @param location - The window.location object + */ +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); + } + // 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); + // TODO: could we use 'pagehide' or 'visibilitychange' instead? + // https://developer.chrome.com/blog/page-lifecycle-api/ + window.addEventListener('beforeunload', beforeUnloadListener, { + passive: true, + }); + 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 `` 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) { + { + warn('Error with push/replace State', 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(), + }); + if (!history.state) { + warn(`history.state seems to have been manually replaced without preserving the necessary values. Make sure to preserve existing history state if you are manually calling history.replaceState:\n\n` + + `history.replaceState(history.state, '', url)\n\n` + + `You can find more information at https://router.vuejs.org/guide/migration/#Usage-of-history-state`); + } + 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 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 `` 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 `` 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 += '#'; + if (!base.endsWith('#/') && !base.endsWith('#')) { + warn(`A hash base must end with a "#":\n"${base}" should be "${base.replace(/#.*$/, '#')}".`); + } + return createWebHistory(base); +} + +function isRouteLocation(route) { + return typeof route === 'string' || (route && typeof route === 'object'); +} +function isRouteName(name) { + return typeof name === 'string' || typeof name === 'symbol'; +} + +const NavigationFailureSymbol = Symbol('navigation failure' ); +/** + * Enumeration with all possible types for navigation failures. Can be passed to + * {@link isNavigationFailure} to check for specific failures. + */ +var NavigationFailureType; +(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"; +})(NavigationFailureType || (NavigationFailureType = {})); +// DEV only debug messages +const 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}".`; + }, +}; +/** + * Creates a typed NavigationFailure object. + * @internal + * @param type - NavigationFailureType + * @param params - { from, to } + */ +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 (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); +} + +// 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 tokens +const 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() +function tokenizePath(path) { + if (!path) + return [[]]; + if (path === '/') + return [[ROOT_TOKEN]]; + if (!path.startsWith('/')) { + throw new Error(`Route paths should start with a "/": "${path}" should be "/${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); + // warn against params with the same name + { + const existingKeys = new Set(); + for (const key of parser.keys) { + if (existingKeys.has(key.name)) + warn(`Found duplicated params with name "${key.name}" for path "${record.path}". Only the last one will be available on "$route.params".`); + existingKeys.add(key.name); + } + } + 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); + { + checkChildMissingNameWithEmptyPath(mainNormalizedRecord, parent); + } + // 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( + // we need to normalize again to ensure the `mods` property + // being non enumerable + normalizeRouteRecord(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); + } + if (normalizedRecord.path === '*') { + throw new Error('Catch all routes ("*") must now be defined using a param with a custom regexp.\n' + + 'See more at https://router.vuejs.org/guide/migration/#Removed-star-or-catch-all-routes.'); + } + // create the object beforehand, so it can be passed to children + matcher = createRouteRecordMatcher(normalizedRecord, parent, options); + if (parent && path[0] === '/') + checkMissingParamsInAbsolutePath(matcher, parent); + // 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); + { + checkSameParams(originalRecord, 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); + } + // 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 (isMatchable(matcher)) { + insertMatcher(matcher); + } + 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) + // } + } + 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) { + const index = findInsertionIndex(matcher, matchers); + matchers.splice(index, 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, + }); + // warn if the user is passing invalid params so they can debug it better when they get removed + { + const invalidParams = Object.keys(location.params || {}).filter(paramName => !matcher.keys.find(k => k.name === paramName)); + if (invalidParams.length) { + warn(`Discarded invalid param(s) "${invalidParams.join('", "')}" when navigating. See https://github.com/vuejs/router/blob/main/packages/router/CHANGELOG.md#414-2022-08-22 for more details.`); + } + } + name = matcher.record.name; + params = assign( + // paramsFromLocation is a new object + paramsFromLocation(currentLocation.params, + // only keep params that exist in the resolved location + // only keep optional params coming from a parent record + matcher.keys + .filter(k => !k.optional) + .concat(matcher.parent ? matcher.parent.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 (location.path != null) { + // 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; + if (!path.startsWith('/')) { + warn(`The Matcher cannot resolve relative paths but received "${path}". Unless you directly called \`matcher.resolve("${path}")\`, this is probably a bug in vue-router. Please open an issue at https://github.com/vuejs/router/issues/new/choose.`); + } + 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)); + function clearRoutes() { + matchers.length = 0; + matcherMap.clear(); + } + return { + addRoute, + resolve, + removeRoute, + clearRoutes, + 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) { + const normalized = { + path: record.path, + redirect: record.redirect, + name: record.name, + meta: record.meta || {}, + aliasOf: record.aliasOf, + beforeEnter: record.beforeEnter, + props: normalizeRecordProps(record), + children: record.children || [], + instances: {}, + leaveGuards: new Set(), + updateGuards: new Set(), + enterCallbacks: {}, + // must be declared afterwards + // mods: {}, + components: 'components' in record + ? record.components || null + : record.component && { default: record.component }, + }; + // mods contain modules and shouldn't be copied, + // logged or anything. It's just used for internal + // advanced use cases like data loaders + Object.defineProperty(normalized, 'mods', { + value: {}, + }); + return normalized; +} +/** + * 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 === 'object' ? props[name] : props; + } + 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 isSameParam(a, b) { + return (a.name === b.name && + a.optional === b.optional && + a.repeatable === b.repeatable); +} +/** + * Check if a path and its alias have the same required params + * + * @param a - original record + * @param b - alias record + */ +function checkSameParams(a, b) { + for (const key of a.keys) { + if (!key.optional && !b.keys.find(isSameParam.bind(null, key))) + return warn(`Alias "${b.record.path}" and the original record: "${a.record.path}" must have the exact same param named "${key.name}"`); + } + for (const key of b.keys) { + if (!key.optional && !a.keys.find(isSameParam.bind(null, key))) + return warn(`Alias "${b.record.path}" and the original record: "${a.record.path}" must have the exact same param named "${key.name}"`); + } +} +/** + * A route with a name and a child with an empty path without a name should warn when adding the route + * + * @param mainNormalizedRecord - RouteRecordNormalized + * @param parent - RouteRecordMatcher + */ +function checkChildMissingNameWithEmptyPath(mainNormalizedRecord, parent) { + if (parent && + parent.record.name && + !mainNormalizedRecord.name && + !mainNormalizedRecord.path) { + warn(`The route named "${String(parent.record.name)}" has a child without a name and an empty path. Using that name won't render the empty path child so you probably want to move the name to the child instead. If this is intentional, add a name to the child route to remove the warning.`); + } +} +function checkMissingParamsInAbsolutePath(record, parent) { + for (const key of parent.keys) { + if (!record.keys.find(isSameParam.bind(null, key))) + return warn(`Absolute path "${record.record.path}" must have the exact same param named "${key.name}" as its parent "${parent.record.path}".`); + } +} +/** + * Performs a binary search to find the correct insertion index for a new matcher. + * + * Matchers are primarily sorted by their score. If scores are tied then we also consider parent/child relationships, + * with descendants coming before ancestors. If there's still a tie, new routes are inserted after existing routes. + * + * @param matcher - new matcher to be inserted + * @param matchers - existing matchers + */ +function findInsertionIndex(matcher, matchers) { + // First phase: binary search based on score + let lower = 0; + let upper = matchers.length; + while (lower !== upper) { + const mid = (lower + upper) >> 1; + const sortOrder = comparePathParserScore(matcher, matchers[mid]); + if (sortOrder < 0) { + upper = mid; + } + else { + lower = mid + 1; + } + } + // Second phase: check for an ancestor with the same score + const insertionAncestor = getInsertionAncestor(matcher); + if (insertionAncestor) { + upper = matchers.lastIndexOf(insertionAncestor, upper - 1); + if (upper < 0) { + // This should never happen + warn(`Finding ancestor route "${insertionAncestor.record.path}" failed for "${matcher.record.path}"`); + } + } + return upper; +} +function getInsertionAncestor(matcher) { + let ancestor = matcher; + while ((ancestor = ancestor.parent)) { + if (isMatchable(ancestor) && + comparePathParserScore(matcher, ancestor) === 0) { + return ancestor; + } + } + return; +} +/** + * Checks if a matcher can be reachable. This means if it's possible to reach it as a route. For example, routes without + * a component, or name, or redirect, are just used to group other routes. + * @param matcher + * @param matcher.record record of the matcher + * @returns + */ +function isMatchable({ record }) { + return !!(record.name || + (record.components && Object.keys(record.components).length) || + record.redirect); +} + +/** + * 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('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('router view depth' ); +/** + * Allows overriding the router instance returned by `useRouter` in tests. r + * stands for router + * + * @internal + */ +const routerKey = Symbol('router' ); +/** + * Allows overriding the current route returned by `useRoute` in tests. rl + * stands for route location + * + * @internal + */ +const routeLocationKey = Symbol('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('router view location' ); + +/** + * 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, + }; +} + +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 (!getCurrentInstance()) { + warn('getCurrentInstance() returned null. onBeforeRouteLeave() must be called at the top of a setup function'); + return; + } + const activeRecord = inject(matchedRouteKey, + // to avoid warning + {}).value; + if (!activeRecord) { + warn('No active route record was found when calling `onBeforeRouteLeave()`. Make sure you call this function inside a component child of . 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 (!getCurrentInstance()) { + warn('getCurrentInstance() returned null. onBeforeRouteUpdate() must be called at the top of a setup function'); + return; + } + const activeRecord = inject(matchedRouteKey, + // to avoid warning + {}).value; + if (!activeRecord) { + warn('No active route record was found when calling `onBeforeRouteUpdate()`. Make sure you call this function inside a component child of . Maybe you called it inside of App.vue?'); + return; + } + registerGuard(activeRecord, 'updateGuards', updateGuard); +} +function guardToPromiseFn(guard, to, from, record, name, runWithContext = fn => fn()) { + // 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 = runWithContext(() => guard.call(record && record.instances[name], to, from, canOnlyBeCalledOnce(next, to, from) )); + let guardCall = Promise.resolve(guardReturn); + if (guard.length < 3) + guardCall = guardCall.then(next); + if (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 => { + // @ts-expect-error: _called is added at canOnlyBeCalledOnce + if (!next._called) { + warn(message); + return Promise.reject(new Error('Invalid navigation guard')); + } + return resolvedValue; + }); + } + else if (guardReturn !== undefined) { + // @ts-expect-error: _called is added at canOnlyBeCalledOnce + if (!next._called) { + warn(message); + reject(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(`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.`); + // @ts-expect-error: we put it in the original one because it's easier to check + 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 (!record.components && !record.children.length) { + warn(`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 (!rawComponent || + (typeof rawComponent !== 'object' && + typeof rawComponent !== 'function')) { + warn(`Component "${name}" in record with path "${record.path}" is not` + + ` a valid component. Received "${String(rawComponent)}".`); + // throw to ensure we stop here but warn to ensure the message isn't + // missed by the user + throw new Error('Invalid route component'); + } + else if ('then' in rawComponent) { + // warn if user wrote import('/component.vue') instead of () => + // import('./component.vue') + warn(`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 && + // warn only once per component + !rawComponent.__warnedDefineAsync) { + rawComponent.__warnedDefineAsync = true; + warn(`Component "${name}" in record with path "${record.path}" is defined ` + + `using "defineAsyncComponent()". ` + + `Write "() => import('./MyPage.vue')" instead of ` + + `"defineAsyncComponent(() => import('./MyPage.vue'))".`); + } + } + // 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, runWithContext)); + } + else { + // start requesting the chunk already + let componentPromise = rawComponent(); + if (!('catch' in componentPromise)) { + warn(`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; + // keep the resolved module for plugins like data loaders + record.mods[name] = 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, runWithContext)()); + })); + } + } + } + return guards; +} +/** + * Ensures a route is loaded, so it can be passed as o prop to ``. + * + * @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; + // keep the resolved module for plugins like data loaders + record.mods[name] = 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 RFC +/** + * Returns the internal behavior of a {@link RouterLink} without the rendering part. + * + * @param props - a `to` location and an optional `replace` flag + */ +function useLink(props) { + const router = inject(routerKey); + const currentRoute = inject(routeLocationKey); + let hasPrevious = false; + let previousTo = null; + const route = computed(() => { + const to = unref(props.to); + if ((!hasPrevious || to !== previousTo)) { + if (!isRouteLocation(to)) { + if (hasPrevious) { + warn(`Invalid value for prop "to" in useLink()\n- to:`, to, `\n- previous to:`, previousTo, `\n- props:`, props); + } + else { + warn(`Invalid value for prop "to" in useLink()\n- to:`, to, `\n- props:`, props); + } + } + previousTo = to; + hasPrevious = true; + } + return router.resolve(to); + }); + const activeRecordIndex = 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 = computed(() => activeRecordIndex.value > -1 && + includesParams(currentRoute.params, route.value.params)); + const isExactActive = computed(() => activeRecordIndex.value > -1 && + activeRecordIndex.value === currentRoute.matched.length - 1 && + isSameRouteLocationParams(currentRoute.params, route.value.params)); + function navigate(e = {}) { + if (guardEvent(e)) { + return router[unref(props.replace) ? 'replace' : 'push'](unref(props.to) + // avoid uncaught errors are they are logged anyway + ).catch(noop); + } + return Promise.resolve(); + } + // devtools only + if (isBrowser) { + const instance = getCurrentInstance(); + if (instance) { + const linkContextDevtools = { + route: route.value, + isActive: isActive.value, + isExactActive: isExactActive.value, + error: null, + }; + // @ts-expect-error: this is internal + instance.__vrl_devtools = instance.__vrl_devtools || []; + // @ts-expect-error: this is internal + instance.__vrl_devtools.push(linkContextDevtools); + watchEffect(() => { + linkContextDevtools.route = route.value; + linkContextDevtools.isActive = isActive.value; + linkContextDevtools.isExactActive = isExactActive.value; + linkContextDevtools.error = isRouteLocation(unref(props.to)) + ? null + : 'Invalid "to" value'; + }, { flush: 'post' }); + } + } + /** + * NOTE: update {@link _RouterLinkI}'s `$slots` type when updating this + */ + return { + route, + href: computed(() => route.value.href), + isActive, + isExactActive, + navigate, + }; +} +const RouterLinkImpl = /*#__PURE__*/ 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 = reactive(useLink(props)); + const { options } = inject(routerKey); + const elClass = 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 + : 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__*/ 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 }) { + warnDeprecatedUsage(); + const injectedRoute = inject(routerViewLocationKey); + const routeToDisplay = computed(() => props.route || injectedRoute.value); + const injectedDepth = 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 = computed(() => { + let initialDepth = unref(injectedDepth); + const { matched } = routeToDisplay.value; + let matchedRoute; + while ((matchedRoute = matched[initialDepth]) && + !matchedRoute.components) { + initialDepth++; + } + return initialDepth; + }); + const matchedRouteRef = computed(() => routeToDisplay.value.matched[depth.value]); + provide(viewDepthKey, computed(() => depth.value + 1)); + provide(matchedRouteKey, matchedRouteRef); + provide(routerViewLocationKey, routeToDisplay); + const viewRef = ref(); + // watch at the same time the component instance, the route record we are + // rendering, and the name + 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 = h(ViewComponent, assign({}, routeProps, attrs, { + onVnodeUnmounted, + ref: viewRef, + })); + if (isBrowser && + component.ref) { + // TODO: can display if it's an alias, its props + const info = { + depth: depth.value, + name: matchedRoute.name, + path: matchedRoute.path, + meta: matchedRoute.meta, + }; + const internalInstances = isArray(component.ref) + ? component.ref.map(r => r.i) + : [component.ref.i]; + internalInstances.forEach(instance => { + // @ts-expect-error + instance.__vrv_devtools = info; + }); + } + return ( + // pass the vnode to the slot as a prop. + // h and 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; +// warn against deprecated usage with & +// due to functional component being no longer eager in Vue 3 +function warnDeprecatedUsage() { + const instance = getCurrentInstance(); + const parentName = instance.parent && instance.parent.type.name; + const parentSubTreeType = instance.parent && instance.parent.subTree && instance.parent.subTree.type; + if (parentName && + (parentName === 'KeepAlive' || parentName.includes('Transition')) && + typeof parentSubTreeType === 'object' && + parentSubTreeType.name === 'RouterView') { + const comp = parentName === 'KeepAlive' ? 'keep-alive' : 'transition'; + warn(` can no longer be used directly inside or .\n` + + `Use slot props instead:\n\n` + + `\n` + + ` <${comp}>\n` + + ` \n` + + ` \n` + + ``); + } +} + +/** + * 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, { + // remove variables that can contain vue instances + 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, + }, + }; +} +// to support multiple router instances +let routerId = 0; +function addDevtools(app, router, matcher) { + // Take over router.beforeEach and afterEach + // make sure we are not registering the devtool twice + if (router.__hasDevtools) + return; + router.__hasDevtools = true; + // increment to support multiple router instances + 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') { + console.warn('[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.'); + } + // display state added by the router + 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'), + }); + } + }); + // mark router-link as active and display tags on router views + 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 multiple useLink are used + 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, () => { + // refresh active state + refreshRoutesView(); + api.notifyComponentUpdate(); + api.sendInspectorTree(routerInspectorId); + api.sendInspectorState(routerInspectorId); + }); + const navigationsLayerId = 'router:navigations:' + id; + api.addTimelineLayer({ + id: navigationsLayerId, + label: `Router${id ? ' ' + id : ''} Navigations`, + color: 0x40a8c4, + }); + // const errorsLayerId = 'router:errors' + // api.addTimelineLayer({ + // id: errorsLayerId, + // label: 'Router Errors', + // color: 0xea5455, + // }) + 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, + }, + }); + }); + // attached to `meta` and used to group events + 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'), + }; + // Used to group navigations together, hide from devtools + 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('✅'); + } + // we set here to have the right order + 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() { + // the routes view isn't active + if (!activeRoutesPayload) + return; + const payload = activeRoutesPayload; + // children routes will appear as nested + let routes = matcher.getRoutes().filter(route => !route.parent || + // these routes have a parent with no component which will not appear in the view + // therefore we still need to include them + !route.parent.record.components); + // reset match state to false + routes.forEach(resetMatchStateOnRouteRecord); + // apply a match state if there is a payload + if (payload.filter) { + routes = routes.filter(route => + // save matches state based on the payload + isRouteMatching(route, payload.filter.toLowerCase())); + } + // mark active routes + 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 routes = matcher.getRoutes(); + const route = routes.find(route => route.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 = 0xec4899; +const BLUE_600 = 0x2563eb; +const LIME_500 = 0x84cc16; +const CYAN_400 = 0x22d3ee; +const ORANGE_400 = 0xfb923c; +// const GRAY_100 = 0xf4f4f5 +const DARK = 0x666666; +const RED_100 = 0xfee2e2; +const RED_700 = 0xb91c1c; +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: 0xffffff, + backgroundColor: DARK, + }); + } + // add an id to be able to select it. Using the `path` is not possible because + // empty path children would collide with their parents + 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), + }; +} +// incremental id for route records and inspector state +let routeRecordId = 0; +const EXTRACT_REGEXP_RE = /^\/(.*)\/([a-z]*)$/; +function markRouteRecordActive(route, currentRoute) { + // no route will be active if matched is empty + // reset the matching state + 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; + } + // use a regexp without $ at the end to match nested routes better + const nonEndingRE = new RegExp(found[1].replace(/\$$/, ''), found[2]); + if (nonEndingRE.test(filter)) { + // mark children as matches + route.children.forEach(child => isRouteMatching(child, filter)); + // exception case: `/` + if (route.record.path !== '/' || filter === '/') { + route.__vd_match = route.re.test(filter); + return true; + } + // hide the / route + return false; + } + const path = route.record.path.toLowerCase(); + const decodedPath = decode(path); + // also allow partial matching on the 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)) { + // @ts-expect-error + ret[key] = obj[key]; + } + } + return ret; +} + +/** + * 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; + if (!routerHistory) + throw new Error('Provide the "history" option when calling "createRouter()":' + + ' https://router.vuejs.org/api/interfaces/RouterOptions.html#history'); + const beforeGuards = useCallbacks(); + const beforeResolveGuards = useCallbacks(); + const afterGuards = useCallbacks(); + const currentRoute = 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); + if (!parent) { + warn(`Parent route "${String(parentOrRoute)}" not found when adding child route`, route); + } + record = route; + } + else { + record = parentOrRoute; + } + return matcher.addRoute(record, parent); + } + function removeRoute(name) { + const recordMatcher = matcher.getRecordMatcher(name); + if (recordMatcher) { + matcher.removeRoute(recordMatcher); + } + else { + warn(`Cannot remove non-existent route "${String(name)}"`); + } + } + function getRoutes() { + return matcher.getRoutes().map(routeMatcher => routeMatcher.record); + } + function hasRoute(name) { + return !!matcher.getRecordMatcher(name); + } + function resolve(rawLocation, currentLocation) { + // const resolve: Router['resolve'] = (rawLocation: RouteLocationRaw, 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); + { + if (href.startsWith('//')) + warn(`Location "${rawLocation}" resolved to "${href}". A resolved location cannot start with multiple slashes.`); + else if (!matchedRoute.matched.length) { + warn(`No match found for location with path "${rawLocation}"`); + } + } + // locationNormalized is always a new object + return assign(locationNormalized, matchedRoute, { + params: decodeParams(matchedRoute.params), + hash: decode(locationNormalized.hash), + redirectedFrom: undefined, + href, + }); + } + if (!isRouteLocation(rawLocation)) { + warn(`router.resolve() was passed an invalid location. This will fail in production.\n- Location:`, rawLocation); + return resolve({}); + } + let matcherLocation; + // path could be relative in object as well + if (rawLocation.path != null) { + if ('params' in rawLocation && + !('name' in rawLocation) && + // @ts-expect-error: the type is never + Object.keys(rawLocation.params).length) { + warn(`Path "${rawLocation.path}" was passed with params but they will be ignored. Use a named route alongside params instead.`); + } + 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(targetParams), + }); + // 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 || ''; + if (hash && !hash.startsWith('#')) { + warn(`A \`hash\` should always start with the character "#". Replace "${hash}" with "#${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); + { + if (href.startsWith('//')) { + warn(`Location "${rawLocation}" resolved to "${href}". A resolved location cannot start with multiple slashes.`); + } + else if (!matchedRoute.matched.length) { + warn(`No match found for location with path "${rawLocation.path != null ? rawLocation.path : rawLocation}"`); + } + } + 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 = {}; + } + if (newTargetLocation.path == null && + !('name' in newTargetLocation)) { + warn(`Invalid redirect found:\n${JSON.stringify(newTargetLocation, null, 2)}\n when navigating to "${to.fullPath}". A redirect must contain a name or path. This will break in production.`); + throw new Error('Invalid redirect'); + } + return assign({ + query: to.query, + hash: to.hash, + // avoid transferring params if the redirect has a path + params: newTargetLocation.path != null ? {} : 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 */)) { + if (// we are redirecting to the same location we were already at + isSameRouteLocation(stringifyQuery$1, resolve(failure.to), toLocation) && + // and we have done it a couple of times + redirectedFrom && + // @ts-expect-error: added only in dev + (redirectedFrom._count = redirectedFrom._count + ? // @ts-expect-error + redirectedFrom._count + 1 + : 1) > 30) { + warn(`Detected a possibly infinite redirection in a navigation guard when going from "${from.fullPath}" to "${toLocation.fullPath}". Aborting to avoid a Stack Overflow.\n Are you always returning a new location within a navigation guard? That would lead to this error. Only return when redirecting or aborting, that should fix this. This might break in production if not fixed.`); + return Promise.reject(new Error('Infinite redirect in navigation guard')); + } + 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(); + } + function runWithContext(fn) { + const app = installedApps.values().next().value; + // support Vue < 3.3 + return app && typeof app.runWithContext === 'function' + ? app.runWithContext(fn) + : fn(); + } + // 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 enteringRecords) { + // do not trigger beforeEnter on reused views + if (record.beforeEnter) { + 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 + // clear existing enterCallbacks, these are added by extractComponentsGuards + to.matched.forEach(record => (record.enterCallbacks = {})); + // check in-component beforeRouteEnter + guards = extractComponentsGuards(enteringRecords, 'beforeRouteEnter', to, from, runWithContext); + 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 + afterGuards + .list() + .forEach(guard => runWithContext(() => 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); + }) + // avoid warnings in the console about uncaught rejections, they are logged by triggerErrors + .catch(noop); + }); + } + // Initialization and Errors + let readyHandlers = useCallbacks(); + let errorListeners = useCallbacks(); + let ready; + /** + * Trigger errorListeners 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 = errorListeners.list(); + if (list.length) { + list.forEach(handler => handler(error, to, from)); + } + else { + { + warn('uncaught error during route navigation:'); + } + console.error(error); + } + // reject the error no matter there were error listeners or not + 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 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, + clearRoutes: matcher.clearRoutes, + hasRoute, + getRoutes, + resolve, + options, + push, + replace, + go, + back: () => go(-1), + forward: () => go(1), + beforeEach: beforeGuards.add, + beforeResolve: beforeResolveGuards.add, + afterEach: afterGuards.add, + onError: errorListeners.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: () => 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 => { + warn('Unexpected error when starting the router:', err); + }); + } + const reactiveRoute = {}; + for (const key in START_LOCATION_NORMALIZED) { + Object.defineProperty(reactiveRoute, key, { + get: () => currentRoute.value[key], + enumerable: true, + }); + } + app.provide(routerKey, router); + app.provide(routeLocationKey, shallowReactive(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(); + }; + // TODO: this probably needs to be updated so it can be used by vue-termui + if (isBrowser) { + addDevtools(app, router, matcher); + } + }, + }; + // TODO: type this as NavigationGuardReturn or similar instead of any + function runGuardQueue(guards) { + return guards.reduce((promise, guard) => promise.then(() => runWithContext(guard)), Promise.resolve()); + } + return router; +} +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 inject(routerKey); +} +/** + * Returns the current route location. Equivalent to using `$route` inside + * templates. + */ +function useRoute(_name) { + return inject(routeLocationKey); +} + +export { NavigationFailureType, RouterLink, RouterView, START_LOCATION_NORMALIZED as START_LOCATION, createMemoryHistory, createRouter, createRouterMatcher, createWebHashHistory, createWebHistory, isNavigationFailure, loadRouteLocation, matchedRouteKey, onBeforeRouteLeave, onBeforeRouteUpdate, parseQuery, routeLocationKey, routerKey, routerViewLocationKey, stringifyQuery, useLink, useRoute, useRouter, viewDepthKey }; diff --git a/node_modules/vue-router/dist/vue-router.esm-bundler.js b/node_modules/vue-router/dist/vue-router.esm-bundler.js new file mode 100644 index 0000000..78c61c2 --- /dev/null +++ b/node_modules/vue-router/dist/vue-router.esm-bundler.js @@ -0,0 +1 @@ +export * from '../dist/vue-router.mjs' \ No newline at end of file diff --git a/node_modules/vue-router/dist/vue-router.global.js b/node_modules/vue-router/dist/vue-router.global.js new file mode 100644 index 0000000..1479c3a --- /dev/null +++ b/node_modules/vue-router/dist/vue-router.global.js @@ -0,0 +1,3934 @@ +/*! + * vue-router v4.4.5 + * (c) 2024 Eduardo San Martin Morote + * @license MIT + */ +var VueRouter = (function (exports, vue) { + 'use strict'; + + const isBrowser = typeof document !== 'undefined'; + + /** + * 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' || + // support CF with dynamic imports that do not + // add the Module string tag + (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 warn(msg) { + // avoid using ...args as it breaks in older Edge builds + const args = Array.from(arguments).slice(1); + console.warn.apply(console, ['[Vue Router warn]: ' + msg].concat(args)); + } + + /** + * 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; // %23 + const AMPERSAND_RE = /&/g; // %26 + const SLASH_RE = /\//g; // %2F + const EQUAL_RE = /=/g; // %3D + const IM_RE = /\?/g; // %3F + const 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) { + warn(`Error decoding "${text}". Using original value`); + } + return '' + text; + } + + 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: decode(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 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, 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 (!from.startsWith('/')) { + warn(`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]; + // make . and ./ the same (../ === .., ../../ === ../..) + // this is the same behavior as new URL() + if (lastToSegment === '..' || lastToSegment === '.') { + toSegments.push(''); + } + 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.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: '/', + // TODO: could we use a symbol in the future? + name: undefined, + params: {}, + query: {}, + hash: '', + fullPath: '/', + matched: [], + meta: {}, + redirectedFrom: undefined, + }; + + 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 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 hash + const 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.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 (typeof position.el === 'string') { + if (!isIdSelector || !document.getElementById(position.el.slice(1))) { + try { + const foundEl = document.querySelector(position.el); + if (isIdSelector && foundEl) { + warn(`The selector "${position.el}" should be passed as "el: document.querySelector('${position.el}')" because it starts with "#".`); + // return to avoid other warnings + return; + } + } + catch (err) { + warn(`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 to avoid other warnings + return; + } + } + } + const el = typeof positionEl === 'string' + ? isIdSelector + ? document.getElementById(positionEl.slice(1)) + : document.querySelector(positionEl) + : positionEl; + if (!el) { + warn(`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) { + 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 { + // // 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 = { + // compute: computeScroll, + // scroll: scrollToPosition, + // } + + let createBaseLocation = () => location.protocol + '//' + location.host; + /** + * Creates a normalized history location from a window.location object + * @param base - The base path + * @param location - The window.location object + */ + 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); + } + // 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); + // TODO: could we use 'pagehide' or 'visibilitychange' instead? + // https://developer.chrome.com/blog/page-lifecycle-api/ + window.addEventListener('beforeunload', beforeUnloadListener, { + passive: true, + }); + 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 `` 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) { + { + warn('Error with push/replace State', 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(), + }); + if (!history.state) { + warn(`history.state seems to have been manually replaced without preserving the necessary values. Make sure to preserve existing history state if you are manually calling history.replaceState:\n\n` + + `history.replaceState(history.state, '', url)\n\n` + + `You can find more information at https://router.vuejs.org/guide/migration/#Usage-of-history-state`); + } + 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 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 `` 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 `` 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 += '#'; + if (!base.endsWith('#/') && !base.endsWith('#')) { + warn(`A hash base must end with a "#":\n"${base}" should be "${base.replace(/#.*$/, '#')}".`); + } + return createWebHistory(base); + } + + function isRouteLocation(route) { + return typeof route === 'string' || (route && typeof route === 'object'); + } + function isRouteName(name) { + return typeof name === 'string' || typeof name === 'symbol'; + } + + const NavigationFailureSymbol = Symbol('navigation failure' ); + /** + * 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 messages + const 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}".`; + }, + }; + /** + * Creates a typed NavigationFailure object. + * @internal + * @param type - NavigationFailureType + * @param params - { from, to } + */ + 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 (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); + } + + // 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 tokens + const 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() + function tokenizePath(path) { + if (!path) + return [[]]; + if (path === '/') + return [[ROOT_TOKEN]]; + if (!path.startsWith('/')) { + throw new Error(`Route paths should start with a "/": "${path}" should be "/${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); + // warn against params with the same name + { + const existingKeys = new Set(); + for (const key of parser.keys) { + if (existingKeys.has(key.name)) + warn(`Found duplicated params with name "${key.name}" for path "${record.path}". Only the last one will be available on "$route.params".`); + existingKeys.add(key.name); + } + } + 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); + { + checkChildMissingNameWithEmptyPath(mainNormalizedRecord, parent); + } + // 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( + // we need to normalize again to ensure the `mods` property + // being non enumerable + normalizeRouteRecord(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); + } + if (normalizedRecord.path === '*') { + throw new Error('Catch all routes ("*") must now be defined using a param with a custom regexp.\n' + + 'See more at https://router.vuejs.org/guide/migration/#Removed-star-or-catch-all-routes.'); + } + // create the object beforehand, so it can be passed to children + matcher = createRouteRecordMatcher(normalizedRecord, parent, options); + if (parent && path[0] === '/') + checkMissingParamsInAbsolutePath(matcher, parent); + // 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); + { + checkSameParams(originalRecord, 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); + } + // 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 (isMatchable(matcher)) { + insertMatcher(matcher); + } + 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) + // } + } + 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) { + const index = findInsertionIndex(matcher, matchers); + matchers.splice(index, 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, + }); + // warn if the user is passing invalid params so they can debug it better when they get removed + { + const invalidParams = Object.keys(location.params || {}).filter(paramName => !matcher.keys.find(k => k.name === paramName)); + if (invalidParams.length) { + warn(`Discarded invalid param(s) "${invalidParams.join('", "')}" when navigating. See https://github.com/vuejs/router/blob/main/packages/router/CHANGELOG.md#414-2022-08-22 for more details.`); + } + } + name = matcher.record.name; + params = assign( + // paramsFromLocation is a new object + paramsFromLocation(currentLocation.params, + // only keep params that exist in the resolved location + // only keep optional params coming from a parent record + matcher.keys + .filter(k => !k.optional) + .concat(matcher.parent ? matcher.parent.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 (location.path != null) { + // 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; + if (!path.startsWith('/')) { + warn(`The Matcher cannot resolve relative paths but received "${path}". Unless you directly called \`matcher.resolve("${path}")\`, this is probably a bug in vue-router. Please open an issue at https://github.com/vuejs/router/issues/new/choose.`); + } + 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)); + function clearRoutes() { + matchers.length = 0; + matcherMap.clear(); + } + return { + addRoute, + resolve, + removeRoute, + clearRoutes, + 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) { + const normalized = { + path: record.path, + redirect: record.redirect, + name: record.name, + meta: record.meta || {}, + aliasOf: record.aliasOf, + beforeEnter: record.beforeEnter, + props: normalizeRecordProps(record), + children: record.children || [], + instances: {}, + leaveGuards: new Set(), + updateGuards: new Set(), + enterCallbacks: {}, + // must be declared afterwards + // mods: {}, + components: 'components' in record + ? record.components || null + : record.component && { default: record.component }, + }; + // mods contain modules and shouldn't be copied, + // logged or anything. It's just used for internal + // advanced use cases like data loaders + Object.defineProperty(normalized, 'mods', { + value: {}, + }); + return normalized; + } + /** + * 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 === 'object' ? props[name] : props; + } + 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 isSameParam(a, b) { + return (a.name === b.name && + a.optional === b.optional && + a.repeatable === b.repeatable); + } + /** + * Check if a path and its alias have the same required params + * + * @param a - original record + * @param b - alias record + */ + function checkSameParams(a, b) { + for (const key of a.keys) { + if (!key.optional && !b.keys.find(isSameParam.bind(null, key))) + return warn(`Alias "${b.record.path}" and the original record: "${a.record.path}" must have the exact same param named "${key.name}"`); + } + for (const key of b.keys) { + if (!key.optional && !a.keys.find(isSameParam.bind(null, key))) + return warn(`Alias "${b.record.path}" and the original record: "${a.record.path}" must have the exact same param named "${key.name}"`); + } + } + /** + * A route with a name and a child with an empty path without a name should warn when adding the route + * + * @param mainNormalizedRecord - RouteRecordNormalized + * @param parent - RouteRecordMatcher + */ + function checkChildMissingNameWithEmptyPath(mainNormalizedRecord, parent) { + if (parent && + parent.record.name && + !mainNormalizedRecord.name && + !mainNormalizedRecord.path) { + warn(`The route named "${String(parent.record.name)}" has a child without a name and an empty path. Using that name won't render the empty path child so you probably want to move the name to the child instead. If this is intentional, add a name to the child route to remove the warning.`); + } + } + function checkMissingParamsInAbsolutePath(record, parent) { + for (const key of parent.keys) { + if (!record.keys.find(isSameParam.bind(null, key))) + return warn(`Absolute path "${record.record.path}" must have the exact same param named "${key.name}" as its parent "${parent.record.path}".`); + } + } + /** + * Performs a binary search to find the correct insertion index for a new matcher. + * + * Matchers are primarily sorted by their score. If scores are tied then we also consider parent/child relationships, + * with descendants coming before ancestors. If there's still a tie, new routes are inserted after existing routes. + * + * @param matcher - new matcher to be inserted + * @param matchers - existing matchers + */ + function findInsertionIndex(matcher, matchers) { + // First phase: binary search based on score + let lower = 0; + let upper = matchers.length; + while (lower !== upper) { + const mid = (lower + upper) >> 1; + const sortOrder = comparePathParserScore(matcher, matchers[mid]); + if (sortOrder < 0) { + upper = mid; + } + else { + lower = mid + 1; + } + } + // Second phase: check for an ancestor with the same score + const insertionAncestor = getInsertionAncestor(matcher); + if (insertionAncestor) { + upper = matchers.lastIndexOf(insertionAncestor, upper - 1); + if (upper < 0) { + // This should never happen + warn(`Finding ancestor route "${insertionAncestor.record.path}" failed for "${matcher.record.path}"`); + } + } + return upper; + } + function getInsertionAncestor(matcher) { + let ancestor = matcher; + while ((ancestor = ancestor.parent)) { + if (isMatchable(ancestor) && + comparePathParserScore(matcher, ancestor) === 0) { + return ancestor; + } + } + return; + } + /** + * Checks if a matcher can be reachable. This means if it's possible to reach it as a route. For example, routes without + * a component, or name, or redirect, are just used to group other routes. + * @param matcher + * @param matcher.record record of the matcher + * @returns + */ + function isMatchable({ record }) { + return !!(record.name || + (record.components && Object.keys(record.components).length) || + record.redirect); + } + + /** + * 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('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('router view depth' ); + /** + * Allows overriding the router instance returned by `useRouter` in tests. r + * stands for router + * + * @internal + */ + const routerKey = Symbol('router' ); + /** + * Allows overriding the current route returned by `useRoute` in tests. rl + * stands for route location + * + * @internal + */ + const routeLocationKey = Symbol('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('router view location' ); + + /** + * 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, + }; + } + + 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) { + if (!vue.getCurrentInstance()) { + warn('getCurrentInstance() returned null. onBeforeRouteLeave() must be called at the top of a setup function'); + return; + } + const activeRecord = vue.inject(matchedRouteKey, + // to avoid warning + {}).value; + if (!activeRecord) { + warn('No active route record was found when calling `onBeforeRouteLeave()`. Make sure you call this function inside a component child of . 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 (!vue.getCurrentInstance()) { + warn('getCurrentInstance() returned null. onBeforeRouteUpdate() must be called at the top of a setup function'); + return; + } + const activeRecord = vue.inject(matchedRouteKey, + // to avoid warning + {}).value; + if (!activeRecord) { + warn('No active route record was found when calling `onBeforeRouteUpdate()`. Make sure you call this function inside a component child of . Maybe you called it inside of App.vue?'); + return; + } + registerGuard(activeRecord, 'updateGuards', updateGuard); + } + function guardToPromiseFn(guard, to, from, record, name, runWithContext = fn => fn()) { + // 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 = runWithContext(() => guard.call(record && record.instances[name], to, from, canOnlyBeCalledOnce(next, to, from) )); + let guardCall = Promise.resolve(guardReturn); + if (guard.length < 3) + guardCall = guardCall.then(next); + if (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 => { + // @ts-expect-error: _called is added at canOnlyBeCalledOnce + if (!next._called) { + warn(message); + return Promise.reject(new Error('Invalid navigation guard')); + } + return resolvedValue; + }); + } + else if (guardReturn !== undefined) { + // @ts-expect-error: _called is added at canOnlyBeCalledOnce + if (!next._called) { + warn(message); + reject(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(`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.`); + // @ts-expect-error: we put it in the original one because it's easier to check + 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 (!record.components && !record.children.length) { + warn(`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 (!rawComponent || + (typeof rawComponent !== 'object' && + typeof rawComponent !== 'function')) { + warn(`Component "${name}" in record with path "${record.path}" is not` + + ` a valid component. Received "${String(rawComponent)}".`); + // throw to ensure we stop here but warn to ensure the message isn't + // missed by the user + throw new Error('Invalid route component'); + } + else if ('then' in rawComponent) { + // warn if user wrote import('/component.vue') instead of () => + // import('./component.vue') + warn(`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 && + // warn only once per component + !rawComponent.__warnedDefineAsync) { + rawComponent.__warnedDefineAsync = true; + warn(`Component "${name}" in record with path "${record.path}" is defined ` + + `using "defineAsyncComponent()". ` + + `Write "() => import('./MyPage.vue')" instead of ` + + `"defineAsyncComponent(() => import('./MyPage.vue'))".`); + } + } + // 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, runWithContext)); + } + else { + // start requesting the chunk already + let componentPromise = rawComponent(); + if (!('catch' in componentPromise)) { + warn(`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; + // keep the resolved module for plugins like data loaders + record.mods[name] = 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, runWithContext)()); + })); + } + } + } + return guards; + } + /** + * Ensures a route is loaded, so it can be passed as o prop to ``. + * + * @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; + // keep the resolved module for plugins like data loaders + record.mods[name] = 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 RFC + /** + * Returns the internal behavior of a {@link RouterLink} without the rendering part. + * + * @param props - a `to` location and an optional `replace` flag + */ + function useLink(props) { + const router = vue.inject(routerKey); + const currentRoute = vue.inject(routeLocationKey); + let hasPrevious = false; + let previousTo = null; + const route = vue.computed(() => { + const to = vue.unref(props.to); + if ((!hasPrevious || to !== previousTo)) { + if (!isRouteLocation(to)) { + if (hasPrevious) { + warn(`Invalid value for prop "to" in useLink()\n- to:`, to, `\n- previous to:`, previousTo, `\n- props:`, props); + } + else { + warn(`Invalid value for prop "to" in useLink()\n- to:`, to, `\n- props:`, props); + } + } + previousTo = to; + hasPrevious = true; + } + return router.resolve(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(); + } + // devtools only + if (isBrowser) { + const instance = vue.getCurrentInstance(); + if (instance) { + const linkContextDevtools = { + route: route.value, + isActive: isActive.value, + isExactActive: isExactActive.value, + error: null, + }; + // @ts-expect-error: this is internal + instance.__vrl_devtools = instance.__vrl_devtools || []; + // @ts-expect-error: this is internal + instance.__vrl_devtools.push(linkContextDevtools); + vue.watchEffect(() => { + linkContextDevtools.route = route.value; + linkContextDevtools.isActive = isActive.value; + linkContextDevtools.isExactActive = isExactActive.value; + linkContextDevtools.error = isRouteLocation(vue.unref(props.to)) + ? null + : 'Invalid "to" value'; + }, { flush: 'post' }); + } + } + /** + * 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 }) { + warnDeprecatedUsage(); + 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, + })); + if (isBrowser && + component.ref) { + // TODO: can display if it's an alias, its props + const info = { + depth: depth.value, + name: matchedRoute.name, + path: matchedRoute.path, + meta: matchedRoute.meta, + }; + const internalInstances = isArray(component.ref) + ? component.ref.map(r => r.i) + : [component.ref.i]; + internalInstances.forEach(instance => { + // @ts-expect-error + instance.__vrv_devtools = info; + }); + } + return ( + // pass the vnode to the slot as a prop. + // h and 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; + // warn against deprecated usage with & + // due to functional component being no longer eager in Vue 3 + function warnDeprecatedUsage() { + const instance = vue.getCurrentInstance(); + const parentName = instance.parent && instance.parent.type.name; + const parentSubTreeType = instance.parent && instance.parent.subTree && instance.parent.subTree.type; + if (parentName && + (parentName === 'KeepAlive' || parentName.includes('Transition')) && + typeof parentSubTreeType === 'object' && + parentSubTreeType.name === 'RouterView') { + const comp = parentName === 'KeepAlive' ? 'keep-alive' : 'transition'; + warn(` can no longer be used directly inside or .\n` + + `Use slot props instead:\n\n` + + `\n` + + ` <${comp}>\n` + + ` \n` + + ` \n` + + ``); + } + } + + function getDevtoolsGlobalHook() { + return getTarget().__VUE_DEVTOOLS_GLOBAL_HOOK__; + } + function getTarget() { + // @ts-expect-error navigator and windows are not available in all environments + return (typeof navigator !== 'undefined' && typeof window !== 'undefined') + ? window + : typeof globalThis !== 'undefined' + ? globalThis + : {}; + } + const isProxyAvailable = typeof Proxy === 'function'; + + const HOOK_SETUP = 'devtools-plugin:setup'; + const HOOK_PLUGIN_SETTINGS_SET = 'plugin:settings:set'; + + let supported; + let perf; + function isPerformanceSupported() { + var _a; + if (supported !== undefined) { + return supported; + } + if (typeof window !== 'undefined' && window.performance) { + supported = true; + perf = window.performance; + } + else if (typeof globalThis !== 'undefined' && ((_a = globalThis.perf_hooks) === null || _a === void 0 ? void 0 : _a.performance)) { + supported = true; + perf = globalThis.perf_hooks.performance; + } + else { + supported = false; + } + return supported; + } + function now() { + return isPerformanceSupported() ? perf.now() : Date.now(); + } + + class ApiProxy { + constructor(plugin, hook) { + this.target = null; + this.targetQueue = []; + this.onQueue = []; + this.plugin = plugin; + this.hook = hook; + const defaultSettings = {}; + if (plugin.settings) { + for (const id in plugin.settings) { + const item = plugin.settings[id]; + defaultSettings[id] = item.defaultValue; + } + } + const localSettingsSaveId = `__vue-devtools-plugin-settings__${plugin.id}`; + let currentSettings = Object.assign({}, defaultSettings); + try { + const raw = localStorage.getItem(localSettingsSaveId); + const data = JSON.parse(raw); + Object.assign(currentSettings, data); + } + catch (e) { + // noop + } + this.fallbacks = { + getSettings() { + return currentSettings; + }, + setSettings(value) { + try { + localStorage.setItem(localSettingsSaveId, JSON.stringify(value)); + } + catch (e) { + // noop + } + currentSettings = value; + }, + now() { + return now(); + }, + }; + if (hook) { + hook.on(HOOK_PLUGIN_SETTINGS_SET, (pluginId, value) => { + if (pluginId === this.plugin.id) { + this.fallbacks.setSettings(value); + } + }); + } + this.proxiedOn = new Proxy({}, { + get: (_target, prop) => { + if (this.target) { + return this.target.on[prop]; + } + else { + return (...args) => { + this.onQueue.push({ + method: prop, + args, + }); + }; + } + }, + }); + this.proxiedTarget = new Proxy({}, { + get: (_target, prop) => { + if (this.target) { + return this.target[prop]; + } + else if (prop === 'on') { + return this.proxiedOn; + } + else if (Object.keys(this.fallbacks).includes(prop)) { + return (...args) => { + this.targetQueue.push({ + method: prop, + args, + resolve: () => { }, + }); + return this.fallbacks[prop](...args); + }; + } + else { + return (...args) => { + return new Promise((resolve) => { + this.targetQueue.push({ + method: prop, + args, + resolve, + }); + }); + }; + } + }, + }); + } + async setRealTarget(target) { + this.target = target; + for (const item of this.onQueue) { + this.target.on[item.method](...item.args); + } + for (const item of this.targetQueue) { + item.resolve(await this.target[item.method](...item.args)); + } + } + } + + function setupDevtoolsPlugin(pluginDescriptor, setupFn) { + const descriptor = pluginDescriptor; + const target = getTarget(); + const hook = getDevtoolsGlobalHook(); + const enableProxy = isProxyAvailable && descriptor.enableEarlyProxy; + if (hook && (target.__VUE_DEVTOOLS_PLUGIN_API_AVAILABLE__ || !enableProxy)) { + hook.emit(HOOK_SETUP, pluginDescriptor, setupFn); + } + else { + const proxy = enableProxy ? new ApiProxy(descriptor, hook) : null; + const list = target.__VUE_DEVTOOLS_PLUGINS__ = target.__VUE_DEVTOOLS_PLUGINS__ || []; + list.push({ + pluginDescriptor: descriptor, + setupFn, + proxy, + }); + if (proxy) { + setupFn(proxy.proxiedTarget); + } + } + } + + /** + * 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, { + // remove variables that can contain vue instances + 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, + }, + }; + } + // to support multiple router instances + let routerId = 0; + function addDevtools(app, router, matcher) { + // Take over router.beforeEach and afterEach + // make sure we are not registering the devtool twice + if (router.__hasDevtools) + return; + router.__hasDevtools = true; + // increment to support multiple router instances + 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') { + console.warn('[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.'); + } + // display state added by the router + 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'), + }); + } + }); + // mark router-link as active and display tags on router views + 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 multiple useLink are used + 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, + }); + }); + } + }); + vue.watch(router.currentRoute, () => { + // refresh active state + refreshRoutesView(); + api.notifyComponentUpdate(); + api.sendInspectorTree(routerInspectorId); + api.sendInspectorState(routerInspectorId); + }); + const navigationsLayerId = 'router:navigations:' + id; + api.addTimelineLayer({ + id: navigationsLayerId, + label: `Router${id ? ' ' + id : ''} Navigations`, + color: 0x40a8c4, + }); + // const errorsLayerId = 'router:errors' + // api.addTimelineLayer({ + // id: errorsLayerId, + // label: 'Router Errors', + // color: 0xea5455, + // }) + 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, + }, + }); + }); + // attached to `meta` and used to group events + 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'), + }; + // Used to group navigations together, hide from devtools + 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('✅'); + } + // we set here to have the right order + 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() { + // the routes view isn't active + if (!activeRoutesPayload) + return; + const payload = activeRoutesPayload; + // children routes will appear as nested + let routes = matcher.getRoutes().filter(route => !route.parent || + // these routes have a parent with no component which will not appear in the view + // therefore we still need to include them + !route.parent.record.components); + // reset match state to false + routes.forEach(resetMatchStateOnRouteRecord); + // apply a match state if there is a payload + if (payload.filter) { + routes = routes.filter(route => + // save matches state based on the payload + isRouteMatching(route, payload.filter.toLowerCase())); + } + // mark active routes + 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 routes = matcher.getRoutes(); + const route = routes.find(route => route.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 = 0xec4899; + const BLUE_600 = 0x2563eb; + const LIME_500 = 0x84cc16; + const CYAN_400 = 0x22d3ee; + const ORANGE_400 = 0xfb923c; + // const GRAY_100 = 0xf4f4f5 + const DARK = 0x666666; + const RED_100 = 0xfee2e2; + const RED_700 = 0xb91c1c; + 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: 0xffffff, + backgroundColor: DARK, + }); + } + // add an id to be able to select it. Using the `path` is not possible because + // empty path children would collide with their parents + 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), + }; + } + // incremental id for route records and inspector state + let routeRecordId = 0; + const EXTRACT_REGEXP_RE = /^\/(.*)\/([a-z]*)$/; + function markRouteRecordActive(route, currentRoute) { + // no route will be active if matched is empty + // reset the matching state + 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; + } + // use a regexp without $ at the end to match nested routes better + const nonEndingRE = new RegExp(found[1].replace(/\$$/, ''), found[2]); + if (nonEndingRE.test(filter)) { + // mark children as matches + route.children.forEach(child => isRouteMatching(child, filter)); + // exception case: `/` + if (route.record.path !== '/' || filter === '/') { + route.__vd_match = route.re.test(filter); + return true; + } + // hide the / route + return false; + } + const path = route.record.path.toLowerCase(); + const decodedPath = decode(path); + // also allow partial matching on the 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)) { + // @ts-expect-error + ret[key] = obj[key]; + } + } + return ret; + } + + /** + * 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; + if (!routerHistory) + throw new Error('Provide the "history" option when calling "createRouter()":' + + ' https://router.vuejs.org/api/interfaces/RouterOptions.html#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); + if (!parent) { + warn(`Parent route "${String(parentOrRoute)}" not found when adding child route`, route); + } + record = route; + } + else { + record = parentOrRoute; + } + return matcher.addRoute(record, parent); + } + function removeRoute(name) { + const recordMatcher = matcher.getRecordMatcher(name); + if (recordMatcher) { + matcher.removeRoute(recordMatcher); + } + else { + warn(`Cannot remove non-existent route "${String(name)}"`); + } + } + function getRoutes() { + return matcher.getRoutes().map(routeMatcher => routeMatcher.record); + } + function hasRoute(name) { + return !!matcher.getRecordMatcher(name); + } + function resolve(rawLocation, currentLocation) { + // const resolve: Router['resolve'] = (rawLocation: RouteLocationRaw, 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); + { + if (href.startsWith('//')) + warn(`Location "${rawLocation}" resolved to "${href}". A resolved location cannot start with multiple slashes.`); + else if (!matchedRoute.matched.length) { + warn(`No match found for location with path "${rawLocation}"`); + } + } + // locationNormalized is always a new object + return assign(locationNormalized, matchedRoute, { + params: decodeParams(matchedRoute.params), + hash: decode(locationNormalized.hash), + redirectedFrom: undefined, + href, + }); + } + if (!isRouteLocation(rawLocation)) { + warn(`router.resolve() was passed an invalid location. This will fail in production.\n- Location:`, rawLocation); + return resolve({}); + } + let matcherLocation; + // path could be relative in object as well + if (rawLocation.path != null) { + if ('params' in rawLocation && + !('name' in rawLocation) && + // @ts-expect-error: the type is never + Object.keys(rawLocation.params).length) { + warn(`Path "${rawLocation.path}" was passed with params but they will be ignored. Use a named route alongside params instead.`); + } + 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(targetParams), + }); + // 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 || ''; + if (hash && !hash.startsWith('#')) { + warn(`A \`hash\` should always start with the character "#". Replace "${hash}" with "#${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); + { + if (href.startsWith('//')) { + warn(`Location "${rawLocation}" resolved to "${href}". A resolved location cannot start with multiple slashes.`); + } + else if (!matchedRoute.matched.length) { + warn(`No match found for location with path "${rawLocation.path != null ? rawLocation.path : rawLocation}"`); + } + } + 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 = {}; + } + if (newTargetLocation.path == null && + !('name' in newTargetLocation)) { + warn(`Invalid redirect found:\n${JSON.stringify(newTargetLocation, null, 2)}\n when navigating to "${to.fullPath}". A redirect must contain a name or path. This will break in production.`); + throw new Error('Invalid redirect'); + } + return assign({ + query: to.query, + hash: to.hash, + // avoid transferring params if the redirect has a path + params: newTargetLocation.path != null ? {} : 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 */)) { + if (// we are redirecting to the same location we were already at + isSameRouteLocation(stringifyQuery$1, resolve(failure.to), toLocation) && + // and we have done it a couple of times + redirectedFrom && + // @ts-expect-error: added only in dev + (redirectedFrom._count = redirectedFrom._count + ? // @ts-expect-error + redirectedFrom._count + 1 + : 1) > 30) { + warn(`Detected a possibly infinite redirection in a navigation guard when going from "${from.fullPath}" to "${toLocation.fullPath}". Aborting to avoid a Stack Overflow.\n Are you always returning a new location within a navigation guard? That would lead to this error. Only return when redirecting or aborting, that should fix this. This might break in production if not fixed.`); + return Promise.reject(new Error('Infinite redirect in navigation guard')); + } + 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(); + } + function runWithContext(fn) { + const app = installedApps.values().next().value; + // support Vue < 3.3 + return app && typeof app.runWithContext === 'function' + ? app.runWithContext(fn) + : fn(); + } + // 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 enteringRecords) { + // do not trigger beforeEnter on reused views + if (record.beforeEnter) { + 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 + // clear existing enterCallbacks, these are added by extractComponentsGuards + to.matched.forEach(record => (record.enterCallbacks = {})); + // check in-component beforeRouteEnter + guards = extractComponentsGuards(enteringRecords, 'beforeRouteEnter', to, from, runWithContext); + 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 + afterGuards + .list() + .forEach(guard => runWithContext(() => 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); + }) + // avoid warnings in the console about uncaught rejections, they are logged by triggerErrors + .catch(noop); + }); + } + // Initialization and Errors + let readyHandlers = useCallbacks(); + let errorListeners = useCallbacks(); + let ready; + /** + * Trigger errorListeners 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 = errorListeners.list(); + if (list.length) { + list.forEach(handler => handler(error, to, from)); + } + else { + { + warn('uncaught error during route navigation:'); + } + console.error(error); + } + // reject the error no matter there were error listeners or not + 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, + clearRoutes: matcher.clearRoutes, + hasRoute, + getRoutes, + resolve, + options, + push, + replace, + go, + back: () => go(-1), + forward: () => go(1), + beforeEach: beforeGuards.add, + beforeResolve: beforeResolveGuards.add, + afterEach: afterGuards.add, + onError: errorListeners.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 => { + warn('Unexpected error when starting the router:', err); + }); + } + const reactiveRoute = {}; + for (const key in START_LOCATION_NORMALIZED) { + Object.defineProperty(reactiveRoute, key, { + get: () => currentRoute.value[key], + enumerable: true, + }); + } + app.provide(routerKey, router); + app.provide(routeLocationKey, vue.shallowReactive(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(); + }; + // TODO: this probably needs to be updated so it can be used by vue-termui + if (isBrowser) { + addDevtools(app, router, matcher); + } + }, + }; + // TODO: type this as NavigationGuardReturn or similar instead of any + function runGuardQueue(guards) { + return guards.reduce((promise, guard) => promise.then(() => runWithContext(guard)), Promise.resolve()); + } + return router; + } + 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(_name) { + 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; + + return exports; + +})({}, Vue); diff --git a/node_modules/vue-router/dist/vue-router.global.prod.js b/node_modules/vue-router/dist/vue-router.global.prod.js new file mode 100644 index 0000000..82159ff --- /dev/null +++ b/node_modules/vue-router/dist/vue-router.global.prod.js @@ -0,0 +1,6 @@ +/*! + * vue-router v4.4.5 + * (c) 2024 Eduardo San Martin Morote + * @license MIT + */ +var VueRouter=function(e,t){"use strict";const n="undefined"!=typeof document;function r(e){return"object"==typeof e||"displayName"in e||"props"in e||"__vccOpts"in e}function o(e){return e.__esModule||"Module"===e[Symbol.toStringTag]||e.default&&r(e.default)}const c=Object.assign;function a(e,t){const n={};for(const r in t){const o=t[r];n[r]=i(o)?o.map(e):e(o)}return n}const s=()=>{},i=Array.isArray,l=/#/g,u=/&/g,f=/\//g,p=/=/g,h=/\?/g,d=/\+/g,m=/%5B/g,g=/%5D/g,v=/%5E/g,y=/%60/g,b=/%7B/g,w=/%7C/g,E=/%7D/g,R=/%20/g;function k(e){return encodeURI(""+e).replace(w,"|").replace(m,"[").replace(g,"]")}function O(e){return k(e).replace(d,"%2B").replace(R,"+").replace(l,"%23").replace(u,"%26").replace(y,"`").replace(b,"{").replace(E,"}").replace(v,"^")}function j(e){return null==e?"":function(e){return k(e).replace(l,"%23").replace(h,"%3F")}(e).replace(f,"%2F")}function P(e){try{return decodeURIComponent(""+e)}catch(e){}return""+e}const C=/\/$/,x=e=>e.replace(C,"");function $(e,t,n="/"){let r,o={},c="",a="";const s=t.indexOf("#");let i=t.indexOf("?");return s=0&&(i=-1),i>-1&&(r=t.slice(0,i),c=t.slice(i+1,s>-1?s:t.length),o=e(c)),s>-1&&(r=r||t.slice(0,s),a=t.slice(s,t.length)),r=function(e,t){if(e.startsWith("/"))return e;if(!e)return t;const n=t.split("/"),r=e.split("/"),o=r[r.length-1];".."!==o&&"."!==o||r.push("");let c,a,s=n.length-1;for(c=0;c1&&s--}return n.slice(0,s).join("/")+"/"+r.slice(c).join("/")}(null!=r?r:t,n),{fullPath:r+(c&&"?")+c+a,path:r,query:o,hash:P(a)}}function S(e,t){return t&&e.toLowerCase().startsWith(t.toLowerCase())?e.slice(t.length)||"/":e}function A(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function L(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const n in e)if(!M(e[n],t[n]))return!1;return!0}function M(e,t){return i(e)?q(e,t):i(t)?q(t,e):e===t}function q(e,t){return i(t)?e.length===t.length&&e.every(((e,n)=>e===t[n])):1===e.length&&e[0]===t}const B={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0};var T,G;!function(e){e.pop="pop",e.push="push"}(T||(T={})),function(e){e.back="back",e.forward="forward",e.unknown=""}(G||(G={}));function _(e){if(!e)if(n){const t=document.querySelector("base");e=(e=t&&t.getAttribute("href")||"/").replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return"/"!==e[0]&&"#"!==e[0]&&(e="/"+e),x(e)}const F=/^[^#]+#/;function I(e,t){return e.replace(F,"#")+t}const W=()=>({left:window.scrollX,top:window.scrollY});function D(e){let t;if("el"in e){const n=e.el,r="string"==typeof n&&n.startsWith("#"),o="string"==typeof n?r?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!o)return;t=function(e,t){const n=document.documentElement.getBoundingClientRect(),r=e.getBoundingClientRect();return{behavior:t.behavior,left:r.left-n.left-(t.left||0),top:r.top-n.top-(t.top||0)}}(o,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(null!=t.left?t.left:window.scrollX,null!=t.top?t.top:window.scrollY)}function K(e,t){return(history.state?history.state.position-t:-1)+e}const U=new Map;let V=()=>location.protocol+"//"+location.host;function H(e,t){const{pathname:n,search:r,hash:o}=t,c=e.indexOf("#");if(c>-1){let t=o.includes(e.slice(c))?e.slice(c).length:1,n=o.slice(t);return"/"!==n[0]&&(n="/"+n),S(n,"")}return S(n,e)+r+o}function N(e,t,n,r=!1,o=!1){return{back:e,current:t,forward:n,replaced:r,position:window.history.length,scroll:o?W():null}}function z(e){const t=function(e){const{history:t,location:n}=window,r={value:H(e,n)},o={value:t.state};function a(r,c,a){const s=e.indexOf("#"),i=s>-1?(n.host&&document.querySelector("base")?e:e.slice(s))+r:V()+e+r;try{t[a?"replaceState":"pushState"](c,"",i),o.value=c}catch(e){console.error(e),n[a?"replace":"assign"](i)}}return o.value||a(r.value,{back:null,current:r.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0),{location:r,state:o,push:function(e,n){const s=c({},o.value,t.state,{forward:e,scroll:W()});a(s.current,s,!0),a(e,c({},N(r.value,e,null),{position:s.position+1},n),!1),r.value=e},replace:function(e,n){a(e,c({},t.state,N(o.value.back,e,o.value.forward,!0),n,{position:o.value.position}),!0),r.value=e}}}(e=_(e)),n=function(e,t,n,r){let o=[],a=[],s=null;const i=({state:c})=>{const a=H(e,location),i=n.value,l=t.value;let u=0;if(c){if(n.value=a,t.value=c,s&&s===i)return void(s=null);u=l?c.position-l.position:0}else r(a);o.forEach((e=>{e(n.value,i,{delta:u,type:T.pop,direction:u?u>0?G.forward:G.back:G.unknown})}))};function l(){const{history:e}=window;e.state&&e.replaceState(c({},e.state,{scroll:W()}),"")}return window.addEventListener("popstate",i),window.addEventListener("beforeunload",l,{passive:!0}),{pauseListeners:function(){s=n.value},listen:function(e){o.push(e);const t=()=>{const t=o.indexOf(e);t>-1&&o.splice(t,1)};return a.push(t),t},destroy:function(){for(const e of a)e();a=[],window.removeEventListener("popstate",i),window.removeEventListener("beforeunload",l)}}}(e,t.state,t.location,t.replace);const r=c({location:"",base:e,go:function(e,t=!0){t||n.pauseListeners(),history.go(e)},createHref:I.bind(null,e)},t,n);return Object.defineProperty(r,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(r,"state",{enumerable:!0,get:()=>t.state.value}),r}function Q(e){return"string"==typeof e||"symbol"==typeof e}const X=Symbol("");var Y;function Z(e,t){return c(new Error,{type:e,[X]:!0},t)}function J(e,t){return e instanceof Error&&X in e&&(null==t||!!(e.type&t))}e.NavigationFailureType=void 0,(Y=e.NavigationFailureType||(e.NavigationFailureType={}))[Y.aborted=4]="aborted",Y[Y.cancelled=8]="cancelled",Y[Y.duplicated=16]="duplicated";const ee="[^/]+?",te={sensitive:!1,strict:!1,start:!0,end:!0},ne=/[.+*?^${}()[\]/\\]/g;function re(e,t){let n=0;for(;nt.length?1===t.length&&80===t[0]?1:-1:0}function oe(e,t){let n=0;const r=e.score,o=t.score;for(;n0&&t[t.length-1]<0}const ae={type:0,value:""},se=/[a-zA-Z0-9_]/;function ie(e,t,n){const r=function(e,t){const n=c({},te,t),r=[];let o=n.start?"^":"";const a=[];for(const t of e){const e=t.length?[]:[90];n.strict&&!t.length&&(o+="/");for(let r=0;r1&&("*"===s||"+"===s)&&t(`A repeatable param (${l}) must be alone in its segment. eg: '/:ids+.`),c.push({type:1,value:l,regexp:u,repeatable:"*"===s||"+"===s,optional:"*"===s||"?"===s})):t("Invalid state to consume buffer"),l="")}function p(){l+=s}for(;i{a(d)}:s}function a(e){if(Q(e)){const t=r.get(e);t&&(r.delete(e),n.splice(n.indexOf(t),1),t.children.forEach(a),t.alias.forEach(a))}else{const t=n.indexOf(e);t>-1&&(n.splice(t,1),e.record.name&&r.delete(e.record.name),e.children.forEach(a),e.alias.forEach(a))}}function i(e){const t=function(e,t){let n=0,r=t.length;for(;n!==r;){const o=n+r>>1;oe(e,t[o])<0?r=o:n=o+1}const o=function(e){let t=e;for(;t=t.parent;)if(ge(t)&&0===oe(e,t))return t;return}(e);o&&(r=t.lastIndexOf(o,r-1));return r}(e,n);n.splice(t,0,e),e.record.name&&!he(e)&&r.set(e.record.name,e)}return t=me({strict:!1,end:!0,sensitive:!1},t),e.forEach((e=>o(e))),{addRoute:o,resolve:function(e,t){let o,a,s,i={};if("name"in e&&e.name){if(o=r.get(e.name),!o)throw Z(1,{location:e});s=o.record.name,i=c(ue(t.params,o.keys.filter((e=>!e.optional)).concat(o.parent?o.parent.keys.filter((e=>e.optional)):[]).map((e=>e.name))),e.params&&ue(e.params,o.keys.map((e=>e.name)))),a=o.stringify(i)}else if(null!=e.path)a=e.path,o=n.find((e=>e.re.test(a))),o&&(i=o.parse(a),s=o.record.name);else{if(o=t.name?r.get(t.name):n.find((e=>e.re.test(t.path))),!o)throw Z(1,{location:e,currentLocation:t});s=o.record.name,i=c({},t.params,e.params),a=o.stringify(i)}const l=[];let u=o;for(;u;)l.unshift(u.record),u=u.parent;return{name:s,path:a,params:i,matched:l,meta:de(l)}},removeRoute:a,clearRoutes:function(){n.length=0,r.clear()},getRoutes:function(){return n},getRecordMatcher:function(e){return r.get(e)}}}function ue(e,t){const n={};for(const r of t)r in e&&(n[r]=e[r]);return n}function fe(e){const t={path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:e.aliasOf,beforeEnter:e.beforeEnter,props:pe(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:"components"in e?e.components||null:e.component&&{default:e.component}};return Object.defineProperty(t,"mods",{value:{}}),t}function pe(e){const t={},n=e.props||!1;if("component"in e)t.default=n;else for(const r in e.components)t[r]="object"==typeof n?n[r]:n;return t}function he(e){for(;e;){if(e.record.aliasOf)return!0;e=e.parent}return!1}function de(e){return e.reduce(((e,t)=>c(e,t.meta)),{})}function me(e,t){const n={};for(const r in e)n[r]=r in t?t[r]:e[r];return n}function ge({record:e}){return!!(e.name||e.components&&Object.keys(e.components).length||e.redirect)}function ve(e){const t={};if(""===e||"?"===e)return t;const n=("?"===e[0]?e.slice(1):e).split("&");for(let e=0;ee&&O(e))):[r&&O(r)]).forEach((e=>{void 0!==e&&(t+=(t.length?"&":"")+n,null!=e&&(t+="="+e))}))}return t}function be(e){const t={};for(const n in e){const r=e[n];void 0!==r&&(t[n]=i(r)?r.map((e=>null==e?null:""+e)):null==r?r:""+r)}return t}const we=Symbol(""),Ee=Symbol(""),Re=Symbol(""),ke=Symbol(""),Oe=Symbol("");function je(){let e=[];return{add:function(t){return e.push(t),()=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)}},list:()=>e.slice(),reset:function(){e=[]}}}function Pe(e,n,r){const o=()=>{e[n].delete(r)};t.onUnmounted(o),t.onDeactivated(o),t.onActivated((()=>{e[n].add(r)})),e[n].add(r)}function Ce(e,t,n,r,o,c=(e=>e())){const a=r&&(r.enterCallbacks[o]=r.enterCallbacks[o]||[]);return()=>new Promise(((s,i)=>{const l=e=>{var c;!1===e?i(Z(4,{from:n,to:t})):e instanceof Error?i(e):"string"==typeof(c=e)||c&&"object"==typeof c?i(Z(2,{from:t,to:e})):(a&&r.enterCallbacks[o]===a&&"function"==typeof e&&a.push(e),s())},u=c((()=>e.call(r&&r.instances[o],t,n,l)));let f=Promise.resolve(u);e.length<3&&(f=f.then(l)),f.catch((e=>i(e)))}))}function xe(e,t,n,c,a=(e=>e())){const s=[];for(const i of e)for(const e in i.components){let l=i.components[e];if("beforeRouteEnter"===t||i.instances[e])if(r(l)){const r=(l.__vccOpts||l)[t];r&&s.push(Ce(r,n,c,i,e,a))}else{let r=l();s.push((()=>r.then((r=>{if(!r)throw new Error(`Couldn't resolve component "${e}" at "${i.path}"`);const s=o(r)?r.default:r;i.mods[e]=r,i.components[e]=s;const l=(s.__vccOpts||s)[t];return l&&Ce(l,n,c,i,e,a)()}))))}}return s}function $e(e){const n=t.inject(Re),r=t.inject(ke),o=t.computed((()=>{const r=t.unref(e.to);return n.resolve(r)})),c=t.computed((()=>{const{matched:e}=o.value,{length:t}=e,n=e[t-1],c=r.matched;if(!n||!c.length)return-1;const a=c.findIndex(A.bind(null,n));if(a>-1)return a;const s=Ae(e[t-2]);return t>1&&Ae(n)===s&&c[c.length-1].path!==s?c.findIndex(A.bind(null,e[t-2])):a})),a=t.computed((()=>c.value>-1&&function(e,t){for(const n in t){const r=t[n],o=e[n];if("string"==typeof r){if(r!==o)return!1}else if(!i(o)||o.length!==r.length||r.some(((e,t)=>e!==o[t])))return!1}return!0}(r.params,o.value.params))),l=t.computed((()=>c.value>-1&&c.value===r.matched.length-1&&L(r.params,o.value.params)));return{route:o,href:t.computed((()=>o.value.href)),isActive:a,isExactActive:l,navigate:function(r={}){return function(e){if(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)return;if(e.defaultPrevented)return;if(void 0!==e.button&&0!==e.button)return;if(e.currentTarget&&e.currentTarget.getAttribute){const t=e.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(t))return}e.preventDefault&&e.preventDefault();return!0}(r)?n[t.unref(e.replace)?"replace":"push"](t.unref(e.to)).catch(s):Promise.resolve()}}}const Se=t.defineComponent({name:"RouterLink",compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:"page"}},useLink:$e,setup(e,{slots:n}){const r=t.reactive($e(e)),{options:o}=t.inject(Re),c=t.computed((()=>({[Le(e.activeClass,o.linkActiveClass,"router-link-active")]:r.isActive,[Le(e.exactActiveClass,o.linkExactActiveClass,"router-link-exact-active")]:r.isExactActive})));return()=>{const o=n.default&&n.default(r);return e.custom?o:t.h("a",{"aria-current":r.isExactActive?e.ariaCurrentValue:null,href:r.href,onClick:r.navigate,class:c.value},o)}}});function Ae(e){return e?e.aliasOf?e.aliasOf.path:e.path:""}const Le=(e,t,n)=>null!=e?e:null!=t?t:n;function Me(e,t){if(!e)return null;const n=e(t);return 1===n.length?n[0]:n}const qe=t.defineComponent({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:n,slots:r}){const o=t.inject(Oe),a=t.computed((()=>e.route||o.value)),s=t.inject(Ee,0),i=t.computed((()=>{let e=t.unref(s);const{matched:n}=a.value;let r;for(;(r=n[e])&&!r.components;)e++;return e})),l=t.computed((()=>a.value.matched[i.value]));t.provide(Ee,t.computed((()=>i.value+1))),t.provide(we,l),t.provide(Oe,a);const u=t.ref();return t.watch((()=>[u.value,l.value,e.name]),(([e,t,n],[r,o,c])=>{t&&(t.instances[n]=e,o&&o!==t&&e&&e===r&&(t.leaveGuards.size||(t.leaveGuards=o.leaveGuards),t.updateGuards.size||(t.updateGuards=o.updateGuards))),!e||!t||o&&A(t,o)&&r||(t.enterCallbacks[n]||[]).forEach((t=>t(e)))}),{flush:"post"}),()=>{const o=a.value,s=e.name,i=l.value,f=i&&i.components[s];if(!f)return Me(r.default,{Component:f,route:o});const p=i.props[s],h=p?!0===p?o.params:"function"==typeof p?p(o):p:null,d=t.h(f,c({},h,n,{onVnodeUnmounted:e=>{e.component.isUnmounted&&(i.instances[s]=null)},ref:u}));return Me(r.default,{Component:d,route:o})||d}}});return e.RouterLink=Se,e.RouterView=qe,e.START_LOCATION=B,e.createMemoryHistory=function(e=""){let t=[],n=[""],r=0;function o(e){r++,r!==n.length&&n.splice(r),n.push(e)}const c={location:"",state:{},base:e=_(e),createHref:I.bind(null,e),replace(e){n.splice(r--,1),o(e)},push(e,t){o(e)},listen:e=>(t.push(e),()=>{const n=t.indexOf(e);n>-1&&t.splice(n,1)}),destroy(){t=[],n=[""],r=0},go(e,o=!0){const c=this.location,a=e<0?G.back:G.forward;r=Math.max(0,Math.min(r+e,n.length-1)),o&&function(e,n,{direction:r,delta:o}){const c={direction:r,delta:o,type:T.pop};for(const r of t)r(e,n,c)}(this.location,c,{direction:a,delta:e})}};return Object.defineProperty(c,"location",{enumerable:!0,get:()=>n[r]}),c},e.createRouter=function(e){const r=le(e.routes,e),o=e.parseQuery||ve,l=e.stringifyQuery||ye,u=e.history,f=je(),p=je(),h=je(),d=t.shallowRef(B);let m=B;n&&e.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const g=a.bind(null,(e=>""+e)),y=a.bind(null,j),w=a.bind(null,P);function R(e,t){if(t=c({},t||d.value),"string"==typeof e){const n=$(o,e,t.path),a=r.resolve({path:n.path},t),s=u.createHref(n.fullPath);return c(n,a,{params:w(a.params),hash:P(n.hash),redirectedFrom:void 0,href:s})}let n;if(null!=e.path)n=c({},e,{path:$(o,e.path,t.path).path});else{const r=c({},e.params);for(const e in r)null==r[e]&&delete r[e];n=c({},e,{params:y(r)}),t.params=y(t.params)}const a=r.resolve(n,t),s=e.hash||"";a.params=g(w(a.params));const i=function(e,t){const n=t.query?e(t.query):"";return t.path+(n&&"?")+n+(t.hash||"")}(l,c({},e,{hash:(f=s,k(f).replace(b,"{").replace(E,"}").replace(v,"^")),path:a.path}));var f;const p=u.createHref(i);return c({fullPath:i,hash:s,query:l===ye?be(e.query):e.query||{}},a,{redirectedFrom:void 0,href:p})}function O(e){return"string"==typeof e?$(o,e,d.value.path):c({},e)}function C(e,t){if(m!==e)return Z(8,{from:t,to:e})}function x(e){return M(e)}function S(e){const t=e.matched[e.matched.length-1];if(t&&t.redirect){const{redirect:n}=t;let r="function"==typeof n?n(e):n;return"string"==typeof r&&(r=r.includes("?")||r.includes("#")?r=O(r):{path:r},r.params={}),c({query:e.query,hash:e.hash,params:null!=r.path?{}:e.params},r)}}function M(e,t){const n=m=R(e),r=d.value,o=e.state,a=e.force,s=!0===e.replace,i=S(n);if(i)return M(c(O(i),{state:"object"==typeof i?c({},o,i.state):o,force:a,replace:s}),t||n);const u=n;let f;return u.redirectedFrom=t,!a&&function(e,t,n){const r=t.matched.length-1,o=n.matched.length-1;return r>-1&&r===o&&A(t.matched[r],n.matched[o])&&L(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}(l,r,n)&&(f=Z(16,{to:u,from:r}),te(r,r,!0,!1)),(f?Promise.resolve(f):_(u,r)).catch((e=>J(e)?J(e,2)?e:ee(e):Y(e,u,r))).then((e=>{if(e){if(J(e,2))return M(c({replace:s},O(e.to),{state:"object"==typeof e.to?c({},o,e.to.state):o,force:a}),t||u)}else e=I(u,r,!0,s,o);return F(u,r,e),e}))}function q(e,t){const n=C(e,t);return n?Promise.reject(n):Promise.resolve()}function G(e){const t=oe.values().next().value;return t&&"function"==typeof t.runWithContext?t.runWithContext(e):e()}function _(e,t){let n;const[r,o,c]=function(e,t){const n=[],r=[],o=[],c=Math.max(t.matched.length,e.matched.length);for(let a=0;aA(e,c)))?r.push(c):n.push(c));const s=e.matched[a];s&&(t.matched.find((e=>A(e,s)))||o.push(s))}return[n,r,o]}(e,t);n=xe(r.reverse(),"beforeRouteLeave",e,t);for(const o of r)o.leaveGuards.forEach((r=>{n.push(Ce(r,e,t))}));const a=q.bind(null,e,t);return n.push(a),ae(n).then((()=>{n=[];for(const r of f.list())n.push(Ce(r,e,t));return n.push(a),ae(n)})).then((()=>{n=xe(o,"beforeRouteUpdate",e,t);for(const r of o)r.updateGuards.forEach((r=>{n.push(Ce(r,e,t))}));return n.push(a),ae(n)})).then((()=>{n=[];for(const r of c)if(r.beforeEnter)if(i(r.beforeEnter))for(const o of r.beforeEnter)n.push(Ce(o,e,t));else n.push(Ce(r.beforeEnter,e,t));return n.push(a),ae(n)})).then((()=>(e.matched.forEach((e=>e.enterCallbacks={})),n=xe(c,"beforeRouteEnter",e,t,G),n.push(a),ae(n)))).then((()=>{n=[];for(const r of p.list())n.push(Ce(r,e,t));return n.push(a),ae(n)})).catch((e=>J(e,8)?e:Promise.reject(e)))}function F(e,t,n){h.list().forEach((r=>G((()=>r(e,t,n)))))}function I(e,t,r,o,a){const s=C(e,t);if(s)return s;const i=t===B,l=n?history.state:{};r&&(o||i?u.replace(e.fullPath,c({scroll:i&&l&&l.scroll},a)):u.push(e.fullPath,a)),d.value=e,te(e,t,r,i),ee()}let V;function H(){V||(V=u.listen(((e,t,r)=>{if(!ce.listening)return;const o=R(e),a=S(o);if(a)return void M(c(a,{replace:!0}),o).catch(s);m=o;const i=d.value;var l,f;n&&(l=K(i.fullPath,r.delta),f=W(),U.set(l,f)),_(o,i).catch((e=>J(e,12)?e:J(e,2)?(M(e.to,o).then((e=>{J(e,20)&&!r.delta&&r.type===T.pop&&u.go(-1,!1)})).catch(s),Promise.reject()):(r.delta&&u.go(-r.delta,!1),Y(e,o,i)))).then((e=>{(e=e||I(o,i,!1))&&(r.delta&&!J(e,8)?u.go(-r.delta,!1):r.type===T.pop&&J(e,20)&&u.go(-1,!1)),F(o,i,e)})).catch(s)})))}let N,z=je(),X=je();function Y(e,t,n){ee(e);const r=X.list();return r.length?r.forEach((r=>r(e,t,n))):console.error(e),Promise.reject(e)}function ee(e){return N||(N=!e,H(),z.list().forEach((([t,n])=>e?n(e):t())),z.reset()),e}function te(r,o,c,a){const{scrollBehavior:s}=e;if(!n||!s)return Promise.resolve();const i=!c&&function(e){const t=U.get(e);return U.delete(e),t}(K(r.fullPath,0))||(a||!c)&&history.state&&history.state.scroll||null;return t.nextTick().then((()=>s(r,o,i))).then((e=>e&&D(e))).catch((e=>Y(e,r,o)))}const ne=e=>u.go(e);let re;const oe=new Set,ce={currentRoute:d,listening:!0,addRoute:function(e,t){let n,o;return Q(e)?(n=r.getRecordMatcher(e),o=t):o=e,r.addRoute(o,n)},removeRoute:function(e){const t=r.getRecordMatcher(e);t&&r.removeRoute(t)},clearRoutes:r.clearRoutes,hasRoute:function(e){return!!r.getRecordMatcher(e)},getRoutes:function(){return r.getRoutes().map((e=>e.record))},resolve:R,options:e,push:x,replace:function(e){return x(c(O(e),{replace:!0}))},go:ne,back:()=>ne(-1),forward:()=>ne(1),beforeEach:f.add,beforeResolve:p.add,afterEach:h.add,onError:X.add,isReady:function(){return N&&d.value!==B?Promise.resolve():new Promise(((e,t)=>{z.add([e,t])}))},install(e){e.component("RouterLink",Se),e.component("RouterView",qe),e.config.globalProperties.$router=this,Object.defineProperty(e.config.globalProperties,"$route",{enumerable:!0,get:()=>t.unref(d)}),n&&!re&&d.value===B&&(re=!0,x(u.location).catch((e=>{})));const r={};for(const e in B)Object.defineProperty(r,e,{get:()=>d.value[e],enumerable:!0});e.provide(Re,this),e.provide(ke,t.shallowReactive(r)),e.provide(Oe,d);const o=e.unmount;oe.add(e),e.unmount=function(){oe.delete(e),oe.size<1&&(m=B,V&&V(),V=null,d.value=B,re=!1,N=!1),o()}}};function ae(e){return e.reduce(((e,t)=>e.then((()=>G(t)))),Promise.resolve())}return ce},e.createRouterMatcher=le,e.createWebHashHistory=function(e){return(e=location.host?e||location.pathname+location.search:"").includes("#")||(e+="#"),z(e)},e.createWebHistory=z,e.isNavigationFailure=J,e.loadRouteLocation=function(e){return e.matched.every((e=>e.redirect))?Promise.reject(new Error("Cannot load a route that redirects.")):Promise.all(e.matched.map((e=>e.components&&Promise.all(Object.keys(e.components).reduce(((t,n)=>{const r=e.components[n];return"function"!=typeof r||"displayName"in r||t.push(r().then((t=>{if(!t)return Promise.reject(new Error(`Couldn't resolve component "${n}" at "${e.path}". Ensure you passed a function that returns a promise.`));const r=o(t)?t.default:t;e.mods[n]=t,e.components[n]=r}))),t}),[]))))).then((()=>e))},e.matchedRouteKey=we,e.onBeforeRouteLeave=function(e){const n=t.inject(we,{}).value;n&&Pe(n,"leaveGuards",e)},e.onBeforeRouteUpdate=function(e){const n=t.inject(we,{}).value;n&&Pe(n,"updateGuards",e)},e.parseQuery=ve,e.routeLocationKey=ke,e.routerKey=Re,e.routerViewLocationKey=Oe,e.stringifyQuery=ye,e.useLink=$e,e.useRoute=function(e){return t.inject(ke)},e.useRouter=function(){return t.inject(Re)},e.viewDepthKey=Ee,e}({},Vue); diff --git a/node_modules/vue-router/dist/vue-router.mjs b/node_modules/vue-router/dist/vue-router.mjs new file mode 100644 index 0000000..e0acf6b --- /dev/null +++ b/node_modules/vue-router/dist/vue-router.mjs @@ -0,0 +1,3759 @@ +/*! + * vue-router v4.4.5 + * (c) 2024 Eduardo San Martin Morote + * @license MIT + */ +import { getCurrentInstance, inject, onUnmounted, onDeactivated, onActivated, computed, unref, watchEffect, defineComponent, reactive, h, provide, ref, watch, shallowRef, shallowReactive, nextTick } from 'vue'; +import { setupDevtoolsPlugin } from '@vue/devtools-api'; + +const isBrowser = typeof document !== 'undefined'; + +/** + * 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' || + // support CF with dynamic imports that do not + // add the Module string tag + (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 warn(msg) { + // avoid using ...args as it breaks in older Edge builds + const args = Array.from(arguments).slice(1); + console.warn.apply(console, ['[Vue Router warn]: ' + msg].concat(args)); +} + +/** + * 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; // %23 +const AMPERSAND_RE = /&/g; // %26 +const SLASH_RE = /\//g; // %2F +const EQUAL_RE = /=/g; // %3D +const IM_RE = /\?/g; // %3F +const 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) { + (process.env.NODE_ENV !== 'production') && warn(`Error decoding "${text}". Using original value`); + } + return '' + text; +} + +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: decode(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 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, 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 ((process.env.NODE_ENV !== 'production') && !from.startsWith('/')) { + warn(`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]; + // make . and ./ the same (../ === .., ../../ === ../..) + // this is the same behavior as new URL() + if (lastToSegment === '..' || lastToSegment === '.') { + toSegments.push(''); + } + 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.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: '/', + // TODO: could we use a symbol in the future? + name: undefined, + params: {}, + query: {}, + hash: '', + fullPath: '/', + matched: [], + meta: {}, + redirectedFrom: undefined, +}; + +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 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 hash +const 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.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(`The selector "${position.el}" should be passed as "el: document.querySelector('${position.el}')" because it starts with "#".`); + // return to avoid other warnings + return; + } + } + catch (err) { + warn(`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 to avoid other warnings + return; + } + } + } + const el = typeof positionEl === 'string' + ? isIdSelector + ? document.getElementById(positionEl.slice(1)) + : document.querySelector(positionEl) + : positionEl; + if (!el) { + (process.env.NODE_ENV !== 'production') && + warn(`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) { + 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 { +// // 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 = { +// compute: computeScroll, +// scroll: scrollToPosition, +// } + +let createBaseLocation = () => location.protocol + '//' + location.host; +/** + * Creates a normalized history location from a window.location object + * @param base - The base path + * @param location - The window.location object + */ +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); + } + // 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); + // TODO: could we use 'pagehide' or 'visibilitychange' instead? + // https://developer.chrome.com/blog/page-lifecycle-api/ + window.addEventListener('beforeunload', beforeUnloadListener, { + passive: true, + }); + 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 `` 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) { + if ((process.env.NODE_ENV !== 'production')) { + warn('Error with push/replace State', err); + } + else { + 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(), + }); + if ((process.env.NODE_ENV !== 'production') && !history.state) { + warn(`history.state seems to have been manually replaced without preserving the necessary values. Make sure to preserve existing history state if you are manually calling history.replaceState:\n\n` + + `history.replaceState(history.state, '', url)\n\n` + + `You can find more information at https://router.vuejs.org/guide/migration/#Usage-of-history-state`); + } + 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 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 `` 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 `` 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 += '#'; + if ((process.env.NODE_ENV !== 'production') && !base.endsWith('#/') && !base.endsWith('#')) { + warn(`A hash base must end with a "#":\n"${base}" should be "${base.replace(/#.*$/, '#')}".`); + } + return createWebHistory(base); +} + +function isRouteLocation(route) { + return typeof route === 'string' || (route && typeof route === 'object'); +} +function isRouteName(name) { + return typeof name === 'string' || typeof name === 'symbol'; +} + +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. + */ +var NavigationFailureType; +(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"; +})(NavigationFailureType || (NavigationFailureType = {})); +// DEV only debug messages +const 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}".`; + }, +}; +/** + * Creates a typed NavigationFailure object. + * @internal + * @param type - NavigationFailureType + * @param params - { from, to } + */ +function createRouterError(type, params) { + // keep full error messages in cjs versions + if ((process.env.NODE_ENV !== 'production') || !true) { + return assign(new Error(ErrorTypeMessages[type](params)), { + type, + [NavigationFailureSymbol]: true, + }, params); + } + else { + return assign(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); +} + +// 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 tokens +const 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() +function tokenizePath(path) { + if (!path) + return [[]]; + if (path === '/') + return [[ROOT_TOKEN]]; + if (!path.startsWith('/')) { + throw new Error((process.env.NODE_ENV !== 'production') + ? `Route paths should start with a "/": "${path}" should be "/${path}".` + : `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); + // warn against params with the same name + if ((process.env.NODE_ENV !== 'production')) { + const existingKeys = new Set(); + for (const key of parser.keys) { + if (existingKeys.has(key.name)) + warn(`Found duplicated params with name "${key.name}" for path "${record.path}". Only the last one will be available on "$route.params".`); + existingKeys.add(key.name); + } + } + 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); + if ((process.env.NODE_ENV !== 'production')) { + checkChildMissingNameWithEmptyPath(mainNormalizedRecord, parent); + } + // 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( + // we need to normalize again to ensure the `mods` property + // being non enumerable + normalizeRouteRecord(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); + } + if ((process.env.NODE_ENV !== 'production') && normalizedRecord.path === '*') { + throw new Error('Catch all routes ("*") must now be defined using a param with a custom regexp.\n' + + 'See more at https://router.vuejs.org/guide/migration/#Removed-star-or-catch-all-routes.'); + } + // create the object beforehand, so it can be passed to children + matcher = createRouteRecordMatcher(normalizedRecord, parent, options); + if ((process.env.NODE_ENV !== 'production') && parent && path[0] === '/') + checkMissingParamsInAbsolutePath(matcher, parent); + // 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); + if ((process.env.NODE_ENV !== 'production')) { + checkSameParams(originalRecord, 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); + } + // 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 (isMatchable(matcher)) { + insertMatcher(matcher); + } + 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) + // } + } + 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) { + const index = findInsertionIndex(matcher, matchers); + matchers.splice(index, 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, + }); + // warn if the user is passing invalid params so they can debug it better when they get removed + if ((process.env.NODE_ENV !== 'production')) { + const invalidParams = Object.keys(location.params || {}).filter(paramName => !matcher.keys.find(k => k.name === paramName)); + if (invalidParams.length) { + warn(`Discarded invalid param(s) "${invalidParams.join('", "')}" when navigating. See https://github.com/vuejs/router/blob/main/packages/router/CHANGELOG.md#414-2022-08-22 for more details.`); + } + } + name = matcher.record.name; + params = assign( + // paramsFromLocation is a new object + paramsFromLocation(currentLocation.params, + // only keep params that exist in the resolved location + // only keep optional params coming from a parent record + matcher.keys + .filter(k => !k.optional) + .concat(matcher.parent ? matcher.parent.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 (location.path != null) { + // 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; + if ((process.env.NODE_ENV !== 'production') && !path.startsWith('/')) { + warn(`The Matcher cannot resolve relative paths but received "${path}". Unless you directly called \`matcher.resolve("${path}")\`, this is probably a bug in vue-router. Please open an issue at https://github.com/vuejs/router/issues/new/choose.`); + } + 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)); + function clearRoutes() { + matchers.length = 0; + matcherMap.clear(); + } + return { + addRoute, + resolve, + removeRoute, + clearRoutes, + 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) { + const normalized = { + path: record.path, + redirect: record.redirect, + name: record.name, + meta: record.meta || {}, + aliasOf: record.aliasOf, + beforeEnter: record.beforeEnter, + props: normalizeRecordProps(record), + children: record.children || [], + instances: {}, + leaveGuards: new Set(), + updateGuards: new Set(), + enterCallbacks: {}, + // must be declared afterwards + // mods: {}, + components: 'components' in record + ? record.components || null + : record.component && { default: record.component }, + }; + // mods contain modules and shouldn't be copied, + // logged or anything. It's just used for internal + // advanced use cases like data loaders + Object.defineProperty(normalized, 'mods', { + value: {}, + }); + return normalized; +} +/** + * 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 === 'object' ? props[name] : props; + } + 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 isSameParam(a, b) { + return (a.name === b.name && + a.optional === b.optional && + a.repeatable === b.repeatable); +} +/** + * Check if a path and its alias have the same required params + * + * @param a - original record + * @param b - alias record + */ +function checkSameParams(a, b) { + for (const key of a.keys) { + if (!key.optional && !b.keys.find(isSameParam.bind(null, key))) + return warn(`Alias "${b.record.path}" and the original record: "${a.record.path}" must have the exact same param named "${key.name}"`); + } + for (const key of b.keys) { + if (!key.optional && !a.keys.find(isSameParam.bind(null, key))) + return warn(`Alias "${b.record.path}" and the original record: "${a.record.path}" must have the exact same param named "${key.name}"`); + } +} +/** + * A route with a name and a child with an empty path without a name should warn when adding the route + * + * @param mainNormalizedRecord - RouteRecordNormalized + * @param parent - RouteRecordMatcher + */ +function checkChildMissingNameWithEmptyPath(mainNormalizedRecord, parent) { + if (parent && + parent.record.name && + !mainNormalizedRecord.name && + !mainNormalizedRecord.path) { + warn(`The route named "${String(parent.record.name)}" has a child without a name and an empty path. Using that name won't render the empty path child so you probably want to move the name to the child instead. If this is intentional, add a name to the child route to remove the warning.`); + } +} +function checkMissingParamsInAbsolutePath(record, parent) { + for (const key of parent.keys) { + if (!record.keys.find(isSameParam.bind(null, key))) + return warn(`Absolute path "${record.record.path}" must have the exact same param named "${key.name}" as its parent "${parent.record.path}".`); + } +} +/** + * Performs a binary search to find the correct insertion index for a new matcher. + * + * Matchers are primarily sorted by their score. If scores are tied then we also consider parent/child relationships, + * with descendants coming before ancestors. If there's still a tie, new routes are inserted after existing routes. + * + * @param matcher - new matcher to be inserted + * @param matchers - existing matchers + */ +function findInsertionIndex(matcher, matchers) { + // First phase: binary search based on score + let lower = 0; + let upper = matchers.length; + while (lower !== upper) { + const mid = (lower + upper) >> 1; + const sortOrder = comparePathParserScore(matcher, matchers[mid]); + if (sortOrder < 0) { + upper = mid; + } + else { + lower = mid + 1; + } + } + // Second phase: check for an ancestor with the same score + const insertionAncestor = getInsertionAncestor(matcher); + if (insertionAncestor) { + upper = matchers.lastIndexOf(insertionAncestor, upper - 1); + if ((process.env.NODE_ENV !== 'production') && upper < 0) { + // This should never happen + warn(`Finding ancestor route "${insertionAncestor.record.path}" failed for "${matcher.record.path}"`); + } + } + return upper; +} +function getInsertionAncestor(matcher) { + let ancestor = matcher; + while ((ancestor = ancestor.parent)) { + if (isMatchable(ancestor) && + comparePathParserScore(matcher, ancestor) === 0) { + return ancestor; + } + } + return; +} +/** + * Checks if a matcher can be reachable. This means if it's possible to reach it as a route. For example, routes without + * a component, or name, or redirect, are just used to group other routes. + * @param matcher + * @param matcher.record record of the matcher + * @returns + */ +function isMatchable({ record }) { + return !!(record.name || + (record.components && Object.keys(record.components).length) || + record.redirect); +} + +/** + * 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((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' : ''); + +/** + * 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, + }; +} + +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('getCurrentInstance() returned null. onBeforeRouteLeave() must be called at the top of a setup function'); + return; + } + const activeRecord = inject(matchedRouteKey, + // to avoid warning + {}).value; + if (!activeRecord) { + (process.env.NODE_ENV !== 'production') && + warn('No active route record was found when calling `onBeforeRouteLeave()`. Make sure you call this function inside a component child of . 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('getCurrentInstance() returned null. onBeforeRouteUpdate() must be called at the top of a setup function'); + return; + } + const activeRecord = inject(matchedRouteKey, + // to avoid warning + {}).value; + if (!activeRecord) { + (process.env.NODE_ENV !== 'production') && + warn('No active route record was found when calling `onBeforeRouteUpdate()`. Make sure you call this function inside a component child of . Maybe you called it inside of App.vue?'); + return; + } + registerGuard(activeRecord, 'updateGuards', updateGuard); +} +function guardToPromiseFn(guard, to, from, record, name, runWithContext = fn => fn()) { + // 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 = 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 => { + // @ts-expect-error: _called is added at canOnlyBeCalledOnce + if (!next._called) { + warn(message); + return Promise.reject(new Error('Invalid navigation guard')); + } + return resolvedValue; + }); + } + else if (guardReturn !== undefined) { + // @ts-expect-error: _called is added at canOnlyBeCalledOnce + if (!next._called) { + warn(message); + reject(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(`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.`); + // @ts-expect-error: we put it in the original one because it's easier to check + 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.length) { + warn(`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(`Component "${name}" in record with path "${record.path}" is not` + + ` a valid component. Received "${String(rawComponent)}".`); + // throw to ensure we stop here but warn to ensure the message isn't + // missed by the user + throw new Error('Invalid route component'); + } + else if ('then' in rawComponent) { + // warn if user wrote import('/component.vue') instead of () => + // import('./component.vue') + warn(`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 && + // warn only once per component + !rawComponent.__warnedDefineAsync) { + rawComponent.__warnedDefineAsync = true; + warn(`Component "${name}" in record with path "${record.path}" is defined ` + + `using "defineAsyncComponent()". ` + + `Write "() => import('./MyPage.vue')" instead of ` + + `"defineAsyncComponent(() => import('./MyPage.vue'))".`); + } + } + // 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, runWithContext)); + } + else { + // start requesting the chunk already + let componentPromise = rawComponent(); + if ((process.env.NODE_ENV !== 'production') && !('catch' in componentPromise)) { + warn(`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; + // keep the resolved module for plugins like data loaders + record.mods[name] = 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, runWithContext)()); + })); + } + } + } + return guards; +} +/** + * Ensures a route is loaded, so it can be passed as o prop to ``. + * + * @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; + // keep the resolved module for plugins like data loaders + record.mods[name] = 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 RFC +/** + * Returns the internal behavior of a {@link RouterLink} without the rendering part. + * + * @param props - a `to` location and an optional `replace` flag + */ +function useLink(props) { + const router = inject(routerKey); + const currentRoute = inject(routeLocationKey); + let hasPrevious = false; + let previousTo = null; + const route = computed(() => { + const to = unref(props.to); + if ((process.env.NODE_ENV !== 'production') && (!hasPrevious || to !== previousTo)) { + if (!isRouteLocation(to)) { + if (hasPrevious) { + warn(`Invalid value for prop "to" in useLink()\n- to:`, to, `\n- previous to:`, previousTo, `\n- props:`, props); + } + else { + warn(`Invalid value for prop "to" in useLink()\n- to:`, to, `\n- props:`, props); + } + } + previousTo = to; + hasPrevious = true; + } + return router.resolve(to); + }); + const activeRecordIndex = 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 = computed(() => activeRecordIndex.value > -1 && + includesParams(currentRoute.params, route.value.params)); + const isExactActive = computed(() => activeRecordIndex.value > -1 && + activeRecordIndex.value === currentRoute.matched.length - 1 && + isSameRouteLocationParams(currentRoute.params, route.value.params)); + function navigate(e = {}) { + if (guardEvent(e)) { + return router[unref(props.replace) ? 'replace' : 'push'](unref(props.to) + // avoid uncaught errors are they are logged anyway + ).catch(noop); + } + return Promise.resolve(); + } + // devtools only + if (((process.env.NODE_ENV !== 'production') || __VUE_PROD_DEVTOOLS__) && isBrowser) { + const instance = getCurrentInstance(); + if (instance) { + const linkContextDevtools = { + route: route.value, + isActive: isActive.value, + isExactActive: isExactActive.value, + error: null, + }; + // @ts-expect-error: this is internal + instance.__vrl_devtools = instance.__vrl_devtools || []; + // @ts-expect-error: this is internal + instance.__vrl_devtools.push(linkContextDevtools); + watchEffect(() => { + linkContextDevtools.route = route.value; + linkContextDevtools.isActive = isActive.value; + linkContextDevtools.isExactActive = isExactActive.value; + linkContextDevtools.error = isRouteLocation(unref(props.to)) + ? null + : 'Invalid "to" value'; + }, { flush: 'post' }); + } + } + /** + * NOTE: update {@link _RouterLinkI}'s `$slots` type when updating this + */ + return { + route, + href: computed(() => route.value.href), + isActive, + isExactActive, + navigate, + }; +} +const RouterLinkImpl = /*#__PURE__*/ 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 = reactive(useLink(props)); + const { options } = inject(routerKey); + const elClass = 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 + : 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__*/ 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 }) { + (process.env.NODE_ENV !== 'production') && warnDeprecatedUsage(); + const injectedRoute = inject(routerViewLocationKey); + const routeToDisplay = computed(() => props.route || injectedRoute.value); + const injectedDepth = 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 = computed(() => { + let initialDepth = unref(injectedDepth); + const { matched } = routeToDisplay.value; + let matchedRoute; + while ((matchedRoute = matched[initialDepth]) && + !matchedRoute.components) { + initialDepth++; + } + return initialDepth; + }); + const matchedRouteRef = computed(() => routeToDisplay.value.matched[depth.value]); + provide(viewDepthKey, computed(() => depth.value + 1)); + provide(matchedRouteKey, matchedRouteRef); + provide(routerViewLocationKey, routeToDisplay); + const viewRef = ref(); + // watch at the same time the component instance, the route record we are + // rendering, and the name + 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 = h(ViewComponent, assign({}, routeProps, attrs, { + onVnodeUnmounted, + ref: viewRef, + })); + if (((process.env.NODE_ENV !== 'production') || __VUE_PROD_DEVTOOLS__) && + isBrowser && + component.ref) { + // TODO: can display if it's an alias, its props + const info = { + depth: depth.value, + name: matchedRoute.name, + path: matchedRoute.path, + meta: matchedRoute.meta, + }; + const internalInstances = isArray(component.ref) + ? component.ref.map(r => r.i) + : [component.ref.i]; + internalInstances.forEach(instance => { + // @ts-expect-error + instance.__vrv_devtools = info; + }); + } + return ( + // pass the vnode to the slot as a prop. + // h and 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; +// warn against deprecated usage with & +// due to functional component being no longer eager in Vue 3 +function warnDeprecatedUsage() { + const instance = getCurrentInstance(); + const parentName = instance.parent && instance.parent.type.name; + const parentSubTreeType = instance.parent && instance.parent.subTree && instance.parent.subTree.type; + if (parentName && + (parentName === 'KeepAlive' || parentName.includes('Transition')) && + typeof parentSubTreeType === 'object' && + parentSubTreeType.name === 'RouterView') { + const comp = parentName === 'KeepAlive' ? 'keep-alive' : 'transition'; + warn(` can no longer be used directly inside or .\n` + + `Use slot props instead:\n\n` + + `\n` + + ` <${comp}>\n` + + ` \n` + + ` \n` + + ``); + } +} + +/** + * 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, { + // remove variables that can contain vue instances + 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, + }, + }; +} +// to support multiple router instances +let routerId = 0; +function addDevtools(app, router, matcher) { + // Take over router.beforeEach and afterEach + // make sure we are not registering the devtool twice + if (router.__hasDevtools) + return; + router.__hasDevtools = true; + // increment to support multiple router instances + 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') { + console.warn('[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.'); + } + // display state added by the router + 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'), + }); + } + }); + // mark router-link as active and display tags on router views + 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 multiple useLink are used + 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, () => { + // refresh active state + refreshRoutesView(); + api.notifyComponentUpdate(); + api.sendInspectorTree(routerInspectorId); + api.sendInspectorState(routerInspectorId); + }); + const navigationsLayerId = 'router:navigations:' + id; + api.addTimelineLayer({ + id: navigationsLayerId, + label: `Router${id ? ' ' + id : ''} Navigations`, + color: 0x40a8c4, + }); + // const errorsLayerId = 'router:errors' + // api.addTimelineLayer({ + // id: errorsLayerId, + // label: 'Router Errors', + // color: 0xea5455, + // }) + 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, + }, + }); + }); + // attached to `meta` and used to group events + 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'), + }; + // Used to group navigations together, hide from devtools + 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('✅'); + } + // we set here to have the right order + 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() { + // the routes view isn't active + if (!activeRoutesPayload) + return; + const payload = activeRoutesPayload; + // children routes will appear as nested + let routes = matcher.getRoutes().filter(route => !route.parent || + // these routes have a parent with no component which will not appear in the view + // therefore we still need to include them + !route.parent.record.components); + // reset match state to false + routes.forEach(resetMatchStateOnRouteRecord); + // apply a match state if there is a payload + if (payload.filter) { + routes = routes.filter(route => + // save matches state based on the payload + isRouteMatching(route, payload.filter.toLowerCase())); + } + // mark active routes + 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 routes = matcher.getRoutes(); + const route = routes.find(route => route.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 = 0xec4899; +const BLUE_600 = 0x2563eb; +const LIME_500 = 0x84cc16; +const CYAN_400 = 0x22d3ee; +const ORANGE_400 = 0xfb923c; +// const GRAY_100 = 0xf4f4f5 +const DARK = 0x666666; +const RED_100 = 0xfee2e2; +const RED_700 = 0xb91c1c; +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: 0xffffff, + backgroundColor: DARK, + }); + } + // add an id to be able to select it. Using the `path` is not possible because + // empty path children would collide with their parents + 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), + }; +} +// incremental id for route records and inspector state +let routeRecordId = 0; +const EXTRACT_REGEXP_RE = /^\/(.*)\/([a-z]*)$/; +function markRouteRecordActive(route, currentRoute) { + // no route will be active if matched is empty + // reset the matching state + 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; + } + // use a regexp without $ at the end to match nested routes better + const nonEndingRE = new RegExp(found[1].replace(/\$$/, ''), found[2]); + if (nonEndingRE.test(filter)) { + // mark children as matches + route.children.forEach(child => isRouteMatching(child, filter)); + // exception case: `/` + if (route.record.path !== '/' || filter === '/') { + route.__vd_match = route.re.test(filter); + return true; + } + // hide the / route + return false; + } + const path = route.record.path.toLowerCase(); + const decodedPath = decode(path); + // also allow partial matching on the 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)) { + // @ts-expect-error + ret[key] = obj[key]; + } + } + return ret; +} + +/** + * 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; + if ((process.env.NODE_ENV !== 'production') && !routerHistory) + throw new Error('Provide the "history" option when calling "createRouter()":' + + ' https://router.vuejs.org/api/interfaces/RouterOptions.html#history'); + const beforeGuards = useCallbacks(); + const beforeResolveGuards = useCallbacks(); + const afterGuards = useCallbacks(); + const currentRoute = 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); + if ((process.env.NODE_ENV !== 'production') && !parent) { + warn(`Parent route "${String(parentOrRoute)}" not found when adding child route`, route); + } + record = route; + } + else { + record = parentOrRoute; + } + return matcher.addRoute(record, parent); + } + function removeRoute(name) { + const recordMatcher = matcher.getRecordMatcher(name); + if (recordMatcher) { + matcher.removeRoute(recordMatcher); + } + else if ((process.env.NODE_ENV !== 'production')) { + warn(`Cannot remove non-existent route "${String(name)}"`); + } + } + function getRoutes() { + return matcher.getRoutes().map(routeMatcher => routeMatcher.record); + } + function hasRoute(name) { + return !!matcher.getRecordMatcher(name); + } + function resolve(rawLocation, currentLocation) { + // const resolve: Router['resolve'] = (rawLocation: RouteLocationRaw, 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); + if ((process.env.NODE_ENV !== 'production')) { + if (href.startsWith('//')) + warn(`Location "${rawLocation}" resolved to "${href}". A resolved location cannot start with multiple slashes.`); + else if (!matchedRoute.matched.length) { + warn(`No match found for location with path "${rawLocation}"`); + } + } + // locationNormalized is always a new object + return assign(locationNormalized, matchedRoute, { + params: decodeParams(matchedRoute.params), + hash: decode(locationNormalized.hash), + redirectedFrom: undefined, + href, + }); + } + if ((process.env.NODE_ENV !== 'production') && !isRouteLocation(rawLocation)) { + warn(`router.resolve() was passed an invalid location. This will fail in production.\n- Location:`, rawLocation); + return resolve({}); + } + let matcherLocation; + // path could be relative in object as well + if (rawLocation.path != null) { + if ((process.env.NODE_ENV !== 'production') && + 'params' in rawLocation && + !('name' in rawLocation) && + // @ts-expect-error: the type is never + Object.keys(rawLocation.params).length) { + warn(`Path "${rawLocation.path}" was passed with params but they will be ignored. Use a named route alongside params instead.`); + } + 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(targetParams), + }); + // 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 || ''; + if ((process.env.NODE_ENV !== 'production') && hash && !hash.startsWith('#')) { + warn(`A \`hash\` should always start with the character "#". Replace "${hash}" with "#${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); + if ((process.env.NODE_ENV !== 'production')) { + if (href.startsWith('//')) { + warn(`Location "${rawLocation}" resolved to "${href}". A resolved location cannot start with multiple slashes.`); + } + else if (!matchedRoute.matched.length) { + warn(`No match found for location with path "${rawLocation.path != null ? rawLocation.path : rawLocation}"`); + } + } + 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 = {}; + } + if ((process.env.NODE_ENV !== 'production') && + newTargetLocation.path == null && + !('name' in newTargetLocation)) { + warn(`Invalid redirect found:\n${JSON.stringify(newTargetLocation, null, 2)}\n when navigating to "${to.fullPath}". A redirect must contain a name or path. This will break in production.`); + throw new Error('Invalid redirect'); + } + return assign({ + query: to.query, + hash: to.hash, + // avoid transferring params if the redirect has a path + params: newTargetLocation.path != null ? {} : 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 */)) { + if ((process.env.NODE_ENV !== 'production') && + // we are redirecting to the same location we were already at + isSameRouteLocation(stringifyQuery$1, resolve(failure.to), toLocation) && + // and we have done it a couple of times + redirectedFrom && + // @ts-expect-error: added only in dev + (redirectedFrom._count = redirectedFrom._count + ? // @ts-expect-error + redirectedFrom._count + 1 + : 1) > 30) { + warn(`Detected a possibly infinite redirection in a navigation guard when going from "${from.fullPath}" to "${toLocation.fullPath}". Aborting to avoid a Stack Overflow.\n Are you always returning a new location within a navigation guard? That would lead to this error. Only return when redirecting or aborting, that should fix this. This might break in production if not fixed.`); + return Promise.reject(new Error('Infinite redirect in navigation guard')); + } + 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(); + } + function runWithContext(fn) { + const app = installedApps.values().next().value; + // support Vue < 3.3 + return app && typeof app.runWithContext === 'function' + ? app.runWithContext(fn) + : fn(); + } + // 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 enteringRecords) { + // do not trigger beforeEnter on reused views + if (record.beforeEnter) { + 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 + // clear existing enterCallbacks, these are added by extractComponentsGuards + to.matched.forEach(record => (record.enterCallbacks = {})); + // check in-component beforeRouteEnter + guards = extractComponentsGuards(enteringRecords, 'beforeRouteEnter', to, from, runWithContext); + 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 + afterGuards + .list() + .forEach(guard => runWithContext(() => 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); + }) + // avoid warnings in the console about uncaught rejections, they are logged by triggerErrors + .catch(noop); + }); + } + // Initialization and Errors + let readyHandlers = useCallbacks(); + let errorListeners = useCallbacks(); + let ready; + /** + * Trigger errorListeners 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 = errorListeners.list(); + if (list.length) { + list.forEach(handler => handler(error, to, from)); + } + else { + if ((process.env.NODE_ENV !== 'production')) { + warn('uncaught error during route navigation:'); + } + console.error(error); + } + // reject the error no matter there were error listeners or not + 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 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, + clearRoutes: matcher.clearRoutes, + hasRoute, + getRoutes, + resolve, + options, + push, + replace, + go, + back: () => go(-1), + forward: () => go(1), + beforeEach: beforeGuards.add, + beforeResolve: beforeResolveGuards.add, + afterEach: afterGuards.add, + onError: errorListeners.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: () => 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 => { + if ((process.env.NODE_ENV !== 'production')) + warn('Unexpected error when starting the router:', err); + }); + } + const reactiveRoute = {}; + for (const key in START_LOCATION_NORMALIZED) { + Object.defineProperty(reactiveRoute, key, { + get: () => currentRoute.value[key], + enumerable: true, + }); + } + app.provide(routerKey, router); + app.provide(routeLocationKey, shallowReactive(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(); + }; + // TODO: this probably needs to be updated so it can be used by vue-termui + if (((process.env.NODE_ENV !== 'production') || __VUE_PROD_DEVTOOLS__) && isBrowser) { + addDevtools(app, router, matcher); + } + }, + }; + // TODO: type this as NavigationGuardReturn or similar instead of any + function runGuardQueue(guards) { + return guards.reduce((promise, guard) => promise.then(() => runWithContext(guard)), Promise.resolve()); + } + return router; +} +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 inject(routerKey); +} +/** + * Returns the current route location. Equivalent to using `$route` inside + * templates. + */ +function useRoute(_name) { + return inject(routeLocationKey); +} + +export { NavigationFailureType, RouterLink, RouterView, START_LOCATION_NORMALIZED as START_LOCATION, createMemoryHistory, createRouter, createRouterMatcher, createWebHashHistory, createWebHistory, isNavigationFailure, loadRouteLocation, matchedRouteKey, onBeforeRouteLeave, onBeforeRouteUpdate, parseQuery, routeLocationKey, routerKey, routerViewLocationKey, stringifyQuery, useLink, useRoute, useRouter, viewDepthKey }; diff --git a/node_modules/vue-router/dist/vue-router.node.mjs b/node_modules/vue-router/dist/vue-router.node.mjs new file mode 100644 index 0000000..919e9fd --- /dev/null +++ b/node_modules/vue-router/dist/vue-router.node.mjs @@ -0,0 +1,2 @@ +global.__VUE_PROD_DEVTOOLS__ = false; +export * from '../dist/vue-router.mjs' \ No newline at end of file diff --git a/node_modules/vue-router/dist/vue-router.prod.cjs b/node_modules/vue-router/dist/vue-router.prod.cjs new file mode 100644 index 0000000..38bd94b --- /dev/null +++ b/node_modules/vue-router/dist/vue-router.prod.cjs @@ -0,0 +1,2953 @@ +/*! + * vue-router v4.4.5 + * (c) 2024 Eduardo San Martin Morote + * @license MIT + */ +'use strict'; + +var vue = require('vue'); + +const isBrowser = typeof document !== 'undefined'; + +/** + * 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' || + // support CF with dynamic imports that do not + // add the Module string tag + (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; + +/** + * 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; // %23 +const AMPERSAND_RE = /&/g; // %26 +const SLASH_RE = /\//g; // %2F +const EQUAL_RE = /=/g; // %3D +const IM_RE = /\?/g; // %3F +const 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; +} + +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: decode(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 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, 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('/'); + const lastToSegment = toSegments[toSegments.length - 1]; + // make . and ./ the same (../ === .., ../../ === ../..) + // this is the same behavior as new URL() + if (lastToSegment === '..' || lastToSegment === '.') { + toSegments.push(''); + } + 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.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: '/', + // TODO: could we use a symbol in the future? + name: undefined, + params: {}, + query: {}, + hash: '', + fullPath: '/', + matched: [], + meta: {}, + redirectedFrom: undefined, +}; + +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 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 hash +const 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.scrollX, + top: window.scrollY, +}); +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.scrollX, scrollToOptions.top != null ? scrollToOptions.top : window.scrollY); + } +} +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 { +// // 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 = { +// compute: computeScroll, +// scroll: scrollToPosition, +// } + +let createBaseLocation = () => location.protocol + '//' + location.host; +/** + * Creates a normalized history location from a window.location object + * @param base - The base path + * @param location - The window.location object + */ +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); + } + // 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); + // TODO: could we use 'pagehide' or 'visibilitychange' instead? + // https://developer.chrome.com/blog/page-lifecycle-api/ + window.addEventListener('beforeunload', beforeUnloadListener, { + passive: true, + }); + 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 `` 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 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 `` 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 `` 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'; +} + +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 messages +const 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}".`; + }, +}; +/** + * Creates a typed NavigationFailure object. + * @internal + * @param type - NavigationFailureType + * @param params - { from, to } + */ +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 (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); +} + +// 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 tokens +const 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() +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( + // we need to normalize again to ensure the `mods` property + // being non enumerable + normalizeRouteRecord(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); + } + // 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 (isMatchable(matcher)) { + insertMatcher(matcher); + } + 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) + // } + } + 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) { + const index = findInsertionIndex(matcher, matchers); + matchers.splice(index, 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 + // only keep optional params coming from a parent record + matcher.keys + .filter(k => !k.optional) + .concat(matcher.parent ? matcher.parent.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 (location.path != null) { + // 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)); + function clearRoutes() { + matchers.length = 0; + matcherMap.clear(); + } + return { + addRoute, + resolve, + removeRoute, + clearRoutes, + 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) { + const normalized = { + path: record.path, + redirect: record.redirect, + name: record.name, + meta: record.meta || {}, + aliasOf: record.aliasOf, + beforeEnter: record.beforeEnter, + props: normalizeRecordProps(record), + children: record.children || [], + instances: {}, + leaveGuards: new Set(), + updateGuards: new Set(), + enterCallbacks: {}, + // must be declared afterwards + // mods: {}, + components: 'components' in record + ? record.components || null + : record.component && { default: record.component }, + }; + // mods contain modules and shouldn't be copied, + // logged or anything. It's just used for internal + // advanced use cases like data loaders + Object.defineProperty(normalized, 'mods', { + value: {}, + }); + return normalized; +} +/** + * 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 === 'object' ? props[name] : props; + } + 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; +} +/** + * Performs a binary search to find the correct insertion index for a new matcher. + * + * Matchers are primarily sorted by their score. If scores are tied then we also consider parent/child relationships, + * with descendants coming before ancestors. If there's still a tie, new routes are inserted after existing routes. + * + * @param matcher - new matcher to be inserted + * @param matchers - existing matchers + */ +function findInsertionIndex(matcher, matchers) { + // First phase: binary search based on score + let lower = 0; + let upper = matchers.length; + while (lower !== upper) { + const mid = (lower + upper) >> 1; + const sortOrder = comparePathParserScore(matcher, matchers[mid]); + if (sortOrder < 0) { + upper = mid; + } + else { + lower = mid + 1; + } + } + // Second phase: check for an ancestor with the same score + const insertionAncestor = getInsertionAncestor(matcher); + if (insertionAncestor) { + upper = matchers.lastIndexOf(insertionAncestor, upper - 1); + } + return upper; +} +function getInsertionAncestor(matcher) { + let ancestor = matcher; + while ((ancestor = ancestor.parent)) { + if (isMatchable(ancestor) && + comparePathParserScore(matcher, ancestor) === 0) { + return ancestor; + } + } + return; +} +/** + * Checks if a matcher can be reachable. This means if it's possible to reach it as a route. For example, routes without + * a component, or name, or redirect, are just used to group other routes. + * @param matcher + * @param matcher.record record of the matcher + * @returns + */ +function isMatchable({ record }) { + return !!(record.name || + (record.components && Object.keys(record.components).length) || + record.redirect); +} + +/** + * 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.slice(), + 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, runWithContext = fn => fn()) { + // 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 = runWithContext(() => 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, runWithContext = fn => fn()) { + 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, runWithContext)); + } + else { + // start requesting the chunk already + let componentPromise = rawComponent(); + 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; + // keep the resolved module for plugins like data loaders + record.mods[name] = 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, runWithContext)()); + })); + } + } + } + return guards; +} +/** + * Ensures a route is loaded, so it can be passed as o prop to ``. + * + * @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; + // keep the resolved module for plugins like data loaders + record.mods[name] = 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 RFC +/** + * Returns the internal behavior of a {@link RouterLink} without the rendering part. + * + * @param props - a `to` location and an optional `replace` flag + */ +function useLink(props) { + const router = vue.inject(routerKey); + const currentRoute = vue.inject(routeLocationKey); + const route = vue.computed(() => { + const to = vue.unref(props.to); + return router.resolve(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 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 resolve: Router['resolve'] = (rawLocation: RouteLocationRaw, 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 (rawLocation.path != null) { + 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(targetParams), + }); + // 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: newTargetLocation.path != null ? {} : 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(); + } + function runWithContext(fn) { + const app = installedApps.values().next().value; + // support Vue < 3.3 + return app && typeof app.runWithContext === 'function' + ? app.runWithContext(fn) + : fn(); + } + // 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 enteringRecords) { + // do not trigger beforeEnter on reused views + if (record.beforeEnter) { + 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 + // clear existing enterCallbacks, these are added by extractComponentsGuards + to.matched.forEach(record => (record.enterCallbacks = {})); + // check in-component beforeRouteEnter + guards = extractComponentsGuards(enteringRecords, 'beforeRouteEnter', to, from, runWithContext); + 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 + afterGuards + .list() + .forEach(guard => runWithContext(() => 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); + }) + // avoid warnings in the console about uncaught rejections, they are logged by triggerErrors + .catch(noop); + }); + } + // Initialization and Errors + let readyHandlers = useCallbacks(); + let errorListeners = useCallbacks(); + let ready; + /** + * Trigger errorListeners 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 = errorListeners.list(); + if (list.length) { + list.forEach(handler => handler(error, to, from)); + } + else { + console.error(error); + } + // reject the error no matter there were error listeners or not + 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, + clearRoutes: matcher.clearRoutes, + hasRoute, + getRoutes, + resolve, + options, + push, + replace, + go, + back: () => go(-1), + forward: () => go(1), + beforeEach: beforeGuards.add, + beforeResolve: beforeResolveGuards.add, + afterEach: afterGuards.add, + onError: errorListeners.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) { + Object.defineProperty(reactiveRoute, key, { + get: () => currentRoute.value[key], + enumerable: true, + }); + } + app.provide(routerKey, router); + app.provide(routeLocationKey, vue.shallowReactive(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(); + }; + }, + }; + // TODO: type this as NavigationGuardReturn or similar instead of any + function runGuardQueue(guards) { + return guards.reduce((promise, guard) => promise.then(() => runWithContext(guard)), Promise.resolve()); + } + return router; +} +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(_name) { + 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; diff --git a/node_modules/vue-router/index.js b/node_modules/vue-router/index.js new file mode 100644 index 0000000..9be86a8 --- /dev/null +++ b/node_modules/vue-router/index.js @@ -0,0 +1,7 @@ +'use strict' + +if (process.env.NODE_ENV === 'production') { + module.exports = require('./dist/vue-router.prod.cjs') +} else { + module.exports = require('./dist/vue-router.cjs') +} diff --git a/node_modules/vue-router/package.json b/node_modules/vue-router/package.json new file mode 100644 index 0000000..d2a22a6 --- /dev/null +++ b/node_modules/vue-router/package.json @@ -0,0 +1,153 @@ +{ + "name": "vue-router", + "version": "4.4.5", + "main": "index.js", + "unpkg": "dist/vue-router.global.js", + "jsdelivr": "dist/vue-router.global.js", + "module": "dist/vue-router.mjs", + "types": "dist/vue-router.d.ts", + "exports": { + ".": { + "types": "./dist/vue-router.d.ts", + "node": { + "import": { + "production": "./dist/vue-router.node.mjs", + "development": "./dist/vue-router.node.mjs", + "default": "./dist/vue-router.node.mjs" + }, + "require": { + "production": "./dist/vue-router.prod.cjs", + "development": "./dist/vue-router.cjs", + "default": "./index.js" + } + }, + "import": "./dist/vue-router.mjs", + "require": "./index.js" + }, + "./dist/*": "./dist/*", + "./vetur/*": "./vetur/*", + "./package.json": "./package.json", + "./auto-routes": { + "types": "./vue-router-auto-routes.d.ts", + "node": { + "import": { + "production": "./dist/vue-router.node.mjs", + "development": "./dist/vue-router.node.mjs", + "default": "./dist/vue-router.node.mjs" + }, + "require": { + "production": "./dist/vue-router.prod.cjs", + "development": "./dist/vue-router.cjs", + "default": "./index.js" + } + }, + "import": "./dist/vue-router.mjs", + "require": "./index.js" + }, + "./auto": { + "types": "./vue-router-auto.d.ts", + "node": { + "import": { + "production": "./dist/vue-router.node.mjs", + "development": "./dist/vue-router.node.mjs", + "default": "./dist/vue-router.node.mjs" + }, + "require": { + "production": "./dist/vue-router.prod.cjs", + "development": "./dist/vue-router.cjs", + "default": "./index.js" + } + }, + "import": "./dist/vue-router.mjs", + "require": "./index.js" + } + }, + "sideEffects": false, + "author": { + "name": "Eduardo San Martin Morote", + "email": "posva13@gmail.com" + }, + "funding": "https://github.com/sponsors/posva", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/vuejs/router.git" + }, + "bugs": { + "url": "https://github.com/vuejs/router/issues" + }, + "homepage": "https://github.com/vuejs/router#readme", + "files": [ + "index.js", + "dist/*.{js,cjs,mjs}", + "dist/vue-router.d.ts", + "vue-router-auto.d.ts", + "vue-router-auto-routes.d.ts", + "vetur/tags.json", + "vetur/attributes.json", + "README.md" + ], + "peerDependencies": { + "vue": "^3.2.0" + }, + "vetur": { + "tags": "vetur/tags.json", + "attributes": "vetur/attributes.json" + }, + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "devDependencies": { + "@microsoft/api-extractor": "^7.40.1", + "@rollup/plugin-alias": "^5.1.0", + "@rollup/plugin-commonjs": "^25.0.8", + "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-replace": "^5.0.7", + "@rollup/plugin-terser": "^0.4.4", + "@types/jsdom": "^21.1.7", + "@types/nightwatch": "^2.3.31", + "@vitejs/plugin-vue": "^5.1.3", + "@vitest/coverage-v8": "^1.6.0", + "@vitest/ui": "^1.6.0", + "@vue/compiler-sfc": "~3.4.3", + "@vue/server-renderer": "~3.4.3", + "@vue/test-utils": "^2.4.6", + "browserstack-local": "^1.5.5", + "chromedriver": "^128.0.1", + "connect-history-api-fallback": "^1.6.0", + "conventional-changelog-cli": "^2.2.2", + "dotenv": "^16.4.5", + "faked-promise": "^2.2.2", + "geckodriver": "^4.4.4", + "happy-dom": "^15.7.3", + "nightwatch": "^2.6.25", + "nightwatch-helpers": "^1.2.0", + "rimraf": "^6.0.1", + "rollup": "^3.29.4", + "rollup-plugin-analyzer": "^4.0.0", + "rollup-plugin-typescript2": "^0.36.0", + "typescript": "~5.3.3", + "vite": "^5.4.3", + "vitest": "^1.6.0", + "vue": "~3.4.3" + }, + "scripts": { + "dev": "vitest --ui", + "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 1", + "build": "rimraf dist && rollup -c rollup.config.mjs", + "build:dts": "api-extractor run --local --verbose && tail -n +10 src/globalExtensions.ts >> dist/vue-router.d.ts", + "build:playground": "vue-tsc --noEmit && vite build --config playground/vite.config.ts", + "build:e2e": "vue-tsc --noEmit && vite build --config e2e/vite.config.mjs", + "build:size": "pnpm run build && rollup -c size-checks/rollup.config.mjs", + "dev:e2e": "vite --config e2e/vite.config.mjs", + "test:types": "tsc --build tsconfig.json", + "test:unit": "vitest --coverage run", + "test": "pnpm run build && pnpm run build:dts && pnpm run test:types && pnpm run test:unit && pnpm run test:e2e", + "test:e2e": "pnpm run test:e2e:headless", + "test:e2e:headless": "node e2e/runner.mjs --env chrome-headless", + "test:e2e:native": "node e2e/runner.mjs --env chrome", + "test:e2e:ci": "node e2e/runner.mjs --env chrome-headless --retries 2", + "test:e2e:bs": "node e2e/runner.mjs --local -e android5 --tag browserstack", + "test:e2e:bs-test": "node e2e/runner.mjs --local --env browserstack.local_chrome --tag browserstack" + } +} \ No newline at end of file diff --git a/node_modules/vue-router/vetur/attributes.json b/node_modules/vue-router/vetur/attributes.json new file mode 100644 index 0000000..7ca18ef --- /dev/null +++ b/node_modules/vue-router/vetur/attributes.json @@ -0,0 +1,32 @@ +{ + "name": { + "type": "string | symbol", + "description": "When a `` has a `name` prop, it will render the component with the corresponding name in the matched route record's components option." + }, + "route": { + "description": "When a `` has a `route` prop, it will use that resolved Route Location instead of the current location." + }, + "to": { + "description": "Denotes the target route of the link. When clicked, the value of the `to` prop will be internally passed to `router.push()`, so the value can be either a string or a location descriptor object." + }, + "replace": { + "type": "boolean", + "description": "Setting replace prop will call `router.replace()` instead of `router.push()` when clicked, so the navigation will replace the current history entry." + }, + "custom": { + "type": "boolean", + "description": "Whether `` should not wrap its content in an `` tag." + }, + "active-class": { + "type": "string", + "description": "Configure the active CSS class applied when the link is active. Note the default value can also be configured globally via the `linkActiveClass` router constructor option." + }, + "exact-active-class": { + "type": "string", + "description": "Configure the active CSS class applied when the link is exactly active. Note the default value can also be configured globally via the `linkExactActiveClass` router constructor option." + }, + "aria-current-value": { + "options": ["page", "step", "location", "date", "time", "true", "false"], + "description": "Configure the value of `aria-current` when the link is active with exact match. It must be one of the [allowed values for `aria-current`](https://www.w3.org/TR/wai-aria-1.2/#aria-current) in the ARIA spec. In most cases, the default of `page` should be the best fit." + } +} diff --git a/node_modules/vue-router/vetur/tags.json b/node_modules/vue-router/vetur/tags.json new file mode 100644 index 0000000..dc4f77e --- /dev/null +++ b/node_modules/vue-router/vetur/tags.json @@ -0,0 +1,10 @@ +{ + "router-view": { + "attributes": ["name", "route"], + "description": "Component that renders the matched component for the current location. Components rendered by `` can also contain their own `` to render nested routes." + }, + "router-link": { + "attributes": ["to", "replace", "custom", "active-class","exact-active-class", "aria-current-value"], + "description": "Component that renders an `` with the correct `href` attribute and click listeners to trigger a local navigation when clicked. Can also customize its rendering by providing the `custom` prop and using its `v-slot` API." + } +} diff --git a/node_modules/vue-router/vue-router-auto-routes.d.ts b/node_modules/vue-router/vue-router-auto-routes.d.ts new file mode 100644 index 0000000..12fcf1c --- /dev/null +++ b/node_modules/vue-router/vue-router-auto-routes.d.ts @@ -0,0 +1,4 @@ +/** + * Array of routes generated by unplugin-vue-router + */ +export declare const routes: any[] diff --git a/node_modules/vue-router/vue-router-auto.d.ts b/node_modules/vue-router/vue-router-auto.d.ts new file mode 100644 index 0000000..56e8a09 --- /dev/null +++ b/node_modules/vue-router/vue-router-auto.d.ts @@ -0,0 +1,4 @@ +/** + * Extended by unplugin-vue-router to create typed routes. + */ +export interface RouteNamedMap {} diff --git a/node_modules/vue/LICENSE b/node_modules/vue/LICENSE new file mode 100644 index 0000000..15f1f7e --- /dev/null +++ b/node_modules/vue/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2018-present, Yuxi (Evan) You + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/vue/README.md b/node_modules/vue/README.md new file mode 100644 index 0000000..69dbf69 --- /dev/null +++ b/node_modules/vue/README.md @@ -0,0 +1,62 @@ +# vue + +## Which dist file to use? + +### From CDN or without a Bundler + +- **`vue(.runtime).global(.prod).js`**: + + - For direct use via `