#
tokens: 41814/50000 2/252 files (page 5/10)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 5 of 10. Use http://codebase.md/jakedismo/master-mcp-server?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .env.example
├── .eslintignore
├── .eslintrc.cjs
├── .eslintrc.js
├── .gitignore
├── .prettierignore
├── .prettierrc
├── .prettierrc.json
├── CHANGELOG.md
├── config
│   ├── default.json
│   ├── development.json
│   ├── production.json
│   └── schema.json
├── config.json
├── CONTRIBUTING.md
├── debug-stdio.cjs
├── debug-stdio.js
├── deploy
│   ├── cloudflare
│   │   ├── .gitkeep
│   │   ├── README.md
│   │   └── wrangler.toml
│   ├── docker
│   │   ├── .gitkeep
│   │   ├── docker-compose.yml
│   │   ├── Dockerfile
│   │   └── entrypoint.sh
│   ├── koyeb
│   │   ├── .gitkeep
│   │   └── koyeb.yaml
│   └── README.md
├── docker-compose.yml
├── Dockerfile
├── docs
│   ├── .DS_Store
│   ├── .vitepress
│   │   ├── cache
│   │   │   └── deps
│   │   │       ├── _metadata.json
│   │   │       ├── chunk-HVR2FF6M.js
│   │   │       ├── chunk-HVR2FF6M.js.map
│   │   │       ├── chunk-P2XGSYO7.js
│   │   │       ├── chunk-P2XGSYO7.js.map
│   │   │       ├── package.json
│   │   │       ├── vitepress___@vue_devtools-api.js
│   │   │       ├── vitepress___@vue_devtools-api.js.map
│   │   │       ├── vitepress___@vueuse_core.js
│   │   │       ├── vitepress___@vueuse_core.js.map
│   │   │       ├── vitepress___@vueuse_integrations_useFocusTrap.js
│   │   │       ├── vitepress___@vueuse_integrations_useFocusTrap.js.map
│   │   │       ├── vitepress___mark__js_src_vanilla__js.js
│   │   │       ├── vitepress___mark__js_src_vanilla__js.js.map
│   │   │       ├── vitepress___minisearch.js
│   │   │       ├── vitepress___minisearch.js.map
│   │   │       ├── vue.js
│   │   │       └── vue.js.map
│   │   ├── config.ts
│   │   ├── dist
│   │   │   ├── 404.html
│   │   │   ├── advanced
│   │   │   │   ├── extensibility.html
│   │   │   │   ├── index.html
│   │   │   │   ├── monitoring.html
│   │   │   │   ├── performance.html
│   │   │   │   └── security.html
│   │   │   ├── api
│   │   │   │   ├── index.html
│   │   │   │   └── README.html
│   │   │   ├── assets
│   │   │   │   ├── advanced_extensibility.md.TrXUn5w5.js
│   │   │   │   ├── advanced_extensibility.md.TrXUn5w5.lean.js
│   │   │   │   ├── advanced_index.md.CPcpUlw_.js
│   │   │   │   ├── advanced_index.md.CPcpUlw_.lean.js
│   │   │   │   ├── advanced_monitoring.md.DTybdNg-.js
│   │   │   │   ├── advanced_monitoring.md.DTybdNg-.lean.js
│   │   │   │   ├── advanced_performance.md.DKmzK0ia.js
│   │   │   │   ├── advanced_performance.md.DKmzK0ia.lean.js
│   │   │   │   ├── advanced_security.md.B-oBD7IB.js
│   │   │   │   ├── advanced_security.md.B-oBD7IB.lean.js
│   │   │   │   ├── api_index.md.Dl1JB08_.js
│   │   │   │   ├── api_index.md.Dl1JB08_.lean.js
│   │   │   │   ├── chunks
│   │   │   │   │   └── framework.CHl2ywxc.js
│   │   │   │   ├── configuration_environment-variables.md.Ddy3P_Wz.js
│   │   │   │   ├── configuration_environment-variables.md.Ddy3P_Wz.lean.js
│   │   │   │   ├── configuration_environment.md.DxcTQ623.js
│   │   │   │   ├── configuration_environment.md.DxcTQ623.lean.js
│   │   │   │   ├── configuration_overview.md.DIkVDv7V.js
│   │   │   │   ├── configuration_overview.md.DIkVDv7V.lean.js
│   │   │   │   ├── configuration_performance.md.DbJdmLrW.js
│   │   │   │   ├── configuration_performance.md.DbJdmLrW.lean.js
│   │   │   │   ├── configuration_reference.md.27IKWqtk.js
│   │   │   │   ├── configuration_reference.md.27IKWqtk.lean.js
│   │   │   │   ├── configuration_security.md.-OOlkzN4.js
│   │   │   │   ├── configuration_security.md.-OOlkzN4.lean.js
│   │   │   │   ├── contributing_dev-setup.md.Ceqh4w-R.js
│   │   │   │   ├── contributing_dev-setup.md.Ceqh4w-R.lean.js
│   │   │   │   ├── contributing_guidelines.md.ZEAX2yVh.js
│   │   │   │   ├── contributing_guidelines.md.ZEAX2yVh.lean.js
│   │   │   │   ├── contributing_index.md.DYq9R6wr.js
│   │   │   │   ├── contributing_index.md.DYq9R6wr.lean.js
│   │   │   │   ├── contributing_maintenance.md.k2bR0IaR.js
│   │   │   │   ├── contributing_maintenance.md.k2bR0IaR.lean.js
│   │   │   │   ├── deployment_cicd.md.Ci2T0UYC.js
│   │   │   │   ├── deployment_cicd.md.Ci2T0UYC.lean.js
│   │   │   │   ├── deployment_cloudflare-workers.md.D2WHsfep.js
│   │   │   │   ├── deployment_cloudflare-workers.md.D2WHsfep.lean.js
│   │   │   │   ├── deployment_docker.md.B8bQDQTo.js
│   │   │   │   ├── deployment_docker.md.B8bQDQTo.lean.js
│   │   │   │   ├── deployment_index.md.ClYeOkpy.js
│   │   │   │   ├── deployment_index.md.ClYeOkpy.lean.js
│   │   │   │   ├── deployment_koyeb.md.B_wJhvF7.js
│   │   │   │   ├── deployment_koyeb.md.B_wJhvF7.lean.js
│   │   │   │   ├── examples_advanced-routing.md.B3CqhLZ7.js
│   │   │   │   ├── examples_advanced-routing.md.B3CqhLZ7.lean.js
│   │   │   │   ├── examples_basic-node.md.CaDZzGlO.js
│   │   │   │   ├── examples_basic-node.md.CaDZzGlO.lean.js
│   │   │   │   ├── examples_cloudflare-worker.md.DwVSz-c7.js
│   │   │   │   ├── examples_cloudflare-worker.md.DwVSz-c7.lean.js
│   │   │   │   ├── examples_index.md.CBF_BLkl.js
│   │   │   │   ├── examples_index.md.CBF_BLkl.lean.js
│   │   │   │   ├── examples_oauth-delegation.md.1hZxoqDl.js
│   │   │   │   ├── examples_oauth-delegation.md.1hZxoqDl.lean.js
│   │   │   │   ├── examples_overview.md.CZN0JbZ7.js
│   │   │   │   ├── examples_overview.md.CZN0JbZ7.lean.js
│   │   │   │   ├── examples_testing.md.Dek4GpNs.js
│   │   │   │   ├── examples_testing.md.Dek4GpNs.lean.js
│   │   │   │   ├── getting-started_concepts.md.D7ON9iGB.js
│   │   │   │   ├── getting-started_concepts.md.D7ON9iGB.lean.js
│   │   │   │   ├── getting-started_installation.md.BKnVqAGg.js
│   │   │   │   ├── getting-started_installation.md.BKnVqAGg.lean.js
│   │   │   │   ├── getting-started_overview.md.DvJDFL2N.js
│   │   │   │   ├── getting-started_overview.md.DvJDFL2N.lean.js
│   │   │   │   ├── getting-started_quickstart-node.md.GOO4aGas.js
│   │   │   │   ├── getting-started_quickstart-node.md.GOO4aGas.lean.js
│   │   │   │   ├── getting-started_quickstart-workers.md.Cpofh8Mj.js
│   │   │   │   ├── getting-started_quickstart-workers.md.Cpofh8Mj.lean.js
│   │   │   │   ├── getting-started.md.DG9ndneo.js
│   │   │   │   ├── getting-started.md.DG9ndneo.lean.js
│   │   │   │   ├── guides_configuration-management.md.B-jwYMbA.js
│   │   │   │   ├── guides_configuration-management.md.B-jwYMbA.lean.js
│   │   │   │   ├── guides_configuration.md.Ci3zYDFA.js
│   │   │   │   ├── guides_configuration.md.Ci3zYDFA.lean.js
│   │   │   │   ├── guides_index.md.CIlq2fmx.js
│   │   │   │   ├── guides_index.md.CIlq2fmx.lean.js
│   │   │   │   ├── guides_module-loading.md.BkJvuRnQ.js
│   │   │   │   ├── guides_module-loading.md.BkJvuRnQ.lean.js
│   │   │   │   ├── guides_oauth-delegation.md.DEOZ-_G0.js
│   │   │   │   ├── guides_oauth-delegation.md.DEOZ-_G0.lean.js
│   │   │   │   ├── guides_request-routing.md.Bdzf0VLg.js
│   │   │   │   ├── guides_request-routing.md.Bdzf0VLg.lean.js
│   │   │   │   ├── guides_testing.md.kYfHqJLu.js
│   │   │   │   ├── guides_testing.md.kYfHqJLu.lean.js
│   │   │   │   ├── inter-italic-cyrillic-ext.r48I6akx.woff2
│   │   │   │   ├── inter-italic-cyrillic.By2_1cv3.woff2
│   │   │   │   ├── inter-italic-greek-ext.1u6EdAuj.woff2
│   │   │   │   ├── inter-italic-greek.DJ8dCoTZ.woff2
│   │   │   │   ├── inter-italic-latin-ext.CN1xVJS-.woff2
│   │   │   │   ├── inter-italic-latin.C2AdPX0b.woff2
│   │   │   │   ├── inter-italic-vietnamese.BSbpV94h.woff2
│   │   │   │   ├── inter-roman-cyrillic-ext.BBPuwvHQ.woff2
│   │   │   │   ├── inter-roman-cyrillic.C5lxZ8CY.woff2
│   │   │   │   ├── inter-roman-greek-ext.CqjqNYQ-.woff2
│   │   │   │   ├── inter-roman-greek.BBVDIX6e.woff2
│   │   │   │   ├── inter-roman-latin-ext.4ZJIpNVo.woff2
│   │   │   │   ├── inter-roman-latin.Di8DUHzh.woff2
│   │   │   │   ├── inter-roman-vietnamese.BjW4sHH5.woff2
│   │   │   │   ├── README.md.BO5r5M9u.js
│   │   │   │   ├── README.md.BO5r5M9u.lean.js
│   │   │   │   ├── style.BQrfSMzK.css
│   │   │   │   ├── troubleshooting_common-issues.md.CScvzWM1.js
│   │   │   │   ├── troubleshooting_common-issues.md.CScvzWM1.lean.js
│   │   │   │   ├── troubleshooting_deployment.md.DUhpqnLE.js
│   │   │   │   ├── troubleshooting_deployment.md.DUhpqnLE.lean.js
│   │   │   │   ├── troubleshooting_errors.md.BSCsEmGc.js
│   │   │   │   ├── troubleshooting_errors.md.BSCsEmGc.lean.js
│   │   │   │   ├── troubleshooting_oauth.md.Cw60Eka3.js
│   │   │   │   ├── troubleshooting_oauth.md.Cw60Eka3.lean.js
│   │   │   │   ├── troubleshooting_performance.md.DxY6LJcT.js
│   │   │   │   ├── troubleshooting_performance.md.DxY6LJcT.lean.js
│   │   │   │   ├── troubleshooting_routing.md.BHN-MDhs.js
│   │   │   │   ├── troubleshooting_routing.md.BHN-MDhs.lean.js
│   │   │   │   ├── troubleshooting_security-best-practices.md.Yiu8E-zt.js
│   │   │   │   ├── troubleshooting_security-best-practices.md.Yiu8E-zt.lean.js
│   │   │   │   ├── tutorials_beginner-getting-started.md.BXObgobW.js
│   │   │   │   ├── tutorials_beginner-getting-started.md.BXObgobW.lean.js
│   │   │   │   ├── tutorials_cloudflare-workers-tutorial.md.MPHsc0aT.js
│   │   │   │   ├── tutorials_cloudflare-workers-tutorial.md.MPHsc0aT.lean.js
│   │   │   │   ├── tutorials_load-balancing-and-resilience.md.Dv9r9jyW.js
│   │   │   │   ├── tutorials_load-balancing-and-resilience.md.Dv9r9jyW.lean.js
│   │   │   │   ├── tutorials_oauth-delegation-github.md.Nq4glqCe.js
│   │   │   │   └── tutorials_oauth-delegation-github.md.Nq4glqCe.lean.js
│   │   │   ├── configuration
│   │   │   │   ├── environment-variables.html
│   │   │   │   ├── environment.html
│   │   │   │   ├── examples.html
│   │   │   │   ├── overview.html
│   │   │   │   ├── performance.html
│   │   │   │   ├── reference.html
│   │   │   │   └── security.html
│   │   │   ├── contributing
│   │   │   │   ├── dev-setup.html
│   │   │   │   ├── guidelines.html
│   │   │   │   ├── index.html
│   │   │   │   └── maintenance.html
│   │   │   ├── deployment
│   │   │   │   ├── cicd.html
│   │   │   │   ├── cloudflare-workers.html
│   │   │   │   ├── docker.html
│   │   │   │   ├── index.html
│   │   │   │   └── koyeb.html
│   │   │   ├── diagrams
│   │   │   │   └── architecture.svg
│   │   │   ├── examples
│   │   │   │   ├── advanced-routing.html
│   │   │   │   ├── basic-node.html
│   │   │   │   ├── cloudflare-worker.html
│   │   │   │   ├── index.html
│   │   │   │   ├── oauth-delegation.html
│   │   │   │   ├── overview.html
│   │   │   │   └── testing.html
│   │   │   ├── getting-started
│   │   │   │   ├── concepts.html
│   │   │   │   ├── installation.html
│   │   │   │   ├── overview.html
│   │   │   │   ├── quick-start.html
│   │   │   │   ├── quickstart-node.html
│   │   │   │   └── quickstart-workers.html
│   │   │   ├── getting-started.html
│   │   │   ├── guides
│   │   │   │   ├── authentication.html
│   │   │   │   ├── client-integration.html
│   │   │   │   ├── configuration-management.html
│   │   │   │   ├── configuration.html
│   │   │   │   ├── index.html
│   │   │   │   ├── module-loading.html
│   │   │   │   ├── oauth-delegation.html
│   │   │   │   ├── request-routing.html
│   │   │   │   ├── server-management.html
│   │   │   │   ├── server-sharing.html
│   │   │   │   └── testing.html
│   │   │   ├── hashmap.json
│   │   │   ├── index.html
│   │   │   ├── logo.svg
│   │   │   ├── README.html
│   │   │   ├── reports
│   │   │   │   └── mcp-compliance-audit.html
│   │   │   ├── troubleshooting
│   │   │   │   ├── common-issues.html
│   │   │   │   ├── deployment.html
│   │   │   │   ├── errors.html
│   │   │   │   ├── index.html
│   │   │   │   ├── oauth.html
│   │   │   │   ├── performance.html
│   │   │   │   ├── routing.html
│   │   │   │   └── security-best-practices.html
│   │   │   ├── tutorials
│   │   │   │   ├── beginner-getting-started.html
│   │   │   │   ├── cloudflare-workers-tutorial.html
│   │   │   │   ├── load-balancing-and-resilience.html
│   │   │   │   └── oauth-delegation-github.html
│   │   │   └── vp-icons.css
│   │   └── theme
│   │       ├── components
│   │       │   ├── ApiPlayground.vue
│   │       │   ├── AuthFlowDemo.vue
│   │       │   ├── CodeTabs.vue
│   │       │   └── ConfigGenerator.vue
│   │       ├── index.ts
│   │       └── style.css
│   ├── advanced
│   │   ├── extensibility.md
│   │   ├── index.md
│   │   ├── monitoring.md
│   │   ├── performance.md
│   │   └── security.md
│   ├── api
│   │   ├── functions
│   │   │   └── createServer.md
│   │   ├── index.md
│   │   ├── interfaces
│   │   │   └── RunningServer.md
│   │   └── README.md
│   ├── architecture
│   │   └── images
│   │       └── mcp_master_architecture.svg
│   ├── configuration
│   │   ├── environment-variables.md
│   │   ├── environment.md
│   │   ├── examples.md
│   │   ├── overview.md
│   │   ├── performance.md
│   │   ├── reference.md
│   │   └── security.md
│   ├── contributing
│   │   ├── dev-setup.md
│   │   ├── guidelines.md
│   │   ├── index.md
│   │   └── maintenance.md
│   ├── deployment
│   │   ├── cicd.md
│   │   ├── cloudflare-workers.md
│   │   ├── docker.md
│   │   ├── docs-site.md
│   │   ├── index.md
│   │   └── koyeb.md
│   ├── examples
│   │   ├── advanced-routing.md
│   │   ├── basic-node.md
│   │   ├── cloudflare-worker.md
│   │   ├── index.md
│   │   ├── oauth-delegation.md
│   │   ├── overview.md
│   │   └── testing.md
│   ├── getting-started
│   │   ├── concepts.md
│   │   ├── installation.md
│   │   ├── overview.md
│   │   ├── quick-start.md
│   │   ├── quickstart-node.md
│   │   └── quickstart-workers.md
│   ├── getting-started.md
│   ├── guides
│   │   ├── authentication.md
│   │   ├── client-integration.md
│   │   ├── configuration-management.md
│   │   ├── configuration.md
│   │   ├── index.md
│   │   ├── module-loading.md
│   │   ├── oauth-delegation.md
│   │   ├── request-routing.md
│   │   ├── server-management.md
│   │   ├── server-sharing.md
│   │   └── testing.md
│   ├── index.html
│   ├── public
│   │   ├── diagrams
│   │   │   └── architecture.svg
│   │   ├── github-social.png
│   │   │   └── image.png
│   │   ├── logo.png
│   │   └── logo.svg
│   ├── README.md
│   ├── stdio-servers.md
│   ├── testing
│   │   └── phase-9-testing-architecture.md
│   ├── troubleshooting
│   │   ├── common-issues.md
│   │   ├── deployment.md
│   │   ├── errors.md
│   │   ├── index.md
│   │   ├── oauth.md
│   │   ├── performance.md
│   │   ├── routing.md
│   │   └── security-best-practices.md
│   └── tutorials
│       ├── beginner-getting-started.md
│       ├── cloudflare-workers-tutorial.md
│       ├── load-balancing-and-resilience.md
│       └── oauth-delegation-github.md
├── examples
│   ├── advanced-routing
│   │   ├── config.yaml
│   │   └── README.md
│   ├── basic-node
│   │   ├── config.yaml
│   │   ├── README.md
│   │   └── server.ts
│   ├── cloudflare-worker
│   │   ├── README.md
│   │   └── worker.ts
│   ├── custom-auth
│   │   ├── config.yaml
│   │   ├── index.ts
│   │   └── README.md
│   ├── multi-server
│   │   ├── config.yaml
│   │   └── README.md
│   ├── oauth-delegation
│   │   └── README.md
│   ├── oauth-node
│   │   ├── config.yaml
│   │   └── README.md
│   ├── performance
│   │   ├── config.yaml
│   │   └── README.md
│   ├── sample-configs
│   │   ├── basic.yaml
│   │   └── simple-setup.yaml
│   ├── security-hardening
│   │   └── README.md
│   ├── stdio-mcp-server.cjs
│   ├── test-mcp-server.js
│   └── test-stdio-server.js
├── LICENSE
├── master-mcp-definition.md
├── package-lock.json
├── package.json
├── README.md
├── reports
│   └── claude_report_20250815_222153.html
├── scripts
│   └── generate-config-docs.ts
├── src
│   ├── auth
│   │   ├── multi-auth-manager.ts
│   │   ├── oauth-providers.ts
│   │   └── token-manager.ts
│   ├── config
│   │   ├── config-loader.ts
│   │   ├── environment-manager.ts
│   │   ├── schema-validator.ts
│   │   └── secret-manager.ts
│   ├── index.ts
│   ├── mcp-server.ts
│   ├── modules
│   │   ├── capability-aggregator.ts
│   │   ├── module-loader.ts
│   │   ├── request-router.ts
│   │   ├── stdio-capability-discovery.ts
│   │   └── stdio-manager.ts
│   ├── oauth
│   │   ├── callback-handler.ts
│   │   ├── flow-controller.ts
│   │   ├── flow-validator.ts
│   │   ├── pkce-manager.ts
│   │   ├── state-manager.ts
│   │   └── web-interface.ts
│   ├── routing
│   │   ├── circuit-breaker.ts
│   │   ├── load-balancer.ts
│   │   ├── retry-handler.ts
│   │   └── route-registry.ts
│   ├── runtime
│   │   ├── node.ts
│   │   └── worker.ts
│   ├── server
│   │   ├── config-manager.ts
│   │   ├── dependency-container.ts
│   │   ├── master-server.ts
│   │   └── protocol-handler.ts
│   ├── types
│   │   ├── auth.ts
│   │   ├── config.ts
│   │   ├── jose-shim.d.ts
│   │   ├── mcp.ts
│   │   └── server.ts
│   └── utils
│       ├── cache.ts
│       ├── crypto.ts
│       ├── dev.ts
│       ├── errors.ts
│       ├── http.ts
│       ├── logger.ts
│       ├── monitoring.ts
│       ├── string.ts
│       ├── time.ts
│       ├── validation.ts
│       └── validators.ts
├── static
│   └── oauth
│       ├── consent.html
│       ├── error.html
│       ├── script.js
│       ├── style.css
│       └── success.html
├── tests
│   ├── _setup
│   │   ├── miniflare.setup.ts
│   │   └── vitest.setup.ts
│   ├── _utils
│   │   ├── log-capture.ts
│   │   ├── mock-fetch.ts
│   │   └── test-server.ts
│   ├── .gitkeep
│   ├── e2e
│   │   ├── flow-controller.express.test.ts
│   │   └── flow-controller.worker.test.ts
│   ├── factories
│   │   ├── configFactory.ts
│   │   ├── mcpFactory.ts
│   │   └── oauthFactory.ts
│   ├── fixtures
│   │   ├── capabilities.json
│   │   └── stdio-server.js
│   ├── integration
│   │   ├── modules.capability-aggregator.test.ts
│   │   ├── modules.module-loader-health.test.ts
│   │   ├── oauth.callback-handler.test.ts
│   │   └── request-router.test.ts
│   ├── mocks
│   │   ├── mcp
│   │   │   └── fake-backend.ts
│   │   └── oauth
│   │       └── mock-oidc-provider.ts
│   ├── perf
│   │   ├── artillery
│   │   │   └── auth-routing.yaml
│   │   └── perf.auth-and-routing.test.ts
│   ├── security
│   │   └── security.oauth-and-input.test.ts
│   ├── servers
│   │   ├── test-auth-simple.js
│   │   ├── test-debug.js
│   │   ├── test-master-mcp.js
│   │   ├── test-mcp-client.js
│   │   ├── test-streaming-both-complete.js
│   │   ├── test-streaming-both-full.js
│   │   ├── test-streaming-both-simple.js
│   │   ├── test-streaming-both.js
│   │   └── test-streaming.js
│   ├── setup
│   │   └── test-setup.ts
│   ├── unit
│   │   ├── auth.multi-auth-manager.test.ts
│   │   ├── auth.token-manager.test.ts
│   │   ├── config.environment-manager.test.ts
│   │   ├── config.schema-validator.test.ts
│   │   ├── config.secret-manager.test.ts
│   │   ├── modules
│   │   │   ├── stdio-capability-discovery.test.ts
│   │   │   └── stdio-manager.test.ts
│   │   ├── modules.route-registry.test.ts
│   │   ├── oauth.pkce-state.test.ts
│   │   ├── routing
│   │   │   └── circuit-breaker.test.ts
│   │   ├── routing.core.test.ts
│   │   ├── stdio-capability-discovery.test.ts
│   │   ├── utils.crypto.test.ts
│   │   ├── utils.logger.test.ts
│   │   └── utils.monitoring.test.ts
│   └── utils
│       ├── fake-express.ts
│       ├── mock-http.ts
│       ├── oauth-mocks.ts
│       └── token-storages.ts
├── tsconfig.base.json
├── tsconfig.json
├── tsconfig.node.json
├── tsconfig.worker.json
├── typedoc.json
├── vitest.config.ts
└── vitest.worker.config.ts
```

# Files

--------------------------------------------------------------------------------
/docs/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js:
--------------------------------------------------------------------------------

```javascript
   1 | import {
   2 |   notNullish,
   3 |   toArray,
   4 |   tryOnScopeDispose,
   5 |   unrefElement
   6 | } from "./chunk-P2XGSYO7.js";
   7 | import {
   8 |   computed,
   9 |   shallowRef,
  10 |   toValue,
  11 |   watch
  12 | } from "./chunk-HVR2FF6M.js";
  13 | 
  14 | // node_modules/tabbable/dist/index.esm.js
  15 | var candidateSelectors = ["input:not([inert])", "select:not([inert])", "textarea:not([inert])", "a[href]:not([inert])", "button:not([inert])", "[tabindex]:not(slot):not([inert])", "audio[controls]:not([inert])", "video[controls]:not([inert])", '[contenteditable]:not([contenteditable="false"]):not([inert])', "details>summary:first-of-type:not([inert])", "details:not([inert])"];
  16 | var candidateSelector = candidateSelectors.join(",");
  17 | var NoElement = typeof Element === "undefined";
  18 | var matches = NoElement ? function() {
  19 | } : Element.prototype.matches || Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
  20 | var getRootNode = !NoElement && Element.prototype.getRootNode ? function(element) {
  21 |   var _element$getRootNode;
  22 |   return element === null || element === void 0 ? void 0 : (_element$getRootNode = element.getRootNode) === null || _element$getRootNode === void 0 ? void 0 : _element$getRootNode.call(element);
  23 | } : function(element) {
  24 |   return element === null || element === void 0 ? void 0 : element.ownerDocument;
  25 | };
  26 | var isInert = function isInert2(node, lookUp) {
  27 |   var _node$getAttribute;
  28 |   if (lookUp === void 0) {
  29 |     lookUp = true;
  30 |   }
  31 |   var inertAtt = node === null || node === void 0 ? void 0 : (_node$getAttribute = node.getAttribute) === null || _node$getAttribute === void 0 ? void 0 : _node$getAttribute.call(node, "inert");
  32 |   var inert = inertAtt === "" || inertAtt === "true";
  33 |   var result = inert || lookUp && node && isInert2(node.parentNode);
  34 |   return result;
  35 | };
  36 | var isContentEditable = function isContentEditable2(node) {
  37 |   var _node$getAttribute2;
  38 |   var attValue = node === null || node === void 0 ? void 0 : (_node$getAttribute2 = node.getAttribute) === null || _node$getAttribute2 === void 0 ? void 0 : _node$getAttribute2.call(node, "contenteditable");
  39 |   return attValue === "" || attValue === "true";
  40 | };
  41 | var getCandidates = function getCandidates2(el, includeContainer, filter) {
  42 |   if (isInert(el)) {
  43 |     return [];
  44 |   }
  45 |   var candidates = Array.prototype.slice.apply(el.querySelectorAll(candidateSelector));
  46 |   if (includeContainer && matches.call(el, candidateSelector)) {
  47 |     candidates.unshift(el);
  48 |   }
  49 |   candidates = candidates.filter(filter);
  50 |   return candidates;
  51 | };
  52 | var getCandidatesIteratively = function getCandidatesIteratively2(elements, includeContainer, options) {
  53 |   var candidates = [];
  54 |   var elementsToCheck = Array.from(elements);
  55 |   while (elementsToCheck.length) {
  56 |     var element = elementsToCheck.shift();
  57 |     if (isInert(element, false)) {
  58 |       continue;
  59 |     }
  60 |     if (element.tagName === "SLOT") {
  61 |       var assigned = element.assignedElements();
  62 |       var content = assigned.length ? assigned : element.children;
  63 |       var nestedCandidates = getCandidatesIteratively2(content, true, options);
  64 |       if (options.flatten) {
  65 |         candidates.push.apply(candidates, nestedCandidates);
  66 |       } else {
  67 |         candidates.push({
  68 |           scopeParent: element,
  69 |           candidates: nestedCandidates
  70 |         });
  71 |       }
  72 |     } else {
  73 |       var validCandidate = matches.call(element, candidateSelector);
  74 |       if (validCandidate && options.filter(element) && (includeContainer || !elements.includes(element))) {
  75 |         candidates.push(element);
  76 |       }
  77 |       var shadowRoot = element.shadowRoot || // check for an undisclosed shadow
  78 |       typeof options.getShadowRoot === "function" && options.getShadowRoot(element);
  79 |       var validShadowRoot = !isInert(shadowRoot, false) && (!options.shadowRootFilter || options.shadowRootFilter(element));
  80 |       if (shadowRoot && validShadowRoot) {
  81 |         var _nestedCandidates = getCandidatesIteratively2(shadowRoot === true ? element.children : shadowRoot.children, true, options);
  82 |         if (options.flatten) {
  83 |           candidates.push.apply(candidates, _nestedCandidates);
  84 |         } else {
  85 |           candidates.push({
  86 |             scopeParent: element,
  87 |             candidates: _nestedCandidates
  88 |           });
  89 |         }
  90 |       } else {
  91 |         elementsToCheck.unshift.apply(elementsToCheck, element.children);
  92 |       }
  93 |     }
  94 |   }
  95 |   return candidates;
  96 | };
  97 | var hasTabIndex = function hasTabIndex2(node) {
  98 |   return !isNaN(parseInt(node.getAttribute("tabindex"), 10));
  99 | };
 100 | var getTabIndex = function getTabIndex2(node) {
 101 |   if (!node) {
 102 |     throw new Error("No node provided");
 103 |   }
 104 |   if (node.tabIndex < 0) {
 105 |     if ((/^(AUDIO|VIDEO|DETAILS)$/.test(node.tagName) || isContentEditable(node)) && !hasTabIndex(node)) {
 106 |       return 0;
 107 |     }
 108 |   }
 109 |   return node.tabIndex;
 110 | };
 111 | var getSortOrderTabIndex = function getSortOrderTabIndex2(node, isScope) {
 112 |   var tabIndex = getTabIndex(node);
 113 |   if (tabIndex < 0 && isScope && !hasTabIndex(node)) {
 114 |     return 0;
 115 |   }
 116 |   return tabIndex;
 117 | };
 118 | var sortOrderedTabbables = function sortOrderedTabbables2(a, b) {
 119 |   return a.tabIndex === b.tabIndex ? a.documentOrder - b.documentOrder : a.tabIndex - b.tabIndex;
 120 | };
 121 | var isInput = function isInput2(node) {
 122 |   return node.tagName === "INPUT";
 123 | };
 124 | var isHiddenInput = function isHiddenInput2(node) {
 125 |   return isInput(node) && node.type === "hidden";
 126 | };
 127 | var isDetailsWithSummary = function isDetailsWithSummary2(node) {
 128 |   var r = node.tagName === "DETAILS" && Array.prototype.slice.apply(node.children).some(function(child) {
 129 |     return child.tagName === "SUMMARY";
 130 |   });
 131 |   return r;
 132 | };
 133 | var getCheckedRadio = function getCheckedRadio2(nodes, form) {
 134 |   for (var i = 0; i < nodes.length; i++) {
 135 |     if (nodes[i].checked && nodes[i].form === form) {
 136 |       return nodes[i];
 137 |     }
 138 |   }
 139 | };
 140 | var isTabbableRadio = function isTabbableRadio2(node) {
 141 |   if (!node.name) {
 142 |     return true;
 143 |   }
 144 |   var radioScope = node.form || getRootNode(node);
 145 |   var queryRadios = function queryRadios2(name) {
 146 |     return radioScope.querySelectorAll('input[type="radio"][name="' + name + '"]');
 147 |   };
 148 |   var radioSet;
 149 |   if (typeof window !== "undefined" && typeof window.CSS !== "undefined" && typeof window.CSS.escape === "function") {
 150 |     radioSet = queryRadios(window.CSS.escape(node.name));
 151 |   } else {
 152 |     try {
 153 |       radioSet = queryRadios(node.name);
 154 |     } catch (err) {
 155 |       console.error("Looks like you have a radio button with a name attribute containing invalid CSS selector characters and need the CSS.escape polyfill: %s", err.message);
 156 |       return false;
 157 |     }
 158 |   }
 159 |   var checked = getCheckedRadio(radioSet, node.form);
 160 |   return !checked || checked === node;
 161 | };
 162 | var isRadio = function isRadio2(node) {
 163 |   return isInput(node) && node.type === "radio";
 164 | };
 165 | var isNonTabbableRadio = function isNonTabbableRadio2(node) {
 166 |   return isRadio(node) && !isTabbableRadio(node);
 167 | };
 168 | var isNodeAttached = function isNodeAttached2(node) {
 169 |   var _nodeRoot;
 170 |   var nodeRoot = node && getRootNode(node);
 171 |   var nodeRootHost = (_nodeRoot = nodeRoot) === null || _nodeRoot === void 0 ? void 0 : _nodeRoot.host;
 172 |   var attached = false;
 173 |   if (nodeRoot && nodeRoot !== node) {
 174 |     var _nodeRootHost, _nodeRootHost$ownerDo, _node$ownerDocument;
 175 |     attached = !!((_nodeRootHost = nodeRootHost) !== null && _nodeRootHost !== void 0 && (_nodeRootHost$ownerDo = _nodeRootHost.ownerDocument) !== null && _nodeRootHost$ownerDo !== void 0 && _nodeRootHost$ownerDo.contains(nodeRootHost) || node !== null && node !== void 0 && (_node$ownerDocument = node.ownerDocument) !== null && _node$ownerDocument !== void 0 && _node$ownerDocument.contains(node));
 176 |     while (!attached && nodeRootHost) {
 177 |       var _nodeRoot2, _nodeRootHost2, _nodeRootHost2$ownerD;
 178 |       nodeRoot = getRootNode(nodeRootHost);
 179 |       nodeRootHost = (_nodeRoot2 = nodeRoot) === null || _nodeRoot2 === void 0 ? void 0 : _nodeRoot2.host;
 180 |       attached = !!((_nodeRootHost2 = nodeRootHost) !== null && _nodeRootHost2 !== void 0 && (_nodeRootHost2$ownerD = _nodeRootHost2.ownerDocument) !== null && _nodeRootHost2$ownerD !== void 0 && _nodeRootHost2$ownerD.contains(nodeRootHost));
 181 |     }
 182 |   }
 183 |   return attached;
 184 | };
 185 | var isZeroArea = function isZeroArea2(node) {
 186 |   var _node$getBoundingClie = node.getBoundingClientRect(), width = _node$getBoundingClie.width, height = _node$getBoundingClie.height;
 187 |   return width === 0 && height === 0;
 188 | };
 189 | var isHidden = function isHidden2(node, _ref) {
 190 |   var displayCheck = _ref.displayCheck, getShadowRoot = _ref.getShadowRoot;
 191 |   if (getComputedStyle(node).visibility === "hidden") {
 192 |     return true;
 193 |   }
 194 |   var isDirectSummary = matches.call(node, "details>summary:first-of-type");
 195 |   var nodeUnderDetails = isDirectSummary ? node.parentElement : node;
 196 |   if (matches.call(nodeUnderDetails, "details:not([open]) *")) {
 197 |     return true;
 198 |   }
 199 |   if (!displayCheck || displayCheck === "full" || displayCheck === "legacy-full") {
 200 |     if (typeof getShadowRoot === "function") {
 201 |       var originalNode = node;
 202 |       while (node) {
 203 |         var parentElement = node.parentElement;
 204 |         var rootNode = getRootNode(node);
 205 |         if (parentElement && !parentElement.shadowRoot && getShadowRoot(parentElement) === true) {
 206 |           return isZeroArea(node);
 207 |         } else if (node.assignedSlot) {
 208 |           node = node.assignedSlot;
 209 |         } else if (!parentElement && rootNode !== node.ownerDocument) {
 210 |           node = rootNode.host;
 211 |         } else {
 212 |           node = parentElement;
 213 |         }
 214 |       }
 215 |       node = originalNode;
 216 |     }
 217 |     if (isNodeAttached(node)) {
 218 |       return !node.getClientRects().length;
 219 |     }
 220 |     if (displayCheck !== "legacy-full") {
 221 |       return true;
 222 |     }
 223 |   } else if (displayCheck === "non-zero-area") {
 224 |     return isZeroArea(node);
 225 |   }
 226 |   return false;
 227 | };
 228 | var isDisabledFromFieldset = function isDisabledFromFieldset2(node) {
 229 |   if (/^(INPUT|BUTTON|SELECT|TEXTAREA)$/.test(node.tagName)) {
 230 |     var parentNode = node.parentElement;
 231 |     while (parentNode) {
 232 |       if (parentNode.tagName === "FIELDSET" && parentNode.disabled) {
 233 |         for (var i = 0; i < parentNode.children.length; i++) {
 234 |           var child = parentNode.children.item(i);
 235 |           if (child.tagName === "LEGEND") {
 236 |             return matches.call(parentNode, "fieldset[disabled] *") ? true : !child.contains(node);
 237 |           }
 238 |         }
 239 |         return true;
 240 |       }
 241 |       parentNode = parentNode.parentElement;
 242 |     }
 243 |   }
 244 |   return false;
 245 | };
 246 | var isNodeMatchingSelectorFocusable = function isNodeMatchingSelectorFocusable2(options, node) {
 247 |   if (node.disabled || // we must do an inert look up to filter out any elements inside an inert ancestor
 248 |   //  because we're limited in the type of selectors we can use in JSDom (see related
 249 |   //  note related to `candidateSelectors`)
 250 |   isInert(node) || isHiddenInput(node) || isHidden(node, options) || // For a details element with a summary, the summary element gets the focus
 251 |   isDetailsWithSummary(node) || isDisabledFromFieldset(node)) {
 252 |     return false;
 253 |   }
 254 |   return true;
 255 | };
 256 | var isNodeMatchingSelectorTabbable = function isNodeMatchingSelectorTabbable2(options, node) {
 257 |   if (isNonTabbableRadio(node) || getTabIndex(node) < 0 || !isNodeMatchingSelectorFocusable(options, node)) {
 258 |     return false;
 259 |   }
 260 |   return true;
 261 | };
 262 | var isValidShadowRootTabbable = function isValidShadowRootTabbable2(shadowHostNode) {
 263 |   var tabIndex = parseInt(shadowHostNode.getAttribute("tabindex"), 10);
 264 |   if (isNaN(tabIndex) || tabIndex >= 0) {
 265 |     return true;
 266 |   }
 267 |   return false;
 268 | };
 269 | var sortByOrder = function sortByOrder2(candidates) {
 270 |   var regularTabbables = [];
 271 |   var orderedTabbables = [];
 272 |   candidates.forEach(function(item, i) {
 273 |     var isScope = !!item.scopeParent;
 274 |     var element = isScope ? item.scopeParent : item;
 275 |     var candidateTabindex = getSortOrderTabIndex(element, isScope);
 276 |     var elements = isScope ? sortByOrder2(item.candidates) : element;
 277 |     if (candidateTabindex === 0) {
 278 |       isScope ? regularTabbables.push.apply(regularTabbables, elements) : regularTabbables.push(element);
 279 |     } else {
 280 |       orderedTabbables.push({
 281 |         documentOrder: i,
 282 |         tabIndex: candidateTabindex,
 283 |         item,
 284 |         isScope,
 285 |         content: elements
 286 |       });
 287 |     }
 288 |   });
 289 |   return orderedTabbables.sort(sortOrderedTabbables).reduce(function(acc, sortable) {
 290 |     sortable.isScope ? acc.push.apply(acc, sortable.content) : acc.push(sortable.content);
 291 |     return acc;
 292 |   }, []).concat(regularTabbables);
 293 | };
 294 | var tabbable = function tabbable2(container, options) {
 295 |   options = options || {};
 296 |   var candidates;
 297 |   if (options.getShadowRoot) {
 298 |     candidates = getCandidatesIteratively([container], options.includeContainer, {
 299 |       filter: isNodeMatchingSelectorTabbable.bind(null, options),
 300 |       flatten: false,
 301 |       getShadowRoot: options.getShadowRoot,
 302 |       shadowRootFilter: isValidShadowRootTabbable
 303 |     });
 304 |   } else {
 305 |     candidates = getCandidates(container, options.includeContainer, isNodeMatchingSelectorTabbable.bind(null, options));
 306 |   }
 307 |   return sortByOrder(candidates);
 308 | };
 309 | var focusable = function focusable2(container, options) {
 310 |   options = options || {};
 311 |   var candidates;
 312 |   if (options.getShadowRoot) {
 313 |     candidates = getCandidatesIteratively([container], options.includeContainer, {
 314 |       filter: isNodeMatchingSelectorFocusable.bind(null, options),
 315 |       flatten: true,
 316 |       getShadowRoot: options.getShadowRoot
 317 |     });
 318 |   } else {
 319 |     candidates = getCandidates(container, options.includeContainer, isNodeMatchingSelectorFocusable.bind(null, options));
 320 |   }
 321 |   return candidates;
 322 | };
 323 | var isTabbable = function isTabbable2(node, options) {
 324 |   options = options || {};
 325 |   if (!node) {
 326 |     throw new Error("No node provided");
 327 |   }
 328 |   if (matches.call(node, candidateSelector) === false) {
 329 |     return false;
 330 |   }
 331 |   return isNodeMatchingSelectorTabbable(options, node);
 332 | };
 333 | var focusableCandidateSelector = candidateSelectors.concat("iframe").join(",");
 334 | var isFocusable = function isFocusable2(node, options) {
 335 |   options = options || {};
 336 |   if (!node) {
 337 |     throw new Error("No node provided");
 338 |   }
 339 |   if (matches.call(node, focusableCandidateSelector) === false) {
 340 |     return false;
 341 |   }
 342 |   return isNodeMatchingSelectorFocusable(options, node);
 343 | };
 344 | 
 345 | // node_modules/focus-trap/dist/focus-trap.esm.js
 346 | function _arrayLikeToArray(r, a) {
 347 |   (null == a || a > r.length) && (a = r.length);
 348 |   for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
 349 |   return n;
 350 | }
 351 | function _arrayWithoutHoles(r) {
 352 |   if (Array.isArray(r)) return _arrayLikeToArray(r);
 353 | }
 354 | function _defineProperty(e, r, t) {
 355 |   return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
 356 |     value: t,
 357 |     enumerable: true,
 358 |     configurable: true,
 359 |     writable: true
 360 |   }) : e[r] = t, e;
 361 | }
 362 | function _iterableToArray(r) {
 363 |   if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
 364 | }
 365 | function _nonIterableSpread() {
 366 |   throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
 367 | }
 368 | function ownKeys(e, r) {
 369 |   var t = Object.keys(e);
 370 |   if (Object.getOwnPropertySymbols) {
 371 |     var o = Object.getOwnPropertySymbols(e);
 372 |     r && (o = o.filter(function(r2) {
 373 |       return Object.getOwnPropertyDescriptor(e, r2).enumerable;
 374 |     })), t.push.apply(t, o);
 375 |   }
 376 |   return t;
 377 | }
 378 | function _objectSpread2(e) {
 379 |   for (var r = 1; r < arguments.length; r++) {
 380 |     var t = null != arguments[r] ? arguments[r] : {};
 381 |     r % 2 ? ownKeys(Object(t), true).forEach(function(r2) {
 382 |       _defineProperty(e, r2, t[r2]);
 383 |     }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r2) {
 384 |       Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
 385 |     });
 386 |   }
 387 |   return e;
 388 | }
 389 | function _toConsumableArray(r) {
 390 |   return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
 391 | }
 392 | function _toPrimitive(t, r) {
 393 |   if ("object" != typeof t || !t) return t;
 394 |   var e = t[Symbol.toPrimitive];
 395 |   if (void 0 !== e) {
 396 |     var i = e.call(t, r);
 397 |     if ("object" != typeof i) return i;
 398 |     throw new TypeError("@@toPrimitive must return a primitive value.");
 399 |   }
 400 |   return ("string" === r ? String : Number)(t);
 401 | }
 402 | function _toPropertyKey(t) {
 403 |   var i = _toPrimitive(t, "string");
 404 |   return "symbol" == typeof i ? i : i + "";
 405 | }
 406 | function _unsupportedIterableToArray(r, a) {
 407 |   if (r) {
 408 |     if ("string" == typeof r) return _arrayLikeToArray(r, a);
 409 |     var t = {}.toString.call(r).slice(8, -1);
 410 |     return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
 411 |   }
 412 | }
 413 | var activeFocusTraps = {
 414 |   activateTrap: function activateTrap(trapStack, trap) {
 415 |     if (trapStack.length > 0) {
 416 |       var activeTrap = trapStack[trapStack.length - 1];
 417 |       if (activeTrap !== trap) {
 418 |         activeTrap._setPausedState(true);
 419 |       }
 420 |     }
 421 |     var trapIndex = trapStack.indexOf(trap);
 422 |     if (trapIndex === -1) {
 423 |       trapStack.push(trap);
 424 |     } else {
 425 |       trapStack.splice(trapIndex, 1);
 426 |       trapStack.push(trap);
 427 |     }
 428 |   },
 429 |   deactivateTrap: function deactivateTrap(trapStack, trap) {
 430 |     var trapIndex = trapStack.indexOf(trap);
 431 |     if (trapIndex !== -1) {
 432 |       trapStack.splice(trapIndex, 1);
 433 |     }
 434 |     if (trapStack.length > 0 && !trapStack[trapStack.length - 1]._isManuallyPaused()) {
 435 |       trapStack[trapStack.length - 1]._setPausedState(false);
 436 |     }
 437 |   }
 438 | };
 439 | var isSelectableInput = function isSelectableInput2(node) {
 440 |   return node.tagName && node.tagName.toLowerCase() === "input" && typeof node.select === "function";
 441 | };
 442 | var isEscapeEvent = function isEscapeEvent2(e) {
 443 |   return (e === null || e === void 0 ? void 0 : e.key) === "Escape" || (e === null || e === void 0 ? void 0 : e.key) === "Esc" || (e === null || e === void 0 ? void 0 : e.keyCode) === 27;
 444 | };
 445 | var isTabEvent = function isTabEvent2(e) {
 446 |   return (e === null || e === void 0 ? void 0 : e.key) === "Tab" || (e === null || e === void 0 ? void 0 : e.keyCode) === 9;
 447 | };
 448 | var isKeyForward = function isKeyForward2(e) {
 449 |   return isTabEvent(e) && !e.shiftKey;
 450 | };
 451 | var isKeyBackward = function isKeyBackward2(e) {
 452 |   return isTabEvent(e) && e.shiftKey;
 453 | };
 454 | var delay = function delay2(fn) {
 455 |   return setTimeout(fn, 0);
 456 | };
 457 | var valueOrHandler = function valueOrHandler2(value) {
 458 |   for (var _len = arguments.length, params = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
 459 |     params[_key - 1] = arguments[_key];
 460 |   }
 461 |   return typeof value === "function" ? value.apply(void 0, params) : value;
 462 | };
 463 | var getActualTarget = function getActualTarget2(event) {
 464 |   return event.target.shadowRoot && typeof event.composedPath === "function" ? event.composedPath()[0] : event.target;
 465 | };
 466 | var internalTrapStack = [];
 467 | var createFocusTrap = function createFocusTrap2(elements, userOptions) {
 468 |   var doc = (userOptions === null || userOptions === void 0 ? void 0 : userOptions.document) || document;
 469 |   var trapStack = (userOptions === null || userOptions === void 0 ? void 0 : userOptions.trapStack) || internalTrapStack;
 470 |   var config = _objectSpread2({
 471 |     returnFocusOnDeactivate: true,
 472 |     escapeDeactivates: true,
 473 |     delayInitialFocus: true,
 474 |     isKeyForward,
 475 |     isKeyBackward
 476 |   }, userOptions);
 477 |   var state = {
 478 |     // containers given to createFocusTrap()
 479 |     // @type {Array<HTMLElement>}
 480 |     containers: [],
 481 |     // list of objects identifying tabbable nodes in `containers` in the trap
 482 |     // NOTE: it's possible that a group has no tabbable nodes if nodes get removed while the trap
 483 |     //  is active, but the trap should never get to a state where there isn't at least one group
 484 |     //  with at least one tabbable node in it (that would lead to an error condition that would
 485 |     //  result in an error being thrown)
 486 |     // @type {Array<{
 487 |     //   container: HTMLElement,
 488 |     //   tabbableNodes: Array<HTMLElement>, // empty if none
 489 |     //   focusableNodes: Array<HTMLElement>, // empty if none
 490 |     //   posTabIndexesFound: boolean,
 491 |     //   firstTabbableNode: HTMLElement|undefined,
 492 |     //   lastTabbableNode: HTMLElement|undefined,
 493 |     //   firstDomTabbableNode: HTMLElement|undefined,
 494 |     //   lastDomTabbableNode: HTMLElement|undefined,
 495 |     //   nextTabbableNode: (node: HTMLElement, forward: boolean) => HTMLElement|undefined
 496 |     // }>}
 497 |     containerGroups: [],
 498 |     // same order/length as `containers` list
 499 |     // references to objects in `containerGroups`, but only those that actually have
 500 |     //  tabbable nodes in them
 501 |     // NOTE: same order as `containers` and `containerGroups`, but __not necessarily__
 502 |     //  the same length
 503 |     tabbableGroups: [],
 504 |     nodeFocusedBeforeActivation: null,
 505 |     mostRecentlyFocusedNode: null,
 506 |     active: false,
 507 |     paused: false,
 508 |     manuallyPaused: false,
 509 |     // timer ID for when delayInitialFocus is true and initial focus in this trap
 510 |     //  has been delayed during activation
 511 |     delayInitialFocusTimer: void 0,
 512 |     // the most recent KeyboardEvent for the configured nav key (typically [SHIFT+]TAB), if any
 513 |     recentNavEvent: void 0
 514 |   };
 515 |   var trap;
 516 |   var getOption = function getOption2(configOverrideOptions, optionName, configOptionName) {
 517 |     return configOverrideOptions && configOverrideOptions[optionName] !== void 0 ? configOverrideOptions[optionName] : config[configOptionName || optionName];
 518 |   };
 519 |   var findContainerIndex = function findContainerIndex2(element, event) {
 520 |     var composedPath = typeof (event === null || event === void 0 ? void 0 : event.composedPath) === "function" ? event.composedPath() : void 0;
 521 |     return state.containerGroups.findIndex(function(_ref) {
 522 |       var container = _ref.container, tabbableNodes = _ref.tabbableNodes;
 523 |       return container.contains(element) || // fall back to explicit tabbable search which will take into consideration any
 524 |       //  web components if the `tabbableOptions.getShadowRoot` option was used for
 525 |       //  the trap, enabling shadow DOM support in tabbable (`Node.contains()` doesn't
 526 |       //  look inside web components even if open)
 527 |       (composedPath === null || composedPath === void 0 ? void 0 : composedPath.includes(container)) || tabbableNodes.find(function(node) {
 528 |         return node === element;
 529 |       });
 530 |     });
 531 |   };
 532 |   var getNodeForOption = function getNodeForOption2(optionName) {
 533 |     var _ref2 = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {}, _ref2$hasFallback = _ref2.hasFallback, hasFallback = _ref2$hasFallback === void 0 ? false : _ref2$hasFallback, _ref2$params = _ref2.params, params = _ref2$params === void 0 ? [] : _ref2$params;
 534 |     var optionValue = config[optionName];
 535 |     if (typeof optionValue === "function") {
 536 |       optionValue = optionValue.apply(void 0, _toConsumableArray(params));
 537 |     }
 538 |     if (optionValue === true) {
 539 |       optionValue = void 0;
 540 |     }
 541 |     if (!optionValue) {
 542 |       if (optionValue === void 0 || optionValue === false) {
 543 |         return optionValue;
 544 |       }
 545 |       throw new Error("`".concat(optionName, "` was specified but was not a node, or did not return a node"));
 546 |     }
 547 |     var node = optionValue;
 548 |     if (typeof optionValue === "string") {
 549 |       try {
 550 |         node = doc.querySelector(optionValue);
 551 |       } catch (err) {
 552 |         throw new Error("`".concat(optionName, '` appears to be an invalid selector; error="').concat(err.message, '"'));
 553 |       }
 554 |       if (!node) {
 555 |         if (!hasFallback) {
 556 |           throw new Error("`".concat(optionName, "` as selector refers to no known node"));
 557 |         }
 558 |       }
 559 |     }
 560 |     return node;
 561 |   };
 562 |   var getInitialFocusNode = function getInitialFocusNode2() {
 563 |     var node = getNodeForOption("initialFocus", {
 564 |       hasFallback: true
 565 |     });
 566 |     if (node === false) {
 567 |       return false;
 568 |     }
 569 |     if (node === void 0 || node && !isFocusable(node, config.tabbableOptions)) {
 570 |       if (findContainerIndex(doc.activeElement) >= 0) {
 571 |         node = doc.activeElement;
 572 |       } else {
 573 |         var firstTabbableGroup = state.tabbableGroups[0];
 574 |         var firstTabbableNode = firstTabbableGroup && firstTabbableGroup.firstTabbableNode;
 575 |         node = firstTabbableNode || getNodeForOption("fallbackFocus");
 576 |       }
 577 |     } else if (node === null) {
 578 |       node = getNodeForOption("fallbackFocus");
 579 |     }
 580 |     if (!node) {
 581 |       throw new Error("Your focus-trap needs to have at least one focusable element");
 582 |     }
 583 |     return node;
 584 |   };
 585 |   var updateTabbableNodes = function updateTabbableNodes2() {
 586 |     state.containerGroups = state.containers.map(function(container) {
 587 |       var tabbableNodes = tabbable(container, config.tabbableOptions);
 588 |       var focusableNodes = focusable(container, config.tabbableOptions);
 589 |       var firstTabbableNode = tabbableNodes.length > 0 ? tabbableNodes[0] : void 0;
 590 |       var lastTabbableNode = tabbableNodes.length > 0 ? tabbableNodes[tabbableNodes.length - 1] : void 0;
 591 |       var firstDomTabbableNode = focusableNodes.find(function(node) {
 592 |         return isTabbable(node);
 593 |       });
 594 |       var lastDomTabbableNode = focusableNodes.slice().reverse().find(function(node) {
 595 |         return isTabbable(node);
 596 |       });
 597 |       var posTabIndexesFound = !!tabbableNodes.find(function(node) {
 598 |         return getTabIndex(node) > 0;
 599 |       });
 600 |       return {
 601 |         container,
 602 |         tabbableNodes,
 603 |         focusableNodes,
 604 |         /** True if at least one node with positive `tabindex` was found in this container. */
 605 |         posTabIndexesFound,
 606 |         /** First tabbable node in container, __tabindex__ order; `undefined` if none. */
 607 |         firstTabbableNode,
 608 |         /** Last tabbable node in container, __tabindex__ order; `undefined` if none. */
 609 |         lastTabbableNode,
 610 |         // NOTE: DOM order is NOT NECESSARILY "document position" order, but figuring that out
 611 |         //  would require more than just https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition
 612 |         //  because that API doesn't work with Shadow DOM as well as it should (@see
 613 |         //  https://github.com/whatwg/dom/issues/320) and since this first/last is only needed, so far,
 614 |         //  to address an edge case related to positive tabindex support, this seems like a much easier,
 615 |         //  "close enough most of the time" alternative for positive tabindexes which should generally
 616 |         //  be avoided anyway...
 617 |         /** First tabbable node in container, __DOM__ order; `undefined` if none. */
 618 |         firstDomTabbableNode,
 619 |         /** Last tabbable node in container, __DOM__ order; `undefined` if none. */
 620 |         lastDomTabbableNode,
 621 |         /**
 622 |          * Finds the __tabbable__ node that follows the given node in the specified direction,
 623 |          *  in this container, if any.
 624 |          * @param {HTMLElement} node
 625 |          * @param {boolean} [forward] True if going in forward tab order; false if going
 626 |          *  in reverse.
 627 |          * @returns {HTMLElement|undefined} The next tabbable node, if any.
 628 |          */
 629 |         nextTabbableNode: function nextTabbableNode(node) {
 630 |           var forward = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : true;
 631 |           var nodeIdx = tabbableNodes.indexOf(node);
 632 |           if (nodeIdx < 0) {
 633 |             if (forward) {
 634 |               return focusableNodes.slice(focusableNodes.indexOf(node) + 1).find(function(el) {
 635 |                 return isTabbable(el);
 636 |               });
 637 |             }
 638 |             return focusableNodes.slice(0, focusableNodes.indexOf(node)).reverse().find(function(el) {
 639 |               return isTabbable(el);
 640 |             });
 641 |           }
 642 |           return tabbableNodes[nodeIdx + (forward ? 1 : -1)];
 643 |         }
 644 |       };
 645 |     });
 646 |     state.tabbableGroups = state.containerGroups.filter(function(group) {
 647 |       return group.tabbableNodes.length > 0;
 648 |     });
 649 |     if (state.tabbableGroups.length <= 0 && !getNodeForOption("fallbackFocus")) {
 650 |       throw new Error("Your focus-trap must have at least one container with at least one tabbable node in it at all times");
 651 |     }
 652 |     if (state.containerGroups.find(function(g) {
 653 |       return g.posTabIndexesFound;
 654 |     }) && state.containerGroups.length > 1) {
 655 |       throw new Error("At least one node with a positive tabindex was found in one of your focus-trap's multiple containers. Positive tabindexes are only supported in single-container focus-traps.");
 656 |     }
 657 |   };
 658 |   var _getActiveElement = function getActiveElement(el) {
 659 |     var activeElement = el.activeElement;
 660 |     if (!activeElement) {
 661 |       return;
 662 |     }
 663 |     if (activeElement.shadowRoot && activeElement.shadowRoot.activeElement !== null) {
 664 |       return _getActiveElement(activeElement.shadowRoot);
 665 |     }
 666 |     return activeElement;
 667 |   };
 668 |   var _tryFocus = function tryFocus(node) {
 669 |     if (node === false) {
 670 |       return;
 671 |     }
 672 |     if (node === _getActiveElement(document)) {
 673 |       return;
 674 |     }
 675 |     if (!node || !node.focus) {
 676 |       _tryFocus(getInitialFocusNode());
 677 |       return;
 678 |     }
 679 |     node.focus({
 680 |       preventScroll: !!config.preventScroll
 681 |     });
 682 |     state.mostRecentlyFocusedNode = node;
 683 |     if (isSelectableInput(node)) {
 684 |       node.select();
 685 |     }
 686 |   };
 687 |   var getReturnFocusNode = function getReturnFocusNode2(previousActiveElement) {
 688 |     var node = getNodeForOption("setReturnFocus", {
 689 |       params: [previousActiveElement]
 690 |     });
 691 |     return node ? node : node === false ? false : previousActiveElement;
 692 |   };
 693 |   var findNextNavNode = function findNextNavNode2(_ref3) {
 694 |     var target = _ref3.target, event = _ref3.event, _ref3$isBackward = _ref3.isBackward, isBackward = _ref3$isBackward === void 0 ? false : _ref3$isBackward;
 695 |     target = target || getActualTarget(event);
 696 |     updateTabbableNodes();
 697 |     var destinationNode = null;
 698 |     if (state.tabbableGroups.length > 0) {
 699 |       var containerIndex = findContainerIndex(target, event);
 700 |       var containerGroup = containerIndex >= 0 ? state.containerGroups[containerIndex] : void 0;
 701 |       if (containerIndex < 0) {
 702 |         if (isBackward) {
 703 |           destinationNode = state.tabbableGroups[state.tabbableGroups.length - 1].lastTabbableNode;
 704 |         } else {
 705 |           destinationNode = state.tabbableGroups[0].firstTabbableNode;
 706 |         }
 707 |       } else if (isBackward) {
 708 |         var startOfGroupIndex = state.tabbableGroups.findIndex(function(_ref4) {
 709 |           var firstTabbableNode = _ref4.firstTabbableNode;
 710 |           return target === firstTabbableNode;
 711 |         });
 712 |         if (startOfGroupIndex < 0 && (containerGroup.container === target || isFocusable(target, config.tabbableOptions) && !isTabbable(target, config.tabbableOptions) && !containerGroup.nextTabbableNode(target, false))) {
 713 |           startOfGroupIndex = containerIndex;
 714 |         }
 715 |         if (startOfGroupIndex >= 0) {
 716 |           var destinationGroupIndex = startOfGroupIndex === 0 ? state.tabbableGroups.length - 1 : startOfGroupIndex - 1;
 717 |           var destinationGroup = state.tabbableGroups[destinationGroupIndex];
 718 |           destinationNode = getTabIndex(target) >= 0 ? destinationGroup.lastTabbableNode : destinationGroup.lastDomTabbableNode;
 719 |         } else if (!isTabEvent(event)) {
 720 |           destinationNode = containerGroup.nextTabbableNode(target, false);
 721 |         }
 722 |       } else {
 723 |         var lastOfGroupIndex = state.tabbableGroups.findIndex(function(_ref5) {
 724 |           var lastTabbableNode = _ref5.lastTabbableNode;
 725 |           return target === lastTabbableNode;
 726 |         });
 727 |         if (lastOfGroupIndex < 0 && (containerGroup.container === target || isFocusable(target, config.tabbableOptions) && !isTabbable(target, config.tabbableOptions) && !containerGroup.nextTabbableNode(target))) {
 728 |           lastOfGroupIndex = containerIndex;
 729 |         }
 730 |         if (lastOfGroupIndex >= 0) {
 731 |           var _destinationGroupIndex = lastOfGroupIndex === state.tabbableGroups.length - 1 ? 0 : lastOfGroupIndex + 1;
 732 |           var _destinationGroup = state.tabbableGroups[_destinationGroupIndex];
 733 |           destinationNode = getTabIndex(target) >= 0 ? _destinationGroup.firstTabbableNode : _destinationGroup.firstDomTabbableNode;
 734 |         } else if (!isTabEvent(event)) {
 735 |           destinationNode = containerGroup.nextTabbableNode(target);
 736 |         }
 737 |       }
 738 |     } else {
 739 |       destinationNode = getNodeForOption("fallbackFocus");
 740 |     }
 741 |     return destinationNode;
 742 |   };
 743 |   var checkPointerDown = function checkPointerDown2(e) {
 744 |     var target = getActualTarget(e);
 745 |     if (findContainerIndex(target, e) >= 0) {
 746 |       return;
 747 |     }
 748 |     if (valueOrHandler(config.clickOutsideDeactivates, e)) {
 749 |       trap.deactivate({
 750 |         // NOTE: by setting `returnFocus: false`, deactivate() will do nothing,
 751 |         //  which will result in the outside click setting focus to the node
 752 |         //  that was clicked (and if not focusable, to "nothing"); by setting
 753 |         //  `returnFocus: true`, we'll attempt to re-focus the node originally-focused
 754 |         //  on activation (or the configured `setReturnFocus` node), whether the
 755 |         //  outside click was on a focusable node or not
 756 |         returnFocus: config.returnFocusOnDeactivate
 757 |       });
 758 |       return;
 759 |     }
 760 |     if (valueOrHandler(config.allowOutsideClick, e)) {
 761 |       return;
 762 |     }
 763 |     e.preventDefault();
 764 |   };
 765 |   var checkFocusIn = function checkFocusIn2(event) {
 766 |     var target = getActualTarget(event);
 767 |     var targetContained = findContainerIndex(target, event) >= 0;
 768 |     if (targetContained || target instanceof Document) {
 769 |       if (targetContained) {
 770 |         state.mostRecentlyFocusedNode = target;
 771 |       }
 772 |     } else {
 773 |       event.stopImmediatePropagation();
 774 |       var nextNode;
 775 |       var navAcrossContainers = true;
 776 |       if (state.mostRecentlyFocusedNode) {
 777 |         if (getTabIndex(state.mostRecentlyFocusedNode) > 0) {
 778 |           var mruContainerIdx = findContainerIndex(state.mostRecentlyFocusedNode);
 779 |           var tabbableNodes = state.containerGroups[mruContainerIdx].tabbableNodes;
 780 |           if (tabbableNodes.length > 0) {
 781 |             var mruTabIdx = tabbableNodes.findIndex(function(node) {
 782 |               return node === state.mostRecentlyFocusedNode;
 783 |             });
 784 |             if (mruTabIdx >= 0) {
 785 |               if (config.isKeyForward(state.recentNavEvent)) {
 786 |                 if (mruTabIdx + 1 < tabbableNodes.length) {
 787 |                   nextNode = tabbableNodes[mruTabIdx + 1];
 788 |                   navAcrossContainers = false;
 789 |                 }
 790 |               } else {
 791 |                 if (mruTabIdx - 1 >= 0) {
 792 |                   nextNode = tabbableNodes[mruTabIdx - 1];
 793 |                   navAcrossContainers = false;
 794 |                 }
 795 |               }
 796 |             }
 797 |           }
 798 |         } else {
 799 |           if (!state.containerGroups.some(function(g) {
 800 |             return g.tabbableNodes.some(function(n) {
 801 |               return getTabIndex(n) > 0;
 802 |             });
 803 |           })) {
 804 |             navAcrossContainers = false;
 805 |           }
 806 |         }
 807 |       } else {
 808 |         navAcrossContainers = false;
 809 |       }
 810 |       if (navAcrossContainers) {
 811 |         nextNode = findNextNavNode({
 812 |           // move FROM the MRU node, not event-related node (which will be the node that is
 813 |           //  outside the trap causing the focus escape we're trying to fix)
 814 |           target: state.mostRecentlyFocusedNode,
 815 |           isBackward: config.isKeyBackward(state.recentNavEvent)
 816 |         });
 817 |       }
 818 |       if (nextNode) {
 819 |         _tryFocus(nextNode);
 820 |       } else {
 821 |         _tryFocus(state.mostRecentlyFocusedNode || getInitialFocusNode());
 822 |       }
 823 |     }
 824 |     state.recentNavEvent = void 0;
 825 |   };
 826 |   var checkKeyNav = function checkKeyNav2(event) {
 827 |     var isBackward = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : false;
 828 |     state.recentNavEvent = event;
 829 |     var destinationNode = findNextNavNode({
 830 |       event,
 831 |       isBackward
 832 |     });
 833 |     if (destinationNode) {
 834 |       if (isTabEvent(event)) {
 835 |         event.preventDefault();
 836 |       }
 837 |       _tryFocus(destinationNode);
 838 |     }
 839 |   };
 840 |   var checkTabKey = function checkTabKey2(event) {
 841 |     if (config.isKeyForward(event) || config.isKeyBackward(event)) {
 842 |       checkKeyNav(event, config.isKeyBackward(event));
 843 |     }
 844 |   };
 845 |   var checkEscapeKey = function checkEscapeKey2(event) {
 846 |     if (isEscapeEvent(event) && valueOrHandler(config.escapeDeactivates, event) !== false) {
 847 |       event.preventDefault();
 848 |       trap.deactivate();
 849 |     }
 850 |   };
 851 |   var checkClick = function checkClick2(e) {
 852 |     var target = getActualTarget(e);
 853 |     if (findContainerIndex(target, e) >= 0) {
 854 |       return;
 855 |     }
 856 |     if (valueOrHandler(config.clickOutsideDeactivates, e)) {
 857 |       return;
 858 |     }
 859 |     if (valueOrHandler(config.allowOutsideClick, e)) {
 860 |       return;
 861 |     }
 862 |     e.preventDefault();
 863 |     e.stopImmediatePropagation();
 864 |   };
 865 |   var addListeners = function addListeners2() {
 866 |     if (!state.active) {
 867 |       return;
 868 |     }
 869 |     activeFocusTraps.activateTrap(trapStack, trap);
 870 |     state.delayInitialFocusTimer = config.delayInitialFocus ? delay(function() {
 871 |       _tryFocus(getInitialFocusNode());
 872 |     }) : _tryFocus(getInitialFocusNode());
 873 |     doc.addEventListener("focusin", checkFocusIn, true);
 874 |     doc.addEventListener("mousedown", checkPointerDown, {
 875 |       capture: true,
 876 |       passive: false
 877 |     });
 878 |     doc.addEventListener("touchstart", checkPointerDown, {
 879 |       capture: true,
 880 |       passive: false
 881 |     });
 882 |     doc.addEventListener("click", checkClick, {
 883 |       capture: true,
 884 |       passive: false
 885 |     });
 886 |     doc.addEventListener("keydown", checkTabKey, {
 887 |       capture: true,
 888 |       passive: false
 889 |     });
 890 |     doc.addEventListener("keydown", checkEscapeKey);
 891 |     return trap;
 892 |   };
 893 |   var removeListeners = function removeListeners2() {
 894 |     if (!state.active) {
 895 |       return;
 896 |     }
 897 |     doc.removeEventListener("focusin", checkFocusIn, true);
 898 |     doc.removeEventListener("mousedown", checkPointerDown, true);
 899 |     doc.removeEventListener("touchstart", checkPointerDown, true);
 900 |     doc.removeEventListener("click", checkClick, true);
 901 |     doc.removeEventListener("keydown", checkTabKey, true);
 902 |     doc.removeEventListener("keydown", checkEscapeKey);
 903 |     return trap;
 904 |   };
 905 |   var checkDomRemoval = function checkDomRemoval2(mutations) {
 906 |     var isFocusedNodeRemoved = mutations.some(function(mutation) {
 907 |       var removedNodes = Array.from(mutation.removedNodes);
 908 |       return removedNodes.some(function(node) {
 909 |         return node === state.mostRecentlyFocusedNode;
 910 |       });
 911 |     });
 912 |     if (isFocusedNodeRemoved) {
 913 |       _tryFocus(getInitialFocusNode());
 914 |     }
 915 |   };
 916 |   var mutationObserver = typeof window !== "undefined" && "MutationObserver" in window ? new MutationObserver(checkDomRemoval) : void 0;
 917 |   var updateObservedNodes = function updateObservedNodes2() {
 918 |     if (!mutationObserver) {
 919 |       return;
 920 |     }
 921 |     mutationObserver.disconnect();
 922 |     if (state.active && !state.paused) {
 923 |       state.containers.map(function(container) {
 924 |         mutationObserver.observe(container, {
 925 |           subtree: true,
 926 |           childList: true
 927 |         });
 928 |       });
 929 |     }
 930 |   };
 931 |   trap = {
 932 |     get active() {
 933 |       return state.active;
 934 |     },
 935 |     get paused() {
 936 |       return state.paused;
 937 |     },
 938 |     activate: function activate(activateOptions) {
 939 |       if (state.active) {
 940 |         return this;
 941 |       }
 942 |       var onActivate = getOption(activateOptions, "onActivate");
 943 |       var onPostActivate = getOption(activateOptions, "onPostActivate");
 944 |       var checkCanFocusTrap = getOption(activateOptions, "checkCanFocusTrap");
 945 |       if (!checkCanFocusTrap) {
 946 |         updateTabbableNodes();
 947 |       }
 948 |       state.active = true;
 949 |       state.paused = false;
 950 |       state.nodeFocusedBeforeActivation = _getActiveElement(doc);
 951 |       onActivate === null || onActivate === void 0 || onActivate();
 952 |       var finishActivation = function finishActivation2() {
 953 |         if (checkCanFocusTrap) {
 954 |           updateTabbableNodes();
 955 |         }
 956 |         addListeners();
 957 |         updateObservedNodes();
 958 |         onPostActivate === null || onPostActivate === void 0 || onPostActivate();
 959 |       };
 960 |       if (checkCanFocusTrap) {
 961 |         checkCanFocusTrap(state.containers.concat()).then(finishActivation, finishActivation);
 962 |         return this;
 963 |       }
 964 |       finishActivation();
 965 |       return this;
 966 |     },
 967 |     deactivate: function deactivate(deactivateOptions) {
 968 |       if (!state.active) {
 969 |         return this;
 970 |       }
 971 |       var options = _objectSpread2({
 972 |         onDeactivate: config.onDeactivate,
 973 |         onPostDeactivate: config.onPostDeactivate,
 974 |         checkCanReturnFocus: config.checkCanReturnFocus
 975 |       }, deactivateOptions);
 976 |       clearTimeout(state.delayInitialFocusTimer);
 977 |       state.delayInitialFocusTimer = void 0;
 978 |       removeListeners();
 979 |       state.active = false;
 980 |       state.paused = false;
 981 |       updateObservedNodes();
 982 |       activeFocusTraps.deactivateTrap(trapStack, trap);
 983 |       var onDeactivate = getOption(options, "onDeactivate");
 984 |       var onPostDeactivate = getOption(options, "onPostDeactivate");
 985 |       var checkCanReturnFocus = getOption(options, "checkCanReturnFocus");
 986 |       var returnFocus = getOption(options, "returnFocus", "returnFocusOnDeactivate");
 987 |       onDeactivate === null || onDeactivate === void 0 || onDeactivate();
 988 |       var finishDeactivation = function finishDeactivation2() {
 989 |         delay(function() {
 990 |           if (returnFocus) {
 991 |             _tryFocus(getReturnFocusNode(state.nodeFocusedBeforeActivation));
 992 |           }
 993 |           onPostDeactivate === null || onPostDeactivate === void 0 || onPostDeactivate();
 994 |         });
 995 |       };
 996 |       if (returnFocus && checkCanReturnFocus) {
 997 |         checkCanReturnFocus(getReturnFocusNode(state.nodeFocusedBeforeActivation)).then(finishDeactivation, finishDeactivation);
 998 |         return this;
 999 |       }
1000 |       finishDeactivation();
1001 |       return this;
1002 |     },
1003 |     pause: function pause(pauseOptions) {
1004 |       if (!state.active) {
1005 |         return this;
1006 |       }
1007 |       state.manuallyPaused = true;
1008 |       return this._setPausedState(true, pauseOptions);
1009 |     },
1010 |     unpause: function unpause(unpauseOptions) {
1011 |       if (!state.active) {
1012 |         return this;
1013 |       }
1014 |       state.manuallyPaused = false;
1015 |       if (trapStack[trapStack.length - 1] !== this) {
1016 |         return this;
1017 |       }
1018 |       return this._setPausedState(false, unpauseOptions);
1019 |     },
1020 |     updateContainerElements: function updateContainerElements(containerElements) {
1021 |       var elementsAsArray = [].concat(containerElements).filter(Boolean);
1022 |       state.containers = elementsAsArray.map(function(element) {
1023 |         return typeof element === "string" ? doc.querySelector(element) : element;
1024 |       });
1025 |       if (state.active) {
1026 |         updateTabbableNodes();
1027 |       }
1028 |       updateObservedNodes();
1029 |       return this;
1030 |     }
1031 |   };
1032 |   Object.defineProperties(trap, {
1033 |     _isManuallyPaused: {
1034 |       value: function value() {
1035 |         return state.manuallyPaused;
1036 |       }
1037 |     },
1038 |     _setPausedState: {
1039 |       value: function value(paused, options) {
1040 |         if (state.paused === paused) {
1041 |           return this;
1042 |         }
1043 |         state.paused = paused;
1044 |         if (paused) {
1045 |           var onPause = getOption(options, "onPause");
1046 |           var onPostPause = getOption(options, "onPostPause");
1047 |           onPause === null || onPause === void 0 || onPause();
1048 |           removeListeners();
1049 |           updateObservedNodes();
1050 |           onPostPause === null || onPostPause === void 0 || onPostPause();
1051 |         } else {
1052 |           var onUnpause = getOption(options, "onUnpause");
1053 |           var onPostUnpause = getOption(options, "onPostUnpause");
1054 |           onUnpause === null || onUnpause === void 0 || onUnpause();
1055 |           updateTabbableNodes();
1056 |           addListeners();
1057 |           updateObservedNodes();
1058 |           onPostUnpause === null || onPostUnpause === void 0 || onPostUnpause();
1059 |         }
1060 |         return this;
1061 |       }
1062 |     }
1063 |   });
1064 |   trap.updateContainerElements(elements);
1065 |   return trap;
1066 | };
1067 | 
1068 | // node_modules/@vueuse/integrations/useFocusTrap.mjs
1069 | function useFocusTrap(target, options = {}) {
1070 |   let trap;
1071 |   const { immediate, ...focusTrapOptions } = options;
1072 |   const hasFocus = shallowRef(false);
1073 |   const isPaused = shallowRef(false);
1074 |   const activate = (opts) => trap && trap.activate(opts);
1075 |   const deactivate = (opts) => trap && trap.deactivate(opts);
1076 |   const pause = () => {
1077 |     if (trap) {
1078 |       trap.pause();
1079 |       isPaused.value = true;
1080 |     }
1081 |   };
1082 |   const unpause = () => {
1083 |     if (trap) {
1084 |       trap.unpause();
1085 |       isPaused.value = false;
1086 |     }
1087 |   };
1088 |   const targets = computed(() => {
1089 |     const _targets = toValue(target);
1090 |     return toArray(_targets).map((el) => {
1091 |       const _el = toValue(el);
1092 |       return typeof _el === "string" ? _el : unrefElement(_el);
1093 |     }).filter(notNullish);
1094 |   });
1095 |   watch(
1096 |     targets,
1097 |     (els) => {
1098 |       if (!els.length)
1099 |         return;
1100 |       trap = createFocusTrap(els, {
1101 |         ...focusTrapOptions,
1102 |         onActivate() {
1103 |           hasFocus.value = true;
1104 |           if (options.onActivate)
1105 |             options.onActivate();
1106 |         },
1107 |         onDeactivate() {
1108 |           hasFocus.value = false;
1109 |           if (options.onDeactivate)
1110 |             options.onDeactivate();
1111 |         }
1112 |       });
1113 |       if (immediate)
1114 |         activate();
1115 |     },
1116 |     { flush: "post" }
1117 |   );
1118 |   tryOnScopeDispose(() => deactivate());
1119 |   return {
1120 |     hasFocus,
1121 |     isPaused,
1122 |     activate,
1123 |     deactivate,
1124 |     pause,
1125 |     unpause
1126 |   };
1127 | }
1128 | export {
1129 |   useFocusTrap
1130 | };
1131 | /*! Bundled license information:
1132 | 
1133 | tabbable/dist/index.esm.js:
1134 |   (*!
1135 |   * tabbable 6.2.0
1136 |   * @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE
1137 |   *)
1138 | 
1139 | focus-trap/dist/focus-trap.esm.js:
1140 |   (*!
1141 |   * focus-trap 7.6.5
1142 |   * @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE
1143 |   *)
1144 | */
1145 | //# sourceMappingURL=vitepress___@vueuse_integrations_useFocusTrap.js.map
1146 | 
```

--------------------------------------------------------------------------------
/docs/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js:
--------------------------------------------------------------------------------

```javascript
   1 | // node_modules/mark.js/src/lib/domiterator.js
   2 | var DOMIterator = class _DOMIterator {
   3 |   /**
   4 |    * @param {HTMLElement|HTMLElement[]|NodeList|string} ctx - The context DOM
   5 |    * element, an array of DOM elements, a NodeList or a selector
   6 |    * @param {boolean} [iframes=true] - A boolean indicating if iframes should
   7 |    * be handled
   8 |    * @param {string[]} [exclude=[]] - An array containing exclusion selectors
   9 |    * for iframes
  10 |    * @param {number} [iframesTimeout=5000] - A number indicating the ms to
  11 |    * wait before an iframe should be skipped, in case the load event isn't
  12 |    * fired. This also applies if the user is offline and the resource of the
  13 |    * iframe is online (either by the browsers "offline" mode or because
  14 |    * there's no internet connection)
  15 |    */
  16 |   constructor(ctx, iframes = true, exclude = [], iframesTimeout = 5e3) {
  17 |     this.ctx = ctx;
  18 |     this.iframes = iframes;
  19 |     this.exclude = exclude;
  20 |     this.iframesTimeout = iframesTimeout;
  21 |   }
  22 |   /**
  23 |    * Checks if the specified DOM element matches the selector
  24 |    * @param  {HTMLElement} element - The DOM element
  25 |    * @param  {string|string[]} selector - The selector or an array with
  26 |    * selectors
  27 |    * @return {boolean}
  28 |    * @access public
  29 |    */
  30 |   static matches(element, selector) {
  31 |     const selectors = typeof selector === "string" ? [selector] : selector, fn = element.matches || element.matchesSelector || element.msMatchesSelector || element.mozMatchesSelector || element.oMatchesSelector || element.webkitMatchesSelector;
  32 |     if (fn) {
  33 |       let match = false;
  34 |       selectors.every((sel) => {
  35 |         if (fn.call(element, sel)) {
  36 |           match = true;
  37 |           return false;
  38 |         }
  39 |         return true;
  40 |       });
  41 |       return match;
  42 |     } else {
  43 |       return false;
  44 |     }
  45 |   }
  46 |   /**
  47 |    * Returns all contexts filtered by duplicates (even nested)
  48 |    * @return {HTMLElement[]} - An array containing DOM contexts
  49 |    * @access protected
  50 |    */
  51 |   getContexts() {
  52 |     let ctx, filteredCtx = [];
  53 |     if (typeof this.ctx === "undefined" || !this.ctx) {
  54 |       ctx = [];
  55 |     } else if (NodeList.prototype.isPrototypeOf(this.ctx)) {
  56 |       ctx = Array.prototype.slice.call(this.ctx);
  57 |     } else if (Array.isArray(this.ctx)) {
  58 |       ctx = this.ctx;
  59 |     } else if (typeof this.ctx === "string") {
  60 |       ctx = Array.prototype.slice.call(
  61 |         document.querySelectorAll(this.ctx)
  62 |       );
  63 |     } else {
  64 |       ctx = [this.ctx];
  65 |     }
  66 |     ctx.forEach((ctx2) => {
  67 |       const isDescendant = filteredCtx.filter((contexts) => {
  68 |         return contexts.contains(ctx2);
  69 |       }).length > 0;
  70 |       if (filteredCtx.indexOf(ctx2) === -1 && !isDescendant) {
  71 |         filteredCtx.push(ctx2);
  72 |       }
  73 |     });
  74 |     return filteredCtx;
  75 |   }
  76 |   /**
  77 |    * @callback DOMIterator~getIframeContentsSuccessCallback
  78 |    * @param {HTMLDocument} contents - The contentDocument of the iframe
  79 |    */
  80 |   /**
  81 |    * Calls the success callback function with the iframe document. If it can't
  82 |    * be accessed it calls the error callback function
  83 |    * @param {HTMLElement} ifr - The iframe DOM element
  84 |    * @param {DOMIterator~getIframeContentsSuccessCallback} successFn
  85 |    * @param {function} [errorFn]
  86 |    * @access protected
  87 |    */
  88 |   getIframeContents(ifr, successFn, errorFn = () => {
  89 |   }) {
  90 |     let doc;
  91 |     try {
  92 |       const ifrWin = ifr.contentWindow;
  93 |       doc = ifrWin.document;
  94 |       if (!ifrWin || !doc) {
  95 |         throw new Error("iframe inaccessible");
  96 |       }
  97 |     } catch (e) {
  98 |       errorFn();
  99 |     }
 100 |     if (doc) {
 101 |       successFn(doc);
 102 |     }
 103 |   }
 104 |   /**
 105 |    * Checks if an iframe is empty (if about:blank is the shown page)
 106 |    * @param {HTMLElement} ifr - The iframe DOM element
 107 |    * @return {boolean}
 108 |    * @access protected
 109 |    */
 110 |   isIframeBlank(ifr) {
 111 |     const bl = "about:blank", src = ifr.getAttribute("src").trim(), href = ifr.contentWindow.location.href;
 112 |     return href === bl && src !== bl && src;
 113 |   }
 114 |   /**
 115 |    * Observes the onload event of an iframe and calls the success callback or
 116 |    * the error callback if the iframe is inaccessible. If the event isn't
 117 |    * fired within the specified {@link DOMIterator#iframesTimeout}, then it'll
 118 |    * call the error callback too
 119 |    * @param {HTMLElement} ifr - The iframe DOM element
 120 |    * @param {DOMIterator~getIframeContentsSuccessCallback} successFn
 121 |    * @param {function} errorFn
 122 |    * @access protected
 123 |    */
 124 |   observeIframeLoad(ifr, successFn, errorFn) {
 125 |     let called = false, tout = null;
 126 |     const listener = () => {
 127 |       if (called) {
 128 |         return;
 129 |       }
 130 |       called = true;
 131 |       clearTimeout(tout);
 132 |       try {
 133 |         if (!this.isIframeBlank(ifr)) {
 134 |           ifr.removeEventListener("load", listener);
 135 |           this.getIframeContents(ifr, successFn, errorFn);
 136 |         }
 137 |       } catch (e) {
 138 |         errorFn();
 139 |       }
 140 |     };
 141 |     ifr.addEventListener("load", listener);
 142 |     tout = setTimeout(listener, this.iframesTimeout);
 143 |   }
 144 |   /**
 145 |    * Callback when the iframe is ready
 146 |    * @callback DOMIterator~onIframeReadySuccessCallback
 147 |    * @param {HTMLDocument} contents - The contentDocument of the iframe
 148 |    */
 149 |   /**
 150 |    * Callback if the iframe can't be accessed
 151 |    * @callback DOMIterator~onIframeReadyErrorCallback
 152 |    */
 153 |   /**
 154 |    * Calls the callback if the specified iframe is ready for DOM access
 155 |    * @param  {HTMLElement} ifr - The iframe DOM element
 156 |    * @param  {DOMIterator~onIframeReadySuccessCallback} successFn - Success
 157 |    * callback
 158 |    * @param {DOMIterator~onIframeReadyErrorCallback} errorFn - Error callback
 159 |    * @see {@link http://stackoverflow.com/a/36155560/3894981} for
 160 |    * background information
 161 |    * @access protected
 162 |    */
 163 |   onIframeReady(ifr, successFn, errorFn) {
 164 |     try {
 165 |       if (ifr.contentWindow.document.readyState === "complete") {
 166 |         if (this.isIframeBlank(ifr)) {
 167 |           this.observeIframeLoad(ifr, successFn, errorFn);
 168 |         } else {
 169 |           this.getIframeContents(ifr, successFn, errorFn);
 170 |         }
 171 |       } else {
 172 |         this.observeIframeLoad(ifr, successFn, errorFn);
 173 |       }
 174 |     } catch (e) {
 175 |       errorFn();
 176 |     }
 177 |   }
 178 |   /**
 179 |    * Callback when all iframes are ready for DOM access
 180 |    * @callback DOMIterator~waitForIframesDoneCallback
 181 |    */
 182 |   /**
 183 |    * Iterates over all iframes and calls the done callback when all of them
 184 |    * are ready for DOM access (including nested ones)
 185 |    * @param {HTMLElement} ctx - The context DOM element
 186 |    * @param {DOMIterator~waitForIframesDoneCallback} done - Done callback
 187 |    */
 188 |   waitForIframes(ctx, done) {
 189 |     let eachCalled = 0;
 190 |     this.forEachIframe(ctx, () => true, (ifr) => {
 191 |       eachCalled++;
 192 |       this.waitForIframes(ifr.querySelector("html"), () => {
 193 |         if (!--eachCalled) {
 194 |           done();
 195 |         }
 196 |       });
 197 |     }, (handled) => {
 198 |       if (!handled) {
 199 |         done();
 200 |       }
 201 |     });
 202 |   }
 203 |   /**
 204 |    * Callback allowing to filter an iframe. Must return true when the element
 205 |    * should remain, otherwise false
 206 |    * @callback DOMIterator~forEachIframeFilterCallback
 207 |    * @param {HTMLElement} iframe - The iframe DOM element
 208 |    */
 209 |   /**
 210 |    * Callback for each iframe content
 211 |    * @callback DOMIterator~forEachIframeEachCallback
 212 |    * @param {HTMLElement} content - The iframe document
 213 |    */
 214 |   /**
 215 |    * Callback if all iframes inside the context were handled
 216 |    * @callback DOMIterator~forEachIframeEndCallback
 217 |    * @param {number} handled - The number of handled iframes (those who
 218 |    * wheren't filtered)
 219 |    */
 220 |   /**
 221 |    * Iterates over all iframes inside the specified context and calls the
 222 |    * callbacks when they're ready. Filters iframes based on the instance
 223 |    * exclusion selectors
 224 |    * @param {HTMLElement} ctx - The context DOM element
 225 |    * @param {DOMIterator~forEachIframeFilterCallback} filter - Filter callback
 226 |    * @param {DOMIterator~forEachIframeEachCallback} each - Each callback
 227 |    * @param {DOMIterator~forEachIframeEndCallback} [end] - End callback
 228 |    * @access protected
 229 |    */
 230 |   forEachIframe(ctx, filter, each, end = () => {
 231 |   }) {
 232 |     let ifr = ctx.querySelectorAll("iframe"), open = ifr.length, handled = 0;
 233 |     ifr = Array.prototype.slice.call(ifr);
 234 |     const checkEnd = () => {
 235 |       if (--open <= 0) {
 236 |         end(handled);
 237 |       }
 238 |     };
 239 |     if (!open) {
 240 |       checkEnd();
 241 |     }
 242 |     ifr.forEach((ifr2) => {
 243 |       if (_DOMIterator.matches(ifr2, this.exclude)) {
 244 |         checkEnd();
 245 |       } else {
 246 |         this.onIframeReady(ifr2, (con) => {
 247 |           if (filter(ifr2)) {
 248 |             handled++;
 249 |             each(con);
 250 |           }
 251 |           checkEnd();
 252 |         }, checkEnd);
 253 |       }
 254 |     });
 255 |   }
 256 |   /**
 257 |    * Creates a NodeIterator on the specified context
 258 |    * @see {@link https://developer.mozilla.org/en/docs/Web/API/NodeIterator}
 259 |    * @param {HTMLElement} ctx - The context DOM element
 260 |    * @param {DOMIterator~whatToShow} whatToShow
 261 |    * @param {DOMIterator~filterCb} filter
 262 |    * @return {NodeIterator}
 263 |    * @access protected
 264 |    */
 265 |   createIterator(ctx, whatToShow, filter) {
 266 |     return document.createNodeIterator(ctx, whatToShow, filter, false);
 267 |   }
 268 |   /**
 269 |    * Creates an instance of DOMIterator in an iframe
 270 |    * @param {HTMLDocument} contents - Iframe document
 271 |    * @return {DOMIterator}
 272 |    * @access protected
 273 |    */
 274 |   createInstanceOnIframe(contents) {
 275 |     return new _DOMIterator(contents.querySelector("html"), this.iframes);
 276 |   }
 277 |   /**
 278 |    * Checks if an iframe occurs between two nodes, more specifically if an
 279 |    * iframe occurs before the specified node and after the specified prevNode
 280 |    * @param {HTMLElement} node - The node that should occur after the iframe
 281 |    * @param {HTMLElement} prevNode - The node that should occur before the
 282 |    * iframe
 283 |    * @param {HTMLElement} ifr - The iframe to check against
 284 |    * @return {boolean}
 285 |    * @access protected
 286 |    */
 287 |   compareNodeIframe(node, prevNode, ifr) {
 288 |     const compCurr = node.compareDocumentPosition(ifr), prev = Node.DOCUMENT_POSITION_PRECEDING;
 289 |     if (compCurr & prev) {
 290 |       if (prevNode !== null) {
 291 |         const compPrev = prevNode.compareDocumentPosition(ifr), after = Node.DOCUMENT_POSITION_FOLLOWING;
 292 |         if (compPrev & after) {
 293 |           return true;
 294 |         }
 295 |       } else {
 296 |         return true;
 297 |       }
 298 |     }
 299 |     return false;
 300 |   }
 301 |   /**
 302 |    * @typedef {DOMIterator~getIteratorNodeReturn}
 303 |    * @type {object.<string>}
 304 |    * @property {HTMLElement} prevNode - The previous node or null if there is
 305 |    * no
 306 |    * @property {HTMLElement} node - The current node
 307 |    */
 308 |   /**
 309 |    * Returns the previous and current node of the specified iterator
 310 |    * @param {NodeIterator} itr - The iterator
 311 |    * @return {DOMIterator~getIteratorNodeReturn}
 312 |    * @access protected
 313 |    */
 314 |   getIteratorNode(itr) {
 315 |     const prevNode = itr.previousNode();
 316 |     let node;
 317 |     if (prevNode === null) {
 318 |       node = itr.nextNode();
 319 |     } else {
 320 |       node = itr.nextNode() && itr.nextNode();
 321 |     }
 322 |     return {
 323 |       prevNode,
 324 |       node
 325 |     };
 326 |   }
 327 |   /**
 328 |    * An array containing objects. The object key "val" contains an iframe
 329 |    * DOM element. The object key "handled" contains a boolean indicating if
 330 |    * the iframe was handled already.
 331 |    * It wouldn't be enough to save all open or all already handled iframes.
 332 |    * The information of open iframes is necessary because they may occur after
 333 |    * all other text nodes (and compareNodeIframe would never be true). The
 334 |    * information of already handled iframes is necessary as otherwise they may
 335 |    * be handled multiple times
 336 |    * @typedef DOMIterator~checkIframeFilterIfr
 337 |    * @type {object[]}
 338 |    */
 339 |   /**
 340 |    * Checks if an iframe wasn't handled already and if so, calls
 341 |    * {@link DOMIterator#compareNodeIframe} to check if it should be handled.
 342 |    * Information wheter an iframe was or wasn't handled is given within the
 343 |    * <code>ifr</code> dictionary
 344 |    * @param {HTMLElement} node - The node that should occur after the iframe
 345 |    * @param {HTMLElement} prevNode - The node that should occur before the
 346 |    * iframe
 347 |    * @param {HTMLElement} currIfr - The iframe to check
 348 |    * @param {DOMIterator~checkIframeFilterIfr} ifr - The iframe dictionary.
 349 |    * Will be manipulated (by reference)
 350 |    * @return {boolean} Returns true when it should be handled, otherwise false
 351 |    * @access protected
 352 |    */
 353 |   checkIframeFilter(node, prevNode, currIfr, ifr) {
 354 |     let key = false, handled = false;
 355 |     ifr.forEach((ifrDict, i) => {
 356 |       if (ifrDict.val === currIfr) {
 357 |         key = i;
 358 |         handled = ifrDict.handled;
 359 |       }
 360 |     });
 361 |     if (this.compareNodeIframe(node, prevNode, currIfr)) {
 362 |       if (key === false && !handled) {
 363 |         ifr.push({
 364 |           val: currIfr,
 365 |           handled: true
 366 |         });
 367 |       } else if (key !== false && !handled) {
 368 |         ifr[key].handled = true;
 369 |       }
 370 |       return true;
 371 |     }
 372 |     if (key === false) {
 373 |       ifr.push({
 374 |         val: currIfr,
 375 |         handled: false
 376 |       });
 377 |     }
 378 |     return false;
 379 |   }
 380 |   /**
 381 |    * Creates an iterator on all open iframes in the specified array and calls
 382 |    * the end callback when finished
 383 |    * @param {DOMIterator~checkIframeFilterIfr} ifr
 384 |    * @param {DOMIterator~whatToShow} whatToShow
 385 |    * @param  {DOMIterator~forEachNodeCallback} eCb - Each callback
 386 |    * @param {DOMIterator~filterCb} fCb
 387 |    * @access protected
 388 |    */
 389 |   handleOpenIframes(ifr, whatToShow, eCb, fCb) {
 390 |     ifr.forEach((ifrDict) => {
 391 |       if (!ifrDict.handled) {
 392 |         this.getIframeContents(ifrDict.val, (con) => {
 393 |           this.createInstanceOnIframe(con).forEachNode(
 394 |             whatToShow,
 395 |             eCb,
 396 |             fCb
 397 |           );
 398 |         });
 399 |       }
 400 |     });
 401 |   }
 402 |   /**
 403 |    * Iterates through all nodes in the specified context and handles iframe
 404 |    * nodes at the correct position
 405 |    * @param {DOMIterator~whatToShow} whatToShow
 406 |    * @param {HTMLElement} ctx - The context
 407 |    * @param  {DOMIterator~forEachNodeCallback} eachCb - Each callback
 408 |    * @param {DOMIterator~filterCb} filterCb - Filter callback
 409 |    * @param {DOMIterator~forEachNodeEndCallback} doneCb - End callback
 410 |    * @access protected
 411 |    */
 412 |   iterateThroughNodes(whatToShow, ctx, eachCb, filterCb, doneCb) {
 413 |     const itr = this.createIterator(ctx, whatToShow, filterCb);
 414 |     let ifr = [], elements = [], node, prevNode, retrieveNodes = () => {
 415 |       ({
 416 |         prevNode,
 417 |         node
 418 |       } = this.getIteratorNode(itr));
 419 |       return node;
 420 |     };
 421 |     while (retrieveNodes()) {
 422 |       if (this.iframes) {
 423 |         this.forEachIframe(ctx, (currIfr) => {
 424 |           return this.checkIframeFilter(node, prevNode, currIfr, ifr);
 425 |         }, (con) => {
 426 |           this.createInstanceOnIframe(con).forEachNode(
 427 |             whatToShow,
 428 |             (ifrNode) => elements.push(ifrNode),
 429 |             filterCb
 430 |           );
 431 |         });
 432 |       }
 433 |       elements.push(node);
 434 |     }
 435 |     elements.forEach((node2) => {
 436 |       eachCb(node2);
 437 |     });
 438 |     if (this.iframes) {
 439 |       this.handleOpenIframes(ifr, whatToShow, eachCb, filterCb);
 440 |     }
 441 |     doneCb();
 442 |   }
 443 |   /**
 444 |    * Callback for each node
 445 |    * @callback DOMIterator~forEachNodeCallback
 446 |    * @param {HTMLElement} node - The DOM text node element
 447 |    */
 448 |   /**
 449 |    * Callback if all contexts were handled
 450 |    * @callback DOMIterator~forEachNodeEndCallback
 451 |    */
 452 |   /**
 453 |    * Iterates over all contexts and initializes
 454 |    * {@link DOMIterator#iterateThroughNodes iterateThroughNodes} on them
 455 |    * @param {DOMIterator~whatToShow} whatToShow
 456 |    * @param  {DOMIterator~forEachNodeCallback} each - Each callback
 457 |    * @param {DOMIterator~filterCb} filter - Filter callback
 458 |    * @param {DOMIterator~forEachNodeEndCallback} done - End callback
 459 |    * @access public
 460 |    */
 461 |   forEachNode(whatToShow, each, filter, done = () => {
 462 |   }) {
 463 |     const contexts = this.getContexts();
 464 |     let open = contexts.length;
 465 |     if (!open) {
 466 |       done();
 467 |     }
 468 |     contexts.forEach((ctx) => {
 469 |       const ready = () => {
 470 |         this.iterateThroughNodes(whatToShow, ctx, each, filter, () => {
 471 |           if (--open <= 0) {
 472 |             done();
 473 |           }
 474 |         });
 475 |       };
 476 |       if (this.iframes) {
 477 |         this.waitForIframes(ctx, ready);
 478 |       } else {
 479 |         ready();
 480 |       }
 481 |     });
 482 |   }
 483 |   /**
 484 |    * Callback to filter nodes. Can return e.g. NodeFilter.FILTER_ACCEPT or
 485 |    * NodeFilter.FILTER_REJECT
 486 |    * @see {@link http://tinyurl.com/zdczmm2}
 487 |    * @callback DOMIterator~filterCb
 488 |    * @param {HTMLElement} node - The node to filter
 489 |    */
 490 |   /**
 491 |    * @typedef DOMIterator~whatToShow
 492 |    * @see {@link http://tinyurl.com/zfqqkx2}
 493 |    * @type {number}
 494 |    */
 495 | };
 496 | 
 497 | // node_modules/mark.js/src/lib/mark.js
 498 | var Mark = class {
 499 |   // eslint-disable-line no-unused-vars
 500 |   /**
 501 |    * @param {HTMLElement|HTMLElement[]|NodeList|string} ctx - The context DOM
 502 |    * element, an array of DOM elements, a NodeList or a selector
 503 |    */
 504 |   constructor(ctx) {
 505 |     this.ctx = ctx;
 506 |     this.ie = false;
 507 |     const ua = window.navigator.userAgent;
 508 |     if (ua.indexOf("MSIE") > -1 || ua.indexOf("Trident") > -1) {
 509 |       this.ie = true;
 510 |     }
 511 |   }
 512 |   /**
 513 |    * Options defined by the user. They will be initialized from one of the
 514 |    * public methods. See {@link Mark#mark}, {@link Mark#markRegExp},
 515 |    * {@link Mark#markRanges} and {@link Mark#unmark} for option properties.
 516 |    * @type {object}
 517 |    * @param {object} [val] - An object that will be merged with defaults
 518 |    * @access protected
 519 |    */
 520 |   set opt(val) {
 521 |     this._opt = Object.assign({}, {
 522 |       "element": "",
 523 |       "className": "",
 524 |       "exclude": [],
 525 |       "iframes": false,
 526 |       "iframesTimeout": 5e3,
 527 |       "separateWordSearch": true,
 528 |       "diacritics": true,
 529 |       "synonyms": {},
 530 |       "accuracy": "partially",
 531 |       "acrossElements": false,
 532 |       "caseSensitive": false,
 533 |       "ignoreJoiners": false,
 534 |       "ignoreGroups": 0,
 535 |       "ignorePunctuation": [],
 536 |       "wildcards": "disabled",
 537 |       "each": () => {
 538 |       },
 539 |       "noMatch": () => {
 540 |       },
 541 |       "filter": () => true,
 542 |       "done": () => {
 543 |       },
 544 |       "debug": false,
 545 |       "log": window.console
 546 |     }, val);
 547 |   }
 548 |   get opt() {
 549 |     return this._opt;
 550 |   }
 551 |   /**
 552 |    * An instance of DOMIterator
 553 |    * @type {DOMIterator}
 554 |    * @access protected
 555 |    */
 556 |   get iterator() {
 557 |     return new DOMIterator(
 558 |       this.ctx,
 559 |       this.opt.iframes,
 560 |       this.opt.exclude,
 561 |       this.opt.iframesTimeout
 562 |     );
 563 |   }
 564 |   /**
 565 |    * Logs a message if log is enabled
 566 |    * @param {string} msg - The message to log
 567 |    * @param {string} [level="debug"] - The log level, e.g. <code>warn</code>
 568 |    * <code>error</code>, <code>debug</code>
 569 |    * @access protected
 570 |    */
 571 |   log(msg, level = "debug") {
 572 |     const log = this.opt.log;
 573 |     if (!this.opt.debug) {
 574 |       return;
 575 |     }
 576 |     if (typeof log === "object" && typeof log[level] === "function") {
 577 |       log[level](`mark.js: ${msg}`);
 578 |     }
 579 |   }
 580 |   /**
 581 |    * Escapes a string for usage within a regular expression
 582 |    * @param {string} str - The string to escape
 583 |    * @return {string}
 584 |    * @access protected
 585 |    */
 586 |   escapeStr(str) {
 587 |     return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
 588 |   }
 589 |   /**
 590 |    * Creates a regular expression string to match the specified search
 591 |    * term including synonyms, diacritics and accuracy if defined
 592 |    * @param  {string} str - The search term to be used
 593 |    * @return {string}
 594 |    * @access protected
 595 |    */
 596 |   createRegExp(str) {
 597 |     if (this.opt.wildcards !== "disabled") {
 598 |       str = this.setupWildcardsRegExp(str);
 599 |     }
 600 |     str = this.escapeStr(str);
 601 |     if (Object.keys(this.opt.synonyms).length) {
 602 |       str = this.createSynonymsRegExp(str);
 603 |     }
 604 |     if (this.opt.ignoreJoiners || this.opt.ignorePunctuation.length) {
 605 |       str = this.setupIgnoreJoinersRegExp(str);
 606 |     }
 607 |     if (this.opt.diacritics) {
 608 |       str = this.createDiacriticsRegExp(str);
 609 |     }
 610 |     str = this.createMergedBlanksRegExp(str);
 611 |     if (this.opt.ignoreJoiners || this.opt.ignorePunctuation.length) {
 612 |       str = this.createJoinersRegExp(str);
 613 |     }
 614 |     if (this.opt.wildcards !== "disabled") {
 615 |       str = this.createWildcardsRegExp(str);
 616 |     }
 617 |     str = this.createAccuracyRegExp(str);
 618 |     return str;
 619 |   }
 620 |   /**
 621 |    * Creates a regular expression string to match the defined synonyms
 622 |    * @param  {string} str - The search term to be used
 623 |    * @return {string}
 624 |    * @access protected
 625 |    */
 626 |   createSynonymsRegExp(str) {
 627 |     const syn = this.opt.synonyms, sens = this.opt.caseSensitive ? "" : "i", joinerPlaceholder = this.opt.ignoreJoiners || this.opt.ignorePunctuation.length ? "\0" : "";
 628 |     for (let index in syn) {
 629 |       if (syn.hasOwnProperty(index)) {
 630 |         const value = syn[index], k1 = this.opt.wildcards !== "disabled" ? this.setupWildcardsRegExp(index) : this.escapeStr(index), k2 = this.opt.wildcards !== "disabled" ? this.setupWildcardsRegExp(value) : this.escapeStr(value);
 631 |         if (k1 !== "" && k2 !== "") {
 632 |           str = str.replace(
 633 |             new RegExp(
 634 |               `(${this.escapeStr(k1)}|${this.escapeStr(k2)})`,
 635 |               `gm${sens}`
 636 |             ),
 637 |             joinerPlaceholder + `(${this.processSynomyms(k1)}|${this.processSynomyms(k2)})` + joinerPlaceholder
 638 |           );
 639 |         }
 640 |       }
 641 |     }
 642 |     return str;
 643 |   }
 644 |   /**
 645 |    * Setup synonyms to work with ignoreJoiners and or ignorePunctuation
 646 |    * @param {string} str - synonym key or value to process
 647 |    * @return {string} - processed synonym string
 648 |    */
 649 |   processSynomyms(str) {
 650 |     if (this.opt.ignoreJoiners || this.opt.ignorePunctuation.length) {
 651 |       str = this.setupIgnoreJoinersRegExp(str);
 652 |     }
 653 |     return str;
 654 |   }
 655 |   /**
 656 |    * Sets up the regular expression string to allow later insertion of
 657 |    * wildcard regular expression matches
 658 |    * @param  {string} str - The search term to be used
 659 |    * @return {string}
 660 |    * @access protected
 661 |    */
 662 |   setupWildcardsRegExp(str) {
 663 |     str = str.replace(/(?:\\)*\?/g, (val) => {
 664 |       return val.charAt(0) === "\\" ? "?" : "";
 665 |     });
 666 |     return str.replace(/(?:\\)*\*/g, (val) => {
 667 |       return val.charAt(0) === "\\" ? "*" : "";
 668 |     });
 669 |   }
 670 |   /**
 671 |    * Sets up the regular expression string to allow later insertion of
 672 |    * wildcard regular expression matches
 673 |    * @param  {string} str - The search term to be used
 674 |    * @return {string}
 675 |    * @access protected
 676 |    */
 677 |   createWildcardsRegExp(str) {
 678 |     let spaces = this.opt.wildcards === "withSpaces";
 679 |     return str.replace(/\u0001/g, spaces ? "[\\S\\s]?" : "\\S?").replace(/\u0002/g, spaces ? "[\\S\\s]*?" : "\\S*");
 680 |   }
 681 |   /**
 682 |    * Sets up the regular expression string to allow later insertion of
 683 |    * designated characters (soft hyphens & zero width characters)
 684 |    * @param  {string} str - The search term to be used
 685 |    * @return {string}
 686 |    * @access protected
 687 |    */
 688 |   setupIgnoreJoinersRegExp(str) {
 689 |     return str.replace(/[^(|)\\]/g, (val, indx, original) => {
 690 |       let nextChar = original.charAt(indx + 1);
 691 |       if (/[(|)\\]/.test(nextChar) || nextChar === "") {
 692 |         return val;
 693 |       } else {
 694 |         return val + "\0";
 695 |       }
 696 |     });
 697 |   }
 698 |   /**
 699 |    * Creates a regular expression string to allow ignoring of designated
 700 |    * characters (soft hyphens, zero width characters & punctuation) based on
 701 |    * the specified option values of <code>ignorePunctuation</code> and
 702 |    * <code>ignoreJoiners</code>
 703 |    * @param  {string} str - The search term to be used
 704 |    * @return {string}
 705 |    * @access protected
 706 |    */
 707 |   createJoinersRegExp(str) {
 708 |     let joiner = [];
 709 |     const ignorePunctuation = this.opt.ignorePunctuation;
 710 |     if (Array.isArray(ignorePunctuation) && ignorePunctuation.length) {
 711 |       joiner.push(this.escapeStr(ignorePunctuation.join("")));
 712 |     }
 713 |     if (this.opt.ignoreJoiners) {
 714 |       joiner.push("\\u00ad\\u200b\\u200c\\u200d");
 715 |     }
 716 |     return joiner.length ? str.split(/\u0000+/).join(`[${joiner.join("")}]*`) : str;
 717 |   }
 718 |   /**
 719 |    * Creates a regular expression string to match diacritics
 720 |    * @param  {string} str - The search term to be used
 721 |    * @return {string}
 722 |    * @access protected
 723 |    */
 724 |   createDiacriticsRegExp(str) {
 725 |     const sens = this.opt.caseSensitive ? "" : "i", dct = this.opt.caseSensitive ? [
 726 |       "aàáảãạăằắẳẵặâầấẩẫậäåāą",
 727 |       "AÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ",
 728 |       "cçćč",
 729 |       "CÇĆČ",
 730 |       "dđď",
 731 |       "DĐĎ",
 732 |       "eèéẻẽẹêềếểễệëěēę",
 733 |       "EÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ",
 734 |       "iìíỉĩịîïī",
 735 |       "IÌÍỈĨỊÎÏĪ",
 736 |       "lł",
 737 |       "LŁ",
 738 |       "nñňń",
 739 |       "NÑŇŃ",
 740 |       "oòóỏõọôồốổỗộơởỡớờợöøō",
 741 |       "OÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ",
 742 |       "rř",
 743 |       "RŘ",
 744 |       "sšśșş",
 745 |       "SŠŚȘŞ",
 746 |       "tťțţ",
 747 |       "TŤȚŢ",
 748 |       "uùúủũụưừứửữựûüůū",
 749 |       "UÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ",
 750 |       "yýỳỷỹỵÿ",
 751 |       "YÝỲỶỸỴŸ",
 752 |       "zžżź",
 753 |       "ZŽŻŹ"
 754 |     ] : [
 755 |       "aàáảãạăằắẳẵặâầấẩẫậäåāąAÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ",
 756 |       "cçćčCÇĆČ",
 757 |       "dđďDĐĎ",
 758 |       "eèéẻẽẹêềếểễệëěēęEÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ",
 759 |       "iìíỉĩịîïīIÌÍỈĨỊÎÏĪ",
 760 |       "lłLŁ",
 761 |       "nñňńNÑŇŃ",
 762 |       "oòóỏõọôồốổỗộơởỡớờợöøōOÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ",
 763 |       "rřRŘ",
 764 |       "sšśșşSŠŚȘŞ",
 765 |       "tťțţTŤȚŢ",
 766 |       "uùúủũụưừứửữựûüůūUÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ",
 767 |       "yýỳỷỹỵÿYÝỲỶỸỴŸ",
 768 |       "zžżźZŽŻŹ"
 769 |     ];
 770 |     let handled = [];
 771 |     str.split("").forEach((ch) => {
 772 |       dct.every((dct2) => {
 773 |         if (dct2.indexOf(ch) !== -1) {
 774 |           if (handled.indexOf(dct2) > -1) {
 775 |             return false;
 776 |           }
 777 |           str = str.replace(
 778 |             new RegExp(`[${dct2}]`, `gm${sens}`),
 779 |             `[${dct2}]`
 780 |           );
 781 |           handled.push(dct2);
 782 |         }
 783 |         return true;
 784 |       });
 785 |     });
 786 |     return str;
 787 |   }
 788 |   /**
 789 |    * Creates a regular expression string that merges whitespace characters
 790 |    * including subsequent ones into a single pattern, one or multiple
 791 |    * whitespaces
 792 |    * @param  {string} str - The search term to be used
 793 |    * @return {string}
 794 |    * @access protected
 795 |    */
 796 |   createMergedBlanksRegExp(str) {
 797 |     return str.replace(/[\s]+/gmi, "[\\s]+");
 798 |   }
 799 |   /**
 800 |    * Creates a regular expression string to match the specified string with
 801 |    * the defined accuracy. As in the regular expression of "exactly" can be
 802 |    * a group containing a blank at the beginning, all regular expressions will
 803 |    * be created with two groups. The first group can be ignored (may contain
 804 |    * the said blank), the second contains the actual match
 805 |    * @param  {string} str - The searm term to be used
 806 |    * @return {str}
 807 |    * @access protected
 808 |    */
 809 |   createAccuracyRegExp(str) {
 810 |     const chars = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~¡¿";
 811 |     let acc = this.opt.accuracy, val = typeof acc === "string" ? acc : acc.value, ls = typeof acc === "string" ? [] : acc.limiters, lsJoin = "";
 812 |     ls.forEach((limiter) => {
 813 |       lsJoin += `|${this.escapeStr(limiter)}`;
 814 |     });
 815 |     switch (val) {
 816 |       case "partially":
 817 |       default:
 818 |         return `()(${str})`;
 819 |       case "complementary":
 820 |         lsJoin = "\\s" + (lsJoin ? lsJoin : this.escapeStr(chars));
 821 |         return `()([^${lsJoin}]*${str}[^${lsJoin}]*)`;
 822 |       case "exactly":
 823 |         return `(^|\\s${lsJoin})(${str})(?=$|\\s${lsJoin})`;
 824 |     }
 825 |   }
 826 |   /**
 827 |    * @typedef Mark~separatedKeywords
 828 |    * @type {object.<string>}
 829 |    * @property {array.<string>} keywords - The list of keywords
 830 |    * @property {number} length - The length
 831 |    */
 832 |   /**
 833 |    * Returns a list of keywords dependent on whether separate word search
 834 |    * was defined. Also it filters empty keywords
 835 |    * @param {array} sv - The array of keywords
 836 |    * @return {Mark~separatedKeywords}
 837 |    * @access protected
 838 |    */
 839 |   getSeparatedKeywords(sv) {
 840 |     let stack = [];
 841 |     sv.forEach((kw) => {
 842 |       if (!this.opt.separateWordSearch) {
 843 |         if (kw.trim() && stack.indexOf(kw) === -1) {
 844 |           stack.push(kw);
 845 |         }
 846 |       } else {
 847 |         kw.split(" ").forEach((kwSplitted) => {
 848 |           if (kwSplitted.trim() && stack.indexOf(kwSplitted) === -1) {
 849 |             stack.push(kwSplitted);
 850 |           }
 851 |         });
 852 |       }
 853 |     });
 854 |     return {
 855 |       // sort because of https://git.io/v6USg
 856 |       "keywords": stack.sort((a, b) => {
 857 |         return b.length - a.length;
 858 |       }),
 859 |       "length": stack.length
 860 |     };
 861 |   }
 862 |   /**
 863 |    * Check if a value is a number
 864 |    * @param {number|string} value - the value to check;
 865 |    * numeric strings allowed
 866 |    * @return {boolean}
 867 |    * @access protected
 868 |    */
 869 |   isNumeric(value) {
 870 |     return Number(parseFloat(value)) == value;
 871 |   }
 872 |   /**
 873 |    * @typedef Mark~rangeObject
 874 |    * @type {object}
 875 |    * @property {number} start - The start position within the composite value
 876 |    * @property {number} length - The length of the string to mark within the
 877 |    * composite value.
 878 |    */
 879 |   /**
 880 |    * @typedef Mark~setOfRanges
 881 |    * @type {object[]}
 882 |    * @property {Mark~rangeObject}
 883 |    */
 884 |   /**
 885 |    * Returns a processed list of integer offset indexes that do not overlap
 886 |    * each other, and remove any string values or additional elements
 887 |    * @param {Mark~setOfRanges} array - unprocessed raw array
 888 |    * @return {Mark~setOfRanges} - processed array with any invalid entries
 889 |    * removed
 890 |    * @throws Will throw an error if an array of objects is not passed
 891 |    * @access protected
 892 |    */
 893 |   checkRanges(array) {
 894 |     if (!Array.isArray(array) || Object.prototype.toString.call(array[0]) !== "[object Object]") {
 895 |       this.log("markRanges() will only accept an array of objects");
 896 |       this.opt.noMatch(array);
 897 |       return [];
 898 |     }
 899 |     const stack = [];
 900 |     let last = 0;
 901 |     array.sort((a, b) => {
 902 |       return a.start - b.start;
 903 |     }).forEach((item) => {
 904 |       let { start, end, valid } = this.callNoMatchOnInvalidRanges(item, last);
 905 |       if (valid) {
 906 |         item.start = start;
 907 |         item.length = end - start;
 908 |         stack.push(item);
 909 |         last = end;
 910 |       }
 911 |     });
 912 |     return stack;
 913 |   }
 914 |   /**
 915 |    * @typedef Mark~validObject
 916 |    * @type {object}
 917 |    * @property {number} start - The start position within the composite value
 918 |    * @property {number} end - The calculated end position within the composite
 919 |    * value.
 920 |    * @property {boolean} valid - boolean value indicating that the start and
 921 |    * calculated end range is valid
 922 |    */
 923 |   /**
 924 |     * Initial validation of ranges for markRanges. Preliminary checks are done
 925 |     * to ensure the start and length values exist and are not zero or non-
 926 |     * numeric
 927 |     * @param {Mark~rangeObject} range - the current range object
 928 |     * @param {number} last - last index of range
 929 |     * @return {Mark~validObject}
 930 |     * @access protected
 931 |     */
 932 |   callNoMatchOnInvalidRanges(range, last) {
 933 |     let start, end, valid = false;
 934 |     if (range && typeof range.start !== "undefined") {
 935 |       start = parseInt(range.start, 10);
 936 |       end = start + parseInt(range.length, 10);
 937 |       if (this.isNumeric(range.start) && this.isNumeric(range.length) && end - last > 0 && end - start > 0) {
 938 |         valid = true;
 939 |       } else {
 940 |         this.log(
 941 |           `Ignoring invalid or overlapping range: ${JSON.stringify(range)}`
 942 |         );
 943 |         this.opt.noMatch(range);
 944 |       }
 945 |     } else {
 946 |       this.log(`Ignoring invalid range: ${JSON.stringify(range)}`);
 947 |       this.opt.noMatch(range);
 948 |     }
 949 |     return {
 950 |       start,
 951 |       end,
 952 |       valid
 953 |     };
 954 |   }
 955 |   /**
 956 |    * Check valid range for markRanges. Check ranges with access to the context
 957 |    * string. Range values are double checked, lengths that extend the mark
 958 |    * beyond the string length are limitied and ranges containing only
 959 |    * whitespace are ignored
 960 |    * @param {Mark~rangeObject} range - the current range object
 961 |    * @param {number} originalLength - original length of the context string
 962 |    * @param {string} string - current content string
 963 |    * @return {Mark~validObject}
 964 |    * @access protected
 965 |    */
 966 |   checkWhitespaceRanges(range, originalLength, string) {
 967 |     let end, valid = true, max = string.length, offset = originalLength - max, start = parseInt(range.start, 10) - offset;
 968 |     start = start > max ? max : start;
 969 |     end = start + parseInt(range.length, 10);
 970 |     if (end > max) {
 971 |       end = max;
 972 |       this.log(`End range automatically set to the max value of ${max}`);
 973 |     }
 974 |     if (start < 0 || end - start < 0 || start > max || end > max) {
 975 |       valid = false;
 976 |       this.log(`Invalid range: ${JSON.stringify(range)}`);
 977 |       this.opt.noMatch(range);
 978 |     } else if (string.substring(start, end).replace(/\s+/g, "") === "") {
 979 |       valid = false;
 980 |       this.log("Skipping whitespace only range: " + JSON.stringify(range));
 981 |       this.opt.noMatch(range);
 982 |     }
 983 |     return {
 984 |       start,
 985 |       end,
 986 |       valid
 987 |     };
 988 |   }
 989 |   /**
 990 |    * @typedef Mark~getTextNodesDict
 991 |    * @type {object.<string>}
 992 |    * @property {string} value - The composite value of all text nodes
 993 |    * @property {object[]} nodes - An array of objects
 994 |    * @property {number} nodes.start - The start position within the composite
 995 |    * value
 996 |    * @property {number} nodes.end - The end position within the composite
 997 |    * value
 998 |    * @property {HTMLElement} nodes.node - The DOM text node element
 999 |    */
1000 |   /**
1001 |    * Callback
1002 |    * @callback Mark~getTextNodesCallback
1003 |    * @param {Mark~getTextNodesDict}
1004 |    */
1005 |   /**
1006 |    * Calls the callback with an object containing all text nodes (including
1007 |    * iframe text nodes) with start and end positions and the composite value
1008 |    * of them (string)
1009 |    * @param {Mark~getTextNodesCallback} cb - Callback
1010 |    * @access protected
1011 |    */
1012 |   getTextNodes(cb) {
1013 |     let val = "", nodes = [];
1014 |     this.iterator.forEachNode(NodeFilter.SHOW_TEXT, (node) => {
1015 |       nodes.push({
1016 |         start: val.length,
1017 |         end: (val += node.textContent).length,
1018 |         node
1019 |       });
1020 |     }, (node) => {
1021 |       if (this.matchesExclude(node.parentNode)) {
1022 |         return NodeFilter.FILTER_REJECT;
1023 |       } else {
1024 |         return NodeFilter.FILTER_ACCEPT;
1025 |       }
1026 |     }, () => {
1027 |       cb({
1028 |         value: val,
1029 |         nodes
1030 |       });
1031 |     });
1032 |   }
1033 |   /**
1034 |    * Checks if an element matches any of the specified exclude selectors. Also
1035 |    * it checks for elements in which no marks should be performed (e.g.
1036 |    * script and style tags) and optionally already marked elements
1037 |    * @param  {HTMLElement} el - The element to check
1038 |    * @return {boolean}
1039 |    * @access protected
1040 |    */
1041 |   matchesExclude(el) {
1042 |     return DOMIterator.matches(el, this.opt.exclude.concat([
1043 |       // ignores the elements itself, not their childrens (selector *)
1044 |       "script",
1045 |       "style",
1046 |       "title",
1047 |       "head",
1048 |       "html"
1049 |     ]));
1050 |   }
1051 |   /**
1052 |    * Wraps the instance element and class around matches that fit the start
1053 |    * and end positions within the node
1054 |    * @param  {HTMLElement} node - The DOM text node
1055 |    * @param  {number} start - The position where to start wrapping
1056 |    * @param  {number} end - The position where to end wrapping
1057 |    * @return {HTMLElement} Returns the splitted text node that will appear
1058 |    * after the wrapped text node
1059 |    * @access protected
1060 |    */
1061 |   wrapRangeInTextNode(node, start, end) {
1062 |     const hEl = !this.opt.element ? "mark" : this.opt.element, startNode = node.splitText(start), ret = startNode.splitText(end - start);
1063 |     let repl = document.createElement(hEl);
1064 |     repl.setAttribute("data-markjs", "true");
1065 |     if (this.opt.className) {
1066 |       repl.setAttribute("class", this.opt.className);
1067 |     }
1068 |     repl.textContent = startNode.textContent;
1069 |     startNode.parentNode.replaceChild(repl, startNode);
1070 |     return ret;
1071 |   }
1072 |   /**
1073 |    * @typedef Mark~wrapRangeInMappedTextNodeDict
1074 |    * @type {object.<string>}
1075 |    * @property {string} value - The composite value of all text nodes
1076 |    * @property {object[]} nodes - An array of objects
1077 |    * @property {number} nodes.start - The start position within the composite
1078 |    * value
1079 |    * @property {number} nodes.end - The end position within the composite
1080 |    * value
1081 |    * @property {HTMLElement} nodes.node - The DOM text node element
1082 |    */
1083 |   /**
1084 |    * Each callback
1085 |    * @callback Mark~wrapMatchesEachCallback
1086 |    * @param {HTMLElement} node - The wrapped DOM element
1087 |    * @param {number} lastIndex - The last matching position within the
1088 |    * composite value of text nodes
1089 |    */
1090 |   /**
1091 |    * Filter callback
1092 |    * @callback Mark~wrapMatchesFilterCallback
1093 |    * @param {HTMLElement} node - The matching text node DOM element
1094 |    */
1095 |   /**
1096 |    * Determines matches by start and end positions using the text node
1097 |    * dictionary even across text nodes and calls
1098 |    * {@link Mark#wrapRangeInTextNode} to wrap them
1099 |    * @param  {Mark~wrapRangeInMappedTextNodeDict} dict - The dictionary
1100 |    * @param  {number} start - The start position of the match
1101 |    * @param  {number} end - The end position of the match
1102 |    * @param  {Mark~wrapMatchesFilterCallback} filterCb - Filter callback
1103 |    * @param  {Mark~wrapMatchesEachCallback} eachCb - Each callback
1104 |    * @access protected
1105 |    */
1106 |   wrapRangeInMappedTextNode(dict, start, end, filterCb, eachCb) {
1107 |     dict.nodes.every((n, i) => {
1108 |       const sibl = dict.nodes[i + 1];
1109 |       if (typeof sibl === "undefined" || sibl.start > start) {
1110 |         if (!filterCb(n.node)) {
1111 |           return false;
1112 |         }
1113 |         const s = start - n.start, e = (end > n.end ? n.end : end) - n.start, startStr = dict.value.substr(0, n.start), endStr = dict.value.substr(e + n.start);
1114 |         n.node = this.wrapRangeInTextNode(n.node, s, e);
1115 |         dict.value = startStr + endStr;
1116 |         dict.nodes.forEach((k, j) => {
1117 |           if (j >= i) {
1118 |             if (dict.nodes[j].start > 0 && j !== i) {
1119 |               dict.nodes[j].start -= e;
1120 |             }
1121 |             dict.nodes[j].end -= e;
1122 |           }
1123 |         });
1124 |         end -= e;
1125 |         eachCb(n.node.previousSibling, n.start);
1126 |         if (end > n.end) {
1127 |           start = n.end;
1128 |         } else {
1129 |           return false;
1130 |         }
1131 |       }
1132 |       return true;
1133 |     });
1134 |   }
1135 |   /**
1136 |    * Filter callback before each wrapping
1137 |    * @callback Mark~wrapMatchesFilterCallback
1138 |    * @param {string} match - The matching string
1139 |    * @param {HTMLElement} node - The text node where the match occurs
1140 |    */
1141 |   /**
1142 |    * Callback for each wrapped element
1143 |    * @callback Mark~wrapMatchesEachCallback
1144 |    * @param {HTMLElement} element - The marked DOM element
1145 |    */
1146 |   /**
1147 |    * Callback on end
1148 |    * @callback Mark~wrapMatchesEndCallback
1149 |    */
1150 |   /**
1151 |    * Wraps the instance element and class around matches within single HTML
1152 |    * elements in all contexts
1153 |    * @param {RegExp} regex - The regular expression to be searched for
1154 |    * @param {number} ignoreGroups - A number indicating the amount of RegExp
1155 |    * matching groups to ignore
1156 |    * @param {Mark~wrapMatchesFilterCallback} filterCb
1157 |    * @param {Mark~wrapMatchesEachCallback} eachCb
1158 |    * @param {Mark~wrapMatchesEndCallback} endCb
1159 |    * @access protected
1160 |    */
1161 |   wrapMatches(regex, ignoreGroups, filterCb, eachCb, endCb) {
1162 |     const matchIdx = ignoreGroups === 0 ? 0 : ignoreGroups + 1;
1163 |     this.getTextNodes((dict) => {
1164 |       dict.nodes.forEach((node) => {
1165 |         node = node.node;
1166 |         let match;
1167 |         while ((match = regex.exec(node.textContent)) !== null && match[matchIdx] !== "") {
1168 |           if (!filterCb(match[matchIdx], node)) {
1169 |             continue;
1170 |           }
1171 |           let pos = match.index;
1172 |           if (matchIdx !== 0) {
1173 |             for (let i = 1; i < matchIdx; i++) {
1174 |               pos += match[i].length;
1175 |             }
1176 |           }
1177 |           node = this.wrapRangeInTextNode(
1178 |             node,
1179 |             pos,
1180 |             pos + match[matchIdx].length
1181 |           );
1182 |           eachCb(node.previousSibling);
1183 |           regex.lastIndex = 0;
1184 |         }
1185 |       });
1186 |       endCb();
1187 |     });
1188 |   }
1189 |   /**
1190 |    * Callback for each wrapped element
1191 |    * @callback Mark~wrapMatchesAcrossElementsEachCallback
1192 |    * @param {HTMLElement} element - The marked DOM element
1193 |    */
1194 |   /**
1195 |    * Filter callback before each wrapping
1196 |    * @callback Mark~wrapMatchesAcrossElementsFilterCallback
1197 |    * @param {string} match - The matching string
1198 |    * @param {HTMLElement} node - The text node where the match occurs
1199 |    */
1200 |   /**
1201 |    * Callback on end
1202 |    * @callback Mark~wrapMatchesAcrossElementsEndCallback
1203 |    */
1204 |   /**
1205 |    * Wraps the instance element and class around matches across all HTML
1206 |    * elements in all contexts
1207 |    * @param {RegExp} regex - The regular expression to be searched for
1208 |    * @param {number} ignoreGroups - A number indicating the amount of RegExp
1209 |    * matching groups to ignore
1210 |    * @param {Mark~wrapMatchesAcrossElementsFilterCallback} filterCb
1211 |    * @param {Mark~wrapMatchesAcrossElementsEachCallback} eachCb
1212 |    * @param {Mark~wrapMatchesAcrossElementsEndCallback} endCb
1213 |    * @access protected
1214 |    */
1215 |   wrapMatchesAcrossElements(regex, ignoreGroups, filterCb, eachCb, endCb) {
1216 |     const matchIdx = ignoreGroups === 0 ? 0 : ignoreGroups + 1;
1217 |     this.getTextNodes((dict) => {
1218 |       let match;
1219 |       while ((match = regex.exec(dict.value)) !== null && match[matchIdx] !== "") {
1220 |         let start = match.index;
1221 |         if (matchIdx !== 0) {
1222 |           for (let i = 1; i < matchIdx; i++) {
1223 |             start += match[i].length;
1224 |           }
1225 |         }
1226 |         const end = start + match[matchIdx].length;
1227 |         this.wrapRangeInMappedTextNode(dict, start, end, (node) => {
1228 |           return filterCb(match[matchIdx], node);
1229 |         }, (node, lastIndex) => {
1230 |           regex.lastIndex = lastIndex;
1231 |           eachCb(node);
1232 |         });
1233 |       }
1234 |       endCb();
1235 |     });
1236 |   }
1237 |   /**
1238 |    * Callback for each wrapped element
1239 |    * @callback Mark~wrapRangeFromIndexEachCallback
1240 |    * @param {HTMLElement} element - The marked DOM element
1241 |    * @param {Mark~rangeObject} range - the current range object; provided
1242 |    * start and length values will be numeric integers modified from the
1243 |    * provided original ranges.
1244 |    */
1245 |   /**
1246 |    * Filter callback before each wrapping
1247 |    * @callback Mark~wrapRangeFromIndexFilterCallback
1248 |    * @param {HTMLElement} node - The text node which includes the range
1249 |    * @param {Mark~rangeObject} range - the current range object
1250 |    * @param {string} match - string extracted from the matching range
1251 |    * @param {number} counter - A counter indicating the number of all marks
1252 |    */
1253 |   /**
1254 |    * Callback on end
1255 |    * @callback Mark~wrapRangeFromIndexEndCallback
1256 |    */
1257 |   /**
1258 |    * Wraps the indicated ranges across all HTML elements in all contexts
1259 |    * @param {Mark~setOfRanges} ranges
1260 |    * @param {Mark~wrapRangeFromIndexFilterCallback} filterCb
1261 |    * @param {Mark~wrapRangeFromIndexEachCallback} eachCb
1262 |    * @param {Mark~wrapRangeFromIndexEndCallback} endCb
1263 |    * @access protected
1264 |    */
1265 |   wrapRangeFromIndex(ranges, filterCb, eachCb, endCb) {
1266 |     this.getTextNodes((dict) => {
1267 |       const originalLength = dict.value.length;
1268 |       ranges.forEach((range, counter) => {
1269 |         let { start, end, valid } = this.checkWhitespaceRanges(
1270 |           range,
1271 |           originalLength,
1272 |           dict.value
1273 |         );
1274 |         if (valid) {
1275 |           this.wrapRangeInMappedTextNode(dict, start, end, (node) => {
1276 |             return filterCb(
1277 |               node,
1278 |               range,
1279 |               dict.value.substring(start, end),
1280 |               counter
1281 |             );
1282 |           }, (node) => {
1283 |             eachCb(node, range);
1284 |           });
1285 |         }
1286 |       });
1287 |       endCb();
1288 |     });
1289 |   }
1290 |   /**
1291 |    * Unwraps the specified DOM node with its content (text nodes or HTML)
1292 |    * without destroying possibly present events (using innerHTML) and
1293 |    * normalizes the parent at the end (merge splitted text nodes)
1294 |    * @param  {HTMLElement} node - The DOM node to unwrap
1295 |    * @access protected
1296 |    */
1297 |   unwrapMatches(node) {
1298 |     const parent = node.parentNode;
1299 |     let docFrag = document.createDocumentFragment();
1300 |     while (node.firstChild) {
1301 |       docFrag.appendChild(node.removeChild(node.firstChild));
1302 |     }
1303 |     parent.replaceChild(docFrag, node);
1304 |     if (!this.ie) {
1305 |       parent.normalize();
1306 |     } else {
1307 |       this.normalizeTextNode(parent);
1308 |     }
1309 |   }
1310 |   /**
1311 |    * Normalizes text nodes. It's a workaround for the native normalize method
1312 |    * that has a bug in IE (see attached link). Should only be used in IE
1313 |    * browsers as it's slower than the native method.
1314 |    * @see {@link http://tinyurl.com/z5asa8c}
1315 |    * @param {HTMLElement} node - The DOM node to normalize
1316 |    * @access protected
1317 |    */
1318 |   normalizeTextNode(node) {
1319 |     if (!node) {
1320 |       return;
1321 |     }
1322 |     if (node.nodeType === 3) {
1323 |       while (node.nextSibling && node.nextSibling.nodeType === 3) {
1324 |         node.nodeValue += node.nextSibling.nodeValue;
1325 |         node.parentNode.removeChild(node.nextSibling);
1326 |       }
1327 |     } else {
1328 |       this.normalizeTextNode(node.firstChild);
1329 |     }
1330 |     this.normalizeTextNode(node.nextSibling);
1331 |   }
1332 |   /**
1333 |    * Callback when finished
1334 |    * @callback Mark~commonDoneCallback
1335 |    * @param {number} totalMatches - The number of marked elements
1336 |    */
1337 |   /**
1338 |    * @typedef Mark~commonOptions
1339 |    * @type {object.<string>}
1340 |    * @property {string} [element="mark"] - HTML element tag name
1341 |    * @property {string} [className] - An optional class name
1342 |    * @property {string[]} [exclude] - An array with exclusion selectors.
1343 |    * Elements matching those selectors will be ignored
1344 |    * @property {boolean} [iframes=false] - Whether to search inside iframes
1345 |    * @property {Mark~commonDoneCallback} [done]
1346 |    * @property {boolean} [debug=false] - Wheter to log messages
1347 |    * @property {object} [log=window.console] - Where to log messages (only if
1348 |    * debug is true)
1349 |    */
1350 |   /**
1351 |    * Callback for each marked element
1352 |    * @callback Mark~markRegExpEachCallback
1353 |    * @param {HTMLElement} element - The marked DOM element
1354 |    */
1355 |   /**
1356 |    * Callback if there were no matches
1357 |    * @callback Mark~markRegExpNoMatchCallback
1358 |    * @param {RegExp} regexp - The regular expression
1359 |    */
1360 |   /**
1361 |    * Callback to filter matches
1362 |    * @callback Mark~markRegExpFilterCallback
1363 |    * @param {HTMLElement} textNode - The text node which includes the match
1364 |    * @param {string} match - The matching string for the RegExp
1365 |    * @param {number} counter - A counter indicating the number of all marks
1366 |    */
1367 |   /**
1368 |    * These options also include the common options from
1369 |    * {@link Mark~commonOptions}
1370 |    * @typedef Mark~markRegExpOptions
1371 |    * @type {object.<string>}
1372 |    * @property {Mark~markRegExpEachCallback} [each]
1373 |    * @property {Mark~markRegExpNoMatchCallback} [noMatch]
1374 |    * @property {Mark~markRegExpFilterCallback} [filter]
1375 |    */
1376 |   /**
1377 |    * Marks a custom regular expression
1378 |    * @param  {RegExp} regexp - The regular expression
1379 |    * @param  {Mark~markRegExpOptions} [opt] - Optional options object
1380 |    * @access public
1381 |    */
1382 |   markRegExp(regexp, opt) {
1383 |     this.opt = opt;
1384 |     this.log(`Searching with expression "${regexp}"`);
1385 |     let totalMatches = 0, fn = "wrapMatches";
1386 |     const eachCb = (element) => {
1387 |       totalMatches++;
1388 |       this.opt.each(element);
1389 |     };
1390 |     if (this.opt.acrossElements) {
1391 |       fn = "wrapMatchesAcrossElements";
1392 |     }
1393 |     this[fn](regexp, this.opt.ignoreGroups, (match, node) => {
1394 |       return this.opt.filter(node, match, totalMatches);
1395 |     }, eachCb, () => {
1396 |       if (totalMatches === 0) {
1397 |         this.opt.noMatch(regexp);
1398 |       }
1399 |       this.opt.done(totalMatches);
1400 |     });
1401 |   }
1402 |   /**
1403 |    * Callback for each marked element
1404 |    * @callback Mark~markEachCallback
1405 |    * @param {HTMLElement} element - The marked DOM element
1406 |    */
1407 |   /**
1408 |    * Callback if there were no matches
1409 |    * @callback Mark~markNoMatchCallback
1410 |    * @param {RegExp} term - The search term that was not found
1411 |    */
1412 |   /**
1413 |    * Callback to filter matches
1414 |    * @callback Mark~markFilterCallback
1415 |    * @param {HTMLElement} textNode - The text node which includes the match
1416 |    * @param {string} match - The matching term
1417 |    * @param {number} totalCounter - A counter indicating the number of all
1418 |    * marks
1419 |    * @param {number} termCounter - A counter indicating the number of marks
1420 |    * for the specific match
1421 |    */
1422 |   /**
1423 |    * @typedef Mark~markAccuracyObject
1424 |    * @type {object.<string>}
1425 |    * @property {string} value - A accuracy string value
1426 |    * @property {string[]} limiters - A custom array of limiters. For example
1427 |    * <code>["-", ","]</code>
1428 |    */
1429 |   /**
1430 |    * @typedef Mark~markAccuracySetting
1431 |    * @type {string}
1432 |    * @property {"partially"|"complementary"|"exactly"|Mark~markAccuracyObject}
1433 |    * [accuracy="partially"] - Either one of the following string values:
1434 |    * <ul>
1435 |    *   <li><i>partially</i>: When searching for "lor" only "lor" inside
1436 |    *   "lorem" will be marked</li>
1437 |    *   <li><i>complementary</i>: When searching for "lor" the whole word
1438 |    *   "lorem" will be marked</li>
1439 |    *   <li><i>exactly</i>: When searching for "lor" only those exact words
1440 |    *   will be marked. In this example nothing inside "lorem". This value
1441 |    *   is equivalent to the previous option <i>wordBoundary</i></li>
1442 |    * </ul>
1443 |    * Or an object containing two properties:
1444 |    * <ul>
1445 |    *   <li><i>value</i>: One of the above named string values</li>
1446 |    *   <li><i>limiters</i>: A custom array of string limiters for accuracy
1447 |    *   "exactly" or "complementary"</li>
1448 |    * </ul>
1449 |    */
1450 |   /**
1451 |    * @typedef Mark~markWildcardsSetting
1452 |    * @type {string}
1453 |    * @property {"disabled"|"enabled"|"withSpaces"}
1454 |    * [wildcards="disabled"] - Set to any of the following string values:
1455 |    * <ul>
1456 |    *   <li><i>disabled</i>: Disable wildcard usage</li>
1457 |    *   <li><i>enabled</i>: When searching for "lor?m", the "?" will match zero
1458 |    *   or one non-space character (e.g. "lorm", "loram", "lor3m", etc). When
1459 |    *   searching for "lor*m", the "*" will match zero or more non-space
1460 |    *   characters (e.g. "lorm", "loram", "lor123m", etc).</li>
1461 |    *   <li><i>withSpaces</i>: When searching for "lor?m", the "?" will
1462 |    *   match zero or one space or non-space character (e.g. "lor m", "loram",
1463 |    *   etc). When searching for "lor*m", the "*" will match zero or more space
1464 |    *   or non-space characters (e.g. "lorm", "lore et dolor ipsum", "lor: m",
1465 |    *   etc).</li>
1466 |    * </ul>
1467 |    */
1468 |   /**
1469 |    * @typedef Mark~markIgnorePunctuationSetting
1470 |    * @type {string[]}
1471 |    * @property {string} The strings in this setting will contain punctuation
1472 |    * marks that will be ignored:
1473 |    * <ul>
1474 |    *   <li>These punctuation marks can be between any characters, e.g. setting
1475 |    *   this option to <code>["'"]</code> would match "Worlds", "World's" and
1476 |    *   "Wo'rlds"</li>
1477 |    *   <li>One or more apostrophes between the letters would still produce a
1478 |    *   match (e.g. "W'o''r'l'd's").</li>
1479 |    *   <li>A typical setting for this option could be as follows:
1480 |    *   <pre>ignorePunctuation: ":;.,-–—‒_(){}[]!'\"+=".split(""),</pre> This
1481 |    *   setting includes common punctuation as well as a minus, en-dash,
1482 |    *   em-dash and figure-dash
1483 |    *   ({@link https://en.wikipedia.org/wiki/Dash#Figure_dash ref}), as well
1484 |    *   as an underscore.</li>
1485 |    * </ul>
1486 |    */
1487 |   /**
1488 |    * These options also include the common options from
1489 |    * {@link Mark~commonOptions}
1490 |    * @typedef Mark~markOptions
1491 |    * @type {object.<string>}
1492 |    * @property {boolean} [separateWordSearch=true] - Whether to search for
1493 |    * each word separated by a blank instead of the complete term
1494 |    * @property {boolean} [diacritics=true] - If diacritic characters should be
1495 |    * matched. ({@link https://en.wikipedia.org/wiki/Diacritic Diacritics})
1496 |    * @property {object} [synonyms] - An object with synonyms. The key will be
1497 |    * a synonym for the value and the value for the key
1498 |    * @property {Mark~markAccuracySetting} [accuracy]
1499 |    * @property {Mark~markWildcardsSetting} [wildcards]
1500 |    * @property {boolean} [acrossElements=false] - Whether to find matches
1501 |    * across HTML elements. By default, only matches within single HTML
1502 |    * elements will be found
1503 |    * @property {boolean} [ignoreJoiners=false] - Whether to ignore word
1504 |    * joiners inside of key words. These include soft-hyphens, zero-width
1505 |    * space, zero-width non-joiners and zero-width joiners.
1506 |    * @property {Mark~markIgnorePunctuationSetting} [ignorePunctuation]
1507 |    * @property {Mark~markEachCallback} [each]
1508 |    * @property {Mark~markNoMatchCallback} [noMatch]
1509 |    * @property {Mark~markFilterCallback} [filter]
1510 |    */
1511 |   /**
1512 |    * Marks the specified search terms
1513 |    * @param {string|string[]} [sv] - Search value, either a search string or
1514 |    * an array containing multiple search strings
1515 |    * @param  {Mark~markOptions} [opt] - Optional options object
1516 |    * @access public
1517 |    */
1518 |   mark(sv, opt) {
1519 |     this.opt = opt;
1520 |     let totalMatches = 0, fn = "wrapMatches";
1521 |     const {
1522 |       keywords: kwArr,
1523 |       length: kwArrLen
1524 |     } = this.getSeparatedKeywords(typeof sv === "string" ? [sv] : sv), sens = this.opt.caseSensitive ? "" : "i", handler = (kw) => {
1525 |       let regex = new RegExp(this.createRegExp(kw), `gm${sens}`), matches = 0;
1526 |       this.log(`Searching with expression "${regex}"`);
1527 |       this[fn](regex, 1, (term, node) => {
1528 |         return this.opt.filter(node, kw, totalMatches, matches);
1529 |       }, (element) => {
1530 |         matches++;
1531 |         totalMatches++;
1532 |         this.opt.each(element);
1533 |       }, () => {
1534 |         if (matches === 0) {
1535 |           this.opt.noMatch(kw);
1536 |         }
1537 |         if (kwArr[kwArrLen - 1] === kw) {
1538 |           this.opt.done(totalMatches);
1539 |         } else {
1540 |           handler(kwArr[kwArr.indexOf(kw) + 1]);
1541 |         }
1542 |       });
1543 |     };
1544 |     if (this.opt.acrossElements) {
1545 |       fn = "wrapMatchesAcrossElements";
1546 |     }
1547 |     if (kwArrLen === 0) {
1548 |       this.opt.done(totalMatches);
1549 |     } else {
1550 |       handler(kwArr[0]);
1551 |     }
1552 |   }
1553 |   /**
1554 |    * Callback for each marked element
1555 |    * @callback Mark~markRangesEachCallback
1556 |    * @param {HTMLElement} element - The marked DOM element
1557 |    * @param {array} range - array of range start and end points
1558 |    */
1559 |   /**
1560 |    * Callback if a processed range is invalid, out-of-bounds, overlaps another
1561 |    * range, or only matches whitespace
1562 |    * @callback Mark~markRangesNoMatchCallback
1563 |    * @param {Mark~rangeObject} range - a range object
1564 |    */
1565 |   /**
1566 |    * Callback to filter matches
1567 |    * @callback Mark~markRangesFilterCallback
1568 |    * @param {HTMLElement} node - The text node which includes the range
1569 |    * @param {array} range - array of range start and end points
1570 |    * @param {string} match - string extracted from the matching range
1571 |    * @param {number} counter - A counter indicating the number of all marks
1572 |    */
1573 |   /**
1574 |    * These options also include the common options from
1575 |    * {@link Mark~commonOptions}
1576 |    * @typedef Mark~markRangesOptions
1577 |    * @type {object.<string>}
1578 |    * @property {Mark~markRangesEachCallback} [each]
1579 |    * @property {Mark~markRangesNoMatchCallback} [noMatch]
1580 |    * @property {Mark~markRangesFilterCallback} [filter]
1581 |    */
1582 |   /**
1583 |    * Marks an array of objects containing a start with an end or length of the
1584 |    * string to mark
1585 |    * @param  {Mark~setOfRanges} rawRanges - The original (preprocessed)
1586 |    * array of objects
1587 |    * @param  {Mark~markRangesOptions} [opt] - Optional options object
1588 |    * @access public
1589 |    */
1590 |   markRanges(rawRanges, opt) {
1591 |     this.opt = opt;
1592 |     let totalMatches = 0, ranges = this.checkRanges(rawRanges);
1593 |     if (ranges && ranges.length) {
1594 |       this.log(
1595 |         "Starting to mark with the following ranges: " + JSON.stringify(ranges)
1596 |       );
1597 |       this.wrapRangeFromIndex(
1598 |         ranges,
1599 |         (node, range, match, counter) => {
1600 |           return this.opt.filter(node, range, match, counter);
1601 |         },
1602 |         (element, range) => {
1603 |           totalMatches++;
1604 |           this.opt.each(element, range);
1605 |         },
1606 |         () => {
1607 |           this.opt.done(totalMatches);
1608 |         }
1609 |       );
1610 |     } else {
1611 |       this.opt.done(totalMatches);
1612 |     }
1613 |   }
1614 |   /**
1615 |    * Removes all marked elements inside the context with their HTML and
1616 |    * normalizes the parent at the end
1617 |    * @param  {Mark~commonOptions} [opt] - Optional options object
1618 |    * @access public
1619 |    */
1620 |   unmark(opt) {
1621 |     this.opt = opt;
1622 |     let sel = this.opt.element ? this.opt.element : "*";
1623 |     sel += "[data-markjs]";
1624 |     if (this.opt.className) {
1625 |       sel += `.${this.opt.className}`;
1626 |     }
1627 |     this.log(`Removal selector "${sel}"`);
1628 |     this.iterator.forEachNode(NodeFilter.SHOW_ELEMENT, (node) => {
1629 |       this.unwrapMatches(node);
1630 |     }, (node) => {
1631 |       const matchesSel = DOMIterator.matches(node, sel), matchesExclude = this.matchesExclude(node);
1632 |       if (!matchesSel || matchesExclude) {
1633 |         return NodeFilter.FILTER_REJECT;
1634 |       } else {
1635 |         return NodeFilter.FILTER_ACCEPT;
1636 |       }
1637 |     }, this.opt.done);
1638 |   }
1639 | };
1640 | 
1641 | // node_modules/mark.js/src/vanilla.js
1642 | function Mark2(ctx) {
1643 |   const instance = new Mark(ctx);
1644 |   this.mark = (sv, opt) => {
1645 |     instance.mark(sv, opt);
1646 |     return this;
1647 |   };
1648 |   this.markRegExp = (sv, opt) => {
1649 |     instance.markRegExp(sv, opt);
1650 |     return this;
1651 |   };
1652 |   this.markRanges = (sv, opt) => {
1653 |     instance.markRanges(sv, opt);
1654 |     return this;
1655 |   };
1656 |   this.unmark = (opt) => {
1657 |     instance.unmark(opt);
1658 |     return this;
1659 |   };
1660 |   return this;
1661 | }
1662 | export {
1663 |   Mark2 as default
1664 | };
1665 | //# sourceMappingURL=vitepress___mark__js_src_vanilla__js.js.map
1666 | 
```
Page 5/10FirstPrevNextLast