Full Code of vuejs/vue-router for AI

dev 680ccc68c506 cached
458 files
1.4 MB
433.3k tokens
740 symbols
1 requests
Download .txt
Showing preview only (1,589K chars total). Download the full file or copy to clipboard to get everything.
Repository: vuejs/vue-router
Branch: dev
Commit: 680ccc68c506
Files: 458
Total size: 1.4 MB

Directory structure:
gitextract_7kypz9ur/

├── .babelrc
├── .circleci/
│   └── config.yml
├── .eslintignore
├── .eslintrc
├── .flowconfig
├── .github/
│   ├── ISSUE_TEMPLATE.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── funding.yml
│   └── workflows/
│       └── release-tag.yml
├── .gitignore
├── .prettierrc
├── CHANGELOG.md
├── LICENSE
├── README.md
├── build/
│   ├── build.js
│   ├── configs.js
│   └── rollup.dev.config.js
├── composables.d.ts
├── composables.js
├── composables.mjs
├── dist/
│   ├── vue-router.common.js
│   ├── vue-router.esm.browser.js
│   ├── vue-router.esm.js
│   ├── vue-router.js
│   └── vue-router.mjs
├── docs/
│   ├── .vuepress/
│   │   ├── components/
│   │   │   ├── HomeSponsors.vue
│   │   │   ├── HomeSponsorsGroup.vue
│   │   │   └── sponsors.json
│   │   ├── config.js
│   │   ├── public/
│   │   │   └── _redirects
│   │   ├── styles/
│   │   │   └── index.styl
│   │   └── theme/
│   │       ├── Layout.vue
│   │       ├── components/
│   │       │   ├── BuySellAds.vue
│   │       │   ├── CarbonAds.vue
│   │       │   └── VueSchool/
│   │       │       └── BannerTop.vue
│   │       └── index.js
│   ├── README.md
│   ├── api/
│   │   └── README.md
│   ├── fr/
│   │   ├── README.md
│   │   ├── api/
│   │   │   └── README.md
│   │   ├── guide/
│   │   │   ├── README.md
│   │   │   ├── advanced/
│   │   │   │   ├── data-fetching.md
│   │   │   │   ├── lazy-loading.md
│   │   │   │   ├── meta.md
│   │   │   │   ├── navigation-guards.md
│   │   │   │   ├── scroll-behavior.md
│   │   │   │   └── transitions.md
│   │   │   └── essentials/
│   │   │       ├── dynamic-matching.md
│   │   │       ├── history-mode.md
│   │   │       ├── named-routes.md
│   │   │       ├── named-views.md
│   │   │       ├── navigation.md
│   │   │       ├── nested-routes.md
│   │   │       ├── passing-props.md
│   │   │       └── redirect-and-alias.md
│   │   └── installation.md
│   ├── guide/
│   │   ├── README.md
│   │   ├── advanced/
│   │   │   ├── data-fetching.md
│   │   │   ├── lazy-loading.md
│   │   │   ├── meta.md
│   │   │   ├── navigation-failures.md
│   │   │   ├── navigation-guards.md
│   │   │   ├── scroll-behavior.md
│   │   │   └── transitions.md
│   │   └── essentials/
│   │       ├── dynamic-matching.md
│   │       ├── history-mode.md
│   │       ├── named-routes.md
│   │       ├── named-views.md
│   │       ├── navigation.md
│   │       ├── nested-routes.md
│   │       ├── passing-props.md
│   │       └── redirect-and-alias.md
│   ├── installation.md
│   ├── ja/
│   │   ├── README.md
│   │   ├── api/
│   │   │   └── README.md
│   │   ├── guide/
│   │   │   ├── README.md
│   │   │   ├── advanced/
│   │   │   │   ├── data-fetching.md
│   │   │   │   ├── lazy-loading.md
│   │   │   │   ├── meta.md
│   │   │   │   ├── navigation-failures.md
│   │   │   │   ├── navigation-guards.md
│   │   │   │   ├── scroll-behavior.md
│   │   │   │   └── transitions.md
│   │   │   └── essentials/
│   │   │       ├── dynamic-matching.md
│   │   │       ├── history-mode.md
│   │   │       ├── named-routes.md
│   │   │       ├── named-views.md
│   │   │       ├── navigation.md
│   │   │       ├── nested-routes.md
│   │   │       ├── passing-props.md
│   │   │       └── redirect-and-alias.md
│   │   └── installation.md
│   ├── kr/
│   │   ├── README.md
│   │   ├── api/
│   │   │   └── README.md
│   │   ├── guide/
│   │   │   ├── README.md
│   │   │   ├── advanced/
│   │   │   │   ├── data-fetching.md
│   │   │   │   ├── lazy-loading.md
│   │   │   │   ├── meta.md
│   │   │   │   ├── navigation-guards.md
│   │   │   │   ├── scroll-behavior.md
│   │   │   │   └── transitions.md
│   │   │   └── essentials/
│   │   │       ├── dynamic-matching.md
│   │   │       ├── getting-started.md
│   │   │       ├── history-mode.md
│   │   │       ├── named-routes.md
│   │   │       ├── named-views.md
│   │   │       ├── navigation.md
│   │   │       ├── nested-routes.md
│   │   │       ├── passing-props.md
│   │   │       └── redirect-and-alias.md
│   │   └── installation.md
│   ├── ru/
│   │   ├── README.md
│   │   ├── api/
│   │   │   └── README.md
│   │   ├── guide/
│   │   │   ├── README.md
│   │   │   ├── advanced/
│   │   │   │   ├── data-fetching.md
│   │   │   │   ├── lazy-loading.md
│   │   │   │   ├── meta.md
│   │   │   │   ├── navigation-failures.md
│   │   │   │   ├── navigation-guards.md
│   │   │   │   ├── scroll-behavior.md
│   │   │   │   └── transitions.md
│   │   │   └── essentials/
│   │   │       ├── dynamic-matching.md
│   │   │       ├── history-mode.md
│   │   │       ├── named-routes.md
│   │   │       ├── named-views.md
│   │   │       ├── navigation.md
│   │   │       ├── nested-routes.md
│   │   │       ├── passing-props.md
│   │   │       └── redirect-and-alias.md
│   │   └── installation.md
│   └── zh/
│       ├── README.md
│       ├── api/
│       │   └── README.md
│       ├── guide/
│       │   ├── README.md
│       │   ├── advanced/
│       │   │   ├── data-fetching.md
│       │   │   ├── lazy-loading.md
│       │   │   ├── meta.md
│       │   │   ├── navigation-failures.md
│       │   │   ├── navigation-guards.md
│       │   │   ├── scroll-behavior.md
│       │   │   └── transitions.md
│       │   └── essentials/
│       │       ├── dynamic-matching.md
│       │       ├── history-mode.md
│       │       ├── named-routes.md
│       │       ├── named-views.md
│       │       ├── navigation.md
│       │       ├── nested-routes.md
│       │       ├── passing-props.md
│       │       └── redirect-and-alias.md
│       └── installation.md
├── docs-gitbook/
│   ├── LANGS.md
│   ├── assets/
│   │   ├── CNAME
│   │   └── circle.yml
│   ├── book.json
│   ├── de/
│   │   ├── SUMMARY.md
│   │   ├── advanced/
│   │   │   ├── data-fetching.md
│   │   │   ├── lazy-loading.md
│   │   │   ├── meta.md
│   │   │   ├── navigation-guards.md
│   │   │   ├── scroll-behavior.md
│   │   │   └── transitions.md
│   │   ├── api/
│   │   │   ├── component-injections.md
│   │   │   ├── options.md
│   │   │   ├── route-object.md
│   │   │   ├── router-instance.md
│   │   │   ├── router-link.md
│   │   │   └── router-view.md
│   │   ├── essentials/
│   │   │   ├── dynamic-matching.md
│   │   │   ├── getting-started.md
│   │   │   ├── history-mode.md
│   │   │   ├── named-routes.md
│   │   │   ├── named-views.md
│   │   │   ├── navigation.md
│   │   │   ├── nested-routes.md
│   │   │   └── redirect-and-alias.md
│   │   └── installation.md
│   ├── es/
│   │   ├── README.md
│   │   ├── SUMMARY.md
│   │   ├── advanced/
│   │   │   ├── data-fetching.md
│   │   │   ├── lazy-loading.md
│   │   │   ├── meta.md
│   │   │   ├── navigation-guards.md
│   │   │   ├── scroll-behavior.md
│   │   │   └── transitions.md
│   │   ├── api/
│   │   │   ├── component-injections.md
│   │   │   ├── options.md
│   │   │   ├── route-object.md
│   │   │   ├── router-instance.md
│   │   │   ├── router-link.md
│   │   │   └── router-view.md
│   │   ├── essentials/
│   │   │   ├── dynamic-matching.md
│   │   │   ├── getting-started.md
│   │   │   ├── history-mode.md
│   │   │   ├── named-routes.md
│   │   │   ├── named-views.md
│   │   │   ├── navigation.md
│   │   │   ├── nested-routes.md
│   │   │   ├── passing-props.md
│   │   │   └── redirect-and-alias.md
│   │   └── installation.md
│   ├── fr/
│   │   ├── README.md
│   │   ├── SUMMARY.md
│   │   ├── advanced/
│   │   │   ├── data-fetching.md
│   │   │   ├── lazy-loading.md
│   │   │   ├── meta.md
│   │   │   ├── navigation-guards.md
│   │   │   ├── scroll-behavior.md
│   │   │   └── transitions.md
│   │   ├── api/
│   │   │   ├── component-injections.md
│   │   │   ├── options.md
│   │   │   ├── route-object.md
│   │   │   ├── router-instance.md
│   │   │   ├── router-link.md
│   │   │   └── router-view.md
│   │   ├── essentials/
│   │   │   ├── dynamic-matching.md
│   │   │   ├── getting-started.md
│   │   │   ├── history-mode.md
│   │   │   ├── named-routes.md
│   │   │   ├── named-views.md
│   │   │   ├── navigation.md
│   │   │   ├── nested-routes.md
│   │   │   ├── passing-props.md
│   │   │   └── redirect-and-alias.md
│   │   └── installation.md
│   ├── ja/
│   │   ├── README.md
│   │   ├── SUMMARY.md
│   │   ├── advanced/
│   │   │   ├── data-fetching.md
│   │   │   ├── lazy-loading.md
│   │   │   ├── meta.md
│   │   │   ├── navigation-guards.md
│   │   │   ├── scroll-behavior.md
│   │   │   └── transitions.md
│   │   ├── api/
│   │   │   ├── component-injections.md
│   │   │   ├── options.md
│   │   │   ├── route-object.md
│   │   │   ├── router-instance.md
│   │   │   ├── router-link.md
│   │   │   └── router-view.md
│   │   ├── essentials/
│   │   │   ├── dynamic-matching.md
│   │   │   ├── getting-started.md
│   │   │   ├── history-mode.md
│   │   │   ├── named-routes.md
│   │   │   ├── named-views.md
│   │   │   ├── navigation.md
│   │   │   ├── nested-routes.md
│   │   │   ├── passing-props.md
│   │   │   └── redirect-and-alias.md
│   │   └── installation.md
│   ├── kr/
│   │   ├── README.md
│   │   ├── SUMMARY.md
│   │   ├── advanced/
│   │   │   ├── data-fetching.md
│   │   │   ├── lazy-loading.md
│   │   │   ├── meta.md
│   │   │   ├── navigation-guards.md
│   │   │   ├── scroll-behavior.md
│   │   │   └── transitions.md
│   │   ├── api/
│   │   │   ├── component-injections.md
│   │   │   ├── options.md
│   │   │   ├── route-object.md
│   │   │   ├── router-instance.md
│   │   │   ├── router-link.md
│   │   │   └── router-view.md
│   │   ├── essentials/
│   │   │   ├── dynamic-matching.md
│   │   │   ├── getting-started.md
│   │   │   ├── history-mode.md
│   │   │   ├── named-routes.md
│   │   │   ├── named-views.md
│   │   │   ├── navigation.md
│   │   │   ├── nested-routes.md
│   │   │   ├── passing-props.md
│   │   │   └── redirect-and-alias.md
│   │   └── installation.md
│   ├── old/
│   │   ├── README.md
│   │   └── SUMMARY.md
│   └── ru/
│       ├── README.md
│       ├── SUMMARY.md
│       ├── advanced/
│       │   ├── data-fetching.md
│       │   ├── lazy-loading.md
│       │   ├── meta.md
│       │   ├── navigation-guards.md
│       │   ├── scroll-behavior.md
│       │   └── transitions.md
│       ├── api/
│       │   ├── component-injections.md
│       │   ├── options.md
│       │   ├── route-object.md
│       │   ├── router-instance.md
│       │   ├── router-link.md
│       │   └── router-view.md
│       ├── essentials/
│       │   ├── dynamic-matching.md
│       │   ├── getting-started.md
│       │   ├── history-mode.md
│       │   ├── named-routes.md
│       │   ├── named-views.md
│       │   ├── navigation.md
│       │   ├── nested-routes.md
│       │   ├── passing-props.md
│       │   └── redirect-and-alias.md
│       └── installation.md
├── examples/
│   ├── active-links/
│   │   ├── app.js
│   │   └── index.html
│   ├── auth-flow/
│   │   ├── app.js
│   │   ├── auth.js
│   │   ├── components/
│   │   │   ├── About.vue
│   │   │   ├── App.vue
│   │   │   ├── Dashboard.vue
│   │   │   └── Login.vue
│   │   └── index.html
│   ├── basic/
│   │   ├── app.js
│   │   └── index.html
│   ├── composables/
│   │   ├── app.js
│   │   └── index.html
│   ├── data-fetching/
│   │   ├── Post.vue
│   │   ├── api.js
│   │   ├── app.js
│   │   └── index.html
│   ├── discrete-components/
│   │   ├── app.js
│   │   └── index.html
│   ├── global.css
│   ├── hash-mode/
│   │   ├── app.js
│   │   └── index.html
│   ├── hash-scroll-behavior/
│   │   ├── app.js
│   │   └── index.html
│   ├── index.html
│   ├── keepalive-view/
│   │   ├── app.js
│   │   └── index.html
│   ├── lazy-loading/
│   │   ├── Bar.vue
│   │   ├── Baz.vue
│   │   ├── Foo.vue
│   │   ├── app.js
│   │   └── index.html
│   ├── lazy-loading-before-mount/
│   │   ├── app.js
│   │   └── index.html
│   ├── multi-app/
│   │   ├── app.js
│   │   └── index.html
│   ├── named-routes/
│   │   ├── app.js
│   │   └── index.html
│   ├── named-views/
│   │   ├── app.js
│   │   └── index.html
│   ├── navigation-guards/
│   │   ├── app.js
│   │   └── index.html
│   ├── nested-router/
│   │   ├── app.js
│   │   └── index.html
│   ├── nested-routes/
│   │   ├── app.js
│   │   └── index.html
│   ├── redirect/
│   │   ├── app.js
│   │   └── index.html
│   ├── restart-app/
│   │   ├── app.js
│   │   └── index.html
│   ├── route-alias/
│   │   ├── app.js
│   │   └── index.html
│   ├── route-matching/
│   │   ├── app.js
│   │   └── index.html
│   ├── route-params/
│   │   ├── app.js
│   │   └── index.html
│   ├── route-props/
│   │   ├── Hello.vue
│   │   ├── app.js
│   │   └── index.html
│   ├── router-errors/
│   │   ├── app.js
│   │   └── index.html
│   ├── scroll-behavior/
│   │   ├── app.js
│   │   └── index.html
│   ├── server.js
│   ├── transitions/
│   │   ├── app.js
│   │   └── index.html
│   └── webpack.config.js
├── flow/
│   └── declarations.js
├── netlify.toml
├── package.json
├── scripts/
│   ├── release.sh
│   └── verifyCommitMsg.js
├── src/
│   ├── components/
│   │   ├── link.js
│   │   └── view.js
│   ├── composables/
│   │   ├── globals.js
│   │   ├── guards.js
│   │   ├── index.js
│   │   ├── useLink.js
│   │   └── utils.js
│   ├── create-matcher.js
│   ├── create-route-map.js
│   ├── entries/
│   │   ├── cjs.js
│   │   └── esm.js
│   ├── history/
│   │   ├── abstract.js
│   │   ├── base.js
│   │   ├── hash.js
│   │   └── html5.js
│   ├── index.js
│   ├── install.js
│   ├── router.js
│   └── util/
│       ├── async.js
│       ├── dom.js
│       ├── errors.js
│       ├── location.js
│       ├── misc.js
│       ├── params.js
│       ├── path.js
│       ├── push-state.js
│       ├── query.js
│       ├── resolve-components.js
│       ├── route.js
│       ├── scroll.js
│       ├── state-key.js
│       └── warn.js
├── test/
│   ├── .eslintrc
│   ├── e2e/
│   │   ├── .eslintrc
│   │   ├── browserstack-send-status.js
│   │   ├── nightwatch.browserstack.js
│   │   ├── nightwatch.config.js
│   │   ├── runner.js
│   │   └── specs/
│   │       ├── .prettierrc
│   │       ├── active-links.js
│   │       ├── auth-flow.js
│   │       ├── basic.js
│   │       ├── composables.js
│   │       ├── data-fetching.js
│   │       ├── hash-mode.js
│   │       ├── hash-scroll-behavior.js
│   │       ├── history-state.js
│   │       ├── keepalive-view.js
│   │       ├── lazy-loading-before-mount.js
│   │       ├── lazy-loading.js
│   │       ├── multi-app.js
│   │       ├── named-routes.js
│   │       ├── named-views.js
│   │       ├── navigation-guards.js
│   │       ├── nested-router.js
│   │       ├── nested-routes.js
│   │       ├── redirect.js
│   │       ├── restart-app.js
│   │       ├── route-alias.js
│   │       ├── route-matching.js
│   │       ├── route-params.js
│   │       ├── route-props.js
│   │       ├── scroll-behavior.js
│   │       └── transitions.js
│   └── unit/
│       ├── .eslintrc
│       ├── jasmine.json
│       └── specs/
│           ├── abstract-history.spec.js
│           ├── api.spec.js
│           ├── async.spec.js
│           ├── create-map.spec.js
│           ├── create-matcher.spec.js
│           ├── custom-query.spec.js
│           ├── discrete-components.spec.js
│           ├── error-handling.spec.js
│           ├── location.spec.js
│           ├── node.spec.js
│           ├── onReady.spec.js
│           ├── path.spec.js
│           ├── query.spec.js
│           └── route.spec.js
├── types/
│   ├── composables.d.ts
│   ├── index.d.ts
│   ├── router.d.ts
│   ├── test/
│   │   ├── index.ts
│   │   ├── meta.ts
│   │   └── tsconfig.json
│   └── vue.d.ts
└── vetur/
    ├── attributes.json
    └── tags.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .babelrc
================================================
{
  "presets": ["env", "flow-vue"],
  "plugins": ["syntax-dynamic-import"]
}


================================================
FILE: .circleci/config.yml
================================================
version: 2

defaults: &defaults
  working_directory: ~/project/vue-router
  docker:
    - image: circleci/node:lts-browsers

jobs:
  install:
    <<: *defaults
    steps:
      - checkout
      - restore_cache:
          keys:
            - v1-vue-router-{{ .Branch }}-{{ checksum "yarn.lock" }}
            - v1-vue-router-{{ .Branch }}-
            - v1-vue-router-
      - run: yarn install
      - save_cache:
          key: v1-vue-router-{{ .Branch }}-{{ checksum "yarn.lock" }}
          paths:
            - node_modules/
      - persist_to_workspace:
          root: ~/project
          paths:
            - vue-router

  lint-flow-types:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/project
      - run: yarn run lint
      - run: yarn run flow
      - run: yarn run test:types

  test-unit:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/project
      - run: yarn run test:unit
      # add codecov once it is actually ran
      # - run:
      #    name: report coverage stats for non-PRs
      #    command: |
      #      if [[ -z $CI_PULL_REQUEST ]]; then
      #        ./node_modules/.bin/codecov
      #      fi

  test-e2e:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/project
      - run: yarn run test:e2e

  test-e2e-bs-ie9:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/project
      - run: yarn run test:e2e:ie9

workflows:
  version: 2
  install-and-parallel-test:
    jobs:
      - install
      - test-unit:
          requires:
            - install
      - lint-flow-types:
          requires:
            - install
      - test-e2e:
          requires:
            - install
      - test-e2e-bs-ie9:
          requires:
            - install


================================================
FILE: .eslintignore
================================================
dist
*.ts


================================================
FILE: .eslintrc
================================================
{
  "root": true,
  "plugins": [
    "flowtype"
  ],
  "extends": [
    "plugin:vue-libs/recommended",
    "plugin:flowtype/recommended"
  ]
}


================================================
FILE: .flowconfig
================================================
[ignore]
.*/node_modules/.*
.*/test/.*
.*/dist/.*
.*/examples/.*
.*/vue/.*

[include]

[libs]
flow

[options]
#unsafe.enable_getters_and_setters=true
suppress_comment= \\(.\\|\n\\)*\\$flow-disable-line


================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
<!--
IMPORTANT: Please use the following link to create a new issue:

  https://new-issue.vuejs.org/?repo=vuejs/vue-router

If your issue was not created using the app above, it will be closed immediately.
-->


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
<!--
Please make sure to read the Pull Request Guidelines:
https://github.com/vuejs/vue/blob/dev/.github/CONTRIBUTING.md#pull-request-guidelines
-->


================================================
FILE: .github/funding.yml
================================================
github: [posva, yyx990803]
open_collective: vuejs


================================================
FILE: .github/workflows/release-tag.yml
================================================
on:
  push:
    tags:
      - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10

name: Create Release

jobs:
  build:
    name: Create Release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@master
      - name: Create Release for Tag
        id: release_tag
        uses: yyx990803/release-tag@master
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.ref }}
          body: |
            Please refer to [CHANGELOG.md](https://github.com/vuejs/vue-router/blob/dev/CHANGELOG.md) for details.


================================================
FILE: .gitignore
================================================
.DS_Store
node_modules
TODOs.md
test/e2e/reports
test/e2e/screenshots
selenium-debug.log
dist/*.gz
dist/*.map
explorations
docs/.vuepress/dist
yarn-error.log
.idea
.vscode/settings.json
.env
selenium-server.log
local.log
browserstack.err


================================================
FILE: .prettierrc
================================================
{
  "semi": false,
  "singleQuote": true,
  "printWidth": 80
}


================================================
FILE: CHANGELOG.md
================================================
## [3.6.5](https://github.com/vuejs/vue-router/compare/v3.6.4...v3.6.5) (2022-09-06)

### Bug Fixes

- **types:** Component with 4 generics for Vue 2.6 ([d6064df](https://github.com/vuejs/vue-router/commit/d6064df1112497dac98e4302d81607efdb1a58c6)), closes [#3786](https://github.com/vuejs/vue-router/issues/3786)

## [3.6.4](https://github.com/vuejs/vue-router/compare/v3.6.3...v3.6.4) (2022-08-25)

This release fixes some compatibility issues of the new `vue-router/composables` with webpack 4.

### Features

- **types:** add composables.d.ts in root ([#3784](https://github.com/vuejs/vue-router/issues/3784)) ([0cf54de](https://github.com/vuejs/vue-router/commit/0cf54de782a0b05692bbe78a7181495b6a35b8d9))

## [3.6.3](https://github.com/vuejs/vue-router/compare/v3.6.2...v3.6.3) (2022-08-23)

### Bug Fixes

- **build:** export all named exports esm build ([a6647c8](https://github.com/vuejs/vue-router/commit/a6647c8c3d7022f1b702935461c7d234b052ca06))
- **types:** allow jsx components ([0cb86b3](https://github.com/vuejs/vue-router/commit/0cb86b3865b713201f9db49c7a8d23e9a2876f29)), closes [#3776](https://github.com/vuejs/vue-router/issues/3776)
- **types:** missing NavigationFailureType and isNavigationFailure ([#3777](https://github.com/vuejs/vue-router/issues/3777)) ([9d001dd](https://github.com/vuejs/vue-router/commit/9d001dd0bebdea1e1a8ec2f0c77113b6a2e2b6a3))

## [3.6.2](https://github.com/vuejs/vue-router/compare/v3.6.1...v3.6.2) (2022-08-23)

### Bug Fixes

- **build:** add mjs build ([b4c3940](https://github.com/vuejs/vue-router/commit/b4c39404eff7ae2f657c405d7b0f939ce20cfdec))
- **types:** missing start location ([1356acb](https://github.com/vuejs/vue-router/commit/1356acb983c5eccb00c5c0ec3f406218ae49a8c1))

## [3.6.1](https://github.com/vuejs/vue-router/compare/v3.6.0...v3.6.1) (2022-08-23)

### Bug Fixes

- **build:** ensure install fn before Vue.use ([0126bcb](https://github.com/vuejs/vue-router/commit/0126bcbfb0e3cb824bfce05090ca018faf02ce5e)), closes [#3772](https://github.com/vuejs/vue-router/issues/3772)

# [3.6.0](https://github.com/vuejs/vue-router/compare/v3.5.4...v3.6.0) (2022-08-22)

This release of Vue Router introduces composables from Vue Router 4:

```js
import { useRoute, useRouter, useLink, onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router/composables'
```

Since these composables **require Vue 2.7**, they are only exposed under `vue-router/composables` submodule, so it shouldn't affect you if you stay on Vue 2.6 (Note there are no new features or fixes besides the composables in this release). Refer to [the Vue Router 4 API documentation](https://router.vuejs.org/api/#onbeforerouteleave) for details on the composables.

### Features

- **types:** useLink() ([77bd0e3](https://github.com/vuejs/vue-router/commit/77bd0e317dd5a9aebfca515f0f28f3284c7d8260))
- useLink() ([50332e5](https://github.com/vuejs/vue-router/commit/50332e5e93e6aa1194a9e68a60937a6f9e8bcecd))
- **types:** expose RouterLink and RouterView in d.ts ([cad978a](https://github.com/vuejs/vue-router/commit/cad978a832174aac59cad86fe780f8a64a9754d7))
- add RouterLink and RouterView to esm ([4511f39](https://github.com/vuejs/vue-router/commit/4511f393334247c9702ed378220bf925cdc09add))
- add vue 2.7 types ([cba9650](https://github.com/vuejs/vue-router/commit/cba9650e5cbf958c1db9cd259a2e7bfbc28bddbe))
- onBeforeRouteUpdate onBeforeRouteLeave ([9861c55](https://github.com/vuejs/vue-router/commit/9861c553627f5f34a07ad3ac28e2ed02aab99d47))
- useRoute and useRouter ([ea35594](https://github.com/vuejs/vue-router/commit/ea355943e097914ae55fa54ccb7df929c901e80d))

## [3.5.4](https://github.com/vuejs/vue-router/compare/v3.5.3...v3.5.4) (2022-05-16)

### Bug Fixes

- remove whitespace between mulitple slashes ([86d7f1f](https://github.com/vuejs/vue-router/commit/86d7f1fdaa36432f6564309925690ec20bb2981e)), closes [#3743](https://github.com/vuejs/vue-router/issues/3743)

## [3.5.3](https://github.com/vuejs/vue-router/compare/v3.5.2...v3.5.3) (2021-10-26)

### Bug Fixes

- clean more than two consecutive slashes ([#3652](https://github.com/vuejs/vue-router/issues/3652)) ([3e3a07e](https://github.com/vuejs/vue-router/commit/3e3a07ee6e7defd6cae75bddcede5a28b0092709))
- **scrollBehavior:** trigger scroll behavior if same route with hash ([#3592](https://github.com/vuejs/vue-router/issues/3592)) ([57d8042](https://github.com/vuejs/vue-router/commit/57d8042c8b99f92bfe35493b8ae9bba827864bf0))

### Features

- add constructor hint ([#3626](https://github.com/vuejs/vue-router/issues/3626)) ([28b769b](https://github.com/vuejs/vue-router/commit/28b769b2a07e3bf984c0ec20d6d797291a480e81))

## [3.5.2](https://github.com/vuejs/vue-router/compare/v3.5.1...v3.5.2) (2021-06-21)

### Bug Fixes

- **history:** stricter check of base in HTML5 ([#3556](https://github.com/vuejs/vue-router/issues/3556)) ([11dd184](https://github.com/vuejs/vue-router/commit/11dd184dc6a872c6399977fa4b7c259225ce4834))
- **types:** added missing router.match ([#3554](https://github.com/vuejs/vue-router/issues/3554)) ([394a3b6](https://github.com/vuejs/vue-router/commit/394a3b6cce5e395ae4ccf3e2efb0c115d492978c))

## [3.5.1](https://github.com/vuejs/vue-router/compare/v3.5.0...v3.5.1) (2021-01-26)

### Bug Fixes

- **warn:** only warn if "tag" or "event" is used ([#3458](https://github.com/vuejs/vue-router/issues/3458)) ([b7a31b9](https://github.com/vuejs/vue-router/commit/b7a31b9)), closes [#3457](https://github.com/vuejs/vue-router/issues/3457)

# [3.5.0](https://github.com/vuejs/vue-router/compare/v3.4.9...v3.5.0) (2021-01-25)

### Features

- **link:** exact-path prop ([825328e](https://github.com/vuejs/vue-router/commit/825328e)), closes [#2040](https://github.com/vuejs/vue-router/issues/2040)
- **warn:** warn deprecated addRoutes ([2e41445](https://github.com/vuejs/vue-router/commit/2e41445))
- expose START_LOCATION ([53b68dd](https://github.com/vuejs/vue-router/commit/53b68dd)), closes [#2718](https://github.com/vuejs/vue-router/issues/2718)
- **link:** deprecate v-slot without custom prop ([ceeda4c](https://github.com/vuejs/vue-router/commit/ceeda4c))
- **link:** warn deprecated props ([d2cb951](https://github.com/vuejs/vue-router/commit/d2cb951))
- **router:** add getRoutes ([6bc30aa](https://github.com/vuejs/vue-router/commit/6bc30aa))
- **types:** add types for getRoutes addRoute ([fb9bb60](https://github.com/vuejs/vue-router/commit/fb9bb60))
- addRoute as nested route ([ca80c44](https://github.com/vuejs/vue-router/commit/ca80c44)), closes [#1156](https://github.com/vuejs/vue-router/issues/1156)

## [3.4.9](https://github.com/vuejs/vue-router/compare/v3.4.8...v3.4.9) (2020-11-05)

### Bug Fixes

- **encoding:** decode params ([#3350](https://github.com/vuejs/vue-router/issues/3350)) ([63c749c](https://github.com/vuejs/vue-router/commit/63c749c))

## [3.4.8](https://github.com/vuejs/vue-router/compare/v3.4.7...v3.4.8) (2020-10-26)

### Features

- **scroll:** add behavior support on scrollBehavior ([#3351](https://github.com/vuejs/vue-router/issues/3351)) ([4e0b3e0](https://github.com/vuejs/vue-router/commit/4e0b3e0))

## [3.4.7](https://github.com/vuejs/vue-router/compare/v3.4.6...v3.4.7) (2020-10-16)

### Bug Fixes

- **matcher:** should try catch decode only ([1f32f03](https://github.com/vuejs/vue-router/commit/1f32f03))
- **query:** check existing keys ([4b926e3](https://github.com/vuejs/vue-router/commit/4b926e3)), closes [#3341](https://github.com/vuejs/vue-router/issues/3341)

## [3.4.6](https://github.com/vuejs/vue-router/compare/v3.4.5...v3.4.6) (2020-10-07)

### Bug Fixes

- **encoding:** try catch decodes ([607ce2d](https://github.com/vuejs/vue-router/commit/607ce2d))
- **ssr:** memory leak in poll method ([#2875](https://github.com/vuejs/vue-router/issues/2875)) ([7693eb5](https://github.com/vuejs/vue-router/commit/7693eb5))
- remove duplicated decodeURIComponent ([#3323](https://github.com/vuejs/vue-router/issues/3323)) ([560d11d](https://github.com/vuejs/vue-router/commit/560d11d))

## [3.4.5](https://github.com/vuejs/vue-router/compare/v3.4.4...v3.4.5) (2020-09-26)

### Bug Fixes

- **history:** do not call onReady on initial redirection ([a1a290e](https://github.com/vuejs/vue-router/commit/a1a290e)), closes [#3331](https://github.com/vuejs/vue-router/issues/3331)

## [3.4.4](https://github.com/vuejs/vue-router/compare/v3.4.3...v3.4.4) (2020-09-24)

### Bug Fixes

- **abstract:** call afterHooks with go ([4da7021](https://github.com/vuejs/vue-router/commit/4da7021)), closes [#3250](https://github.com/vuejs/vue-router/issues/3250)
- **history:** mark redundant navigation as pending ([893d86b](https://github.com/vuejs/vue-router/commit/893d86b)), closes [#3133](https://github.com/vuejs/vue-router/issues/3133)
- **types:** add missing NavigationFailure types ([fda7067](https://github.com/vuejs/vue-router/commit/fda7067)), closes [#3293](https://github.com/vuejs/vue-router/issues/3293)
- **types:** fix VueRouter.NavigationFailureType ([ecc8e27](https://github.com/vuejs/vue-router/commit/ecc8e27))

### Features

- **history:** Reset history.current when all apps are destroyed ([#3298](https://github.com/vuejs/vue-router/issues/3298)) ([c69ff7b](https://github.com/vuejs/vue-router/commit/c69ff7b))

## [3.4.3](https://github.com/vuejs/vue-router/compare/v3.4.2...v3.4.3) (2020-08-11)

- Revert 4fbaa9f7880276e661227442ef5923131a589210: "fix: keep repeated params in query/hash relative locations" Closes #3289

## [3.4.2](https://github.com/vuejs/vue-router/compare/v3.4.1...v3.4.2) (2020-08-07)

### Bug Fixes

- **query:** leave object as is ([7b3328d](https://github.com/vuejs/vue-router/commit/7b3328d)), closes [#3282](https://github.com/vuejs/vue-router/issues/3282)
- keep repeated params in query/hash relative locations ([4fbaa9f](https://github.com/vuejs/vue-router/commit/4fbaa9f))

## [3.4.1](https://github.com/vuejs/vue-router/compare/v3.4.0...v3.4.1) (2020-08-06)

### Bug Fixes

- **query:** remove undefined values ([b952573](https://github.com/vuejs/vue-router/commit/b952573)), closes [#3276](https://github.com/vuejs/vue-router/issues/3276)
- **router:** properly check null and undefined in isSameRoute ([d6546d9](https://github.com/vuejs/vue-router/commit/d6546d9))

# [3.4.0](https://github.com/vuejs/vue-router/compare/v3.3.4...v3.4.0) (2020-08-05)

### Bug Fixes

- **query:** cast query values to strings (fix [#2131](https://github.com/vuejs/vue-router/issues/2131)) ([#3232](https://github.com/vuejs/vue-router/issues/3232)) ([f0d9c2d](https://github.com/vuejs/vue-router/commit/f0d9c2d))
- **scroll:** run scrollBehavior on initial load (fix [#3196](https://github.com/vuejs/vue-router/issues/3196)) ([#3199](https://github.com/vuejs/vue-router/issues/3199)) ([84398ae](https://github.com/vuejs/vue-router/commit/84398ae))
- **types:** add missing `options` property type ([#3248](https://github.com/vuejs/vue-router/issues/3248)) ([83920c9](https://github.com/vuejs/vue-router/commit/83920c9))

### Features

- add vetur tags and attributes ([bf1e1bd](https://github.com/vuejs/vue-router/commit/bf1e1bd))
- **errors:** capture errors thrown in redirect callback in onError ([#3251](https://github.com/vuejs/vue-router/issues/3251)) ([40e4df7](https://github.com/vuejs/vue-router/commit/40e4df7)), closes [#3201](https://github.com/vuejs/vue-router/issues/3201) [#3201](https://github.com/vuejs/vue-router/issues/3201) [#3201](https://github.com/vuejs/vue-router/issues/3201)
- **errors:** expose `isNavigationFailure` ([8d92dc0](https://github.com/vuejs/vue-router/commit/8d92dc0))
- **errors:** NavigationDuplicated name for backwards compatibility ([b854a20](https://github.com/vuejs/vue-router/commit/b854a20))

## [3.3.4](https://github.com/vuejs/vue-router/compare/v3.3.3...v3.3.4) (2020-06-13)

### Bug Fixes

- **matcher:** navigate to same as current location ([62598b9](https://github.com/vuejs/vue-router/commit/62598b9)), closes [#3216](https://github.com/vuejs/vue-router/issues/3216)
- **types:** missing children ([c1df447](https://github.com/vuejs/vue-router/commit/c1df447)), closes [#3230](https://github.com/vuejs/vue-router/issues/3230)

## [3.3.3](https://github.com/vuejs/vue-router/compare/v3.3.2...v3.3.3) (2020-06-12)

### Bug Fixes

- **history:** initial redirect call onReady's onSuccess ([4d484bf](https://github.com/vuejs/vue-router/commit/4d484bf)), closes [#3225](https://github.com/vuejs/vue-router/issues/3225)
- update ja docs ([#3214](https://github.com/vuejs/vue-router/issues/3214)) ([c05f741](https://github.com/vuejs/vue-router/commit/c05f741))

### Features

- better wording for navigation redirected failure ([1f3aea6](https://github.com/vuejs/vue-router/commit/1f3aea6))
- **types:** RouterConfig for multiple components ([#3217](https://github.com/vuejs/vue-router/issues/3217)) ([#3218](https://github.com/vuejs/vue-router/issues/3218)) ([dab86c5](https://github.com/vuejs/vue-router/commit/dab86c5))

## [3.3.2](https://github.com/vuejs/vue-router/compare/v3.3.1...v3.3.2) (2020-05-29)

### Bug Fixes

- **errors:** NavigationCanceled with async components ([#3211](https://github.com/vuejs/vue-router/issues/3211)) ([be39ca3](https://github.com/vuejs/vue-router/commit/be39ca3))
- remove error.stack modification ([#3212](https://github.com/vuejs/vue-router/issues/3212)) ([a0075ed](https://github.com/vuejs/vue-router/commit/a0075ed))

## [3.3.1](https://github.com/vuejs/vue-router/compare/v3.3.0...v3.3.1) (2020-05-27)

### Bug Fixes

- **errors:** avoid unnecessary log of errors ([2c77247](https://github.com/vuejs/vue-router/commit/2c77247))

# [3.3.0](https://github.com/vuejs/vue-router/compare/v3.2.0...v3.3.0) (2020-05-27)

### Features

- **errors:** create router errors ([#3047](https://github.com/vuejs/vue-router/issues/3047)) ([4c727f9](https://github.com/vuejs/vue-router/commit/4c727f9))
- **history:** Remove event listeners when all apps are destroyed. ([#3172](https://github.com/vuejs/vue-router/issues/3172)) ([4c81be8](https://github.com/vuejs/vue-router/commit/4c81be8)), closes [#3152](https://github.com/vuejs/vue-router/issues/3152) [#2341](https://github.com/vuejs/vue-router/issues/2341)
- **url:** call afterEach hooks after url is ensured ([#2292](https://github.com/vuejs/vue-router/issues/2292)) ([1575a18](https://github.com/vuejs/vue-router/commit/1575a18)), closes [#2079](https://github.com/vuejs/vue-router/issues/2079)

# [3.2.0](https://github.com/vuejs/vue-router/compare/v3.1.6...v3.2.0) (2020-05-19)

### Bug Fixes

- **html5:** make base case insensitive ([04a2143](https://github.com/vuejs/vue-router/commit/04a2143)), closes [#2154](https://github.com/vuejs/vue-router/issues/2154)
- check for pushState being a function ([bc41f67](https://github.com/vuejs/vue-router/commit/bc41f67)), closes [#3154](https://github.com/vuejs/vue-router/issues/3154)

### Features

- **link:** add aria-current to active links (close [#2116](https://github.com/vuejs/vue-router/issues/2116)) ([#3073](https://github.com/vuejs/vue-router/issues/3073)) ([6ec0ee5](https://github.com/vuejs/vue-router/commit/6ec0ee5))
- **scroll:** use manual scrollRestoration with scrollBehavior ([#1814](https://github.com/vuejs/vue-router/issues/1814)) ([1261363](https://github.com/vuejs/vue-router/commit/1261363))
- **types:** NavigationGuardNext ([#2497](https://github.com/vuejs/vue-router/issues/2497)) ([d18c497](https://github.com/vuejs/vue-router/commit/d18c497))

## [3.1.6](https://github.com/vuejs/vue-router/compare/v3.1.5...v3.1.6) (2020-02-26)

### Bug Fixes

- preserve history state when reloading ([a4ec3e2](https://github.com/vuejs/vue-router/commit/a4ec3e2))
- **ts:** add null to Route.name ([#3117](https://github.com/vuejs/vue-router/issues/3117)) ([8f831f2](https://github.com/vuejs/vue-router/commit/8f831f2))
- correctly calculate `path` when `pathMatch` is empty string ([#3111](https://github.com/vuejs/vue-router/issues/3111)) ([38e6ccd](https://github.com/vuejs/vue-router/commit/38e6ccd)), closes [#3106](https://github.com/vuejs/vue-router/issues/3106)

## [3.1.5](https://github.com/vuejs/vue-router/compare/v3.1.4...v3.1.5) (2020-01-15)

### Bug Fixes

- **view:** add passing props to inactive component ([#2773](https://github.com/vuejs/vue-router/issues/2773)) ([0fb1343](https://github.com/vuejs/vue-router/commit/0fb1343)), closes [#2301](https://github.com/vuejs/vue-router/issues/2301)
- **view:** fix deeply nested keep-alive router-views displaying ([#2930](https://github.com/vuejs/vue-router/issues/2930)) ([0c2b1aa](https://github.com/vuejs/vue-router/commit/0c2b1aa)), closes [#2923](https://github.com/vuejs/vue-router/issues/2923)

## [3.1.4](https://github.com/vuejs/vue-router/compare/v3.1.3...v3.1.4) (2020-01-14)

### Bug Fixes

- suppress warning if `pathMatch` is empty ([#3081](https://github.com/vuejs/vue-router/issues/3081)) ([ddc6bc7](https://github.com/vuejs/vue-router/commit/ddc6bc7)), closes [#3072](https://github.com/vuejs/vue-router/issues/3072)
- **link:** correctly warn wrong v-slot usage ([a150291](https://github.com/vuejs/vue-router/commit/a150291)), closes [#3091](https://github.com/vuejs/vue-router/issues/3091)
- **location:** add a copy for params with named locations ([#2802](https://github.com/vuejs/vue-router/issues/2802)) ([2b39f5a](https://github.com/vuejs/vue-router/commit/2b39f5a)), closes [#2800](https://github.com/vuejs/vue-router/issues/2800) [#2938](https://github.com/vuejs/vue-router/issues/2938) [#2938](https://github.com/vuejs/vue-router/issues/2938)

### Features

- **history:** preserve existing history.state ([c0d3376](https://github.com/vuejs/vue-router/commit/c0d3376)), closes [#3006](https://github.com/vuejs/vue-router/issues/3006)

## [3.1.3](https://github.com/vuejs/vue-router/compare/v3.1.2...v3.1.3) (2019-08-30)

### Bug Fixes

- **link:** merge event listeners when provided in an anchor ([e0d4dc4](https://github.com/vuejs/vue-router/commit/e0d4dc4)), closes [#2890](https://github.com/vuejs/vue-router/issues/2890)

### Features

- **errors:** add stack trace to NavigationDuplicated ([5ef5d73](https://github.com/vuejs/vue-router/commit/5ef5d73)), closes [#2881](https://github.com/vuejs/vue-router/issues/2881)
- warn about root paths without a leading slash ([#2591](https://github.com/vuejs/vue-router/issues/2591)) ([7d7e048](https://github.com/vuejs/vue-router/commit/7d7e048)), closes [#2550](https://github.com/vuejs/vue-router/issues/2550) [#2550](https://github.com/vuejs/vue-router/issues/2550)

## [3.1.2](https://github.com/vuejs/vue-router/compare/v3.1.1...v3.1.2) (2019-08-08)

### Bug Fixes

- **types:** prioritize promise based push/replace ([1243e8b](https://github.com/vuejs/vue-router/commit/1243e8b))

### Reverts

- "fix(hash): correctly place query if placed before hash ([#2851](https://github.com/vuejs/vue-router/issues/2851))" ([9b30e4c](https://github.com/vuejs/vue-router/commit/9b30e4c)), closes [#2876](https://github.com/vuejs/vue-router/issues/2876). See more information at https://github.com/vuejs/vue-router/issues/2125#issuecomment-519521424

## [3.1.1](https://github.com/vuejs/vue-router/compare/v3.1.0...v3.1.1) (2019-08-06)

### Bug Fixes

- **link:** silence back navigations errors ([59b6da3](https://github.com/vuejs/vue-router/commit/59b6da3))

# [3.1.0](https://github.com/vuejs/vue-router/compare/v3.0.7...v3.1.0) (2019-08-06)

### Bug Fixes

- **abstract history:** allow router.back in abstract mode when 2 consecutive same routes appear in history stack ([#2771](https://github.com/vuejs/vue-router/issues/2771)) ([8910979](https://github.com/vuejs/vue-router/commit/8910979)), closes [#2607](https://github.com/vuejs/vue-router/issues/2607)
- **hash:** correctly place query if placed before hash ([#2851](https://github.com/vuejs/vue-router/issues/2851)) ([b7715dc](https://github.com/vuejs/vue-router/commit/b7715dc)), closes [#2125](https://github.com/vuejs/vue-router/issues/2125) [#2262](https://github.com/vuejs/vue-router/issues/2262)
- **link:** Fix active links when parent link redirects to child ([#2772](https://github.com/vuejs/vue-router/issues/2772)) ([64785a9](https://github.com/vuejs/vue-router/commit/64785a9)), closes [#2724](https://github.com/vuejs/vue-router/issues/2724)
- adapt error to work on IE9 ([527d6d5](https://github.com/vuejs/vue-router/commit/527d6d5))

### Features

- **alias:** warn against redundant aliases ([04a02c0](https://github.com/vuejs/vue-router/commit/04a02c0)), closes [#2461](https://github.com/vuejs/vue-router/issues/2461) [#2462](https://github.com/vuejs/vue-router/issues/2462)
- **scroll:** handle id selectors starting with a number ([799ceca](https://github.com/vuejs/vue-router/commit/799ceca)), closes [#2163](https://github.com/vuejs/vue-router/issues/2163)
- return a promise with push and replace ([#2862](https://github.com/vuejs/vue-router/issues/2862)) ([d907a13](https://github.com/vuejs/vue-router/commit/d907a13)), closes [#1769](https://github.com/vuejs/vue-router/issues/1769) [#1769](https://github.com/vuejs/vue-router/issues/1769)
- scoped slot for link ([e289dde](https://github.com/vuejs/vue-router/commit/e289dde))
- warn the user for invalid uses of v-slot with Link ([44c63a9](https://github.com/vuejs/vue-router/commit/44c63a9))

## [3.0.7](https://github.com/vuejs/vue-router/compare/v3.0.6...v3.0.7) (2019-07-03)

### Bug Fixes

- apps loaded from Windows file shares not mapped to network drives ([#2774](https://github.com/vuejs/vue-router/issues/2774)) ([c2c78a3](https://github.com/vuejs/vue-router/commit/c2c78a3))
- make callback of next in beforeRouterEnter more consistent ([#2738](https://github.com/vuejs/vue-router/issues/2738)) ([8ac478f](https://github.com/vuejs/vue-router/commit/8ac478f)), closes [#2761](https://github.com/vuejs/vue-router/issues/2761) [#2728](https://github.com/vuejs/vue-router/issues/2728)

## [3.0.6](https://github.com/vuejs/vue-router/compare/v3.0.5...v3.0.6) (2019-04-17)

### Bug Fixes

- revert [#2713](https://github.com/vuejs/vue-router/issues/2713) ([#2723](https://github.com/vuejs/vue-router/issues/2723)) ([ec6eab7](https://github.com/vuejs/vue-router/commit/ec6eab7)), closes [#2719](https://github.com/vuejs/vue-router/issues/2719)

## [3.0.5](https://github.com/vuejs/vue-router/compare/v3.0.4...v3.0.5) (2019-04-15)

### Bug Fixes

- push before creating Vue instance ([#2713](https://github.com/vuejs/vue-router/issues/2713)) ([6974a6f](https://github.com/vuejs/vue-router/commit/6974a6f)), closes [#2712](https://github.com/vuejs/vue-router/issues/2712)
- **router-view:** add condition to see whether the tree is inactive (fix [#2552](https://github.com/vuejs/vue-router/issues/2552)) ([#2592](https://github.com/vuejs/vue-router/issues/2592)) ([e6d8fd2](https://github.com/vuejs/vue-router/commit/e6d8fd2))
- **router-view:** register instance in init hook ([c3abdf6](https://github.com/vuejs/vue-router/commit/c3abdf6)), closes [#2561](https://github.com/vuejs/vue-router/issues/2561) [#2689](https://github.com/vuejs/vue-router/issues/2689) [#2561](https://github.com/vuejs/vue-router/issues/2561) [#2561](https://github.com/vuejs/vue-router/issues/2561)

## [3.0.4](https://github.com/vuejs/vue-router/compare/v3.0.3...v3.0.4) (2019-04-12)

### Bug Fixes

- prevent memory leaks by removing app references ([#2706](https://github.com/vuejs/vue-router/issues/2706)) ([8056105](https://github.com/vuejs/vue-router/commit/8056105)), closes [#2639](https://github.com/vuejs/vue-router/issues/2639)
- **hash:** prevent double decoding ([#2711](https://github.com/vuejs/vue-router/issues/2711)) ([a775fb1](https://github.com/vuejs/vue-router/commit/a775fb1)), closes [#2708](https://github.com/vuejs/vue-router/issues/2708)

### Features

- **esm build:** build ES modules for browser ([#2705](https://github.com/vuejs/vue-router/issues/2705)) ([627027f](https://github.com/vuejs/vue-router/commit/627027f))

## [3.0.3](https://github.com/vuejs/vue-router/compare/v3.0.2...v3.0.3) (2019-04-08)

### Bug Fixes

- removes warning resolving asterisk routes ([e224637](https://github.com/vuejs/vue-router/commit/e224637)), closes [#2505](https://github.com/vuejs/vue-router/issues/2505) [#2505](https://github.com/vuejs/vue-router/issues/2505)
- **normalizeLocation:** create a copy with named locations ([#2286](https://github.com/vuejs/vue-router/issues/2286)) ([53cce99](https://github.com/vuejs/vue-router/commit/53cce99)), closes [#2121](https://github.com/vuejs/vue-router/issues/2121)
- **resolve:** use current location if not provided ([#2390](https://github.com/vuejs/vue-router/issues/2390)) ([7ff4de4](https://github.com/vuejs/vue-router/commit/7ff4de4)), closes [#2385](https://github.com/vuejs/vue-router/issues/2385)
- **types:** allow null/undefined in query params ([ca30a75](https://github.com/vuejs/vue-router/commit/ca30a75)), closes [#2605](https://github.com/vuejs/vue-router/issues/2605)

## [3.0.2](https://github.com/vuejs/vue-router/compare/v3.0.1...v3.0.2) (2018-11-23)

### Bug Fixes

- **errors:** throws with invalid route objects ([#1893](https://github.com/vuejs/vue-router/issues/1893)) ([c837666](https://github.com/vuejs/vue-router/commit/c837666))
- fix the test in async.spec.js ([#1953](https://github.com/vuejs/vue-router/issues/1953)) ([4e9e66b](https://github.com/vuejs/vue-router/commit/4e9e66b))
- initial url path for non ascii urls ([#2375](https://github.com/vuejs/vue-router/issues/2375)) ([c3b0a33](https://github.com/vuejs/vue-router/commit/c3b0a33))
- only setupScroll when support pushState due to possible fallback: false ([#1835](https://github.com/vuejs/vue-router/issues/1835)) ([fac60f6](https://github.com/vuejs/vue-router/commit/fac60f6)), closes [#1834](https://github.com/vuejs/vue-router/issues/1834)
- workaround replaceState bug in Safari ([#2295](https://github.com/vuejs/vue-router/issues/2295)) ([3c7d8ab](https://github.com/vuejs/vue-router/commit/3c7d8ab)), closes [#2195](https://github.com/vuejs/vue-router/issues/2195)
- **hash:** support unicode in initial route ([8369c6b](https://github.com/vuejs/vue-router/commit/8369c6b))
- **history-mode:** correcting indentation in web.config example ([#1948](https://github.com/vuejs/vue-router/issues/1948)) ([4b071f9](https://github.com/vuejs/vue-router/commit/4b071f9))
- **match:** use pathMatch for the param of \* routes ([#1995](https://github.com/vuejs/vue-router/issues/1995)) ([ca1fccd](https://github.com/vuejs/vue-router/commit/ca1fccd)), closes [#1994](https://github.com/vuejs/vue-router/issues/1994)

### Features

- call scrollBehavior with app context ([#1804](https://github.com/vuejs/vue-router/issues/1804)) ([c93a734](https://github.com/vuejs/vue-router/commit/c93a734))

## [3.0.1](https://github.com/vuejs/vue-router/compare/v3.0.0...v3.0.1) (2017-10-13)

### Bug Fixes

- fix props-passing regression ([02ff792](https://github.com/vuejs/vue-router/commit/02ff792)), closes [#1800](https://github.com/vuejs/vue-router/issues/1800)

## [3.0.0](https://github.com/vuejs/vue-router/compare/v2.8.0...v3.0.0) (2017-10-11)

### Features

- **typings:** adapt to the new Vue typings ([#1685](https://github.com/vuejs/vue-router/issues/1685)) ([8855e36](https://github.com/vuejs/vue-router/commit/8855e36))

### BREAKING CHANGES

- **typings:** It is no longer compatible with the old Vue typings

## [2.8.0](https://github.com/vuejs/vue-router/compare/v2.7.0...v2.8.0) (2017-10-11)

### Bug Fixes

- allow insllation on extended Vue copies ([f62c5d6](https://github.com/vuejs/vue-router/commit/f62c5d6))
- avoid first popstate event with async guard together (fix [#1508](https://github.com/vuejs/vue-router/issues/1508)) ([#1661](https://github.com/vuejs/vue-router/issues/1661)) ([3cbc0f3](https://github.com/vuejs/vue-router/commit/3cbc0f3))
- deep clone query when creating routes ([effb114](https://github.com/vuejs/vue-router/commit/effb114)), closes [#1690](https://github.com/vuejs/vue-router/issues/1690)
- fix scroll when going back to initial route ([#1586](https://github.com/vuejs/vue-router/issues/1586)) ([c166822](https://github.com/vuejs/vue-router/commit/c166822))
- handle null values when comparing objects ([#1568](https://github.com/vuejs/vue-router/issues/1568)) ([4e95bd8](https://github.com/vuejs/vue-router/commit/4e95bd8)), closes [#1566](https://github.com/vuejs/vue-router/issues/1566)
- resolve native ES modules ([8a28426](https://github.com/vuejs/vue-router/commit/8a28426))
- send props not defined on the route component in \$attrs. Fixes [#1695](https://github.com/vuejs/vue-router/issues/1695). ([#1702](https://github.com/vuejs/vue-router/issues/1702)) ([a722b6a](https://github.com/vuejs/vue-router/commit/a722b6a))

### Features

- enhance hashHistory to support scrollBehavior ([#1662](https://github.com/vuejs/vue-router/issues/1662)) ([1422eb5](https://github.com/vuejs/vue-router/commit/1422eb5))
- scrollBehavior accept returning a promise ([#1758](https://github.com/vuejs/vue-router/issues/1758)) ([ce13b55](https://github.com/vuejs/vue-router/commit/ce13b55))

# [2.7.0](https://github.com/vuejs/vue-router/compare/v2.6.0...v2.7.0) (2017-06-29)

### Features

- auto resolve ES module default when resolving async components ([d539788](https://github.com/vuejs/vue-router/commit/d539788))


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2013-present 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.


================================================
FILE: README.md
================================================
# vue-router [![Build Status](https://img.shields.io/circleci/project/github/vuejs/vue-router/dev.svg)](https://circleci.com/gh/vuejs/vue-router)

> This is vue-router 3.0 which works only with Vue 2.0. and both have reached end of life.
>
> - For the 1.x router see the [1.0 branch](https://github.com/vuejs/vue-router/tree/1.0).
> - For Vue Router 4 (for Vue 3) see [vuejs/router](https://github.com/vuejs/router).

<h2 align="center">Supporting Vue Router</h2>

Vue Router is part of the Vue Ecosystem and is an MIT-licensed open source project with its ongoing development made possible entirely by the support of Sponsors. If you would like to become a sponsor, please consider:

- [Become a Sponsor on GitHub](https://github.com/sponsors/posva)
- [One-time donation via PayPal](https://paypal.me/posva)

<!--sponsors start-->

<h4 align="center">Gold Sponsors</h4>
<p align="center">
    <a href="https://vuejobs.com/?utm_source=vuerouter&utm_campaign=sponsor" target="_blank" rel="noopener noreferrer">
    <picture>
      <source srcset="https://posva-sponsors.pages.dev/logos/vuejobs.svg" media="(prefers-color-scheme: dark)" height="72px" alt="VueJobs" />
      <img src="https://posva-sponsors.pages.dev/logos/vuejobs.svg" height="72px" alt="VueJobs" />
    </picture>
  </a>
</p>

<h4 align="center">Silver Sponsors</h4>
<p align="center">
    <a href="https://www.vuemastery.com/" target="_blank" rel="noopener noreferrer">
    <picture>
      <source srcset="https://posva-sponsors.pages.dev/logos/vuemastery-dark.png" media="(prefers-color-scheme: dark)" height="42px" alt="VueMastery" />
      <img src="https://posva-sponsors.pages.dev/logos/vuemastery-light.svg" height="42px" alt="VueMastery" />
    </picture>
  </a>
    <a href="https://www.prefect.io/" target="_blank" rel="noopener noreferrer">
    <picture>
      <source srcset="https://posva-sponsors.pages.dev/logos/prefectlogo-dark.svg" media="(prefers-color-scheme: dark)" height="42px" alt="Prefect" />
      <img src="https://posva-sponsors.pages.dev/logos/prefectlogo-light.svg" height="42px" alt="Prefect" />
    </picture>
  </a>
</p>

<h4 align="center">Bronze Sponsors</h4>
<p align="center">
    <a href="https://stormier.ninja" target="_blank" rel="noopener noreferrer">
    <picture>
      <source srcset="https://avatars.githubusercontent.com/u/2486424?u=7b0c73ae5d090ce53bf59473094e9606fe082c59&v=4" media="(prefers-color-scheme: dark)" height="26px" alt="Stanislas Ormières" />
      <img src="https://avatars.githubusercontent.com/u/2486424?u=7b0c73ae5d090ce53bf59473094e9606fe082c59&v=4" height="26px" alt="Stanislas Ormières" />
    </picture>
  </a>
    <a href="www.vuejs.de" target="_blank" rel="noopener noreferrer">
    <picture>
      <source srcset="https://avatars.githubusercontent.com/u/4183726?u=6b50a8ea16de29d2982f43c5640b1db9299ebcd1&v=4" media="(prefers-color-scheme: dark)" height="26px" alt="Antony Konstantinidis" />
      <img src="https://avatars.githubusercontent.com/u/4183726?u=6b50a8ea16de29d2982f43c5640b1db9299ebcd1&v=4" height="26px" alt="Antony Konstantinidis" />
    </picture>
  </a>
    <a href="https://storyblok.com" target="_blank" rel="noopener noreferrer">
    <picture>
      <source srcset="https://posva-sponsors.pages.dev/logos/storyblok.png" media="(prefers-color-scheme: dark)" height="26px" alt="Storyblok" />
      <img src="https://posva-sponsors.pages.dev/logos/storyblok.png" height="26px" alt="Storyblok" />
    </picture>
  </a>
    <a href="https://nuxtjs.org" target="_blank" rel="noopener noreferrer">
    <picture>
      <source srcset="https://posva-sponsors.pages.dev/logos/nuxt-dark.svg" media="(prefers-color-scheme: dark)" height="26px" alt="NuxtJS" />
      <img src="https://posva-sponsors.pages.dev/logos/nuxt-light.svg" height="26px" alt="NuxtJS" />
    </picture>
  </a>
</p>

<!--sponsors end-->

---

Get started with the [documentation](http://v3.router.vuejs.org), or play with the [examples](https://github.com/vuejs/vue-router/tree/dev/examples) (see how to run them below).

### Development Setup

```bash
# install deps
yarn

# build dist files
yarn build

# serve examples at localhost:8080
yarn dev

# lint & run all tests
yarn test

# serve docs at localhost:8080
yarn docs
```

## Releasing

- `yarn run release`
  - Ensure tests are passing `yarn run test`
  - Build dist files `VERSION=<the_version> yarn run build`
  - Build changelog `yarn run changelog`
  - Commit dist files `git add dist CHANGELOG.md && git commit -m "[build $VERSION]"`
  - Publish a new version `npm version $VERSION --message "[release] $VERSION"
  - Push tags `git push origin refs/tags/v$VERSION && git push`
  - Publish to npm `npm publish`

## Questions

For questions and support please use the [Discord chat server](https://chat.vuejs.org) or [the official forum](http://forum.vuejs.org). The issue list of this repo is **exclusively** for bug reports and feature requests.

## Issues

Please make sure to read the [Issue Reporting Checklist](https://github.com/vuejs/vue/blob/dev/.github/CONTRIBUTING.md#issue-reporting-guidelines) before opening an issue. Issues not conforming to the guidelines may be closed immediately.

## Contribution

Please make sure to read the [Contributing Guide](https://github.com/vuejs/vue/blob/dev/.github/CONTRIBUTING.md) before making a pull request.

## Changelog

Details changes for each release are documented in the [`CHANGELOG.md file`](https://github.com/vuejs/vue-router/blob/dev/CHANGELOG.md).

## Stay In Touch

- For latest releases and announcements, follow on Twitter: [@vuejs](https://twitter.com/vuejs)

## License

[MIT](http://opensource.org/licenses/MIT)

Copyright (c) 2013-present Evan You

## Special Thanks

<a href="https://www.browserstack.com">
  <img src="/assets/browserstack-logo-600x315.png" height="80" title="BrowserStack Logo" alt="BrowserStack Logo" />
</a>

Special thanks to [BrowserStack](https://www.browserstack.com) for letting the maintainers use their service to debug browser specific issues.


================================================
FILE: build/build.js
================================================
const fs = require('fs')
const path = require('path')
const zlib = require('zlib')
const terser = require('terser')
const rollup = require('rollup')
const configs = require('./configs')

if (!fs.existsSync('dist')) {
  fs.mkdirSync('dist')
}

build(configs)

function build (builds) {
  let built = 0
  const total = builds.length
  const next = () => {
    buildEntry(builds[built])
      .then(() => {
        built++
        if (built < total) {
          next()
        }
      })
      .catch(logError)
  }

  next()
}

function buildEntry ({ input, output }) {
  const { file, banner } = output
  const isProd = /min\.js$/.test(file)
  return rollup
    .rollup(input)
    .then(bundle => bundle.generate(output))
    .then(bundle => {
      // console.log(bundle)
      const code = bundle.output[0].code
      if (isProd) {
        const minified =
          (banner ? banner + '\n' : '') +
          terser.minify(code, {
            toplevel: true,
            output: {
              ascii_only: true
            },
            compress: {
              pure_funcs: ['makeMap']
            }
          }).code
        return write(file, minified, true)
      } else {
        return write(file, code)
      }
    })
}

function write (dest, code, zip) {
  return new Promise((resolve, reject) => {
    function report (extra) {
      console.log(
        blue(path.relative(process.cwd(), dest)) +
          ' ' +
          getSize(code) +
          (extra || '')
      )
      resolve()
    }

    fs.writeFile(dest, code, err => {
      if (err) return reject(err)
      if (zip) {
        zlib.gzip(code, (err, zipped) => {
          if (err) return reject(err)
          report(' (gzipped: ' + getSize(zipped) + ')')
        })
      } else {
        report()
      }
    })
  })
}

function getSize (code) {
  return (code.length / 1024).toFixed(2) + 'kb'
}

function logError (e) {
  console.log(e)
}

function blue (str) {
  return '\x1b[1m\x1b[34m' + str + '\x1b[39m\x1b[22m'
}


================================================
FILE: build/configs.js
================================================
const path = require('path')
const buble = require('rollup-plugin-buble')
const flow = require('rollup-plugin-flow-no-whitespace')
const cjs = require('@rollup/plugin-commonjs')
const node = require('@rollup/plugin-node-resolve').nodeResolve
const replace = require('rollup-plugin-replace')
const version = process.env.VERSION || require('../package.json').version
const banner = `/*!
  * vue-router v${version}
  * (c) ${new Date().getFullYear()} Evan You
  * @license MIT
  */`

const resolve = _path => path.resolve(__dirname, '../', _path)

module.exports = [
  // browser dev
  {
    file: resolve('dist/vue-router.js'),
    format: 'umd',
    env: 'development'
  },
  {
    file: resolve('dist/vue-router.min.js'),
    format: 'umd',
    env: 'production'
  },
  {
    file: resolve('dist/vue-router.common.js'),
    format: 'cjs'
  },
  {
    input: resolve('src/entries/esm.js'),
    file: resolve('dist/vue-router.esm.js'),
    format: 'es'
  },
  {
    input: resolve('src/entries/esm.js'),
    file: resolve('dist/vue-router.mjs'),
    format: 'es'
  },
  {
    input: resolve('src/entries/esm.js'),
    file: resolve('dist/vue-router.esm.browser.js'),
    format: 'es',
    env: 'development',
    transpile: false
  },
  {
    input: resolve('src/entries/esm.js'),
    file: resolve('dist/vue-router.esm.browser.min.js'),
    format: 'es',
    env: 'production',
    transpile: false
  },
  {
    input: resolve('src/composables/index.js'),
    file: resolve('./composables.mjs'),
    format: 'es'
  },
  {
    input: resolve('src/composables/index.js'),
    file: resolve('./composables.js'),
    format: 'cjs'
  }
].map(genConfig)

function genConfig (opts) {
  const config = {
    input: {
      input: opts.input || resolve('src/index.js'),
      plugins: [
        flow(),
        node(),
        cjs(),
        replace({
          __VERSION__: version
        })
      ],
      external: ['vue']
    },
    output: {
      file: opts.file,
      format: opts.format,
      banner,
      name: 'VueRouter'
    }
  }

  if (opts.env) {
    config.input.plugins.unshift(
      replace({
        'process.env.NODE_ENV': JSON.stringify(opts.env)
      })
    )
  }

  if (opts.transpile !== false) {
    config.input.plugins.push(buble())
  }

  return config
}


================================================
FILE: build/rollup.dev.config.js
================================================
const { input, output } = require('./configs')[0]

module.exports = Object.assign({}, input, { output })


================================================
FILE: composables.d.ts
================================================
export * from './types/composables'


================================================
FILE: composables.js
================================================
/*!
  * vue-router v3.6.5
  * (c) 2022 Evan You
  * @license MIT
  */
'use strict'

Object.defineProperty(exports, '__esModule', { value: true })

var vue = require('vue')

// dev only warn if no current instance

function throwNoCurrentInstance (method) {
  if (!vue.getCurrentInstance()) {
    throw new Error(
      ('[vue-router]: Missing current instance. ' + method + '() must be called inside <script setup> or setup().')
    )
  }
}

function useRouter () {
  if (process.env.NODE_ENV !== 'production') {
    throwNoCurrentInstance('useRouter')
  }

  return vue.getCurrentInstance().proxy.$root.$router
}

function useRoute () {
  if (process.env.NODE_ENV !== 'production') {
    throwNoCurrentInstance('useRoute')
  }

  var root = vue.getCurrentInstance().proxy.$root
  if (!root._$route) {
    var route = vue.effectScope(true).run(function () { return vue.shallowReactive(Object.assign({}, root.$router.currentRoute)) }
    )
    root._$route = route

    root.$router.afterEach(function (to) {
      Object.assign(route, to)
    })
  }

  return root._$route
}

function onBeforeRouteUpdate (guard) {
  if (process.env.NODE_ENV !== 'production') {
    throwNoCurrentInstance('onBeforeRouteUpdate')
  }

  return useFilteredGuard(guard, isUpdateNavigation)
}
function isUpdateNavigation (to, from, depth) {
  var toMatched = to.matched
  var fromMatched = from.matched
  return (
    toMatched.length >= depth &&
    toMatched
      .slice(0, depth + 1)
      .every(function (record, i) { return record === fromMatched[i] })
  )
}

function isLeaveNavigation (to, from, depth) {
  var toMatched = to.matched
  var fromMatched = from.matched
  return toMatched.length < depth || toMatched[depth] !== fromMatched[depth]
}

function onBeforeRouteLeave (guard) {
  if (process.env.NODE_ENV !== 'production') {
    throwNoCurrentInstance('onBeforeRouteLeave')
  }

  return useFilteredGuard(guard, isLeaveNavigation)
}

var noop = function () {}
function useFilteredGuard (guard, fn) {
  var instance = vue.getCurrentInstance()
  var router = useRouter()

  var target = instance.proxy
  // find the nearest RouterView to know the depth
  while (
    target &&
    target.$vnode &&
    target.$vnode.data &&
    target.$vnode.data.routerViewDepth == null
  ) {
    target = target.$parent
  }

  var depth =
    target && target.$vnode && target.$vnode.data
      ? target.$vnode.data.routerViewDepth
      : null

  if (depth != null) {
    var removeGuard = router.beforeEach(function (to, from, next) {
      return fn(to, from, depth) ? guard(to, from, next) : next()
    })

    vue.onUnmounted(removeGuard)
    return removeGuard
  }

  return noop
}

/*  */

function guardEvent (e) {
  // don't redirect with control keys
  if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) { return }
  // don't redirect when preventDefault called
  if (e.defaultPrevented) { return }
  // don't redirect on right click
  if (e.button !== undefined && e.button !== 0) { return }
  // don't redirect if `target="_blank"`
  if (e.currentTarget && e.currentTarget.getAttribute) {
    var target = e.currentTarget.getAttribute('target')
    if (/\b_blank\b/i.test(target)) { return }
  }
  // this may be a Weex event which doesn't have this method
  if (e.preventDefault) {
    e.preventDefault()
  }
  return true
}

function includesParams (outer, inner) {
  var loop = function (key) {
    var innerValue = inner[key]
    var outerValue = outer[key]
    if (typeof innerValue === 'string') {
      if (innerValue !== outerValue) { return { v: false } }
    } else {
      if (
        !Array.isArray(outerValue) ||
        outerValue.length !== innerValue.length ||
        innerValue.some(function (value, i) { return value !== outerValue[i] })
      ) {
        return { v: false }
      }
    }
  }

  for (var key in inner) {
    var returned = loop(key)

    if (returned) return returned.v
  }

  return true
}

// helpers from vue router 4

function isSameRouteLocationParamsValue (a, b) {
  return Array.isArray(a)
    ? isEquivalentArray(a, b)
    : Array.isArray(b)
      ? isEquivalentArray(b, a)
      : a === b
}

function isEquivalentArray (a, b) {
  return Array.isArray(b)
    ? a.length === b.length && a.every(function (value, i) { return value === b[i] })
    : a.length === 1 && a[0] === b
}

function isSameRouteLocationParams (a, b) {
  if (Object.keys(a).length !== Object.keys(b).length) { return false }

  for (var key in a) {
    if (!isSameRouteLocationParamsValue(a[key], b[key])) { return false }
  }

  return true
}

function useLink (props) {
  if (process.env.NODE_ENV !== 'production') {
    throwNoCurrentInstance('useLink')
  }

  var router = useRouter()
  var currentRoute = useRoute()

  var resolvedRoute = vue.computed(function () { return router.resolve(vue.unref(props.to), currentRoute) })

  var activeRecordIndex = vue.computed(function () {
    var route = resolvedRoute.value.route
    var matched = route.matched
    var length = matched.length
    var routeMatched = matched[length - 1]
    var currentMatched = currentRoute.matched
    if (!routeMatched || !currentMatched.length) { return -1 }
    var index = currentMatched.indexOf(routeMatched)
    if (index > -1) { return index }
    // possible parent record
    var parentRecord = currentMatched[currentMatched.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
        parentRecord && parentRecord === routeMatched.parent
    )
  })

  var isActive = vue.computed(
    function () {
      return activeRecordIndex.value > -1 &&
      includesParams(currentRoute.params, resolvedRoute.value.route.params)
    }
  )
  var isExactActive = vue.computed(
    function () {
      return activeRecordIndex.value > -1 &&
      activeRecordIndex.value === currentRoute.matched.length - 1 &&
      isSameRouteLocationParams(currentRoute.params, resolvedRoute.value.route.params)
    }
  )

  var navigate = function (e) {
    var href = resolvedRoute.value.route
    if (guardEvent(e)) {
      return props.replace
        ? router.replace(href)
        : router.push(href)
    }
    return Promise.resolve()
  }

  return {
    href: vue.computed(function () { return resolvedRoute.value.href }),
    route: vue.computed(function () { return resolvedRoute.value.route }),
    isExactActive: isExactActive,
    isActive: isActive,
    navigate: navigate
  }
}

exports.isSameRouteLocationParams = isSameRouteLocationParams
exports.onBeforeRouteLeave = onBeforeRouteLeave
exports.onBeforeRouteUpdate = onBeforeRouteUpdate
exports.useLink = useLink
exports.useRoute = useRoute
exports.useRouter = useRouter


================================================
FILE: composables.mjs
================================================
/*!
  * vue-router v3.6.5
  * (c) 2022 Evan You
  * @license MIT
  */
import { getCurrentInstance, effectScope, shallowReactive, onUnmounted, computed, unref } from 'vue';

// dev only warn if no current instance

function throwNoCurrentInstance (method) {
  if (!getCurrentInstance()) {
    throw new Error(
      ("[vue-router]: Missing current instance. " + method + "() must be called inside <script setup> or setup().")
    )
  }
}

function useRouter () {
  if (process.env.NODE_ENV !== 'production') {
    throwNoCurrentInstance('useRouter');
  }

  return getCurrentInstance().proxy.$root.$router
}

function useRoute () {
  if (process.env.NODE_ENV !== 'production') {
    throwNoCurrentInstance('useRoute');
  }

  var root = getCurrentInstance().proxy.$root;
  if (!root._$route) {
    var route = effectScope(true).run(function () { return shallowReactive(Object.assign({}, root.$router.currentRoute)); }
    );
    root._$route = route;

    root.$router.afterEach(function (to) {
      Object.assign(route, to);
    });
  }

  return root._$route
}

function onBeforeRouteUpdate (guard) {
  if (process.env.NODE_ENV !== 'production') {
    throwNoCurrentInstance('onBeforeRouteUpdate');
  }

  return useFilteredGuard(guard, isUpdateNavigation)
}
function isUpdateNavigation (to, from, depth) {
  var toMatched = to.matched;
  var fromMatched = from.matched;
  return (
    toMatched.length >= depth &&
    toMatched
      .slice(0, depth + 1)
      .every(function (record, i) { return record === fromMatched[i]; })
  )
}

function isLeaveNavigation (to, from, depth) {
  var toMatched = to.matched;
  var fromMatched = from.matched;
  return toMatched.length < depth || toMatched[depth] !== fromMatched[depth]
}

function onBeforeRouteLeave (guard) {
  if (process.env.NODE_ENV !== 'production') {
    throwNoCurrentInstance('onBeforeRouteLeave');
  }

  return useFilteredGuard(guard, isLeaveNavigation)
}

var noop = function () {};
function useFilteredGuard (guard, fn) {
  var instance = getCurrentInstance();
  var router = useRouter();

  var target = instance.proxy;
  // find the nearest RouterView to know the depth
  while (
    target &&
    target.$vnode &&
    target.$vnode.data &&
    target.$vnode.data.routerViewDepth == null
  ) {
    target = target.$parent;
  }

  var depth =
    target && target.$vnode && target.$vnode.data
      ? target.$vnode.data.routerViewDepth
      : null;

  if (depth != null) {
    var removeGuard = router.beforeEach(function (to, from, next) {
      return fn(to, from, depth) ? guard(to, from, next) : next()
    });

    onUnmounted(removeGuard);
    return removeGuard
  }

  return noop
}

/*  */

function guardEvent (e) {
  // don't redirect with control keys
  if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) { return }
  // don't redirect when preventDefault called
  if (e.defaultPrevented) { return }
  // don't redirect on right click
  if (e.button !== undefined && e.button !== 0) { return }
  // don't redirect if `target="_blank"`
  if (e.currentTarget && e.currentTarget.getAttribute) {
    var target = e.currentTarget.getAttribute('target');
    if (/\b_blank\b/i.test(target)) { return }
  }
  // this may be a Weex event which doesn't have this method
  if (e.preventDefault) {
    e.preventDefault();
  }
  return true
}

function includesParams (outer, inner) {
  var loop = function ( key ) {
    var innerValue = inner[key];
    var outerValue = outer[key];
    if (typeof innerValue === 'string') {
      if (innerValue !== outerValue) { return { v: false } }
    } else {
      if (
        !Array.isArray(outerValue) ||
        outerValue.length !== innerValue.length ||
        innerValue.some(function (value, i) { return value !== outerValue[i]; })
      ) {
        return { v: false }
      }
    }
  };

  for (var key in inner) {
    var returned = loop( key );

    if ( returned ) return returned.v;
  }

  return true
}

// helpers from vue router 4

function isSameRouteLocationParamsValue (a, b) {
  return Array.isArray(a)
    ? isEquivalentArray(a, b)
    : Array.isArray(b)
      ? isEquivalentArray(b, a)
      : a === b
}

function isEquivalentArray (a, b) {
  return Array.isArray(b)
    ? a.length === b.length && a.every(function (value, i) { return value === b[i]; })
    : a.length === 1 && a[0] === b
}

function isSameRouteLocationParams (a, b) {
  if (Object.keys(a).length !== Object.keys(b).length) { return false }

  for (var key in a) {
    if (!isSameRouteLocationParamsValue(a[key], b[key])) { return false }
  }

  return true
}

function useLink (props) {
  if (process.env.NODE_ENV !== 'production') {
    throwNoCurrentInstance('useLink');
  }

  var router = useRouter();
  var currentRoute = useRoute();

  var resolvedRoute = computed(function () { return router.resolve(unref(props.to), currentRoute); });

  var activeRecordIndex = computed(function () {
    var route = resolvedRoute.value.route;
    var matched = route.matched;
    var length = matched.length;
    var routeMatched = matched[length - 1];
    var currentMatched = currentRoute.matched;
    if (!routeMatched || !currentMatched.length) { return -1 }
    var index = currentMatched.indexOf(routeMatched);
    if (index > -1) { return index }
    // possible parent record
    var parentRecord = currentMatched[currentMatched.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
        parentRecord && parentRecord === routeMatched.parent
    )
  });

  var isActive = computed(
    function () { return activeRecordIndex.value > -1 &&
      includesParams(currentRoute.params, resolvedRoute.value.route.params); }
  );
  var isExactActive = computed(
    function () { return activeRecordIndex.value > -1 &&
      activeRecordIndex.value === currentRoute.matched.length - 1 &&
      isSameRouteLocationParams(currentRoute.params, resolvedRoute.value.route.params); }
  );

  var navigate = function (e) {
    var href = resolvedRoute.value.route;
    if (guardEvent(e)) {
      return props.replace
        ? router.replace(href)
        : router.push(href)
    }
    return Promise.resolve()
  };

  return {
    href: computed(function () { return resolvedRoute.value.href; }),
    route: computed(function () { return resolvedRoute.value.route; }),
    isExactActive: isExactActive,
    isActive: isActive,
    navigate: navigate
  }
}

export { isSameRouteLocationParams, onBeforeRouteLeave, onBeforeRouteUpdate, useLink, useRoute, useRouter };


================================================
FILE: dist/vue-router.common.js
================================================
/*!
  * vue-router v3.6.5
  * (c) 2022 Evan You
  * @license MIT
  */
'use strict';

/*  */

function assert (condition, message) {
  if (!condition) {
    throw new Error(("[vue-router] " + message))
  }
}

function warn (condition, message) {
  if (!condition) {
    typeof console !== 'undefined' && console.warn(("[vue-router] " + message));
  }
}

function extend (a, b) {
  for (var key in b) {
    a[key] = b[key];
  }
  return a
}

/*  */

var encodeReserveRE = /[!'()*]/g;
var encodeReserveReplacer = function (c) { return '%' + c.charCodeAt(0).toString(16); };
var commaRE = /%2C/g;

// fixed encodeURIComponent which is more conformant to RFC3986:
// - escapes [!'()*]
// - preserve commas
var encode = function (str) { return encodeURIComponent(str)
    .replace(encodeReserveRE, encodeReserveReplacer)
    .replace(commaRE, ','); };

function decode (str) {
  try {
    return decodeURIComponent(str)
  } catch (err) {
    if (process.env.NODE_ENV !== 'production') {
      warn(false, ("Error decoding \"" + str + "\". Leaving it intact."));
    }
  }
  return str
}

function resolveQuery (
  query,
  extraQuery,
  _parseQuery
) {
  if ( extraQuery === void 0 ) extraQuery = {};

  var parse = _parseQuery || parseQuery;
  var parsedQuery;
  try {
    parsedQuery = parse(query || '');
  } catch (e) {
    process.env.NODE_ENV !== 'production' && warn(false, e.message);
    parsedQuery = {};
  }
  for (var key in extraQuery) {
    var value = extraQuery[key];
    parsedQuery[key] = Array.isArray(value)
      ? value.map(castQueryParamValue)
      : castQueryParamValue(value);
  }
  return parsedQuery
}

var castQueryParamValue = function (value) { return (value == null || typeof value === 'object' ? value : String(value)); };

function parseQuery (query) {
  var res = {};

  query = query.trim().replace(/^(\?|#|&)/, '');

  if (!query) {
    return res
  }

  query.split('&').forEach(function (param) {
    var parts = param.replace(/\+/g, ' ').split('=');
    var key = decode(parts.shift());
    var val = parts.length > 0 ? decode(parts.join('=')) : null;

    if (res[key] === undefined) {
      res[key] = val;
    } else if (Array.isArray(res[key])) {
      res[key].push(val);
    } else {
      res[key] = [res[key], val];
    }
  });

  return res
}

function stringifyQuery (obj) {
  var res = obj
    ? Object.keys(obj)
      .map(function (key) {
        var val = obj[key];

        if (val === undefined) {
          return ''
        }

        if (val === null) {
          return encode(key)
        }

        if (Array.isArray(val)) {
          var result = [];
          val.forEach(function (val2) {
            if (val2 === undefined) {
              return
            }
            if (val2 === null) {
              result.push(encode(key));
            } else {
              result.push(encode(key) + '=' + encode(val2));
            }
          });
          return result.join('&')
        }

        return encode(key) + '=' + encode(val)
      })
      .filter(function (x) { return x.length > 0; })
      .join('&')
    : null;
  return res ? ("?" + res) : ''
}

/*  */

var trailingSlashRE = /\/?$/;

function createRoute (
  record,
  location,
  redirectedFrom,
  router
) {
  var stringifyQuery = router && router.options.stringifyQuery;

  var query = location.query || {};
  try {
    query = clone(query);
  } catch (e) {}

  var route = {
    name: location.name || (record && record.name),
    meta: (record && record.meta) || {},
    path: location.path || '/',
    hash: location.hash || '',
    query: query,
    params: location.params || {},
    fullPath: getFullPath(location, stringifyQuery),
    matched: record ? formatMatch(record) : []
  };
  if (redirectedFrom) {
    route.redirectedFrom = getFullPath(redirectedFrom, stringifyQuery);
  }
  return Object.freeze(route)
}

function clone (value) {
  if (Array.isArray(value)) {
    return value.map(clone)
  } else if (value && typeof value === 'object') {
    var res = {};
    for (var key in value) {
      res[key] = clone(value[key]);
    }
    return res
  } else {
    return value
  }
}

// the starting route that represents the initial state
var START = createRoute(null, {
  path: '/'
});

function formatMatch (record) {
  var res = [];
  while (record) {
    res.unshift(record);
    record = record.parent;
  }
  return res
}

function getFullPath (
  ref,
  _stringifyQuery
) {
  var path = ref.path;
  var query = ref.query; if ( query === void 0 ) query = {};
  var hash = ref.hash; if ( hash === void 0 ) hash = '';

  var stringify = _stringifyQuery || stringifyQuery;
  return (path || '/') + stringify(query) + hash
}

function isSameRoute (a, b, onlyPath) {
  if (b === START) {
    return a === b
  } else if (!b) {
    return false
  } else if (a.path && b.path) {
    return a.path.replace(trailingSlashRE, '') === b.path.replace(trailingSlashRE, '') && (onlyPath ||
      a.hash === b.hash &&
      isObjectEqual(a.query, b.query))
  } else if (a.name && b.name) {
    return (
      a.name === b.name &&
      (onlyPath || (
        a.hash === b.hash &&
      isObjectEqual(a.query, b.query) &&
      isObjectEqual(a.params, b.params))
      )
    )
  } else {
    return false
  }
}

function isObjectEqual (a, b) {
  if ( a === void 0 ) a = {};
  if ( b === void 0 ) b = {};

  // handle null value #1566
  if (!a || !b) { return a === b }
  var aKeys = Object.keys(a).sort();
  var bKeys = Object.keys(b).sort();
  if (aKeys.length !== bKeys.length) {
    return false
  }
  return aKeys.every(function (key, i) {
    var aVal = a[key];
    var bKey = bKeys[i];
    if (bKey !== key) { return false }
    var bVal = b[key];
    // query values can be null and undefined
    if (aVal == null || bVal == null) { return aVal === bVal }
    // check nested equality
    if (typeof aVal === 'object' && typeof bVal === 'object') {
      return isObjectEqual(aVal, bVal)
    }
    return String(aVal) === String(bVal)
  })
}

function isIncludedRoute (current, target) {
  return (
    current.path.replace(trailingSlashRE, '/').indexOf(
      target.path.replace(trailingSlashRE, '/')
    ) === 0 &&
    (!target.hash || current.hash === target.hash) &&
    queryIncludes(current.query, target.query)
  )
}

function queryIncludes (current, target) {
  for (var key in target) {
    if (!(key in current)) {
      return false
    }
  }
  return true
}

function handleRouteEntered (route) {
  for (var i = 0; i < route.matched.length; i++) {
    var record = route.matched[i];
    for (var name in record.instances) {
      var instance = record.instances[name];
      var cbs = record.enteredCbs[name];
      if (!instance || !cbs) { continue }
      delete record.enteredCbs[name];
      for (var i$1 = 0; i$1 < cbs.length; i$1++) {
        if (!instance._isBeingDestroyed) { cbs[i$1](instance); }
      }
    }
  }
}

var View = {
  name: 'RouterView',
  functional: true,
  props: {
    name: {
      type: String,
      default: 'default'
    }
  },
  render: function render (_, ref) {
    var props = ref.props;
    var children = ref.children;
    var parent = ref.parent;
    var data = ref.data;

    // used by devtools to display a router-view badge
    data.routerView = true;

    // directly use parent context's createElement() function
    // so that components rendered by router-view can resolve named slots
    var h = parent.$createElement;
    var name = props.name;
    var route = parent.$route;
    var cache = parent._routerViewCache || (parent._routerViewCache = {});

    // determine current view depth, also check to see if the tree
    // has been toggled inactive but kept-alive.
    var depth = 0;
    var inactive = false;
    while (parent && parent._routerRoot !== parent) {
      var vnodeData = parent.$vnode ? parent.$vnode.data : {};
      if (vnodeData.routerView) {
        depth++;
      }
      if (vnodeData.keepAlive && parent._directInactive && parent._inactive) {
        inactive = true;
      }
      parent = parent.$parent;
    }
    data.routerViewDepth = depth;

    // render previous view if the tree is inactive and kept-alive
    if (inactive) {
      var cachedData = cache[name];
      var cachedComponent = cachedData && cachedData.component;
      if (cachedComponent) {
        // #2301
        // pass props
        if (cachedData.configProps) {
          fillPropsinData(cachedComponent, data, cachedData.route, cachedData.configProps);
        }
        return h(cachedComponent, data, children)
      } else {
        // render previous empty view
        return h()
      }
    }

    var matched = route.matched[depth];
    var component = matched && matched.components[name];

    // render empty node if no matched route or no config component
    if (!matched || !component) {
      cache[name] = null;
      return h()
    }

    // cache component
    cache[name] = { component: component };

    // attach instance registration hook
    // this will be called in the instance's injected lifecycle hooks
    data.registerRouteInstance = function (vm, val) {
      // val could be undefined for unregistration
      var current = matched.instances[name];
      if (
        (val && current !== vm) ||
        (!val && current === vm)
      ) {
        matched.instances[name] = val;
      }
    }

    // also register instance in prepatch hook
    // in case the same component instance is reused across different routes
    ;(data.hook || (data.hook = {})).prepatch = function (_, vnode) {
      matched.instances[name] = vnode.componentInstance;
    };

    // register instance in init hook
    // in case kept-alive component be actived when routes changed
    data.hook.init = function (vnode) {
      if (vnode.data.keepAlive &&
        vnode.componentInstance &&
        vnode.componentInstance !== matched.instances[name]
      ) {
        matched.instances[name] = vnode.componentInstance;
      }

      // if the route transition has already been confirmed then we weren't
      // able to call the cbs during confirmation as the component was not
      // registered yet, so we call it here.
      handleRouteEntered(route);
    };

    var configProps = matched.props && matched.props[name];
    // save route and configProps in cache
    if (configProps) {
      extend(cache[name], {
        route: route,
        configProps: configProps
      });
      fillPropsinData(component, data, route, configProps);
    }

    return h(component, data, children)
  }
};

function fillPropsinData (component, data, route, configProps) {
  // resolve props
  var propsToPass = data.props = resolveProps(route, configProps);
  if (propsToPass) {
    // clone to prevent mutation
    propsToPass = data.props = extend({}, propsToPass);
    // pass non-declared props as attrs
    var attrs = data.attrs = data.attrs || {};
    for (var key in propsToPass) {
      if (!component.props || !(key in component.props)) {
        attrs[key] = propsToPass[key];
        delete propsToPass[key];
      }
    }
  }
}

function resolveProps (route, config) {
  switch (typeof config) {
    case 'undefined':
      return
    case 'object':
      return config
    case 'function':
      return config(route)
    case 'boolean':
      return config ? route.params : undefined
    default:
      if (process.env.NODE_ENV !== 'production') {
        warn(
          false,
          "props in \"" + (route.path) + "\" is a " + (typeof config) + ", " +
          "expecting an object, function or boolean."
        );
      }
  }
}

/*  */

function resolvePath (
  relative,
  base,
  append
) {
  var firstChar = relative.charAt(0);
  if (firstChar === '/') {
    return relative
  }

  if (firstChar === '?' || firstChar === '#') {
    return base + relative
  }

  var stack = base.split('/');

  // remove trailing segment if:
  // - not appending
  // - appending to trailing slash (last segment is empty)
  if (!append || !stack[stack.length - 1]) {
    stack.pop();
  }

  // resolve relative path
  var segments = relative.replace(/^\//, '').split('/');
  for (var i = 0; i < segments.length; i++) {
    var segment = segments[i];
    if (segment === '..') {
      stack.pop();
    } else if (segment !== '.') {
      stack.push(segment);
    }
  }

  // ensure leading slash
  if (stack[0] !== '') {
    stack.unshift('');
  }

  return stack.join('/')
}

function parsePath (path) {
  var hash = '';
  var query = '';

  var hashIndex = path.indexOf('#');
  if (hashIndex >= 0) {
    hash = path.slice(hashIndex);
    path = path.slice(0, hashIndex);
  }

  var queryIndex = path.indexOf('?');
  if (queryIndex >= 0) {
    query = path.slice(queryIndex + 1);
    path = path.slice(0, queryIndex);
  }

  return {
    path: path,
    query: query,
    hash: hash
  }
}

function cleanPath (path) {
  return path.replace(/\/(?:\s*\/)+/g, '/')
}

var isarray = Array.isArray || function (arr) {
  return Object.prototype.toString.call(arr) == '[object Array]';
};

/**
 * Expose `pathToRegexp`.
 */
var pathToRegexp_1 = pathToRegexp;
var parse_1 = parse;
var compile_1 = compile;
var tokensToFunction_1 = tokensToFunction;
var tokensToRegExp_1 = tokensToRegExp;

/**
 * The main path matching regexp utility.
 *
 * @type {RegExp}
 */
var PATH_REGEXP = new RegExp([
  // Match escaped characters that would otherwise appear in future matches.
  // This allows the user to escape special characters that won't transform.
  '(\\\\.)',
  // Match Express-style parameters and un-named parameters with a prefix
  // and optional suffixes. Matches appear as:
  //
  // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined]
  // "/route(\\d+)"  => [undefined, undefined, undefined, "\d+", undefined, undefined]
  // "/*"            => ["/", undefined, undefined, undefined, undefined, "*"]
  '([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))'
].join('|'), 'g');

/**
 * Parse a string for the raw tokens.
 *
 * @param  {string}  str
 * @param  {Object=} options
 * @return {!Array}
 */
function parse (str, options) {
  var tokens = [];
  var key = 0;
  var index = 0;
  var path = '';
  var defaultDelimiter = options && options.delimiter || '/';
  var res;

  while ((res = PATH_REGEXP.exec(str)) != null) {
    var m = res[0];
    var escaped = res[1];
    var offset = res.index;
    path += str.slice(index, offset);
    index = offset + m.length;

    // Ignore already escaped sequences.
    if (escaped) {
      path += escaped[1];
      continue
    }

    var next = str[index];
    var prefix = res[2];
    var name = res[3];
    var capture = res[4];
    var group = res[5];
    var modifier = res[6];
    var asterisk = res[7];

    // Push the current path onto the tokens.
    if (path) {
      tokens.push(path);
      path = '';
    }

    var partial = prefix != null && next != null && next !== prefix;
    var repeat = modifier === '+' || modifier === '*';
    var optional = modifier === '?' || modifier === '*';
    var delimiter = res[2] || defaultDelimiter;
    var pattern = capture || group;

    tokens.push({
      name: name || key++,
      prefix: prefix || '',
      delimiter: delimiter,
      optional: optional,
      repeat: repeat,
      partial: partial,
      asterisk: !!asterisk,
      pattern: pattern ? escapeGroup(pattern) : (asterisk ? '.*' : '[^' + escapeString(delimiter) + ']+?')
    });
  }

  // Match any characters still remaining.
  if (index < str.length) {
    path += str.substr(index);
  }

  // If the path exists, push it onto the end.
  if (path) {
    tokens.push(path);
  }

  return tokens
}

/**
 * Compile a string to a template function for the path.
 *
 * @param  {string}             str
 * @param  {Object=}            options
 * @return {!function(Object=, Object=)}
 */
function compile (str, options) {
  return tokensToFunction(parse(str, options), options)
}

/**
 * Prettier encoding of URI path segments.
 *
 * @param  {string}
 * @return {string}
 */
function encodeURIComponentPretty (str) {
  return encodeURI(str).replace(/[\/?#]/g, function (c) {
    return '%' + c.charCodeAt(0).toString(16).toUpperCase()
  })
}

/**
 * Encode the asterisk parameter. Similar to `pretty`, but allows slashes.
 *
 * @param  {string}
 * @return {string}
 */
function encodeAsterisk (str) {
  return encodeURI(str).replace(/[?#]/g, function (c) {
    return '%' + c.charCodeAt(0).toString(16).toUpperCase()
  })
}

/**
 * Expose a method for transforming tokens into the path function.
 */
function tokensToFunction (tokens, options) {
  // Compile all the tokens into regexps.
  var matches = new Array(tokens.length);

  // Compile all the patterns before compilation.
  for (var i = 0; i < tokens.length; i++) {
    if (typeof tokens[i] === 'object') {
      matches[i] = new RegExp('^(?:' + tokens[i].pattern + ')$', flags(options));
    }
  }

  return function (obj, opts) {
    var path = '';
    var data = obj || {};
    var options = opts || {};
    var encode = options.pretty ? encodeURIComponentPretty : encodeURIComponent;

    for (var i = 0; i < tokens.length; i++) {
      var token = tokens[i];

      if (typeof token === 'string') {
        path += token;

        continue
      }

      var value = data[token.name];
      var segment;

      if (value == null) {
        if (token.optional) {
          // Prepend partial segment prefixes.
          if (token.partial) {
            path += token.prefix;
          }

          continue
        } else {
          throw new TypeError('Expected "' + token.name + '" to be defined')
        }
      }

      if (isarray(value)) {
        if (!token.repeat) {
          throw new TypeError('Expected "' + token.name + '" to not repeat, but received `' + JSON.stringify(value) + '`')
        }

        if (value.length === 0) {
          if (token.optional) {
            continue
          } else {
            throw new TypeError('Expected "' + token.name + '" to not be empty')
          }
        }

        for (var j = 0; j < value.length; j++) {
          segment = encode(value[j]);

          if (!matches[i].test(segment)) {
            throw new TypeError('Expected all "' + token.name + '" to match "' + token.pattern + '", but received `' + JSON.stringify(segment) + '`')
          }

          path += (j === 0 ? token.prefix : token.delimiter) + segment;
        }

        continue
      }

      segment = token.asterisk ? encodeAsterisk(value) : encode(value);

      if (!matches[i].test(segment)) {
        throw new TypeError('Expected "' + token.name + '" to match "' + token.pattern + '", but received "' + segment + '"')
      }

      path += token.prefix + segment;
    }

    return path
  }
}

/**
 * Escape a regular expression string.
 *
 * @param  {string} str
 * @return {string}
 */
function escapeString (str) {
  return str.replace(/([.+*?=^!:${}()[\]|\/\\])/g, '\\$1')
}

/**
 * Escape the capturing group by escaping special characters and meaning.
 *
 * @param  {string} group
 * @return {string}
 */
function escapeGroup (group) {
  return group.replace(/([=!:$\/()])/g, '\\$1')
}

/**
 * Attach the keys as a property of the regexp.
 *
 * @param  {!RegExp} re
 * @param  {Array}   keys
 * @return {!RegExp}
 */
function attachKeys (re, keys) {
  re.keys = keys;
  return re
}

/**
 * Get the flags for a regexp from the options.
 *
 * @param  {Object} options
 * @return {string}
 */
function flags (options) {
  return options && options.sensitive ? '' : 'i'
}

/**
 * Pull out keys from a regexp.
 *
 * @param  {!RegExp} path
 * @param  {!Array}  keys
 * @return {!RegExp}
 */
function regexpToRegexp (path, keys) {
  // Use a negative lookahead to match only capturing groups.
  var groups = path.source.match(/\((?!\?)/g);

  if (groups) {
    for (var i = 0; i < groups.length; i++) {
      keys.push({
        name: i,
        prefix: null,
        delimiter: null,
        optional: false,
        repeat: false,
        partial: false,
        asterisk: false,
        pattern: null
      });
    }
  }

  return attachKeys(path, keys)
}

/**
 * Transform an array into a regexp.
 *
 * @param  {!Array}  path
 * @param  {Array}   keys
 * @param  {!Object} options
 * @return {!RegExp}
 */
function arrayToRegexp (path, keys, options) {
  var parts = [];

  for (var i = 0; i < path.length; i++) {
    parts.push(pathToRegexp(path[i], keys, options).source);
  }

  var regexp = new RegExp('(?:' + parts.join('|') + ')', flags(options));

  return attachKeys(regexp, keys)
}

/**
 * Create a path regexp from string input.
 *
 * @param  {string}  path
 * @param  {!Array}  keys
 * @param  {!Object} options
 * @return {!RegExp}
 */
function stringToRegexp (path, keys, options) {
  return tokensToRegExp(parse(path, options), keys, options)
}

/**
 * Expose a function for taking tokens and returning a RegExp.
 *
 * @param  {!Array}          tokens
 * @param  {(Array|Object)=} keys
 * @param  {Object=}         options
 * @return {!RegExp}
 */
function tokensToRegExp (tokens, keys, options) {
  if (!isarray(keys)) {
    options = /** @type {!Object} */ (keys || options);
    keys = [];
  }

  options = options || {};

  var strict = options.strict;
  var end = options.end !== false;
  var route = '';

  // Iterate over the tokens and create our regexp string.
  for (var i = 0; i < tokens.length; i++) {
    var token = tokens[i];

    if (typeof token === 'string') {
      route += escapeString(token);
    } else {
      var prefix = escapeString(token.prefix);
      var capture = '(?:' + token.pattern + ')';

      keys.push(token);

      if (token.repeat) {
        capture += '(?:' + prefix + capture + ')*';
      }

      if (token.optional) {
        if (!token.partial) {
          capture = '(?:' + prefix + '(' + capture + '))?';
        } else {
          capture = prefix + '(' + capture + ')?';
        }
      } else {
        capture = prefix + '(' + capture + ')';
      }

      route += capture;
    }
  }

  var delimiter = escapeString(options.delimiter || '/');
  var endsWithDelimiter = route.slice(-delimiter.length) === delimiter;

  // In non-strict mode we allow a slash at the end of match. If the path to
  // match already ends with a slash, we remove it for consistency. The slash
  // is valid at the end of a path match, not in the middle. This is important
  // in non-ending mode, where "/test/" shouldn't match "/test//route".
  if (!strict) {
    route = (endsWithDelimiter ? route.slice(0, -delimiter.length) : route) + '(?:' + delimiter + '(?=$))?';
  }

  if (end) {
    route += '$';
  } else {
    // In non-ending mode, we need the capturing groups to match as much as
    // possible by using a positive lookahead to the end or next path segment.
    route += strict && endsWithDelimiter ? '' : '(?=' + delimiter + '|$)';
  }

  return attachKeys(new RegExp('^' + route, flags(options)), keys)
}

/**
 * Normalize the given path string, returning a regular expression.
 *
 * An empty array can be passed in for the keys, which will hold the
 * placeholder key descriptions. For example, using `/user/:id`, `keys` will
 * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.
 *
 * @param  {(string|RegExp|Array)} path
 * @param  {(Array|Object)=}       keys
 * @param  {Object=}               options
 * @return {!RegExp}
 */
function pathToRegexp (path, keys, options) {
  if (!isarray(keys)) {
    options = /** @type {!Object} */ (keys || options);
    keys = [];
  }

  options = options || {};

  if (path instanceof RegExp) {
    return regexpToRegexp(path, /** @type {!Array} */ (keys))
  }

  if (isarray(path)) {
    return arrayToRegexp(/** @type {!Array} */ (path), /** @type {!Array} */ (keys), options)
  }

  return stringToRegexp(/** @type {string} */ (path), /** @type {!Array} */ (keys), options)
}
pathToRegexp_1.parse = parse_1;
pathToRegexp_1.compile = compile_1;
pathToRegexp_1.tokensToFunction = tokensToFunction_1;
pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;

/*  */

// $flow-disable-line
var regexpCompileCache = Object.create(null);

function fillParams (
  path,
  params,
  routeMsg
) {
  params = params || {};
  try {
    var filler =
      regexpCompileCache[path] ||
      (regexpCompileCache[path] = pathToRegexp_1.compile(path));

    // Fix #2505 resolving asterisk routes { name: 'not-found', params: { pathMatch: '/not-found' }}
    // and fix #3106 so that you can work with location descriptor object having params.pathMatch equal to empty string
    if (typeof params.pathMatch === 'string') { params[0] = params.pathMatch; }

    return filler(params, { pretty: true })
  } catch (e) {
    if (process.env.NODE_ENV !== 'production') {
      // Fix #3072 no warn if `pathMatch` is string
      warn(typeof params.pathMatch === 'string', ("missing param for " + routeMsg + ": " + (e.message)));
    }
    return ''
  } finally {
    // delete the 0 if it was added
    delete params[0];
  }
}

/*  */

function normalizeLocation (
  raw,
  current,
  append,
  router
) {
  var next = typeof raw === 'string' ? { path: raw } : raw;
  // named target
  if (next._normalized) {
    return next
  } else if (next.name) {
    next = extend({}, raw);
    var params = next.params;
    if (params && typeof params === 'object') {
      next.params = extend({}, params);
    }
    return next
  }

  // relative params
  if (!next.path && next.params && current) {
    next = extend({}, next);
    next._normalized = true;
    var params$1 = extend(extend({}, current.params), next.params);
    if (current.name) {
      next.name = current.name;
      next.params = params$1;
    } else if (current.matched.length) {
      var rawPath = current.matched[current.matched.length - 1].path;
      next.path = fillParams(rawPath, params$1, ("path " + (current.path)));
    } else if (process.env.NODE_ENV !== 'production') {
      warn(false, "relative params navigation requires a current route.");
    }
    return next
  }

  var parsedPath = parsePath(next.path || '');
  var basePath = (current && current.path) || '/';
  var path = parsedPath.path
    ? resolvePath(parsedPath.path, basePath, append || next.append)
    : basePath;

  var query = resolveQuery(
    parsedPath.query,
    next.query,
    router && router.options.parseQuery
  );

  var hash = next.hash || parsedPath.hash;
  if (hash && hash.charAt(0) !== '#') {
    hash = "#" + hash;
  }

  return {
    _normalized: true,
    path: path,
    query: query,
    hash: hash
  }
}

/*  */

// work around weird flow bug
var toTypes = [String, Object];
var eventTypes = [String, Array];

var noop = function () {};

var warnedCustomSlot;
var warnedTagProp;
var warnedEventProp;

var Link = {
  name: 'RouterLink',
  props: {
    to: {
      type: toTypes,
      required: true
    },
    tag: {
      type: String,
      default: 'a'
    },
    custom: Boolean,
    exact: Boolean,
    exactPath: Boolean,
    append: Boolean,
    replace: Boolean,
    activeClass: String,
    exactActiveClass: String,
    ariaCurrentValue: {
      type: String,
      default: 'page'
    },
    event: {
      type: eventTypes,
      default: 'click'
    }
  },
  render: function render (h) {
    var this$1$1 = this;

    var router = this.$router;
    var current = this.$route;
    var ref = router.resolve(
      this.to,
      current,
      this.append
    );
    var location = ref.location;
    var route = ref.route;
    var href = ref.href;

    var classes = {};
    var globalActiveClass = router.options.linkActiveClass;
    var globalExactActiveClass = router.options.linkExactActiveClass;
    // Support global empty active class
    var activeClassFallback =
      globalActiveClass == null ? 'router-link-active' : globalActiveClass;
    var exactActiveClassFallback =
      globalExactActiveClass == null
        ? 'router-link-exact-active'
        : globalExactActiveClass;
    var activeClass =
      this.activeClass == null ? activeClassFallback : this.activeClass;
    var exactActiveClass =
      this.exactActiveClass == null
        ? exactActiveClassFallback
        : this.exactActiveClass;

    var compareTarget = route.redirectedFrom
      ? createRoute(null, normalizeLocation(route.redirectedFrom), null, router)
      : route;

    classes[exactActiveClass] = isSameRoute(current, compareTarget, this.exactPath);
    classes[activeClass] = this.exact || this.exactPath
      ? classes[exactActiveClass]
      : isIncludedRoute(current, compareTarget);

    var ariaCurrentValue = classes[exactActiveClass] ? this.ariaCurrentValue : null;

    var handler = function (e) {
      if (guardEvent(e)) {
        if (this$1$1.replace) {
          router.replace(location, noop);
        } else {
          router.push(location, noop);
        }
      }
    };

    var on = { click: guardEvent };
    if (Array.isArray(this.event)) {
      this.event.forEach(function (e) {
        on[e] = handler;
      });
    } else {
      on[this.event] = handler;
    }

    var data = { class: classes };

    var scopedSlot =
      !this.$scopedSlots.$hasNormal &&
      this.$scopedSlots.default &&
      this.$scopedSlots.default({
        href: href,
        route: route,
        navigate: handler,
        isActive: classes[activeClass],
        isExactActive: classes[exactActiveClass]
      });

    if (scopedSlot) {
      if (process.env.NODE_ENV !== 'production' && !this.custom) {
        !warnedCustomSlot && warn(false, 'In Vue Router 4, the v-slot API will by default wrap its content with an <a> element. Use the custom prop to remove this warning:\n<router-link v-slot="{ navigate, href }" custom></router-link>\n');
        warnedCustomSlot = true;
      }
      if (scopedSlot.length === 1) {
        return scopedSlot[0]
      } else if (scopedSlot.length > 1 || !scopedSlot.length) {
        if (process.env.NODE_ENV !== 'production') {
          warn(
            false,
            ("<router-link> with to=\"" + (this.to) + "\" is trying to use a scoped slot but it didn't provide exactly one child. Wrapping the content with a span element.")
          );
        }
        return scopedSlot.length === 0 ? h() : h('span', {}, scopedSlot)
      }
    }

    if (process.env.NODE_ENV !== 'production') {
      if ('tag' in this.$options.propsData && !warnedTagProp) {
        warn(
          false,
          "<router-link>'s tag prop is deprecated and has been removed in Vue Router 4. Use the v-slot API to remove this warning: https://next.router.vuejs.org/guide/migration/#removal-of-event-and-tag-props-in-router-link."
        );
        warnedTagProp = true;
      }
      if ('event' in this.$options.propsData && !warnedEventProp) {
        warn(
          false,
          "<router-link>'s event prop is deprecated and has been removed in Vue Router 4. Use the v-slot API to remove this warning: https://next.router.vuejs.org/guide/migration/#removal-of-event-and-tag-props-in-router-link."
        );
        warnedEventProp = true;
      }
    }

    if (this.tag === 'a') {
      data.on = on;
      data.attrs = { href: href, 'aria-current': ariaCurrentValue };
    } else {
      // find the first <a> child and apply listener and href
      var a = findAnchor(this.$slots.default);
      if (a) {
        // in case the <a> is a static node
        a.isStatic = false;
        var aData = (a.data = extend({}, a.data));
        aData.on = aData.on || {};
        // transform existing events in both objects into arrays so we can push later
        for (var event in aData.on) {
          var handler$1 = aData.on[event];
          if (event in on) {
            aData.on[event] = Array.isArray(handler$1) ? handler$1 : [handler$1];
          }
        }
        // append new listeners for router-link
        for (var event$1 in on) {
          if (event$1 in aData.on) {
            // on[event] is always a function
            aData.on[event$1].push(on[event$1]);
          } else {
            aData.on[event$1] = handler;
          }
        }

        var aAttrs = (a.data.attrs = extend({}, a.data.attrs));
        aAttrs.href = href;
        aAttrs['aria-current'] = ariaCurrentValue;
      } else {
        // doesn't have <a> child, apply listener to self
        data.on = on;
      }
    }

    return h(this.tag, data, this.$slots.default)
  }
};

function guardEvent (e) {
  // don't redirect with control keys
  if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) { return }
  // don't redirect when preventDefault called
  if (e.defaultPrevented) { return }
  // don't redirect on right click
  if (e.button !== undefined && e.button !== 0) { return }
  // don't redirect if `target="_blank"`
  if (e.currentTarget && e.currentTarget.getAttribute) {
    var target = e.currentTarget.getAttribute('target');
    if (/\b_blank\b/i.test(target)) { return }
  }
  // this may be a Weex event which doesn't have this method
  if (e.preventDefault) {
    e.preventDefault();
  }
  return true
}

function findAnchor (children) {
  if (children) {
    var child;
    for (var i = 0; i < children.length; i++) {
      child = children[i];
      if (child.tag === 'a') {
        return child
      }
      if (child.children && (child = findAnchor(child.children))) {
        return child
      }
    }
  }
}

var _Vue;

function install (Vue) {
  if (install.installed && _Vue === Vue) { return }
  install.installed = true;

  _Vue = Vue;

  var isDef = function (v) { return v !== undefined; };

  var registerInstance = function (vm, callVal) {
    var i = vm.$options._parentVnode;
    if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
      i(vm, callVal);
    }
  };

  Vue.mixin({
    beforeCreate: function beforeCreate () {
      if (isDef(this.$options.router)) {
        this._routerRoot = this;
        this._router = this.$options.router;
        this._router.init(this);
        Vue.util.defineReactive(this, '_route', this._router.history.current);
      } else {
        this._routerRoot = (this.$parent && this.$parent._routerRoot) || this;
      }
      registerInstance(this, this);
    },
    destroyed: function destroyed () {
      registerInstance(this);
    }
  });

  Object.defineProperty(Vue.prototype, '$router', {
    get: function get () { return this._routerRoot._router }
  });

  Object.defineProperty(Vue.prototype, '$route', {
    get: function get () { return this._routerRoot._route }
  });

  Vue.component('RouterView', View);
  Vue.component('RouterLink', Link);

  var strats = Vue.config.optionMergeStrategies;
  // use the same hook merging strategy for route hooks
  strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created;
}

/*  */

var inBrowser = typeof window !== 'undefined';

/*  */

function createRouteMap (
  routes,
  oldPathList,
  oldPathMap,
  oldNameMap,
  parentRoute
) {
  // the path list is used to control path matching priority
  var pathList = oldPathList || [];
  // $flow-disable-line
  var pathMap = oldPathMap || Object.create(null);
  // $flow-disable-line
  var nameMap = oldNameMap || Object.create(null);

  routes.forEach(function (route) {
    addRouteRecord(pathList, pathMap, nameMap, route, parentRoute);
  });

  // ensure wildcard routes are always at the end
  for (var i = 0, l = pathList.length; i < l; i++) {
    if (pathList[i] === '*') {
      pathList.push(pathList.splice(i, 1)[0]);
      l--;
      i--;
    }
  }

  if (process.env.NODE_ENV === 'development') {
    // warn if routes do not include leading slashes
    var found = pathList
    // check for missing leading slash
      .filter(function (path) { return path && path.charAt(0) !== '*' && path.charAt(0) !== '/'; });

    if (found.length > 0) {
      var pathNames = found.map(function (path) { return ("- " + path); }).join('\n');
      warn(false, ("Non-nested routes must include a leading slash character. Fix the following routes: \n" + pathNames));
    }
  }

  return {
    pathList: pathList,
    pathMap: pathMap,
    nameMap: nameMap
  }
}

function addRouteRecord (
  pathList,
  pathMap,
  nameMap,
  route,
  parent,
  matchAs
) {
  var path = route.path;
  var name = route.name;
  if (process.env.NODE_ENV !== 'production') {
    assert(path != null, "\"path\" is required in a route configuration.");
    assert(
      typeof route.component !== 'string',
      "route config \"component\" for path: " + (String(
        path || name
      )) + " cannot be a " + "string id. Use an actual component instead."
    );

    warn(
      // eslint-disable-next-line no-control-regex
      !/[^\u0000-\u007F]+/.test(path),
      "Route with path \"" + path + "\" contains unencoded characters, make sure " +
        "your path is correctly encoded before passing it to the router. Use " +
        "encodeURI to encode static segments of your path."
    );
  }

  var pathToRegexpOptions =
    route.pathToRegexpOptions || {};
  var normalizedPath = normalizePath(path, parent, pathToRegexpOptions.strict);

  if (typeof route.caseSensitive === 'boolean') {
    pathToRegexpOptions.sensitive = route.caseSensitive;
  }

  var record = {
    path: normalizedPath,
    regex: compileRouteRegex(normalizedPath, pathToRegexpOptions),
    components: route.components || { default: route.component },
    alias: route.alias
      ? typeof route.alias === 'string'
        ? [route.alias]
        : route.alias
      : [],
    instances: {},
    enteredCbs: {},
    name: name,
    parent: parent,
    matchAs: matchAs,
    redirect: route.redirect,
    beforeEnter: route.beforeEnter,
    meta: route.meta || {},
    props:
      route.props == null
        ? {}
        : route.components
          ? route.props
          : { default: route.props }
  };

  if (route.children) {
    // Warn if route is named, does not redirect and has a default child route.
    // If users navigate to this route by name, the default child will
    // not be rendered (GH Issue #629)
    if (process.env.NODE_ENV !== 'production') {
      if (
        route.name &&
        !route.redirect &&
        route.children.some(function (child) { return /^\/?$/.test(child.path); })
      ) {
        warn(
          false,
          "Named Route '" + (route.name) + "' has a default child route. " +
            "When navigating to this named route (:to=\"{name: '" + (route.name) + "'}\"), " +
            "the default child route will not be rendered. Remove the name from " +
            "this route and use the name of the default child route for named " +
            "links instead."
        );
      }
    }
    route.children.forEach(function (child) {
      var childMatchAs = matchAs
        ? cleanPath((matchAs + "/" + (child.path)))
        : undefined;
      addRouteRecord(pathList, pathMap, nameMap, child, record, childMatchAs);
    });
  }

  if (!pathMap[record.path]) {
    pathList.push(record.path);
    pathMap[record.path] = record;
  }

  if (route.alias !== undefined) {
    var aliases = Array.isArray(route.alias) ? route.alias : [route.alias];
    for (var i = 0; i < aliases.length; ++i) {
      var alias = aliases[i];
      if (process.env.NODE_ENV !== 'production' && alias === path) {
        warn(
          false,
          ("Found an alias with the same value as the path: \"" + path + "\". You have to remove that alias. It will be ignored in development.")
        );
        // skip in dev to make it work
        continue
      }

      var aliasRoute = {
        path: alias,
        children: route.children
      };
      addRouteRecord(
        pathList,
        pathMap,
        nameMap,
        aliasRoute,
        parent,
        record.path || '/' // matchAs
      );
    }
  }

  if (name) {
    if (!nameMap[name]) {
      nameMap[name] = record;
    } else if (process.env.NODE_ENV !== 'production' && !matchAs) {
      warn(
        false,
        "Duplicate named routes definition: " +
          "{ name: \"" + name + "\", path: \"" + (record.path) + "\" }"
      );
    }
  }
}

function compileRouteRegex (
  path,
  pathToRegexpOptions
) {
  var regex = pathToRegexp_1(path, [], pathToRegexpOptions);
  if (process.env.NODE_ENV !== 'production') {
    var keys = Object.create(null);
    regex.keys.forEach(function (key) {
      warn(
        !keys[key.name],
        ("Duplicate param keys in route with path: \"" + path + "\"")
      );
      keys[key.name] = true;
    });
  }
  return regex
}

function normalizePath (
  path,
  parent,
  strict
) {
  if (!strict) { path = path.replace(/\/$/, ''); }
  if (path[0] === '/') { return path }
  if (parent == null) { return path }
  return cleanPath(((parent.path) + "/" + path))
}

/*  */



function createMatcher (
  routes,
  router
) {
  var ref = createRouteMap(routes);
  var pathList = ref.pathList;
  var pathMap = ref.pathMap;
  var nameMap = ref.nameMap;

  function addRoutes (routes) {
    createRouteMap(routes, pathList, pathMap, nameMap);
  }

  function addRoute (parentOrRoute, route) {
    var parent = (typeof parentOrRoute !== 'object') ? nameMap[parentOrRoute] : undefined;
    // $flow-disable-line
    createRouteMap([route || parentOrRoute], pathList, pathMap, nameMap, parent);

    // add aliases of parent
    if (parent && parent.alias.length) {
      createRouteMap(
        // $flow-disable-line route is defined if parent is
        parent.alias.map(function (alias) { return ({ path: alias, children: [route] }); }),
        pathList,
        pathMap,
        nameMap,
        parent
      );
    }
  }

  function getRoutes () {
    return pathList.map(function (path) { return pathMap[path]; })
  }

  function match (
    raw,
    currentRoute,
    redirectedFrom
  ) {
    var location = normalizeLocation(raw, currentRoute, false, router);
    var name = location.name;

    if (name) {
      var record = nameMap[name];
      if (process.env.NODE_ENV !== 'production') {
        warn(record, ("Route with name '" + name + "' does not exist"));
      }
      if (!record) { return _createRoute(null, location) }
      var paramNames = record.regex.keys
        .filter(function (key) { return !key.optional; })
        .map(function (key) { return key.name; });

      if (typeof location.params !== 'object') {
        location.params = {};
      }

      if (currentRoute && typeof currentRoute.params === 'object') {
        for (var key in currentRoute.params) {
          if (!(key in location.params) && paramNames.indexOf(key) > -1) {
            location.params[key] = currentRoute.params[key];
          }
        }
      }

      location.path = fillParams(record.path, location.params, ("named route \"" + name + "\""));
      return _createRoute(record, location, redirectedFrom)
    } else if (location.path) {
      location.params = {};
      for (var i = 0; i < pathList.length; i++) {
        var path = pathList[i];
        var record$1 = pathMap[path];
        if (matchRoute(record$1.regex, location.path, location.params)) {
          return _createRoute(record$1, location, redirectedFrom)
        }
      }
    }
    // no match
    return _createRoute(null, location)
  }

  function redirect (
    record,
    location
  ) {
    var originalRedirect = record.redirect;
    var redirect = typeof originalRedirect === 'function'
      ? originalRedirect(createRoute(record, location, null, router))
      : originalRedirect;

    if (typeof redirect === 'string') {
      redirect = { path: redirect };
    }

    if (!redirect || typeof redirect !== 'object') {
      if (process.env.NODE_ENV !== 'production') {
        warn(
          false, ("invalid redirect option: " + (JSON.stringify(redirect)))
        );
      }
      return _createRoute(null, location)
    }

    var re = redirect;
    var name = re.name;
    var path = re.path;
    var query = location.query;
    var hash = location.hash;
    var params = location.params;
    query = re.hasOwnProperty('query') ? re.query : query;
    hash = re.hasOwnProperty('hash') ? re.hash : hash;
    params = re.hasOwnProperty('params') ? re.params : params;

    if (name) {
      // resolved named direct
      var targetRecord = nameMap[name];
      if (process.env.NODE_ENV !== 'production') {
        assert(targetRecord, ("redirect failed: named route \"" + name + "\" not found."));
      }
      return match({
        _normalized: true,
        name: name,
        query: query,
        hash: hash,
        params: params
      }, undefined, location)
    } else if (path) {
      // 1. resolve relative redirect
      var rawPath = resolveRecordPath(path, record);
      // 2. resolve params
      var resolvedPath = fillParams(rawPath, params, ("redirect route with path \"" + rawPath + "\""));
      // 3. rematch with existing query and hash
      return match({
        _normalized: true,
        path: resolvedPath,
        query: query,
        hash: hash
      }, undefined, location)
    } else {
      if (process.env.NODE_ENV !== 'production') {
        warn(false, ("invalid redirect option: " + (JSON.stringify(redirect))));
      }
      return _createRoute(null, location)
    }
  }

  function alias (
    record,
    location,
    matchAs
  ) {
    var aliasedPath = fillParams(matchAs, location.params, ("aliased route with path \"" + matchAs + "\""));
    var aliasedMatch = match({
      _normalized: true,
      path: aliasedPath
    });
    if (aliasedMatch) {
      var matched = aliasedMatch.matched;
      var aliasedRecord = matched[matched.length - 1];
      location.params = aliasedMatch.params;
      return _createRoute(aliasedRecord, location)
    }
    return _createRoute(null, location)
  }

  function _createRoute (
    record,
    location,
    redirectedFrom
  ) {
    if (record && record.redirect) {
      return redirect(record, redirectedFrom || location)
    }
    if (record && record.matchAs) {
      return alias(record, location, record.matchAs)
    }
    return createRoute(record, location, redirectedFrom, router)
  }

  return {
    match: match,
    addRoute: addRoute,
    getRoutes: getRoutes,
    addRoutes: addRoutes
  }
}

function matchRoute (
  regex,
  path,
  params
) {
  var m = path.match(regex);

  if (!m) {
    return false
  } else if (!params) {
    return true
  }

  for (var i = 1, len = m.length; i < len; ++i) {
    var key = regex.keys[i - 1];
    if (key) {
      // Fix #1994: using * with props: true generates a param named 0
      params[key.name || 'pathMatch'] = typeof m[i] === 'string' ? decode(m[i]) : m[i];
    }
  }

  return true
}

function resolveRecordPath (path, record) {
  return resolvePath(path, record.parent ? record.parent.path : '/', true)
}

/*  */

// use User Timing api (if present) for more accurate key precision
var Time =
  inBrowser && window.performance && window.performance.now
    ? window.performance
    : Date;

function genStateKey () {
  return Time.now().toFixed(3)
}

var _key = genStateKey();

function getStateKey () {
  return _key
}

function setStateKey (key) {
  return (_key = key)
}

/*  */

var positionStore = Object.create(null);

function setupScroll () {
  // Prevent browser scroll behavior on History popstate
  if ('scrollRestoration' in window.history) {
    window.history.scrollRestoration = 'manual';
  }
  // Fix for #1585 for Firefox
  // Fix for #2195 Add optional third attribute to workaround a bug in safari https://bugs.webkit.org/show_bug.cgi?id=182678
  // Fix for #2774 Support for apps loaded from Windows file shares not mapped to network drives: replaced location.origin with
  // window.location.protocol + '//' + window.location.host
  // location.host contains the port and location.hostname doesn't
  var protocolAndPath = window.location.protocol + '//' + window.location.host;
  var absolutePath = window.location.href.replace(protocolAndPath, '');
  // preserve existing history state as it could be overriden by the user
  var stateCopy = extend({}, window.history.state);
  stateCopy.key = getStateKey();
  window.history.replaceState(stateCopy, '', absolutePath);
  window.addEventListener('popstate', handlePopState);
  return function () {
    window.removeEventListener('popstate', handlePopState);
  }
}

function handleScroll (
  router,
  to,
  from,
  isPop
) {
  if (!router.app) {
    return
  }

  var behavior = router.options.scrollBehavior;
  if (!behavior) {
    return
  }

  if (process.env.NODE_ENV !== 'production') {
    assert(typeof behavior === 'function', "scrollBehavior must be a function");
  }

  // wait until re-render finishes before scrolling
  router.app.$nextTick(function () {
    var position = getScrollPosition();
    var shouldScroll = behavior.call(
      router,
      to,
      from,
      isPop ? position : null
    );

    if (!shouldScroll) {
      return
    }

    if (typeof shouldScroll.then === 'function') {
      shouldScroll
        .then(function (shouldScroll) {
          scrollToPosition((shouldScroll), position);
        })
        .catch(function (err) {
          if (process.env.NODE_ENV !== 'production') {
            assert(false, err.toString());
          }
        });
    } else {
      scrollToPosition(shouldScroll, position);
    }
  });
}

function saveScrollPosition () {
  var key = getStateKey();
  if (key) {
    positionStore[key] = {
      x: window.pageXOffset,
      y: window.pageYOffset
    };
  }
}

function handlePopState (e) {
  saveScrollPosition();
  if (e.state && e.state.key) {
    setStateKey(e.state.key);
  }
}

function getScrollPosition () {
  var key = getStateKey();
  if (key) {
    return positionStore[key]
  }
}

function getElementPosition (el, offset) {
  var docEl = document.documentElement;
  var docRect = docEl.getBoundingClientRect();
  var elRect = el.getBoundingClientRect();
  return {
    x: elRect.left - docRect.left - offset.x,
    y: elRect.top - docRect.top - offset.y
  }
}

function isValidPosition (obj) {
  return isNumber(obj.x) || isNumber(obj.y)
}

function normalizePosition (obj) {
  return {
    x: isNumber(obj.x) ? obj.x : window.pageXOffset,
    y: isNumber(obj.y) ? obj.y : window.pageYOffset
  }
}

function normalizeOffset (obj) {
  return {
    x: isNumber(obj.x) ? obj.x : 0,
    y: isNumber(obj.y) ? obj.y : 0
  }
}

function isNumber (v) {
  return typeof v === 'number'
}

var hashStartsWithNumberRE = /^#\d/;

function scrollToPosition (shouldScroll, position) {
  var isObject = typeof shouldScroll === 'object';
  if (isObject && typeof shouldScroll.selector === 'string') {
    // getElementById would still fail if the selector contains a more complicated query like #main[data-attr]
    // but at the same time, it doesn't make much sense to select an element with an id and an extra selector
    var el = hashStartsWithNumberRE.test(shouldScroll.selector) // $flow-disable-line
      ? document.getElementById(shouldScroll.selector.slice(1)) // $flow-disable-line
      : document.querySelector(shouldScroll.selector);

    if (el) {
      var offset =
        shouldScroll.offset && typeof shouldScroll.offset === 'object'
          ? shouldScroll.offset
          : {};
      offset = normalizeOffset(offset);
      position = getElementPosition(el, offset);
    } else if (isValidPosition(shouldScroll)) {
      position = normalizePosition(shouldScroll);
    }
  } else if (isObject && isValidPosition(shouldScroll)) {
    position = normalizePosition(shouldScroll);
  }

  if (position) {
    // $flow-disable-line
    if ('scrollBehavior' in document.documentElement.style) {
      window.scrollTo({
        left: position.x,
        top: position.y,
        // $flow-disable-line
        behavior: shouldScroll.behavior
      });
    } else {
      window.scrollTo(position.x, position.y);
    }
  }
}

/*  */

var supportsPushState =
  inBrowser &&
  (function () {
    var ua = window.navigator.userAgent;

    if (
      (ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) &&
      ua.indexOf('Mobile Safari') !== -1 &&
      ua.indexOf('Chrome') === -1 &&
      ua.indexOf('Windows Phone') === -1
    ) {
      return false
    }

    return window.history && typeof window.history.pushState === 'function'
  })();

function pushState (url, replace) {
  saveScrollPosition();
  // try...catch the pushState call to get around Safari
  // DOM Exception 18 where it limits to 100 pushState calls
  var history = window.history;
  try {
    if (replace) {
      // preserve existing history state as it could be overriden by the user
      var stateCopy = extend({}, history.state);
      stateCopy.key = getStateKey();
      history.replaceState(stateCopy, '', url);
    } else {
      history.pushState({ key: setStateKey(genStateKey()) }, '', url);
    }
  } catch (e) {
    window.location[replace ? 'replace' : 'assign'](url);
  }
}

function replaceState (url) {
  pushState(url, true);
}

// When changing thing, also edit router.d.ts
var NavigationFailureType = {
  redirected: 2,
  aborted: 4,
  cancelled: 8,
  duplicated: 16
};

function createNavigationRedirectedError (from, to) {
  return createRouterError(
    from,
    to,
    NavigationFailureType.redirected,
    ("Redirected when going from \"" + (from.fullPath) + "\" to \"" + (stringifyRoute(
      to
    )) + "\" via a navigation guard.")
  )
}

function createNavigationDuplicatedError (from, to) {
  var error = createRouterError(
    from,
    to,
    NavigationFailureType.duplicated,
    ("Avoided redundant navigation to current location: \"" + (from.fullPath) + "\".")
  );
  // backwards compatible with the first introduction of Errors
  error.name = 'NavigationDuplicated';
  return error
}

function createNavigationCancelledError (from, to) {
  return createRouterError(
    from,
    to,
    NavigationFailureType.cancelled,
    ("Navigation cancelled from \"" + (from.fullPath) + "\" to \"" + (to.fullPath) + "\" with a new navigation.")
  )
}

function createNavigationAbortedError (from, to) {
  return createRouterError(
    from,
    to,
    NavigationFailureType.aborted,
    ("Navigation aborted from \"" + (from.fullPath) + "\" to \"" + (to.fullPath) + "\" via a navigation guard.")
  )
}

function createRouterError (from, to, type, message) {
  var error = new Error(message);
  error._isRouter = true;
  error.from = from;
  error.to = to;
  error.type = type;

  return error
}

var propertiesToLog = ['params', 'query', 'hash'];

function stringifyRoute (to) {
  if (typeof to === 'string') { return to }
  if ('path' in to) { return to.path }
  var location = {};
  propertiesToLog.forEach(function (key) {
    if (key in to) { location[key] = to[key]; }
  });
  return JSON.stringify(location, null, 2)
}

function isError (err) {
  return Object.prototype.toString.call(err).indexOf('Error') > -1
}

function isNavigationFailure (err, errorType) {
  return (
    isError(err) &&
    err._isRouter &&
    (errorType == null || err.type === errorType)
  )
}

/*  */

function runQueue (queue, fn, cb) {
  var step = function (index) {
    if (index >= queue.length) {
      cb();
    } else {
      if (queue[index]) {
        fn(queue[index], function () {
          step(index + 1);
        });
      } else {
        step(index + 1);
      }
    }
  };
  step(0);
}

/*  */

function resolveAsyncComponents (matched) {
  return function (to, from, next) {
    var hasAsync = false;
    var pending = 0;
    var error = null;

    flatMapComponents(matched, function (def, _, match, key) {
      // if it's a function and doesn't have cid attached,
      // assume it's an async component resolve function.
      // we are not using Vue's default async resolving mechanism because
      // we want to halt the navigation until the incoming component has been
      // resolved.
      if (typeof def === 'function' && def.cid === undefined) {
        hasAsync = true;
        pending++;

        var resolve = once(function (resolvedDef) {
          if (isESModule(resolvedDef)) {
            resolvedDef = resolvedDef.default;
          }
          // save resolved on async factory in case it's used elsewhere
          def.resolved = typeof resolvedDef === 'function'
            ? resolvedDef
            : _Vue.extend(resolvedDef);
          match.components[key] = resolvedDef;
          pending--;
          if (pending <= 0) {
            next();
          }
        });

        var reject = once(function (reason) {
          var msg = "Failed to resolve async component " + key + ": " + reason;
          process.env.NODE_ENV !== 'production' && warn(false, msg);
          if (!error) {
            error = isError(reason)
              ? reason
              : new Error(msg);
            next(error);
          }
        });

        var res;
        try {
          res = def(resolve, reject);
        } catch (e) {
          reject(e);
        }
        if (res) {
          if (typeof res.then === 'function') {
            res.then(resolve, reject);
          } else {
            // new syntax in Vue 2.3
            var comp = res.component;
            if (comp && typeof comp.then === 'function') {
              comp.then(resolve, reject);
            }
          }
        }
      }
    });

    if (!hasAsync) { next(); }
  }
}

function flatMapComponents (
  matched,
  fn
) {
  return flatten(matched.map(function (m) {
    return Object.keys(m.components).map(function (key) { return fn(
      m.components[key],
      m.instances[key],
      m, key
    ); })
  }))
}

function flatten (arr) {
  return Array.prototype.concat.apply([], arr)
}

var hasSymbol =
  typeof Symbol === 'function' &&
  typeof Symbol.toStringTag === 'symbol';

function isESModule (obj) {
  return obj.__esModule || (hasSymbol && obj[Symbol.toStringTag] === 'Module')
}

// in Webpack 2, require.ensure now also returns a Promise
// so the resolve/reject functions may get called an extra time
// if the user uses an arrow function shorthand that happens to
// return that Promise.
function once (fn) {
  var called = false;
  return function () {
    var args = [], len = arguments.length;
    while ( len-- ) args[ len ] = arguments[ len ];

    if (called) { return }
    called = true;
    return fn.apply(this, args)
  }
}

/*  */

var History = function History (router, base) {
  this.router = router;
  this.base = normalizeBase(base);
  // start with a route object that stands for "nowhere"
  this.current = START;
  this.pending = null;
  this.ready = false;
  this.readyCbs = [];
  this.readyErrorCbs = [];
  this.errorCbs = [];
  this.listeners = [];
};

History.prototype.listen = function listen (cb) {
  this.cb = cb;
};

History.prototype.onReady = function onReady (cb, errorCb) {
  if (this.ready) {
    cb();
  } else {
    this.readyCbs.push(cb);
    if (errorCb) {
      this.readyErrorCbs.push(errorCb);
    }
  }
};

History.prototype.onError = function onError (errorCb) {
  this.errorCbs.push(errorCb);
};

History.prototype.transitionTo = function transitionTo (
  location,
  onComplete,
  onAbort
) {
    var this$1$1 = this;

  var route;
  // catch redirect option https://github.com/vuejs/vue-router/issues/3201
  try {
    route = this.router.match(location, this.current);
  } catch (e) {
    this.errorCbs.forEach(function (cb) {
      cb(e);
    });
    // Exception should still be thrown
    throw e
  }
  var prev = this.current;
  this.confirmTransition(
    route,
    function () {
      this$1$1.updateRoute(route);
      onComplete && onComplete(route);
      this$1$1.ensureURL();
      this$1$1.router.afterHooks.forEach(function (hook) {
        hook && hook(route, prev);
      });

      // fire ready cbs once
      if (!this$1$1.ready) {
        this$1$1.ready = true;
        this$1$1.readyCbs.forEach(function (cb) {
          cb(route);
        });
      }
    },
    function (err) {
      if (onAbort) {
        onAbort(err);
      }
      if (err && !this$1$1.ready) {
        // Initial redirection should not mark the history as ready yet
        // because it's triggered by the redirection instead
        // https://github.com/vuejs/vue-router/issues/3225
        // https://github.com/vuejs/vue-router/issues/3331
        if (!isNavigationFailure(err, NavigationFailureType.redirected) || prev !== START) {
          this$1$1.ready = true;
          this$1$1.readyErrorCbs.forEach(function (cb) {
            cb(err);
          });
        }
      }
    }
  );
};

History.prototype.confirmTransition = function confirmTransition (route, onComplete, onAbort) {
    var this$1$1 = this;

  var current = this.current;
  this.pending = route;
  var abort = function (err) {
    // changed after adding errors with
    // https://github.com/vuejs/vue-router/pull/3047 before that change,
    // redirect and aborted navigation would produce an err == null
    if (!isNavigationFailure(err) && isError(err)) {
      if (this$1$1.errorCbs.length) {
        this$1$1.errorCbs.forEach(function (cb) {
          cb(err);
        });
      } else {
        if (process.env.NODE_ENV !== 'production') {
          warn(false, 'uncaught error during route navigation:');
        }
        console.error(err);
      }
    }
    onAbort && onAbort(err);
  };
  var lastRouteIndex = route.matched.length - 1;
  var lastCurrentIndex = current.matched.length - 1;
  if (
    isSameRoute(route, current) &&
    // in the case the route map has been dynamically appended to
    lastRouteIndex === lastCurrentIndex &&
    route.matched[lastRouteIndex] === current.matched[lastCurrentIndex]
  ) {
    this.ensureURL();
    if (route.hash) {
      handleScroll(this.router, current, route, false);
    }
    return abort(createNavigationDuplicatedError(current, route))
  }

  var ref = resolveQueue(
    this.current.matched,
    route.matched
  );
    var updated = ref.updated;
    var deactivated = ref.deactivated;
    var activated = ref.activated;

  var queue = [].concat(
    // in-component leave guards
    extractLeaveGuards(deactivated),
    // global before hooks
    this.router.beforeHooks,
    // in-component update hooks
    extractUpdateHooks(updated),
    // in-config enter guards
    activated.map(function (m) { return m.beforeEnter; }),
    // async components
    resolveAsyncComponents(activated)
  );

  var iterator = function (hook, next) {
    if (this$1$1.pending !== route) {
      return abort(createNavigationCancelledError(current, route))
    }
    try {
      hook(route, current, function (to) {
        if (to === false) {
          // next(false) -> abort navigation, ensure current URL
          this$1$1.ensureURL(true);
          abort(createNavigationAbortedError(current, route));
        } else if (isError(to)) {
          this$1$1.ensureURL(true);
          abort(to);
        } else if (
          typeof to === 'string' ||
          (typeof to === 'object' &&
            (typeof to.path === 'string' || typeof to.name === 'string'))
        ) {
          // next('/') or next({ path: '/' }) -> redirect
          abort(createNavigationRedirectedError(current, route));
          if (typeof to === 'object' && to.replace) {
            this$1$1.replace(to);
          } else {
            this$1$1.push(to);
          }
        } else {
          // confirm transition and pass on the value
          next(to);
        }
      });
    } catch (e) {
      abort(e);
    }
  };

  runQueue(queue, iterator, function () {
    // wait until async components are resolved before
    // extracting in-component enter guards
    var enterGuards = extractEnterGuards(activated);
    var queue = enterGuards.concat(this$1$1.router.resolveHooks);
    runQueue(queue, iterator, function () {
      if (this$1$1.pending !== route) {
        return abort(createNavigationCancelledError(current, route))
      }
      this$1$1.pending = null;
      onComplete(route);
      if (this$1$1.router.app) {
        this$1$1.router.app.$nextTick(function () {
          handleRouteEntered(route);
        });
      }
    });
  });
};

History.prototype.updateRoute = function updateRoute (route) {
  this.current = route;
  this.cb && this.cb(route);
};

History.prototype.setupListeners = function setupListeners () {
  // Default implementation is empty
};

History.prototype.teardown = function teardown () {
  // clean up event listeners
  // https://github.com/vuejs/vue-router/issues/2341
  this.listeners.forEach(function (cleanupListener) {
    cleanupListener();
  });
  this.listeners = [];

  // reset current history route
  // https://github.com/vuejs/vue-router/issues/3294
  this.current = START;
  this.pending = null;
};

function normalizeBase (base) {
  if (!base) {
    if (inBrowser) {
      // respect <base> tag
      var baseEl = document.querySelector('base');
      base = (baseEl && baseEl.getAttribute('href')) || '/';
      // strip full URL origin
      base = base.replace(/^https?:\/\/[^\/]+/, '');
    } else {
      base = '/';
    }
  }
  // make sure there's the starting slash
  if (base.charAt(0) !== '/') {
    base = '/' + base;
  }
  // remove trailing slash
  return base.replace(/\/$/, '')
}

function resolveQueue (
  current,
  next
) {
  var i;
  var max = Math.max(current.length, next.length);
  for (i = 0; i < max; i++) {
    if (current[i] !== next[i]) {
      break
    }
  }
  return {
    updated: next.slice(0, i),
    activated: next.slice(i),
    deactivated: current.slice(i)
  }
}

function extractGuards (
  records,
  name,
  bind,
  reverse
) {
  var guards = flatMapComponents(records, function (def, instance, match, key) {
    var guard = extractGuard(def, name);
    if (guard) {
      return Array.isArray(guard)
        ? guard.map(function (guard) { return bind(guard, instance, match, key); })
        : bind(guard, instance, match, key)
    }
  });
  return flatten(reverse ? guards.reverse() : guards)
}

function extractGuard (
  def,
  key
) {
  if (typeof def !== 'function') {
    // extend now so that global mixins are applied.
    def = _Vue.extend(def);
  }
  return def.options[key]
}

function extractLeaveGuards (deactivated) {
  return extractGuards(deactivated, 'beforeRouteLeave', bindGuard, true)
}

function extractUpdateHooks (updated) {
  return extractGuards(updated, 'beforeRouteUpdate', bindGuard)
}

function bindGuard (guard, instance) {
  if (instance) {
    return function boundRouteGuard () {
      return guard.apply(instance, arguments)
    }
  }
}

function extractEnterGuards (
  activated
) {
  return extractGuards(
    activated,
    'beforeRouteEnter',
    function (guard, _, match, key) {
      return bindEnterGuard(guard, match, key)
    }
  )
}

function bindEnterGuard (
  guard,
  match,
  key
) {
  return function routeEnterGuard (to, from, next) {
    return guard(to, from, function (cb) {
      if (typeof cb === 'function') {
        if (!match.enteredCbs[key]) {
          match.enteredCbs[key] = [];
        }
        match.enteredCbs[key].push(cb);
      }
      next(cb);
    })
  }
}

/*  */

var HTML5History = /*@__PURE__*/(function (History) {
  function HTML5History (router, base) {
    History.call(this, router, base);

    this._startLocation = getLocation(this.base);
  }

  if ( History ) HTML5History.__proto__ = History;
  HTML5History.prototype = Object.create( History && History.prototype );
  HTML5History.prototype.constructor = HTML5History;

  HTML5History.prototype.setupListeners = function setupListeners () {
    var this$1$1 = this;

    if (this.listeners.length > 0) {
      return
    }

    var router = this.router;
    var expectScroll = router.options.scrollBehavior;
    var supportsScroll = supportsPushState && expectScroll;

    if (supportsScroll) {
      this.listeners.push(setupScroll());
    }

    var handleRoutingEvent = function () {
      var current = this$1$1.current;

      // Avoiding first `popstate` event dispatched in some browsers but first
      // history route not updated since async guard at the same time.
      var location = getLocation(this$1$1.base);
      if (this$1$1.current === START && location === this$1$1._startLocation) {
        return
      }

      this$1$1.transitionTo(location, function (route) {
        if (supportsScroll) {
          handleScroll(router, route, current, true);
        }
      });
    };
    window.addEventListener('popstate', handleRoutingEvent);
    this.listeners.push(function () {
      window.removeEventListener('popstate', handleRoutingEvent);
    });
  };

  HTML5History.prototype.go = function go (n) {
    window.history.go(n);
  };

  HTML5History.prototype.push = function push (location, onComplete, onAbort) {
    var this$1$1 = this;

    var ref = this;
    var fromRoute = ref.current;
    this.transitionTo(location, function (route) {
      pushState(cleanPath(this$1$1.base + route.fullPath));
      handleScroll(this$1$1.router, route, fromRoute, false);
      onComplete && onComplete(route);
    }, onAbort);
  };

  HTML5History.prototype.replace = function replace (location, onComplete, onAbort) {
    var this$1$1 = this;

    var ref = this;
    var fromRoute = ref.current;
    this.transitionTo(location, function (route) {
      replaceState(cleanPath(this$1$1.base + route.fullPath));
      handleScroll(this$1$1.router, route, fromRoute, false);
      onComplete && onComplete(route);
    }, onAbort);
  };

  HTML5History.prototype.ensureURL = function ensureURL (push) {
    if (getLocation(this.base) !== this.current.fullPath) {
      var current = cleanPath(this.base + this.current.fullPath);
      push ? pushState(current) : replaceState(current);
    }
  };

  HTML5History.prototype.getCurrentLocation = function getCurrentLocation () {
    return getLocation(this.base)
  };

  return HTML5History;
}(History));

function getLocation (base) {
  var path = window.location.pathname;
  var pathLowerCase = path.toLowerCase();
  var baseLowerCase = base.toLowerCase();
  // base="/a" shouldn't turn path="/app" into "/a/pp"
  // https://github.com/vuejs/vue-router/issues/3555
  // so we ensure the trailing slash in the base
  if (base && ((pathLowerCase === baseLowerCase) ||
    (pathLowerCase.indexOf(cleanPath(baseLowerCase + '/')) === 0))) {
    path = path.slice(base.length);
  }
  return (path || '/') + window.location.search + window.location.hash
}

/*  */

var HashHistory = /*@__PURE__*/(function (History) {
  function HashHistory (router, base, fallback) {
    History.call(this, router, base);
    // check history fallback deeplinking
    if (fallback && checkFallback(this.base)) {
      return
    }
    ensureSlash();
  }

  if ( History ) HashHistory.__proto__ = History;
  HashHistory.prototype = Object.create( History && History.prototype );
  HashHistory.prototype.constructor = HashHistory;

  // this is delayed until the app mounts
  // to avoid the hashchange listener being fired too early
  HashHistory.prototype.setupListeners = function setupListeners () {
    var this$1$1 = this;

    if (this.listeners.length > 0) {
      return
    }

    var router = this.router;
    var expectScroll = router.options.scrollBehavior;
    var supportsScroll = supportsPushState && expectScroll;

    if (supportsScroll) {
      this.listeners.push(setupScroll());
    }

    var handleRoutingEvent = function () {
      var current = this$1$1.current;
      if (!ensureSlash()) {
        return
      }
      this$1$1.transitionTo(getHash(), function (route) {
        if (supportsScroll) {
          handleScroll(this$1$1.router, route, current, true);
        }
        if (!supportsPushState) {
          replaceHash(route.fullPath);
        }
      });
    };
    var eventType = supportsPushState ? 'popstate' : 'hashchange';
    window.addEventListener(
      eventType,
      handleRoutingEvent
    );
    this.listeners.push(function () {
      window.removeEventListener(eventType, handleRoutingEvent);
    });
  };

  HashHistory.prototype.push = function push (location, onComplete, onAbort) {
    var this$1$1 = this;

    var ref = this;
    var fromRoute = ref.current;
    this.transitionTo(
      location,
      function (route) {
        pushHash(route.fullPath);
        handleScroll(this$1$1.router, route, fromRoute, false);
        onComplete && onComplete(route);
      },
      onAbort
    );
  };

  HashHistory.prototype.replace = function replace (location, onComplete, onAbort) {
    var this$1$1 = this;

    var ref = this;
    var fromRoute = ref.current;
    this.transitionTo(
      location,
      function (route) {
        replaceHash(route.fullPath);
        handleScroll(this$1$1.router, route, fromRoute, false);
        onComplete && onComplete(route);
      },
      onAbort
    );
  };

  HashHistory.prototype.go = function go (n) {
    window.history.go(n);
  };

  HashHistory.prototype.ensureURL = function ensureURL (push) {
    var current = this.current.fullPath;
    if (getHash() !== current) {
      push ? pushHash(current) : replaceHash(current);
    }
  };

  HashHistory.prototype.getCurrentLocation = function getCurrentLocation () {
    return getHash()
  };

  return HashHistory;
}(History));

function checkFallback (base) {
  var location = getLocation(base);
  if (!/^\/#/.test(location)) {
    window.location.replace(cleanPath(base + '/#' + location));
    return true
  }
}

function ensureSlash () {
  var path = getHash();
  if (path.charAt(0) === '/') {
    return true
  }
  replaceHash('/' + path);
  return false
}

function getHash () {
  // We can't use window.location.hash here because it's not
  // consistent across browsers - Firefox will pre-decode it!
  var href = window.location.href;
  var index = href.indexOf('#');
  // empty path
  if (index < 0) { return '' }

  href = href.slice(index + 1);

  return href
}

function getUrl (path) {
  var href = window.location.href;
  var i = href.indexOf('#');
  var base = i >= 0 ? href.slice(0, i) : href;
  return (base + "#" + path)
}

function pushHash (path) {
  if (supportsPushState) {
    pushState(getUrl(path));
  } else {
    window.location.hash = path;
  }
}

function replaceHash (path) {
  if (supportsPushState) {
    replaceState(getUrl(path));
  } else {
    window.location.replace(getUrl(path));
  }
}

/*  */

var AbstractHistory = /*@__PURE__*/(function (History) {
  function AbstractHistory (router, base) {
    History.call(this, router, base);
    this.stack = [];
    this.index = -1;
  }

  if ( History ) AbstractHistory.__proto__ = History;
  AbstractHistory.prototype = Object.create( History && History.prototype );
  AbstractHistory.prototype.constructor = AbstractHistory;

  AbstractHistory.prototype.push = function push (location, onComplete, onAbort) {
    var this$1$1 = this;

    this.transitionTo(
      location,
      function (route) {
        this$1$1.stack = this$1$1.stack.slice(0, this$1$1.index + 1).concat(route);
        this$1$1.index++;
        onComplete && onComplete(route);
      },
      onAbort
    );
  };

  AbstractHistory.prototype.replace = function replace (location, onComplete, onAbort) {
    var this$1$1 = this;

    this.transitionTo(
      location,
      function (route) {
        this$1$1.stack = this$1$1.stack.slice(0, this$1$1.index).concat(route);
        onComplete && onComplete(route);
      },
      onAbort
    );
  };

  AbstractHistory.prototype.go = function go (n) {
    var this$1$1 = this;

    var targetIndex = this.index + n;
    if (targetIndex < 0 || targetIndex >= this.stack.length) {
      return
    }
    var route = this.stack[targetIndex];
    this.confirmTransition(
      route,
      function () {
        var prev = this$1$1.current;
        this$1$1.index = targetIndex;
        this$1$1.updateRoute(route);
        this$1$1.router.afterHooks.forEach(function (hook) {
          hook && hook(route, prev);
        });
      },
      function (err) {
        if (isNavigationFailure(err, NavigationFailureType.duplicated)) {
          this$1$1.index = targetIndex;
        }
      }
    );
  };

  AbstractHistory.prototype.getCurrentLocation = function getCurrentLocation () {
    var current = this.stack[this.stack.length - 1];
    return current ? current.fullPath : '/'
  };

  AbstractHistory.prototype.ensureURL = function ensureURL () {
    // noop
  };

  return AbstractHistory;
}(History));

/*  */



var VueRouter = function VueRouter (options) {
  if ( options === void 0 ) options = {};

  if (process.env.NODE_ENV !== 'production') {
    warn(this instanceof VueRouter, "Router must be called with the new operator.");
  }
  this.app = null;
  this.apps = [];
  this.options = options;
  this.beforeHooks = [];
  this.resolveHooks = [];
  this.afterHooks = [];
  this.matcher = createMatcher(options.routes || [], this);

  var mode = options.mode || 'hash';
  this.fallback =
    mode === 'history' && !supportsPushState && options.fallback !== false;
  if (this.fallback) {
    mode = 'hash';
  }
  if (!inBrowser) {
    mode = 'abstract';
  }
  this.mode = mode;

  switch (mode) {
    case 'history':
      this.history = new HTML5History(this, options.base);
      break
    case 'hash':
      this.history = new HashHistory(this, options.base, this.fallback);
      break
    case 'abstract':
      this.history = new AbstractHistory(this, options.base);
      break
    default:
      if (process.env.NODE_ENV !== 'production') {
        assert(false, ("invalid mode: " + mode));
      }
  }
};

var prototypeAccessors = { currentRoute: { configurable: true } };

VueRouter.prototype.match = function match (raw, current, redirectedFrom) {
  return this.matcher.match(raw, current, redirectedFrom)
};

prototypeAccessors.currentRoute.get = function () {
  return this.history && this.history.current
};

VueRouter.prototype.init = function init (app /* Vue component instance */) {
    var this$1$1 = this;

  process.env.NODE_ENV !== 'production' &&
    assert(
      install.installed,
      "not installed. Make sure to call `Vue.use(VueRouter)` " +
        "before creating root instance."
    );

  this.apps.push(app);

  // set up app destroyed handler
  // https://github.com/vuejs/vue-router/issues/2639
  app.$once('hook:destroyed', function () {
    // clean out app from this.apps array once destroyed
    var index = this$1$1.apps.indexOf(app);
    if (index > -1) { this$1$1.apps.splice(index, 1); }
    // ensure we still have a main app or null if no apps
    // we do not release the router so it can be reused
    if (this$1$1.app === app) { this$1$1.app = this$1$1.apps[0] || null; }

    if (!this$1$1.app) { this$1$1.history.teardown(); }
  });

  // main app previously initialized
  // return as we don't need to set up new history listener
  if (this.app) {
    return
  }

  this.app = app;

  var history = this.history;

  if (history instanceof HTML5History || history instanceof HashHistory) {
    var handleInitialScroll = function (routeOrError) {
      var from = history.current;
      var expectScroll = this$1$1.options.scrollBehavior;
      var supportsScroll = supportsPushState && expectScroll;

      if (supportsScroll && 'fullPath' in routeOrError) {
        handleScroll(this$1$1, routeOrError, from, false);
      }
    };
    var setupListeners = function (routeOrError) {
      history.setupListeners();
      handleInitialScroll(routeOrError);
    };
    history.transitionTo(
      history.getCurrentLocation(),
      setupListeners,
      setupListeners
    );
  }

  history.listen(function (route) {
    this$1$1.apps.forEach(function (app) {
      app._route = route;
    });
  });
};

VueRouter.prototype.beforeEach = function beforeEach (fn) {
  return registerHook(this.beforeHooks, fn)
};

VueRouter.prototype.beforeResolve = function beforeResolve (fn) {
  return registerHook(this.resolveHooks, fn)
};

VueRouter.prototype.afterEach = function afterEach (fn) {
  return registerHook(this.afterHooks, fn)
};

VueRouter.prototype.onReady = function onReady (cb, errorCb) {
  this.history.onReady(cb, errorCb);
};

VueRouter.prototype.onError = function onError (errorCb) {
  this.history.onError(errorCb);
};

VueRouter.prototype.push = function push (location, onComplete, onAbort) {
    var this$1$1 = this;

  // $flow-disable-line
  if (!onComplete && !onAbort && typeof Promise !== 'undefined') {
    return new Promise(function (resolve, reject) {
      this$1$1.history.push(location, resolve, reject);
    })
  } else {
    this.history.push(location, onComplete, onAbort);
  }
};

VueRouter.prototype.replace = function replace (location, onComplete, onAbort) {
    var this$1$1 = this;

  // $flow-disable-line
  if (!onComplete && !onAbort && typeof Promise !== 'undefined') {
    return new Promise(function (resolve, reject) {
      this$1$1.history.replace(location, resolve, reject);
    })
  } else {
    this.history.replace(location, onComplete, onAbort);
  }
};

VueRouter.prototype.go = function go (n) {
  this.history.go(n);
};

VueRouter.prototype.back = function back () {
  this.go(-1);
};

VueRouter.prototype.forward = function forward () {
  this.go(1);
};

VueRouter.prototype.getMatchedComponents = function getMatchedComponents (to) {
  var route = to
    ? to.matched
      ? to
      : this.resolve(to).route
    : this.currentRoute;
  if (!route) {
    return []
  }
  return [].concat.apply(
    [],
    route.matched.map(function (m) {
      return Object.keys(m.components).map(function (key) {
        return m.components[key]
      })
    })
  )
};

VueRouter.prototype.resolve = function resolve (
  to,
  current,
  append
) {
  current = current || this.history.current;
  var location = normalizeLocation(to, current, append, this);
  var route = this.match(location, current);
  var fullPath = route.redirectedFrom || route.fullPath;
  var base = this.history.base;
  var href = createHref(base, fullPath, this.mode);
  return {
    location: location,
    route: route,
    href: href,
    // for backwards compat
    normalizedTo: location,
    resolved: route
  }
};

VueRouter.prototype.getRoutes = function getRoutes () {
  return this.matcher.getRoutes()
};

VueRouter.prototype.addRoute = function addRoute (parentOrRoute, route) {
  this.matcher.addRoute(parentOrRoute, route);
  if (this.history.current !== START) {
    this.history.transitionTo(this.history.getCurrentLocation());
  }
};

VueRouter.prototype.addRoutes = function addRoutes (routes) {
  if (process.env.NODE_ENV !== 'production') {
    warn(false, 'router.addRoutes() is deprecated and has been removed in Vue Router 4. Use router.addRoute() instead.');
  }
  this.matcher.addRoutes(routes);
  if (this.history.current !== START) {
    this.history.transitionTo(this.history.getCurrentLocation());
  }
};

Object.defineProperties( VueRouter.prototype, prototypeAccessors );

var VueRouter$1 = VueRouter;

function registerHook (list, fn) {
  list.push(fn);
  return function () {
    var i = list.indexOf(fn);
    if (i > -1) { list.splice(i, 1); }
  }
}

function createHref (base, fullPath, mode) {
  var path = mode === 'hash' ? '#' + fullPath : fullPath;
  return base ? cleanPath(base + '/' + path) : path
}

// We cannot remove this as it would be a breaking change
VueRouter.install = install;
VueRouter.version = '3.6.5';
VueRouter.isNavigationFailure = isNavigationFailure;
VueRouter.NavigationFailureType = NavigationFailureType;
VueRouter.START_LOCATION = START;

if (inBrowser && window.Vue) {
  window.Vue.use(VueRouter);
}

module.exports = VueRouter$1;


================================================
FILE: dist/vue-router.esm.browser.js
================================================
/*!
  * vue-router v3.6.5
  * (c) 2022 Evan You
  * @license MIT
  */
/*  */

function assert (condition, message) {
  if (!condition) {
    throw new Error(`[vue-router] ${message}`)
  }
}

function warn (condition, message) {
  if (!condition) {
    typeof console !== 'undefined' && console.warn(`[vue-router] ${message}`);
  }
}

function extend (a, b) {
  for (const key in b) {
    a[key] = b[key];
  }
  return a
}

/*  */

const encodeReserveRE = /[!'()*]/g;
const encodeReserveReplacer = c => '%' + c.charCodeAt(0).toString(16);
const commaRE = /%2C/g;

// fixed encodeURIComponent which is more conformant to RFC3986:
// - escapes [!'()*]
// - preserve commas
const encode = str =>
  encodeURIComponent(str)
    .replace(encodeReserveRE, encodeReserveReplacer)
    .replace(commaRE, ',');

function decode (str) {
  try {
    return decodeURIComponent(str)
  } catch (err) {
    {
      warn(false, `Error decoding "${str}". Leaving it intact.`);
    }
  }
  return str
}

function resolveQuery (
  query,
  extraQuery = {},
  _parseQuery
) {
  const parse = _parseQuery || parseQuery;
  let parsedQuery;
  try {
    parsedQuery = parse(query || '');
  } catch (e) {
    warn(false, e.message);
    parsedQuery = {};
  }
  for (const key in extraQuery) {
    const value = extraQuery[key];
    parsedQuery[key] = Array.isArray(value)
      ? value.map(castQueryParamValue)
      : castQueryParamValue(value);
  }
  return parsedQuery
}

const castQueryParamValue = value => (value == null || typeof value === 'object' ? value : String(value));

function parseQuery (query) {
  const res = {};

  query = query.trim().replace(/^(\?|#|&)/, '');

  if (!query) {
    return res
  }

  query.split('&').forEach(param => {
    const parts = param.replace(/\+/g, ' ').split('=');
    const key = decode(parts.shift());
    const val = parts.length > 0 ? decode(parts.join('=')) : null;

    if (res[key] === undefined) {
      res[key] = val;
    } else if (Array.isArray(res[key])) {
      res[key].push(val);
    } else {
      res[key] = [res[key], val];
    }
  });

  return res
}

function stringifyQuery (obj) {
  const res = obj
    ? Object.keys(obj)
      .map(key => {
        const val = obj[key];

        if (val === undefined) {
          return ''
        }

        if (val === null) {
          return encode(key)
        }

        if (Array.isArray(val)) {
          const result = [];
          val.forEach(val2 => {
            if (val2 === undefined) {
              return
            }
            if (val2 === null) {
              result.push(encode(key));
            } else {
              result.push(encode(key) + '=' + encode(val2));
            }
          });
          return result.join('&')
        }

        return encode(key) + '=' + encode(val)
      })
      .filter(x => x.length > 0)
      .join('&')
    : null;
  return res ? `?${res}` : ''
}

/*  */

const trailingSlashRE = /\/?$/;

function createRoute (
  record,
  location,
  redirectedFrom,
  router
) {
  const stringifyQuery = router && router.options.stringifyQuery;

  let query = location.query || {};
  try {
    query = clone(query);
  } catch (e) {}

  const route = {
    name: location.name || (record && record.name),
    meta: (record && record.meta) || {},
    path: location.path || '/',
    hash: location.hash || '',
    query,
    params: location.params || {},
    fullPath: getFullPath(location, stringifyQuery),
    matched: record ? formatMatch(record) : []
  };
  if (redirectedFrom) {
    route.redirectedFrom = getFullPath(redirectedFrom, stringifyQuery);
  }
  return Object.freeze(route)
}

function clone (value) {
  if (Array.isArray(value)) {
    return value.map(clone)
  } else if (value && typeof value === 'object') {
    const res = {};
    for (const key in value) {
      res[key] = clone(value[key]);
    }
    return res
  } else {
    return value
  }
}

// the starting route that represents the initial state
const START = createRoute(null, {
  path: '/'
});

function formatMatch (record) {
  const res = [];
  while (record) {
    res.unshift(record);
    record = record.parent;
  }
  return res
}

function getFullPath (
  { path, query = {}, hash = '' },
  _stringifyQuery
) {
  const stringify = _stringifyQuery || stringifyQuery;
  return (path || '/') + stringify(query) + hash
}

function isSameRoute (a, b, onlyPath) {
  if (b === START) {
    return a === b
  } else if (!b) {
    return false
  } else if (a.path && b.path) {
    return a.path.replace(trailingSlashRE, '') === b.path.replace(trailingSlashRE, '') && (onlyPath ||
      a.hash === b.hash &&
      isObjectEqual(a.query, b.query))
  } else if (a.name && b.name) {
    return (
      a.name === b.name &&
      (onlyPath || (
        a.hash === b.hash &&
      isObjectEqual(a.query, b.query) &&
      isObjectEqual(a.params, b.params))
      )
    )
  } else {
    return false
  }
}

function isObjectEqual (a = {}, b = {}) {
  // handle null value #1566
  if (!a || !b) return a === b
  const aKeys = Object.keys(a).sort();
  const bKeys = Object.keys(b).sort();
  if (aKeys.length !== bKeys.length) {
    return false
  }
  return aKeys.every((key, i) => {
    const aVal = a[key];
    const bKey = bKeys[i];
    if (bKey !== key) return false
    const bVal = b[key];
    // query values can be null and undefined
    if (aVal == null || bVal == null) return aVal === bVal
    // check nested equality
    if (typeof aVal === 'object' && typeof bVal === 'object') {
      return isObjectEqual(aVal, bVal)
    }
    return String(aVal) === String(bVal)
  })
}

function isIncludedRoute (current, target) {
  return (
    current.path.replace(trailingSlashRE, '/').indexOf(
      target.path.replace(trailingSlashRE, '/')
    ) === 0 &&
    (!target.hash || current.hash === target.hash) &&
    queryIncludes(current.query, target.query)
  )
}

function queryIncludes (current, target) {
  for (const key in target) {
    if (!(key in current)) {
      return false
    }
  }
  return true
}

function handleRouteEntered (route) {
  for (let i = 0; i < route.matched.length; i++) {
    const record = route.matched[i];
    for (const name in record.instances) {
      const instance = record.instances[name];
      const cbs = record.enteredCbs[name];
      if (!instance || !cbs) continue
      delete record.enteredCbs[name];
      for (let i = 0; i < cbs.length; i++) {
        if (!instance._isBeingDestroyed) cbs[i](instance);
      }
    }
  }
}

var View = {
  name: 'RouterView',
  functional: true,
  props: {
    name: {
      type: String,
      default: 'default'
    }
  },
  render (_, { props, children, parent, data }) {
    // used by devtools to display a router-view badge
    data.routerView = true;

    // directly use parent context's createElement() function
    // so that components rendered by router-view can resolve named slots
    const h = parent.$createElement;
    const name = props.name;
    const route = parent.$route;
    const cache = parent._routerViewCache || (parent._routerViewCache = {});

    // determine current view depth, also check to see if the tree
    // has been toggled inactive but kept-alive.
    let depth = 0;
    let inactive = false;
    while (parent && parent._routerRoot !== parent) {
      const vnodeData = parent.$vnode ? parent.$vnode.data : {};
      if (vnodeData.routerView) {
        depth++;
      }
      if (vnodeData.keepAlive && parent._directInactive && parent._inactive) {
        inactive = true;
      }
      parent = parent.$parent;
    }
    data.routerViewDepth = depth;

    // render previous view if the tree is inactive and kept-alive
    if (inactive) {
      const cachedData = cache[name];
      const cachedComponent = cachedData && cachedData.component;
      if (cachedComponent) {
        // #2301
        // pass props
        if (cachedData.configProps) {
          fillPropsinData(cachedComponent, data, cachedData.route, cachedData.configProps);
        }
        return h(cachedComponent, data, children)
      } else {
        // render previous empty view
        return h()
      }
    }

    const matched = route.matched[depth];
    const component = matched && matched.components[name];

    // render empty node if no matched route or no config component
    if (!matched || !component) {
      cache[name] = null;
      return h()
    }

    // cache component
    cache[name] = { component };

    // attach instance registration hook
    // this will be called in the instance's injected lifecycle hooks
    data.registerRouteInstance = (vm, val) => {
      // val could be undefined for unregistration
      const current = matched.instances[name];
      if (
        (val && current !== vm) ||
        (!val && current === vm)
      ) {
        matched.instances[name] = val;
      }
    }

    // also register instance in prepatch hook
    // in case the same component instance is reused across different routes
    ;(data.hook || (data.hook = {})).prepatch = (_, vnode) => {
      matched.instances[name] = vnode.componentInstance;
    };

    // register instance in init hook
    // in case kept-alive component be actived when routes changed
    data.hook.init = (vnode) => {
      if (vnode.data.keepAlive &&
        vnode.componentInstance &&
        vnode.componentInstance !== matched.instances[name]
      ) {
        matched.instances[name] = vnode.componentInstance;
      }

      // if the route transition has already been confirmed then we weren't
      // able to call the cbs during confirmation as the component was not
      // registered yet, so we call it here.
      handleRouteEntered(route);
    };

    const configProps = matched.props && matched.props[name];
    // save route and configProps in cache
    if (configProps) {
      extend(cache[name], {
        route,
        configProps
      });
      fillPropsinData(component, data, route, configProps);
    }

    return h(component, data, children)
  }
};

function fillPropsinData (component, data, route, configProps) {
  // resolve props
  let propsToPass = data.props = resolveProps(route, configProps);
  if (propsToPass) {
    // clone to prevent mutation
    propsToPass = data.props = extend({}, propsToPass);
    // pass non-declared props as attrs
    const attrs = data.attrs = data.attrs || {};
    for (const key in propsToPass) {
      if (!component.props || !(key in component.props)) {
        attrs[key] = propsToPass[key];
        delete propsToPass[key];
      }
    }
  }
}

function resolveProps (route, config) {
  switch (typeof config) {
    case 'undefined':
      return
    case 'object':
      return config
    case 'function':
      return config(route)
    case 'boolean':
      return config ? route.params : undefined
    default:
      {
        warn(
          false,
          `props in "${route.path}" is a ${typeof config}, ` +
          `expecting an object, function or boolean.`
        );
      }
  }
}

/*  */

function resolvePath (
  relative,
  base,
  append
) {
  const firstChar = relative.charAt(0);
  if (firstChar === '/') {
    return relative
  }

  if (firstChar === '?' || firstChar === '#') {
    return base + relative
  }

  const stack = base.split('/');

  // remove trailing segment if:
  // - not appending
  // - appending to trailing slash (last segment is empty)
  if (!append || !stack[stack.length - 1]) {
    stack.pop();
  }

  // resolve relative path
  const segments = relative.replace(/^\//, '').split('/');
  for (let i = 0; i < segments.length; i++) {
    const segment = segments[i];
    if (segment === '..') {
      stack.pop();
    } else if (segment !== '.') {
      stack.push(segment);
    }
  }

  // ensure leading slash
  if (stack[0] !== '') {
    stack.unshift('');
  }

  return stack.join('/')
}

function parsePath (path) {
  let hash = '';
  let query = '';

  const hashIndex = path.indexOf('#');
  if (hashIndex >= 0) {
    hash = path.slice(hashIndex);
    path = path.slice(0, hashIndex);
  }

  const queryIndex = path.indexOf('?');
  if (queryIndex >= 0) {
    query = path.slice(queryIndex + 1);
    path = path.slice(0, queryIndex);
  }

  return {
    path,
    query,
    hash
  }
}

function cleanPath (path) {
  return path.replace(/\/(?:\s*\/)+/g, '/')
}

var isarray = Array.isArray || function (arr) {
  return Object.prototype.toString.call(arr) == '[object Array]';
};

/**
 * Expose `pathToRegexp`.
 */
var pathToRegexp_1 = pathToRegexp;
var parse_1 = parse;
var compile_1 = compile;
var tokensToFunction_1 = tokensToFunction;
var tokensToRegExp_1 = tokensToRegExp;

/**
 * The main path matching regexp utility.
 *
 * @type {RegExp}
 */
var PATH_REGEXP = new RegExp([
  // Match escaped characters that would otherwise appear in future matches.
  // This allows the user to escape special characters that won't transform.
  '(\\\\.)',
  // Match Express-style parameters and un-named parameters with a prefix
  // and optional suffixes. Matches appear as:
  //
  // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined]
  // "/route(\\d+)"  => [undefined, undefined, undefined, "\d+", undefined, undefined]
  // "/*"            => ["/", undefined, undefined, undefined, undefined, "*"]
  '([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))'
].join('|'), 'g');

/**
 * Parse a string for the raw tokens.
 *
 * @param  {string}  str
 * @param  {Object=} options
 * @return {!Array}
 */
function parse (str, options) {
  var tokens = [];
  var key = 0;
  var index = 0;
  var path = '';
  var defaultDelimiter = options && options.delimiter || '/';
  var res;

  while ((res = PATH_REGEXP.exec(str)) != null) {
    var m = res[0];
    var escaped = res[1];
    var offset = res.index;
    path += str.slice(index, offset);
    index = offset + m.length;

    // Ignore already escaped sequences.
    if (escaped) {
      path += escaped[1];
      continue
    }

    var next = str[index];
    var prefix = res[2];
    var name = res[3];
    var capture = res[4];
    var group = res[5];
    var modifier = res[6];
    var asterisk = res[7];

    // Push the current path onto the tokens.
    if (path) {
      tokens.push(path);
      path = '';
    }

    var partial = prefix != null && next != null && next !== prefix;
    var repeat = modifier === '+' || modifier === '*';
    var optional = modifier === '?' || modifier === '*';
    var delimiter = res[2] || defaultDelimiter;
    var pattern = capture || group;

    tokens.push({
      name: name || key++,
      prefix: prefix || '',
      delimiter: delimiter,
      optional: optional,
      repeat: repeat,
      partial: partial,
      asterisk: !!asterisk,
      pattern: pattern ? escapeGroup(pattern) : (asterisk ? '.*' : '[^' + escapeString(delimiter) + ']+?')
    });
  }

  // Match any characters still remaining.
  if (index < str.length) {
    path += str.substr(index);
  }

  // If the path exists, push it onto the end.
  if (path) {
    tokens.push(path);
  }

  return tokens
}

/**
 * Compile a string to a template function for the path.
 *
 * @param  {string}             str
 * @param  {Object=}            options
 * @return {!function(Object=, Object=)}
 */
function compile (str, options) {
  return tokensToFunction(parse(str, options), options)
}

/**
 * Prettier encoding of URI path segments.
 *
 * @param  {string}
 * @return {string}
 */
function encodeURIComponentPretty (str) {
  return encodeURI(str).replace(/[\/?#]/g, function (c) {
    return '%' + c.charCodeAt(0).toString(16).toUpperCase()
  })
}

/**
 * Encode the asterisk parameter. Similar to `pretty`, but allows slashes.
 *
 * @param  {string}
 * @return {string}
 */
function encodeAsterisk (str) {
  return encodeURI(str).replace(/[?#]/g, function (c) {
    return '%' + c.charCodeAt(0).toString(16).toUpperCase()
  })
}

/**
 * Expose a method for transforming tokens into the path function.
 */
function tokensToFunction (tokens, options) {
  // Compile all the tokens into regexps.
  var matches = new Array(tokens.length);

  // Compile all the patterns before compilation.
  for (var i = 0; i < tokens.length; i++) {
    if (typeof tokens[i] === 'object') {
      matches[i] = new RegExp('^(?:' + tokens[i].pattern + ')$', flags(options));
    }
  }

  return function (obj, opts) {
    var path = '';
    var data = obj || {};
    var options = opts || {};
    var encode = options.pretty ? encodeURIComponentPretty : encodeURIComponent;

    for (var i = 0; i < tokens.length; i++) {
      var token = tokens[i];

      if (typeof token === 'string') {
        path += token;

        continue
      }

      var value = data[token.name];
      var segment;

      if (value == null) {
        if (token.optional) {
          // Prepend partial segment prefixes.
          if (token.partial) {
            path += token.prefix;
          }

          continue
        } else {
          throw new TypeError('Expected "' + token.name + '" to be defined')
        }
      }

      if (isarray(value)) {
        if (!token.repeat) {
          throw new TypeError('Expected "' + token.name + '" to not repeat, but received `' + JSON.stringify(value) + '`')
        }

        if (value.length === 0) {
          if (token.optional) {
            continue
          } else {
            throw new TypeError('Expected "' + token.name + '" to not be empty')
          }
        }

        for (var j = 0; j < value.length; j++) {
          segment = encode(value[j]);

          if (!matches[i].test(segment)) {
            throw new TypeError('Expected all "' + token.name + '" to match "' + token.pattern + '", but received `' + JSON.stringify(segment) + '`')
          }

          path += (j === 0 ? token.prefix : token.delimiter) + segment;
        }

        continue
      }

      segment = token.asterisk ? encodeAsterisk(value) : encode(value);

      if (!matches[i].test(segment)) {
        throw new TypeError('Expected "' + token.name + '" to match "' + token.pattern + '", but received "' + segment + '"')
      }

      path += token.prefix + segment;
    }

    return path
  }
}

/**
 * Escape a regular expression string.
 *
 * @param  {string} str
 * @return {string}
 */
function escapeString (str) {
  return str.replace(/([.+*?=^!:${}()[\]|\/\\])/g, '\\$1')
}

/**
 * Escape the capturing group by escaping special characters and meaning.
 *
 * @param  {string} group
 * @return {string}
 */
function escapeGroup (group) {
  return group.replace(/([=!:$\/()])/g, '\\$1')
}

/**
 * Attach the keys as a property of the regexp.
 *
 * @param  {!RegExp} re
 * @param  {Array}   keys
 * @return {!RegExp}
 */
function attachKeys (re, keys) {
  re.keys = keys;
  return re
}

/**
 * Get the flags for a regexp from the options.
 *
 * @param  {Object} options
 * @return {string}
 */
function flags (options) {
  return options && options.sensitive ? '' : 'i'
}

/**
 * Pull out keys from a regexp.
 *
 * @param  {!RegExp} path
 * @param  {!Array}  keys
 * @return {!RegExp}
 */
function regexpToRegexp (path, keys) {
  // Use a negative lookahead to match only capturing groups.
  var groups = path.source.match(/\((?!\?)/g);

  if (groups) {
    for (var i = 0; i < groups.length; i++) {
      keys.push({
        name: i,
        prefix: null,
        delimiter: null,
        optional: false,
        repeat: false,
        partial: false,
        asterisk: false,
        pattern: null
      });
    }
  }

  return attachKeys(path, keys)
}

/**
 * Transform an array into a regexp.
 *
 * @param  {!Array}  path
 * @param  {Array}   keys
 * @param  {!Object} options
 * @return {!RegExp}
 */
function arrayToRegexp (path, keys, options) {
  var parts = [];

  for (var i = 0; i < path.length; i++) {
    parts.push(pathToRegexp(path[i], keys, options).source);
  }

  var regexp = new RegExp('(?:' + parts.join('|') + ')', flags(options));

  return attachKeys(regexp, keys)
}

/**
 * Create a path regexp from string input.
 *
 * @param  {string}  path
 * @param  {!Array}  keys
 * @param  {!Object} options
 * @return {!RegExp}
 */
function stringToRegexp (path, keys, options) {
  return tokensToRegExp(parse(path, options), keys, options)
}

/**
 * Expose a function for taking tokens and returning a RegExp.
 *
 * @param  {!Array}          tokens
 * @param  {(Array|Object)=} keys
 * @param  {Object=}         options
 * @return {!RegExp}
 */
function tokensToRegExp (tokens, keys, options) {
  if (!isarray(keys)) {
    options = /** @type {!Object} */ (keys || options);
    keys = [];
  }

  options = options || {};

  var strict = options.strict;
  var end = options.end !== false;
  var route = '';

  // Iterate over the tokens and create our regexp string.
  for (var i = 0; i < tokens.length; i++) {
    var token = tokens[i];

    if (typeof token === 'string') {
      route += escapeString(token);
    } else {
      var prefix = escapeString(token.prefix);
      var capture = '(?:' + token.pattern + ')';

      keys.push(token);

      if (token.repeat) {
        capture += '(?:' + prefix + capture + ')*';
      }

      if (token.optional) {
        if (!token.partial) {
          capture = '(?:' + prefix + '(' + capture + '))?';
        } else {
          capture = prefix + '(' + capture + ')?';
        }
      } else {
        capture = prefix + '(' + capture + ')';
      }

      route += capture;
    }
  }

  var delimiter = escapeString(options.delimiter || '/');
  var endsWithDelimiter = route.slice(-delimiter.length) === delimiter;

  // In non-strict mode we allow a slash at the end of match. If the path to
  // match already ends with a slash, we remove it for consistency. The slash
  // is valid at the end of a path match, not in the middle. This is important
  // in non-ending mode, where "/test/" shouldn't match "/test//route".
  if (!strict) {
    route = (endsWithDelimiter ? route.slice(0, -delimiter.length) : route) + '(?:' + delimiter + '(?=$))?';
  }

  if (end) {
    route += '$';
  } else {
    // In non-ending mode, we need the capturing groups to match as much as
    // possible by using a positive lookahead to the end or next path segment.
    route += strict && endsWithDelimiter ? '' : '(?=' + delimiter + '|$)';
  }

  return attachKeys(new RegExp('^' + route, flags(options)), keys)
}

/**
 * Normalize the given path string, returning a regular expression.
 *
 * An empty array can be passed in for the keys, which will hold the
 * placeholder key descriptions. For example, using `/user/:id`, `keys` will
 * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.
 *
 * @param  {(string|RegExp|Array)} path
 * @param  {(Array|Object)=}       keys
 * @param  {Object=}               options
 * @return {!RegExp}
 */
function pathToRegexp (path, keys, options) {
  if (!isarray(keys)) {
    options = /** @type {!Object} */ (keys || options);
    keys = [];
  }

  options = options || {};

  if (path instanceof RegExp) {
    return regexpToRegexp(path, /** @type {!Array} */ (keys))
  }

  if (isarray(path)) {
    return arrayToRegexp(/** @type {!Array} */ (path), /** @type {!Array} */ (keys), options)
  }

  return stringToRegexp(/** @type {string} */ (path), /** @type {!Array} */ (keys), options)
}
pathToRegexp_1.parse = parse_1;
pathToRegexp_1.compile = compile_1;
pathToRegexp_1.tokensToFunction = tokensToFunction_1;
pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;

/*  */

// $flow-disable-line
const regexpCompileCache = Object.create(null);

function fillParams (
  path,
  params,
  routeMsg
) {
  params = params || {};
  try {
    const filler =
      regexpCompileCache[path] ||
      (regexpCompileCache[path] = pathToRegexp_1.compile(path));

    // Fix #2505 resolving asterisk routes { name: 'not-found', params: { pathMatch: '/not-found' }}
    // and fix #3106 so that you can work with location descriptor object having params.pathMatch equal to empty string
    if (typeof params.pathMatch === 'string') params[0] = params.pathMatch;

    return filler(params, { pretty: true })
  } catch (e) {
    {
      // Fix #3072 no warn if `pathMatch` is string
      warn(typeof params.pathMatch === 'string', `missing param for ${routeMsg}: ${e.message}`);
    }
    return ''
  } finally {
    // delete the 0 if it was added
    delete params[0];
  }
}

/*  */

function normalizeLocation (
  raw,
  current,
  append,
  router
) {
  let next = typeof raw === 'string' ? { path: raw } : raw;
  // named target
  if (next._normalized) {
    return next
  } else if (next.name) {
    next = extend({}, raw);
    const params = next.params;
    if (params && typeof params === 'object') {
      next.params = extend({}, params);
    }
    return next
  }

  // relative params
  if (!next.path && next.params && current) {
    next = extend({}, next);
    next._normalized = true;
    const params = extend(extend({}, current.params), next.params);
    if (current.name) {
      next.name = current.name;
      next.params = params;
    } else if (current.matched.length) {
      const rawPath = current.matched[current.matched.length - 1].path;
      next.path = fillParams(rawPath, params, `path ${current.path}`);
    } else {
      warn(false, `relative params navigation requires a current route.`);
    }
    return next
  }

  const parsedPath = parsePath(next.path || '');
  const basePath = (current && current.path) || '/';
  const path = parsedPath.path
    ? resolvePath(parsedPath.path, basePath, append || next.append)
    : basePath;

  const query = resolveQuery(
    parsedPath.query,
    next.query,
    router && router.options.parseQuery
  );

  let hash = next.hash || parsedPath.hash;
  if (hash && hash.charAt(0) !== '#') {
    hash = `#${hash}`;
  }

  return {
    _normalized: true,
    path,
    query,
    hash
  }
}

/*  */

// work around weird flow bug
const toTypes = [String, Object];
const eventTypes = [String, Array];

const noop = () => {};

let warnedCustomSlot;
let warnedTagProp;
let warnedEventProp;

var Link = {
  name: 'RouterLink',
  props: {
    to: {
      type: toTypes,
      required: true
    },
    tag: {
      type: String,
      default: 'a'
    },
    custom: Boolean,
    exact: Boolean,
    exactPath: Boolean,
    append: Boolean,
    replace: Boolean,
    activeClass: String,
    exactActiveClass: String,
    ariaCurrentValue: {
      type: String,
      default: 'page'
    },
    event: {
      type: eventTypes,
      default: 'click'
    }
  },
  render (h) {
    const router = this.$router;
    const current = this.$route;
    const { location, route, href } = router.resolve(
      this.to,
      current,
      this.append
    );

    const classes = {};
    const globalActiveClass = router.options.linkActiveClass;
    const globalExactActiveClass = router.options.linkExactActiveClass;
    // Support global empty active class
    const activeClassFallback =
      globalActiveClass == null ? 'router-link-active' : globalActiveClass;
    const exactActiveClassFallback =
      globalExactActiveClass == null
        ? 'router-link-exact-active'
        : globalExactActiveClass;
    const activeClass =
      this.activeClass == null ? activeClassFallback : this.activeClass;
    const exactActiveClass =
      this.exactActiveClass == null
        ? exactActiveClassFallback
        : this.exactActiveClass;

    const compareTarget = route.redirectedFrom
      ? createRoute(null, normalizeLocation(route.redirectedFrom), null, router)
      : route;

    classes[exactActiveClass] = isSameRoute(current, compareTarget, this.exactPath);
    classes[activeClass] = this.exact || this.exactPath
      ? classes[exactActiveClass]
      : isIncludedRoute(current, compareTarget);

    const ariaCurrentValue = classes[exactActiveClass] ? this.ariaCurrentValue : null;

    const handler = e => {
      if (guardEvent(e)) {
        if (this.replace) {
          router.replace(location, noop);
        } else {
          router.push(location, noop);
        }
      }
    };

    const on = { click: guardEvent };
    if (Array.isArray(this.event)) {
      this.event.forEach(e => {
        on[e] = handler;
      });
    } else {
      on[this.event] = handler;
    }

    const data = { class: classes };

    const scopedSlot =
      !this.$scopedSlots.$hasNormal &&
      this.$scopedSlots.default &&
      this.$scopedSlots.default({
        href,
        route,
        navigate: handler,
        isActive: classes[activeClass],
        isExactActive: classes[exactActiveClass]
      });

    if (scopedSlot) {
      if (!this.custom) {
        !warnedCustomSlot && warn(false, 'In Vue Router 4, the v-slot API will by default wrap its content with an <a> element. Use the custom prop to remove this warning:\n<router-link v-slot="{ navigate, href }" custom></router-link>\n');
        warnedCustomSlot = true;
      }
      if (scopedSlot.length === 1) {
        return scopedSlot[0]
      } else if (scopedSlot.length > 1 || !scopedSlot.length) {
        {
          warn(
            false,
            `<router-link> with to="${
              this.to
            }" is trying to use a scoped slot but it didn't provide exactly one child. Wrapping the content with a span element.`
          );
        }
        return scopedSlot.length === 0 ? h() : h('span', {}, scopedSlot)
      }
    }

    {
      if ('tag' in this.$options.propsData && !warnedTagProp) {
        warn(
          false,
          `<router-link>'s tag prop is deprecated and has been removed in Vue Router 4. Use the v-slot API to remove this warning: https://next.router.vuejs.org/guide/migration/#removal-of-event-and-tag-props-in-router-link.`
        );
        warnedTagProp = true;
      }
      if ('event' in this.$options.propsData && !warnedEventProp) {
        warn(
          false,
          `<router-link>'s event prop is deprecated and has been removed in Vue Router 4. Use the v-slot API to remove this warning: https://next.router.vuejs.org/guide/migration/#removal-of-event-and-tag-props-in-router-link.`
        );
        warnedEventProp = true;
      }
    }

    if (this.tag === 'a') {
      data.on = on;
      data.attrs = { href, 'aria-current': ariaCurrentValue };
    } else {
      // find the first <a> child and apply listener and href
      const a = findAnchor(this.$slots.default);
      if (a) {
        // in case the <a> is a static node
        a.isStatic = false;
        const aData = (a.data = extend({}, a.data));
        aData.on = aData.on || {};
        // transform existing events in both objects into arrays so we can push later
        for (const event in aData.on) {
          const handler = aData.on[event];
          if (event in on) {
            aData.on[event] = Array.isArray(handler) ? handler : [handler];
          }
        }
        // append new listeners for router-link
        for (const event in on) {
          if (event in aData.on) {
            // on[event] is always a function
            aData.on[event].push(on[event]);
          } else {
            aData.on[event] = handler;
          }
        }

        const aAttrs = (a.data.attrs = extend({}, a.data.attrs));
        aAttrs.href = href;
        aAttrs['aria-current'] = ariaCurrentValue;
      } else {
        // doesn't have <a> child, apply listener to self
        data.on = on;
      }
    }

    return h(this.tag, data, this.$slots.default)
  }
};

function guardEvent (e) {
  // don't redirect with control keys
  if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return
  // don't redirect when preventDefault called
  if (e.defaultPrevented) return
  // don't redirect on right click
  if (e.button !== undefined && e.button !== 0) return
  // don't redirect if `target="_blank"`
  if (e.currentTarget && e.currentTarget.getAttribute) {
    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 findAnchor (children) {
  if (children) {
    let child;
    for (let i = 0; i < children.length; i++) {
      child = children[i];
      if (child.tag === 'a') {
        return child
      }
      if (child.children && (child = findAnchor(child.children))) {
        return child
      }
    }
  }
}

let _Vue;

function install (Vue) {
  if (install.installed && _Vue === Vue) return
  install.installed = true;

  _Vue = Vue;

  const isDef = v => v !== undefined;

  const registerInstance = (vm, callVal) => {
    let i = vm.$options._parentVnode;
    if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
      i(vm, callVal);
    }
  };

  Vue.mixin({
    beforeCreate () {
      if (isDef(this.$options.router)) {
        this._routerRoot = this;
        this._router = this.$options.router;
        this._router.init(this);
        Vue.util.defineReactive(this, '_route', this._router.history.current);
      } else {
        this._routerRoot = (this.$parent && this.$parent._routerRoot) || this;
      }
      registerInstance(this, this);
    },
    destroyed () {
      registerInstance(this);
    }
  });

  Object.defineProperty(Vue.prototype, '$router', {
    get () { return this._routerRoot._router }
  });

  Object.defineProperty(Vue.prototype, '$route', {
    get () { return this._routerRoot._route }
  });

  Vue.component('RouterView', View);
  Vue.component('RouterLink', Link);

  const strats = Vue.config.optionMergeStrategies;
  // use the same hook merging strategy for route hooks
  strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created;
}

/*  */

const inBrowser = typeof window !== 'undefined';

/*  */

function createRouteMap (
  routes,
  oldPathList,
  oldPathMap,
  oldNameMap,
  parentRoute
) {
  // the path list is used to control path matching priority
  const pathList = oldPathList || [];
  // $flow-disable-line
  const pathMap = oldPathMap || Object.create(null);
  // $flow-disable-line
  const nameMap = oldNameMap || Object.create(null);

  routes.forEach(route => {
    addRouteRecord(pathList, pathMap, nameMap, route, parentRoute);
  });

  // ensure wildcard routes are always at the end
  for (let i = 0, l = pathList.length; i < l; i++) {
    if (pathList[i] === '*') {
      pathList.push(pathList.splice(i, 1)[0]);
      l--;
      i--;
    }
  }

  {
    // warn if routes do not include leading slashes
    const found = pathList
    // check for missing leading slash
      .filter(path => path && path.charAt(0) !== '*' && path.charAt(0) !== '/');

    if (found.length > 0) {
      const pathNames = found.map(path => `- ${path}`).join('\n');
      warn(false, `Non-nested routes must include a leading slash character. Fix the following routes: \n${pathNames}`);
    }
  }

  return {
    pathList,
    pathMap,
    nameMap
  }
}

function addRouteRecord (
  pathList,
  pathMap,
  nameMap,
  route,
  parent,
  matchAs
) {
  const { path, name } = route;
  {
    assert(path != null, `"path" is required in a route configuration.`);
    assert(
      typeof route.component !== 'string',
      `route config "component" for path: ${String(
        path || name
      )} cannot be a ` + `string id. Use an actual component instead.`
    );

    warn(
      // eslint-disable-next-line no-control-regex
      !/[^\u0000-\u007F]+/.test(path),
      `Route with path "${path}" contains unencoded characters, make sure ` +
        `your path is correctly encoded before passing it to the router. Use ` +
        `encodeURI to encode static segments of your path.`
    );
  }

  const pathToRegexpOptions =
    route.pathToRegexpOptions || {};
  const normalizedPath = normalizePath(path, parent, pathToRegexpOptions.strict);

  if (typeof route.caseSensitive === 'boolean') {
    pathToRegexpOptions.sensitive = route.caseSensitive;
  }

  const record = {
    path: normalizedPath,
    regex: compileRouteRegex(normalizedPath, pathToRegexpOptions),
    components: route.components || { default: route.component },
    alias: route.alias
      ? typeof route.alias === 'string'
        ? [route.alias]
        : route.alias
      : [],
    instances: {},
    enteredCbs: {},
    name,
    parent,
    matchAs,
    redirect: route.redirect,
    beforeEnter: route.beforeEnter,
    meta: route.meta || {},
    props:
      route.props == null
        ? {}
        : route.components
          ? route.props
          : { default: route.props }
  };

  if (route.children) {
    // Warn if route is named, does not redirect and has a default child route.
    // If users navigate to this route by name, the default child will
    // not be rendered (GH Issue #629)
    {
      if (
        route.name &&
        !route.redirect &&
        route.children.some(child => /^\/?$/.test(child.path))
      ) {
        warn(
          false,
          `Named Route '${route.name}' has a default child route. ` +
            `When navigating to this named route (:to="{name: '${
              route.name
            }'}"), ` +
            `the default child route will not be rendered. Remove the name from ` +
            `this route and use the name of the default child route for named ` +
            `links instead.`
        );
      }
    }
    route.children.forEach(child => {
      const childMatchAs = matchAs
        ? cleanPath(`${matchAs}/${child.path}`)
        : undefined;
      addRouteRecord(pathList, pathMap, nameMap, child, record, childMatchAs);
    });
  }

  if (!pathMap[record.path]) {
    pathList.push(record.path);
    pathMap[record.path] = record;
  }

  if (route.alias !== undefined) {
    const aliases = Array.isArray(route.alias) ? route.alias : [route.alias];
    for (let i = 0; i < aliases.length; ++i) {
      const alias = aliases[i];
      if (alias === path) {
        warn(
          false,
          `Found an alias with the same value as the path: "${path}". You have to remove that alias. It will be ignored in development.`
        );
        // skip in dev to make it work
        continue
      }

      const aliasRoute = {
        path: alias,
        children: route.children
      };
      addRouteRecord(
        pathList,
        pathMap,
        nameMap,
        aliasRoute,
        parent,
        record.path || '/' // matchAs
      );
    }
  }

  if (name) {
    if (!nameMap[name]) {
      nameMap[name] = record;
    } else if (!matchAs) {
      warn(
        false,
        `Duplicate named routes definition: ` +
          `{ name: "${name}", path: "${record.path}" }`
      );
    }
  }
}

function compileRouteRegex (
  path,
  pathToRegexpOptions
) {
  const regex = pathToRegexp_1(path, [], pathToRegexpOptions);
  {
    const keys = Object.create(null);
    regex.keys.forEach(key => {
      warn(
        !keys[key.name],
        `Duplicate param keys in route with path: "${path}"`
      );
      keys[key.name] = true;
    });
  }
  return regex
}

function normalizePath (
  path,
  parent,
  strict
) {
  if (!strict) path = path.replace(/\/$/, '');
  if (path[0] === '/') return path
  if (parent == null) return path
  return cleanPath(`${parent.path}/${path}`)
}

/*  */



function createMatcher (
  routes,
  router
) {
  const { pathList, pathMap, nameMap } = createRouteMap(routes);

  function addRoutes (routes) {
    createRouteMap(routes, pathList, pathMap, nameMap);
  }

  function addRoute (parentOrRoute, route) {
    const parent = (typeof parentOrRoute !== 'object') ? nameMap[parentOrRoute] : undefined;
    // $flow-disable-line
    createRouteMap([route || parentOrRoute], pathList, pathMap, nameMap, parent);

    // add aliases of parent
    if (parent && parent.alias.length) {
      createRouteMap(
        // $flow-disable-line route is defined if parent is
        parent.alias.map(alias => ({ path: alias, children: [route] })),
        pathList,
        pathMap,
        nameMap,
        parent
      );
    }
  }

  function getRoutes () {
    return pathList.map(path => pathMap[path])
  }

  function match (
    raw,
    currentRoute,
    redirectedFrom
  ) {
    const location = normalizeLocation(raw, currentRoute, false, router);
    const { name } = location;

    if (name) {
      const record = nameMap[name];
      {
        warn(record, `Route with name '${name}' does not exist`);
      }
      if (!record) return _createRoute(null, location)
      const paramNames = record.regex.keys
        .filter(key => !key.optional)
        .map(key => key.name);

      if (typeof location.params !== 'object') {
        location.params = {};
      }

      if (currentRoute && typeof currentRoute.params === 'object') {
        for (const key in currentRoute.params) {
          if (!(key in location.params) && paramNames.indexOf(key) > -1) {
            location.params[key] = currentRoute.params[key];
          }
        }
      }

      location.path = fillParams(record.path, location.params, `named route "${name}"`);
      return _createRoute(record, location, redirectedFrom)
    } else if (location.path) {
      location.params = {};
      for (let i = 0; i < pathList.length; i++) {
        const path = pathList[i];
        const record = pathMap[path];
        if (matchRoute(record.regex, location.path, location.params)) {
          return _createRoute(record, location, redirectedFrom)
        }
      }
    }
    // no match
    return _createRoute(null, location)
  }

  function redirect (
    record,
    location
  ) {
    const originalRedirect = record.redirect;
    let redirect = typeof originalRedirect === 'function'
      ? originalRedirect(createRoute(record, location, null, router))
      : originalRedirect;

    if (typeof redirect === 'string') {
      redirect = { path: redirect };
    }

    if (!redirect || typeof redirect !== 'object') {
      {
        warn(
          false, `invalid redirect option: ${JSON.stringify(redirect)}`
        );
      }
      return _createRoute(null, location)
    }

    const re = redirect;
    const { name, path } = re;
    let { query, hash, params } = location;
    query = re.hasOwnProperty('query') ? re.query : query;
    hash = re.hasOwnProperty('hash') ? re.hash : hash;
    params = re.hasOwnProperty('params') ? re.params : params;

    if (name) {
      // resolved named direct
      const targetRecord = nameMap[name];
      {
        assert(targetRecord, `redirect failed: named route "${name}" not found.`);
      }
      return match({
        _normalized: true,
        name,
        query,
        hash,
        params
      }, undefined, location)
    } else if (path) {
      // 1. resolve relative redirect
      const rawPath = resolveRecordPath(path, record);
      // 2. resolve params
      const resolvedPath = fillParams(rawPath, params, `redirect route with path "${rawPath}"`);
      // 3. rematch with existing query and hash
      return match({
        _normalized: true,
        path: resolvedPath,
        query,
        hash
      }, undefined, location)
    } else {
      {
        warn(false, `invalid redirect option: ${JSON.stringify(redirect)}`);
      }
      return _createRoute(null, location)
    }
  }

  function alias (
    record,
    location,
    matchAs
  ) {
    const aliasedPath = fillParams(matchAs, location.params, `aliased route with path "${matchAs}"`);
    const aliasedMatch = match({
      _normalized: true,
      path: aliasedPath
    });
    if (aliasedMatch) {
      const matched = aliasedMatch.matched;
      const aliasedRecord = matched[matched.length - 1];
      location.params = aliasedMatch.params;
      return _createRoute(aliasedRecord, location)
    }
    return _createRoute(null, location)
  }

  function _createRoute (
    record,
    location,
    redirectedFrom
  ) {
    if (record && record.redirect) {
      return redirect(record, redirectedFrom || location)
    }
    if (record && record.matchAs) {
      return alias(record, location, record.matchAs)
    }
    return createRoute(record, location, redirectedFrom, router)
  }

  return {
    match,
    addRoute,
    getRoutes,
    addRoutes
  }
}

function matchRoute (
  regex,
  path,
  params
) {
  const m = path.match(regex);

  if (!m) {
    return false
  } else if (!params) {
    return true
  }

  for (let i = 1, len = m.length; i < len; ++i) {
    const key = regex.keys[i - 1];
    if (key) {
      // Fix #1994: using * with props: true generates a param named 0
      params[key.name || 'pathMatch'] = typeof m[i] === 'string' ? decode(m[i]) : m[i];
    }
  }

  return true
}

function resolveRecordPath (path, record) {
  return resolvePath(path, record.parent ? record.parent.path : '/', true)
}

/*  */

// use User Timing api (if present) for more accurate key precision
const Time =
  inBrowser && window.performance && window.performance.now
    ? window.performance
    : Date;

function genStateKey () {
  return Time.now().toFixed(3)
}

let _key = genStateKey();

function getStateKey () {
  return _key
}

function setStateKey (key) {
  return (_key = key)
}

/*  */

const positionStore = Object.create(null);

function setupScroll () {
  // Prevent browser scroll behavior on History popstate
  if ('scrollRestoration' in window.history) {
    window.history.scrollRestoration = 'manual';
  }
  // Fix for #1585 for Firefox
  // Fix for #2195 Add optional third attribute to workaround a bug in safari https://bugs.webkit.org/show_bug.cgi?id=182678
  // Fix for #2774 Support for apps loaded from Windows file shares not mapped to network drives: replaced location.origin with
  // window.location.protocol + '//' + window.location.host
  // location.host contains the port and location.hostname doesn't
  const protocolAndPath = window.location.protocol + '//' + window.location.host;
  const absolutePath = window.location.href.replace(protocolAndPath, '');
  // preserve existing history state as it could be overriden by the user
  const stateCopy = extend({}, window.history.state);
  stateCopy.key = getStateKey();
  window.history.replaceState(stateCopy, '', absolutePath);
  window.addEventListener('popstate', handlePopState);
  return () => {
    window.removeEventListener('popstate', handlePopState);
  }
}

function handleScroll (
  router,
  to,
  from,
  isPop
) {
  if (!router.app) {
    return
  }

  const behavior = router.options.scrollBehavior;
  if (!behavior) {
    return
  }

  {
    assert(typeof behavior === 'function', `scrollBehavior must be a function`);
  }

  // wait until re-render finishes before scrolling
  router.app.$nextTick(() => {
    const position = getScrollPosition();
    const shouldScroll = behavior.call(
      router,
      to,
      from,
      isPop ? position : null
    );

    if (!shouldScroll) {
      return
    }

    if (typeof shouldScroll.then === 'function') {
      shouldScroll
        .then(shouldScroll => {
          scrollToPosition((shouldScroll), position);
        })
        .catch(err => {
          {
            assert(false, err.toString());
          }
        });
    } else {
      scrollToPosition(shouldScroll, position);
    }
  });
}

function saveScrollPosition () {
  const key = getStateKey();
  if (key) {
    positionStore[key] = {
      x: window.pageXOffset,
      y: window.pageYOffset
    };
  }
}

function handlePopState (e) {
  saveScrollPosition();
  if (e.state && e.state.key) {
    setStateKey(e.state.key);
  }
}

function getScrollPosition () {
  const key = getStateKey();
  if (key) {
    return positionStore[key]
  }
}

function getElementPosition (el, offset) {
  const docEl = document.documentElement;
  const docRect = docEl.getBoundingClientRect();
  const elRect = el.getBoundingClientRect();
  return {
    x: elRect.left - docRect.left - offset.x,
    y: elRect.top - docRect.top - offset.y
  }
}

function isValidPosition (obj) {
  return isNumber(obj.x) || isNumber(obj.y)
}

function normalizePosition (obj) {
  return {
    x: isNumber(obj.x) ? obj.x : window.pageXOffset,
    y: isNumber(obj.y) ? obj.y : window.pageYOffset
  }
}

function normalizeOffset (obj) {
  return {
    x: isNumber(obj.x) ? obj.x : 0,
    y: isNumber(obj.y) ? obj.y : 0
  }
}

function isNumber (v) {
  return typeof v === 'number'
}

const hashStartsWithNumberRE = /^#\d/;

function scrollToPosition (shouldScroll, position) {
  const isObject = typeof shouldScroll === 'object';
  if (isObject && typeof shouldScroll.selector === 'string') {
    // getElementById would still fail if the selector contains a more complicated query like #main[data-attr]
    // but at the same time, it doesn't make much sense to select an element with an id and an extra selector
    const el = hashStartsWithNumberRE.test(shouldScroll.selector) // $flow-disable-line
      ? document.getElementById(shouldScroll.selector.slice(1)) // $flow-disable-line
      : document.querySelector(shouldScroll.selector);

    if (el) {
      let offset =
        shouldScroll.offset && typeof shouldScroll.offset === 'object'
          ? shouldScroll.offset
          : {};
      offset = normalizeOffset(offset);
      position = getElementPosition(el, offset);
    } else if (isValidPosition(shouldScroll)) {
      position = normalizePosition(shouldScroll);
    }
  } else if (isObject && isValidPosition(shouldScroll)) {
    position = normalizePosition(shouldScroll);
  }

  if (position) {
    // $flow-disable-line
    if ('scrollBehavior' in document.documentElement.style) {
      window.scrollTo({
        left: position.x,
        top: position.y,
        // $flow-disable-line
        behavior: shouldScroll.behavior
      });
    } else {
      window.scrollTo(position.x, position.y);
    }
  }
}

/*  */

const supportsPushState =
  inBrowser &&
  (function () {
    const ua = window.navigator.userAgent;

    if (
      (ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) &&
      ua.indexOf('Mobile Safari') !== -1 &&
      ua.indexOf('Chrome') === -1 &&
      ua.indexOf('Windows Phone') === -1
    ) {
      return false
    }

    return window.history && typeof window.history.pushState === 'function'
  })();

function pushState (url, replace) {
  saveScrollPosition();
  // try...catch the pushState call to get around Safari
  // DOM Exception 18 where it limits to 100 pushState calls
  const history = window.history;
  try {
    if (replace) {
      // preserve existing history state as it could be overriden by the user
      const stateCopy = extend({}, history.state);
      stateCopy.key = getStateKey();
      history.replaceState(stateCopy, '', url);
    } else {
      history.pushState({ key: setStateKey(genStateKey()) }, '', url);
    }
  } catch (e) {
    window.location[replace ? 'replace' : 'assign'](url);
  }
}

function replaceState (url) {
  pushState(url, true);
}

// When changing thing, also edit router.d.ts
const NavigationFailureType = {
  redirected: 2,
  aborted: 4,
  cancelled: 8,
  duplicated: 16
};

function createNavigationRedirectedError (from, to) {
  return createRouterError(
    from,
    to,
    NavigationFailureType.redirected,
    `Redirected when going from "${from.fullPath}" to "${stringifyRoute(
      to
    )}" via a navigation guard.`
  )
}

function createNavigationDuplicatedError (from, to) {
  const error = createRouterError(
    from,
    to,
    NavigationFailureType.duplicated,
    `Avoided redundant navigation to current location: "${from.fullPath}".`
  );
  // backwards compatible with the first introduction of Errors
  error.name = 'NavigationDuplicated';
  return error
}

function createNavigationCancelledError (from, to) {
  return createRouterError(
    from,
    to,
    NavigationFailureType.cancelled,
    `Navigation cancelled from "${from.fullPath}" to "${
      to.fullPath
    }" with a new navigation.`
  )
}

function createNavigationAbortedError (from, to) {
  return createRouterError(
    from,
    to,
    NavigationFailureType.aborted,
    `Navigation aborted from "${from.fullPath}" to "${
      to.fullPath
    }" via a navigation guard.`
  )
}

function createRouterError (from, to, type, message) {
  const error = new Error(message);
  error._isRouter = true;
  error.from = from;
  error.to = to;
  error.type = type;

  return error
}

const propertiesToLog = ['params', 'query', 'hash'];

function stringifyRoute (to) {
  if (typeof to === 'string') return to
  if ('path' in to) return to.path
  const location = {};
  propertiesToLog.forEach(key => {
    if (key in to) location[key] = to[key];
  });
  return JSON.stringify(location, null, 2)
}

function isError (err) {
  return Object.prototype.toString.call(err).indexOf('Error') > -1
}

function isNavigationFailure (err, errorType) {
  return (
    isError(err) &&
    err._isRouter &&
    (errorType == null || err.type === errorType)
  )
}

/*  */

function runQueue (queue, fn, cb) {
  const step = index => {
    if (index >= queue.length) {
      cb();
    } else {
      if (queue[index]) {
        fn(queue[index], () => {
          step(index + 1);
        });
      } else {
        step(index + 1);
      }
    }
  };
  step(0);
}

/*  */

function resolveAsyncComponents (matched) {
  return (to, from, next) => {
    let hasAsync = false;
    let pending = 0;
    let error = null;

    flatMapComponents(matched, (def, _, match, key) => {
      // if it's a function and doesn't have cid attached,
      // assume it's an async component resolve function.
      // we are not using Vue's default async resolving mechanism because
      // we want to halt the navigation until the incoming component has been
      // resolved.
      if (typeof def === 'function' && def.cid === undefined) {
        hasAsync = true;
        pending++;

        const resolve = once(resolvedDef => {
          if (isESModule(resolvedDef)) {
            resolvedDef = resolvedDef.default;
          }
          // save resolved on async factory in case it's used elsewhere
          def.resolved = typeof resolvedDef === 'function'
            ? resolvedDef
            : _Vue.extend(resolvedDef);
          match.components[key] = resolvedDef;
          pending--;
          if (pending <= 0) {
            next();
          }
        });

        const reject = once(reason => {
          const msg = `Failed to resolve async component ${key}: ${reason}`;
          warn(false, msg);
          if (!error) {
            error = isError(reason)
              ? reason
              : new Error(msg);
            next(error);
          }
        });

        let res;
        try {
          res = def(resolve, reject);
        } catch (e) {
          reject(e);
        }
        if (res) {
          if (typeof res.then === 'function') {
            res.then(resolve, reject);
          } else {
            // new syntax in Vue 2.3
            const comp = res.component;
            if (comp && typeof comp.then === 'function') {
              comp.then(resolve, reject);
            }
          }
        }
      }
    });

    if (!hasAsync) next();
  }
}

function flatMapComponents (
  matched,
  fn
) {
  return flatten(matched.map(m => {
    return Object.keys(m.components).map(key => fn(
      m.components[key],
      m.instances[key],
      m, key
    ))
  }))
}

function flatten (arr) {
  return Array.prototype.concat.apply([], arr)
}

const hasSymbol =
  typeof Symbol === 'function' &&
  typeof Symbol.toStringTag === 'symbol';

function isESModule (obj) {
  return obj.__esModule || (hasSymbol && obj[Symbol.toStringTag] === 'Module')
}

// in Webpack 2, require.ensure now also returns a Promise
// so the resolve/reject functions may get called an extra time
// if the user uses an arrow function shorthand that happens to
// return that Promise.
function once (fn) {
  let called = false;
  return function (...args) {
    if (called) return
    called = true;
    return fn.apply(this, args)
  }
}

/*  */

class History {
  
  
  
  
  
  
  
  
  
  
  

  // implemented by sub-classes
  
  
  
  
  
  

  constructor (router, base) {
    this.router = router;
 
Download .txt
gitextract_7kypz9ur/

├── .babelrc
├── .circleci/
│   └── config.yml
├── .eslintignore
├── .eslintrc
├── .flowconfig
├── .github/
│   ├── ISSUE_TEMPLATE.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── funding.yml
│   └── workflows/
│       └── release-tag.yml
├── .gitignore
├── .prettierrc
├── CHANGELOG.md
├── LICENSE
├── README.md
├── build/
│   ├── build.js
│   ├── configs.js
│   └── rollup.dev.config.js
├── composables.d.ts
├── composables.js
├── composables.mjs
├── dist/
│   ├── vue-router.common.js
│   ├── vue-router.esm.browser.js
│   ├── vue-router.esm.js
│   ├── vue-router.js
│   └── vue-router.mjs
├── docs/
│   ├── .vuepress/
│   │   ├── components/
│   │   │   ├── HomeSponsors.vue
│   │   │   ├── HomeSponsorsGroup.vue
│   │   │   └── sponsors.json
│   │   ├── config.js
│   │   ├── public/
│   │   │   └── _redirects
│   │   ├── styles/
│   │   │   └── index.styl
│   │   └── theme/
│   │       ├── Layout.vue
│   │       ├── components/
│   │       │   ├── BuySellAds.vue
│   │       │   ├── CarbonAds.vue
│   │       │   └── VueSchool/
│   │       │       └── BannerTop.vue
│   │       └── index.js
│   ├── README.md
│   ├── api/
│   │   └── README.md
│   ├── fr/
│   │   ├── README.md
│   │   ├── api/
│   │   │   └── README.md
│   │   ├── guide/
│   │   │   ├── README.md
│   │   │   ├── advanced/
│   │   │   │   ├── data-fetching.md
│   │   │   │   ├── lazy-loading.md
│   │   │   │   ├── meta.md
│   │   │   │   ├── navigation-guards.md
│   │   │   │   ├── scroll-behavior.md
│   │   │   │   └── transitions.md
│   │   │   └── essentials/
│   │   │       ├── dynamic-matching.md
│   │   │       ├── history-mode.md
│   │   │       ├── named-routes.md
│   │   │       ├── named-views.md
│   │   │       ├── navigation.md
│   │   │       ├── nested-routes.md
│   │   │       ├── passing-props.md
│   │   │       └── redirect-and-alias.md
│   │   └── installation.md
│   ├── guide/
│   │   ├── README.md
│   │   ├── advanced/
│   │   │   ├── data-fetching.md
│   │   │   ├── lazy-loading.md
│   │   │   ├── meta.md
│   │   │   ├── navigation-failures.md
│   │   │   ├── navigation-guards.md
│   │   │   ├── scroll-behavior.md
│   │   │   └── transitions.md
│   │   └── essentials/
│   │       ├── dynamic-matching.md
│   │       ├── history-mode.md
│   │       ├── named-routes.md
│   │       ├── named-views.md
│   │       ├── navigation.md
│   │       ├── nested-routes.md
│   │       ├── passing-props.md
│   │       └── redirect-and-alias.md
│   ├── installation.md
│   ├── ja/
│   │   ├── README.md
│   │   ├── api/
│   │   │   └── README.md
│   │   ├── guide/
│   │   │   ├── README.md
│   │   │   ├── advanced/
│   │   │   │   ├── data-fetching.md
│   │   │   │   ├── lazy-loading.md
│   │   │   │   ├── meta.md
│   │   │   │   ├── navigation-failures.md
│   │   │   │   ├── navigation-guards.md
│   │   │   │   ├── scroll-behavior.md
│   │   │   │   └── transitions.md
│   │   │   └── essentials/
│   │   │       ├── dynamic-matching.md
│   │   │       ├── history-mode.md
│   │   │       ├── named-routes.md
│   │   │       ├── named-views.md
│   │   │       ├── navigation.md
│   │   │       ├── nested-routes.md
│   │   │       ├── passing-props.md
│   │   │       └── redirect-and-alias.md
│   │   └── installation.md
│   ├── kr/
│   │   ├── README.md
│   │   ├── api/
│   │   │   └── README.md
│   │   ├── guide/
│   │   │   ├── README.md
│   │   │   ├── advanced/
│   │   │   │   ├── data-fetching.md
│   │   │   │   ├── lazy-loading.md
│   │   │   │   ├── meta.md
│   │   │   │   ├── navigation-guards.md
│   │   │   │   ├── scroll-behavior.md
│   │   │   │   └── transitions.md
│   │   │   └── essentials/
│   │   │       ├── dynamic-matching.md
│   │   │       ├── getting-started.md
│   │   │       ├── history-mode.md
│   │   │       ├── named-routes.md
│   │   │       ├── named-views.md
│   │   │       ├── navigation.md
│   │   │       ├── nested-routes.md
│   │   │       ├── passing-props.md
│   │   │       └── redirect-and-alias.md
│   │   └── installation.md
│   ├── ru/
│   │   ├── README.md
│   │   ├── api/
│   │   │   └── README.md
│   │   ├── guide/
│   │   │   ├── README.md
│   │   │   ├── advanced/
│   │   │   │   ├── data-fetching.md
│   │   │   │   ├── lazy-loading.md
│   │   │   │   ├── meta.md
│   │   │   │   ├── navigation-failures.md
│   │   │   │   ├── navigation-guards.md
│   │   │   │   ├── scroll-behavior.md
│   │   │   │   └── transitions.md
│   │   │   └── essentials/
│   │   │       ├── dynamic-matching.md
│   │   │       ├── history-mode.md
│   │   │       ├── named-routes.md
│   │   │       ├── named-views.md
│   │   │       ├── navigation.md
│   │   │       ├── nested-routes.md
│   │   │       ├── passing-props.md
│   │   │       └── redirect-and-alias.md
│   │   └── installation.md
│   └── zh/
│       ├── README.md
│       ├── api/
│       │   └── README.md
│       ├── guide/
│       │   ├── README.md
│       │   ├── advanced/
│       │   │   ├── data-fetching.md
│       │   │   ├── lazy-loading.md
│       │   │   ├── meta.md
│       │   │   ├── navigation-failures.md
│       │   │   ├── navigation-guards.md
│       │   │   ├── scroll-behavior.md
│       │   │   └── transitions.md
│       │   └── essentials/
│       │       ├── dynamic-matching.md
│       │       ├── history-mode.md
│       │       ├── named-routes.md
│       │       ├── named-views.md
│       │       ├── navigation.md
│       │       ├── nested-routes.md
│       │       ├── passing-props.md
│       │       └── redirect-and-alias.md
│       └── installation.md
├── docs-gitbook/
│   ├── LANGS.md
│   ├── assets/
│   │   ├── CNAME
│   │   └── circle.yml
│   ├── book.json
│   ├── de/
│   │   ├── SUMMARY.md
│   │   ├── advanced/
│   │   │   ├── data-fetching.md
│   │   │   ├── lazy-loading.md
│   │   │   ├── meta.md
│   │   │   ├── navigation-guards.md
│   │   │   ├── scroll-behavior.md
│   │   │   └── transitions.md
│   │   ├── api/
│   │   │   ├── component-injections.md
│   │   │   ├── options.md
│   │   │   ├── route-object.md
│   │   │   ├── router-instance.md
│   │   │   ├── router-link.md
│   │   │   └── router-view.md
│   │   ├── essentials/
│   │   │   ├── dynamic-matching.md
│   │   │   ├── getting-started.md
│   │   │   ├── history-mode.md
│   │   │   ├── named-routes.md
│   │   │   ├── named-views.md
│   │   │   ├── navigation.md
│   │   │   ├── nested-routes.md
│   │   │   └── redirect-and-alias.md
│   │   └── installation.md
│   ├── es/
│   │   ├── README.md
│   │   ├── SUMMARY.md
│   │   ├── advanced/
│   │   │   ├── data-fetching.md
│   │   │   ├── lazy-loading.md
│   │   │   ├── meta.md
│   │   │   ├── navigation-guards.md
│   │   │   ├── scroll-behavior.md
│   │   │   └── transitions.md
│   │   ├── api/
│   │   │   ├── component-injections.md
│   │   │   ├── options.md
│   │   │   ├── route-object.md
│   │   │   ├── router-instance.md
│   │   │   ├── router-link.md
│   │   │   └── router-view.md
│   │   ├── essentials/
│   │   │   ├── dynamic-matching.md
│   │   │   ├── getting-started.md
│   │   │   ├── history-mode.md
│   │   │   ├── named-routes.md
│   │   │   ├── named-views.md
│   │   │   ├── navigation.md
│   │   │   ├── nested-routes.md
│   │   │   ├── passing-props.md
│   │   │   └── redirect-and-alias.md
│   │   └── installation.md
│   ├── fr/
│   │   ├── README.md
│   │   ├── SUMMARY.md
│   │   ├── advanced/
│   │   │   ├── data-fetching.md
│   │   │   ├── lazy-loading.md
│   │   │   ├── meta.md
│   │   │   ├── navigation-guards.md
│   │   │   ├── scroll-behavior.md
│   │   │   └── transitions.md
│   │   ├── api/
│   │   │   ├── component-injections.md
│   │   │   ├── options.md
│   │   │   ├── route-object.md
│   │   │   ├── router-instance.md
│   │   │   ├── router-link.md
│   │   │   └── router-view.md
│   │   ├── essentials/
│   │   │   ├── dynamic-matching.md
│   │   │   ├── getting-started.md
│   │   │   ├── history-mode.md
│   │   │   ├── named-routes.md
│   │   │   ├── named-views.md
│   │   │   ├── navigation.md
│   │   │   ├── nested-routes.md
│   │   │   ├── passing-props.md
│   │   │   └── redirect-and-alias.md
│   │   └── installation.md
│   ├── ja/
│   │   ├── README.md
│   │   ├── SUMMARY.md
│   │   ├── advanced/
│   │   │   ├── data-fetching.md
│   │   │   ├── lazy-loading.md
│   │   │   ├── meta.md
│   │   │   ├── navigation-guards.md
│   │   │   ├── scroll-behavior.md
│   │   │   └── transitions.md
│   │   ├── api/
│   │   │   ├── component-injections.md
│   │   │   ├── options.md
│   │   │   ├── route-object.md
│   │   │   ├── router-instance.md
│   │   │   ├── router-link.md
│   │   │   └── router-view.md
│   │   ├── essentials/
│   │   │   ├── dynamic-matching.md
│   │   │   ├── getting-started.md
│   │   │   ├── history-mode.md
│   │   │   ├── named-routes.md
│   │   │   ├── named-views.md
│   │   │   ├── navigation.md
│   │   │   ├── nested-routes.md
│   │   │   ├── passing-props.md
│   │   │   └── redirect-and-alias.md
│   │   └── installation.md
│   ├── kr/
│   │   ├── README.md
│   │   ├── SUMMARY.md
│   │   ├── advanced/
│   │   │   ├── data-fetching.md
│   │   │   ├── lazy-loading.md
│   │   │   ├── meta.md
│   │   │   ├── navigation-guards.md
│   │   │   ├── scroll-behavior.md
│   │   │   └── transitions.md
│   │   ├── api/
│   │   │   ├── component-injections.md
│   │   │   ├── options.md
│   │   │   ├── route-object.md
│   │   │   ├── router-instance.md
│   │   │   ├── router-link.md
│   │   │   └── router-view.md
│   │   ├── essentials/
│   │   │   ├── dynamic-matching.md
│   │   │   ├── getting-started.md
│   │   │   ├── history-mode.md
│   │   │   ├── named-routes.md
│   │   │   ├── named-views.md
│   │   │   ├── navigation.md
│   │   │   ├── nested-routes.md
│   │   │   ├── passing-props.md
│   │   │   └── redirect-and-alias.md
│   │   └── installation.md
│   ├── old/
│   │   ├── README.md
│   │   └── SUMMARY.md
│   └── ru/
│       ├── README.md
│       ├── SUMMARY.md
│       ├── advanced/
│       │   ├── data-fetching.md
│       │   ├── lazy-loading.md
│       │   ├── meta.md
│       │   ├── navigation-guards.md
│       │   ├── scroll-behavior.md
│       │   └── transitions.md
│       ├── api/
│       │   ├── component-injections.md
│       │   ├── options.md
│       │   ├── route-object.md
│       │   ├── router-instance.md
│       │   ├── router-link.md
│       │   └── router-view.md
│       ├── essentials/
│       │   ├── dynamic-matching.md
│       │   ├── getting-started.md
│       │   ├── history-mode.md
│       │   ├── named-routes.md
│       │   ├── named-views.md
│       │   ├── navigation.md
│       │   ├── nested-routes.md
│       │   ├── passing-props.md
│       │   └── redirect-and-alias.md
│       └── installation.md
├── examples/
│   ├── active-links/
│   │   ├── app.js
│   │   └── index.html
│   ├── auth-flow/
│   │   ├── app.js
│   │   ├── auth.js
│   │   ├── components/
│   │   │   ├── About.vue
│   │   │   ├── App.vue
│   │   │   ├── Dashboard.vue
│   │   │   └── Login.vue
│   │   └── index.html
│   ├── basic/
│   │   ├── app.js
│   │   └── index.html
│   ├── composables/
│   │   ├── app.js
│   │   └── index.html
│   ├── data-fetching/
│   │   ├── Post.vue
│   │   ├── api.js
│   │   ├── app.js
│   │   └── index.html
│   ├── discrete-components/
│   │   ├── app.js
│   │   └── index.html
│   ├── global.css
│   ├── hash-mode/
│   │   ├── app.js
│   │   └── index.html
│   ├── hash-scroll-behavior/
│   │   ├── app.js
│   │   └── index.html
│   ├── index.html
│   ├── keepalive-view/
│   │   ├── app.js
│   │   └── index.html
│   ├── lazy-loading/
│   │   ├── Bar.vue
│   │   ├── Baz.vue
│   │   ├── Foo.vue
│   │   ├── app.js
│   │   └── index.html
│   ├── lazy-loading-before-mount/
│   │   ├── app.js
│   │   └── index.html
│   ├── multi-app/
│   │   ├── app.js
│   │   └── index.html
│   ├── named-routes/
│   │   ├── app.js
│   │   └── index.html
│   ├── named-views/
│   │   ├── app.js
│   │   └── index.html
│   ├── navigation-guards/
│   │   ├── app.js
│   │   └── index.html
│   ├── nested-router/
│   │   ├── app.js
│   │   └── index.html
│   ├── nested-routes/
│   │   ├── app.js
│   │   └── index.html
│   ├── redirect/
│   │   ├── app.js
│   │   └── index.html
│   ├── restart-app/
│   │   ├── app.js
│   │   └── index.html
│   ├── route-alias/
│   │   ├── app.js
│   │   └── index.html
│   ├── route-matching/
│   │   ├── app.js
│   │   └── index.html
│   ├── route-params/
│   │   ├── app.js
│   │   └── index.html
│   ├── route-props/
│   │   ├── Hello.vue
│   │   ├── app.js
│   │   └── index.html
│   ├── router-errors/
│   │   ├── app.js
│   │   └── index.html
│   ├── scroll-behavior/
│   │   ├── app.js
│   │   └── index.html
│   ├── server.js
│   ├── transitions/
│   │   ├── app.js
│   │   └── index.html
│   └── webpack.config.js
├── flow/
│   └── declarations.js
├── netlify.toml
├── package.json
├── scripts/
│   ├── release.sh
│   └── verifyCommitMsg.js
├── src/
│   ├── components/
│   │   ├── link.js
│   │   └── view.js
│   ├── composables/
│   │   ├── globals.js
│   │   ├── guards.js
│   │   ├── index.js
│   │   ├── useLink.js
│   │   └── utils.js
│   ├── create-matcher.js
│   ├── create-route-map.js
│   ├── entries/
│   │   ├── cjs.js
│   │   └── esm.js
│   ├── history/
│   │   ├── abstract.js
│   │   ├── base.js
│   │   ├── hash.js
│   │   └── html5.js
│   ├── index.js
│   ├── install.js
│   ├── router.js
│   └── util/
│       ├── async.js
│       ├── dom.js
│       ├── errors.js
│       ├── location.js
│       ├── misc.js
│       ├── params.js
│       ├── path.js
│       ├── push-state.js
│       ├── query.js
│       ├── resolve-components.js
│       ├── route.js
│       ├── scroll.js
│       ├── state-key.js
│       └── warn.js
├── test/
│   ├── .eslintrc
│   ├── e2e/
│   │   ├── .eslintrc
│   │   ├── browserstack-send-status.js
│   │   ├── nightwatch.browserstack.js
│   │   ├── nightwatch.config.js
│   │   ├── runner.js
│   │   └── specs/
│   │       ├── .prettierrc
│   │       ├── active-links.js
│   │       ├── auth-flow.js
│   │       ├── basic.js
│   │       ├── composables.js
│   │       ├── data-fetching.js
│   │       ├── hash-mode.js
│   │       ├── hash-scroll-behavior.js
│   │       ├── history-state.js
│   │       ├── keepalive-view.js
│   │       ├── lazy-loading-before-mount.js
│   │       ├── lazy-loading.js
│   │       ├── multi-app.js
│   │       ├── named-routes.js
│   │       ├── named-views.js
│   │       ├── navigation-guards.js
│   │       ├── nested-router.js
│   │       ├── nested-routes.js
│   │       ├── redirect.js
│   │       ├── restart-app.js
│   │       ├── route-alias.js
│   │       ├── route-matching.js
│   │       ├── route-params.js
│   │       ├── route-props.js
│   │       ├── scroll-behavior.js
│   │       └── transitions.js
│   └── unit/
│       ├── .eslintrc
│       ├── jasmine.json
│       └── specs/
│           ├── abstract-history.spec.js
│           ├── api.spec.js
│           ├── async.spec.js
│           ├── create-map.spec.js
│           ├── create-matcher.spec.js
│           ├── custom-query.spec.js
│           ├── discrete-components.spec.js
│           ├── error-handling.spec.js
│           ├── location.spec.js
│           ├── node.spec.js
│           ├── onReady.spec.js
│           ├── path.spec.js
│           ├── query.spec.js
│           └── route.spec.js
├── types/
│   ├── composables.d.ts
│   ├── index.d.ts
│   ├── router.d.ts
│   ├── test/
│   │   ├── index.ts
│   │   ├── meta.ts
│   │   └── tsconfig.json
│   └── vue.d.ts
└── vetur/
    ├── attributes.json
    └── tags.json
Download .txt
SYMBOL INDEX (740 symbols across 53 files)

FILE: build/build.js
  function build (line 14) | function build (builds) {
  function buildEntry (line 31) | function buildEntry ({ input, output }) {
  function write (line 59) | function write (dest, code, zip) {
  function getSize (line 85) | function getSize (code) {
  function logError (line 89) | function logError (e) {
  function blue (line 93) | function blue (str) {

FILE: build/configs.js
  function genConfig (line 68) | function genConfig (opts) {

FILE: composables.js
  function throwNoCurrentInstance (line 14) | function throwNoCurrentInstance (method) {
  function useRouter (line 22) | function useRouter () {
  function useRoute (line 30) | function useRoute () {
  function onBeforeRouteUpdate (line 49) | function onBeforeRouteUpdate (guard) {
  function isUpdateNavigation (line 56) | function isUpdateNavigation (to, from, depth) {
  function isLeaveNavigation (line 67) | function isLeaveNavigation (to, from, depth) {
  function onBeforeRouteLeave (line 73) | function onBeforeRouteLeave (guard) {
  function useFilteredGuard (line 82) | function useFilteredGuard (guard, fn) {
  function guardEvent (line 116) | function guardEvent (e) {
  function includesParams (line 135) | function includesParams (outer, inner) {
  function isSameRouteLocationParamsValue (line 163) | function isSameRouteLocationParamsValue (a, b) {
  function isEquivalentArray (line 171) | function isEquivalentArray (a, b) {
  function isSameRouteLocationParams (line 177) | function isSameRouteLocationParams (a, b) {
  function useLink (line 187) | function useLink (props) {

FILE: composables.mjs
  function throwNoCurrentInstance (line 10) | function throwNoCurrentInstance (method) {
  function useRouter (line 18) | function useRouter () {
  function useRoute (line 26) | function useRoute () {
  function onBeforeRouteUpdate (line 45) | function onBeforeRouteUpdate (guard) {
  function isUpdateNavigation (line 52) | function isUpdateNavigation (to, from, depth) {
  function isLeaveNavigation (line 63) | function isLeaveNavigation (to, from, depth) {
  function onBeforeRouteLeave (line 69) | function onBeforeRouteLeave (guard) {
  function useFilteredGuard (line 78) | function useFilteredGuard (guard, fn) {
  function guardEvent (line 112) | function guardEvent (e) {
  function includesParams (line 131) | function includesParams (outer, inner) {
  function isSameRouteLocationParamsValue (line 159) | function isSameRouteLocationParamsValue (a, b) {
  function isEquivalentArray (line 167) | function isEquivalentArray (a, b) {
  function isSameRouteLocationParams (line 173) | function isSameRouteLocationParams (a, b) {
  function useLink (line 183) | function useLink (props) {

FILE: dist/vue-router.common.js
  function assert (line 10) | function assert (condition, message) {
  function warn (line 16) | function warn (condition, message) {
  function extend (line 22) | function extend (a, b) {
  function decode (line 42) | function decode (str) {
  function resolveQuery (line 53) | function resolveQuery (
  function parseQuery (line 79) | function parseQuery (query) {
  function stringifyQuery (line 105) | function stringifyQuery (obj) {
  function createRoute (line 146) | function createRoute (
  function clone (line 175) | function clone (value) {
  function formatMatch (line 194) | function formatMatch (record) {
  function getFullPath (line 203) | function getFullPath (
  function isSameRoute (line 215) | function isSameRoute (a, b, onlyPath) {
  function isObjectEqual (line 238) | function isObjectEqual (a, b) {
  function isIncludedRoute (line 264) | function isIncludedRoute (current, target) {
  function queryIncludes (line 274) | function queryIncludes (current, target) {
  function handleRouteEntered (line 283) | function handleRouteEntered (route) {
  function fillPropsinData (line 417) | function fillPropsinData (component, data, route, configProps) {
  function resolveProps (line 434) | function resolveProps (route, config) {
  function resolvePath (line 457) | function resolvePath (
  function parsePath (line 499) | function parsePath (path) {
  function cleanPath (line 522) | function cleanPath (path) {
  function parse (line 564) | function parse (str, options) {
  function compile (line 637) | function compile (str, options) {
  function encodeURIComponentPretty (line 647) | function encodeURIComponentPretty (str) {
  function encodeAsterisk (line 659) | function encodeAsterisk (str) {
  function tokensToFunction (line 668) | function tokensToFunction (tokens, options) {
  function escapeString (line 755) | function escapeString (str) {
  function escapeGroup (line 765) | function escapeGroup (group) {
  function attachKeys (line 776) | function attachKeys (re, keys) {
  function flags (line 787) | function flags (options) {
  function regexpToRegexp (line 798) | function regexpToRegexp (path, keys) {
  function arrayToRegexp (line 828) | function arrayToRegexp (path, keys, options) {
  function stringToRegexp (line 848) | function stringToRegexp (path, keys, options) {
  function tokensToRegExp (line 860) | function tokensToRegExp (tokens, keys, options) {
  function pathToRegexp (line 936) | function pathToRegexp (path, keys, options) {
  function fillParams (line 964) | function fillParams (
  function normalizeLocation (line 994) | function normalizeLocation (
  function guardEvent (line 1244) | function guardEvent (e) {
  function findAnchor (line 1263) | function findAnchor (children) {
  function install (line 1280) | function install (Vue) {
  function createRouteMap (line 1334) | function createRouteMap (
  function addRouteRecord (line 1380) | function addRouteRecord (
  function compileRouteRegex (line 1515) | function compileRouteRegex (
  function normalizePath (line 1533) | function normalizePath (
  function createMatcher (line 1548) | function createMatcher (
  function matchRoute (line 1735) | function matchRoute (
  function resolveRecordPath (line 1759) | function resolveRecordPath (path, record) {
  function genStateKey (line 1771) | function genStateKey () {
  function getStateKey (line 1777) | function getStateKey () {
  function setStateKey (line 1781) | function setStateKey (key) {
  function setupScroll (line 1789) | function setupScroll () {
  function handleScroll (line 1811) | function handleScroll (
  function saveScrollPosition (line 1860) | function saveScrollPosition () {
  function handlePopState (line 1870) | function handlePopState (e) {
  function getScrollPosition (line 1877) | function getScrollPosition () {
  function getElementPosition (line 1884) | function getElementPosition (el, offset) {
  function isValidPosition (line 1894) | function isValidPosition (obj) {
  function normalizePosition (line 1898) | function normalizePosition (obj) {
  function normalizeOffset (line 1905) | function normalizeOffset (obj) {
  function isNumber (line 1912) | function isNumber (v) {
  function scrollToPosition (line 1918) | function scrollToPosition (shouldScroll, position) {
  function pushState (line 1975) | function pushState (url, replace) {
  function replaceState (line 1994) | function replaceState (url) {
  function createNavigationRedirectedError (line 2006) | function createNavigationRedirectedError (from, to) {
  function createNavigationDuplicatedError (line 2017) | function createNavigationDuplicatedError (from, to) {
  function createNavigationCancelledError (line 2029) | function createNavigationCancelledError (from, to) {
  function createNavigationAbortedError (line 2038) | function createNavigationAbortedError (from, to) {
  function createRouterError (line 2047) | function createRouterError (from, to, type, message) {
  function stringifyRoute (line 2059) | function stringifyRoute (to) {
  function isError (line 2069) | function isError (err) {
  function isNavigationFailure (line 2073) | function isNavigationFailure (err, errorType) {
  function runQueue (line 2083) | function runQueue (queue, fn, cb) {
  function resolveAsyncComponents (line 2102) | function resolveAsyncComponents (matched) {
  function flatMapComponents (line 2168) | function flatMapComponents (
  function flatten (line 2181) | function flatten (arr) {
  function isESModule (line 2189) | function isESModule (obj) {
  function once (line 2197) | function once (fn) {
  function normalizeBase (line 2437) | function normalizeBase (base) {
  function resolveQueue (line 2457) | function resolveQueue (
  function extractGuards (line 2475) | function extractGuards (
  function extractGuard (line 2492) | function extractGuard (
  function extractLeaveGuards (line 2503) | function extractLeaveGuards (deactivated) {
  function extractUpdateHooks (line 2507) | function extractUpdateHooks (updated) {
  function bindGuard (line 2511) | function bindGuard (guard, instance) {
  function extractEnterGuards (line 2519) | function extractEnterGuards (
  function bindEnterGuard (line 2531) | function bindEnterGuard (
  function HTML5History (line 2552) | function HTML5History (router, base) {
  function getLocation (line 2641) | function getLocation (base) {
  function HashHistory (line 2658) | function HashHistory (router, base, fallback) {
  function checkFallback (line 2762) | function checkFallback (base) {
  function ensureSlash (line 2770) | function ensureSlash () {
  function getHash (line 2779) | function getHash () {
  function getUrl (line 2792) | function getUrl (path) {
  function pushHash (line 2799) | function pushHash (path) {
  function replaceHash (line 2807) | function replaceHash (path) {
  function AbstractHistory (line 2818) | function AbstractHistory (router, base) {
  function registerHook (line 3135) | function registerHook (list, fn) {
  function createHref (line 3143) | function createHref (base, fullPath, mode) {

FILE: dist/vue-router.esm.browser.js
  function assert (line 8) | function assert (condition, message) {
  function warn (line 14) | function warn (condition, message) {
  function extend (line 20) | function extend (a, b) {
  function decode (line 41) | function decode (str) {
  function resolveQuery (line 52) | function resolveQuery (
  function parseQuery (line 76) | function parseQuery (query) {
  function stringifyQuery (line 102) | function stringifyQuery (obj) {
  function createRoute (line 143) | function createRoute (
  function clone (line 172) | function clone (value) {
  constant START (line 187) | const START = createRoute(null, {
  function formatMatch (line 191) | function formatMatch (record) {
  function getFullPath (line 200) | function getFullPath (
  function isSameRoute (line 208) | function isSameRoute (a, b, onlyPath) {
  function isObjectEqual (line 231) | function isObjectEqual (a = {}, b = {}) {
  function isIncludedRoute (line 254) | function isIncludedRoute (current, target) {
  function queryIncludes (line 264) | function queryIncludes (current, target) {
  function handleRouteEntered (line 273) | function handleRouteEntered (route) {
  method render (line 297) | render (_, { props, children, parent, data }) {
  function fillPropsinData (line 402) | function fillPropsinData (component, data, route, configProps) {
  function resolveProps (line 419) | function resolveProps (route, config) {
  function resolvePath (line 442) | function resolvePath (
  function parsePath (line 484) | function parsePath (path) {
  function cleanPath (line 507) | function cleanPath (path) {
  function parse (line 549) | function parse (str, options) {
  function compile (line 622) | function compile (str, options) {
  function encodeURIComponentPretty (line 632) | function encodeURIComponentPretty (str) {
  function encodeAsterisk (line 644) | function encodeAsterisk (str) {
  function tokensToFunction (line 653) | function tokensToFunction (tokens, options) {
  function escapeString (line 740) | function escapeString (str) {
  function escapeGroup (line 750) | function escapeGroup (group) {
  function attachKeys (line 761) | function attachKeys (re, keys) {
  function flags (line 772) | function flags (options) {
  function regexpToRegexp (line 783) | function regexpToRegexp (path, keys) {
  function arrayToRegexp (line 813) | function arrayToRegexp (path, keys, options) {
  function stringToRegexp (line 833) | function stringToRegexp (path, keys, options) {
  function tokensToRegExp (line 845) | function tokensToRegExp (tokens, keys, options) {
  function pathToRegexp (line 921) | function pathToRegexp (path, keys, options) {
  function fillParams (line 949) | function fillParams (
  function normalizeLocation (line 979) | function normalizeLocation (
  method render (line 1079) | render (h) {
  function guardEvent (line 1226) | function guardEvent (e) {
  function findAnchor (line 1245) | function findAnchor (children) {
  function install (line 1262) | function install (Vue) {
  function createRouteMap (line 1316) | function createRouteMap (
  function addRouteRecord (line 1362) | function addRouteRecord (
  function compileRouteRegex (line 1498) | function compileRouteRegex (
  function normalizePath (line 1516) | function normalizePath (
  function createMatcher (line 1531) | function createMatcher (
  function matchRoute (line 1712) | function matchRoute (
  function resolveRecordPath (line 1736) | function resolveRecordPath (path, record) {
  function genStateKey (line 1748) | function genStateKey () {
  function getStateKey (line 1754) | function getStateKey () {
  function setStateKey (line 1758) | function setStateKey (key) {
  function setupScroll (line 1766) | function setupScroll () {
  function handleScroll (line 1788) | function handleScroll (
  function saveScrollPosition (line 1837) | function saveScrollPosition () {
  function handlePopState (line 1847) | function handlePopState (e) {
  function getScrollPosition (line 1854) | function getScrollPosition () {
  function getElementPosition (line 1861) | function getElementPosition (el, offset) {
  function isValidPosition (line 1871) | function isValidPosition (obj) {
  function normalizePosition (line 1875) | function normalizePosition (obj) {
  function normalizeOffset (line 1882) | function normalizeOffset (obj) {
  function isNumber (line 1889) | function isNumber (v) {
  function scrollToPosition (line 1895) | function scrollToPosition (shouldScroll, position) {
  function pushState (line 1952) | function pushState (url, replace) {
  function replaceState (line 1971) | function replaceState (url) {
  function createNavigationRedirectedError (line 1983) | function createNavigationRedirectedError (from, to) {
  function createNavigationDuplicatedError (line 1994) | function createNavigationDuplicatedError (from, to) {
  function createNavigationCancelledError (line 2006) | function createNavigationCancelledError (from, to) {
  function createNavigationAbortedError (line 2017) | function createNavigationAbortedError (from, to) {
  function createRouterError (line 2028) | function createRouterError (from, to, type, message) {
  function stringifyRoute (line 2040) | function stringifyRoute (to) {
  function isError (line 2050) | function isError (err) {
  function isNavigationFailure (line 2054) | function isNavigationFailure (err, errorType) {
  function runQueue (line 2064) | function runQueue (queue, fn, cb) {
  function resolveAsyncComponents (line 2083) | function resolveAsyncComponents (matched) {
  function flatMapComponents (line 2149) | function flatMapComponents (
  function flatten (line 2162) | function flatten (arr) {
  function isESModule (line 2170) | function isESModule (obj) {
  function once (line 2178) | function once (fn) {
  class History (line 2189) | class History {
    method constructor (line 2210) | constructor (router, base) {
    method listen (line 2223) | listen (cb) {
    method onReady (line 2227) | onReady (cb, errorCb) {
    method onError (line 2238) | onError (errorCb) {
    method transitionTo (line 2242) | transitionTo (
    method confirmTransition (line 2297) | confirmTransition (route, onComplete, onAbort) {
    method updateRoute (line 2406) | updateRoute (route) {
    method setupListeners (line 2411) | setupListeners () {
    method teardown (line 2415) | teardown () {
  function normalizeBase (line 2430) | function normalizeBase (base) {
  function resolveQueue (line 2450) | function resolveQueue (
  function extractGuards (line 2468) | function extractGuards (
  function extractGuard (line 2485) | function extractGuard (
  function extractLeaveGuards (line 2496) | function extractLeaveGuards (deactivated) {
  function extractUpdateHooks (line 2500) | function extractUpdateHooks (updated) {
  function bindGuard (line 2504) | function bindGuard (guard, instance) {
  function extractEnterGuards (line 2512) | function extractEnterGuards (
  function bindEnterGuard (line 2524) | function bindEnterGuard (
  class HTML5History (line 2544) | class HTML5History extends History {
    method constructor (line 2547) | constructor (router, base) {
    method setupListeners (line 2553) | setupListeners () {
    method go (line 2588) | go (n) {
    method push (line 2592) | push (location, onComplete, onAbort) {
    method replace (line 2601) | replace (location, onComplete, onAbort) {
    method ensureURL (line 2610) | ensureURL (push) {
    method getCurrentLocation (line 2617) | getCurrentLocation () {
  function getLocation (line 2622) | function getLocation (base) {
  class HashHistory (line 2638) | class HashHistory extends History {
    method constructor (line 2639) | constructor (router, base, fallback) {
    method setupListeners (line 2650) | setupListeners () {
    method push (line 2687) | push (location, onComplete, onAbort) {
    method replace (line 2700) | replace (location, onComplete, onAbort) {
    method go (line 2713) | go (n) {
    method ensureURL (line 2717) | ensureURL (push) {
    method getCurrentLocation (line 2724) | getCurrentLocation () {
  function checkFallback (line 2729) | function checkFallback (base) {
  function ensureSlash (line 2737) | function ensureSlash () {
  function getHash (line 2746) | function getHash () {
  function getUrl (line 2759) | function getUrl (path) {
  function pushHash (line 2766) | function pushHash (path) {
  function replaceHash (line 2774) | function replaceHash (path) {
  class AbstractHistory (line 2784) | class AbstractHistory extends History {
    method constructor (line 2788) | constructor (router, base) {
    method push (line 2794) | push (location, onComplete, onAbort) {
    method replace (line 2806) | replace (location, onComplete, onAbort) {
    method go (line 2817) | go (n) {
    method getCurrentLocation (line 2841) | getCurrentLocation () {
    method ensureURL (line 2846) | ensureURL () {
  class VueRouter (line 2855) | class VueRouter {
    method constructor (line 2875) | constructor (options = {}) {
    method match (line 2915) | match (raw, current, redirectedFrom) {
    method currentRoute (line 2919) | get currentRoute () {
    method init (line 2923) | init (app /* Vue component instance */) {
    method beforeEach (line 2983) | beforeEach (fn) {
    method beforeResolve (line 2987) | beforeResolve (fn) {
    method afterEach (line 2991) | afterEach (fn) {
    method onReady (line 2995) | onReady (cb, errorCb) {
    method onError (line 2999) | onError (errorCb) {
    method push (line 3003) | push (location, onComplete, onAbort) {
    method replace (line 3014) | replace (location, onComplete, onAbort) {
    method go (line 3025) | go (n) {
    method back (line 3029) | back () {
    method forward (line 3033) | forward () {
    method getMatchedComponents (line 3037) | getMatchedComponents (to) {
    method resolve (line 3056) | resolve (
    method getRoutes (line 3077) | getRoutes () {
    method addRoute (line 3081) | addRoute (parentOrRoute, route) {
    method addRoutes (line 3088) | addRoutes (routes) {
  function registerHook (line 3099) | function registerHook (list, fn) {
  function createHref (line 3107) | function createHref (base, fullPath, mode) {

FILE: dist/vue-router.esm.js
  function assert (line 8) | function assert (condition, message) {
  function warn (line 14) | function warn (condition, message) {
  function extend (line 20) | function extend (a, b) {
  function decode (line 40) | function decode (str) {
  function resolveQuery (line 51) | function resolveQuery (
  function parseQuery (line 77) | function parseQuery (query) {
  function stringifyQuery (line 103) | function stringifyQuery (obj) {
  function createRoute (line 144) | function createRoute (
  function clone (line 173) | function clone (value) {
  function formatMatch (line 192) | function formatMatch (record) {
  function getFullPath (line 201) | function getFullPath (
  function isSameRoute (line 213) | function isSameRoute (a, b, onlyPath) {
  function isObjectEqual (line 236) | function isObjectEqual (a, b) {
  function isIncludedRoute (line 262) | function isIncludedRoute (current, target) {
  function queryIncludes (line 272) | function queryIncludes (current, target) {
  function handleRouteEntered (line 281) | function handleRouteEntered (route) {
  function fillPropsinData (line 415) | function fillPropsinData (component, data, route, configProps) {
  function resolveProps (line 432) | function resolveProps (route, config) {
  function resolvePath (line 455) | function resolvePath (
  function parsePath (line 497) | function parsePath (path) {
  function cleanPath (line 520) | function cleanPath (path) {
  function parse (line 562) | function parse (str, options) {
  function compile (line 635) | function compile (str, options) {
  function encodeURIComponentPretty (line 645) | function encodeURIComponentPretty (str) {
  function encodeAsterisk (line 657) | function encodeAsterisk (str) {
  function tokensToFunction (line 666) | function tokensToFunction (tokens, options) {
  function escapeString (line 753) | function escapeString (str) {
  function escapeGroup (line 763) | function escapeGroup (group) {
  function attachKeys (line 774) | function attachKeys (re, keys) {
  function flags (line 785) | function flags (options) {
  function regexpToRegexp (line 796) | function regexpToRegexp (path, keys) {
  function arrayToRegexp (line 826) | function arrayToRegexp (path, keys, options) {
  function stringToRegexp (line 846) | function stringToRegexp (path, keys, options) {
  function tokensToRegExp (line 858) | function tokensToRegExp (tokens, keys, options) {
  function pathToRegexp (line 934) | function pathToRegexp (path, keys, options) {
  function fillParams (line 962) | function fillParams (
  function normalizeLocation (line 992) | function normalizeLocation (
  function guardEvent (line 1242) | function guardEvent (e) {
  function findAnchor (line 1261) | function findAnchor (children) {
  function install (line 1278) | function install (Vue) {
  function createRouteMap (line 1332) | function createRouteMap (
  function addRouteRecord (line 1378) | function addRouteRecord (
  function compileRouteRegex (line 1513) | function compileRouteRegex (
  function normalizePath (line 1531) | function normalizePath (
  function createMatcher (line 1546) | function createMatcher (
  function matchRoute (line 1733) | function matchRoute (
  function resolveRecordPath (line 1757) | function resolveRecordPath (path, record) {
  function genStateKey (line 1769) | function genStateKey () {
  function getStateKey (line 1775) | function getStateKey () {
  function setStateKey (line 1779) | function setStateKey (key) {
  function setupScroll (line 1787) | function setupScroll () {
  function handleScroll (line 1809) | function handleScroll (
  function saveScrollPosition (line 1858) | function saveScrollPosition () {
  function handlePopState (line 1868) | function handlePopState (e) {
  function getScrollPosition (line 1875) | function getScrollPosition () {
  function getElementPosition (line 1882) | function getElementPosition (el, offset) {
  function isValidPosition (line 1892) | function isValidPosition (obj) {
  function normalizePosition (line 1896) | function normalizePosition (obj) {
  function normalizeOffset (line 1903) | function normalizeOffset (obj) {
  function isNumber (line 1910) | function isNumber (v) {
  function scrollToPosition (line 1916) | function scrollToPosition (shouldScroll, position) {
  function pushState (line 1973) | function pushState (url, replace) {
  function replaceState (line 1992) | function replaceState (url) {
  function createNavigationRedirectedError (line 2004) | function createNavigationRedirectedError (from, to) {
  function createNavigationDuplicatedError (line 2015) | function createNavigationDuplicatedError (from, to) {
  function createNavigationCancelledError (line 2027) | function createNavigationCancelledError (from, to) {
  function createNavigationAbortedError (line 2036) | function createNavigationAbortedError (from, to) {
  function createRouterError (line 2045) | function createRouterError (from, to, type, message) {
  function stringifyRoute (line 2057) | function stringifyRoute (to) {
  function isError (line 2067) | function isError (err) {
  function isNavigationFailure (line 2071) | function isNavigationFailure (err, errorType) {
  function runQueue (line 2081) | function runQueue (queue, fn, cb) {
  function resolveAsyncComponents (line 2100) | function resolveAsyncComponents (matched) {
  function flatMapComponents (line 2166) | function flatMapComponents (
  function flatten (line 2179) | function flatten (arr) {
  function isESModule (line 2187) | function isESModule (obj) {
  function once (line 2195) | function once (fn) {
  function normalizeBase (line 2435) | function normalizeBase (base) {
  function resolveQueue (line 2455) | function resolveQueue (
  function extractGuards (line 2473) | function extractGuards (
  function extractGuard (line 2490) | function extractGuard (
  function extractLeaveGuards (line 2501) | function extractLeaveGuards (deactivated) {
  function extractUpdateHooks (line 2505) | function extractUpdateHooks (updated) {
  function bindGuard (line 2509) | function bindGuard (guard, instance) {
  function extractEnterGuards (line 2517) | function extractEnterGuards (
  function bindEnterGuard (line 2529) | function bindEnterGuard (
  function HTML5History (line 2550) | function HTML5History (router, base) {
  function getLocation (line 2639) | function getLocation (base) {
  function HashHistory (line 2656) | function HashHistory (router, base, fallback) {
  function checkFallback (line 2760) | function checkFallback (base) {
  function ensureSlash (line 2768) | function ensureSlash () {
  function getHash (line 2777) | function getHash () {
  function getUrl (line 2790) | function getUrl (path) {
  function pushHash (line 2797) | function pushHash (path) {
  function replaceHash (line 2805) | function replaceHash (path) {
  function AbstractHistory (line 2816) | function AbstractHistory (router, base) {
  function registerHook (line 3133) | function registerHook (list, fn) {
  function createHref (line 3141) | function createHref (base, fullPath, mode) {

FILE: dist/vue-router.js
  function assert (line 14) | function assert (condition, message) {
  function warn (line 20) | function warn (condition, message) {
  function extend (line 26) | function extend (a, b) {
  function decode (line 46) | function decode (str) {
  function resolveQuery (line 57) | function resolveQuery (
  function parseQuery (line 83) | function parseQuery (query) {
  function stringifyQuery (line 109) | function stringifyQuery (obj) {
  function createRoute (line 150) | function createRoute (
  function clone (line 179) | function clone (value) {
  function formatMatch (line 198) | function formatMatch (record) {
  function getFullPath (line 207) | function getFullPath (
  function isSameRoute (line 219) | function isSameRoute (a, b, onlyPath) {
  function isObjectEqual (line 242) | function isObjectEqual (a, b) {
  function isIncludedRoute (line 268) | function isIncludedRoute (current, target) {
  function queryIncludes (line 278) | function queryIncludes (current, target) {
  function handleRouteEntered (line 287) | function handleRouteEntered (route) {
  function fillPropsinData (line 421) | function fillPropsinData (component, data, route, configProps) {
  function resolveProps (line 438) | function resolveProps (route, config) {
  function resolvePath (line 461) | function resolvePath (
  function parsePath (line 503) | function parsePath (path) {
  function cleanPath (line 526) | function cleanPath (path) {
  function parse (line 568) | function parse (str, options) {
  function compile (line 641) | function compile (str, options) {
  function encodeURIComponentPretty (line 651) | function encodeURIComponentPretty (str) {
  function encodeAsterisk (line 663) | function encodeAsterisk (str) {
  function tokensToFunction (line 672) | function tokensToFunction (tokens, options) {
  function escapeString (line 759) | function escapeString (str) {
  function escapeGroup (line 769) | function escapeGroup (group) {
  function attachKeys (line 780) | function attachKeys (re, keys) {
  function flags (line 791) | function flags (options) {
  function regexpToRegexp (line 802) | function regexpToRegexp (path, keys) {
  function arrayToRegexp (line 832) | function arrayToRegexp (path, keys, options) {
  function stringToRegexp (line 852) | function stringToRegexp (path, keys, options) {
  function tokensToRegExp (line 864) | function tokensToRegExp (tokens, keys, options) {
  function pathToRegexp (line 940) | function pathToRegexp (path, keys, options) {
  function fillParams (line 968) | function fillParams (
  function normalizeLocation (line 998) | function normalizeLocation (
  function guardEvent (line 1248) | function guardEvent (e) {
  function findAnchor (line 1267) | function findAnchor (children) {
  function install (line 1284) | function install (Vue) {
  function createRouteMap (line 1338) | function createRouteMap (
  function addRouteRecord (line 1384) | function addRouteRecord (
  function compileRouteRegex (line 1519) | function compileRouteRegex (
  function normalizePath (line 1537) | function normalizePath (
  function createMatcher (line 1552) | function createMatcher (
  function matchRoute (line 1739) | function matchRoute (
  function resolveRecordPath (line 1763) | function resolveRecordPath (path, record) {
  function genStateKey (line 1775) | function genStateKey () {
  function getStateKey (line 1781) | function getStateKey () {
  function setStateKey (line 1785) | function setStateKey (key) {
  function setupScroll (line 1793) | function setupScroll () {
  function handleScroll (line 1815) | function handleScroll (
  function saveScrollPosition (line 1864) | function saveScrollPosition () {
  function handlePopState (line 1874) | function handlePopState (e) {
  function getScrollPosition (line 1881) | function getScrollPosition () {
  function getElementPosition (line 1888) | function getElementPosition (el, offset) {
  function isValidPosition (line 1898) | function isValidPosition (obj) {
  function normalizePosition (line 1902) | function normalizePosition (obj) {
  function normalizeOffset (line 1909) | function normalizeOffset (obj) {
  function isNumber (line 1916) | function isNumber (v) {
  function scrollToPosition (line 1922) | function scrollToPosition (shouldScroll, position) {
  function pushState (line 1979) | function pushState (url, replace) {
  function replaceState (line 1998) | function replaceState (url) {
  function createNavigationRedirectedError (line 2010) | function createNavigationRedirectedError (from, to) {
  function createNavigationDuplicatedError (line 2021) | function createNavigationDuplicatedError (from, to) {
  function createNavigationCancelledError (line 2033) | function createNavigationCancelledError (from, to) {
  function createNavigationAbortedError (line 2042) | function createNavigationAbortedError (from, to) {
  function createRouterError (line 2051) | function createRouterError (from, to, type, message) {
  function stringifyRoute (line 2063) | function stringifyRoute (to) {
  function isError (line 2073) | function isError (err) {
  function isNavigationFailure (line 2077) | function isNavigationFailure (err, errorType) {
  function runQueue (line 2087) | function runQueue (queue, fn, cb) {
  function resolveAsyncComponents (line 2106) | function resolveAsyncComponents (matched) {
  function flatMapComponents (line 2172) | function flatMapComponents (
  function flatten (line 2185) | function flatten (arr) {
  function isESModule (line 2193) | function isESModule (obj) {
  function once (line 2201) | function once (fn) {
  function normalizeBase (line 2441) | function normalizeBase (base) {
  function resolveQueue (line 2461) | function resolveQueue (
  function extractGuards (line 2479) | function extractGuards (
  function extractGuard (line 2496) | function extractGuard (
  function extractLeaveGuards (line 2507) | function extractLeaveGuards (deactivated) {
  function extractUpdateHooks (line 2511) | function extractUpdateHooks (updated) {
  function bindGuard (line 2515) | function bindGuard (guard, instance) {
  function extractEnterGuards (line 2523) | function extractEnterGuards (
  function bindEnterGuard (line 2535) | function bindEnterGuard (
  function HTML5History (line 2556) | function HTML5History (router, base) {
  function getLocation (line 2645) | function getLocation (base) {
  function HashHistory (line 2662) | function HashHistory (router, base, fallback) {
  function checkFallback (line 2766) | function checkFallback (base) {
  function ensureSlash (line 2774) | function ensureSlash () {
  function getHash (line 2783) | function getHash () {
  function getUrl (line 2796) | function getUrl (path) {
  function pushHash (line 2803) | function pushHash (path) {
  function replaceHash (line 2811) | function replaceHash (path) {
  function AbstractHistory (line 2822) | function AbstractHistory (router, base) {
  function registerHook (line 3138) | function registerHook (list, fn) {
  function createHref (line 3146) | function createHref (base, fullPath, mode) {

FILE: dist/vue-router.mjs
  function assert (line 8) | function assert (condition, message) {
  function warn (line 14) | function warn (condition, message) {
  function extend (line 20) | function extend (a, b) {
  function decode (line 40) | function decode (str) {
  function resolveQuery (line 51) | function resolveQuery (
  function parseQuery (line 77) | function parseQuery (query) {
  function stringifyQuery (line 103) | function stringifyQuery (obj) {
  function createRoute (line 144) | function createRoute (
  function clone (line 173) | function clone (value) {
  function formatMatch (line 192) | function formatMatch (record) {
  function getFullPath (line 201) | function getFullPath (
  function isSameRoute (line 213) | function isSameRoute (a, b, onlyPath) {
  function isObjectEqual (line 236) | function isObjectEqual (a, b) {
  function isIncludedRoute (line 262) | function isIncludedRoute (current, target) {
  function queryIncludes (line 272) | function queryIncludes (current, target) {
  function handleRouteEntered (line 281) | function handleRouteEntered (route) {
  function fillPropsinData (line 415) | function fillPropsinData (component, data, route, configProps) {
  function resolveProps (line 432) | function resolveProps (route, config) {
  function resolvePath (line 455) | function resolvePath (
  function parsePath (line 497) | function parsePath (path) {
  function cleanPath (line 520) | function cleanPath (path) {
  function parse (line 562) | function parse (str, options) {
  function compile (line 635) | function compile (str, options) {
  function encodeURIComponentPretty (line 645) | function encodeURIComponentPretty (str) {
  function encodeAsterisk (line 657) | function encodeAsterisk (str) {
  function tokensToFunction (line 666) | function tokensToFunction (tokens, options) {
  function escapeString (line 753) | function escapeString (str) {
  function escapeGroup (line 763) | function escapeGroup (group) {
  function attachKeys (line 774) | function attachKeys (re, keys) {
  function flags (line 785) | function flags (options) {
  function regexpToRegexp (line 796) | function regexpToRegexp (path, keys) {
  function arrayToRegexp (line 826) | function arrayToRegexp (path, keys, options) {
  function stringToRegexp (line 846) | function stringToRegexp (path, keys, options) {
  function tokensToRegExp (line 858) | function tokensToRegExp (tokens, keys, options) {
  function pathToRegexp (line 934) | function pathToRegexp (path, keys, options) {
  function fillParams (line 962) | function fillParams (
  function normalizeLocation (line 992) | function normalizeLocation (
  function guardEvent (line 1242) | function guardEvent (e) {
  function findAnchor (line 1261) | function findAnchor (children) {
  function install (line 1278) | function install (Vue) {
  function createRouteMap (line 1332) | function createRouteMap (
  function addRouteRecord (line 1378) | function addRouteRecord (
  function compileRouteRegex (line 1513) | function compileRouteRegex (
  function normalizePath (line 1531) | function normalizePath (
  function createMatcher (line 1546) | function createMatcher (
  function matchRoute (line 1733) | function matchRoute (
  function resolveRecordPath (line 1757) | function resolveRecordPath (path, record) {
  function genStateKey (line 1769) | function genStateKey () {
  function getStateKey (line 1775) | function getStateKey () {
  function setStateKey (line 1779) | function setStateKey (key) {
  function setupScroll (line 1787) | function setupScroll () {
  function handleScroll (line 1809) | function handleScroll (
  function saveScrollPosition (line 1858) | function saveScrollPosition () {
  function handlePopState (line 1868) | function handlePopState (e) {
  function getScrollPosition (line 1875) | function getScrollPosition () {
  function getElementPosition (line 1882) | function getElementPosition (el, offset) {
  function isValidPosition (line 1892) | function isValidPosition (obj) {
  function normalizePosition (line 1896) | function normalizePosition (obj) {
  function normalizeOffset (line 1903) | function normalizeOffset (obj) {
  function isNumber (line 1910) | function isNumber (v) {
  function scrollToPosition (line 1916) | function scrollToPosition (shouldScroll, position) {
  function pushState (line 1973) | function pushState (url, replace) {
  function replaceState (line 1992) | function replaceState (url) {
  function createNavigationRedirectedError (line 2004) | function createNavigationRedirectedError (from, to) {
  function createNavigationDuplicatedError (line 2015) | function createNavigationDuplicatedError (from, to) {
  function createNavigationCancelledError (line 2027) | function createNavigationCancelledError (from, to) {
  function createNavigationAbortedError (line 2036) | function createNavigationAbortedError (from, to) {
  function createRouterError (line 2045) | function createRouterError (from, to, type, message) {
  function stringifyRoute (line 2057) | function stringifyRoute (to) {
  function isError (line 2067) | function isError (err) {
  function isNavigationFailure (line 2071) | function isNavigationFailure (err, errorType) {
  function runQueue (line 2081) | function runQueue (queue, fn, cb) {
  function resolveAsyncComponents (line 2100) | function resolveAsyncComponents (matched) {
  function flatMapComponents (line 2166) | function flatMapComponents (
  function flatten (line 2179) | function flatten (arr) {
  function isESModule (line 2187) | function isESModule (obj) {
  function once (line 2195) | function once (fn) {
  function normalizeBase (line 2435) | function normalizeBase (base) {
  function resolveQueue (line 2455) | function resolveQueue (
  function extractGuards (line 2473) | function extractGuards (
  function extractGuard (line 2490) | function extractGuard (
  function extractLeaveGuards (line 2501) | function extractLeaveGuards (deactivated) {
  function extractUpdateHooks (line 2505) | function extractUpdateHooks (updated) {
  function bindGuard (line 2509) | function bindGuard (guard, instance) {
  function extractEnterGuards (line 2517) | function extractEnterGuards (
  function bindEnterGuard (line 2529) | function bindEnterGuard (
  function HTML5History (line 2550) | function HTML5History (router, base) {
  function getLocation (line 2639) | function getLocation (base) {
  function HashHistory (line 2656) | function HashHistory (router, base, fallback) {
  function checkFallback (line 2760) | function checkFallback (base) {
  function ensureSlash (line 2768) | function ensureSlash () {
  function getHash (line 2777) | function getHash () {
  function getUrl (line 2790) | function getUrl (path) {
  function pushHash (line 2797) | function pushHash (path) {
  function replaceHash (line 2805) | function replaceHash (path) {
  function AbstractHistory (line 2816) | function AbstractHistory (router, base) {
  function registerHook (line 3133) | function registerHook (list, fn) {
  function createHref (line 3141) | function createHref (base, fullPath, mode) {

FILE: examples/auth-flow/app.js
  function requireAuth (line 12) | function requireAuth (to, from, next) {
  method beforeEnter (line 31) | beforeEnter (to, from, next) {

FILE: examples/auth-flow/auth.js
  method login (line 4) | login (email, pass, cb) {
  method getToken (line 23) | getToken () {
  method logout (line 27) | logout (cb) {
  method loggedIn (line 33) | loggedIn () {
  method onChange (line 37) | onChange () {}
  function pretendRequest (line 40) | function pretendRequest (email, pass, cb) {

FILE: examples/basic/app.js
  method navigateAndIncrement (line 101) | navigateAndIncrement () {

FILE: examples/composables/app.js
  method setup (line 14) | setup () {
  method setup (line 36) | setup () {
  method setup (line 82) | setup () {
  method setup (line 139) | setup () {

FILE: examples/data-fetching/api.js
  function getPost (line 14) | function getPost (id, cb) {

FILE: examples/keepalive-view/app.js
  method beforeRouteEnter (line 18) | beforeRouteEnter (to, from, next) {
  method data (line 52) | data () {
  method beforeRouteEnter (line 57) | beforeRouteEnter (to, from, next) {
  method beforeRouteLeave (line 69) | beforeRouteLeave (to, from, next) {

FILE: examples/navigation-guards/app.js
  function guardRoute (line 19) | function guardRoute (to, from, next) {
  method data (line 31) | data () {
  method beforeRouteLeave (line 40) | beforeRouteLeave (to, from, next) {
  method data (line 54) | data () {
  method beforeRouteEnter (line 60) | beforeRouteEnter (to, from, next) {
  method data (line 81) | data () {
  method beforeRouteUpdate (line 87) | beforeRouteUpdate (to, from, next) {
  method beforeRouteEnter (line 114) | beforeRouteEnter (to, from, next) {
  method beforeRouteEnter (line 122) | beforeRouteEnter (to, from, next) {
  method beforeRouteEnter (line 133) | beforeRouteEnter (to, from, next) {

FILE: examples/route-params/app.js
  method data (line 18) | data () {

FILE: examples/route-props/app.js
  function dynamicPropsFn (line 7) | function dynamicPropsFn (route) {

FILE: examples/scroll-behavior/app.js
  method afterLeave (line 99) | afterLeave () {

FILE: examples/transitions/app.js
  method data (line 16) | data () {
  method beforeRouteUpdate (line 21) | beforeRouteUpdate (to, from, next) {

FILE: src/components/link.js
  method if (line 84) | if (this.replace) {
  method let (line 213) | let child

FILE: src/components/view.js
  method render (line 14) | render (_, { props, children, parent, data }) {
  function fillPropsinData (line 119) | function fillPropsinData (component, data, route, configProps) {
  function resolveProps (line 136) | function resolveProps (route, config) {

FILE: src/composables/globals.js
  function useRouter (line 8) | function useRouter () {
  function useRoute (line 16) | function useRoute () {

FILE: src/composables/guards.js
  function onBeforeRouteUpdate (line 5) | function onBeforeRouteUpdate (guard) {
  function isUpdateNavigation (line 12) | function isUpdateNavigation (to, from, depth) {
  function isLeaveNavigation (line 23) | function isLeaveNavigation (to, from, depth) {
  function onBeforeRouteLeave (line 29) | function onBeforeRouteLeave (guard) {
  function useFilteredGuard (line 38) | function useFilteredGuard (guard, fn) {

FILE: src/composables/useLink.js
  function includesParams (line 6) | function includesParams (outer, inner) {
  function isSameRouteLocationParamsValue (line 28) | function isSameRouteLocationParamsValue (a, b) {
  function isEquivalentArray (line 36) | function isEquivalentArray (a, b) {
  function isSameRouteLocationParams (line 42) | function isSameRouteLocationParams (a, b) {
  function useLink (line 52) | function useLink (props) {

FILE: src/composables/utils.js
  function throwNoCurrentInstance (line 5) | function throwNoCurrentInstance (method) {

FILE: src/create-matcher.js
  function addRoutes (line 25) | function addRoutes (routes) {
  function addRoute (line 29) | function addRoute (parentOrRoute, route) {
  function getRoutes (line 47) | function getRoutes () {
  method for (line 74) | for (const key in currentRoute.params) {
  function matchRoute (line 200) | function matchRoute (
  function resolveRecordPath (line 224) | function resolveRecordPath (path: string, record: RouteRecord): string {

FILE: src/history/base.js
  method if (line 301) | if (current[i] !== next[i]) {
  method if (line 333) | if (typeof def !== 'function') {
  method if (line 349) | if (instance) {

FILE: src/history/hash.js
  function checkFallback (line 101) | function checkFallback (base) {
  function ensureSlash (line 109) | function ensureSlash (): boolean {
  function getHash (line 118) | function getHash (): string {
  function getUrl (line 131) | function getUrl (path) {
  function pushHash (line 138) | function pushHash (path) {
  function replaceHash (line 146) | function replaceHash (path) {

FILE: src/history/html5.js
  function getLocation (line 88) | function getLocation (base: string): string {

FILE: src/install.js
  function install (line 6) | function install (Vue) {

FILE: src/router.js
  method apply (line 212) | apply(
  method if (line 262) | if (process.env.NODE_ENV !== 'production') {
  function createHref (line 280) | function createHref (base: string, fullPath: string, mode) {

FILE: src/util/async.js
  function runQueue (line 3) | function runQueue (queue: Array<?NavigationGuard>, fn: Function, cb: Fun...

FILE: src/util/errors.js
  function createNavigationRedirectedError (line 9) | function createNavigationRedirectedError (from, to) {
  function createNavigationDuplicatedError (line 20) | function createNavigationDuplicatedError (from, to) {
  function createNavigationCancelledError (line 32) | function createNavigationCancelledError (from, to) {
  function createNavigationAbortedError (line 43) | function createNavigationAbortedError (from, to) {
  function createRouterError (line 54) | function createRouterError (from, to, type, message) {
  function stringifyRoute (line 66) | function stringifyRoute (to) {
  function isError (line 76) | function isError (err) {
  function isNavigationFailure (line 80) | function isNavigationFailure (err, errorType) {

FILE: src/util/misc.js
  function extend (line 1) | function extend (a, b) {

FILE: src/util/query.js
  function decode (line 17) | function decode (str: string) {
  function parseQuery (line 52) | function parseQuery (query: string): Dictionary<string> {

FILE: src/util/resolve-components.js
  method return (line 8) | return (to, from, next) => {

FILE: src/util/route.js
  function clone (line 37) | function clone (value) {
  constant START (line 52) | const START = createRoute(null, {
  function formatMatch (line 56) | function formatMatch (record: ?RouteRecord): Array<RouteRecord> {
  function getFullPath (line 65) | function getFullPath (
  function isObjectEqual (line 96) | function isObjectEqual (a = {}, b = {}): boolean {
  function isIncludedRoute (line 119) | function isIncludedRoute (current: Route, target: Route): boolean {
  method for (line 130) | for (const key in target) {

FILE: src/util/scroll.js
  function setupScroll (line 10) | function setupScroll () {
  function handleScroll (line 32) | function handleScroll (
  function saveScrollPosition (line 81) | function saveScrollPosition () {
  function handlePopState (line 91) | function handlePopState (e) {
  function getElementPosition (line 105) | function getElementPosition (el: Element, offset: Object): Object {
  function isValidPosition (line 115) | function isValidPosition (obj: Object): boolean {
  function normalizePosition (line 119) | function normalizePosition (obj: Object): Object {
  function normalizeOffset (line 126) | function normalizeOffset (obj: Object): Object {
  function isNumber (line 133) | function isNumber (v: any): boolean {
  function scrollToPosition (line 139) | function scrollToPosition (shouldScroll, position) {

FILE: src/util/state-key.js
  function genStateKey (line 10) | function genStateKey (): string {
  function getStateKey (line 16) | function getStateKey () {
  function setStateKey (line 20) | function setStateKey (key: string) {

FILE: src/util/warn.js
  function assert (line 3) | function assert (condition: any, message: string) {
  function warn (line 9) | function warn (condition: any, message: string) {

FILE: test/e2e/browserstack-send-status.js
  constant BS_USER (line 3) | const BS_USER = process.env.BS_USER
  constant BS_KEY (line 4) | const BS_KEY = process.env.BS_KEY
  function getKey (line 6) | function getKey (client) {
  function shouldSkipBrowserstackReporting (line 20) | function shouldSkipBrowserstackReporting (client) {
  method beforeEach (line 33) | beforeEach (browser, cb) {
  method afterEach (line 44) | afterEach (browser, cb) {

FILE: test/e2e/nightwatch.browserstack.js
  constant BS_USER (line 5) | const BS_USER = process.env.BS_USER
  constant BS_KEY (line 6) | const BS_KEY = process.env.BS_KEY

FILE: test/e2e/runner.js
  constant DEFAULT_CONFIG (line 35) | const DEFAULT_CONFIG = './nightwatch.json'
  constant NW_CONFIG (line 36) | const NW_CONFIG = isLocal
  function adaptArgv (line 61) | function adaptArgv (argv) {

FILE: test/e2e/specs/active-links.js
  function assertActiveLinks (line 67) | function assertActiveLinks (n, activeA, activeLI, exactActiveA, exactAct...

FILE: test/unit/specs/api.spec.js
  method beforeRouteEnter (line 143) | beforeRouteEnter (to, from, next) {
  method render (line 274) | render (h) { return h('div') }
  method render (line 280) | render (h) { return h('div') }
  method render (line 286) | render (h) { return h('div') }
  method render (line 330) | render (h) { return h('div') }
  method render (line 343) | render (h) { return h('div') }

FILE: test/unit/specs/error-handling.spec.js
  method beforeRouteEnter (line 89) | beforeRouteEnter (to, from, next) {

FILE: test/unit/specs/onReady.spec.js
  function factory (line 7) | function factory () {

FILE: types/composables.d.ts
  type RouterLinkOptions (line 28) | interface RouterLinkOptions {

FILE: types/router.d.ts
  type Component (line 8) | type Component =
  type Dictionary (line 13) | type Dictionary<T> = { [key: string]: T }
  type ErrorHandler (line 14) | type ErrorHandler = (err: Error) => void
  type RouterMode (line 16) | type RouterMode = 'hash' | 'history' | 'abstract'
  type RawLocation (line 17) | type RawLocation = string | Location
  type RedirectOption (line 18) | type RedirectOption = RawLocation | ((to: Route) => RawLocation)
  type NavigationGuardNext (line 19) | type NavigationGuardNext<V extends Vue = Vue> = (
  type NavigationGuard (line 23) | type NavigationGuard<V extends Vue = Vue> = (
  class VueRouter (line 32) | class VueRouter {
  type NavigationFailureType (line 227) | enum NavigationFailureType {
  type NavigationFailure (line 252) | interface NavigationFailure extends Error {
  type Position (line 272) | type Position = { x: number; y: number }
  type PositionResult (line 273) | type PositionResult = Position | { selector: string; offset?: Position, ...
  type RouterOptions (line 279) | interface RouterOptions {
  type RoutePropsFunction (line 326) | type RoutePropsFunction = (route: Route) => Object
  type PathToRegexpOptions (line 328) | interface PathToRegexpOptions {
  type _RouteConfigBase (line 334) | interface _RouteConfigBase {
  type RouteConfigSingleView (line 346) | interface RouteConfigSingleView extends _RouteConfigBase {
  type RouteConfigMultipleViews (line 351) | interface RouteConfigMultipleViews extends _RouteConfigBase {
  type RouteConfig (line 356) | type RouteConfig = RouteConfigSingleView | RouteConfigMultipleViews
  type RouteRecord (line 358) | interface RouteRecord {
  type RouteRecordPublic (line 380) | interface RouteRecordPublic {
  type Location (line 400) | interface Location {
  type Route (line 410) | interface Route {
  type RouteMeta (line 422) | interface RouteMeta extends Record<string | number | symbol, any> {}
  type RouterLinkProps (line 424) | interface RouterLinkProps {
  type RouterLinkSlotArgument (line 510) | interface RouterLinkSlotArgument {
  type RouterViewProps (line 552) | interface RouterViewProps {

FILE: types/test/index.ts
  method beforeRouteEnter (line 33) | beforeRouteEnter(to, from, next) {
  method beforeRouteLeave (line 42) | beforeRouteLeave(to, from, next) {
  method beforeRouteUpdate (line 49) | beforeRouteUpdate(to, from, next) {
  method beforeEnter (line 116) | beforeEnter(to, from, next) {

FILE: types/test/meta.ts
  type RouteMeta (line 6) | interface RouteMeta {

FILE: types/vue.d.ts
  type Vue (line 9) | interface Vue {
  type ComponentOptions (line 16) | interface ComponentOptions<V extends Vue> {
Condensed preview — 458 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,596K chars).
[
  {
    "path": ".babelrc",
    "chars": 77,
    "preview": "{\n  \"presets\": [\"env\", \"flow-vue\"],\n  \"plugins\": [\"syntax-dynamic-import\"]\n}\n"
  },
  {
    "path": ".circleci/config.yml",
    "chars": 1769,
    "preview": "version: 2\n\ndefaults: &defaults\n  working_directory: ~/project/vue-router\n  docker:\n    - image: circleci/node:lts-brows"
  },
  {
    "path": ".eslintignore",
    "chars": 10,
    "preview": "dist\n*.ts\n"
  },
  {
    "path": ".eslintrc",
    "chars": 143,
    "preview": "{\n  \"root\": true,\n  \"plugins\": [\n    \"flowtype\"\n  ],\n  \"extends\": [\n    \"plugin:vue-libs/recommended\",\n    \"plugin:flowt"
  },
  {
    "path": ".flowconfig",
    "chars": 202,
    "preview": "[ignore]\n.*/node_modules/.*\n.*/test/.*\n.*/dist/.*\n.*/examples/.*\n.*/vue/.*\n\n[include]\n\n[libs]\nflow\n\n[options]\n#unsafe.en"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "chars": 210,
    "preview": "<!--\nIMPORTANT: Please use the following link to create a new issue:\n\n  https://new-issue.vuejs.org/?repo=vuejs/vue-rout"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 149,
    "preview": "<!--\nPlease make sure to read the Pull Request Guidelines:\nhttps://github.com/vuejs/vue/blob/dev/.github/CONTRIBUTING.md"
  },
  {
    "path": ".github/funding.yml",
    "chars": 50,
    "preview": "github: [posva, yyx990803]\nopen_collective: vuejs\n"
  },
  {
    "path": ".github/workflows/release-tag.yml",
    "chars": 607,
    "preview": "on:\n  push:\n    tags:\n      - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10\n\nname: Create Release\n\njobs:\n  bui"
  },
  {
    "path": ".gitignore",
    "chars": 238,
    "preview": ".DS_Store\nnode_modules\nTODOs.md\ntest/e2e/reports\ntest/e2e/screenshots\nselenium-debug.log\ndist/*.gz\ndist/*.map\nexploratio"
  },
  {
    "path": ".prettierrc",
    "chars": 63,
    "preview": "{\n  \"semi\": false,\n  \"singleQuote\": true,\n  \"printWidth\": 80\n}\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 29174,
    "preview": "## [3.6.5](https://github.com/vuejs/vue-router/compare/v3.6.4...v3.6.5) (2022-09-06)\n\n### Bug Fixes\n\n- **types:** Compon"
  },
  {
    "path": "LICENSE",
    "chars": 1073,
    "preview": "MIT License\n\nCopyright (c) 2013-present Evan You\n\nPermission is hereby granted, free of charge, to any person obtaining "
  },
  {
    "path": "README.md",
    "chars": 6025,
    "preview": "# vue-router [![Build Status](https://img.shields.io/circleci/project/github/vuejs/vue-router/dev.svg)](https://circleci"
  },
  {
    "path": "build/build.js",
    "chars": 1997,
    "preview": "const fs = require('fs')\nconst path = require('path')\nconst zlib = require('zlib')\nconst terser = require('terser')\ncons"
  },
  {
    "path": "build/configs.js",
    "chars": 2278,
    "preview": "const path = require('path')\nconst buble = require('rollup-plugin-buble')\nconst flow = require('rollup-plugin-flow-no-wh"
  },
  {
    "path": "build/rollup.dev.config.js",
    "chars": 105,
    "preview": "const { input, output } = require('./configs')[0]\n\nmodule.exports = Object.assign({}, input, { output })\n"
  },
  {
    "path": "composables.d.ts",
    "chars": 36,
    "preview": "export * from './types/composables'\n"
  },
  {
    "path": "composables.js",
    "chars": 6836,
    "preview": "/*!\n  * vue-router v3.6.5\n  * (c) 2022 Evan You\n  * @license MIT\n  */\n'use strict'\n\nObject.defineProperty(exports, '__es"
  },
  {
    "path": "composables.mjs",
    "chars": 6684,
    "preview": "/*!\n  * vue-router v3.6.5\n  * (c) 2022 Evan You\n  * @license MIT\n  */\nimport { getCurrentInstance, effectScope, shallowR"
  },
  {
    "path": "dist/vue-router.common.js",
    "chars": 83455,
    "preview": "/*!\n  * vue-router v3.6.5\n  * (c) 2022 Evan You\n  * @license MIT\n  */\n'use strict';\n\n/*  */\n\nfunction assert (condition,"
  },
  {
    "path": "dist/vue-router.esm.browser.js",
    "chars": 78225,
    "preview": "/*!\n  * vue-router v3.6.5\n  * (c) 2022 Evan You\n  * @license MIT\n  */\n/*  */\n\nfunction assert (condition, message) {\n  i"
  },
  {
    "path": "dist/vue-router.esm.js",
    "chars": 83587,
    "preview": "/*!\n  * vue-router v3.6.5\n  * (c) 2022 Evan You\n  * @license MIT\n  */\n/*  */\n\nfunction assert (condition, message) {\n  i"
  },
  {
    "path": "dist/vue-router.js",
    "chars": 88147,
    "preview": "/*!\n  * vue-router v3.6.5\n  * (c) 2022 Evan You\n  * @license MIT\n  */\n(function (global, factory) {\n  typeof exports ==="
  },
  {
    "path": "dist/vue-router.mjs",
    "chars": 83587,
    "preview": "/*!\n  * vue-router v3.6.5\n  * (c) 2022 Evan You\n  * @license MIT\n  */\n/*  */\n\nfunction assert (condition, message) {\n  i"
  },
  {
    "path": "docs/.vuepress/components/HomeSponsors.vue",
    "chars": 1599,
    "preview": "<template>\n  <div id=\"sponsors\">\n    <div class=\"inner\">\n      <HomeSponsorsGroup name=\"Platinum\" size=\"160\" />\n      <H"
  },
  {
    "path": "docs/.vuepress/components/HomeSponsorsGroup.vue",
    "chars": 729,
    "preview": "<template>\n  <div v-if=\"list && list.length\">\n    <h3>{{ name }} Sponsors</h3>\n\n    <a\n      v-for=\"sponsor in list\"\n   "
  },
  {
    "path": "docs/.vuepress/components/sponsors.json",
    "chars": 1673,
    "preview": "{\n  \"platinum\": [],\n  \"gold\": [],\n  \"silver\": [\n    {\n      \"href\": \"https://www.vuemastery.com/\",\n      \"alt\": \"VueMast"
  },
  {
    "path": "docs/.vuepress/config.js",
    "chars": 11975,
    "preview": "module.exports = ctx => ({\n  locales: {\n    '/': {\n      lang: 'en-US',\n      title: 'Vue Router',\n      description: 'T"
  },
  {
    "path": "docs/.vuepress/public/_redirects",
    "chars": 878,
    "preview": "# redirect old urls to root\n\n/en/essentials/getting-started.html /guide/\n/en/essentials/* /guide/essentials/:splat\n/en/a"
  },
  {
    "path": "docs/.vuepress/styles/index.styl",
    "chars": 999,
    "preview": ".bit-sponsor\n  font-weight 600\n  background-color #f3f6f8\n  padding 0.6em 1.2em\n  border-radius 8px\n  display inline-blo"
  },
  {
    "path": "docs/.vuepress/theme/Layout.vue",
    "chars": 4254,
    "preview": "<template>\n  <div class=\"main-container\" :class=\"{ 'has-top-banner': showTopBanner }\">\n    <div id=\"v3-banner\">\n      <s"
  },
  {
    "path": "docs/.vuepress/theme/components/BuySellAds.vue",
    "chars": 2137,
    "preview": "<template>\n  <div class=\"bsa-cpc-wrapper\">\n    <div class=\"bsa-cpc\"></div>\n  </div>\n</template>\n\n<script>\n/* global _bsa"
  },
  {
    "path": "docs/.vuepress/theme/components/CarbonAds.vue",
    "chars": 1373,
    "preview": "<template>\n  <div class=\"carbon-ads\"></div>\n</template>\n\n<script>\nexport default {\n  name: 'CarbonAds',\n  props: {\n    c"
  },
  {
    "path": "docs/.vuepress/theme/components/VueSchool/BannerTop.vue",
    "chars": 5014,
    "preview": "<template>\n  <a\n    id=\"vs\"\n    href=\"https://vueschool.io/sales/price-increase-22?friend=vuerouter\"\n    target=\"_blank\""
  },
  {
    "path": "docs/.vuepress/theme/index.js",
    "chars": 57,
    "preview": "module.exports = {\n  extend: '@vuepress/theme-default'\n}\n"
  },
  {
    "path": "docs/README.md",
    "chars": 906,
    "preview": "---\nhome: true\nheroImage: /logo.png\nactionText: Get Started →\nactionLink: /installation.html\nfooter: MIT Licensed | Copy"
  },
  {
    "path": "docs/api/README.md",
    "chars": 19269,
    "preview": "---\nsidebar: auto\n---\n\n# API Reference\n\n## `<router-link>`\n\n`<router-link>` is the component for enabling user navigatio"
  },
  {
    "path": "docs/fr/README.md",
    "chars": 961,
    "preview": "---\nhome: true\nheroImage: /logo.png\nactionText: Get Started →\nactionLink: /fr/installation.html\nfooter: MIT Licensed | C"
  },
  {
    "path": "docs/fr/api/README.md",
    "chars": 17136,
    "preview": "---\nsidebar: auto\n---\n\n# API\n\n## `<router-link>`\n\n`<router-link>` est le composant pour activer la navigation utilisateu"
  },
  {
    "path": "docs/fr/guide/README.md",
    "chars": 3751,
    "preview": "# Pour commencer\n\n::: tip Note\nNous utiliserons [ES2015](https://github.com/lukehoban/es6features) dans les exemples de "
  },
  {
    "path": "docs/fr/guide/advanced/data-fetching.md",
    "chars": 3841,
    "preview": "# Récupération de données\n\nParfois vous avez besoin de récupérer des données depuis le serveur lorsqu'une route est acti"
  },
  {
    "path": "docs/fr/guide/advanced/lazy-loading.md",
    "chars": 2467,
    "preview": "# Chargement à la volée\n\nPendant la construction d'applications avec un empaqueteur (« bundler »), le paquetage JavaScri"
  },
  {
    "path": "docs/fr/guide/advanced/meta.md",
    "chars": 1687,
    "preview": "# Champs meta de route\n\nVous pouvez inclure un champ `meta` quand vous définissez une route :\n\n``` js\nconst router = new"
  },
  {
    "path": "docs/fr/guide/advanced/navigation-guards.md",
    "chars": 7060,
    "preview": "# Intercepteurs de navigation\n\nComme le nom le suggère, l'interception de navigation fournie par `vue-router` est princi"
  },
  {
    "path": "docs/fr/guide/advanced/scroll-behavior.md",
    "chars": 2965,
    "preview": "# Comportement du défilement\n\nEn utilisant le routage côté client, nous pourrions vouloir faire défiler la page jusqu'en"
  },
  {
    "path": "docs/fr/guide/advanced/transitions.md",
    "chars": 1660,
    "preview": "# Transitions\n\nVu que `<router-view>` est essentiellement un composant dynamique, on peut lui appliquer certains effets "
  },
  {
    "path": "docs/fr/guide/essentials/dynamic-matching.md",
    "chars": 4052,
    "preview": "# Concordance dynamique de route\n\nVous allez très souvent associer des routes avec un motif donné à un même composant. P"
  },
  {
    "path": "docs/fr/guide/essentials/history-mode.md",
    "chars": 4402,
    "preview": "# Mode historique de HTML5\n\nLe mode par défaut de `vue-router` est le _mode hash_. Il utilise la partie hash de l'URL po"
  },
  {
    "path": "docs/fr/guide/essentials/named-routes.md",
    "chars": 992,
    "preview": "# Routes nommées\n\nParfois il est plus pratique d'identifier une route avec un nom, tout particulièrement quand on souhai"
  },
  {
    "path": "docs/fr/guide/essentials/named-views.md",
    "chars": 3371,
    "preview": "# Vues nommées\n\nParfois vous avez besoin d'afficher différentes vues en même temps plutôt que de les imbriquer, c.-à-d. "
  },
  {
    "path": "docs/fr/guide/essentials/navigation.md",
    "chars": 4592,
    "preview": "---\nsidebarDepth: 0\n---\n\n# Navigation programmatique\n\nEn complément du l'utilisation de `<router-link>` pour créer des b"
  },
  {
    "path": "docs/fr/guide/essentials/nested-routes.md",
    "chars": 3616,
    "preview": "# Routes imbriquées\n\nLes vraies interfaces utilisateurs d'application sont faites de composants imbriqués à de multiples"
  },
  {
    "path": "docs/fr/guide/essentials/passing-props.md",
    "chars": 2321,
    "preview": "# Passage de props aux composants de route\n\nUtiliser `$route` dans vos composants crée un couplage fort à la route qui v"
  },
  {
    "path": "docs/fr/guide/essentials/redirect-and-alias.md",
    "chars": 2002,
    "preview": "# Redirection et alias\n\n## Redirection\n\nLes redirections peuvent aussi être faites depuis la configuration de `routes`. "
  },
  {
    "path": "docs/fr/installation.md",
    "chars": 1304,
    "preview": "# Installation\n\n## Téléchargement direct / CDN\n\n[https://unpkg.com/vue-router@3/dist/vue-router.js](https://unpkg.com/vu"
  },
  {
    "path": "docs/guide/README.md",
    "chars": 3785,
    "preview": "# Getting Started\n\n::: tip Note\nYou are reading the documentation of Vue Router 3 **for Vue 2**. If you are working with"
  },
  {
    "path": "docs/guide/advanced/data-fetching.md",
    "chars": 3518,
    "preview": "# Data Fetching\n\nSometimes you need to fetch data from the server when a route is activated. For example, before renderi"
  },
  {
    "path": "docs/guide/advanced/lazy-loading.md",
    "chars": 2427,
    "preview": "# Lazy Loading Routes\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/lessons/how-to-lazy-load-routes-with-vue-rou"
  },
  {
    "path": "docs/guide/advanced/meta.md",
    "chars": 1734,
    "preview": "# Route Meta Fields\n\nSometimes, you might want to attach arbitrary information to routes like transition names, who can "
  },
  {
    "path": "docs/guide/advanced/navigation-failures.md",
    "chars": 3034,
    "preview": "# Navigation Failures\n\n> New in 3.4.0\n\nWhen using `router-link`, Vue Router calls `router.push` to trigger a navigation."
  },
  {
    "path": "docs/guide/advanced/navigation-guards.md",
    "chars": 7418,
    "preview": "# Navigation Guards\n\nAs the name suggests, the navigation guards provided by `vue-router` are primarily used to guard na"
  },
  {
    "path": "docs/guide/advanced/scroll-behavior.md",
    "chars": 3275,
    "preview": "# Scroll Behavior\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/lessons/how-to-control-the-scroll-behavior-of-vu"
  },
  {
    "path": "docs/guide/advanced/transitions.md",
    "chars": 1835,
    "preview": "# Transitions\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/lessons/how-to-create-route-transitions-with-vue-rou"
  },
  {
    "path": "docs/guide/essentials/dynamic-matching.md",
    "chars": 4707,
    "preview": "# Dynamic Route Matching\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/lessons/vue-router-dynamic-routes?friend="
  },
  {
    "path": "docs/guide/essentials/history-mode.md",
    "chars": 4514,
    "preview": "# HTML5 History Mode\n\nThe default mode for `vue-router` is _hash mode_ - it uses the URL hash to simulate a full URL so "
  },
  {
    "path": "docs/guide/essentials/named-routes.md",
    "chars": 1176,
    "preview": "# Named Routes\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/lessons/vue-router-named-routes-and-params?friend=v"
  },
  {
    "path": "docs/guide/essentials/named-views.md",
    "chars": 3141,
    "preview": "# Named Views\n\nSometimes you need to display multiple views at the same time instead of nesting them, e.g. creating a la"
  },
  {
    "path": "docs/guide/essentials/navigation.md",
    "chars": 4168,
    "preview": "---\nsidebarDepth: 0\n---\n\n# Programmatic Navigation\n\nAside from using `<router-link>` to create anchor tags for declarati"
  },
  {
    "path": "docs/guide/essentials/nested-routes.md",
    "chars": 3433,
    "preview": "# Nested Routes\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/lessons/vue-router-nested-routes?friend=vuerouter\""
  },
  {
    "path": "docs/guide/essentials/passing-props.md",
    "chars": 2637,
    "preview": "# Passing Props to Route Components\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/lessons/how-to-pass-vue-router"
  },
  {
    "path": "docs/guide/essentials/redirect-and-alias.md",
    "chars": 1699,
    "preview": "# Redirect and Alias\n\n## Redirect\n\nRedirecting is also done in the `routes` configuration. To redirect from `/a` to `/b`"
  },
  {
    "path": "docs/installation.md",
    "chars": 1497,
    "preview": "# Installation\n\n## Direct Download / CDN\n\n[https://unpkg.com/vue-router@3/dist/vue-router.js](https://unpkg.com/vue-rout"
  },
  {
    "path": "docs/ja/README.md",
    "chars": 1008,
    "preview": "---\nhome: true\nheroImage: /logo.png\nactionText: Get Started →\nactionLink: /ja/installation.html\nfooter: MIT Licensed | C"
  },
  {
    "path": "docs/ja/api/README.md",
    "chars": 12910,
    "preview": "---\nsidebar: auto\n---\n\n# API リファレンス\n\n## `<router-link>`\n\n`<router-link>` はルーターが使用可能になっているアプリケーションでユーザーのナビゲーションを有効にするためのコ"
  },
  {
    "path": "docs/ja/guide/README.md",
    "chars": 2793,
    "preview": "# はじめに\n\n::: tip Note\nガイド内のコードのサンプルは [ES2015](https://github.com/lukehoban/es6features) を使っています。\n\nすべての example では、vue の完全"
  },
  {
    "path": "docs/ja/guide/advanced/data-fetching.md",
    "chars": 2755,
    "preview": "# データ取得\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/courses/vue-router-for-everyone?friend=vuerouter\" target=\""
  },
  {
    "path": "docs/ja/guide/advanced/lazy-loading.md",
    "chars": 1738,
    "preview": "# 遅延ローディングルート\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/courses/vue-router-for-everyone?friend=vuerouter\" ta"
  },
  {
    "path": "docs/ja/guide/advanced/meta.md",
    "chars": 1385,
    "preview": "# ルートメタフィールド\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/courses/vue-router-for-everyone?friend=vuerouter\" tar"
  },
  {
    "path": "docs/ja/guide/advanced/navigation-failures.md",
    "chars": 2117,
    "preview": "# ナビゲーションの失敗\n\n> 3.4.0の新機能\n\n`router-link` を使用すると、ナビゲーションを開始するためにVue Routerは `router.push` を呼び出します。ほとんどのリンクはユーザーを新しいページに移動"
  },
  {
    "path": "docs/ja/guide/advanced/navigation-guards.md",
    "chars": 5149,
    "preview": "# ナビゲーションガード\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/courses/vue-router-for-everyone?friend=vuerouter\" tar"
  },
  {
    "path": "docs/ja/guide/advanced/scroll-behavior.md",
    "chars": 2231,
    "preview": "# スクロールの振る舞い\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/courses/vue-router-for-everyone?friend=vuerouter\" tar"
  },
  {
    "path": "docs/ja/guide/advanced/transitions.md",
    "chars": 1498,
    "preview": "# トランジション\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/courses/vue-router-for-everyone?friend=vuerouter\" target"
  },
  {
    "path": "docs/ja/guide/essentials/dynamic-matching.md",
    "chars": 3562,
    "preview": "# 動的ルートマッチング\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/courses/vue-router-for-everyone?friend=vuerouter\" tar"
  },
  {
    "path": "docs/ja/guide/essentials/history-mode.md",
    "chars": 3659,
    "preview": "# HTML5 History モード\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/courses/vue-router-for-everyone?friend=vuerout"
  },
  {
    "path": "docs/ja/guide/essentials/named-routes.md",
    "chars": 995,
    "preview": "# 名前付きルート\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/courses/vue-router-for-everyone?friend=vuerouter\" target"
  },
  {
    "path": "docs/ja/guide/essentials/named-views.md",
    "chars": 2905,
    "preview": "# 名前付きビュー\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/courses/vue-router-for-everyone?friend=vuerouter\" target"
  },
  {
    "path": "docs/ja/guide/essentials/navigation.md",
    "chars": 3258,
    "preview": "# プログラムによるナビゲーション\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/courses/vue-router-for-everyone?friend=vuerouter"
  },
  {
    "path": "docs/ja/guide/essentials/nested-routes.md",
    "chars": 2805,
    "preview": "# ネストされたルート\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/courses/vue-router-for-everyone?friend=vuerouter\" targ"
  },
  {
    "path": "docs/ja/guide/essentials/passing-props.md",
    "chars": 2032,
    "preview": "# ルートコンポーネントにプロパティを渡す\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/courses/vue-router-for-everyone?friend=vuero"
  },
  {
    "path": "docs/ja/guide/essentials/redirect-and-alias.md",
    "chars": 1581,
    "preview": "# リダイレクトとエイリアス\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/courses/vue-router-for-everyone?friend=vuerouter\" t"
  },
  {
    "path": "docs/ja/installation.md",
    "chars": 1168,
    "preview": "# インストール\n\n### 直接ダウンロード / CDN\n\n[https://unpkg.com/vue-router@3/dist/vue-router.js](https://unpkg.com/vue-router@3/dist/vu"
  },
  {
    "path": "docs/kr/README.md",
    "chars": 692,
    "preview": "---\nhome: true\nheroImage: /logo.png\nactionText: Get Started →\nactionLink: /kr/installation.html\nfooter: MIT Licensed | C"
  },
  {
    "path": "docs/kr/api/README.md",
    "chars": 6095,
    "preview": "---\nsidebar: auto\n---\n\n# API 레퍼런스\n\n## `<router-link>`\n\n`<router-link>`는 라우터 지원 앱에서 사용자 네비게이션을 가능하게하는 컴포넌트입니다. 목표 위치는 `to"
  },
  {
    "path": "docs/kr/guide/README.md",
    "chars": 2462,
    "preview": "# 시작하기\n\n::: tip 참고\n이 가이드는 코드샘플에 [ES2015](https://github.com/lukehoban/es6features)를 사용합니다.\n\n또한 모든 예제는 Vue 정식 버전을 이용해 바로 "
  },
  {
    "path": "docs/kr/guide/advanced/data-fetching.md",
    "chars": 2464,
    "preview": "# 데이터 가져오기\n\n때로는 라우트가 활성화될 때 서버에서 데이터를 가져와야 합니다. 예를 들어, 사용자 프로필을 렌더링하기 전에 서버에서 사용자의 데이터를 가져와야 합니다. 우리는 두 가지 방법을 사용할 수 있습니"
  },
  {
    "path": "docs/kr/guide/advanced/lazy-loading.md",
    "chars": 1489,
    "preview": "# 지연된 로딩\n\n번들러를 이용하여 앱을 제작할 때 JavaScript 번들이 상당히 커져 페이지로드 시간에 영향을 줄 수 있습니다. 각 라우트의 컴포넌트를 별도의 단위로 분할하고 경로를 방문할 때 로드하는 것이 효"
  },
  {
    "path": "docs/kr/guide/advanced/meta.md",
    "chars": 1112,
    "preview": "# 라우트 메타 필드\n\n라우트를 정의 할 때 `meta` 필드를 포함시킬 수 있습니다.\n\n``` js\nconst router = new VueRouter({\n  routes: [\n    {\n      path: '/"
  },
  {
    "path": "docs/kr/guide/advanced/navigation-guards.md",
    "chars": 3265,
    "preview": "# 네비게이션 가드\n\n이름에서 알 수 있듯이 `vue-router`가 제공하는 네비게이션 가드는 주로 리디렉션하거나 취소하여 네비게이션을 보호하는 데 사용됩니다. 라우트 탐색 프로세스에 연결하는 방법에는 전역, 라우"
  },
  {
    "path": "docs/kr/guide/advanced/scroll-behavior.md",
    "chars": 1416,
    "preview": "# 스크롤 동작\n\n클라이언트 측 라우팅을 사용할 때 새로운 경로로 이동할 때 맨 위로 스크롤하거나 실제 페이지를 다시 로드하는 것처럼 컨텐츠 항목의 스크롤 위치를 유지할 수 있습니다. `vue-router`는 이러한"
  },
  {
    "path": "docs/kr/guide/advanced/transitions.md",
    "chars": 1206,
    "preview": "# 트랜지션\n\n`<router-view>`는 본질적으로 동적인 컴포넌트이기 때문에 `<transition>` 컴포넌트를 사용하는 것과 같은 방식으로 트랜지션 효과를 적용할 수 있습니다.\n\n``` html\n<trans"
  },
  {
    "path": "docs/kr/guide/essentials/dynamic-matching.md",
    "chars": 2281,
    "preview": "# 동적 라우트 매칭\n\n주어진 패턴을 가진 라우트를 동일한 컴포넌트에 매핑해야하는 경우가 자주 있습니다. 예를 들어 모든 사용자에 대해 동일한 레이아웃을 가지지만 하지만 다른 사용자 ID로 렌더링되어야하는 `User"
  },
  {
    "path": "docs/kr/guide/essentials/getting-started.md",
    "chars": 1935,
    "preview": "# 시작하기\n\n> 가이드의 샘플 코드는[ES2015](https://github.com/lukehoban/es6features)를 사용합니다.\n\nVue.js와 vue-router로 단일 페이지 애플리케이션을 만드는 "
  },
  {
    "path": "docs/kr/guide/essentials/history-mode.md",
    "chars": 3119,
    "preview": "# HTML5 히스토리 모드\n\n`vue-router`의 기본 모드는 _hash mode_ 입니다. URL 해시를 사용하여 전체 URL을 시뮬레이트하므로 URL이 변경될 때 페이지가 다시 로드 되지 않습니다.\n\n해시를"
  },
  {
    "path": "docs/kr/guide/essentials/named-routes.md",
    "chars": 676,
    "preview": "# 이름을 가지는 라우트\n\n때로는 라우트에 연결하거나 탐색을 수행 할 때 이름이 있는 라우트를 사용하는 것이 더 편리합니다. Router 인스턴스를 생성하는 동안 `routes` 옵션에 라우트를 지정할 수 있습니다."
  },
  {
    "path": "docs/kr/guide/essentials/named-views.md",
    "chars": 716,
    "preview": "# 이름을 가지는 뷰\n\n때로는 여러 개의 뷰를 중첩하지 않고 동시에 표시해야 하는 경우가 있습니다. `sidebar` 뷰와 `main` 뷰로 레이아웃을 생성합니다. 이름이 지정된 뷰가 편리한 경우 입니다. 뷰에 하나"
  },
  {
    "path": "docs/kr/guide/essentials/navigation.md",
    "chars": 2187,
    "preview": "# 프로그래밍 방식 네비게이션\n\n`<router-link>`를 사용하여 선언적 네비게이션용 anchor 태그를 만드는 것 외에도 라우터의 인스턴스 메소드를 사용하여 프로그래밍으로 이를 수행 할 수 있습니다.\n\n###"
  },
  {
    "path": "docs/kr/guide/essentials/nested-routes.md",
    "chars": 2496,
    "preview": "# 중첩된 라우트\n\n실제 앱 UI는 일반적으로 여러 단계로 중첩 된 컴포넌트로 이루어져 있습니다. URL의 세그먼트가 중첩 된 컴포넌트의 특정 구조와 일치한다는 것은 매우 일반적입니다. 예를 들면 다음과 같습니다.\n"
  },
  {
    "path": "docs/kr/guide/essentials/passing-props.md",
    "chars": 1417,
    "preview": "# 라우트 컴포넌트에 속성 전달\n\n컴포넌트에서 `$route`를 사용하면 특정 URL에서만 사용할 수 있는 컴포넌트의 유연성을 제한하는 라우트와 강한 결합을 만듭니다.\n\n컴포넌트와 라우터 속성을 분리하려면 다음과 같"
  },
  {
    "path": "docs/kr/guide/essentials/redirect-and-alias.md",
    "chars": 1090,
    "preview": "# 리다이렉트와 별칭\n\n### 리다이렉트\n\n리디렉션은 `routes` 설정에서도 할 수 있습니다. `/a`에서 `/b`로 리디렉션하려면\n\n``` js\nconst router = new VueRouter({\n  rou"
  },
  {
    "path": "docs/kr/installation.md",
    "chars": 927,
    "preview": "# 설치\n\n### 직접 다운로드 / CDN\n\n[https://unpkg.com/vue-router@3/dist/vue-router.js](https://unpkg.com/vue-router@3/dist/vue-rou"
  },
  {
    "path": "docs/ru/README.md",
    "chars": 975,
    "preview": "---\nhome: true\nheroImage: /logo.png\nactionText: Начать знакомство →\nactionLink: /ru/installation.html\nfooter: MIT Licens"
  },
  {
    "path": "docs/ru/api/README.md",
    "chars": 20732,
    "preview": "---\nsidebar: auto\n---\n\n# Справочник API\n\n## `<router-link>`\n\n`<router-link>` — это компонент предназначенный для навигац"
  },
  {
    "path": "docs/ru/guide/README.md",
    "chars": 3554,
    "preview": "# Начало работы\n\n::: tip Примечание\nМы будем использовать синтаксис [ES2015](https://github.com/lukehoban/es6features) в"
  },
  {
    "path": "docs/ru/guide/advanced/data-fetching.md",
    "chars": 3353,
    "preview": "# Загрузка данных\n\nНередко при переходе между маршрутами требуется получить от сервера какие-либо данные. Например, пере"
  },
  {
    "path": "docs/ru/guide/advanced/lazy-loading.md",
    "chars": 2357,
    "preview": "# Ленивая загрузка маршрутов\n\nПри использовании модульной системы, итоговая JavaScript-сборка может оказаться довольно б"
  },
  {
    "path": "docs/ru/guide/advanced/meta.md",
    "chars": 1848,
    "preview": "# Метаданные маршрутов\n\nИногда может быть удобным добавить дополнительную информацию к маршрутам, например имена анимаци"
  },
  {
    "path": "docs/ru/guide/advanced/navigation-failures.md",
    "chars": 3267,
    "preview": "# Сбои при навигации\n\n> Добавлено в версии 3.4.0\n\nПри использовании `router-link` Vue Router вызывает `router.push` для "
  },
  {
    "path": "docs/ru/guide/advanced/navigation-guards.md",
    "chars": 7402,
    "preview": "# Навигационные хуки\n\nКак следует из названия, навигационные хуки `vue-router` используются для перенаправлений или отме"
  },
  {
    "path": "docs/ru/guide/advanced/scroll-behavior.md",
    "chars": 3237,
    "preview": "# Поведение прокрутки страницы\n\nПри переходе между страницами в рамках клиентской маршрутизации, можно сохранять позицию"
  },
  {
    "path": "docs/ru/guide/advanced/transitions.md",
    "chars": 1664,
    "preview": "# Анимация переходов\n\nПоскольку `<router-view>` — это просто динамический компонент, к нему можно применять анимацию пер"
  },
  {
    "path": "docs/ru/guide/essentials/dynamic-matching.md",
    "chars": 4743,
    "preview": "# Динамические пути\n\nОчень часто нам требуется сопоставить маршруты с заданным шаблоном с одним и тем же компонентом. На"
  },
  {
    "path": "docs/ru/guide/essentials/history-mode.md",
    "chars": 4661,
    "preview": "# Режим HTML5 History\n\nПо умолчанию `vue-router` работает в режиме _хэша_ — он использует хэш URL для симуляции полного "
  },
  {
    "path": "docs/ru/guide/essentials/named-routes.md",
    "chars": 928,
    "preview": "# Именованные маршруты\n\nИногда удобнее определять маршрут по имени, особенно при привязке к маршруту или выполнении нави"
  },
  {
    "path": "docs/ru/guide/essentials/named-views.md",
    "chars": 3384,
    "preview": "# Именованные представления\n\nИногда вам необходимо отображать сразу несколько представлений, а не вкладывать одно из них"
  },
  {
    "path": "docs/ru/guide/essentials/navigation.md",
    "chars": 4303,
    "preview": "---\nsidebarDepth: 0\n---\n\n# Программная навигация\n\nПомимо декларативного использования `<router-link>` для создания ссыло"
  },
  {
    "path": "docs/ru/guide/essentials/nested-routes.md",
    "chars": 3299,
    "preview": "# Вложенные маршруты\n\nПользовательский интерфейс реальных приложений обычно представлен многоуровневой иерархией компоне"
  },
  {
    "path": "docs/ru/guide/essentials/passing-props.md",
    "chars": 2557,
    "preview": "# Передача входных параметров в компоненты маршрута\n\nИспользование `$route` в вашем компоненте создаёт жёсткую связь с м"
  },
  {
    "path": "docs/ru/guide/essentials/redirect-and-alias.md",
    "chars": 1968,
    "preview": "# Перенаправления и псевдонимы\n\n## Перенаправления\n\nПеренаправления также определяются в конфигурации маршрутов в опции "
  },
  {
    "path": "docs/ru/installation.md",
    "chars": 1645,
    "preview": "# Установка\n\n## Скачивание напрямую / CDN\n\n[https://unpkg.com/vue-router@3/dist/vue-router.js](https://unpkg.com/vue-rou"
  },
  {
    "path": "docs/zh/README.md",
    "chars": 892,
    "preview": "---\nhome: true\nheroImage: /logo.png\nactionText: Get Started →\nactionLink: /zh/installation.html\nfooter: MIT Licensed | C"
  },
  {
    "path": "docs/zh/api/README.md",
    "chars": 11801,
    "preview": "---\nsidebar: auto\n---\n\n# API 参考\n\n## `<router-link>`\n\n`<router-link>` 组件支持用户在具有路由功能的应用中 (点击) 导航。\n通过 `to` 属性指定目标地址,默认渲染成带有"
  },
  {
    "path": "docs/zh/guide/README.md",
    "chars": 2449,
    "preview": "# 起步\n\n::: tip 注意\n教程中的案例代码将使用 [ES2015](https://github.com/lukehoban/es6features) 来编写。\n\n同时,所有的例子都将使用完整版的 Vue 以解析模板。更多细节请[移"
  },
  {
    "path": "docs/zh/guide/advanced/data-fetching.md",
    "chars": 2122,
    "preview": "# 数据获取\n\n有时候,进入某个路由后,需要从服务器获取数据。例如,在渲染用户信息时,你需要从服务器获取用户的数据。我们可以通过两种方式来实现:\n\n- **导航完成之后获取**:先完成导航,然后在接下来的组件生命周期钩子中获取数据。在数据获"
  },
  {
    "path": "docs/zh/guide/advanced/lazy-loading.md",
    "chars": 1672,
    "preview": "# 路由懒加载\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/lessons/how-to-lazy-load-routes-with-vue-router?friend=vue"
  },
  {
    "path": "docs/zh/guide/advanced/meta.md",
    "chars": 994,
    "preview": "# 路由元信息\n\n定义路由的时候可以配置 `meta` 字段:\n\n``` js\nconst router = new VueRouter({\n  routes: [\n    {\n      path: '/foo',\n      compo"
  },
  {
    "path": "docs/zh/guide/advanced/navigation-failures.md",
    "chars": 1895,
    "preview": "# 导航故障\n\n> 3.4.0中新增\n\n::: tip 译者注\n*导航故障*,或者叫*导航失败*,表示一次失败的导航,原文叫 navigation failures,本文统一采用*导航故障*。\n:::\n\n当使用 `router-link` "
  },
  {
    "path": "docs/zh/guide/advanced/navigation-guards.md",
    "chars": 4140,
    "preview": "# 导航守卫\n\n::: tip 译者注\n“导航”表示路由正在发生改变。\n:::\n\n正如其名,`vue-router` 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的"
  },
  {
    "path": "docs/zh/guide/advanced/scroll-behavior.md",
    "chars": 2154,
    "preview": "# 滚动行为\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/lessons/how-to-control-the-scroll-behavior-of-vue-router?fr"
  },
  {
    "path": "docs/zh/guide/advanced/transitions.md",
    "chars": 1350,
    "preview": "# 过渡动效\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/lessons/how-to-create-route-transitions-with-vue-router?fri"
  },
  {
    "path": "docs/zh/guide/essentials/dynamic-matching.md",
    "chars": 3016,
    "preview": "# 动态路由匹配\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/lessons/vue-router-dynamic-routes?friend=vuerouter\" targe"
  },
  {
    "path": "docs/zh/guide/essentials/history-mode.md",
    "chars": 3326,
    "preview": "# HTML5 History 模式\n\n`vue-router` 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。\n\n如果不想要很丑的 hash,我们可以用路由的 "
  },
  {
    "path": "docs/zh/guide/essentials/named-routes.md",
    "chars": 878,
    "preview": "# 命名路由\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/lessons/vue-router-named-routes-and-params?friend=vuerouter"
  },
  {
    "path": "docs/zh/guide/essentials/named-views.md",
    "chars": 2289,
    "preview": "# 命名视图\n\n有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 `sidebar` (侧导航) 和 `main` (主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只"
  },
  {
    "path": "docs/zh/guide/essentials/navigation.md",
    "chars": 2699,
    "preview": "---\nsidebarDepth: 0\n---\n\n# 编程式的导航\n\n除了使用 `<router-link>` 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。\n\n## `router.push("
  },
  {
    "path": "docs/zh/guide/essentials/nested-routes.md",
    "chars": 2452,
    "preview": "# 嵌套路由\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/lessons/vue-router-nested-routes?friend=vuerouter\" target=\""
  },
  {
    "path": "docs/zh/guide/essentials/passing-props.md",
    "chars": 1796,
    "preview": "# 路由组件传参\n\n<div class=\"vueschool\"><a href=\"https://vueschool.io/lessons/how-to-pass-vue-router-params-as-props-to-compone"
  },
  {
    "path": "docs/zh/guide/essentials/redirect-and-alias.md",
    "chars": 1087,
    "preview": "# 重定向和别名\n\n## 重定向\n\n重定向也是通过 `routes` 配置来完成,下面例子是从 `/a` 重定向到 `/b`:\n\n``` js\nconst router = new VueRouter({\n  routes: [\n    {"
  },
  {
    "path": "docs/zh/installation.md",
    "chars": 1062,
    "preview": "# 安装\n\n### 直接下载 / CDN\n\n[https://unpkg.com/vue-router@3/dist/vue-router.js](https://unpkg.com/vue-router@3/dist/vue-router"
  },
  {
    "path": "docs-gitbook/LANGS.md",
    "chars": 156,
    "preview": "* [English](en/)\n* [French](fr/)\n* [Japanese](ja/)\n* [中文](zh-cn/)\n* [German](de/)\n* [Русский](ru/)\n* [한국어(Korean)](kr/)\n"
  },
  {
    "path": "docs-gitbook/assets/CNAME",
    "chars": 17,
    "preview": "router.vuejs.org\n"
  },
  {
    "path": "docs-gitbook/assets/circle.yml",
    "chars": 50,
    "preview": "general:\n  branches:\n    ignore:\n      - gh-pages\n"
  },
  {
    "path": "docs-gitbook/book.json",
    "chars": 435,
    "preview": "{\n  \"title\": \"vue-router\",\n  \"gitbook\": \">3.0.0\",\n  \"plugins\": [\"edit-link\", \"theme-vuejs\", \"-fontsettings\", \"github\"],\n"
  },
  {
    "path": "docs-gitbook/de/SUMMARY.md",
    "chars": 1371,
    "preview": "# vue-router\n\n<!--email_off-->\n> Merke: vue-router@2.x ist nur mit Vue 2.x kompatibel. Dokumentation für 0.7.x ist [hier"
  },
  {
    "path": "docs-gitbook/de/advanced/data-fetching.md",
    "chars": 3617,
    "preview": "# Daten laden\n\nOftmals müssen wir Daten von einem Server laden, sobald eine Route aktiviert wird. Zum Beispiel müssen di"
  },
  {
    "path": "docs-gitbook/de/advanced/lazy-loading.md",
    "chars": 2161,
    "preview": "# Lazy Loading\n\nWenn Apps mit einem Bundler erstellt werden, kann das erzeugte \"Bundle\" recht groß werden und so die Sei"
  },
  {
    "path": "docs-gitbook/de/advanced/meta.md",
    "chars": 1543,
    "preview": "# Route Meta-Felder\n\nIn der Route-Definition kann man ein Meta-Feld definieren:\n\n``` js\nconst router = new VueRouter({\n "
  },
  {
    "path": "docs-gitbook/de/advanced/navigation-guards.md",
    "chars": 4129,
    "preview": "# Navigation Guards (\"Navigations-Wächter\")\n\nWie der Name schon andeutet, werden \"navigation guards\" `vue-router` primär"
  },
  {
    "path": "docs-gitbook/de/advanced/scroll-behavior.md",
    "chars": 2016,
    "preview": "# Scroll-Verhalten\n\nOft wollen wir, dass die Seite nach oben scrollt, wenn zu einer neuen Route navigiert wird, oder das"
  },
  {
    "path": "docs-gitbook/de/advanced/transitions.md",
    "chars": 1549,
    "preview": "# Transitions (Übergänge)\n\nDa `<router-view>` im Grunde eine dynamische Komponente ist, kann man Übergangs-Effekte mit d"
  },
  {
    "path": "docs-gitbook/de/api/component-injections.md",
    "chars": 614,
    "preview": "# Injektion von Komponenten\n\n### Injizierte Eigenschaften\n\nDie folgenden Eigenschaften werden in jede Child-Komponente i"
  },
  {
    "path": "docs-gitbook/de/api/options.md",
    "chars": 1856,
    "preview": "# Optionen des Router-Konstruktors\n\n### routes\n\n- Typ: `Array<RouteConfig>`\n\n  Typendeklaration für `RouteConfig`:\n\n  ``"
  },
  {
    "path": "docs-gitbook/de/api/route-object.md",
    "chars": 2558,
    "preview": "# Das Route-Objekt\n\nDas **Route-Objekt** repräsentiert den Zustand der aktuell aktiven Route. Es enthält geparste Inform"
  },
  {
    "path": "docs-gitbook/de/api/router-instance.md",
    "chars": 1954,
    "preview": "# Router-Instanz\n\n### Eigenschaften\n\n#### router.app\n\n- Typ: `Vue instance`\n\n  Die grundlegende Vue-Instanz, in die `rou"
  },
  {
    "path": "docs-gitbook/de/api/router-link.md",
    "chars": 4426,
    "preview": "# `<router-link>`\n\n`<router-link>` ist eine Komponente zum Auslösen von Nutzernavigationen. Die Ziel-Route wird mit der "
  },
  {
    "path": "docs-gitbook/de/api/router-view.md",
    "chars": 1060,
    "preview": "# `<router-view>`\n\nDie `<router-view>`-Komponente ist eine 'functional' Komponente, die die gematchte Komponente zum geg"
  },
  {
    "path": "docs-gitbook/de/essentials/dynamic-matching.md",
    "chars": 3323,
    "preview": "# Dynamisches Route-Matching\n\nHäufig müssen wir URLs, die einem bestimmten Muster entsprechen, einer Route bzw. Komponen"
  },
  {
    "path": "docs-gitbook/de/essentials/getting-started.md",
    "chars": 2929,
    "preview": "# Erste Schritte\n\n> Hinweis: Wir benutzen [ES2015](https://github.com/lukehoban/es6features) in den Code-Beispielen.\n\nEi"
  },
  {
    "path": "docs-gitbook/de/essentials/history-mode.md",
    "chars": 2232,
    "preview": "# HTML5-Verlaufsmodus (\"History Mode\")\n\nDer Standardmodus für `vue-router` ist der _Hash-Modus_. Er nutzt den URL-Hash, "
  },
  {
    "path": "docs-gitbook/de/essentials/named-routes.md",
    "chars": 908,
    "preview": "# Benannte Routes\n\nManchmal ist es einfacher, eine Route mit einem Namen anzusprechen. Besonders bei Links zu einer Rout"
  },
  {
    "path": "docs-gitbook/de/essentials/named-views.md",
    "chars": 995,
    "preview": "# Benannte Views\n\nManchmal muss man mehrere Views zur selben Zeit darstellen, anstatt sie zu verschachteln. Zum Beispiel"
  },
  {
    "path": "docs-gitbook/de/essentials/navigation.md",
    "chars": 3144,
    "preview": "# Programmatische Navigation\n\nNeben `router-link` für deklarative Links in Templates, können wir mit Hilfe der Methoden "
  },
  {
    "path": "docs-gitbook/de/essentials/nested-routes.md",
    "chars": 3626,
    "preview": "# Verschachtelte Routes\n\nEchte App-UIs bestehen normalerweise aus Komponenten, die mehrere Ebenen tief verschachtelt sin"
  },
  {
    "path": "docs-gitbook/de/essentials/redirect-and-alias.md",
    "chars": 1743,
    "preview": "# Redirect und Alias\n\n### Redirect (Umleitung)\n\nEin Redirect bedeutet, dass, wenn der Nutzer `/a` besucht, die URL mit `"
  },
  {
    "path": "docs-gitbook/de/installation.md",
    "chars": 1198,
    "preview": "# Installation\n\n### Direkter Download / CDN\n\n[https://unpkg.com/vue-router](https://unpkg.com/vue-router)\n\n<!--email_off"
  },
  {
    "path": "docs-gitbook/es/README.md",
    "chars": 29,
    "preview": "{% include \"./SUMMARY.md\" %}\n"
  },
  {
    "path": "docs-gitbook/es/SUMMARY.md",
    "chars": 1987,
    "preview": "# vue-router\n<!--email_off-->\n> Notas: vue-router@2.x funciona solamente con Vue 2.x. La documentación para la versión 0"
  },
  {
    "path": "docs-gitbook/es/advanced/data-fetching.md",
    "chars": 3498,
    "preview": "# Obtención de datos\n\nA veces es necesario obtener datos del servidor cuando una ruta es activada. Por ejemplo, antes de"
  },
  {
    "path": "docs-gitbook/es/advanced/lazy-loading.md",
    "chars": 2181,
    "preview": "# Lazy loading\n\nCuando se construyen aplicaciones con un sistema de empaquetamiento de módulos, el archivo JavaScript re"
  },
  {
    "path": "docs-gitbook/es/advanced/meta.md",
    "chars": 1634,
    "preview": "# Campos Meta en las rutas\n\nPuedes incluir un campo `meta` cuando definas una ruta:\n\n``` js\nconst router = new VueRouter"
  },
  {
    "path": "docs-gitbook/es/advanced/navigation-guards.md",
    "chars": 6095,
    "preview": "# Guardias de navegación\n\nComo el nombre sugiere, las guardias de navegación provistas por `vue-router` son básicamente "
  },
  {
    "path": "docs-gitbook/es/advanced/scroll-behavior.md",
    "chars": 2120,
    "preview": "# Comportamiento del scroll\n\nCuando se utiliza enrutamiento del lado cliente, podemos querer hacer `scroll` hacia el ini"
  },
  {
    "path": "docs-gitbook/es/advanced/transitions.md",
    "chars": 1583,
    "preview": "# Transiciones\n\nDado que `<router-view>` es esencialmente un componente dinámico, podemos aplicarle efectos de transició"
  },
  {
    "path": "docs-gitbook/es/api/component-injections.md",
    "chars": 622,
    "preview": "# Inyección en componentes\n\n### Propiedades inyectadas\n\nEstas propiedades son inyectadas dentro de cada componente hijo "
  },
  {
    "path": "docs-gitbook/es/api/options.md",
    "chars": 3097,
    "preview": "# Opciones del constructor de Router\n\n### routes\n\n- tipo: `Array<RouteConfig>`\n\n  Declaración de tipos para `RouteConfig"
  },
  {
    "path": "docs-gitbook/es/api/route-object.md",
    "chars": 2626,
    "preview": "# El objeto Route\n\nUn **objeto Route** representa el estado de la ruta activa actualmente. Contiene información analizad"
  },
  {
    "path": "docs-gitbook/es/api/router-instance.md",
    "chars": 2979,
    "preview": "# La instancia de Router\n\n### Propiedades\n\n#### router.app\n\n- tipo: `Vue instance`\n\n  La instancia principal de Vue dond"
  },
  {
    "path": "docs-gitbook/es/api/router-link.md",
    "chars": 5212,
    "preview": "# `<router-link>`\n\n`<router-link>` es el componente para posibilitar la navegación de los usuarios en una aplicación con"
  },
  {
    "path": "docs-gitbook/es/api/router-view.md",
    "chars": 1113,
    "preview": "# `<router-view>`\n\nEl componente `<router-view>` es un componente funcional que renderiza a otro en base a la ruta selec"
  },
  {
    "path": "docs-gitbook/es/essentials/dynamic-matching.md",
    "chars": 3491,
    "preview": "# Matching dinámico de rutas\n\nEs bastante común tener que mapear rutas con un patrón determinado al mismo componente. Po"
  },
  {
    "path": "docs-gitbook/es/essentials/getting-started.md",
    "chars": 2814,
    "preview": "# Primeros pasos\n\n> Utilizaremos [ES2015](https://github.com/lukehoban/es6features) en el código de los ejemplos en esta"
  },
  {
    "path": "docs-gitbook/es/essentials/history-mode.md",
    "chars": 2297,
    "preview": "# Modo historia HTML5\n\nEl modo por defecto para `vue-router` es _hash mode_ - el cual utiliza una almohadilla para simul"
  },
  {
    "path": "docs-gitbook/es/essentials/named-routes.md",
    "chars": 922,
    "preview": "# Rutas con nombre\n\n A veces es conveniente identificar una ruta con un nombre, especialmente cuando enlazamos a esa rut"
  },
  {
    "path": "docs-gitbook/es/essentials/named-views.md",
    "chars": 1054,
    "preview": "# Vistas con nombre\n\nA veces es necesario mostrar múltiples vistas al mismo tiempo en lugar de anidarlas. Por ejemplo, c"
  },
  {
    "path": "docs-gitbook/es/essentials/navigation.md",
    "chars": 3296,
    "preview": "# Navegación mediante código\n\nAdemás de utilizar `<router-link>` para crear etiquetas `a` para una navegación declarativ"
  },
  {
    "path": "docs-gitbook/es/essentials/nested-routes.md",
    "chars": 3305,
    "preview": "# Sub-rutas\n\nLas interfaces de usuario (UI por sus siglas en inglés) de aplicaciones reales normalmente están compuestas"
  },
  {
    "path": "docs-gitbook/es/essentials/passing-props.md",
    "chars": 2278,
    "preview": "# Pasando propiedades a componentes de ruteo\n\nUsar `$route` en tu componente genera un acoplamiento estrecho con la ruta"
  },
  {
    "path": "docs-gitbook/es/essentials/redirect-and-alias.md",
    "chars": 1696,
    "preview": "# Redireccionamiento y alias\n\n### Redireccionamiento\n\nEl redireccionamiento también se realiza en la configuración de `r"
  },
  {
    "path": "docs-gitbook/es/installation.md",
    "chars": 1244,
    "preview": "# Instalación\n\n### Descarga directa / CDN\n\n[https://unpkg.com/vue-router/dist/vue-router.js](https://unpkg.com/vue-route"
  },
  {
    "path": "docs-gitbook/fr/README.md",
    "chars": 29,
    "preview": "{% include \"./SUMMARY.md\" %}\n"
  }
]

// ... and 258 more files (download for full content)

About this extraction

This page contains the full source code of the vuejs/vue-router GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 458 files (1.4 MB), approximately 433.3k tokens, and a symbol index with 740 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!