diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..3396d2f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,24 @@ +# 配置项文档:https://editorconfig.org/ + +# 告知 EditorConfig 插件,当前即是根文件 +root = true + +# 适用全部文件 +[*] +## 设置字符集 +charset = utf-8 +## 缩进风格 space | tab,建议 space +indent_style = space +## 缩进的空格数(修改这里的话需要将 prettier.config.js 和 .vscode -> settings.json 也同步修改) +indent_size = 2 +## 换行符类型 lf | cr | crlf,一般都是设置为 lf +end_of_line = lf +## 是否在文件末尾插入空白行 +insert_final_newline = true +## 是否删除一行中的前后空格 +trim_trailing_whitespace = true + +# 适用 .md 文件 +[*.md] +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/.env b/.env new file mode 100644 index 0000000..b995432 --- /dev/null +++ b/.env @@ -0,0 +1,4 @@ +# 所有环境自定义的环境变量(命名必须以 VITE_ 开头) + +## 项目标题 +VITE_APP_TITLE = V3 Admin Vite diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..12bc1e2 --- /dev/null +++ b/.env.development @@ -0,0 +1,10 @@ +# 开发环境自定义的环境变量(命名必须以 VITE_ 开头) + +## 后端接口公共路径(如果解决跨域问题采用反向代理就只需写公共路径) +VITE_BASE_API = '/api/v1' + +## 路由模式 hash 或 html5 +VITE_ROUTER_HISTORY = 'hash' + +## 开发环境地址前缀(一般 '/','./' 都可以) +VITE_PUBLIC_PATH = '/' diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..2e29772 --- /dev/null +++ b/.env.production @@ -0,0 +1,10 @@ +# 生产环境自定义的环境变量(命名必须以 VITE_ 开头) + +## 后端接口公共路径(如果解决跨域问题采用 CORS 就需要写全路径) +VITE_BASE_API = 'https://www.fastmock.site/mock/761e2dda2b8890ab86c928a74e8f6538/api/v1' + +## 路由模式 hash 或 html5 +VITE_ROUTER_HISTORY = 'hash' + +## 打包路径(就是网站前缀,例如部署到 https://un-pany.github.io/v3-admin-vite/ 域名下,就需要填写 /v3-admin-vite/) +VITE_PUBLIC_PATH = '/v3-admin-vite/' diff --git a/.env.staging b/.env.staging new file mode 100644 index 0000000..001f3c1 --- /dev/null +++ b/.env.staging @@ -0,0 +1,10 @@ +# 预发布环境自定义的环境变量(命名必须以 VITE_ 开头) + +## 后端接口公共路径(如果解决跨域问题采用 CORS 就需要写全路径) +VITE_BASE_API = 'https://www.fastmock.site/mock/761e2dda2b8890ab86c928a74e8f6538/api/v1' + +## 路由模式 hash 或 html5 +VITE_ROUTER_HISTORY = 'hash' + +## 打包路径(就是网站前缀,例如部署到 https://un-pany.github.io/v3-admin-vite/ 域名下,就需要填写 /v3-admin-vite/) +VITE_PUBLIC_PATH = '/v3-admin-vite/' diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..782f425 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,9 @@ +# Eslint 会忽略的文件 + +.DS_Store +node_modules +dist +dist-ssr +dist.zip +*.local +.npmrc diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..daf3435 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,74 @@ +module.exports = { + root: true, + env: { + browser: true, + node: true, + es6: true + }, + extends: [ + "plugin:vue/vue3-essential", + "eslint:recommended", + "@vue/typescript/recommended", + "@vue/prettier", + "@vue/eslint-config-typescript" + ], + parser: "vue-eslint-parser", + parserOptions: { + parser: "@typescript-eslint/parser", + ecmaVersion: 2020, + sourceType: "module", + jsxPragma: "React", + ecmaFeatures: { + jsx: true, + tsx: true + } + }, + rules: { + // TS + "@typescript-eslint/no-explicit-any": "off", + "no-debugger": "off", + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/ban-types": "off", + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/no-unused-vars": [ + "error", + { + argsIgnorePattern: "^_", + varsIgnorePattern: "^_" + } + ], + "no-unused-vars": [ + "error", + { + argsIgnorePattern: "^_", + varsIgnorePattern: "^_" + } + ], + // Vue + "vue/no-v-html": "off", + "vue/require-default-prop": "off", + "vue/require-explicit-emits": "off", + "vue/multi-word-component-names": "off", + "vue/html-self-closing": [ + "error", + { + html: { + void: "always", + normal: "always", + component: "always" + }, + svg: "always", + math: "always" + } + ], + // Prettier + "prettier/prettier": [ + "error", + { + endOfLine: "auto" + } + ] + } +}; diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..735404b --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +custom: https://github.com/un-pany/v3-admin-vite/issues/69 diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..c0ae192 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,35 @@ +name: Build And Deploy v3-admin-vite + +on: + push: + branches: + - main + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + persist-credentials: false + + - name: Setup Node.js 20.10.0 + uses: actions/setup-node@master + with: + node-version: 20.10.0 + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 8.11.0 + + - name: Build + run: pnpm install && pnpm build:prod + + - name: Deploy + uses: JamesIves/github-pages-deploy-action@releases/v3 + with: + ACCESS_TOKEN: ${{ secrets.V3_ADMIN_VITE }} + BRANCH: gh-pages + FOLDER: dist diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..961114b --- /dev/null +++ b/.gitignore @@ -0,0 +1,36 @@ +# Git 会忽略的文件 + +.DS_Store +node_modules +dist +dist-ssr +dist.zip +.eslintcache + +# Local env files +*.local + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +!.vscode/settings.json +!.vscode/*.code-snippets +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# Use the PNPM +package-lock.json +yarn.lock diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..36af219 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npx lint-staged diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..da691e7 --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +# 通过该配置兜底解决组件没有类型提示的问题 +shamefully-hoist = true diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..6f99eb7 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,9 @@ +# Prettier 会忽略的文件 + +.DS_Store +node_modules +dist +dist-ssr +dist.zip +*.local +.npmrc diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..58910aa --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,12 @@ +{ + "recommendations": [ + "editorconfig.editorconfig", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "vue.vscode-typescript-vue-plugin", + "vue.volar", + "antfu.unocss", + "zixuanchen.vitest-explorer", + "wiensss.region-highlighter" + ] +} diff --git a/.vscode/hook.code-snippets b/.vscode/hook.code-snippets new file mode 100644 index 0000000..158d9ce --- /dev/null +++ b/.vscode/hook.code-snippets @@ -0,0 +1,16 @@ +{ + "Vue3 Hook 代码结构一键生成": { + "prefix": "Vue3 Hook", + "body": [ + "import { ref } from \"vue\"\n", + "const refName1 = ref(\"这是一个响应式变量\")\n", + "export function useHookName() {", + "\tconst refName2 = ref(\"这是一个响应式变量\")\n", + "\tconst fnName = () => {}\n", + "\treturn { refName1, refName2, fnName }", + "}", + "$1" + ], + "description": "Vue3 Hook" + } +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6b7fb6e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,30 @@ +{ + "editor.tabSize": 2, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + }, + "[vue]": { + "editor.defaultFormatter": "Vue.volar" + }, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[json]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[jsonc]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[html]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[css]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[scss]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + } +} diff --git a/.vscode/vue.code-snippets b/.vscode/vue.code-snippets new file mode 100644 index 0000000..e0a2e4b --- /dev/null +++ b/.vscode/vue.code-snippets @@ -0,0 +1,14 @@ +{ + "Vue3 SFC 代码结构一键生成": { + "prefix": "Vue3 SFC", + "body": [ + "\n", + "\n", + "", + "$1" + ], + "description": "Vue3 SFC" + } +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..831d018 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022-present pany + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..75a58dc --- /dev/null +++ b/README.md @@ -0,0 +1,163 @@ +
+ V3 Admin Vite Logo +

V3 Admin Vite

+ English | 中文 +
+ +## ⚡ Introduction + +V3 Admin Vite is a free and open source middle and background management system basic solution, based on mainstream framework such as Vue3, TypeScript, Element Plus, Pinia and Vite + +- Vue Cli 5.x: [v3-admin](https://github.com/un-pany/v3-admin) +- Electron desktop: [v3-electron-vite](https://github.com/un-pany/v3-electron-vite) + +China repository: [Gitee](https://gitee.com/un-pany/v3-admin-vite) + +## 📚 Document + +- Chinese documentation: [link](https://juejin.cn/post/7089377403717287972) +- Chinese getting started tutorial: [link](https://juejin.cn/column/7207659644487139387) + +## 📺 Online preview + +| Location | account | Link | +| ------------ | ------------------- | ----------------------------------------------- | +| github-pages | `admin` or `editor` | [link](https://un-pany.github.io/v3-admin-vite) | + +## ❤️ Generate electricity with love + +- **Completely free**:But hopefully you order a star !!! +- **Very concise**:No complicated encapsulation, no complicated type gymnastics, out of the box +- **Detailed annotations**:Each configuration item is written with as detailed comments as possible +- **Latest dependencies**: Regularly update all third-party dependencies to the latest version +- **Very specification**: The code style is unified, the naming style is unified, and the comment style is unified + +## Feature + +- **Vue3**:The latest Vue3 composition API using Vue3 + script setup +- **Element Plus**:Vue3 version of Element UI +- **Pinia**: An alternative to Vuex in Vue3 +- **Vite**:Really fast +- **Vue Router**:router +- **TypeScript**:JavaScript With Syntax For Types +- **PNPM**:Faster, disk space saving package management tool +- **Scss**:Consistent with Element Plus +- **CSS variable**:Mainly controls the layout and color of the item +- **ESlint**:Code verification +- **Prettier**: Code formatting +- **Axios**: Promise based HTTP client (encapsulated) +- **UnoCSS**: Real-time atomized CSS engine with high performance and flexibility +- **Mobile Compatible**: The layout is compatible with mobile page resolution + +## Functions + +- **User management**: log in, log out of the demo +- **Authority management**: Built-in page permissions (dynamic routing), instruction permissions, permission functions +- **Multiple Environments**: Development, Staging, Production +- **Multiple themes**: Normal, Dark, Dark Blue, theme modes +- **Multiple layouts**:Built-in left, top, left-top three layout modes +- **Error page**: 403, 404 +- **Dashboard**: Display different Dashboard pages according to different users +- **Other functions**:SVG, Dynamic Sidebar, Dynamic Breadcrumb Navigation, Tabbed Navigation, Screenfull, Adaptive Shrink Sidebar, HooK (Composables) + +## 🚀 Development + +```bash +# configure +1. installation of the recommended plugins in the .vscode directory +2. node version 18.x or 20+ +3. pnpm version 8.x or latest + +# clone +git clone https://github.com/un-pany/v3-admin-vite.git + +# enter the project directory +cd v3-admin-vite + +# install dependencies +pnpm i + +# start the service +pnpm dev +``` + +## ✔️ Preview + +```bash +# stage environment +pnpm preview:stage + +# prod environment +pnpm preview:prod +``` + +## 📦️ Multi-environment packaging + +```bash +# build the stage environment +pnpm build:stage + +# build the prod environment +pnpm build:prod +``` + +## 🔧 Code inspection + +```bash +# code formatting +pnpm lint + +# unit test +pnpm test +``` + +## Git commit specification reference + +- `feat` add new functions +- `fix` Fix issues/bugs +- `perf` Optimize performance +- `style` Change the code style without affecting the running result +- `refactor` Re-factor code +- `revert` Undo changes +- `test` Test related, does not involve changes to business code +- `docs` Documentation and Annotation +- `chore` Updating dependencies/modifying scaffolding configuration, etc. +- `workflow` Work flow Improvements +- `ci` CICD +- `types` Type definition +- `wip` In development + +## Project preview + +![preview1.png](./src/assets/docs/preview1.png) +![preview2.png](./src/assets/docs/preview2.png) +![preview3.png](./src/assets/docs/preview3.png) + +## 💕 Contributors + +Thanks to all the contributors! + + + + + +## 💕 Thanks star + +Small projects are not easy to get a star, if you like this project, welcome to support a star! This is the only motivation for the author to maintain it on an ongoing basis (whisper: it's free after all) + +## ☕ Donate + +[See how to donate](https://github.com/un-pany/v3-admin-vite/issues/69) + +## Group + +QQ group:1014374415 (left) && add me on WeChat,Invite you to join WeChat group (right) + +![qq.png](./src/assets/docs/qq.png) +![wechat.png](./src/assets/docs/wechat.png) + +## 📄 License + +[MIT](./LICENSE) + +Copyright (c) 2022-present [pany](https://github.com/pany-ang) diff --git a/README.zh-CN.md b/README.zh-CN.md new file mode 100644 index 0000000..f37d60b --- /dev/null +++ b/README.zh-CN.md @@ -0,0 +1,163 @@ +
+ V3 Admin Vite Logo +

V3 Admin Vite

+ English | 中文 +
+ +## ⚡ 简介 + +V3 Admin Vite 是一个免费开源的中后台管理系统基础解决方案,基于 Vue3、TypeScript、Element Plus、Pinia 和 Vite 等主流技术 + +- Vue Cli 5.x 版: [v3-admin](https://github.com/un-pany/v3-admin) +- Electron 桌面版: [v3-electron-vite](https://github.com/un-pany/v3-electron-vite) + +国内仓库:[Gitee](https://gitee.com/un-pany/v3-admin-vite) + +## 📚 文档 + +- 中文文档:[链接](https://juejin.cn/post/7089377403717287972) +- 手摸手教程:[链接](https://juejin.cn/column/7207659644487139387) + +## 📺 在线预览 + +| 位置 | 账号 | 链接 | +| ------------ | --------------- | ----------------------------------------------- | +| github-pages | admin 或 editor | [链接](https://un-pany.github.io/v3-admin-vite) | + +## ❤️ 用爱发电 + +- **完全免费**:但希望你点一个 star !!! +- **非常简洁**:没有复杂的封装,没有复杂的类型体操,开箱即用 +- **详细的注释**:各个配置项都写有尽可能详细的注释 +- **最新的依赖**: 定期更新所有三方依赖至最新版 +- **有一点规整**: 代码风格统一,命名风格统一,注释风格统一 + +## 特性 + +- **Vue3**:采用 Vue3 + script setup 最新的 Vue3 组合式 API +- **Element Plus**:Element UI 的 Vue3 版本 +- **Pinia**: 传说中的 Vuex5 +- **Vite**:真的很快 +- **Vue Router**:路由路由 +- **TypeScript**:JavaScript 语言的超集 +- **PNPM**:更快速的,节省磁盘空间的包管理工具 +- **Scss**:和 Element Plus 保持一致 +- **CSS 变量**:主要控制项目的布局和颜色 +- **ESlint**:代码校验 +- **Prettier**:代码格式化 +- **Axios**:发送网络请求(已封装好) +- **UnoCSS**:具有高性能且极具灵活性的即时原子化 CSS 引擎 +- **兼容移动端**: 布局兼容移动端页面分辨率 + +## 功能 + +- **用户管理**:登录、登出演示 +- **权限管理**:内置页面权限(动态路由)、指令权限、权限函数、路由守卫 +- **多环境**:开发环境(development)、预发布环境(staging)、正式环境(production) +- **多主题**:内置普通、黑暗、深蓝三种主题模式 +- **多布局**:内置左侧、顶部、混合三种布局模式 +- **错误页面**: 403、404 +- **Dashboard**:根据不同用户显示不同的 Dashboard 页面 +- **其他内置功能**:SVG、动态侧边栏、动态面包屑、标签页快捷导航、Screenfull 全屏、自适应收缩侧边栏、Hook(Composables) + +## 🚀 开发 + +```bash +# 配置 +1. 一键安装 .vscode 目录中推荐的插件 +2. node 版本 18.x 或 20+ +3. pnpm 版本 8.x 或最新版 + +# 克隆项目 +git clone https://github.com/un-pany/v3-admin-vite.git + +# 进入项目目录 +cd v3-admin-vite + +# 安装依赖 +pnpm i + +# 启动服务 +pnpm dev +``` + +## ✔️ 预览 + +```bash +# 预览预发布环境 +pnpm preview:stage + +# 预览正式环境 +pnpm preview:prod +``` + +## 📦️ 多环境打包 + +```bash +# 构建预发布环境 +pnpm build:stage + +# 构建正式环境 +pnpm build:prod +``` + +## 🔧 代码检查 + +```bash +# 代码格式化 +pnpm lint + +# 单元测试 +pnpm test +``` + +## Git 提交规范参考 + +- `feat` 增加新的业务功能 +- `fix` 修复业务问题/BUG +- `perf` 优化性能 +- `style` 更改代码风格, 不影响运行结果 +- `refactor` 重构代码 +- `revert` 撤销更改 +- `test` 测试相关, 不涉及业务代码的更改 +- `docs` 文档和注释相关 +- `chore` 更新依赖/修改脚手架配置等琐事 +- `workflow` 工作流改进 +- `ci` 持续集成相关 +- `types` 类型定义文件更改 +- `wip` 开发中 + +## 项目预览图 + +![preview1.png](./src/assets/docs/preview1.png) +![preview2.png](./src/assets/docs/preview2.png) +![preview3.png](./src/assets/docs/preview3.png) + +## 💕 贡献者 + +感谢所有的贡献者! + + + + + +## 💕 感谢 Star + +小项目获取 star 不易,如果你喜欢这个项目的话,欢迎支持一个 star!这是作者持续维护的唯一动力(小声:毕竟是免费的) + +## ☕ Donate + +[查看捐赠方式](https://github.com/un-pany/v3-admin-vite/issues/69) + +## 可有可无的群 + +QQ 群:1014374415(左)&& 加我微信,拉你进微信群(右) + +![qq.png](./src/assets/docs/qq.png) +![wechat.png](./src/assets/docs/wechat.png) + +## 📄 License + +[MIT](./LICENSE) + +Copyright (c) 2022-present [pany](https://github.com/pany-ang) diff --git a/index.html b/index.html new file mode 100644 index 0000000..a9f0259 --- /dev/null +++ b/index.html @@ -0,0 +1,16 @@ + + + + + + + + %VITE_APP_TITLE% + + +
+
+
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..49374ae --- /dev/null +++ b/package.json @@ -0,0 +1,105 @@ +{ + "name": "v3-admin-vite", + "version": "4.3.0", + "description": "一个免费开源的中后台管理系统基础解决方案,基于 Vue3、TypeScript、Element Plus、Pinia 和 Vite 等主流技术", + "author": { + "name": "pany", + "email": "939630029@qq.com", + "url": "https://github.com/pany-ang" + }, + "repository": { + "type": "git", + "url": "https://github.com/un-pany/v3-admin-vite.git" + }, + "type": "module", + "scripts": { + "dev": "vite", + "build:stage": "vue-tsc --noEmit && vite build --mode staging", + "build:prod": "vue-tsc --noEmit && vite build", + "preview:stage": "pnpm build:stage && vite preview", + "preview:prod": "pnpm build:prod && vite preview", + "lint:eslint": "eslint --cache --max-warnings 0 \"{src,tests,types}/**/*.{vue,js,jsx,ts,tsx}\" --fix", + "lint:prettier": "prettier --write \"{src,tests,types}/**/*.{vue,js,jsx,ts,tsx,json,css,less,scss,html,md}\"", + "lint": "pnpm lint:eslint && pnpm lint:prettier", + "prepare": "husky install", + "test": "vitest" + }, + "dependencies": { + "@ant-design/icons-vue": "^7.0.1", + "@element-plus/icons-vue": "2.3.1", + "ant-design-vue": "4.x", + "axios": "1.6.5", + "dayjs": "1.11.10", + "element-plus": "2.5.2", + "js-cookie": "3.0.5", + "lodash-es": "4.17.21", + "mitt": "3.0.1", + "normalize.css": "8.0.1", + "nprogress": "0.2.0", + "path-browserify": "1.0.1", + "path-to-regexp": "6.2.1", + "pinia": "2.1.7", + "screenfull": "6.0.2", + "vue": "3.4.15", + "vue-router": "4.2.5", + "vxe-table": "4.4.1", + "vxe-table-plugin-element": "3.0.7", + "xe-utils": "3.5.11" + }, + "devDependencies": { + "@types/js-cookie": "3.0.6", + "@types/lodash-es": "4.17.12", + "@types/node": "20.11.5", + "@types/nprogress": "0.2.3", + "@types/path-browserify": "1.0.2", + "@typescript-eslint/eslint-plugin": "6.19.0", + "@typescript-eslint/parser": "6.19.0", + "@vitejs/plugin-vue": "5.0.3", + "@vitejs/plugin-vue-jsx": "3.1.0", + "@vue/eslint-config-prettier": "9.0.0", + "@vue/eslint-config-typescript": "12.0.0", + "@vue/test-utils": "2.4.3", + "eslint": "8.56.0", + "eslint-plugin-prettier": "5.1.3", + "eslint-plugin-vue": "9.20.1", + "husky": "8.0.3", + "jsdom": "23.2.0", + "lint-staged": "15.2.0", + "prettier": "3.2.4", + "sass": "1.70.0", + "typescript": "5.3.3", + "unocss": "0.58.3", + "vite": "5.0.11", + "vite-plugin-svg-icons": "2.0.1", + "vite-svg-loader": "5.1.0", + "vitest": "1.2.1", + "vue-eslint-parser": "9.4.0", + "vue-tsc": "1.8.27" + }, + "lint-staged": { + "*.{vue,js,jsx,ts,tsx}": [ + "eslint --fix", + "prettier --write" + ], + "*.{css,less,scss,html,md}": [ + "prettier --write" + ], + "package.json": [ + "prettier --write" + ] + }, + "keywords": [ + "vue", + "vue3", + "admin", + "vue-admin", + "vue3-admin", + "vite", + "vite-admin", + "element-plus", + "element-plus-admin", + "ts", + "typescript" + ], + "license": "MIT" +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..d394302 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,5527 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@ant-design/icons-vue': + specifier: ^7.0.1 + version: 7.0.1(vue@3.4.15) + '@element-plus/icons-vue': + specifier: 2.3.1 + version: 2.3.1(vue@3.4.15) + ant-design-vue: + specifier: 4.x + version: 4.1.2(vue@3.4.15) + axios: + specifier: 1.6.5 + version: 1.6.5 + dayjs: + specifier: 1.11.10 + version: 1.11.10 + element-plus: + specifier: 2.5.2 + version: 2.5.2(vue@3.4.15) + js-cookie: + specifier: 3.0.5 + version: 3.0.5 + lodash-es: + specifier: 4.17.21 + version: 4.17.21 + mitt: + specifier: 3.0.1 + version: 3.0.1 + normalize.css: + specifier: 8.0.1 + version: 8.0.1 + nprogress: + specifier: 0.2.0 + version: 0.2.0 + path-browserify: + specifier: 1.0.1 + version: 1.0.1 + path-to-regexp: + specifier: 6.2.1 + version: 6.2.1 + pinia: + specifier: 2.1.7 + version: 2.1.7(typescript@5.3.3)(vue@3.4.15) + screenfull: + specifier: 6.0.2 + version: 6.0.2 + vue: + specifier: 3.4.15 + version: 3.4.15(typescript@5.3.3) + vue-router: + specifier: 4.2.5 + version: 4.2.5(vue@3.4.15) + vxe-table: + specifier: 4.4.1 + version: 4.4.1(vue@3.4.15)(xe-utils@3.5.11) + vxe-table-plugin-element: + specifier: 3.0.7 + version: 3.0.7(vxe-table@4.4.1) + xe-utils: + specifier: 3.5.11 + version: 3.5.11 + +devDependencies: + '@types/js-cookie': + specifier: 3.0.6 + version: 3.0.6 + '@types/lodash-es': + specifier: 4.17.12 + version: 4.17.12 + '@types/node': + specifier: 20.11.5 + version: 20.11.5 + '@types/nprogress': + specifier: 0.2.3 + version: 0.2.3 + '@types/path-browserify': + specifier: 1.0.2 + version: 1.0.2 + '@typescript-eslint/eslint-plugin': + specifier: 6.19.0 + version: 6.19.0(@typescript-eslint/parser@6.19.0)(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/parser': + specifier: 6.19.0 + version: 6.19.0(eslint@8.56.0)(typescript@5.3.3) + '@vitejs/plugin-vue': + specifier: 5.0.3 + version: 5.0.3(vite@5.0.11)(vue@3.4.15) + '@vitejs/plugin-vue-jsx': + specifier: 3.1.0 + version: 3.1.0(vite@5.0.11)(vue@3.4.15) + '@vue/eslint-config-prettier': + specifier: 9.0.0 + version: 9.0.0(eslint@8.56.0)(prettier@3.2.4) + '@vue/eslint-config-typescript': + specifier: 12.0.0 + version: 12.0.0(eslint-plugin-vue@9.20.1)(eslint@8.56.0)(typescript@5.3.3) + '@vue/test-utils': + specifier: 2.4.3 + version: 2.4.3(vue@3.4.15) + eslint: + specifier: 8.56.0 + version: 8.56.0 + eslint-plugin-prettier: + specifier: 5.1.3 + version: 5.1.3(eslint-config-prettier@9.1.0)(eslint@8.56.0)(prettier@3.2.4) + eslint-plugin-vue: + specifier: 9.20.1 + version: 9.20.1(eslint@8.56.0) + husky: + specifier: 8.0.3 + version: 8.0.3 + jsdom: + specifier: 23.2.0 + version: 23.2.0 + lint-staged: + specifier: 15.2.0 + version: 15.2.0 + prettier: + specifier: 3.2.4 + version: 3.2.4 + sass: + specifier: 1.70.0 + version: 1.70.0 + typescript: + specifier: 5.3.3 + version: 5.3.3 + unocss: + specifier: 0.58.3 + version: 0.58.3(postcss@8.4.33)(vite@5.0.11) + vite: + specifier: 5.0.11 + version: 5.0.11(@types/node@20.11.5)(sass@1.70.0) + vite-plugin-svg-icons: + specifier: 2.0.1 + version: 2.0.1(vite@5.0.11) + vite-svg-loader: + specifier: 5.1.0 + version: 5.1.0(vue@3.4.15) + vitest: + specifier: 1.2.1 + version: 1.2.1(@types/node@20.11.5)(jsdom@23.2.0)(sass@1.70.0) + vue-eslint-parser: + specifier: 9.4.0 + version: 9.4.0(eslint@8.56.0) + vue-tsc: + specifier: 1.8.27 + version: 1.8.27(typescript@5.3.3) + +packages: + + /@aashutoshrathi/word-wrap@1.2.6: + resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} + engines: {node: '>=0.10.0'} + dev: true + + /@ampproject/remapping@2.2.1: + resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.21 + dev: true + + /@ant-design/colors@6.0.0: + resolution: {integrity: sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==} + dependencies: + '@ctrl/tinycolor': 3.6.1 + dev: false + + /@ant-design/icons-svg@4.4.2: + resolution: {integrity: sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==} + dev: false + + /@ant-design/icons-vue@7.0.1(vue@3.4.15): + resolution: {integrity: sha512-eCqY2unfZK6Fe02AwFlDHLfoyEFreP6rBwAZMIJ1LugmfMiVgwWDYlp1YsRugaPtICYOabV1iWxXdP12u9U43Q==} + peerDependencies: + vue: '>=3.0.3' + dependencies: + '@ant-design/colors': 6.0.0 + '@ant-design/icons-svg': 4.4.2 + vue: 3.4.15(typescript@5.3.3) + dev: false + + /@antfu/install-pkg@0.1.1: + resolution: {integrity: sha512-LyB/8+bSfa0DFGC06zpCEfs89/XoWZwws5ygEa5D+Xsm3OfI+aXQ86VgVG7Acyef+rSZ5HE7J8rrxzrQeM3PjQ==} + dependencies: + execa: 5.1.1 + find-up: 5.0.0 + dev: true + + /@antfu/utils@0.7.7: + resolution: {integrity: sha512-gFPqTG7otEJ8uP6wrhDv6mqwGWYZKNvAcCq6u9hOj0c+IKCEsY4L1oC9trPq2SaWIzAfHvqfBDxF591JkMf+kg==} + dev: true + + /@asamuzakjp/dom-selector@2.0.2: + resolution: {integrity: sha512-x1KXOatwofR6ZAYzXRBL5wrdV0vwNxlTCK9NCuLqAzQYARqGcvFwiJA6A1ERuh+dgeA4Dxm3JBYictIes+SqUQ==} + dependencies: + bidi-js: 1.0.3 + css-tree: 2.3.1 + is-potential-custom-element-name: 1.0.1 + dev: true + + /@babel/code-frame@7.23.5: + resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.23.4 + chalk: 2.4.2 + dev: true + + /@babel/compat-data@7.23.5: + resolution: {integrity: sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/core@7.23.7: + resolution: {integrity: sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.23.5 + '@babel/generator': 7.23.6 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.7) + '@babel/helpers': 7.23.8 + '@babel/parser': 7.23.6 + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.7 + '@babel/types': 7.23.6 + convert-source-map: 2.0.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/generator@7.23.6: + resolution: {integrity: sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.21 + jsesc: 2.5.2 + dev: true + + /@babel/helper-annotate-as-pure@7.22.5: + resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-compilation-targets@7.23.6: + resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/compat-data': 7.23.5 + '@babel/helper-validator-option': 7.23.5 + browserslist: 4.22.2 + lru-cache: 5.1.1 + semver: 6.3.1 + dev: true + + /@babel/helper-create-class-features-plugin@7.23.7(@babel/core@7.23.7): + resolution: {integrity: sha512-xCoqR/8+BoNnXOY7RVSgv6X+o7pmT5q1d+gGcRlXYkI+9B31glE4jeejhKVpA04O1AtzOt7OSQ6VYKP5FcRl9g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-member-expression-to-functions': 7.23.0 + '@babel/helper-optimise-call-expression': 7.22.5 + '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.7) + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + semver: 6.3.1 + dev: true + + /@babel/helper-environment-visitor@7.22.20: + resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-function-name@7.23.0: + resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.15 + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-hoist-variables@7.22.5: + resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-member-expression-to-functions@7.23.0: + resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-module-imports@7.22.15: + resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-module-transforms@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.20 + dev: true + + /@babel/helper-optimise-call-expression@7.22.5: + resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-plugin-utils@7.22.5: + resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-replace-supers@7.22.20(@babel/core@7.23.7): + resolution: {integrity: sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-member-expression-to-functions': 7.23.0 + '@babel/helper-optimise-call-expression': 7.22.5 + dev: true + + /@babel/helper-simple-access@7.22.5: + resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-skip-transparent-expression-wrappers@7.22.5: + resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-split-export-declaration@7.22.6: + resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-string-parser@7.23.4: + resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==} + engines: {node: '>=6.9.0'} + + /@babel/helper-validator-identifier@7.22.20: + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + + /@babel/helper-validator-option@7.23.5: + resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helpers@7.23.8: + resolution: {integrity: sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.7 + '@babel/types': 7.23.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/highlight@7.23.4: + resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + + /@babel/parser@7.23.6: + resolution: {integrity: sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.23.6 + + /@babel/plugin-syntax-jsx@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-typescript@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-modules-commonjs@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.7) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-simple-access': 7.22.5 + dev: true + + /@babel/plugin-transform-typescript@7.23.6(@babel/core@7.23.7): + resolution: {integrity: sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.23.7) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.23.7) + dev: true + + /@babel/preset-typescript@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-validator-option': 7.23.5 + '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-modules-commonjs': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-typescript': 7.23.6(@babel/core@7.23.7) + dev: true + + /@babel/runtime@7.23.9: + resolution: {integrity: sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.1 + dev: false + + /@babel/template@7.22.15: + resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.23.5 + '@babel/parser': 7.23.6 + '@babel/types': 7.23.6 + dev: true + + /@babel/traverse@7.23.7: + resolution: {integrity: sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.23.5 + '@babel/generator': 7.23.6 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/parser': 7.23.6 + '@babel/types': 7.23.6 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/types@7.23.6: + resolution: {integrity: sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.23.4 + '@babel/helper-validator-identifier': 7.22.20 + to-fast-properties: 2.0.0 + + /@ctrl/tinycolor@3.6.1: + resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} + engines: {node: '>=10'} + dev: false + + /@element-plus/icons-vue@2.3.1(vue@3.4.15): + resolution: {integrity: sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==} + peerDependencies: + vue: ^3.2.0 + dependencies: + vue: 3.4.15(typescript@5.3.3) + dev: false + + /@emotion/hash@0.9.1: + resolution: {integrity: sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==} + dev: false + + /@emotion/unitless@0.8.1: + resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==} + dev: false + + /@esbuild/aix-ppc64@0.19.11: + resolution: {integrity: sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64@0.19.11: + resolution: {integrity: sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.19.11: + resolution: {integrity: sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.19.11: + resolution: {integrity: sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.19.11: + resolution: {integrity: sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.19.11: + resolution: {integrity: sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.19.11: + resolution: {integrity: sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.19.11: + resolution: {integrity: sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.19.11: + resolution: {integrity: sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.19.11: + resolution: {integrity: sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.19.11: + resolution: {integrity: sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.19.11: + resolution: {integrity: sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.19.11: + resolution: {integrity: sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.19.11: + resolution: {integrity: sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.19.11: + resolution: {integrity: sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.19.11: + resolution: {integrity: sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.19.11: + resolution: {integrity: sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.19.11: + resolution: {integrity: sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.19.11: + resolution: {integrity: sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.19.11: + resolution: {integrity: sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.19.11: + resolution: {integrity: sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.19.11: + resolution: {integrity: sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.19.11: + resolution: {integrity: sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@eslint-community/eslint-utils@4.4.0(eslint@8.56.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.56.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@eslint-community/regexpp@4.10.0: + resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + /@eslint/eslintrc@2.1.4: + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.6.1 + globals: 13.24.0 + ignore: 5.3.0 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@eslint/js@8.56.0: + resolution: {integrity: sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@floating-ui/core@1.5.3: + resolution: {integrity: sha512-O0WKDOo0yhJuugCx6trZQj5jVJ9yR0ystG2JaNAemYUWce+pmM6WUEFIibnWyEJKdrDxhm75NoSRME35FNaM/Q==} + dependencies: + '@floating-ui/utils': 0.2.1 + dev: false + + /@floating-ui/dom@1.5.4: + resolution: {integrity: sha512-jByEsHIY+eEdCjnTVu+E3ephzTOzkQ8hgUfGwos+bg7NlH33Zc5uO+QHz1mrQUOgIKKDD1RtS201P9NvAfq3XQ==} + dependencies: + '@floating-ui/core': 1.5.3 + '@floating-ui/utils': 0.2.1 + dev: false + + /@floating-ui/utils@0.2.1: + resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} + dev: false + + /@humanwhocodes/config-array@0.11.14: + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 2.0.2 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema@2.0.2: + resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} + dev: true + + /@iconify/types@2.0.0: + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + dev: true + + /@iconify/utils@2.1.15: + resolution: {integrity: sha512-8chdk3NhkYiqIVxPRBPN5wGnVYaTqc8XUagCNez84Ex7yK/oNrj1XINVn7zv+JljqZbF6r5B/bd1gRNlMSwYhg==} + dependencies: + '@antfu/install-pkg': 0.1.1 + '@antfu/utils': 0.7.7 + '@iconify/types': 2.0.0 + debug: 4.3.4 + kolorist: 1.8.0 + local-pkg: 0.4.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@isaacs/cliui@8.0.2: + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + dependencies: + string-width: 5.1.2 + string-width-cjs: /string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: /strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: /wrap-ansi@7.0.0 + dev: true + + /@jest/schemas@29.6.3: + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@sinclair/typebox': 0.27.8 + dev: true + + /@jridgewell/gen-mapping@0.3.3: + resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.21 + dev: true + + /@jridgewell/resolve-uri@3.1.1: + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/set-array@1.1.2: + resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + + /@jridgewell/trace-mapping@0.3.21: + resolution: {integrity: sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.16.0 + dev: true + + /@one-ini/wasm@0.1.1: + resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} + dev: true + + /@pkgjs/parseargs@0.11.0: + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + requiresBuild: true + dev: true + optional: true + + /@pkgr/core@0.1.1: + resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + dev: true + + /@polka/url@1.0.0-next.24: + resolution: {integrity: sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ==} + dev: true + + /@rollup/pluginutils@5.1.0: + resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@types/estree': 1.0.5 + estree-walker: 2.0.2 + picomatch: 2.3.1 + dev: true + + /@rollup/rollup-android-arm-eabi@4.9.5: + resolution: {integrity: sha512-idWaG8xeSRCfRq9KpRysDHJ/rEHBEXcHuJ82XY0yYFIWnLMjZv9vF/7DOq8djQ2n3Lk6+3qfSH8AqlmHlmi1MA==} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-android-arm64@4.9.5: + resolution: {integrity: sha512-f14d7uhAMtsCGjAYwZGv6TwuS3IFaM4ZnGMUn3aCBgkcHAYErhV1Ad97WzBvS2o0aaDv4mVz+syiN0ElMyfBPg==} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-arm64@4.9.5: + resolution: {integrity: sha512-ndoXeLx455FffL68OIUrVr89Xu1WLzAG4n65R8roDlCoYiQcGGg6MALvs2Ap9zs7AHg8mpHtMpwC8jBBjZrT/w==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-x64@4.9.5: + resolution: {integrity: sha512-UmElV1OY2m/1KEEqTlIjieKfVwRg0Zwg4PLgNf0s3glAHXBN99KLpw5A5lrSYCa1Kp63czTpVll2MAqbZYIHoA==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm-gnueabihf@4.9.5: + resolution: {integrity: sha512-Q0LcU61v92tQB6ae+udZvOyZ0wfpGojtAKrrpAaIqmJ7+psq4cMIhT/9lfV6UQIpeItnq/2QDROhNLo00lOD1g==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-gnu@4.9.5: + resolution: {integrity: sha512-dkRscpM+RrR2Ee3eOQmRWFjmV/payHEOrjyq1VZegRUa5OrZJ2MAxBNs05bZuY0YCtpqETDy1Ix4i/hRqX98cA==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-musl@4.9.5: + resolution: {integrity: sha512-QaKFVOzzST2xzY4MAmiDmURagWLFh+zZtttuEnuNn19AiZ0T3fhPyjPPGwLNdiDT82ZE91hnfJsUiDwF9DClIQ==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-riscv64-gnu@4.9.5: + resolution: {integrity: sha512-HeGqmRJuyVg6/X6MpE2ur7GbymBPS8Np0S/vQFHDmocfORT+Zt76qu+69NUoxXzGqVP1pzaY6QIi0FJWLC3OPA==} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-gnu@4.9.5: + resolution: {integrity: sha512-Dq1bqBdLaZ1Gb/l2e5/+o3B18+8TI9ANlA1SkejZqDgdU/jK/ThYaMPMJpVMMXy2uRHvGKbkz9vheVGdq3cJfA==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-musl@4.9.5: + resolution: {integrity: sha512-ezyFUOwldYpj7AbkwyW9AJ203peub81CaAIVvckdkyH8EvhEIoKzaMFJj0G4qYJ5sw3BpqhFrsCc30t54HV8vg==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-arm64-msvc@4.9.5: + resolution: {integrity: sha512-aHSsMnUw+0UETB0Hlv7B/ZHOGY5bQdwMKJSzGfDfvyhnpmVxLMGnQPGNE9wgqkLUs3+gbG1Qx02S2LLfJ5GaRQ==} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-ia32-msvc@4.9.5: + resolution: {integrity: sha512-AiqiLkb9KSf7Lj/o1U3SEP9Zn+5NuVKgFdRIZkvd4N0+bYrTOovVd0+LmYCPQGbocT4kvFyK+LXCDiXPBF3fyA==} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-x64-msvc@4.9.5: + resolution: {integrity: sha512-1q+mykKE3Vot1kaFJIDoUFv5TuW+QQVaf2FmTT9krg86pQrGStOSJJ0Zil7CFagyxDuouTepzt5Y5TVzyajOdQ==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@simonwep/pickr@1.8.2: + resolution: {integrity: sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==} + dependencies: + core-js: 3.35.1 + nanopop: 2.4.2 + dev: false + + /@sinclair/typebox@0.27.8: + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + dev: true + + /@sxzz/popperjs-es@2.11.7: + resolution: {integrity: sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==} + dev: false + + /@trysound/sax@0.2.0: + resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} + engines: {node: '>=10.13.0'} + dev: true + + /@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + dev: true + + /@types/js-cookie@3.0.6: + resolution: {integrity: sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==} + dev: true + + /@types/json-schema@7.0.15: + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + dev: true + + /@types/lodash-es@4.17.12: + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + dependencies: + '@types/lodash': 4.14.202 + + /@types/lodash@4.14.202: + resolution: {integrity: sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==} + + /@types/node@20.11.5: + resolution: {integrity: sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==} + dependencies: + undici-types: 5.26.5 + dev: true + + /@types/nprogress@0.2.3: + resolution: {integrity: sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==} + dev: true + + /@types/path-browserify@1.0.2: + resolution: {integrity: sha512-ZkC5IUqqIFPXx3ASTTybTzmQdwHwe2C0u3eL75ldQ6T9E9IWFJodn6hIfbZGab73DfyiHN4Xw15gNxUq2FbvBA==} + dev: true + + /@types/semver@7.5.6: + resolution: {integrity: sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==} + dev: true + + /@types/svgo@2.6.4: + resolution: {integrity: sha512-l4cmyPEckf8moNYHdJ+4wkHvFxjyW6ulm9l4YGaOxeyBWPhBOT0gvni1InpFPdzx1dKf/2s62qGITwxNWnPQng==} + dependencies: + '@types/node': 20.11.5 + dev: true + + /@types/web-bluetooth@0.0.16: + resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==} + dev: false + + /@typescript-eslint/eslint-plugin@6.19.0(@typescript-eslint/parser@6.19.0)(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-DUCUkQNklCQYnrBSSikjVChdc84/vMPDQSgJTHBZ64G9bA9w0Crc0rd2diujKbTdp6w2J47qkeHQLoi0rpLCdg==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.10.0 + '@typescript-eslint/parser': 6.19.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/scope-manager': 6.19.0 + '@typescript-eslint/type-utils': 6.19.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/utils': 6.19.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.19.0 + debug: 4.3.4 + eslint: 8.56.0 + graphemer: 1.4.0 + ignore: 5.3.0 + natural-compare: 1.4.0 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@6.19.0(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-1DyBLG5SH7PYCd00QlroiW60YJ4rWMuUGa/JBV0iZuqi4l4IK3twKPq5ZkEebmGqRjXWVgsUzfd3+nZveewgow==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 6.19.0 + '@typescript-eslint/types': 6.19.0 + '@typescript-eslint/typescript-estree': 6.19.0(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.19.0 + debug: 4.3.4 + eslint: 8.56.0 + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager@6.19.0: + resolution: {integrity: sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.19.0 + '@typescript-eslint/visitor-keys': 6.19.0 + dev: true + + /@typescript-eslint/type-utils@6.19.0(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-mcvS6WSWbjiSxKCwBcXtOM5pRkPQ6kcDds/juxcy/727IQr3xMEcwr/YLHW2A2+Fp5ql6khjbKBzOyjuPqGi/w==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 6.19.0(typescript@5.3.3) + '@typescript-eslint/utils': 6.19.0(eslint@8.56.0)(typescript@5.3.3) + debug: 4.3.4 + eslint: 8.56.0 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types@6.19.0: + resolution: {integrity: sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==} + engines: {node: ^16.0.0 || >=18.0.0} + dev: true + + /@typescript-eslint/typescript-estree@6.19.0(typescript@5.3.3): + resolution: {integrity: sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 6.19.0 + '@typescript-eslint/visitor-keys': 6.19.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.3 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@6.19.0(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.6 + '@typescript-eslint/scope-manager': 6.19.0 + '@typescript-eslint/types': 6.19.0 + '@typescript-eslint/typescript-estree': 6.19.0(typescript@5.3.3) + eslint: 8.56.0 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys@6.19.0: + resolution: {integrity: sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.19.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@ungap/structured-clone@1.2.0: + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + dev: true + + /@unocss/astro@0.58.3(vite@5.0.11): + resolution: {integrity: sha512-qJL+XkWYJhEIX4AmOtbfb2Zu4holTDpRscfvVci4T+2VWjyE3mgtsyNzi9ZChe/hdEPRa7g26gSpNQeMhjh/Kw==} + peerDependencies: + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 + peerDependenciesMeta: + vite: + optional: true + dependencies: + '@unocss/core': 0.58.3 + '@unocss/reset': 0.58.3 + '@unocss/vite': 0.58.3(vite@5.0.11) + vite: 5.0.11(@types/node@20.11.5)(sass@1.70.0) + transitivePeerDependencies: + - rollup + dev: true + + /@unocss/cli@0.58.3: + resolution: {integrity: sha512-veGdHhwm7GRvruXCMdqoFu3wVozr7ELEVWsFB6GpqWdGYIJ1i72M18l72UHDA2+TuDillZONnAQ5AvX9x/sYAw==} + engines: {node: '>=14'} + hasBin: true + dependencies: + '@ampproject/remapping': 2.2.1 + '@rollup/pluginutils': 5.1.0 + '@unocss/config': 0.58.3 + '@unocss/core': 0.58.3 + '@unocss/preset-uno': 0.58.3 + cac: 6.7.14 + chokidar: 3.5.3 + colorette: 2.0.20 + consola: 3.2.3 + fast-glob: 3.3.2 + magic-string: 0.30.5 + pathe: 1.1.2 + perfect-debounce: 1.0.0 + transitivePeerDependencies: + - rollup + dev: true + + /@unocss/config@0.58.3: + resolution: {integrity: sha512-8BQDoLzf/BkyfnkQsjnXI84oj+Spqkr7Bf2AbOGcX14vof0qqHSDvJXQV1e0u7jv2QETe2D1+PI4fnkJCumaRw==} + engines: {node: '>=14'} + dependencies: + '@unocss/core': 0.58.3 + unconfig: 0.3.11 + dev: true + + /@unocss/core@0.58.3: + resolution: {integrity: sha512-9hTxzsrSLh+07ql/lGhE+8ZbE9MTTeZeMx131cPf2jDJUxAZooLE5pBCoK0k77ZJGcribRrwPGkUScBNOK0cYQ==} + dev: true + + /@unocss/extractor-arbitrary-variants@0.58.3: + resolution: {integrity: sha512-QszC2atLcvzyoZFsjgtMBbILN4lrYI60iVRWdii+GGiKVtoIaKRWiA/3WERkvYGVPseVWOMflUpfxNeq+s9zUw==} + dependencies: + '@unocss/core': 0.58.3 + dev: true + + /@unocss/inspector@0.58.3: + resolution: {integrity: sha512-FqkoHiO23lGGcQ+qJbE1Kb8+kPJWc/LxBz3B4Ehml1vQryncNh4p+3sczVn5YVTfPDGBXBCkP05Q+PJRKabPXQ==} + dependencies: + '@unocss/core': 0.58.3 + '@unocss/rule-utils': 0.58.3 + gzip-size: 6.0.0 + sirv: 2.0.4 + dev: true + + /@unocss/postcss@0.58.3(postcss@8.4.33): + resolution: {integrity: sha512-y1WQNvLUidypCu/tr6oJfaV4pjd8Lsk1N27ASEVsvockOH3MekRYpHtJfTl2fMk+1Y98AHv7hPAVjM2NlvhDow==} + engines: {node: '>=14'} + peerDependencies: + postcss: ^8.4.21 + dependencies: + '@unocss/config': 0.58.3 + '@unocss/core': 0.58.3 + '@unocss/rule-utils': 0.58.3 + css-tree: 2.3.1 + fast-glob: 3.3.2 + magic-string: 0.30.5 + postcss: 8.4.33 + dev: true + + /@unocss/preset-attributify@0.58.3: + resolution: {integrity: sha512-iDXNfnSC0SI51UnMltHmMcPr2SYYkimo86i+SBQqc/WBGcCF7fFqFj8G2WsZfwHvU9SdAHF8tYIwNq06w1WSeg==} + dependencies: + '@unocss/core': 0.58.3 + dev: true + + /@unocss/preset-icons@0.58.3: + resolution: {integrity: sha512-SA4Eu4rOQ9+zUgIyK6RacS01ygm0PJWkqKlD8ccrBqEyZapqiU+vLL+v6X8YVjoZjR+5CVgcMD5Km7zEQgqXQw==} + dependencies: + '@iconify/utils': 2.1.15 + '@unocss/core': 0.58.3 + ofetch: 1.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@unocss/preset-mini@0.58.3: + resolution: {integrity: sha512-vPC97vZPY6J9uZ+KmK4x7atKFlZJPH4tR7+SmzTmguaGIHZJG8k1cjBCg+5M7P4MaxINRMukUQS8/mM/uWFqvQ==} + dependencies: + '@unocss/core': 0.58.3 + '@unocss/extractor-arbitrary-variants': 0.58.3 + '@unocss/rule-utils': 0.58.3 + dev: true + + /@unocss/preset-tagify@0.58.3: + resolution: {integrity: sha512-9CEh4p8M8zFuNFzmPIs1paExWRcwr0Gp6lSMffFnqaVToeRBgEH7VnRj6/R3ZPAmQ2rEemZ1+3eOQlsspEE6aw==} + dependencies: + '@unocss/core': 0.58.3 + dev: true + + /@unocss/preset-typography@0.58.3: + resolution: {integrity: sha512-hOQa2Sjkxo5v+jMwPXYv1MpHSrirf73FKPqwwHlvEUSCq9iweGDOU/MVOc5fI9qCg0SrfWhIvrZb4ASlgAuzWQ==} + dependencies: + '@unocss/core': 0.58.3 + '@unocss/preset-mini': 0.58.3 + dev: true + + /@unocss/preset-uno@0.58.3: + resolution: {integrity: sha512-E/g2BS4KXS9E/4OqyJSt0xSB6gbbk2VGjgIXrpcSXuDr2S2F29XLVlhJA5HJBADPlEfbo41z7Mk3LA3nQPWxQQ==} + dependencies: + '@unocss/core': 0.58.3 + '@unocss/preset-mini': 0.58.3 + '@unocss/preset-wind': 0.58.3 + '@unocss/rule-utils': 0.58.3 + dev: true + + /@unocss/preset-web-fonts@0.58.3: + resolution: {integrity: sha512-g+ru8gX74uZVSfKgdSGp46XQ+wMr66Hp3wtI01yyu9wqmJRAVWQmeehFYZ0hDnGgX20veYSbG+ybZfxIKeTy6w==} + dependencies: + '@unocss/core': 0.58.3 + ofetch: 1.3.3 + dev: true + + /@unocss/preset-wind@0.58.3: + resolution: {integrity: sha512-/YhvKDFGnTNvKxNaBv1dazHaqNmBM0Ulh0U9lhycGz11qsJTQSl/Y9ZP64fVC7fuo+Uiaj8AN/9gpmpVrCgt4A==} + dependencies: + '@unocss/core': 0.58.3 + '@unocss/preset-mini': 0.58.3 + '@unocss/rule-utils': 0.58.3 + dev: true + + /@unocss/reset@0.58.3: + resolution: {integrity: sha512-Q2KiRQlam2iYsTZgKdvnXEfUN4TA2oVpGIVD9Wa0ggs0XlYj5aOo0g0+4Tgqqn+YaviZQeJKnDs/JWE+ygHhZA==} + dev: true + + /@unocss/rule-utils@0.58.3: + resolution: {integrity: sha512-0Px9gIW+VOKetZuYET19uamIRpk7A9c8sCzQuGlNvCLXKEWamqXz5asLtnvPzw6SwCXEQDgWXE9i+aeoXaM0Jg==} + engines: {node: '>=14'} + dependencies: + '@unocss/core': 0.58.3 + magic-string: 0.30.5 + dev: true + + /@unocss/scope@0.58.3: + resolution: {integrity: sha512-Bkf6sk/0wry+fa5P8eLnzjC4pdrRlBY29g4F64qjsMBR0gk0stFRNzeoMOk412gmJXWjjlAQgNYiBZDHoPghZw==} + dev: true + + /@unocss/transformer-attributify-jsx-babel@0.58.3: + resolution: {integrity: sha512-ar+s1rUVHpTy5Yz31WP4DGF2IHxyD4sk/t9ayvR2nOZddAZipdLGSShG03GLkRv4h2/r0x+BIyJGdwAC0BgVZQ==} + dependencies: + '@babel/core': 7.23.7 + '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.7) + '@babel/preset-typescript': 7.23.3(@babel/core@7.23.7) + '@unocss/core': 0.58.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@unocss/transformer-attributify-jsx@0.58.3: + resolution: {integrity: sha512-H6wLJ5aAdHz8K/Z9/7OfiCBpOmKM7Gah2YtooT/Vfxu66bGehZO4QF6fcla6St53HifNvZ5odhlzqVEyHvQEaQ==} + dependencies: + '@unocss/core': 0.58.3 + dev: true + + /@unocss/transformer-compile-class@0.58.3: + resolution: {integrity: sha512-VmnByb3N8uGAEXjnfhra3DzKq8ZeVCL30n46GG5RTC03MK0rZmKVOmBOBIB99rmSV+D/WVrb12Gf4fHsoLca7g==} + dependencies: + '@unocss/core': 0.58.3 + dev: true + + /@unocss/transformer-directives@0.58.3: + resolution: {integrity: sha512-JMfeA8GJz106UqafqsCDp6BBEU7TozZHpLw414CKZjOW1CuMmaKEGrlr2UCjCYgM1vH7KEFKRMwTRUEV3NvywQ==} + dependencies: + '@unocss/core': 0.58.3 + '@unocss/rule-utils': 0.58.3 + css-tree: 2.3.1 + dev: true + + /@unocss/transformer-variant-group@0.58.3: + resolution: {integrity: sha512-/8CyzLwzpJC5cdiA/Wd5/Pg+HEIK+xxJJ3/VXoo93OPNCCbA9/h6DPwDh1ogKk15c6b5H75Ow6zKq1rYQAz2EA==} + dependencies: + '@unocss/core': 0.58.3 + dev: true + + /@unocss/vite@0.58.3(vite@5.0.11): + resolution: {integrity: sha512-gmB2//z7lDEK7Bw5HbHTSQ3abOM0iveAY/W3L3FFXpvduoxMQyuI5dDk0hOCtzhAWeJoynnVN4MBGVmXM4Y/Mg==} + peerDependencies: + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 + dependencies: + '@ampproject/remapping': 2.2.1 + '@rollup/pluginutils': 5.1.0 + '@unocss/config': 0.58.3 + '@unocss/core': 0.58.3 + '@unocss/inspector': 0.58.3 + '@unocss/scope': 0.58.3 + '@unocss/transformer-directives': 0.58.3 + chokidar: 3.5.3 + fast-glob: 3.3.2 + magic-string: 0.30.5 + vite: 5.0.11(@types/node@20.11.5)(sass@1.70.0) + transitivePeerDependencies: + - rollup + dev: true + + /@vitejs/plugin-vue-jsx@3.1.0(vite@5.0.11)(vue@3.4.15): + resolution: {integrity: sha512-w9M6F3LSEU5kszVb9An2/MmXNxocAnUb3WhRr8bHlimhDrXNt6n6D2nJQR3UXpGlZHh/EsgouOHCsM8V3Ln+WA==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.0.0 || ^5.0.0 + vue: ^3.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/plugin-transform-typescript': 7.23.6(@babel/core@7.23.7) + '@vue/babel-plugin-jsx': 1.1.6(@babel/core@7.23.7) + vite: 5.0.11(@types/node@20.11.5)(sass@1.70.0) + vue: 3.4.15(typescript@5.3.3) + transitivePeerDependencies: + - supports-color + dev: true + + /@vitejs/plugin-vue@5.0.3(vite@5.0.11)(vue@3.4.15): + resolution: {integrity: sha512-b8S5dVS40rgHdDrw+DQi/xOM9ed+kSRZzfm1T74bMmBDCd8XO87NKlFYInzCtwvtWwXZvo1QxE2OSspTATWrbA==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + vite: ^5.0.0 + vue: ^3.2.25 + dependencies: + vite: 5.0.11(@types/node@20.11.5)(sass@1.70.0) + vue: 3.4.15(typescript@5.3.3) + dev: true + + /@vitest/expect@1.2.1: + resolution: {integrity: sha512-/bqGXcHfyKgFWYwIgFr1QYDaR9e64pRKxgBNWNXPefPFRhgm+K3+a/dS0cUGEreWngets3dlr8w8SBRw2fCfFQ==} + dependencies: + '@vitest/spy': 1.2.1 + '@vitest/utils': 1.2.1 + chai: 4.4.1 + dev: true + + /@vitest/runner@1.2.1: + resolution: {integrity: sha512-zc2dP5LQpzNzbpaBt7OeYAvmIsRS1KpZQw4G3WM/yqSV1cQKNKwLGmnm79GyZZjMhQGlRcSFMImLjZaUQvNVZQ==} + dependencies: + '@vitest/utils': 1.2.1 + p-limit: 5.0.0 + pathe: 1.1.2 + dev: true + + /@vitest/snapshot@1.2.1: + resolution: {integrity: sha512-Tmp/IcYEemKaqAYCS08sh0vORLJkMr0NRV76Gl8sHGxXT5151cITJCET20063wk0Yr/1koQ6dnmP6eEqezmd/Q==} + dependencies: + magic-string: 0.30.5 + pathe: 1.1.2 + pretty-format: 29.7.0 + dev: true + + /@vitest/spy@1.2.1: + resolution: {integrity: sha512-vG3a/b7INKH7L49Lbp0IWrG6sw9j4waWAucwnksPB1r1FTJgV7nkBByd9ufzu6VWya/QTvQW4V9FShZbZIB2UQ==} + dependencies: + tinyspy: 2.2.0 + dev: true + + /@vitest/utils@1.2.1: + resolution: {integrity: sha512-bsH6WVZYe/J2v3+81M5LDU8kW76xWObKIURpPrOXm2pjBniBu2MERI/XP60GpS4PHU3jyK50LUutOwrx4CyHUg==} + dependencies: + diff-sequences: 29.6.3 + estree-walker: 3.0.3 + loupe: 2.3.7 + pretty-format: 29.7.0 + dev: true + + /@volar/language-core@1.11.1: + resolution: {integrity: sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==} + dependencies: + '@volar/source-map': 1.11.1 + dev: true + + /@volar/source-map@1.11.1: + resolution: {integrity: sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==} + dependencies: + muggle-string: 0.3.1 + dev: true + + /@volar/typescript@1.11.1: + resolution: {integrity: sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==} + dependencies: + '@volar/language-core': 1.11.1 + path-browserify: 1.0.1 + dev: true + + /@vue/babel-helper-vue-transform-on@1.1.6: + resolution: {integrity: sha512-XxM2tZHjYHTd9yiKHHt7fKCN0e2BK2z78UxU5rpjH3YCstEV/tcrW29CaOdrxIdeD0c/9mHHebvXWwDxlphjKA==} + dev: true + + /@vue/babel-plugin-jsx@1.1.6(@babel/core@7.23.7): + resolution: {integrity: sha512-s2pK8Wwg0LiR25lyCKWGJePt8aXF0DsXOmTHYJnlKNdT3yTKfdvkKmsWjaHBctFvwWmetedObrAoINc9BeYZlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + peerDependenciesMeta: + '@babel/core': + optional: true + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-module-imports': 7.22.15 + '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.7) + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.7 + '@babel/types': 7.23.6 + '@vue/babel-helper-vue-transform-on': 1.1.6 + camelcase: 6.3.0 + html-tags: 3.3.1 + svg-tags: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@vue/compiler-core@3.4.15: + resolution: {integrity: sha512-XcJQVOaxTKCnth1vCxEChteGuwG6wqnUHxAm1DO3gCz0+uXKaJNx8/digSz4dLALCy8n2lKq24jSUs8segoqIw==} + dependencies: + '@babel/parser': 7.23.6 + '@vue/shared': 3.4.15 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.0.2 + + /@vue/compiler-dom@3.4.15: + resolution: {integrity: sha512-wox0aasVV74zoXyblarOM3AZQz/Z+OunYcIHe1OsGclCHt8RsRm04DObjefaI82u6XDzv+qGWZ24tIsRAIi5MQ==} + dependencies: + '@vue/compiler-core': 3.4.15 + '@vue/shared': 3.4.15 + + /@vue/compiler-sfc@3.4.15: + resolution: {integrity: sha512-LCn5M6QpkpFsh3GQvs2mJUOAlBQcCco8D60Bcqmf3O3w5a+KWS5GvYbrrJBkgvL1BDnTp+e8q0lXCLgHhKguBA==} + dependencies: + '@babel/parser': 7.23.6 + '@vue/compiler-core': 3.4.15 + '@vue/compiler-dom': 3.4.15 + '@vue/compiler-ssr': 3.4.15 + '@vue/shared': 3.4.15 + estree-walker: 2.0.2 + magic-string: 0.30.5 + postcss: 8.4.33 + source-map-js: 1.0.2 + + /@vue/compiler-ssr@3.4.15: + resolution: {integrity: sha512-1jdeQyiGznr8gjFDadVmOJqZiLNSsMa5ZgqavkPZ8O2wjHv0tVuAEsw5hTdUoUW4232vpBbL/wJhzVW/JwY1Uw==} + dependencies: + '@vue/compiler-dom': 3.4.15 + '@vue/shared': 3.4.15 + + /@vue/devtools-api@6.5.1: + resolution: {integrity: sha512-+KpckaAQyfbvshdDW5xQylLni1asvNSGme1JFs8I1+/H5pHEhqUKMEQD/qn3Nx5+/nycBq11qAEi8lk+LXI2dA==} + dev: false + + /@vue/eslint-config-prettier@9.0.0(eslint@8.56.0)(prettier@3.2.4): + resolution: {integrity: sha512-z1ZIAAUS9pKzo/ANEfd2sO+v2IUalz7cM/cTLOZ7vRFOPk5/xuRKQteOu1DErFLAh/lYGXMVZ0IfYKlyInuDVg==} + peerDependencies: + eslint: '>= 8.0.0' + prettier: '>= 3.0.0' + dependencies: + eslint: 8.56.0 + eslint-config-prettier: 9.1.0(eslint@8.56.0) + eslint-plugin-prettier: 5.1.3(eslint-config-prettier@9.1.0)(eslint@8.56.0)(prettier@3.2.4) + prettier: 3.2.4 + transitivePeerDependencies: + - '@types/eslint' + dev: true + + /@vue/eslint-config-typescript@12.0.0(eslint-plugin-vue@9.20.1)(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-StxLFet2Qe97T8+7L8pGlhYBBr8Eg05LPuTDVopQV6il+SK6qqom59BA/rcFipUef2jD8P2X44Vd8tMFytfvlg==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 + eslint-plugin-vue: ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/eslint-plugin': 6.19.0(@typescript-eslint/parser@6.19.0)(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/parser': 6.19.0(eslint@8.56.0)(typescript@5.3.3) + eslint: 8.56.0 + eslint-plugin-vue: 9.20.1(eslint@8.56.0) + typescript: 5.3.3 + vue-eslint-parser: 9.4.0(eslint@8.56.0) + transitivePeerDependencies: + - supports-color + dev: true + + /@vue/language-core@1.8.27(typescript@5.3.3): + resolution: {integrity: sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@volar/language-core': 1.11.1 + '@volar/source-map': 1.11.1 + '@vue/compiler-dom': 3.4.15 + '@vue/shared': 3.4.15 + computeds: 0.0.1 + minimatch: 9.0.3 + muggle-string: 0.3.1 + path-browserify: 1.0.1 + typescript: 5.3.3 + vue-template-compiler: 2.7.16 + dev: true + + /@vue/reactivity@3.4.15: + resolution: {integrity: sha512-55yJh2bsff20K5O84MxSvXKPHHt17I2EomHznvFiJCAZpJTNW8IuLj1xZWMLELRhBK3kkFV/1ErZGHJfah7i7w==} + dependencies: + '@vue/shared': 3.4.15 + + /@vue/runtime-core@3.4.15: + resolution: {integrity: sha512-6E3by5m6v1AkW0McCeAyhHTw+3y17YCOKG0U0HDKDscV4Hs0kgNT5G+GCHak16jKgcCDHpI9xe5NKb8sdLCLdw==} + dependencies: + '@vue/reactivity': 3.4.15 + '@vue/shared': 3.4.15 + + /@vue/runtime-dom@3.4.15: + resolution: {integrity: sha512-EVW8D6vfFVq3V/yDKNPBFkZKGMFSvZrUQmx196o/v2tHKdwWdiZjYUBS+0Ez3+ohRyF8Njwy/6FH5gYJ75liUw==} + dependencies: + '@vue/runtime-core': 3.4.15 + '@vue/shared': 3.4.15 + csstype: 3.1.3 + + /@vue/server-renderer@3.4.15(vue@3.4.15): + resolution: {integrity: sha512-3HYzaidu9cHjrT+qGUuDhFYvF/j643bHC6uUN9BgM11DVy+pM6ATsG6uPBLnkwOgs7BpJABReLmpL3ZPAsUaqw==} + peerDependencies: + vue: 3.4.15 + dependencies: + '@vue/compiler-ssr': 3.4.15 + '@vue/shared': 3.4.15 + vue: 3.4.15(typescript@5.3.3) + + /@vue/shared@3.4.15: + resolution: {integrity: sha512-KzfPTxVaWfB+eGcGdbSf4CWdaXcGDqckoeXUh7SB3fZdEtzPCK2Vq9B/lRRL3yutax/LWITz+SwvgyOxz5V75g==} + + /@vue/test-utils@2.4.3(vue@3.4.15): + resolution: {integrity: sha512-F4K7mF+ad++VlTrxMJVRnenKSJmO6fkQt2wpRDiKDesQMkfpniGWsqEi/JevxGBo2qEkwwjvTUAoiGJLNx++CA==} + peerDependencies: + '@vue/server-renderer': ^3.0.1 + vue: ^3.0.1 + peerDependenciesMeta: + '@vue/server-renderer': + optional: true + dependencies: + js-beautify: 1.14.11 + vue: 3.4.15(typescript@5.3.3) + vue-component-type-helpers: 1.8.27 + dev: true + + /@vueuse/core@9.13.0(vue@3.4.15): + resolution: {integrity: sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==} + dependencies: + '@types/web-bluetooth': 0.0.16 + '@vueuse/metadata': 9.13.0 + '@vueuse/shared': 9.13.0(vue@3.4.15) + vue-demi: 0.14.6(vue@3.4.15) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: false + + /@vueuse/metadata@9.13.0: + resolution: {integrity: sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==} + dev: false + + /@vueuse/shared@9.13.0(vue@3.4.15): + resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==} + dependencies: + vue-demi: 0.14.6(vue@3.4.15) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: false + + /abbrev@2.0.0: + resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true + + /acorn-jsx@5.3.2(acorn@8.11.3): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.11.3 + dev: true + + /acorn-walk@8.3.2: + resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + engines: {node: '>=0.4.0'} + dev: true + + /acorn@8.11.3: + resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /agent-base@7.1.0: + resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} + engines: {node: '>= 14'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ansi-escapes@6.2.0: + resolution: {integrity: sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==} + engines: {node: '>=14.16'} + dependencies: + type-fest: 3.13.1 + dev: true + + /ansi-regex@2.1.1: + resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} + engines: {node: '>=0.10.0'} + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: true + + /ansi-styles@2.2.1: + resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} + engines: {node: '>=0.10.0'} + dev: true + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + dev: true + + /ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: true + + /ant-design-vue@4.1.2(vue@3.4.15): + resolution: {integrity: sha512-ynFkDJLlHgumeK6Hr1UZ7PvQNZ1uBcri/pmejBdS3kRqHeA5VRsxneYDwa8YxA+uYB5YfT2jpYsSHsiMiCjRGg==} + engines: {node: '>=12.22.0'} + peerDependencies: + vue: '>=3.2.0' + dependencies: + '@ant-design/colors': 6.0.0 + '@ant-design/icons-vue': 7.0.1(vue@3.4.15) + '@babel/runtime': 7.23.9 + '@ctrl/tinycolor': 3.6.1 + '@emotion/hash': 0.9.1 + '@emotion/unitless': 0.8.1 + '@simonwep/pickr': 1.8.2 + array-tree-filter: 2.1.0 + async-validator: 4.2.5 + csstype: 3.1.3 + dayjs: 1.11.10 + dom-align: 1.12.4 + dom-scroll-into-view: 2.0.1 + lodash: 4.17.21 + lodash-es: 4.17.21 + resize-observer-polyfill: 1.5.1 + scroll-into-view-if-needed: 2.2.31 + shallow-equal: 1.2.1 + stylis: 4.3.1 + throttle-debounce: 5.0.0 + vue: 3.4.15(typescript@5.3.3) + vue-types: 3.0.2(vue@3.4.15) + warning: 4.0.3 + dev: false + + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /arr-diff@4.0.0: + resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==} + engines: {node: '>=0.10.0'} + dev: true + + /arr-flatten@1.1.0: + resolution: {integrity: sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==} + engines: {node: '>=0.10.0'} + dev: true + + /arr-union@3.1.0: + resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==} + engines: {node: '>=0.10.0'} + dev: true + + /array-tree-filter@2.1.0: + resolution: {integrity: sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==} + dev: false + + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /array-unique@0.3.2: + resolution: {integrity: sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==} + engines: {node: '>=0.10.0'} + dev: true + + /assertion-error@1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + dev: true + + /assign-symbols@1.0.0: + resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} + engines: {node: '>=0.10.0'} + dev: true + + /async-validator@4.2.5: + resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} + dev: false + + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + /atob@2.1.2: + resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} + engines: {node: '>= 4.5.0'} + hasBin: true + dev: true + + /axios@1.6.5: + resolution: {integrity: sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==} + dependencies: + follow-redirects: 1.15.5 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + dev: false + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /base@0.11.2: + resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} + engines: {node: '>=0.10.0'} + dependencies: + cache-base: 1.0.1 + class-utils: 0.3.6 + component-emitter: 1.3.1 + define-property: 1.0.0 + isobject: 3.0.1 + mixin-deep: 1.3.2 + pascalcase: 0.1.1 + dev: true + + /bidi-js@1.0.3: + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + dependencies: + require-from-string: 2.0.2 + dev: true + + /big.js@5.2.2: + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + dev: true + + /binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: true + + /bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + dev: true + + /boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: true + + /braces@2.3.2: + resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} + engines: {node: '>=0.10.0'} + dependencies: + arr-flatten: 1.1.0 + array-unique: 0.3.2 + extend-shallow: 2.0.1 + fill-range: 4.0.0 + isobject: 3.0.1 + repeat-element: 1.1.4 + snapdragon: 0.8.2 + snapdragon-node: 2.1.1 + split-string: 3.1.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /browserslist@4.22.2: + resolution: {integrity: sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001579 + electron-to-chromium: 1.4.639 + node-releases: 2.0.14 + update-browserslist-db: 1.0.13(browserslist@4.22.2) + dev: true + + /cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + dev: true + + /cache-base@1.0.1: + resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} + engines: {node: '>=0.10.0'} + dependencies: + collection-visit: 1.0.0 + component-emitter: 1.3.1 + get-value: 2.0.6 + has-value: 1.0.0 + isobject: 3.0.1 + set-value: 2.0.1 + to-object-path: 0.3.0 + union-value: 1.0.1 + unset-value: 1.0.0 + dev: true + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + dev: true + + /caniuse-lite@1.0.30001579: + resolution: {integrity: sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==} + dev: true + + /chai@4.4.1: + resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} + engines: {node: '>=4'} + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.3 + deep-eql: 4.1.3 + get-func-name: 2.0.2 + loupe: 2.3.7 + pathval: 1.1.1 + type-detect: 4.0.8 + dev: true + + /chalk@1.1.3: + resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-styles: 2.2.1 + escape-string-regexp: 1.0.5 + has-ansi: 2.0.0 + strip-ansi: 3.0.1 + supports-color: 2.0.0 + dev: true + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: true + + /check-error@1.0.3: + resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + dependencies: + get-func-name: 2.0.2 + dev: true + + /chokidar@3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /class-utils@0.3.6: + resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==} + engines: {node: '>=0.10.0'} + dependencies: + arr-union: 3.1.0 + define-property: 0.2.5 + isobject: 3.0.1 + static-extend: 0.1.2 + dev: true + + /cli-cursor@4.0.0: + resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + restore-cursor: 4.0.0 + dev: true + + /cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} + dependencies: + slice-ansi: 5.0.0 + string-width: 7.0.0 + dev: true + + /clone@2.1.2: + resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} + engines: {node: '>=0.8'} + dev: true + + /collection-visit@1.0.0: + resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==} + engines: {node: '>=0.10.0'} + dependencies: + map-visit: 1.0.0 + object-visit: 1.0.1 + dev: true + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + dev: true + + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + + /commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + dev: true + + /commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + dev: true + + /commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + dev: true + + /component-emitter@1.3.1: + resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} + dev: true + + /compute-scroll-into-view@1.0.20: + resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==} + dev: false + + /computeds@0.0.1: + resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==} + dev: true + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /config-chain@1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + dependencies: + ini: 1.3.8 + proto-list: 1.2.4 + dev: true + + /consola@3.2.3: + resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} + engines: {node: ^14.18.0 || >=16.10.0} + dev: true + + /convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + dev: true + + /copy-descriptor@0.1.1: + resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==} + engines: {node: '>=0.10.0'} + dev: true + + /core-js@3.35.1: + resolution: {integrity: sha512-IgdsbxNyMskrTFxa9lWHyMwAJU5gXOPP+1yO+K59d50VLVAIDAbs7gIv705KzALModfK3ZrSZTPNpC0PQgIZuw==} + requiresBuild: true + dev: false + + /cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + dev: true + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /css-select@4.3.0: + resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 4.3.1 + domutils: 2.8.0 + nth-check: 2.1.1 + dev: true + + /css-select@5.1.0: + resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 5.0.3 + domutils: 3.1.0 + nth-check: 2.1.1 + dev: true + + /css-tree@1.1.3: + resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} + engines: {node: '>=8.0.0'} + dependencies: + mdn-data: 2.0.14 + source-map: 0.6.1 + dev: true + + /css-tree@2.2.1: + resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + dependencies: + mdn-data: 2.0.28 + source-map-js: 1.0.2 + dev: true + + /css-tree@2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + dependencies: + mdn-data: 2.0.30 + source-map-js: 1.0.2 + dev: true + + /css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + dev: true + + /cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /csso@4.2.0: + resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==} + engines: {node: '>=8.0.0'} + dependencies: + css-tree: 1.1.3 + dev: true + + /csso@5.0.5: + resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + dependencies: + css-tree: 2.2.1 + dev: true + + /cssstyle@4.0.1: + resolution: {integrity: sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==} + engines: {node: '>=18'} + dependencies: + rrweb-cssom: 0.6.0 + dev: true + + /csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + /data-urls@5.0.0: + resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} + engines: {node: '>=18'} + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 14.0.0 + dev: true + + /dayjs@1.11.10: + resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==} + dev: false + + /de-indent@1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + dev: true + + /debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: true + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /decimal.js@10.4.3: + resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + dev: true + + /decode-uri-component@0.2.2: + resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} + engines: {node: '>=0.10'} + dev: true + + /deep-eql@4.1.3: + resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} + engines: {node: '>=6'} + dependencies: + type-detect: 4.0.8 + dev: true + + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /define-property@0.2.5: + resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==} + engines: {node: '>=0.10.0'} + dependencies: + is-descriptor: 0.1.7 + dev: true + + /define-property@1.0.0: + resolution: {integrity: sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==} + engines: {node: '>=0.10.0'} + dependencies: + is-descriptor: 1.0.3 + dev: true + + /define-property@2.0.2: + resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-descriptor: 1.0.3 + isobject: 3.0.1 + dev: true + + /defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + dev: true + + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + /destr@2.0.2: + resolution: {integrity: sha512-65AlobnZMiCET00KaFFjUefxDX0khFA/E4myqZ7a6Sq1yZtR8+FVIvilVX66vF2uobSumxooYZChiRPCKNqhmg==} + dev: true + + /diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: true + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /dom-align@1.12.4: + resolution: {integrity: sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==} + dev: false + + /dom-scroll-into-view@2.0.1: + resolution: {integrity: sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==} + dev: false + + /dom-serializer@0.2.2: + resolution: {integrity: sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==} + dependencies: + domelementtype: 2.3.0 + entities: 2.2.0 + dev: true + + /dom-serializer@1.4.1: + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + entities: 2.2.0 + dev: true + + /dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + dev: true + + /domelementtype@1.3.1: + resolution: {integrity: sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==} + dev: true + + /domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + dev: true + + /domhandler@2.4.2: + resolution: {integrity: sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==} + dependencies: + domelementtype: 1.3.1 + dev: true + + /domhandler@4.3.1: + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} + dependencies: + domelementtype: 2.3.0 + dev: true + + /domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + dependencies: + domelementtype: 2.3.0 + dev: true + + /domutils@1.7.0: + resolution: {integrity: sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==} + dependencies: + dom-serializer: 0.2.2 + domelementtype: 1.3.1 + dev: true + + /domutils@2.8.0: + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 + dev: true + + /domutils@3.1.0: + resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + dev: true + + /duplexer@0.1.2: + resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + dev: true + + /eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: true + + /editorconfig@1.0.4: + resolution: {integrity: sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==} + engines: {node: '>=14'} + hasBin: true + dependencies: + '@one-ini/wasm': 0.1.1 + commander: 10.0.1 + minimatch: 9.0.1 + semver: 7.5.4 + dev: true + + /electron-to-chromium@1.4.639: + resolution: {integrity: sha512-CkKf3ZUVZchr+zDpAlNLEEy2NJJ9T64ULWaDgy3THXXlPVPkLu3VOs9Bac44nebVtdwl2geSj6AxTtGDOxoXhg==} + dev: true + + /element-plus@2.5.2(vue@3.4.15): + resolution: {integrity: sha512-0Xbihy5CvpdH+OZeRPnZlfkbZS8uyLvHJiALehvw6n7nvHGrujCmdiw8NXvYhkLpRtwue/N6oBfAvMJvQSPoNA==} + peerDependencies: + vue: ^3.2.0 + dependencies: + '@ctrl/tinycolor': 3.6.1 + '@element-plus/icons-vue': 2.3.1(vue@3.4.15) + '@floating-ui/dom': 1.5.4 + '@popperjs/core': /@sxzz/popperjs-es@2.11.7 + '@types/lodash': 4.14.202 + '@types/lodash-es': 4.17.12 + '@vueuse/core': 9.13.0(vue@3.4.15) + async-validator: 4.2.5 + dayjs: 1.11.10 + escape-html: 1.0.3 + lodash: 4.17.21 + lodash-es: 4.17.21 + lodash-unified: 1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21) + memoize-one: 6.0.0 + normalize-wheel-es: 1.2.0 + vue: 3.4.15(typescript@5.3.3) + transitivePeerDependencies: + - '@vue/composition-api' + dev: false + + /emoji-regex@10.3.0: + resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} + dev: true + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true + + /emojis-list@3.0.0: + resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} + engines: {node: '>= 4'} + dev: true + + /entities@1.1.2: + resolution: {integrity: sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==} + dev: true + + /entities@2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + dev: true + + /entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + /esbuild@0.19.11: + resolution: {integrity: sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.19.11 + '@esbuild/android-arm': 0.19.11 + '@esbuild/android-arm64': 0.19.11 + '@esbuild/android-x64': 0.19.11 + '@esbuild/darwin-arm64': 0.19.11 + '@esbuild/darwin-x64': 0.19.11 + '@esbuild/freebsd-arm64': 0.19.11 + '@esbuild/freebsd-x64': 0.19.11 + '@esbuild/linux-arm': 0.19.11 + '@esbuild/linux-arm64': 0.19.11 + '@esbuild/linux-ia32': 0.19.11 + '@esbuild/linux-loong64': 0.19.11 + '@esbuild/linux-mips64el': 0.19.11 + '@esbuild/linux-ppc64': 0.19.11 + '@esbuild/linux-riscv64': 0.19.11 + '@esbuild/linux-s390x': 0.19.11 + '@esbuild/linux-x64': 0.19.11 + '@esbuild/netbsd-x64': 0.19.11 + '@esbuild/openbsd-x64': 0.19.11 + '@esbuild/sunos-x64': 0.19.11 + '@esbuild/win32-arm64': 0.19.11 + '@esbuild/win32-ia32': 0.19.11 + '@esbuild/win32-x64': 0.19.11 + dev: true + + /escalade@3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + dev: true + + /escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + dev: false + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /eslint-config-prettier@9.1.0(eslint@8.56.0): + resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.56.0 + dev: true + + /eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0)(eslint@8.56.0)(prettier@3.2.4): + resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + '@types/eslint': '>=8.0.0' + eslint: '>=8.0.0' + eslint-config-prettier: '*' + prettier: '>=3.0.0' + peerDependenciesMeta: + '@types/eslint': + optional: true + eslint-config-prettier: + optional: true + dependencies: + eslint: 8.56.0 + eslint-config-prettier: 9.1.0(eslint@8.56.0) + prettier: 3.2.4 + prettier-linter-helpers: 1.0.0 + synckit: 0.8.8 + dev: true + + /eslint-plugin-vue@9.20.1(eslint@8.56.0): + resolution: {integrity: sha512-GyCs8K3lkEvoyC1VV97GJhP1SvqsKCiWGHnbn0gVUYiUhaH2+nB+Dv1uekv1THFMPbBfYxukrzQdltw950k+LQ==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) + eslint: 8.56.0 + natural-compare: 1.4.0 + nth-check: 2.1.1 + postcss-selector-parser: 6.0.15 + semver: 7.5.4 + vue-eslint-parser: 9.4.0(eslint@8.56.0) + xml-name-validator: 4.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint@8.56.0: + resolution: {integrity: sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) + '@eslint-community/regexpp': 4.10.0 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.56.0 + '@humanwhocodes/config-array': 0.11.14 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.24.0 + graphemer: 1.4.0 + ignore: 5.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.3 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.11.3 + acorn-jsx: 5.3.2(acorn@8.11.3) + eslint-visitor-keys: 3.4.3 + dev: true + + /esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + /estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + dependencies: + '@types/estree': 1.0.5 + dev: true + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + dev: true + + /eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + dev: true + + /execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + + /execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.2.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + dev: true + + /expand-brackets@2.1.4: + resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==} + engines: {node: '>=0.10.0'} + dependencies: + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + posix-character-classes: 0.1.1 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + dependencies: + is-extendable: 0.1.1 + dev: true + + /extend-shallow@3.0.2: + resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} + engines: {node: '>=0.10.0'} + dependencies: + assign-symbols: 1.0.0 + is-extendable: 1.0.1 + dev: true + + /extglob@2.0.4: + resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} + engines: {node: '>=0.10.0'} + dependencies: + array-unique: 0.3.2 + define-property: 1.0.0 + expand-brackets: 2.1.4 + extend-shallow: 2.0.1 + fragment-cache: 0.2.1 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + dev: true + + /fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fastq@1.16.0: + resolution: {integrity: sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==} + dependencies: + reusify: 1.0.4 + dev: true + + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.2.0 + dev: true + + /fill-range@4.0.0: + resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 2.0.1 + is-number: 3.0.0 + repeat-string: 1.6.1 + to-regex-range: 2.1.1 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.2.9 + keyv: 4.5.4 + rimraf: 3.0.2 + dev: true + + /flatted@3.2.9: + resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} + dev: true + + /follow-redirects@1.15.5: + resolution: {integrity: sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: false + + /for-in@1.0.2: + resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} + engines: {node: '>=0.10.0'} + dev: true + + /foreground-child@3.1.1: + resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} + engines: {node: '>=14'} + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + dev: true + + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + + /fragment-cache@0.2.1: + resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==} + engines: {node: '>=0.10.0'} + dependencies: + map-cache: 0.2.2 + dev: true + + /fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: true + + /gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: true + + /get-east-asian-width@1.2.0: + resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} + engines: {node: '>=18'} + dev: true + + /get-func-name@2.0.2: + resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + dev: true + + /get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: true + + /get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + dev: true + + /get-value@2.0.6: + resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} + engines: {node: '>=0.10.0'} + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob@10.3.10: + resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + dependencies: + foreground-child: 3.1.1 + jackspeak: 2.3.6 + minimatch: 9.0.3 + minipass: 7.0.4 + path-scurry: 1.10.1 + dev: true + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: true + + /globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.0 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + + /graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + dev: true + + /gzip-size@6.0.0: + resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} + engines: {node: '>=10'} + dependencies: + duplexer: 0.1.2 + dev: true + + /has-ansi@2.0.0: + resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-regex: 2.1.1 + dev: true + + /has-flag@1.0.0: + resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==} + engines: {node: '>=0.10.0'} + dev: true + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has-value@0.3.1: + resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} + engines: {node: '>=0.10.0'} + dependencies: + get-value: 2.0.6 + has-values: 0.1.4 + isobject: 2.1.0 + dev: true + + /has-value@1.0.0: + resolution: {integrity: sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==} + engines: {node: '>=0.10.0'} + dependencies: + get-value: 2.0.6 + has-values: 1.0.0 + isobject: 3.0.1 + dev: true + + /has-values@0.1.4: + resolution: {integrity: sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==} + engines: {node: '>=0.10.0'} + dev: true + + /has-values@1.0.0: + resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-number: 3.0.0 + kind-of: 4.0.0 + dev: true + + /hasown@2.0.0: + resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: true + + /he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + dev: true + + /html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} + dependencies: + whatwg-encoding: 3.1.1 + dev: true + + /html-tags@3.3.1: + resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} + engines: {node: '>=8'} + dev: true + + /htmlparser2@3.10.1: + resolution: {integrity: sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==} + dependencies: + domelementtype: 1.3.1 + domhandler: 2.4.2 + domutils: 1.7.0 + entities: 1.1.2 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: true + + /http-proxy-agent@7.0.0: + resolution: {integrity: sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /https-proxy-agent@7.0.2: + resolution: {integrity: sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + dev: true + + /human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + dev: true + + /husky@8.0.3: + resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: true + + /ignore@5.3.0: + resolution: {integrity: sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==} + engines: {node: '>= 4'} + dev: true + + /image-size@0.5.5: + resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} + engines: {node: '>=0.10.0'} + hasBin: true + dev: true + + /immutable@4.3.4: + resolution: {integrity: sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==} + dev: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: true + + /is-accessor-descriptor@1.0.1: + resolution: {integrity: sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==} + engines: {node: '>= 0.10'} + dependencies: + hasown: 2.0.0 + dev: true + + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: true + + /is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + dev: true + + /is-data-descriptor@1.0.1: + resolution: {integrity: sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==} + engines: {node: '>= 0.4'} + dependencies: + hasown: 2.0.0 + dev: true + + /is-descriptor@0.1.7: + resolution: {integrity: sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==} + engines: {node: '>= 0.4'} + dependencies: + is-accessor-descriptor: 1.0.1 + is-data-descriptor: 1.0.1 + dev: true + + /is-descriptor@1.0.3: + resolution: {integrity: sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==} + engines: {node: '>= 0.4'} + dependencies: + is-accessor-descriptor: 1.0.1 + is-data-descriptor: 1.0.1 + dev: true + + /is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + dev: true + + /is-extendable@1.0.1: + resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} + engines: {node: '>=0.10.0'} + dependencies: + is-plain-object: 2.0.4 + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + + /is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + dev: true + + /is-fullwidth-code-point@5.0.0: + resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + engines: {node: '>=18'} + dependencies: + get-east-asian-width: 1.2.0 + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-number@3.0.0: + resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + + /is-plain-obj@1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + dev: true + + /is-plain-object@2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: true + + /is-plain-object@3.0.1: + resolution: {integrity: sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==} + engines: {node: '>=0.10.0'} + dev: false + + /is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + dev: true + + /is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: true + + /is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + dev: true + + /isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /isobject@2.1.0: + resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} + engines: {node: '>=0.10.0'} + dependencies: + isarray: 1.0.0 + dev: true + + /isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + dev: true + + /jackspeak@2.3.6: + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} + engines: {node: '>=14'} + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + dev: true + + /jiti@1.21.0: + resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} + hasBin: true + dev: true + + /js-base64@2.6.4: + resolution: {integrity: sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==} + dev: true + + /js-beautify@1.14.11: + resolution: {integrity: sha512-rPogWqAfoYh1Ryqqh2agUpVfbxAhbjuN1SmU86dskQUKouRiggUTCO4+2ym9UPXllc2WAp0J+T5qxn7Um3lCdw==} + engines: {node: '>=14'} + hasBin: true + dependencies: + config-chain: 1.1.13 + editorconfig: 1.0.4 + glob: 10.3.10 + nopt: 7.2.0 + dev: true + + /js-cookie@3.0.5: + resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} + engines: {node: '>=14'} + dev: false + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /jsdom@23.2.0: + resolution: {integrity: sha512-L88oL7D/8ufIES+Zjz7v0aes+oBMh2Xnh3ygWvL0OaICOomKEPKuPnIfBJekiXr+BHbbMjrWn/xqrDQuxFTeyA==} + engines: {node: '>=18'} + peerDependencies: + canvas: ^2.11.2 + peerDependenciesMeta: + canvas: + optional: true + dependencies: + '@asamuzakjp/dom-selector': 2.0.2 + cssstyle: 4.0.1 + data-urls: 5.0.0 + decimal.js: 10.4.3 + form-data: 4.0.0 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.0 + https-proxy-agent: 7.0.2 + is-potential-custom-element-name: 1.0.1 + parse5: 7.1.2 + rrweb-cssom: 0.6.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 4.1.3 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.0.0 + ws: 8.16.0 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + dev: true + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /jsonc-parser@3.2.0: + resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + dev: true + + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + dependencies: + json-buffer: 3.0.1 + dev: true + + /kind-of@3.2.2: + resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-buffer: 1.1.6 + dev: true + + /kind-of@4.0.0: + resolution: {integrity: sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==} + engines: {node: '>=0.10.0'} + dependencies: + is-buffer: 1.1.6 + dev: true + + /kind-of@5.1.0: + resolution: {integrity: sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==} + engines: {node: '>=0.10.0'} + dev: true + + /kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: true + + /kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + dev: true + + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /lilconfig@3.0.0: + resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==} + engines: {node: '>=14'} + dev: true + + /lint-staged@15.2.0: + resolution: {integrity: sha512-TFZzUEV00f+2YLaVPWBWGAMq7So6yQx+GG8YRMDeOEIf95Zn5RyiLMsEiX4KTNl9vq/w+NqRJkLA1kPIo15ufQ==} + engines: {node: '>=18.12.0'} + hasBin: true + dependencies: + chalk: 5.3.0 + commander: 11.1.0 + debug: 4.3.4 + execa: 8.0.1 + lilconfig: 3.0.0 + listr2: 8.0.0 + micromatch: 4.0.5 + pidtree: 0.6.0 + string-argv: 0.3.2 + yaml: 2.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /listr2@8.0.0: + resolution: {integrity: sha512-u8cusxAcyqAiQ2RhYvV7kRKNLgUvtObIbhOX2NCXqvp1UU32xIg5CT22ykS2TPKJXZWJwtK3IKLiqAGlGNE+Zg==} + engines: {node: '>=18.0.0'} + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.1 + log-update: 6.0.0 + rfdc: 1.3.0 + wrap-ansi: 9.0.0 + dev: true + + /loader-utils@1.4.2: + resolution: {integrity: sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==} + engines: {node: '>=4.0.0'} + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 1.0.2 + dev: true + + /local-pkg@0.4.3: + resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} + engines: {node: '>=14'} + dev: true + + /local-pkg@0.5.0: + resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} + engines: {node: '>=14'} + dependencies: + mlly: 1.5.0 + pkg-types: 1.0.3 + dev: true + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + dev: false + + /lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21): + resolution: {integrity: sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==} + peerDependencies: + '@types/lodash-es': '*' + lodash: '*' + lodash-es: '*' + dependencies: + '@types/lodash-es': 4.17.12 + lodash: 4.17.21 + lodash-es: 4.17.21 + dev: false + + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + /log-update@6.0.0: + resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==} + engines: {node: '>=18'} + dependencies: + ansi-escapes: 6.2.0 + cli-cursor: 4.0.0 + slice-ansi: 7.1.0 + strip-ansi: 7.1.0 + wrap-ansi: 9.0.0 + dev: true + + /loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + dependencies: + js-tokens: 4.0.0 + dev: false + + /loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + dependencies: + get-func-name: 2.0.2 + dev: true + + /lru-cache@10.1.0: + resolution: {integrity: sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==} + engines: {node: 14 || >=16.14} + dev: true + + /lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + dev: true + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /magic-string@0.30.5: + resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + + /map-cache@0.2.2: + resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} + engines: {node: '>=0.10.0'} + dev: true + + /map-visit@1.0.0: + resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} + engines: {node: '>=0.10.0'} + dependencies: + object-visit: 1.0.1 + dev: true + + /mdn-data@2.0.14: + resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + dev: true + + /mdn-data@2.0.28: + resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} + dev: true + + /mdn-data@2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + dev: true + + /memoize-one@6.0.0: + resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} + dev: false + + /merge-options@1.0.1: + resolution: {integrity: sha512-iuPV41VWKWBIOpBsjoxjDZw8/GbSfZ2mk7N1453bwMrfzdrIk7EzBd+8UVR6rkw67th7xnk9Dytl3J+lHPdxvg==} + engines: {node: '>=4'} + dependencies: + is-plain-obj: 1.1.0 + dev: true + + /merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: true + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micromatch@3.1.0: + resolution: {integrity: sha512-3StSelAE+hnRvMs8IdVW7Uhk8CVed5tp+kLLGlBP6WiRAXS21GPGu/Nat4WNPXj2Eoc24B02SaeoyozPMfj0/g==} + engines: {node: '>=0.10.0'} + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + braces: 2.3.2 + define-property: 1.0.0 + extend-shallow: 2.0.1 + extglob: 2.0.4 + fragment-cache: 0.2.1 + kind-of: 5.1.0 + nanomatch: 1.2.13 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + + /mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: true + + /mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + dev: true + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimatch@9.0.1: + resolution: {integrity: sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true + + /minipass@7.0.4: + resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} + engines: {node: '>=16 || 14 >=14.17'} + dev: true + + /mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + dev: false + + /mixin-deep@1.3.2: + resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} + engines: {node: '>=0.10.0'} + dependencies: + for-in: 1.0.2 + is-extendable: 1.0.1 + dev: true + + /mlly@1.5.0: + resolution: {integrity: sha512-NPVQvAY1xr1QoVeG0cy8yUYC7FQcOx6evl/RjT1wL5FvzPnzOysoqB/jmx/DhssT2dYa8nxECLAaFI/+gVLhDQ==} + dependencies: + acorn: 8.11.3 + pathe: 1.1.2 + pkg-types: 1.0.3 + ufo: 1.3.2 + dev: true + + /mrmime@2.0.0: + resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} + engines: {node: '>=10'} + dev: true + + /ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: true + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /muggle-string@0.3.1: + resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==} + dev: true + + /nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + /nanomatch@1.2.13: + resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} + engines: {node: '>=0.10.0'} + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + define-property: 2.0.2 + extend-shallow: 3.0.2 + fragment-cache: 0.2.1 + is-windows: 1.0.2 + kind-of: 6.0.3 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /nanopop@2.4.2: + resolution: {integrity: sha512-NzOgmMQ+elxxHeIha+OG/Pv3Oc3p4RU2aBhwWwAqDpXrdTbtRylbRLQztLy8dMMwfl6pclznBdfUhccEn9ZIzw==} + dev: false + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /node-fetch-native@1.6.1: + resolution: {integrity: sha512-bW9T/uJDPAJB2YNYEpWzE54U5O3MQidXsOyTfnbKYtTtFexRvGzb1waphBN4ZwP6EcIvYYEOwW0b72BpAqydTw==} + dev: true + + /node-releases@2.0.14: + resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + dev: true + + /nopt@7.2.0: + resolution: {integrity: sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + dependencies: + abbrev: 2.0.0 + dev: true + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /normalize-wheel-es@1.2.0: + resolution: {integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==} + dev: false + + /normalize.css@8.0.1: + resolution: {integrity: sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==} + dev: false + + /npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + dev: true + + /npm-run-path@5.2.0: + resolution: {integrity: sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + path-key: 4.0.0 + dev: true + + /nprogress@0.2.0: + resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==} + dev: false + + /nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + dependencies: + boolbase: 1.0.0 + dev: true + + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: true + + /object-copy@0.1.0: + resolution: {integrity: sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==} + engines: {node: '>=0.10.0'} + dependencies: + copy-descriptor: 0.1.1 + define-property: 0.2.5 + kind-of: 3.2.2 + dev: true + + /object-visit@1.0.1: + resolution: {integrity: sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: true + + /object.pick@1.3.0: + resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: true + + /ofetch@1.3.3: + resolution: {integrity: sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg==} + dependencies: + destr: 2.0.2 + node-fetch-native: 1.6.1 + ufo: 1.3.2 + dev: true + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: true + + /onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + dependencies: + mimic-fn: 4.0.0 + dev: true + + /optionator@0.9.3: + resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + engines: {node: '>= 0.8.0'} + dependencies: + '@aashutoshrathi/word-wrap': 1.2.6 + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-limit@5.0.0: + resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} + engines: {node: '>=18'} + dependencies: + yocto-queue: 1.0.0 + dev: true + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + dependencies: + entities: 4.5.0 + dev: true + + /pascalcase@0.1.1: + resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==} + engines: {node: '>=0.10.0'} + dev: true + + /path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + dev: true + + /path-scurry@1.10.1: + resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + lru-cache: 10.1.0 + minipass: 7.0.4 + dev: true + + /path-to-regexp@6.2.1: + resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} + dev: false + + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /pathe@0.2.0: + resolution: {integrity: sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==} + dev: true + + /pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + dev: true + + /pathval@1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + dev: true + + /perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + dev: true + + /picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /pidtree@0.6.0: + resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} + engines: {node: '>=0.10'} + hasBin: true + dev: true + + /pinia@2.1.7(typescript@5.3.3)(vue@3.4.15): + resolution: {integrity: sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==} + peerDependencies: + '@vue/composition-api': ^1.4.0 + typescript: '>=4.4.4' + vue: ^2.6.14 || ^3.3.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + typescript: + optional: true + dependencies: + '@vue/devtools-api': 6.5.1 + typescript: 5.3.3 + vue: 3.4.15(typescript@5.3.3) + vue-demi: 0.14.6(vue@3.4.15) + dev: false + + /pkg-types@1.0.3: + resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} + dependencies: + jsonc-parser: 3.2.0 + mlly: 1.5.0 + pathe: 1.1.2 + dev: true + + /posix-character-classes@0.1.1: + resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==} + engines: {node: '>=0.10.0'} + dev: true + + /postcss-prefix-selector@1.16.0(postcss@5.2.18): + resolution: {integrity: sha512-rdVMIi7Q4B0XbXqNUEI+Z4E+pueiu/CS5E6vRCQommzdQ/sgsS4dK42U7GX8oJR+TJOtT+Qv3GkNo6iijUMp3Q==} + peerDependencies: + postcss: '>4 <9' + dependencies: + postcss: 5.2.18 + dev: true + + /postcss-selector-parser@6.0.15: + resolution: {integrity: sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: true + + /postcss@5.2.18: + resolution: {integrity: sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==} + engines: {node: '>=0.12'} + dependencies: + chalk: 1.1.3 + js-base64: 2.6.4 + source-map: 0.5.7 + supports-color: 3.2.3 + dev: true + + /postcss@8.4.33: + resolution: {integrity: sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.0 + source-map-js: 1.0.2 + + /posthtml-parser@0.2.1: + resolution: {integrity: sha512-nPC53YMqJnc/+1x4fRYFfm81KV2V+G9NZY+hTohpYg64Ay7NemWWcV4UWuy/SgMupqQ3kJ88M/iRfZmSnxT+pw==} + dependencies: + htmlparser2: 3.10.1 + isobject: 2.1.0 + dev: true + + /posthtml-rename-id@1.0.12: + resolution: {integrity: sha512-UKXf9OF/no8WZo9edRzvuMenb6AD5hDLzIepJW+a4oJT+T/Lx7vfMYWT4aWlGNQh0WMhnUx1ipN9OkZ9q+ddEw==} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + + /posthtml-render@1.4.0: + resolution: {integrity: sha512-W1779iVHGfq0Fvh2PROhCe2QhB8mEErgqzo1wpIt36tCgChafP+hbXIhLDOM8ePJrZcFs0vkNEtdibEWVqChqw==} + engines: {node: '>=10'} + dev: true + + /posthtml-svg-mode@1.0.3: + resolution: {integrity: sha512-hEqw9NHZ9YgJ2/0G7CECOeuLQKZi8HjWLkBaSVtOWjygQ9ZD8P7tqeowYs7WrFdKsWEKG7o+IlsPY8jrr0CJpQ==} + dependencies: + merge-options: 1.0.1 + posthtml: 0.9.2 + posthtml-parser: 0.2.1 + posthtml-render: 1.4.0 + dev: true + + /posthtml@0.9.2: + resolution: {integrity: sha512-spBB5sgC4cv2YcW03f/IAUN1pgDJWNWD8FzkyY4mArLUMJW+KlQhlmUdKAHQuPfb00Jl5xIfImeOsf6YL8QK7Q==} + engines: {node: '>=0.10.0'} + dependencies: + posthtml-parser: 0.2.1 + posthtml-render: 1.4.0 + dev: true + + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + dependencies: + fast-diff: 1.3.0 + dev: true + + /prettier@3.2.4: + resolution: {integrity: sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.2.0 + dev: true + + /proto-list@1.2.4: + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + dev: true + + /proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: false + + /psl@1.9.0: + resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + dev: true + + /punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + dev: true + + /query-string@4.3.4: + resolution: {integrity: sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q==} + engines: {node: '>=0.10.0'} + dependencies: + object-assign: 4.1.1 + strict-uri-encode: 1.1.0 + dev: true + + /querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + dev: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /react-is@18.2.0: + resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + dev: true + + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: true + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + + /regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + dev: false + + /regex-not@1.0.2: + resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 3.0.2 + safe-regex: 1.1.0 + dev: true + + /repeat-element@1.1.4: + resolution: {integrity: sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==} + engines: {node: '>=0.10.0'} + dev: true + + /repeat-string@1.6.1: + resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} + engines: {node: '>=0.10'} + dev: true + + /require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + dev: true + + /requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + dev: true + + /resize-observer-polyfill@1.5.1: + resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} + dev: false + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve-url@0.2.1: + resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} + deprecated: https://github.com/lydell/resolve-url#deprecated + dev: true + + /restore-cursor@4.0.0: + resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + dev: true + + /ret@0.1.15: + resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} + engines: {node: '>=0.12'} + dev: true + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rfdc@1.3.0: + resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} + dev: true + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /rollup@4.9.5: + resolution: {integrity: sha512-E4vQW0H/mbNMw2yLSqJyjtkHY9dslf/p0zuT1xehNRqUTBOFMqEjguDvqhXr7N7r/4ttb2jr4T41d3dncmIgbQ==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.9.5 + '@rollup/rollup-android-arm64': 4.9.5 + '@rollup/rollup-darwin-arm64': 4.9.5 + '@rollup/rollup-darwin-x64': 4.9.5 + '@rollup/rollup-linux-arm-gnueabihf': 4.9.5 + '@rollup/rollup-linux-arm64-gnu': 4.9.5 + '@rollup/rollup-linux-arm64-musl': 4.9.5 + '@rollup/rollup-linux-riscv64-gnu': 4.9.5 + '@rollup/rollup-linux-x64-gnu': 4.9.5 + '@rollup/rollup-linux-x64-musl': 4.9.5 + '@rollup/rollup-win32-arm64-msvc': 4.9.5 + '@rollup/rollup-win32-ia32-msvc': 4.9.5 + '@rollup/rollup-win32-x64-msvc': 4.9.5 + fsevents: 2.3.3 + dev: true + + /rrweb-cssom@0.6.0: + resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: true + + /safe-regex@1.1.0: + resolution: {integrity: sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==} + dependencies: + ret: 0.1.15 + dev: true + + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: true + + /sass@1.70.0: + resolution: {integrity: sha512-uUxNQ3zAHeAx5nRFskBnrWzDUJrrvpCPD5FNAoRvTi0WwremlheES3tg+56PaVtCs5QDRX5CBLxxKMDJMEa1WQ==} + engines: {node: '>=14.0.0'} + hasBin: true + dependencies: + chokidar: 3.5.3 + immutable: 4.3.4 + source-map-js: 1.0.2 + dev: true + + /saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + dependencies: + xmlchars: 2.2.0 + dev: true + + /screenfull@6.0.2: + resolution: {integrity: sha512-AQdy8s4WhNvUZ6P8F6PB21tSPIYKniic+Ogx0AacBMjKP1GUHN2E9URxQHtCusiwxudnCKkdy4GrHXPPJSkCCw==} + engines: {node: ^14.13.1 || >=16.0.0} + dev: false + + /scroll-into-view-if-needed@2.2.31: + resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==} + dependencies: + compute-scroll-into-view: 1.0.20 + dev: false + + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + dev: true + + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /set-value@2.0.1: + resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 2.0.1 + is-extendable: 0.1.1 + is-plain-object: 2.0.4 + split-string: 3.1.0 + dev: true + + /shallow-equal@1.2.1: + resolution: {integrity: sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==} + dev: false + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + dev: true + + /signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true + + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + dev: true + + /sirv@2.0.4: + resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} + engines: {node: '>= 10'} + dependencies: + '@polka/url': 1.0.0-next.24 + mrmime: 2.0.0 + totalist: 3.0.1 + dev: true + + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + dev: true + + /slice-ansi@7.1.0: + resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} + engines: {node: '>=18'} + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 5.0.0 + dev: true + + /snapdragon-node@2.1.1: + resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==} + engines: {node: '>=0.10.0'} + dependencies: + define-property: 1.0.0 + isobject: 3.0.1 + snapdragon-util: 3.0.1 + dev: true + + /snapdragon-util@3.0.1: + resolution: {integrity: sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: true + + /snapdragon@0.8.2: + resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} + engines: {node: '>=0.10.0'} + dependencies: + base: 0.11.2 + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + map-cache: 0.2.2 + source-map: 0.5.7 + source-map-resolve: 0.5.3 + use: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /source-map-js@1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + + /source-map-resolve@0.5.3: + resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} + deprecated: See https://github.com/lydell/source-map-resolve#deprecated + dependencies: + atob: 2.1.2 + decode-uri-component: 0.2.2 + resolve-url: 0.2.1 + source-map-url: 0.4.1 + urix: 0.1.0 + dev: true + + /source-map-url@0.4.1: + resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} + deprecated: See https://github.com/lydell/source-map-url#deprecated + dev: true + + /source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /split-string@3.1.0: + resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 3.0.2 + dev: true + + /stable@0.1.8: + resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==} + deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' + dev: true + + /stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + dev: true + + /static-extend@0.1.2: + resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} + engines: {node: '>=0.10.0'} + dependencies: + define-property: 0.2.5 + object-copy: 0.1.0 + dev: true + + /std-env@3.7.0: + resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} + dev: true + + /strict-uri-encode@1.1.0: + resolution: {integrity: sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==} + engines: {node: '>=0.10.0'} + dev: true + + /string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + dev: true + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: true + + /string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + dev: true + + /string-width@7.0.0: + resolution: {integrity: sha512-GPQHj7row82Hjo9hKZieKcHIhaAIKOJvFSIZXuCU9OASVZrMNUaZuz++SPVrBjnLsnk4k+z9f2EIypgxf2vNFw==} + engines: {node: '>=18'} + dependencies: + emoji-regex: 10.3.0 + get-east-asian-width: 1.2.0 + strip-ansi: 7.1.0 + dev: true + + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /strip-ansi@3.0.1: + resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-regex: 2.1.1 + dev: true + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: true + + /strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + dev: true + + /strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /strip-literal@1.3.0: + resolution: {integrity: sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==} + dependencies: + acorn: 8.11.3 + dev: true + + /stylis@4.3.1: + resolution: {integrity: sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ==} + dev: false + + /supports-color@2.0.0: + resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} + engines: {node: '>=0.8.0'} + dev: true + + /supports-color@3.2.3: + resolution: {integrity: sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==} + engines: {node: '>=0.8.0'} + dependencies: + has-flag: 1.0.0 + dev: true + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /svg-baker@1.7.0: + resolution: {integrity: sha512-nibslMbkXOIkqKVrfcncwha45f97fGuAOn1G99YwnwTj8kF9YiM6XexPcUso97NxOm6GsP0SIvYVIosBis1xLg==} + dependencies: + bluebird: 3.7.2 + clone: 2.1.2 + he: 1.2.0 + image-size: 0.5.5 + loader-utils: 1.4.2 + merge-options: 1.0.1 + micromatch: 3.1.0 + postcss: 5.2.18 + postcss-prefix-selector: 1.16.0(postcss@5.2.18) + posthtml-rename-id: 1.0.12 + posthtml-svg-mode: 1.0.3 + query-string: 4.3.4 + traverse: 0.6.8 + transitivePeerDependencies: + - supports-color + dev: true + + /svg-tags@1.0.0: + resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} + dev: true + + /svgo@2.8.0: + resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==} + engines: {node: '>=10.13.0'} + hasBin: true + dependencies: + '@trysound/sax': 0.2.0 + commander: 7.2.0 + css-select: 4.3.0 + css-tree: 1.1.3 + csso: 4.2.0 + picocolors: 1.0.0 + stable: 0.1.8 + dev: true + + /svgo@3.2.0: + resolution: {integrity: sha512-4PP6CMW/V7l/GmKRKzsLR8xxjdHTV4IMvhTnpuHwwBazSIlw5W/5SmPjN8Dwyt7lKbSJrRDgp4t9ph0HgChFBQ==} + engines: {node: '>=14.0.0'} + hasBin: true + dependencies: + '@trysound/sax': 0.2.0 + commander: 7.2.0 + css-select: 5.1.0 + css-tree: 2.3.1 + css-what: 6.1.0 + csso: 5.0.5 + picocolors: 1.0.0 + dev: true + + /symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + dev: true + + /synckit@0.8.8: + resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} + engines: {node: ^14.18.0 || >=16.0.0} + dependencies: + '@pkgr/core': 0.1.1 + tslib: 2.6.2 + dev: true + + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /throttle-debounce@5.0.0: + resolution: {integrity: sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==} + engines: {node: '>=12.22'} + dev: false + + /tinybench@2.6.0: + resolution: {integrity: sha512-N8hW3PG/3aOoZAN5V/NSAEDz0ZixDSSt5b/a05iqtpgfLWMSVuCo7w0k2vVvEjdrIoeGqZzweX2WlyioNIHchA==} + dev: true + + /tinypool@0.8.2: + resolution: {integrity: sha512-SUszKYe5wgsxnNOVlBYO6IC+8VGWdVGZWAqUxp3UErNBtptZvWbwyUOyzNL59zigz2rCA92QiL3wvG+JDSdJdQ==} + engines: {node: '>=14.0.0'} + dev: true + + /tinyspy@2.2.0: + resolution: {integrity: sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==} + engines: {node: '>=14.0.0'} + dev: true + + /to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + + /to-object-path@0.3.0: + resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: true + + /to-regex-range@2.1.1: + resolution: {integrity: sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==} + engines: {node: '>=0.10.0'} + dependencies: + is-number: 3.0.0 + repeat-string: 1.6.1 + dev: true + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /to-regex@3.0.2: + resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} + engines: {node: '>=0.10.0'} + dependencies: + define-property: 2.0.2 + extend-shallow: 3.0.2 + regex-not: 1.0.2 + safe-regex: 1.1.0 + dev: true + + /totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + dev: true + + /tough-cookie@4.1.3: + resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==} + engines: {node: '>=6'} + dependencies: + psl: 1.9.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + dev: true + + /tr46@5.0.0: + resolution: {integrity: sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==} + engines: {node: '>=18'} + dependencies: + punycode: 2.3.1 + dev: true + + /traverse@0.6.8: + resolution: {integrity: sha512-aXJDbk6SnumuaZSANd21XAo15ucCDE38H4fkqiGsc3MhCK+wOlZvLP9cB/TvpHT0mOyWgC4Z8EwRlzqYSUzdsA==} + engines: {node: '>= 0.4'} + dev: true + + /ts-api-utils@1.0.3(typescript@5.3.3): + resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} + engines: {node: '>=16.13.0'} + peerDependencies: + typescript: '>=4.2.0' + dependencies: + typescript: 5.3.3 + dev: true + + /tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + dev: true + + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + dev: true + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /type-fest@3.13.1: + resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} + engines: {node: '>=14.16'} + dev: true + + /typescript@5.3.3: + resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} + engines: {node: '>=14.17'} + hasBin: true + + /ufo@1.3.2: + resolution: {integrity: sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==} + dev: true + + /unconfig@0.3.11: + resolution: {integrity: sha512-bV/nqePAKv71v3HdVUn6UefbsDKQWRX+bJIkiSm0+twIds6WiD2bJLWWT3i214+J/B4edufZpG2w7Y63Vbwxow==} + dependencies: + '@antfu/utils': 0.7.7 + defu: 6.1.4 + jiti: 1.21.0 + mlly: 1.5.0 + dev: true + + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: true + + /union-value@1.0.1: + resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} + engines: {node: '>=0.10.0'} + dependencies: + arr-union: 3.1.0 + get-value: 2.0.6 + is-extendable: 0.1.1 + set-value: 2.0.1 + dev: true + + /universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + dev: true + + /universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + dev: true + + /unocss@0.58.3(postcss@8.4.33)(vite@5.0.11): + resolution: {integrity: sha512-2rnvghfiIDRQ2cOrmN4P7J7xV2p3yBK+bPAt1aoUxCXcszkLczAnQzh9c7IZ+p70kSVstK45cJTYV6TMzOLF7Q==} + engines: {node: '>=14'} + peerDependencies: + '@unocss/webpack': 0.58.3 + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 + peerDependenciesMeta: + '@unocss/webpack': + optional: true + vite: + optional: true + dependencies: + '@unocss/astro': 0.58.3(vite@5.0.11) + '@unocss/cli': 0.58.3 + '@unocss/core': 0.58.3 + '@unocss/extractor-arbitrary-variants': 0.58.3 + '@unocss/postcss': 0.58.3(postcss@8.4.33) + '@unocss/preset-attributify': 0.58.3 + '@unocss/preset-icons': 0.58.3 + '@unocss/preset-mini': 0.58.3 + '@unocss/preset-tagify': 0.58.3 + '@unocss/preset-typography': 0.58.3 + '@unocss/preset-uno': 0.58.3 + '@unocss/preset-web-fonts': 0.58.3 + '@unocss/preset-wind': 0.58.3 + '@unocss/reset': 0.58.3 + '@unocss/transformer-attributify-jsx': 0.58.3 + '@unocss/transformer-attributify-jsx-babel': 0.58.3 + '@unocss/transformer-compile-class': 0.58.3 + '@unocss/transformer-directives': 0.58.3 + '@unocss/transformer-variant-group': 0.58.3 + '@unocss/vite': 0.58.3(vite@5.0.11) + vite: 5.0.11(@types/node@20.11.5)(sass@1.70.0) + transitivePeerDependencies: + - postcss + - rollup + - supports-color + dev: true + + /unset-value@1.0.0: + resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==} + engines: {node: '>=0.10.0'} + dependencies: + has-value: 0.3.1 + isobject: 3.0.1 + dev: true + + /update-browserslist-db@1.0.13(browserslist@4.22.2): + resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.22.2 + escalade: 3.1.1 + picocolors: 1.0.0 + dev: true + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.1 + dev: true + + /urix@0.1.0: + resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==} + deprecated: Please see https://github.com/lydell/urix#deprecated + dev: true + + /url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + dev: true + + /use@3.1.1: + resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} + engines: {node: '>=0.10.0'} + dev: true + + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: true + + /vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + dev: true + + /vite-node@1.2.1(@types/node@20.11.5)(sass@1.70.0): + resolution: {integrity: sha512-fNzHmQUSOY+y30naohBvSW7pPn/xn3Ib/uqm+5wAJQJiqQsU0NBR78XdRJb04l4bOFKjpTWld0XAfkKlrDbySg==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + dependencies: + cac: 6.7.14 + debug: 4.3.4 + pathe: 1.1.2 + picocolors: 1.0.0 + vite: 5.0.11(@types/node@20.11.5)(sass@1.70.0) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + + /vite-plugin-svg-icons@2.0.1(vite@5.0.11): + resolution: {integrity: sha512-6ktD+DhV6Rz3VtedYvBKKVA2eXF+sAQVaKkKLDSqGUfnhqXl3bj5PPkVTl3VexfTuZy66PmINi8Q6eFnVfRUmA==} + peerDependencies: + vite: '>=2.0.0' + dependencies: + '@types/svgo': 2.6.4 + cors: 2.8.5 + debug: 4.3.4 + etag: 1.8.1 + fs-extra: 10.1.0 + pathe: 0.2.0 + svg-baker: 1.7.0 + svgo: 2.8.0 + vite: 5.0.11(@types/node@20.11.5)(sass@1.70.0) + transitivePeerDependencies: + - supports-color + dev: true + + /vite-svg-loader@5.1.0(vue@3.4.15): + resolution: {integrity: sha512-M/wqwtOEjgb956/+m5ZrYT/Iq6Hax0OakWbokj8+9PXOnB7b/4AxESHieEtnNEy7ZpjsjYW1/5nK8fATQMmRxw==} + peerDependencies: + vue: '>=3.2.13' + dependencies: + svgo: 3.2.0 + vue: 3.4.15(typescript@5.3.3) + dev: true + + /vite@5.0.11(@types/node@20.11.5)(sass@1.70.0): + resolution: {integrity: sha512-XBMnDjZcNAw/G1gEiskiM1v6yzM4GE5aMGvhWTlHAYYhxb7S3/V1s3m2LDHa8Vh6yIWYYB0iJwsEaS523c4oYA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 20.11.5 + esbuild: 0.19.11 + postcss: 8.4.33 + rollup: 4.9.5 + sass: 1.70.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /vitest@1.2.1(@types/node@20.11.5)(jsdom@23.2.0)(sass@1.70.0): + resolution: {integrity: sha512-TRph8N8rnSDa5M2wKWJCMnztCZS9cDcgVTQ6tsTFTG/odHJ4l5yNVqvbeDJYJRZ6is3uxaEpFs8LL6QM+YFSdA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': ^1.0.0 + '@vitest/ui': ^1.0.0 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + dependencies: + '@types/node': 20.11.5 + '@vitest/expect': 1.2.1 + '@vitest/runner': 1.2.1 + '@vitest/snapshot': 1.2.1 + '@vitest/spy': 1.2.1 + '@vitest/utils': 1.2.1 + acorn-walk: 8.3.2 + cac: 6.7.14 + chai: 4.4.1 + debug: 4.3.4 + execa: 8.0.1 + jsdom: 23.2.0 + local-pkg: 0.5.0 + magic-string: 0.30.5 + pathe: 1.1.2 + picocolors: 1.0.0 + std-env: 3.7.0 + strip-literal: 1.3.0 + tinybench: 2.6.0 + tinypool: 0.8.2 + vite: 5.0.11(@types/node@20.11.5)(sass@1.70.0) + vite-node: 1.2.1(@types/node@20.11.5)(sass@1.70.0) + why-is-node-running: 2.2.2 + transitivePeerDependencies: + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + + /vue-component-type-helpers@1.8.27: + resolution: {integrity: sha512-0vOfAtI67UjeO1G6UiX5Kd76CqaQ67wrRZiOe7UAb9Jm6GzlUr/fC7CV90XfwapJRjpCMaZFhv1V0ajWRmE9Dg==} + dev: true + + /vue-demi@0.14.6(vue@3.4.15): + resolution: {integrity: sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + dependencies: + vue: 3.4.15(typescript@5.3.3) + dev: false + + /vue-eslint-parser@9.4.0(eslint@8.56.0): + resolution: {integrity: sha512-7KsNBb6gHFA75BtneJsoK/dbZ281whUIwFYdQxA68QrCrGMXYzUMbPDHGcOQ0OocIVKrWSKWXZ4mL7tonCXoUw==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + debug: 4.3.4 + eslint: 8.56.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + lodash: 4.17.21 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + dev: true + + /vue-router@4.2.5(vue@3.4.15): + resolution: {integrity: sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==} + peerDependencies: + vue: ^3.2.0 + dependencies: + '@vue/devtools-api': 6.5.1 + vue: 3.4.15(typescript@5.3.3) + dev: false + + /vue-template-compiler@2.7.16: + resolution: {integrity: sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==} + dependencies: + de-indent: 1.0.2 + he: 1.2.0 + dev: true + + /vue-tsc@1.8.27(typescript@5.3.3): + resolution: {integrity: sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==} + hasBin: true + peerDependencies: + typescript: '*' + dependencies: + '@volar/typescript': 1.11.1 + '@vue/language-core': 1.8.27(typescript@5.3.3) + semver: 7.5.4 + typescript: 5.3.3 + dev: true + + /vue-types@3.0.2(vue@3.4.15): + resolution: {integrity: sha512-IwUC0Aq2zwaXqy74h4WCvFCUtoV0iSWr0snWnE9TnU18S66GAQyqQbRf2qfJtUuiFsBf6qp0MEwdonlwznlcrw==} + engines: {node: '>=10.15.0'} + peerDependencies: + vue: ^3.0.0 + dependencies: + is-plain-object: 3.0.1 + vue: 3.4.15(typescript@5.3.3) + dev: false + + /vue@3.4.15(typescript@5.3.3): + resolution: {integrity: sha512-jC0GH4KkWLWJOEQjOpkqU1bQsBwf4R1rsFtw5GQJbjHVKWDzO6P0nWWBTmjp1xSemAioDFj1jdaK1qa3DnMQoQ==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@vue/compiler-dom': 3.4.15 + '@vue/compiler-sfc': 3.4.15 + '@vue/runtime-dom': 3.4.15 + '@vue/server-renderer': 3.4.15(vue@3.4.15) + '@vue/shared': 3.4.15 + typescript: 5.3.3 + + /vxe-table-plugin-element@3.0.7(vxe-table@4.4.1): + resolution: {integrity: sha512-cw9krtPRkqCxszWCnVxzgLOEt1HYN2W5AN+AovlN6i7/4gtp1O7YFFVbqmpGYfUU2uf0deXgJXru53Bx9WY20Q==} + peerDependencies: + vxe-table: ^4.2.0 + dependencies: + vxe-table: 4.4.1(vue@3.4.15)(xe-utils@3.5.11) + dev: false + + /vxe-table@4.4.1(vue@3.4.15)(xe-utils@3.5.11): + resolution: {integrity: sha512-yq19+sds2Av625YiS3vpYjdXUN2BFTAyboOT+v5yhi6sroR7WwOnH7jkJ7/Q4U6ZhCDT59u0UOGAPVT27/4OWQ==} + peerDependencies: + vue: ^3.2.28 + xe-utils: ^3.5.0 + dependencies: + vue: 3.4.15(typescript@5.3.3) + xe-utils: 3.5.11 + dev: false + + /w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + dependencies: + xml-name-validator: 5.0.0 + dev: true + + /warning@4.0.3: + resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} + dependencies: + loose-envify: 1.4.0 + dev: false + + /webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + dev: true + + /whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + dependencies: + iconv-lite: 0.6.3 + dev: true + + /whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + dev: true + + /whatwg-url@14.0.0: + resolution: {integrity: sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==} + engines: {node: '>=18'} + dependencies: + tr46: 5.0.0 + webidl-conversions: 7.0.0 + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /why-is-node-running@2.2.2: + resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} + engines: {node: '>=8'} + hasBin: true + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + dev: true + + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + dev: true + + /wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + dependencies: + ansi-styles: 6.2.1 + string-width: 7.0.0 + strip-ansi: 7.1.0 + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /ws@8.16.0: + resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: true + + /xe-utils@3.5.11: + resolution: {integrity: sha512-lyKc/lTBga1Zb63p+FED8mtxLnYIjSS8PVJM1N64NGdCu/3d1XubaVeke2p91RHssP0ExVAl2LUqZYperoz76Q==} + dev: false + + /xml-name-validator@4.0.0: + resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} + engines: {node: '>=12'} + dev: true + + /xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + dev: true + + /xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + dev: true + + /yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: true + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true + + /yaml@2.3.4: + resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} + engines: {node: '>= 14'} + dev: true + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true + + /yocto-queue@1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} + dev: true diff --git a/prettier.config.js b/prettier.config.js new file mode 100644 index 0000000..8b96576 --- /dev/null +++ b/prettier.config.js @@ -0,0 +1,25 @@ +/** + * 配置项文档:https://prettier.io/docs/en/configuration.html + * @type {import("prettier").Config} + */ + +export default { + /** 每一行的宽度 */ + printWidth: 120, + /** Tab 键的空格数 */ + tabWidth: 2, + /** 在对象中的括号之间是否用空格来间隔 */ + bracketSpacing: true, + /** 箭头函数的参数无论有几个,都要括号包裹 */ + arrowParens: "always", + /** 换行符的使用 */ + endOfLine: "auto", + /** 是否采用单引号 */ + singleQuote: false, + /** 对象或者数组的最后一个元素后面不要加逗号 */ + trailingComma: "none", + /** 是否加分号 */ + semi: true, + /** 是否使用 Tab 格式化 */ + useTabs: false +}; diff --git a/public/app-loading.css b/public/app-loading.css new file mode 100644 index 0000000..4f1346d --- /dev/null +++ b/public/app-loading.css @@ -0,0 +1,45 @@ +/** 白屏阶段会执行的 CSS 加载动画 */ + +#app-loading { + position: relative; + top: 45vh; + margin: 0 auto; + color: #409eff; + font-size: 12px; +} + +#app-loading, +#app-loading::before, +#app-loading::after { + width: 2em; + height: 2em; + border-radius: 50%; + animation: 2s ease-in-out infinite app-loading-animation; +} + +#app-loading::before, +#app-loading::after { + content: ""; + position: absolute; +} + +#app-loading::before { + left: -4em; + animation-delay: -0.2s; +} + +#app-loading::after { + left: 4em; + animation-delay: 0.2s; +} + +@keyframes app-loading-animation { + 0%, + 80%, + 100% { + box-shadow: 0 2em 0 -2em; + } + 40% { + box-shadow: 0 2em 0 0; + } +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..de03843 Binary files /dev/null and b/public/favicon.ico differ diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..dafe7a3 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/api/hook-demo/use-fetch-select.ts b/src/api/hook-demo/use-fetch-select.ts new file mode 100644 index 0000000..e7f1573 --- /dev/null +++ b/src/api/hook-demo/use-fetch-select.ts @@ -0,0 +1,36 @@ +/** 模拟接口响应数据 */ +const SELECT_RESPONSE_DATA = { + code: 0, + data: [ + { + label: "苹果", + value: 1 + }, + { + label: "香蕉", + value: 2 + }, + { + label: "橘子", + value: 3, + disabled: true + } + ], + message: "获取 Select 数据成功" +}; + +/** 模拟接口 */ +export function getSelectDataApi() { + return new Promise((resolve, reject) => { + // 模拟接口响应时间 2s + setTimeout(() => { + // 模拟接口调用成功 + if (Math.random() < 0.8) { + resolve(SELECT_RESPONSE_DATA); + } else { + // 模拟接口调用出错 + reject(new Error("接口发生错误")); + } + }, 2000); + }); +} diff --git a/src/api/hook-demo/use-fullscreen-loading.ts b/src/api/hook-demo/use-fullscreen-loading.ts new file mode 100644 index 0000000..5f2a25b --- /dev/null +++ b/src/api/hook-demo/use-fullscreen-loading.ts @@ -0,0 +1,26 @@ +/** 模拟接口响应数据 */ +const SUCCESS_RESPONSE_DATA = { + code: 0, + data: { + list: [] as number[] + }, + message: "获取成功" +}; + +/** 模拟请求接口成功 */ +export function getSuccessApi(list: number[]) { + return new Promise((resolve) => { + setTimeout(() => { + resolve({ ...SUCCESS_RESPONSE_DATA, data: { list } }); + }, 1000); + }); +} + +/** 模拟请求接口失败 */ +export function getErrorApi() { + return new Promise((_resolve, reject) => { + setTimeout(() => { + reject(new Error("发生错误")); + }, 1000); + }); +} diff --git a/src/api/login/index.ts b/src/api/login/index.ts new file mode 100644 index 0000000..b0b1a07 --- /dev/null +++ b/src/api/login/index.ts @@ -0,0 +1,27 @@ +import { request } from "@/utils/service"; +import type * as Login from "./types/login"; + +/** 获取登录验证码 */ +export function getLoginCodeApi() { + return request({ + url: "login/code", + method: "get" + }); +} + +/** 登录并返回 Token */ +export function loginApi(data: Login.LoginRequestData) { + return request({ + url: "users/login", + method: "post", + data + }); +} + +/** 获取用户详情 */ +export function getUserInfoApi() { + return request({ + url: "users/info", + method: "get" + }); +} diff --git a/src/api/login/types/login.ts b/src/api/login/types/login.ts new file mode 100644 index 0000000..84ad09e --- /dev/null +++ b/src/api/login/types/login.ts @@ -0,0 +1,14 @@ +export interface LoginRequestData { + /** admin 或 editor */ + username: "admin" | "editor"; + /** 密码 */ + password: string; + /** 验证码 */ + code: string; +} + +export type LoginCodeResponseData = ApiResponseData; + +export type LoginResponseData = ApiResponseData<{ token: string }>; + +export type UserInfoResponseData = ApiResponseData<{ username: string; roles: string[] }>; diff --git a/src/api/table/index.ts b/src/api/table/index.ts new file mode 100644 index 0000000..7b355e6 --- /dev/null +++ b/src/api/table/index.ts @@ -0,0 +1,37 @@ +import { request } from "@/utils/service"; +import type * as Table from "./types/table"; + +/** 增 */ +export function createTableDataApi(data: Table.CreateOrUpdateTableRequestData) { + return request({ + url: "table", + method: "post", + data + }); +} + +/** 删 */ +export function deleteTableDataApi(id: string) { + return request({ + url: `table/${id}`, + method: "delete" + }); +} + +/** 改 */ +export function updateTableDataApi(data: Table.CreateOrUpdateTableRequestData) { + return request({ + url: "table", + method: "put", + data + }); +} + +/** 查 */ +export function getTableDataApi(params: Table.GetTableRequestData) { + return request({ + url: "table", + method: "get", + params + }); +} diff --git a/src/api/table/types/table.ts b/src/api/table/types/table.ts new file mode 100644 index 0000000..b5384bb --- /dev/null +++ b/src/api/table/types/table.ts @@ -0,0 +1,31 @@ +export interface CreateOrUpdateTableRequestData { + id?: string; + username: string; + password?: string; +} + +export interface GetTableRequestData { + /** 当前页码 */ + currentPage: number; + /** 查询条数 */ + size: number; + /** 查询参数:用户名 */ + username?: string; + /** 查询参数:手机号 */ + phone?: string; +} + +export interface GetTableData { + createTime: string; + email: string; + id: string; + phone: string; + roles: string; + status: boolean; + username: string; +} + +export type GetTableResponseData = ApiResponseData<{ + list: GetTableData[]; + total: number; +}>; diff --git a/src/assets/docs/preview1.png b/src/assets/docs/preview1.png new file mode 100644 index 0000000..01dbdca Binary files /dev/null and b/src/assets/docs/preview1.png differ diff --git a/src/assets/docs/preview2.png b/src/assets/docs/preview2.png new file mode 100644 index 0000000..87c2086 Binary files /dev/null and b/src/assets/docs/preview2.png differ diff --git a/src/assets/docs/preview3.png b/src/assets/docs/preview3.png new file mode 100644 index 0000000..ec5a25d Binary files /dev/null and b/src/assets/docs/preview3.png differ diff --git a/src/assets/docs/qq.png b/src/assets/docs/qq.png new file mode 100644 index 0000000..5cbeffe Binary files /dev/null and b/src/assets/docs/qq.png differ diff --git a/src/assets/docs/wechat.png b/src/assets/docs/wechat.png new file mode 100644 index 0000000..e2ece4a Binary files /dev/null and b/src/assets/docs/wechat.png differ diff --git a/src/assets/error-page/403.svg b/src/assets/error-page/403.svg new file mode 100644 index 0000000..a925322 --- /dev/null +++ b/src/assets/error-page/403.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/error-page/404.svg b/src/assets/error-page/404.svg new file mode 100644 index 0000000..d59f6f1 --- /dev/null +++ b/src/assets/error-page/404.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/layouts/logo-text-1.png b/src/assets/layouts/logo-text-1.png new file mode 100644 index 0000000..1112b25 Binary files /dev/null and b/src/assets/layouts/logo-text-1.png differ diff --git a/src/assets/layouts/logo-text-2.png b/src/assets/layouts/logo-text-2.png new file mode 100644 index 0000000..4515433 Binary files /dev/null and b/src/assets/layouts/logo-text-2.png differ diff --git a/src/assets/layouts/logo.png b/src/assets/layouts/logo.png new file mode 100644 index 0000000..2876965 Binary files /dev/null and b/src/assets/layouts/logo.png differ diff --git a/src/components/Notify/NotifyList.vue b/src/components/Notify/NotifyList.vue new file mode 100644 index 0000000..9b3c142 --- /dev/null +++ b/src/components/Notify/NotifyList.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/src/components/Notify/data.ts b/src/components/Notify/data.ts new file mode 100644 index 0000000..8d5bc24 --- /dev/null +++ b/src/components/Notify/data.ts @@ -0,0 +1,66 @@ +export interface ListItem { + avatar?: string; + title: string; + datetime?: string; + description?: string; + status?: "" | "success" | "info" | "warning" | "danger"; + extra?: string; +} + +export const notifyData: ListItem[] = [ + { + avatar: "https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png", + title: "V3 Admin Vite 上线啦", + datetime: "一年前", + description: + "一个免费开源的中后台管理系统基础解决方案,基于 Vue3、TypeScript、Element Plus、Pinia 和 Vite 等主流技术" + }, + { + avatar: "https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png", + title: "V3 Admin 上线啦", + datetime: "两年前", + description: "一个中后台管理系统基础解决方案,基于 Vue3、TypeScript、Element Plus 和 Pinia" + } +]; + +export const messageData: ListItem[] = [ + { + avatar: "https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png", + title: "来自楚门的世界", + description: "如果再也不能见到你,祝你早安、午安和晚安", + datetime: "1998-06-05" + }, + { + avatar: "https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png", + title: "来自大话西游", + description: "如果非要在这份爱上加上一个期限,我希望是一万年", + datetime: "1995-02-04" + }, + { + avatar: "https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png", + title: "来自龙猫", + description: "心存善意,定能途遇天使", + datetime: "1988-04-16" + } +]; + +export const todoData: ListItem[] = [ + { + title: "任务名称", + description: "这家伙很懒,什么都没留下", + extra: "未开始", + status: "info" + }, + { + title: "任务名称", + description: "这家伙很懒,什么都没留下", + extra: "进行中", + status: "" + }, + { + title: "任务名称", + description: "这家伙很懒,什么都没留下", + extra: "已超时", + status: "danger" + } +]; diff --git a/src/components/Notify/index.vue b/src/components/Notify/index.vue new file mode 100644 index 0000000..9e22dad --- /dev/null +++ b/src/components/Notify/index.vue @@ -0,0 +1,96 @@ + + + + + diff --git a/src/components/Screenfull/index.vue b/src/components/Screenfull/index.vue new file mode 100644 index 0000000..69eb228 --- /dev/null +++ b/src/components/Screenfull/index.vue @@ -0,0 +1,92 @@ + + + + + diff --git a/src/components/SearchMenu/SearchFooter.vue b/src/components/SearchMenu/SearchFooter.vue new file mode 100644 index 0000000..9b43f6c --- /dev/null +++ b/src/components/SearchMenu/SearchFooter.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/src/components/SearchMenu/SearchModal.vue b/src/components/SearchMenu/SearchModal.vue new file mode 100644 index 0000000..9fb5c82 --- /dev/null +++ b/src/components/SearchMenu/SearchModal.vue @@ -0,0 +1,228 @@ + + + + + diff --git a/src/components/SearchMenu/SearchResult.vue b/src/components/SearchMenu/SearchResult.vue new file mode 100644 index 0000000..7f14fd2 --- /dev/null +++ b/src/components/SearchMenu/SearchResult.vue @@ -0,0 +1,122 @@ + + + + + diff --git a/src/components/SearchMenu/index.vue b/src/components/SearchMenu/index.vue new file mode 100644 index 0000000..0eafd44 --- /dev/null +++ b/src/components/SearchMenu/index.vue @@ -0,0 +1,29 @@ + + + + + diff --git a/src/components/SvgIcon/index.vue b/src/components/SvgIcon/index.vue new file mode 100644 index 0000000..a09b43b --- /dev/null +++ b/src/components/SvgIcon/index.vue @@ -0,0 +1,29 @@ + + + + + diff --git a/src/components/ThemeSwitch/index.vue b/src/components/ThemeSwitch/index.vue new file mode 100644 index 0000000..6eabf17 --- /dev/null +++ b/src/components/ThemeSwitch/index.vue @@ -0,0 +1,30 @@ + + + diff --git a/src/config/layouts.ts b/src/config/layouts.ts new file mode 100644 index 0000000..88d1ec0 --- /dev/null +++ b/src/config/layouts.ts @@ -0,0 +1,54 @@ +import { getConfigLayout } from "@/utils/cache/local-storage"; + +/** 项目配置类型 */ +export interface LayoutSettings { + /** 是否显示 Settings Panel */ + showSettings: boolean; + /** 布局模式 */ + layoutMode: "left" | "top" | "left-top"; + /** 是否显示标签栏 */ + showTagsView: boolean; + /** 是否显示 Logo */ + showLogo: boolean; + /** 是否固定 Header */ + fixedHeader: boolean; + /** 是否显示页脚 Footer */ + showFooter: boolean; + /** 是否显示消息通知 */ + showNotify: boolean; + /** 是否显示切换主题按钮 */ + showThemeSwitch: boolean; + /** 是否显示全屏按钮 */ + showScreenfull: boolean; + /** 是否显示搜索按钮 */ + showSearchMenu: boolean; + /** 是否缓存标签栏 */ + cacheTagsView: boolean; + /** 开启系统水印 */ + showWatermark: boolean; + /** 是否显示灰色模式 */ + showGreyMode: boolean; + /** 是否显示色弱模式 */ + showColorWeakness: boolean; +} + +/** 默认配置 */ +const defaultSettings: LayoutSettings = { + layoutMode: "left", + showSettings: true, + showTagsView: true, + fixedHeader: true, + showFooter: true, + showLogo: true, + showNotify: true, + showThemeSwitch: true, + showScreenfull: true, + showSearchMenu: true, + cacheTagsView: false, + showWatermark: false, + showGreyMode: false, + showColorWeakness: false +}; + +/** 项目配置 */ +export const layoutSettings: LayoutSettings = { ...defaultSettings, ...getConfigLayout() }; diff --git a/src/config/route.ts b/src/config/route.ts new file mode 100644 index 0000000..bf87f27 --- /dev/null +++ b/src/config/route.ts @@ -0,0 +1,28 @@ +/** 动态路由配置 */ +interface RouteSettings { + /** + * 是否开启动态路由功能? + * 1. 开启后需要后端配合,在查询用户详情接口返回当前用户可以用来判断并加载动态路由的字段(该项目用的是角色 roles 字段) + * 2. 假如项目不需要根据不同的用户来显示不同的页面,则应该将 async: false + */ + async: boolean; + /** 当动态路由功能关闭时: + * 1. 应该将所有路由都写到常驻路由里面(表明所有登陆的用户能访问的页面都是一样的) + * 2. 系统自动给当前登录用户赋值一个没有任何作用的默认角色 + */ + defaultRoles: Array; + /** + * 是否开启三级及其以上路由缓存功能? + * 1. 开启后会进行路由降级(把三级及其以上的路由转化为二级路由) + * 2. 由于都会转成二级路由,所以二级及其以上路由有内嵌子路由将会失效 + */ + thirdLevelRouteCache: boolean; +} + +const routeSettings: RouteSettings = { + async: true, + defaultRoles: ["DEFAULT_ROLE"], + thirdLevelRouteCache: false +}; + +export default routeSettings; diff --git a/src/config/white-list.ts b/src/config/white-list.ts new file mode 100644 index 0000000..0c1287f --- /dev/null +++ b/src/config/white-list.ts @@ -0,0 +1,15 @@ +import { type RouteLocationNormalized } from "vue-router"; + +/** 免登录白名单(匹配路由 path) */ +const whiteListByPath: string[] = ["/login"]; + +/** 免登录白名单(匹配路由 name) */ +const whiteListByName: string[] = []; + +/** 判断是否在白名单 */ +const isWhiteList = (to: RouteLocationNormalized) => { + // path 和 name 任意一个匹配上即可 + return whiteListByPath.indexOf(to.path) !== -1 || whiteListByName.indexOf(to.name as any) !== -1; +}; + +export default isWhiteList; diff --git a/src/constants/app-key.ts b/src/constants/app-key.ts new file mode 100644 index 0000000..85abb93 --- /dev/null +++ b/src/constants/app-key.ts @@ -0,0 +1,13 @@ +/** 设备类型 */ +export enum DeviceEnum { + Mobile, + Desktop +} + +/** 侧边栏打开状态常量 */ +export const SIDEBAR_OPENED = "opened"; +/** 侧边栏关闭状态常量 */ +export const SIDEBAR_CLOSED = "closed"; + +export type SidebarOpened = typeof SIDEBAR_OPENED; +export type SidebarClosed = typeof SIDEBAR_CLOSED; diff --git a/src/constants/cache-key.ts b/src/constants/cache-key.ts new file mode 100644 index 0000000..dd24cbd --- /dev/null +++ b/src/constants/cache-key.ts @@ -0,0 +1,13 @@ +const SYSTEM_NAME = "v3-admin-vite"; + +/** 缓存数据时用到的 Key */ +class CacheKey { + static readonly TOKEN = `${SYSTEM_NAME}-token-key`; + static readonly CONFIG_LAYOUT = `${SYSTEM_NAME}-config-layout-key`; + static readonly SIDEBAR_STATUS = `${SYSTEM_NAME}-sidebar-status-key`; + static readonly ACTIVE_THEME_NAME = `${SYSTEM_NAME}-active-theme-name-key`; + static readonly VISITED_VIEWS = `${SYSTEM_NAME}-visited-views-key`; + static readonly CACHED_VIEWS = `${SYSTEM_NAME}-cached-views-key`; +} + +export default CacheKey; diff --git a/src/directives/index.ts b/src/directives/index.ts new file mode 100644 index 0000000..d209820 --- /dev/null +++ b/src/directives/index.ts @@ -0,0 +1,7 @@ +import { type App } from "vue"; +import { permission } from "./permission"; + +/** 挂载自定义指令 */ +export function loadDirectives(app: App) { + app.directive("permission", permission); +} diff --git a/src/directives/permission/index.ts b/src/directives/permission/index.ts new file mode 100644 index 0000000..1089ffe --- /dev/null +++ b/src/directives/permission/index.ts @@ -0,0 +1,17 @@ +import { type Directive } from "vue"; +import { useUserStoreHook } from "@/store/modules/user"; + +/** 权限指令,和权限判断函数 checkPermission 功能类似 */ +export const permission: Directive = { + mounted(el, binding) { + const { value: permissionRoles } = binding; + const { roles } = useUserStoreHook(); + if (Array.isArray(permissionRoles) && permissionRoles.length > 0) { + const hasPermission = roles.some((role) => permissionRoles.includes(role)); + // hasPermission || (el.style.display = "none") // 隐藏 + hasPermission || el.parentNode?.removeChild(el); // 销毁 + } else { + throw new Error(`need roles! Like v-permission="['admin','editor']"`); + } + } +}; diff --git a/src/hooks/useFetchSelect.ts b/src/hooks/useFetchSelect.ts new file mode 100644 index 0000000..6e6a71b --- /dev/null +++ b/src/hooks/useFetchSelect.ts @@ -0,0 +1,53 @@ +import { ref, onMounted } from "vue"; + +type OptionValue = string | number; + +/** Select 需要的数据格式 */ +interface SelectOption { + value: OptionValue; + label: string; + disabled?: boolean; +} + +/** 接口响应格式 */ +interface ApiData { + code: number; + data: SelectOption[]; + message: string; +} + +/** 入参格式,暂时只需要传递 api 函数即可 */ +interface FetchSelectProps { + api: () => Promise; +} + +export function useFetchSelect(props: FetchSelectProps) { + const { api } = props; + + const loading = ref(false); + const options = ref([]); + const value = ref(""); + + /** 调用接口获取数据 */ + const loadData = () => { + loading.value = true; + options.value = []; + api() + .then((res) => { + options.value = res.data; + }) + .finally(() => { + loading.value = false; + }); + }; + + onMounted(() => { + loadData(); + }); + + return { + loading, + options, + value + }; +} diff --git a/src/hooks/useFullscreenLoading.ts b/src/hooks/useFullscreenLoading.ts new file mode 100644 index 0000000..6574f62 --- /dev/null +++ b/src/hooks/useFullscreenLoading.ts @@ -0,0 +1,35 @@ +import { type LoadingOptions, ElLoading } from "element-plus"; + +const defaultOptions = { + lock: true, + text: "加载中..." +}; + +interface LoadingInstance { + close: () => void; +} + +interface UseFullscreenLoading { + ReturnType>( + fn: T, + options?: LoadingOptions + ): (...args: Parameters) => Promise>; +} + +/** + * 传入一个函数 fn,在它执行周期内,加上「全屏」loading + * @param fn 要执行的函数 + * @param options LoadingOptions + * @returns 返回一个新的函数,该函数返回一个 Promise + */ +export const useFullscreenLoading: UseFullscreenLoading = (fn, options = {}) => { + let loadingInstance: LoadingInstance; + return async (...args) => { + try { + loadingInstance = ElLoading.service({ ...defaultOptions, ...options }); + return await fn(...args); + } finally { + loadingInstance?.close(); + } + }; +}; diff --git a/src/hooks/usePagination.ts b/src/hooks/usePagination.ts new file mode 100644 index 0000000..7fb0901 --- /dev/null +++ b/src/hooks/usePagination.ts @@ -0,0 +1,41 @@ +import { reactive } from "vue"; + +interface DefaultPaginationData { + total: number; + currentPage: number; + pageSizes: number[]; + pageSize: number; + layout: string; +} + +interface PaginationData { + total?: number; + currentPage?: number; + pageSizes?: number[]; + pageSize?: number; + layout?: string; +} + +/** 默认的分页参数 */ +const defaultPaginationData: DefaultPaginationData = { + total: 0, + currentPage: 1, + pageSizes: [10, 20, 50], + pageSize: 10, + layout: "total, sizes, prev, pager, next, jumper" +}; + +export function usePagination(initialPaginationData: PaginationData = {}) { + /** 合并分页参数 */ + const paginationData = reactive({ ...defaultPaginationData, ...initialPaginationData }); + /** 改变当前页码 */ + const handleCurrentChange = (value: number) => { + paginationData.currentPage = value; + }; + /** 改变页面大小 */ + const handleSizeChange = (value: number) => { + paginationData.pageSize = value; + }; + + return { paginationData, handleCurrentChange, handleSizeChange }; +} diff --git a/src/hooks/useRouteListener.ts b/src/hooks/useRouteListener.ts new file mode 100644 index 0000000..9529cb6 --- /dev/null +++ b/src/hooks/useRouteListener.ts @@ -0,0 +1,48 @@ +import { onBeforeUnmount } from "vue"; +import mitt, { type Handler } from "mitt"; +import { type RouteLocationNormalized } from "vue-router"; + +/** 回调函数的类型 */ +type Callback = (route: RouteLocationNormalized) => void; + +const emitter = mitt(); +const key = Symbol("ROUTE_CHANGE"); +let latestRoute: RouteLocationNormalized; + +/** 设置最新的路由信息,触发路由变化事件 */ +export const setRouteChange = (to: RouteLocationNormalized) => { + // 触发事件 + emitter.emit(key, to); + // 缓存最新的路由信息 + latestRoute = to; +}; + +/** 单独监听路由会浪费渲染性能,使用发布订阅模式去进行分发管理 */ +export function useRouteListener() { + /** 回调函数集合 */ + const callbackList: Callback[] = []; + + /** 监听路由变化(可以选择立即执行) */ + const listenerRouteChange = (callback: Callback, immediate = false) => { + // 缓存回调函数 + callbackList.push(callback); + // 监听事件 + emitter.on(key, callback as Handler); + // 可以选择立即执行一次回调函数 + immediate && latestRoute && callback(latestRoute); + }; + + /** 移除路由变化事件监听器 */ + const removeRouteListener = (callback: Callback) => { + emitter.off(key, callback as Handler); + }; + + /** 组件销毁前移除监听器 */ + onBeforeUnmount(() => { + for (let i = 0; i < callbackList.length; i++) { + removeRouteListener(callbackList[i]); + } + }); + + return { listenerRouteChange, removeRouteListener }; +} diff --git a/src/hooks/useTheme.ts b/src/hooks/useTheme.ts new file mode 100644 index 0000000..0226de4 --- /dev/null +++ b/src/hooks/useTheme.ts @@ -0,0 +1,57 @@ +import { ref, watchEffect } from "vue"; +import { getActiveThemeName, setActiveThemeName } from "@/utils/cache/local-storage"; + +const DEFAULT_THEME_NAME = "normal"; +type DefaultThemeName = typeof DEFAULT_THEME_NAME; + +/** 注册的主题名称, 其中 DefaultThemeName 是必填的 */ +export type ThemeName = DefaultThemeName | "dark" | "dark-blue"; + +interface ThemeList { + title: string; + name: ThemeName; +} + +/** 主题列表 */ +const themeList: ThemeList[] = [ + { + title: "默认", + name: DEFAULT_THEME_NAME + }, + { + title: "黑暗", + name: "dark" + }, + { + title: "深蓝", + name: "dark-blue" + } +]; + +/** 正在应用的主题名称 */ +const activeThemeName = ref(getActiveThemeName() || DEFAULT_THEME_NAME); + +/** 设置主题 */ +const setTheme = (value: ThemeName) => { + activeThemeName.value = value; +}; + +/** 在 html 根元素上挂载 class */ +const setHtmlRootClassName = (value: ThemeName) => { + document.documentElement.className = value; +}; + +/** 初始化 */ +const initTheme = () => { + // watchEffect 来收集副作用 + watchEffect(() => { + const value = activeThemeName.value; + setHtmlRootClassName(value); + setActiveThemeName(value); + }); +}; + +/** 主题 hook */ +export function useTheme() { + return { themeList, activeThemeName, initTheme, setTheme }; +} diff --git a/src/hooks/useTitle.ts b/src/hooks/useTitle.ts new file mode 100644 index 0000000..eabf56d --- /dev/null +++ b/src/hooks/useTitle.ts @@ -0,0 +1,23 @@ +import { ref, watch } from "vue"; + +/** 项目标题 */ +const VITE_APP_TITLE = import.meta.env.VITE_APP_TITLE ?? "V3 Admin Vite"; + +/** 动态标题 */ +const dynamicTitle = ref(""); + +/** 设置标题 */ +const setTitle = (title?: string) => { + dynamicTitle.value = title ? `${VITE_APP_TITLE} | ${title}` : VITE_APP_TITLE; +}; + +/** 监听标题变化 */ +watch(dynamicTitle, (value, oldValue) => { + if (document && value !== oldValue) { + document.title = value; + } +}); + +export function useTitle() { + return { setTitle }; +} diff --git a/src/hooks/useWatermark.ts b/src/hooks/useWatermark.ts new file mode 100644 index 0000000..826318d --- /dev/null +++ b/src/hooks/useWatermark.ts @@ -0,0 +1,236 @@ +import { type Ref, onBeforeUnmount, ref } from "vue"; +import { debounce } from "lodash-es"; + +type Observer = { + watermarkElMutationObserver?: MutationObserver; + parentElMutationObserver?: MutationObserver; + parentElResizeObserver?: ResizeObserver; +}; + +type DefaultConfig = typeof defaultConfig; + +/** 默认配置 */ +const defaultConfig = { + /** 防御(默认开启,能防御水印被删除或隐藏,但可能会有性能损耗) */ + defense: true, + /** 文本颜色 */ + color: "#c0c4cc", + /** 文本透明度 */ + opacity: 0.5, + /** 文本字体大小 */ + size: 16, + /** 文本字体 */ + family: "serif", + /** 文本倾斜角度 */ + angle: -20, + /** 一处水印所占宽度(数值越大水印密度越低) */ + width: 300, + /** 一处水印所占高度(数值越大水印密度越低) */ + height: 200 +}; + +/** body 元素 */ +const bodyEl = ref(document.body); + +/** + * 创建水印 + * 1. 可以选择传入挂载水印的容器元素,默认是 body + * 2. 做了水印防御,能有效防御别人打开控制台删除或隐藏水印 + */ +export function useWatermark(parentEl: Ref = bodyEl) { + /** 备份文本 */ + let backupText: string; + /** 最终配置 */ + let mergeConfig: DefaultConfig; + /** 水印元素 */ + let watermarkEl: HTMLElement | null = null; + /** 观察器 */ + const observer: Observer = { + watermarkElMutationObserver: undefined, + parentElMutationObserver: undefined, + parentElResizeObserver: undefined + }; + + /** 设置水印 */ + const setWatermark = (text: string, config: Partial = {}) => { + if (!parentEl.value) { + console.warn("请在 DOM 挂载完成后再调用 setWatermark 方法设置水印"); + return; + } + // 备份文本 + backupText = text; + // 合并配置 + mergeConfig = { ...defaultConfig, ...config }; + // 创建或更新水印元素 + watermarkEl ? updateWatermarkEl() : createWatermarkEl(); + // 监听水印元素和容器元素的变化 + addElListener(parentEl.value); + }; + + /** 创建水印元素 */ + const createWatermarkEl = () => { + const isBody = parentEl.value!.tagName.toLowerCase() === bodyEl.value.tagName.toLowerCase(); + const watermarkElPosition = isBody ? "fixed" : "absolute"; + const parentElPosition = isBody ? "" : "relative"; + watermarkEl = document.createElement("div"); + watermarkEl.style.pointerEvents = "none"; + watermarkEl.style.top = "0"; + watermarkEl.style.left = "0"; + watermarkEl.style.position = watermarkElPosition; + watermarkEl.style.zIndex = "99999"; + const { clientWidth, clientHeight } = parentEl.value!; + updateWatermarkEl({ width: clientWidth, height: clientHeight }); + // 设置水印容器为相对定位 + parentEl.value!.style.position = parentElPosition; + // 将水印元素添加到水印容器中 + parentEl.value!.appendChild(watermarkEl); + }; + + /** 更新水印元素 */ + const updateWatermarkEl = ( + options: Partial<{ + width: number; + height: number; + }> = {} + ) => { + if (!watermarkEl) return; + backupText && (watermarkEl.style.background = `url(${createBase64()}) left top repeat`); + options.width && (watermarkEl.style.width = `${options.width}px`); + options.height && (watermarkEl.style.height = `${options.height}px`); + }; + + /** 创建 base64 图片 */ + const createBase64 = () => { + const { color, opacity, size, family, angle, width, height } = mergeConfig; + const canvasEl = document.createElement("canvas"); + canvasEl.width = width; + canvasEl.height = height; + const ctx = canvasEl.getContext("2d"); + if (ctx) { + ctx.fillStyle = color; + ctx.globalAlpha = opacity; + ctx.font = `${size}px ${family}`; + ctx.rotate((Math.PI / 180) * angle); + ctx.fillText(backupText, 0, height / 2); + } + return canvasEl.toDataURL(); + }; + + /** 清除水印 */ + const clearWatermark = () => { + if (!parentEl.value || !watermarkEl) return; + // 移除对水印元素和容器元素的监听 + removeListener(); + // 移除水印元素 + try { + parentEl.value.removeChild(watermarkEl); + } catch { + // 比如在无防御情况下,用户打开控制台删除了这个元素 + console.warn("水印元素已不存在,请重新创建"); + } finally { + watermarkEl = null; + } + }; + + /** 刷新水印(防御时调用) */ + const updateWatermark = debounce(() => { + clearWatermark(); + createWatermarkEl(); + addElListener(parentEl.value!); + }, 100); + + /** 监听水印元素和容器元素的变化(DOM 变化 & DOM 大小变化) */ + const addElListener = (targetNode: HTMLElement) => { + // 判断是否开启防御 + if (mergeConfig.defense) { + // 防止重复添加监听 + if (!observer.watermarkElMutationObserver && !observer.parentElMutationObserver) { + // 监听 DOM 变化 + addMutationListener(targetNode); + } + } else { + // 无防御时不需要 mutation 监听 + removeListener("mutation"); + } + // 防止重复添加监听 + if (!observer.parentElResizeObserver) { + // 监听 DOM 大小变化 + addResizeListener(targetNode); + } + }; + + /** 移除对水印元素和容器元素的监听,传参可指定要移除哪个监听,不传默认移除全部监听 */ + const removeListener = (kind: "mutation" | "resize" | "all" = "all") => { + // 移除 mutation 监听 + if (kind === "mutation" || kind === "all") { + observer.watermarkElMutationObserver?.disconnect(); + observer.watermarkElMutationObserver = undefined; + observer.parentElMutationObserver?.disconnect(); + observer.parentElMutationObserver = undefined; + } + // 移除 resize 监听 + if (kind === "resize" || kind === "all") { + observer.parentElResizeObserver?.disconnect(); + observer.parentElResizeObserver = undefined; + } + }; + + /** 监听 DOM 变化 */ + const addMutationListener = (targetNode: HTMLElement) => { + // 当观察到变动时执行的回调 + const mutationCallback = debounce((mutationList: MutationRecord[]) => { + // 水印的防御(防止用户手动删除水印元素或通过 CSS 隐藏水印) + mutationList.forEach( + debounce((mutation: MutationRecord) => { + switch (mutation.type) { + case "attributes": + mutation.target === watermarkEl && updateWatermark(); + break; + case "childList": + mutation.removedNodes.forEach((item) => { + item === watermarkEl && targetNode.appendChild(watermarkEl); + }); + break; + } + }, 100) + ); + }, 100); + // 创建观察器实例并传入回调 + observer.watermarkElMutationObserver = new MutationObserver(mutationCallback); + observer.parentElMutationObserver = new MutationObserver(mutationCallback); + // 以上述配置开始观察目标节点 + observer.watermarkElMutationObserver.observe(watermarkEl!, { + // 观察目标节点属性是否变动,默认为 true + attributes: true, + // 观察目标子节点是否有添加或者删除,默认为 false + childList: false, + // 是否拓展到观察所有后代节点,默认为 false + subtree: false + }); + observer.parentElMutationObserver.observe(targetNode, { + attributes: false, + childList: true, + subtree: false + }); + }; + + /** 监听 DOM 大小变化 */ + const addResizeListener = (targetNode: HTMLElement) => { + // 当 targetNode 元素大小变化时去更新整个水印的大小 + const resizeCallback = debounce(() => { + const { clientWidth, clientHeight } = targetNode; + updateWatermarkEl({ width: clientWidth, height: clientHeight }); + }, 500); + // 创建一个观察器实例并传入回调 + observer.parentElResizeObserver = new ResizeObserver(resizeCallback); + // 开始观察目标节点 + observer.parentElResizeObserver.observe(targetNode); + }; + + /** 在组件卸载前移除水印以及各种监听 */ + onBeforeUnmount(() => { + clearWatermark(); + }); + + return { setWatermark, clearWatermark }; +} diff --git a/src/icons/index.ts b/src/icons/index.ts new file mode 100644 index 0000000..a3e7766 --- /dev/null +++ b/src/icons/index.ts @@ -0,0 +1,7 @@ +import { type App } from "vue"; +import SvgIcon from "@/components/SvgIcon/index.vue"; // Svg Component +import "virtual:svg-icons-register"; + +export function loadSvg(app: App) { + app.component("SvgIcon", SvgIcon); +} diff --git a/src/icons/svg/404.svg b/src/icons/svg/404.svg new file mode 100644 index 0000000..1319e77 --- /dev/null +++ b/src/icons/svg/404.svg @@ -0,0 +1 @@ + diff --git a/src/icons/svg/bug.svg b/src/icons/svg/bug.svg new file mode 100644 index 0000000..9b35ad8 --- /dev/null +++ b/src/icons/svg/bug.svg @@ -0,0 +1 @@ + diff --git a/src/icons/svg/component.svg b/src/icons/svg/component.svg new file mode 100644 index 0000000..94280f4 --- /dev/null +++ b/src/icons/svg/component.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/svg/dashboard.svg b/src/icons/svg/dashboard.svg new file mode 100644 index 0000000..c8863a0 --- /dev/null +++ b/src/icons/svg/dashboard.svg @@ -0,0 +1 @@ + diff --git a/src/icons/svg/fullscreen-exit.svg b/src/icons/svg/fullscreen-exit.svg new file mode 100644 index 0000000..42aa505 --- /dev/null +++ b/src/icons/svg/fullscreen-exit.svg @@ -0,0 +1 @@ + diff --git a/src/icons/svg/fullscreen.svg b/src/icons/svg/fullscreen.svg new file mode 100644 index 0000000..a97be9e --- /dev/null +++ b/src/icons/svg/fullscreen.svg @@ -0,0 +1 @@ + diff --git a/src/icons/svg/keyboard-down.svg b/src/icons/svg/keyboard-down.svg new file mode 100644 index 0000000..de62543 --- /dev/null +++ b/src/icons/svg/keyboard-down.svg @@ -0,0 +1 @@ + diff --git a/src/icons/svg/keyboard-enter.svg b/src/icons/svg/keyboard-enter.svg new file mode 100644 index 0000000..819b87e --- /dev/null +++ b/src/icons/svg/keyboard-enter.svg @@ -0,0 +1 @@ + diff --git a/src/icons/svg/keyboard-esc.svg b/src/icons/svg/keyboard-esc.svg new file mode 100644 index 0000000..33256bf --- /dev/null +++ b/src/icons/svg/keyboard-esc.svg @@ -0,0 +1 @@ + diff --git a/src/icons/svg/keyboard-up.svg b/src/icons/svg/keyboard-up.svg new file mode 100644 index 0000000..e84519a --- /dev/null +++ b/src/icons/svg/keyboard-up.svg @@ -0,0 +1 @@ + diff --git a/src/icons/svg/link.svg b/src/icons/svg/link.svg new file mode 100644 index 0000000..9ac0b2c --- /dev/null +++ b/src/icons/svg/link.svg @@ -0,0 +1 @@ + diff --git a/src/icons/svg/lock.svg b/src/icons/svg/lock.svg new file mode 100644 index 0000000..21a7582 --- /dev/null +++ b/src/icons/svg/lock.svg @@ -0,0 +1 @@ + diff --git a/src/icons/svg/menu.svg b/src/icons/svg/menu.svg new file mode 100644 index 0000000..5321191 --- /dev/null +++ b/src/icons/svg/menu.svg @@ -0,0 +1 @@ + diff --git a/src/icons/svg/search.svg b/src/icons/svg/search.svg new file mode 100644 index 0000000..691a5f1 --- /dev/null +++ b/src/icons/svg/search.svg @@ -0,0 +1 @@ + diff --git a/src/icons/svg/unocss.svg b/src/icons/svg/unocss.svg new file mode 100644 index 0000000..5eaef35 --- /dev/null +++ b/src/icons/svg/unocss.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/layouts/LeftMode.vue b/src/layouts/LeftMode.vue new file mode 100644 index 0000000..e48ed2c --- /dev/null +++ b/src/layouts/LeftMode.vue @@ -0,0 +1,168 @@ + + + + + diff --git a/src/layouts/LeftTopMode.vue b/src/layouts/LeftTopMode.vue new file mode 100644 index 0000000..246fb8d --- /dev/null +++ b/src/layouts/LeftTopMode.vue @@ -0,0 +1,110 @@ + + + + + diff --git a/src/layouts/TopMode.vue b/src/layouts/TopMode.vue new file mode 100644 index 0000000..3d4a608 --- /dev/null +++ b/src/layouts/TopMode.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/src/layouts/components/AppMain.vue b/src/layouts/components/AppMain.vue new file mode 100644 index 0000000..81b4e9e --- /dev/null +++ b/src/layouts/components/AppMain.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/src/layouts/components/Breadcrumb/index.vue b/src/layouts/components/Breadcrumb/index.vue new file mode 100644 index 0000000..30681a1 --- /dev/null +++ b/src/layouts/components/Breadcrumb/index.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/src/layouts/components/CompConsumer/index.ts b/src/layouts/components/CompConsumer/index.ts new file mode 100644 index 0000000..20fdad1 --- /dev/null +++ b/src/layouts/components/CompConsumer/index.ts @@ -0,0 +1,67 @@ +import { type VNode, cloneVNode, createVNode, defineComponent, h, KeepAlive } from "vue"; +import { useRoute } from "vue-router"; +import { useTagsViewStore } from "@/store/modules/tags-view"; + +interface CompConsumerProps { + component: VNode; +} + +/** 定义 compMap 对象,用于存储路由名称和对应的组件 */ +const compMap = new Map(); + +/** + * CompConsumer 组件 + * 用法:替换 标签以及内部代码,变成: + * 优点:缓存路由时只需写路由 Name,无需再写组件 Name + * 缺点:当路由表有动态路由匹配时(指向同一个组件),会出现复用组件的情况(例如修改 /info/1 时 /info/2 也会跟着改变) + */ +export const CompConsumer = defineComponent( + (props: CompConsumerProps) => { + const tagsViewStore = useTagsViewStore(); + const route = useRoute(); + return () => { + // 获取传入的组件 + const component = props.component; + // 判断当前是否包含 name,如果不包含 name,那就直接处理掉 name + if (!route.name) return component; + // 获取当前组件的名称 + const compName = (component.type as any)?.name; + // 获取当前路由的名称 + const routeName = route.name as string; + let Comp: VNode; + // 检查 compMap 中是否已经存在对应的组件 + if (compMap.has(routeName)) { + // 如果存在,则直接使用该组件进行渲染 + Comp = compMap.get(routeName)!; + } else { + // 如果不存在,则克隆传入的组件并创建一个新的组件,将其添加到 compMap 中 + const node = cloneVNode(component); + if (compName && compName === routeName) { + (node.type as any).name = `__${compName}__CUSTOM_NAME`; + } + // @ts-expect-error this is VNode + Comp = defineComponent({ + name: routeName, + setup() { + return () => node; + } + }); + compMap.set(routeName, Comp); + } + // 使用 createVNode 函数创建一个 KeepAlive 组件,并缓存 cachedViews 数组中对应的组件 + return createVNode( + KeepAlive, + { + include: tagsViewStore.cachedViews + }, + { + default: () => h(Comp) + } + ); + }; + }, + { + name: "CompConsumer", + props: ["component"] + } +); diff --git a/src/layouts/components/Footer/index.vue b/src/layouts/components/Footer/index.vue new file mode 100644 index 0000000..bb70dca --- /dev/null +++ b/src/layouts/components/Footer/index.vue @@ -0,0 +1,18 @@ + + + + + diff --git a/src/layouts/components/Hamburger/index.vue b/src/layouts/components/Hamburger/index.vue new file mode 100644 index 0000000..9f62ad1 --- /dev/null +++ b/src/layouts/components/Hamburger/index.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/src/layouts/components/Logo/index.vue b/src/layouts/components/Logo/index.vue new file mode 100644 index 0000000..ab2e22a --- /dev/null +++ b/src/layouts/components/Logo/index.vue @@ -0,0 +1,67 @@ + + + + + diff --git a/src/layouts/components/NavigationBar/index.vue b/src/layouts/components/NavigationBar/index.vue new file mode 100644 index 0000000..3944f64 --- /dev/null +++ b/src/layouts/components/NavigationBar/index.vue @@ -0,0 +1,132 @@ + + + + + diff --git a/src/layouts/components/RightPanel/index.vue b/src/layouts/components/RightPanel/index.vue new file mode 100644 index 0000000..0179a81 --- /dev/null +++ b/src/layouts/components/RightPanel/index.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/src/layouts/components/Settings/SelectLayoutMode.vue b/src/layouts/components/Settings/SelectLayoutMode.vue new file mode 100644 index 0000000..574f451 --- /dev/null +++ b/src/layouts/components/Settings/SelectLayoutMode.vue @@ -0,0 +1,106 @@ + + + + + diff --git a/src/layouts/components/Settings/index.vue b/src/layouts/components/Settings/index.vue new file mode 100644 index 0000000..4597cff --- /dev/null +++ b/src/layouts/components/Settings/index.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/src/layouts/components/Sidebar/SidebarItem.vue b/src/layouts/components/Sidebar/SidebarItem.vue new file mode 100644 index 0000000..40247ed --- /dev/null +++ b/src/layouts/components/Sidebar/SidebarItem.vue @@ -0,0 +1,120 @@ + + + + + diff --git a/src/layouts/components/Sidebar/SidebarItemLink.vue b/src/layouts/components/Sidebar/SidebarItemLink.vue new file mode 100644 index 0000000..3912e6a --- /dev/null +++ b/src/layouts/components/Sidebar/SidebarItemLink.vue @@ -0,0 +1,18 @@ + + + diff --git a/src/layouts/components/Sidebar/index.vue b/src/layouts/components/Sidebar/index.vue new file mode 100644 index 0000000..ee18939 --- /dev/null +++ b/src/layouts/components/Sidebar/index.vue @@ -0,0 +1,171 @@ + + + + + diff --git a/src/layouts/components/TagsView/ScrollPane.vue b/src/layouts/components/TagsView/ScrollPane.vue new file mode 100644 index 0000000..89f1ce6 --- /dev/null +++ b/src/layouts/components/TagsView/ScrollPane.vue @@ -0,0 +1,154 @@ + + + + + diff --git a/src/layouts/components/TagsView/index.vue b/src/layouts/components/TagsView/index.vue new file mode 100644 index 0000000..52f91b5 --- /dev/null +++ b/src/layouts/components/TagsView/index.vue @@ -0,0 +1,268 @@ + + + + + diff --git a/src/layouts/components/index.ts b/src/layouts/components/index.ts new file mode 100644 index 0000000..ea6db87 --- /dev/null +++ b/src/layouts/components/index.ts @@ -0,0 +1,7 @@ +export { default as AppMain } from "./AppMain.vue"; +export { default as NavigationBar } from "./NavigationBar/index.vue"; +export { default as Settings } from "./Settings/index.vue"; +export { default as Sidebar } from "./Sidebar/index.vue"; +export { default as TagsView } from "./TagsView/index.vue"; +export { default as RightPanel } from "./RightPanel/index.vue"; +export { default as Logo } from "./Logo/index.vue"; diff --git a/src/layouts/hooks/useResize.ts b/src/layouts/hooks/useResize.ts new file mode 100644 index 0000000..02eeb48 --- /dev/null +++ b/src/layouts/hooks/useResize.ts @@ -0,0 +1,52 @@ +import { onBeforeMount, onMounted, onBeforeUnmount } from "vue"; +import { useAppStore } from "@/store/modules/app"; +import { useRouteListener } from "@/hooks/useRouteListener"; +import { DeviceEnum } from "@/constants/app-key"; + +/** 参考 Bootstrap 的响应式设计将最大移动端宽度设置为 992 */ +const MAX_MOBILE_WIDTH = 992; + +/** 根据浏览器宽度变化,变换 Layout 布局 */ +export default () => { + const appStore = useAppStore(); + const { listenerRouteChange } = useRouteListener(); + + /** 用于判断当前设备是否为移动端 */ + const _isMobile = () => { + const rect = document.body.getBoundingClientRect(); + return rect.width - 1 < MAX_MOBILE_WIDTH; + }; + + /** 用于处理窗口大小变化事件 */ + const _resizeHandler = () => { + if (!document.hidden) { + const isMobile = _isMobile(); + appStore.toggleDevice(isMobile ? DeviceEnum.Mobile : DeviceEnum.Desktop); + isMobile && appStore.closeSidebar(true); + } + }; + /** 监听路由变化,根据设备类型调整布局 */ + listenerRouteChange(() => { + if (appStore.device === DeviceEnum.Mobile && appStore.sidebar.opened) { + appStore.closeSidebar(false); + } + }); + + /** 在组件挂载前添加窗口大小变化事件监听器 */ + onBeforeMount(() => { + window.addEventListener("resize", _resizeHandler); + }); + + /** 在组件挂载后根据窗口大小判断设备类型并调整布局 */ + onMounted(() => { + if (_isMobile()) { + appStore.toggleDevice(DeviceEnum.Mobile); + appStore.closeSidebar(true); + } + }); + + /** 在组件卸载前移除窗口大小变化事件监听器 */ + onBeforeUnmount(() => { + window.removeEventListener("resize", _resizeHandler); + }); +}; diff --git a/src/layouts/index.vue b/src/layouts/index.vue new file mode 100644 index 0000000..1291000 --- /dev/null +++ b/src/layouts/index.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..2e17f61 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,33 @@ +// core +import { createApp } from "vue"; +import App from "@/App.vue"; +import store from "@/store"; +import router from "@/router"; +import "@/router/permission"; +// load +import { loadSvg } from "@/icons"; +import { loadPlugins } from "@/plugins"; +import { loadDirectives } from "@/directives"; +// css +import "uno.css"; +import "normalize.css"; +import "element-plus/dist/index.css"; +import "ant-design-vue/dist/reset.css"; +import "element-plus/theme-chalk/dark/css-vars.css"; +import "vxe-table/lib/style.css"; +import "vxe-table-plugin-element/dist/style.css"; +import "@/styles/index.scss"; + +const app = createApp(App); + +/** 加载插件 */ +loadPlugins(app); +/** 加载全局 SVG */ +loadSvg(app); +/** 加载自定义指令 */ +loadDirectives(app); + +app.use(store).use(router); +router.isReady().then(() => { + app.mount("#app"); +}); diff --git a/src/plugins/element-plus-icon/index.ts b/src/plugins/element-plus-icon/index.ts new file mode 100644 index 0000000..62d08dd --- /dev/null +++ b/src/plugins/element-plus-icon/index.ts @@ -0,0 +1,9 @@ +import { type App } from "vue"; +import * as ElementPlusIconsVue from "@element-plus/icons-vue"; + +export function loadElementPlusIcon(app: App) { + /** 注册所有 Element Plus Icon */ + for (const [key, component] of Object.entries(ElementPlusIconsVue)) { + app.component(key, component); + } +} diff --git a/src/plugins/element-plus/index.ts b/src/plugins/element-plus/index.ts new file mode 100644 index 0000000..a9a6761 --- /dev/null +++ b/src/plugins/element-plus/index.ts @@ -0,0 +1,10 @@ +import { type App } from "vue"; +import ElementPlus from "element-plus"; +import AntDesignVue from "ant-design-vue"; + +export function loadElementPlus(app: App) { + /** Element Plus 组件完整引入 */ + app.use(ElementPlus); + /** Ant Design Vue */ + app.use(AntDesignVue); +} diff --git a/src/plugins/index.ts b/src/plugins/index.ts new file mode 100644 index 0000000..0602dc9 --- /dev/null +++ b/src/plugins/index.ts @@ -0,0 +1,10 @@ +import { type App } from "vue"; +import { loadElementPlus } from "./element-plus"; +import { loadElementPlusIcon } from "./element-plus-icon"; +import { loadVxeTable } from "./vxe-table"; + +export function loadPlugins(app: App) { + loadElementPlus(app); + loadElementPlusIcon(app); + loadVxeTable(app); +} diff --git a/src/plugins/vxe-table/index.ts b/src/plugins/vxe-table/index.ts new file mode 100644 index 0000000..7010f73 --- /dev/null +++ b/src/plugins/vxe-table/index.ts @@ -0,0 +1,66 @@ +import { type App } from "vue"; +// https://vxetable.cn/#/table/start/install +import VXETable from "vxe-table"; +// https://github.com/x-extends/vxe-table-plugin-element +import VXETablePluginElement from "vxe-table-plugin-element"; + +VXETable.use(VXETablePluginElement); + +/** 全局默认参数 */ +VXETable.setup({ + /** 全局尺寸 */ + size: "medium", + /** 全局 zIndex 起始值,如果项目的的 z-index 样式值过大时就需要跟随设置更大,避免被遮挡 */ + zIndex: 9999, + /** 版本号,对于某些带数据缓存的功能有用到,上升版本号可以用于重置数据 */ + version: 0, + /** 全局 loading 提示内容,如果为 null 则不显示文本 */ + loadingText: null, + table: { + showHeader: true, + showOverflow: "tooltip", + showHeaderOverflow: "tooltip", + autoResize: true, + // stripe: false, + border: "inner", + // round: false, + emptyText: "暂无数据", + rowConfig: { + isHover: true, + isCurrent: true + }, + columnConfig: { + resizable: false + }, + align: "center", + headerAlign: "center", + /** 行数据的唯一主键字段名 */ + rowId: "_VXE_ID" + }, + pager: { + // size: "medium", + /** 配套的样式 */ + perfect: false, + pageSize: 10, + pagerCount: 7, + pageSizes: [10, 20, 50], + layouts: ["Total", "PrevJump", "PrevPage", "Number", "NextPage", "NextJump", "Sizes", "FullJump"] + }, + modal: { + minWidth: 500, + minHeight: 400, + lockView: true, + mask: true, + // duration: 3000, + // marginSize: 20, + dblclickZoom: false, + showTitleOverflow: true, + transfer: true, + draggable: false + } +}); + +export function loadVxeTable(app: App) { + /** Vxe Table 组件完整引入 */ + app.use(VXETable); +} diff --git a/src/router/helper.ts b/src/router/helper.ts new file mode 100644 index 0000000..1c6215a --- /dev/null +++ b/src/router/helper.ts @@ -0,0 +1,69 @@ +import { + type Router, + type RouteRecordNormalized, + type RouteRecordRaw, + createRouter, + createWebHashHistory, + createWebHistory +} from "vue-router"; +import { cloneDeep, omit } from "lodash-es"; + +/** 路由模式 */ +export const history = + import.meta.env.VITE_ROUTER_HISTORY === "hash" + ? createWebHashHistory(import.meta.env.VITE_PUBLIC_PATH) + : createWebHistory(import.meta.env.VITE_PUBLIC_PATH); + +/** 路由降级(把三级及其以上的路由转化为二级路由) */ +export const flatMultiLevelRoutes = (routes: RouteRecordRaw[]) => { + const routesMirror = cloneDeep(routes); + routesMirror.forEach((route) => { + // 如果路由是三级及其以上路由,对其进行降级处理 + isMultipleRoute(route) && promoteRouteLevel(route); + }); + return routesMirror; +}; + +/** 判断路由层级是否大于 2 */ +const isMultipleRoute = (route: RouteRecordRaw) => { + const children = route.children; + if (children?.length) { + // 只要有一个子路由的 children 长度大于 0,就说明是三级及其以上路由 + return children.some((child) => child.children?.length); + } + return false; +}; + +/** 生成二级路由 */ +const promoteRouteLevel = (route: RouteRecordRaw) => { + // 创建 router 实例是为了获取到当前传入的 route 的所有路由信息 + let router: Router | null = createRouter({ + history, + routes: [route] + }); + const routes = router.getRoutes(); + // 在 addToChildren 函数中使用上面获取到的路由信息来更新 route 的 children + addToChildren(routes, route.children || [], route); + router = null; + // 转为二级路由后,去除所有子路由中的 children + route.children = route.children?.map((item) => omit(item, "children") as RouteRecordRaw); +}; + +/** 将给定的子路由添加到指定的路由模块中 */ +const addToChildren = (routes: RouteRecordNormalized[], children: RouteRecordRaw[], routeModule: RouteRecordRaw) => { + children.forEach((child) => { + const route = routes.find((item) => item.name === child.name); + if (route) { + // 初始化 routeModule 的 children + routeModule.children = routeModule.children || []; + // 如果 routeModule 的 children 属性中不包含该路由,则将其添加进去 + if (!routeModule.children.includes(route)) { + routeModule.children.push(route); + } + // 如果该子路由还有自己的子路由,则递归调用此函数将它们也添加进去 + if (child.children?.length) { + addToChildren(routes, child.children, routeModule); + } + } + }); +}; diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..0539011 --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,321 @@ +import { type RouteRecordRaw, createRouter } from "vue-router"; +import { history, flatMultiLevelRoutes } from "./helper"; +import routeSettings from "@/config/route"; + +const Layouts = () => import("@/layouts/index.vue"); + +/** + * 常驻路由 + * 除了 redirect/403/404/login 等隐藏页面,其他页面建议设置 Name 属性 + */ +export const constantRoutes: RouteRecordRaw[] = [ + { + path: "/redirect", + component: Layouts, + meta: { + hidden: true + }, + children: [ + { + path: "/redirect/:path(.*)", + component: () => import("@/views/redirect/index.vue") + } + ] + }, + { + path: "/403", + component: () => import("@/views/error-page/403.vue"), + meta: { + hidden: true + } + }, + { + path: "/404", + component: () => import("@/views/error-page/404.vue"), + meta: { + hidden: true + }, + alias: "/:pathMatch(.*)*" + }, + { + path: "/login", + component: () => import("@/views/login/index.vue"), + meta: { + hidden: true + } + }, + { + path: "/", + component: Layouts, + redirect: "/dashboard", + children: [ + { + path: "dashboard", + component: () => import("@/views/dashboard/index.vue"), + name: "Dashboard", + meta: { + title: "首页", + svgIcon: "dashboard", + affix: true + } + } + ] + }, + { + path: "/unocss", + component: Layouts, + redirect: "/unocss/index", + children: [ + { + path: "index", + component: () => import("@/views/unocss/index.vue"), + name: "UnoCSS", + meta: { + title: "UnoCSS", + svgIcon: "unocss" + } + } + ] + }, + { + path: "/link", + meta: { + title: "外链", + svgIcon: "link" + }, + children: [ + { + path: "https://juejin.cn/post/7089377403717287972", + component: () => {}, + name: "Link1", + meta: { + title: "中文文档" + } + }, + { + path: "https://juejin.cn/column/7207659644487139387", + component: () => {}, + name: "Link2", + meta: { + title: "新手教程" + } + } + ] + }, + { + path: "/table", + component: Layouts, + redirect: "/table/element-plus", + name: "Table", + meta: { + title: "表格", + elIcon: "Grid" + }, + children: [ + { + path: "element-plus", + component: () => import("@/views/table/element-plus/index.vue"), + name: "ElementPlus", + meta: { + title: "Element Plus", + keepAlive: true + } + }, + { + path: "vxe-table", + component: () => import("@/views/table/vxe-table/index.vue"), + name: "VxeTable", + meta: { + title: "Vxe Table", + keepAlive: true + } + } + ] + }, + { + path: "/menu", + component: Layouts, + redirect: "/menu/menu1", + name: "Menu", + meta: { + title: "多级路由", + svgIcon: "menu" + }, + children: [ + { + path: "menu1", + component: () => import("@/views/menu/menu1/index.vue"), + redirect: "/menu/menu1/menu1-1", + name: "Menu1", + meta: { + title: "menu1" + }, + children: [ + { + path: "menu1-1", + component: () => import("@/views/menu/menu1/menu1-1/index.vue"), + name: "Menu1-1", + meta: { + title: "menu1-1", + keepAlive: true + } + }, + { + path: "menu1-2", + component: () => import("@/views/menu/menu1/menu1-2/index.vue"), + redirect: "/menu/menu1/menu1-2/menu1-2-1", + name: "Menu1-2", + meta: { + title: "menu1-2" + }, + children: [ + { + path: "menu1-2-1", + component: () => import("@/views/menu/menu1/menu1-2/menu1-2-1/index.vue"), + name: "Menu1-2-1", + meta: { + title: "menu1-2-1", + keepAlive: true + } + }, + { + path: "menu1-2-2", + component: () => import("@/views/menu/menu1/menu1-2/menu1-2-2/index.vue"), + name: "Menu1-2-2", + meta: { + title: "menu1-2-2", + keepAlive: true + } + } + ] + }, + { + path: "menu1-3", + component: () => import("@/views/menu/menu1/menu1-3/index.vue"), + name: "Menu1-3", + meta: { + title: "menu1-3", + keepAlive: true + } + } + ] + }, + { + path: "menu2", + component: () => import("@/views/menu/menu2/index.vue"), + name: "Menu2", + meta: { + title: "menu2", + keepAlive: true + } + } + ] + }, + { + path: "/hook-demo", + component: Layouts, + redirect: "/hook-demo/use-fetch-select", + name: "HookDemo", + meta: { + title: "Hook 示例", + elIcon: "Menu", + alwaysShow: true + }, + children: [ + { + path: "use-fetch-select", + component: () => import("@/views/hook-demo/use-fetch-select.vue"), + name: "UseFetchSelect", + meta: { + title: "useFetchSelect" + } + }, + { + path: "use-fullscreen-loading", + component: () => import("@/views/hook-demo/use-fullscreen-loading.vue"), + name: "UseFullscreenLoading", + meta: { + title: "useFullscreenLoading" + } + }, + { + path: "use-watermark", + component: () => import("@/views/hook-demo/use-watermark.vue"), + name: "UseWatermark", + meta: { + title: "useWatermark" + } + } + ] + } +]; + +/** + * 动态路由 + * 用来放置有权限 (Roles 属性) 的路由 + * 必须带有 Name 属性 + */ +export const asyncRoutes: RouteRecordRaw[] = [ + { + path: "/permission", + component: Layouts, + redirect: "/permission/page", + name: "Permission", + meta: { + title: "权限管理", + svgIcon: "lock", + roles: ["admin", "editor"], // 可以在根路由中设置角色 + alwaysShow: true // 将始终显示根菜单 + }, + children: [ + { + path: "page", + component: () => import("@/views/permission/page.vue"), + name: "PagePermission", + meta: { + title: "页面权限", + roles: ["admin"] // 或者在子导航中设置角色 + } + }, + { + path: "directive", + component: () => import("@/views/permission/directive.vue"), + name: "DirectivePermission", + meta: { + title: "指令权限" // 如果未设置角色,则表示:该页面不需要权限,但会继承根路由的角色 + } + } + ] + }, + { + path: "/:pathMatch(.*)*", // Must put the 'ErrorPage' route at the end, 必须将 'ErrorPage' 路由放在最后 + redirect: "/404", + name: "ErrorPage", + meta: { + hidden: true + } + } +]; + +const router = createRouter({ + history, + routes: routeSettings.thirdLevelRouteCache ? flatMultiLevelRoutes(constantRoutes) : constantRoutes +}); + +/** 重置路由 */ +export function resetRouter() { + // 注意:所有动态路由路由必须带有 Name 属性,否则可能会不能完全重置干净 + try { + router.getRoutes().forEach((route) => { + const { name, meta } = route; + if (name && meta.roles?.length) { + router.hasRoute(name) && router.removeRoute(name); + } + }); + } catch { + // 强制刷新浏览器也行,只是交互体验不是很好 + window.location.reload(); + } +} + +export default router; diff --git a/src/router/permission.ts b/src/router/permission.ts new file mode 100644 index 0000000..79c68c4 --- /dev/null +++ b/src/router/permission.ts @@ -0,0 +1,77 @@ +import router from "@/router"; +import { useUserStoreHook } from "@/store/modules/user"; +import { usePermissionStoreHook } from "@/store/modules/permission"; +import { ElMessage } from "element-plus"; +import { setRouteChange } from "@/hooks/useRouteListener"; +import { useTitle } from "@/hooks/useTitle"; +import { getToken } from "@/utils/cache/cookies"; +import { fixBlankPage } from "@/utils/fix-blank-page"; +import routeSettings from "@/config/route"; +import isWhiteList from "@/config/white-list"; +import NProgress from "nprogress"; +import "nprogress/nprogress.css"; + +const { setTitle } = useTitle(); +NProgress.configure({ showSpinner: false }); + +router.beforeEach(async (to, _from, next) => { + fixBlankPage(); + NProgress.start(); + const userStore = useUserStoreHook(); + const permissionStore = usePermissionStoreHook(); + const token = getToken(); + + // 判断该用户是否已经登录 + if (!token) { + // 如果在免登录的白名单中,则直接进入 + if (isWhiteList(to)) { + next(); + } else { + // 其他没有访问权限的页面将被重定向到登录页面 + NProgress.done(); + next("/login"); + } + return; + } + + // 如果已经登录,并准备进入 Login 页面,则重定向到主页 + if (to.path === "/login") { + NProgress.done(); + return next({ path: "/" }); + } + + // 如果用户已经获得其权限角色 + if (userStore.roles.length !== 0) return next(); + + // 否则要重新获取权限角色 + try { + if (routeSettings.async) { + // 注意:角色必须是一个数组! 例如: ['admin'] 或 ['developer', 'editor'] + await userStore.getInfo(); + const roles = userStore.roles; + // 根据角色生成可访问的 Routes(可访问路由 = 常驻路由 + 有访问权限的动态路由) + permissionStore.setRoutes(roles); + } else { + // 没有开启动态路由功能,则启用默认角色 + userStore.setRoles(routeSettings.defaultRoles); + permissionStore.setRoutes(routeSettings.defaultRoles); + } + // 将'有访问权限的动态路由' 添加到 Router 中 + permissionStore.dynamicRoutes.forEach((route) => router.addRoute(route)); + // 确保添加路由已完成 + // 设置 replace: true, 因此导航将不会留下历史记录 + next({ ...to, replace: true }); + } catch (err: any) { + // 过程中发生任何错误,都直接重置 Token,并重定向到登录页面 + userStore.resetToken(); + ElMessage.error(err.message || "路由守卫过程发生错误"); + NProgress.done(); + next("/login"); + } +}); + +router.afterEach((to) => { + setRouteChange(to); + setTitle(to.meta.title); + NProgress.done(); +}); diff --git a/src/store/index.ts b/src/store/index.ts new file mode 100644 index 0000000..e32948c --- /dev/null +++ b/src/store/index.ts @@ -0,0 +1,5 @@ +import { createPinia } from "pinia"; + +const store = createPinia(); + +export default store; diff --git a/src/store/modules/app.ts b/src/store/modules/app.ts new file mode 100644 index 0000000..d04978a --- /dev/null +++ b/src/store/modules/app.ts @@ -0,0 +1,47 @@ +import { reactive, ref, watch } from "vue"; +import { defineStore } from "pinia"; +import { getSidebarStatus, setSidebarStatus } from "@/utils/cache/local-storage"; +import { DeviceEnum, SIDEBAR_OPENED, SIDEBAR_CLOSED } from "@/constants/app-key"; + +interface Sidebar { + opened: boolean; + withoutAnimation: boolean; +} + +/** 设置侧边栏状态本地缓存 */ +function handleSidebarStatus(opened: boolean) { + opened ? setSidebarStatus(SIDEBAR_OPENED) : setSidebarStatus(SIDEBAR_CLOSED); +} + +export const useAppStore = defineStore("app", () => { + /** 侧边栏状态 */ + const sidebar: Sidebar = reactive({ + opened: getSidebarStatus() !== SIDEBAR_CLOSED, + withoutAnimation: false + }); + /** 设备类型 */ + const device = ref(DeviceEnum.Desktop); + + /** 监听侧边栏 opened 状态 */ + watch( + () => sidebar.opened, + (opened) => handleSidebarStatus(opened) + ); + + /** 切换侧边栏 */ + const toggleSidebar = (withoutAnimation: boolean) => { + sidebar.opened = !sidebar.opened; + sidebar.withoutAnimation = withoutAnimation; + }; + /** 关闭侧边栏 */ + const closeSidebar = (withoutAnimation: boolean) => { + sidebar.opened = false; + sidebar.withoutAnimation = withoutAnimation; + }; + /** 切换设备类型 */ + const toggleDevice = (value: DeviceEnum) => { + device.value = value; + }; + + return { device, sidebar, toggleSidebar, closeSidebar, toggleDevice }; +}); diff --git a/src/store/modules/permission.ts b/src/store/modules/permission.ts new file mode 100644 index 0000000..dd385f0 --- /dev/null +++ b/src/store/modules/permission.ts @@ -0,0 +1,44 @@ +import { ref } from "vue"; +import store from "@/store"; +import { defineStore } from "pinia"; +import { type RouteRecordRaw } from "vue-router"; +import { constantRoutes, asyncRoutes } from "@/router"; +import { flatMultiLevelRoutes } from "@/router/helper"; +import routeSettings from "@/config/route"; + +const hasPermission = (roles: string[], route: RouteRecordRaw) => { + const routeRoles = route.meta?.roles; + return routeRoles ? roles.some((role) => routeRoles.includes(role)) : true; +}; + +const filterAsyncRoutes = (routes: RouteRecordRaw[], roles: string[]) => { + const res: RouteRecordRaw[] = []; + routes.forEach((route) => { + const tempRoute = { ...route }; + if (hasPermission(roles, tempRoute)) { + if (tempRoute.children) { + tempRoute.children = filterAsyncRoutes(tempRoute.children, roles); + } + res.push(tempRoute); + } + }); + return res; +}; + +export const usePermissionStore = defineStore("permission", () => { + const routes = ref([]); + const dynamicRoutes = ref([]); + + const setRoutes = (roles: string[]) => { + const accessedRoutes = routeSettings.async ? filterAsyncRoutes(asyncRoutes, roles) : asyncRoutes; + routes.value = constantRoutes.concat(accessedRoutes); + dynamicRoutes.value = routeSettings.thirdLevelRouteCache ? flatMultiLevelRoutes(accessedRoutes) : accessedRoutes; + }; + + return { routes, dynamicRoutes, setRoutes }; +}); + +/** 在 setup 外使用 */ +export function usePermissionStoreHook() { + return usePermissionStore(store); +} diff --git a/src/store/modules/settings.ts b/src/store/modules/settings.ts new file mode 100644 index 0000000..93ef880 --- /dev/null +++ b/src/store/modules/settings.ts @@ -0,0 +1,40 @@ +import { type Ref, ref, watch } from "vue"; +import { defineStore } from "pinia"; +import { type LayoutSettings, layoutSettings } from "@/config/layouts"; +import { setConfigLayout } from "@/utils/cache/local-storage"; + +type SettingsStore = { + // 使用映射类型来遍历 layoutSettings 对象的键 + [Key in keyof LayoutSettings]: Ref; +}; + +type SettingsStoreKey = keyof SettingsStore; + +export const useSettingsStore = defineStore("settings", () => { + /** 状态对象 */ + const state = {} as SettingsStore; + // 遍历 layoutSettings 对象的键值对 + for (const [key, value] of Object.entries(layoutSettings)) { + // 使用类型断言来指定 key 的类型,将 value 包装在 ref 函数中,创建一个响应式变量 + const refValue = ref(value); + // @ts-ignore + state[key as SettingsStoreKey] = refValue; + // 监听每个响应式变量 + watch(refValue, () => { + // 缓存 + const settings = _getCacheData(); + setConfigLayout(settings); + }); + } + /** 获取要缓存的数据:将 state 对象转化为 settings 对象 */ + const _getCacheData = () => { + const settings = {} as LayoutSettings; + for (const [key, value] of Object.entries(state)) { + // @ts-ignore + settings[key as SettingsStoreKey] = value.value; + } + return settings; + }; + + return state; +}); diff --git a/src/store/modules/tags-view.ts b/src/store/modules/tags-view.ts new file mode 100644 index 0000000..4b83b37 --- /dev/null +++ b/src/store/modules/tags-view.ts @@ -0,0 +1,101 @@ +import { ref, watchEffect } from "vue"; +import store from "@/store"; +import { defineStore } from "pinia"; +import { useSettingsStore } from "./settings"; +import { type RouteLocationNormalized } from "vue-router"; +import { getVisitedViews, setVisitedViews, getCachedViews, setCachedViews } from "@/utils/cache/local-storage"; + +export type TagView = Partial; + +export const useTagsViewStore = defineStore("tags-view", () => { + const { cacheTagsView } = useSettingsStore(); + const visitedViews = ref(cacheTagsView ? getVisitedViews() : []); + const cachedViews = ref(cacheTagsView ? getCachedViews() : []); + + /** 缓存标签栏数据 */ + watchEffect(() => { + setVisitedViews(visitedViews.value); + setCachedViews(cachedViews.value); + }); + + //#region add + const addVisitedView = (view: TagView) => { + // 检查是否已经存在相同的 visitedView + const index = visitedViews.value.findIndex((v) => v.path === view.path); + if (index !== -1) { + // 防止 query 参数丢失 + visitedViews.value[index].fullPath !== view.fullPath && (visitedViews.value[index] = { ...view }); + } else { + // 添加新的 visitedView + visitedViews.value.push({ ...view }); + } + }; + + const addCachedView = (view: TagView) => { + if (typeof view.name !== "string") return; + if (cachedViews.value.includes(view.name)) return; + if (view.meta?.keepAlive) cachedViews.value.push(view.name); + }; + //#endregion + + //#region del + const delVisitedView = (view: TagView) => { + const index = visitedViews.value.findIndex((v) => v.path === view.path); + if (index !== -1) visitedViews.value.splice(index, 1); + }; + + const delCachedView = (view: TagView) => { + if (typeof view.name !== "string") return; + const index = cachedViews.value.indexOf(view.name); + if (index !== -1) cachedViews.value.splice(index, 1); + }; + //#endregion + + //#region delOthers + const delOthersVisitedViews = (view: TagView) => { + visitedViews.value = visitedViews.value.filter((v) => { + return v.meta?.affix || v.path === view.path; + }); + }; + + const delOthersCachedViews = (view: TagView) => { + if (typeof view.name !== "string") return; + const index = cachedViews.value.indexOf(view.name); + if (index !== -1) { + cachedViews.value = cachedViews.value.slice(index, index + 1); + } else { + // 如果 index = -1, 没有缓存的 tags + cachedViews.value = []; + } + }; + //#endregion + + //#region delAll + const delAllVisitedViews = () => { + // 保留固定的 tags + visitedViews.value = visitedViews.value.filter((tag) => tag.meta?.affix); + }; + + const delAllCachedViews = () => { + cachedViews.value = []; + }; + //#endregion + + return { + visitedViews, + cachedViews, + addVisitedView, + addCachedView, + delVisitedView, + delCachedView, + delOthersVisitedViews, + delOthersCachedViews, + delAllVisitedViews, + delAllCachedViews + }; +}); + +/** 在 setup 外使用 */ +export function useTagsViewStoreHook() { + return useTagsViewStore(store); +} diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts new file mode 100644 index 0000000..1420efc --- /dev/null +++ b/src/store/modules/user.ts @@ -0,0 +1,81 @@ +import { ref } from "vue"; +import store from "@/store"; +import { defineStore } from "pinia"; +import { usePermissionStore } from "./permission"; +import { useTagsViewStore } from "./tags-view"; +import { useSettingsStore } from "./settings"; +import { getToken, removeToken, setToken } from "@/utils/cache/cookies"; +import router, { resetRouter } from "@/router"; +import { loginApi, getUserInfoApi } from "@/api/login"; +import { type LoginRequestData } from "@/api/login/types/login"; +import { type RouteRecordRaw } from "vue-router"; +import routeSettings from "@/config/route"; + +export const useUserStore = defineStore("user", () => { + const token = ref(getToken() || ""); + const roles = ref([]); + const username = ref(""); + + const permissionStore = usePermissionStore(); + const tagsViewStore = useTagsViewStore(); + const settingsStore = useSettingsStore(); + + /** 设置角色数组 */ + const setRoles = (value: string[]) => { + roles.value = value; + }; + /** 登录 */ + const login = async ({ username, password, code }: LoginRequestData) => { + const { data } = await loginApi({ username, password, code }); + setToken(data.token); + token.value = data.token; + }; + /** 获取用户详情 */ + const getInfo = async () => { + const { data } = await getUserInfoApi(); + username.value = data.username; + // 验证返回的 roles 是否为一个非空数组,否则塞入一个没有任何作用的默认角色,防止路由守卫逻辑进入无限循环 + roles.value = data.roles?.length > 0 ? data.roles : routeSettings.defaultRoles; + }; + /** 切换角色 */ + const changeRoles = async (role: string) => { + const newToken = "token-" + role; + token.value = newToken; + setToken(newToken); + await getInfo(); + permissionStore.setRoutes(roles.value); + resetRouter(); + permissionStore.dynamicRoutes.forEach((item: RouteRecordRaw) => { + router.addRoute(item); + }); + _resetTagsView(); + }; + /** 登出 */ + const logout = () => { + removeToken(); + token.value = ""; + roles.value = []; + resetRouter(); + _resetTagsView(); + }; + /** 重置 Token */ + const resetToken = () => { + removeToken(); + token.value = ""; + roles.value = []; + }; + /** 重置 Visited Views 和 Cached Views */ + const _resetTagsView = () => { + if (!settingsStore.cacheTagsView) { + tagsViewStore.delAllVisitedViews(); + tagsViewStore.delAllCachedViews(); + } + }; + + return { token, roles, username, setRoles, login, getInfo, changeRoles, logout, resetToken }; +}); + +/** 在 setup 外使用 */ +export function useUserStoreHook() { + return useUserStore(store); +} diff --git a/src/styles/element-plus.scss b/src/styles/element-plus.scss new file mode 100644 index 0000000..acd07ac --- /dev/null +++ b/src/styles/element-plus.scss @@ -0,0 +1,27 @@ +/** 自定义 Element Plus 样式 */ + +// 表格 +.el-table { + // 表头 + th.el-table__cell { + background-color: var(--el-fill-color-light) !important; + } + // 行元素 + tr { + background-color: transparent; + } +} + +// 分页 +.el-pagination { + // 参考 Bootstrap 的响应式设计 WIDTH = 768 + @media screen and (max-width: 768px) { + .el-pagination__total, + .el-pagination__sizes, + .el-pagination__jump, + .btn-prev, + .btn-next { + display: none !important; + } + } +} diff --git a/src/styles/index.scss b/src/styles/index.scss new file mode 100644 index 0000000..fb4938e --- /dev/null +++ b/src/styles/index.scss @@ -0,0 +1,53 @@ +// 全局 CSS 变量 +@import "./variables.css"; +// Transition +@import "./transition.scss"; +// Element Plus +@import "./element-plus.scss"; +// Vxe Table +@import "./vxe-table.scss"; +// 注册多主题 +@import "./theme/register.scss"; +// mixin +@import "./mixins.scss"; + +// 业务页面几乎都应该在根元素上挂载 class="app-container",以保持页面美观 +.app-container { + padding: 20px; +} + +html { + height: 100%; +} + +body { + height: 100%; + background-color: var(--v3-body-bg-color); + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, + sans-serif; + @extend %scrollbar; +} + +#app { + height: 100%; +} + +*, +*::before, +*::after { + box-sizing: border-box; +} + +a, +a:focus, +a:hover { + color: inherit; + outline: none; + text-decoration: none; +} + +div:focus { + outline: none; +} diff --git a/src/styles/mixins.scss b/src/styles/mixins.scss new file mode 100644 index 0000000..87d4e17 --- /dev/null +++ b/src/styles/mixins.scss @@ -0,0 +1,42 @@ +/** 清除浮动 */ +%clearfix { + &::after { + content: ""; + display: table; + clear: both; + } +} + +/** 美化原生滚动条 */ +%scrollbar { + // 整个滚动条 + &::-webkit-scrollbar { + width: 8px; + height: 8px; + } + // 滚动条上的滚动滑块 + &::-webkit-scrollbar-thumb { + border-radius: 4px; + background-color: #90939955; + } + &::-webkit-scrollbar-thumb:hover { + background-color: #90939977; + } + &::-webkit-scrollbar-thumb:active { + background-color: #90939999; + } + // 当同时有垂直滚动条和水平滚动条时交汇的部分 + &::-webkit-scrollbar-corner { + background-color: transparent; + } +} + +/** 文本溢出时显示省略号 */ +%ellipsis { + // 隐藏溢出的文本 + overflow: hidden; + // 防止文本换行 + white-space: nowrap; + // 文本内容溢出容器时,文本末尾显示省略号 + text-overflow: ellipsis; +} diff --git a/src/styles/theme/core/element-plus.scss b/src/styles/theme/core/element-plus.scss new file mode 100644 index 0000000..44f0de8 --- /dev/null +++ b/src/styles/theme/core/element-plus.scss @@ -0,0 +1,30 @@ +/** Element Plus 相关 */ + +// 侧边栏的 item 的 popper +.el-popper { + border: none !important; + .el-menu { + background-color: lighten($theme-bg-color, 2%) !important; + .el-menu-item { + background-color: lighten($theme-bg-color, 2%) !important; + &.is-active, + &:hover { + background-color: lighten($theme-bg-color, 6%) !important; + color: $active-font-color !important; + } + } + .el-sub-menu__title { + background-color: lighten($theme-bg-color, 2%) !important; + } + .el-sub-menu { + &.is-active { + > .el-sub-menu__title { + color: $active-font-color !important; + } + } + } + } + .el-menu--horizontal { + border: none; + } +} diff --git a/src/styles/theme/core/error-page.scss b/src/styles/theme/core/error-page.scss new file mode 100644 index 0000000..ec9c941 --- /dev/null +++ b/src/styles/theme/core/error-page.scss @@ -0,0 +1,5 @@ +/** ErrorPage 页面相关 */ + +.error-page { + background-color: $theme-bg-color; +} diff --git a/src/styles/theme/core/index.scss b/src/styles/theme/core/index.scss new file mode 100644 index 0000000..5ae838b --- /dev/null +++ b/src/styles/theme/core/index.scss @@ -0,0 +1,8 @@ +.#{$theme-name} { + @import "./layouts.scss"; + @import "./login.scss"; + @import "./error-page.scss"; + @import "./element-plus.scss"; + @import "./vxe-table.scss"; + @import "./other.scss"; +} diff --git a/src/styles/theme/core/layouts.scss b/src/styles/theme/core/layouts.scss new file mode 100644 index 0000000..f322941 --- /dev/null +++ b/src/styles/theme/core/layouts.scss @@ -0,0 +1,77 @@ +/** Layout 相关 */ + +#app { + color: $font-color; + // 右侧设置面板 + .handle-button { + background-color: lighten($theme-bg-color, 20%) !important; + } +} + +.app-wrapper { + // 侧边栏 + .sidebar-container { + background-color: lighten($theme-bg-color, 2%); + .el-menu { + background-color: lighten($theme-bg-color, 2%) !important; + .el-menu-item { + background-color: lighten($theme-bg-color, 2%) !important; + &.is-active, + &:hover { + background-color: lighten($theme-bg-color, 6%) !important; + color: $active-font-color !important; + } + } + } + .el-sub-menu__title { + background-color: lighten($theme-bg-color, 2%) !important; + } + .el-sub-menu { + &.is-active { + > .el-sub-menu__title { + color: $active-font-color !important; + } + } + } + } + + // Header + .layout-header { + background-color: $theme-bg-color; + border-bottom: 1px solid lighten($theme-bg-color, 10%) !important; + } + + // 顶部导航栏 + .navigation-bar { + background-color: $theme-bg-color; + .right-menu { + .svg-icon { + color: $font-color; + } + } + } + + // TagsView + .tags-view-container { + background-color: $theme-bg-color !important; + .tags-view-item { + background-color: $theme-bg-color !important; + color: $font-color !important; + border: 1px solid $border-color !important; + &.active { + background-color: $theme-color !important; + color: $active-font-color !important; + border-color: $border-color !important; + } + } + // 右键菜单 + .contextmenu { + background-color: lighten($theme-bg-color, 8%); + color: $font-color; + li:hover { + background-color: lighten($theme-bg-color, 16%); + color: $active-font-color; + } + } + } +} diff --git a/src/styles/theme/core/login.scss b/src/styles/theme/core/login.scss new file mode 100644 index 0000000..2b1a180 --- /dev/null +++ b/src/styles/theme/core/login.scss @@ -0,0 +1,9 @@ +/** Login 页面相关 */ + +.login-container { + background-color: $theme-bg-color; + color: $font-color; + .login-card { + background-color: lighten($theme-bg-color, 4%) !important; + } +} diff --git a/src/styles/theme/core/other.scss b/src/styles/theme/core/other.scss new file mode 100644 index 0000000..ea76a9c --- /dev/null +++ b/src/styles/theme/core/other.scss @@ -0,0 +1,6 @@ +/** 这里可以写业务页面的黑暗样式 */ + +.app-main { + background-color: $theme-bg-color !important; + // 写在这里... +} diff --git a/src/styles/theme/core/vxe-table.scss b/src/styles/theme/core/vxe-table.scss new file mode 100644 index 0000000..57fa5ef --- /dev/null +++ b/src/styles/theme/core/vxe-table.scss @@ -0,0 +1,58 @@ +/** + * Vxe Table SCSS 变量 + * 在此查阅所有可自定义的变量:https://github.com/x-extends/vxe-table/blob/master/styles/variable.scss + */ + +/** font */ +$vxe-font-color: $font-color; + +/** color */ +$vxe-primary-color: $theme-color; +$vxe-success-color: $theme-color; + +/** input/radio/checkbox */ +$vxe-input-border-color: $theme-color; +$vxe-input-disabled-color: $theme-color; +$vxe-input-disabled-background-color: lighten($theme-bg-color, 12%); + +/** popup */ +$vxe-table-popup-border-color: $border-color; + +/** table */ +$vxe-table-font-color: $font-color; +$vxe-table-border-color: $border-color; +$vxe-table-header-background-color: lighten($theme-bg-color, 8%); +$vxe-table-body-background-color: lighten($theme-bg-color, 4%); +$vxe-table-row-hover-background-color: lighten($theme-bg-color, 8%); +$vxe-table-row-current-background-color: lighten($theme-bg-color, 8%); +$vxe-table-row-hover-current-background-color: lighten($theme-bg-color, 8%); +$vxe-table-checkbox-range-background-color: lighten($theme-bg-color, 8%); + +/** toolbar */ +$vxe-toolbar-background-color: lighten($theme-bg-color, 4%); +$vxe-toolbar-custom-active-background-color: lighten($theme-bg-color, 16%); +$vxe-toolbar-panel-background-color: lighten($theme-bg-color, 4%); + +/** pager */ +$vxe-pager-background-color: lighten($theme-bg-color, 4%); + +/** modal */ +$vxe-modal-header-background-color: lighten($theme-bg-color, 4%); +$vxe-modal-body-background-color: lighten($theme-bg-color, 4%); +$vxe-modal-border-color: $border-color; + +/** button */ +$vxe-button-default-background-color: lighten($theme-bg-color, 8%); + +/** input */ +$vxe-input-background-color: lighten($theme-bg-color, 4%); +$vxe-input-panel-background-color: $vxe-input-background-color; + +/** form */ +$vxe-form-background-color: lighten($theme-bg-color, 4%); + +/** select */ +$vxe-select-option-hover-background-color: lighten($theme-bg-color, 8%); +$vxe-select-panel-background-color: lighten($theme-bg-color, 4%); + +@import "vxe-table/styles/index.scss"; diff --git a/src/styles/theme/dark-blue/element-plus.css b/src/styles/theme/dark-blue/element-plus.css new file mode 100644 index 0000000..7f31578 --- /dev/null +++ b/src/styles/theme/dark-blue/element-plus.css @@ -0,0 +1,41 @@ +/** + * dark-blue 主题下的 Element Plus CSS 变量 + * 在此查阅所有可自定义的变量:https://github.com/element-plus/element-plus/blob/dev/packages/theme-chalk/src/common/var.scss + * 也可以打开浏览器控制台选择元素,查看要覆盖的变量名 + */ + +html.dark-blue { + /** color */ + --el-color-primary: #01efb7bb; + --el-color-primary-light-3: rgba(1, 147, 127, 0.8133333333); + --el-color-primary-light-5: rgba(2, 102, 99, 0.8666666667); + --el-color-primary-light-7: rgba(2, 65, 77, 0.92); + --el-color-primary-light-8: rgba(2, 49, 68, 0.9466666667); + --el-color-primary-light-9: rgba(2, 35, 59, 0.9733333333); + --el-color-primary-dark-2: rgba(1, 167, 128, 0.7866666667); + --el-color-success: #01efb7bb; + /** text-color */ + --el-text-color-primary: rgba(255, 255, 255, 0.8); + --el-text-color-regular: rgba(255, 255, 255, 0.8); + --el-text-color-secondary: rgba(255, 255, 255, 0.8); + --el-text-color-placeholder: rgba(255, 255, 255, 0.8); + --el-text-color-disabled: rgba(255, 255, 255, 0.3); + /** border-color */ + --el-border-color: #01efb755; + --el-border-color-light: #01efb755; + --el-border-color-lighter: #01efb755; + /** fill-color */ + --el-fill-color: #01efb710; + --el-fill-color-light: #01efb710; + --el-fill-color-blank: #031e47; + /** bg-color */ + --el-bg-color: #021633; + --el-bg-color-overlay: #031e47; + /** mask */ + --el-mask-color: rgba(0, 0, 0, 0.5); +} + +/** button */ +html.dark-blue .el-button { + --el-button-disabled-text-color: rgba(255, 255, 255, 0.5); +} diff --git a/src/styles/theme/dark-blue/element-plus.scss b/src/styles/theme/dark-blue/element-plus.scss new file mode 100644 index 0000000..faa2d98 --- /dev/null +++ b/src/styles/theme/dark-blue/element-plus.scss @@ -0,0 +1,127 @@ +/** + * dark-blue 主题下的 Element Plus SCSS 变量 + * 在此查阅所有可自定义的变量:https://github.com/element-plus/element-plus/blob/dev/packages/theme-chalk/src/common/var.scss + */ + +@use "sass:map"; +@use "sass:math"; +@use "element-plus/theme-chalk/src/mixins/function.scss" as *; +@use "element-plus/theme-chalk/src/mixins/_var.scss" as *; +@use "element-plus/theme-chalk/src/mixins/mixins.scss" as *; +@use "./variables.scss" as *; + +// 生成指定颜色的明亮/黑暗颜色 +@mixin set-color-mix-level($type, $number, $mode: "light", $mix-color: $color-white) { + $colors: map.deep-merge( + ( + $type: ( + "#{$mode}-#{$number}": mix($mix-color, map.get($colors, $type, "base"), math.percentage(math.div($number, 10))) + ) + ), + $colors + ) !global; +} + +$types: primary, success, warning, danger, error, info; + +$color: $theme-color; +$success: #01efb7bb; + +$colors: () !default; +$colors: map.deep-merge( + ( + "white": #ffffff, + "primary": ( + "base": $color + ), + "success": ( + "base": $success + ) + ), + $colors +); + +// text +$text-color-base: #fff; +$text-color: () !default; +$text-color: map.merge( + ( + "primary": rgba($text-color-base, 0.8), + "regular": rgba($text-color-base, 0.8), + "secondary": rgba($text-color-base, 0.8), + "placeholder": rgba($text-color-base, 0.8), + "disabled": rgba($text-color-base, 0.3) + ), + $text-color +); + +// 生成 --el-color-${type}-light-i +@each $type in (primary) { + @for $i from 1 through 9 { + @include set-color-mix-level($type, $i, "light", #021633); + } + // --el-color-${type}-dark-2 + @include set-color-mix-level($type, 2, "dark", #000); +} + +// border +$border: () !default; +$border: map.merge( + ( + "": #01efb755, + "light": #01efb755, + "lighter": #01efb755 + ), + $border +); + +// fill +$fill-color: () !default; +$fill-color: map.merge( + ( + "": #01efb710, + "light": #01efb710, + "blank": #031e47 + ), + $fill-color +); + +// background +$bg-color: () !default; +$bg-color: map.merge( + ( + "": #021633, + "overlay": #031e47 + ), + $bg-color +); + +// mask +$mask-color: () !default; +$mask-color: map.merge( + ( + "": rgba(0, 0, 0, 0.5) + ), + $mask-color +); + +// button +$button: () !default; +$button: map.merge( + ( + "disabled-text-color": rgba(255, 255, 255, 0.5) + ), + $button +); + +html.dark-blue { + @include set-css-color-type($colors, "primary"); + @include set-component-css-var("text-color", $text-color); + @include set-component-css-var("border-color", $border); + @include set-component-css-var("fill-color", $fill-color); + @include set-component-css-var("bg-color", $bg-color); + @include set-component-css-var("mask-color", $mask-color); + @include b(button) { + @include set-component-css-var("button", $button); + } +} diff --git a/src/styles/theme/dark-blue/index.scss b/src/styles/theme/dark-blue/index.scss new file mode 100644 index 0000000..95456ef --- /dev/null +++ b/src/styles/theme/dark-blue/index.scss @@ -0,0 +1,4 @@ +@use "./element-plus.css"; // 方案一 +// @use "./element-plus.scss"; // 方案二 +@import "./variables.scss"; +@import "../core/index.scss"; diff --git a/src/styles/theme/dark-blue/variables.scss b/src/styles/theme/dark-blue/variables.scss new file mode 100644 index 0000000..d71847d --- /dev/null +++ b/src/styles/theme/dark-blue/variables.scss @@ -0,0 +1,16 @@ +/** dark-blue 主题下的变量 */ + +// 主题名称 +$theme-name: "dark-blue"; +// 主题背景颜色 +$theme-bg-color: #021633; +// 主题色 +$theme-color: #01efb7bb; +// 默认文字颜色 +$font-color: rgba(255, 255, 255, 0.8); +// active 状态下文字颜色 +$active-font-color: #fff; +// hover 状态下文字颜色 +$hover-color: #fff; +// 边框颜色 +$border-color: #01efb755; diff --git a/src/styles/theme/dark/index.scss b/src/styles/theme/dark/index.scss new file mode 100644 index 0000000..d39200d --- /dev/null +++ b/src/styles/theme/dark/index.scss @@ -0,0 +1,2 @@ +@import "./variables.scss"; +@import "../core/index.scss"; diff --git a/src/styles/theme/dark/variables.scss b/src/styles/theme/dark/variables.scss new file mode 100644 index 0000000..9ce62b9 --- /dev/null +++ b/src/styles/theme/dark/variables.scss @@ -0,0 +1,16 @@ +/** dark 主题下的变量 */ + +// 主题名称 +$theme-name: "dark"; +// 主题背景颜色 +$theme-bg-color: #151515; +// 主题色 +$theme-color: #409eff; +// 默认文字颜色 +$font-color: #c0c4cc; +// active 状态下文字颜色 +$active-font-color: #fff; +// hover 状态下文字颜色 +$hover-color: #fff; +// 边框颜色 +$border-color: #303133; diff --git a/src/styles/theme/register.scss b/src/styles/theme/register.scss new file mode 100644 index 0000000..6b74211 --- /dev/null +++ b/src/styles/theme/register.scss @@ -0,0 +1,3 @@ +// 注册多主题 +@import "./dark/index.scss"; +@import "./dark-blue/index.scss"; diff --git a/src/styles/transition.scss b/src/styles/transition.scss new file mode 100644 index 0000000..ae5e8b1 --- /dev/null +++ b/src/styles/transition.scss @@ -0,0 +1,25 @@ +// See https://cn.vuejs.org/guide/built-ins/transition.html for detail + +// fade-transform +.fade-transform-leave-active, +.fade-transform-enter-active { + transition: all 0.5s; +} +.fade-transform-enter { + opacity: 0; + transform: translateX(-30px); +} +.fade-transform-leave-to { + opacity: 0; + transform: translateX(30px); +} + +// layout-logo-fade +.layout-logo-fade-enter-active, +.layout-logo-fade-leave-active { + transition: opacity 1.5s; +} +.layout-logo-fade-enter-from, +.layout-logo-fade-leave-to { + opacity: 0; +} diff --git a/src/styles/variables.css b/src/styles/variables.css new file mode 100644 index 0000000..fae92c1 --- /dev/null +++ b/src/styles/variables.css @@ -0,0 +1,44 @@ +/** 全局 CSS 变量,这种变量不仅可以在 CSS 和 SCSS 中使用,还可以导入到 JS 中使用 */ +:root { + /** 全局背景色 */ + --v3-body-bg-color: #f2f3f5; + /** Header 区域 = NavigationBar 组件 + TagsView 组件 */ + --v3-header-height: calc(var(--v3-navigationbar-height) + var(--v3-tagsview-height)); + --v3-header-bg-color: #ffffff; + /** NavigationBar 组件 */ + --v3-navigationbar-height: 50px; + /** Sidebar 组件(左侧模式全部生效、顶部模式全部不生效、混合模式非颜色部分生效) */ + --v3-sidebar-width: 220px; + --v3-sidebar-hide-width: 58px; + --v3-sidebar-menu-item-height: 60px; + --v3-sidebar-menu-tip-line-bg-color: var(--el-color-primary); + --v3-sidebar-menu-bg-color: #001428; + --v3-sidebar-menu-hover-bg-color: #409eff10; + --v3-sidebar-menu-text-color: #c0c4cc; + --v3-sidebar-menu-active-text-color: #ffffff; + /** TagsView 组件 */ + --v3-tagsview-height: 34px; + --v3-tagsview-tag-text-color: #495060; + --v3-tagsview-tag-active-text-color: #ffffff; + --v3-tagsview-tag-bg-color: #ffffff; + --v3-tagsview-tag-active-bg-color: var(--el-color-primary); + --v3-tagsview-tag-border-radius: 2px; + --v3-tagsview-tag-border-color: #d8dce5; + --v3-tagsview-tag-active-border-color: var(--el-color-primary); + --v3-tagsview-tag-active-before-color: #ffffff; + --v3-tagsview-tag-icon-hover-bg-color: #00000030; + --v3-tagsview-tag-icon-hover-color: #ffffff; + /** RightPanel 组件 */ + --v3-rightpanel-button-bg-color: #001428; +} + +/** 内容区放大时,将不需要的组件隐藏 */ +body.content-large { + /** Header 区域 = TagsView 组件 */ + --v3-header-height: var(--v3-tagsview-height); + /** NavigationBar 组件 */ + --v3-navigationbar-height: 0px; + /** Sidebar 组件 */ + --v3-sidebar-width: 0px; + --v3-sidebar-hide-width: 0px; +} diff --git a/src/styles/vxe-table.scss b/src/styles/vxe-table.scss new file mode 100644 index 0000000..684cf39 --- /dev/null +++ b/src/styles/vxe-table.scss @@ -0,0 +1,38 @@ +/** 自定义 Vxe Table 样式 */ + +.vxe-grid { + // 表单 + &--form-wrapper { + .vxe-form { + padding: 10px 20px !important; + margin-bottom: 20px !important; + } + } + + // 工具栏 + &--toolbar-wrapper { + .vxe-toolbar { + padding: 20px !important; + } + } + + // 分页 + &--pager-wrapper { + .vxe-pager { + height: 70px !important; + padding: 0 20px !important; + &--wrapper { + // 参考 Bootstrap 的响应式设计 WIDTH = 768 + @media screen and (max-width: 768px) { + .vxe-pager--total, + .vxe-pager--sizes, + .vxe-pager--jump, + .vxe-pager--jump-prev, + .vxe-pager--jump-next { + display: none !important; + } + } + } + } + } +} diff --git a/src/utils/cache/cookies.ts b/src/utils/cache/cookies.ts new file mode 100644 index 0000000..9547b39 --- /dev/null +++ b/src/utils/cache/cookies.ts @@ -0,0 +1,14 @@ +/** 统一处理 Cookie */ + +import CacheKey from "@/constants/cache-key"; +import Cookies from "js-cookie"; + +export const getToken = () => { + return Cookies.get(CacheKey.TOKEN); +}; +export const setToken = (token: string) => { + Cookies.set(CacheKey.TOKEN, token); +}; +export const removeToken = () => { + Cookies.remove(CacheKey.TOKEN); +}; diff --git a/src/utils/cache/local-storage.ts b/src/utils/cache/local-storage.ts new file mode 100644 index 0000000..f6dd25c --- /dev/null +++ b/src/utils/cache/local-storage.ts @@ -0,0 +1,60 @@ +/** 统一处理 localStorage */ + +import CacheKey from "@/constants/cache-key"; +import { type SidebarOpened, type SidebarClosed } from "@/constants/app-key"; +import { type ThemeName } from "@/hooks/useTheme"; +import { type TagView } from "@/store/modules/tags-view"; +import { type LayoutSettings } from "@/config/layouts"; + +//#region 系统布局配置 +export const getConfigLayout = () => { + const json = localStorage.getItem(CacheKey.CONFIG_LAYOUT); + return json ? (JSON.parse(json) as LayoutSettings) : null; +}; +export const setConfigLayout = (settings: LayoutSettings) => { + localStorage.setItem(CacheKey.CONFIG_LAYOUT, JSON.stringify(settings)); +}; +export const removeConfigLayout = () => { + localStorage.removeItem(CacheKey.CONFIG_LAYOUT); +}; +//#endregion + +//#region 侧边栏状态 +export const getSidebarStatus = () => { + return localStorage.getItem(CacheKey.SIDEBAR_STATUS); +}; +export const setSidebarStatus = (sidebarStatus: SidebarOpened | SidebarClosed) => { + localStorage.setItem(CacheKey.SIDEBAR_STATUS, sidebarStatus); +}; +//#endregion + +//#region 正在应用的主题名称 +export const getActiveThemeName = () => { + return localStorage.getItem(CacheKey.ACTIVE_THEME_NAME) as ThemeName | null; +}; +export const setActiveThemeName = (themeName: ThemeName) => { + localStorage.setItem(CacheKey.ACTIVE_THEME_NAME, themeName); +}; +//#endregion + +//#region 标签栏 +export const getVisitedViews = () => { + const json = localStorage.getItem(CacheKey.VISITED_VIEWS); + return JSON.parse(json ?? "[]") as TagView[]; +}; +export const setVisitedViews = (views: TagView[]) => { + views.forEach((view) => { + // 删除不必要的属性,防止 JSON.stringify 处理到循环引用 + delete view.matched; + delete view.redirectedFrom; + }); + localStorage.setItem(CacheKey.VISITED_VIEWS, JSON.stringify(views)); +}; +export const getCachedViews = () => { + const json = localStorage.getItem(CacheKey.CACHED_VIEWS); + return JSON.parse(json ?? "[]") as string[]; +}; +export const setCachedViews = (views: string[]) => { + localStorage.setItem(CacheKey.CACHED_VIEWS, JSON.stringify(views)); +}; +//#endregion diff --git a/src/utils/fix-blank-page.ts b/src/utils/fix-blank-page.ts new file mode 100644 index 0000000..6d58b13 --- /dev/null +++ b/src/utils/fix-blank-page.ts @@ -0,0 +1,15 @@ +import { useTagsViewStoreHook } from "@/store/modules/tags-view"; + +/** + * 功能:修复 组合使用导致的页面空白 + * 原因:似乎是 Vue 本身的 BUG:https://github.com/vuejs/core/issues/7121 + * 复现:在不使用该函数的情况下,可以通过如下步骤复现: + * 1. 进入一个页面 + * 2. 修改该页面的 TS 代码并保存 + * 3. 回到浏览器切换一下页面 + * 4. 结果:内容区没有加载出来呈现空白状态 + */ +export const fixBlankPage = () => { + const tagsViewStore = useTagsViewStoreHook(); + tagsViewStore.cachedViews = [...tagsViewStore.cachedViews]; +}; diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..c8d45f3 --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,34 @@ +import dayjs from "dayjs"; +import { removeConfigLayout } from "@/utils/cache/local-storage"; + +/** 格式化时间 */ +export const formatDateTime = (time: string | number | Date) => { + return time ? dayjs(new Date(time)).format("YYYY-MM-DD HH:mm:ss") : "N/A"; +}; + +/** 用 JS 获取全局 css 变量 */ +export const getCssVariableValue = (cssVariableName: string) => { + let cssVariableValue = ""; + try { + // 没有拿到值时,会返回空串 + cssVariableValue = getComputedStyle(document.documentElement).getPropertyValue(cssVariableName); + } catch (error) { + console.error(error); + } + return cssVariableValue; +}; + +/** 用 JS 设置全局 CSS 变量 */ +export const setCssVariableValue = (cssVariableName: string, cssVariableValue: string) => { + try { + document.documentElement.style.setProperty(cssVariableName, cssVariableValue); + } catch (error) { + console.error(error); + } +}; + +/** 重置项目配置 */ +export const resetConfigLayout = () => { + removeConfigLayout(); + location.reload(); +}; diff --git a/src/utils/permission.ts b/src/utils/permission.ts new file mode 100644 index 0000000..483f986 --- /dev/null +++ b/src/utils/permission.ts @@ -0,0 +1,12 @@ +import { useUserStoreHook } from "@/store/modules/user"; + +/** 全局权限判断函数,和权限指令 v-permission 功能类似 */ +export const checkPermission = (permissionRoles: string[]): boolean => { + if (Array.isArray(permissionRoles) && permissionRoles.length > 0) { + const { roles } = useUserStoreHook(); + return roles.some((role) => permissionRoles.includes(role)); + } else { + console.error("need roles! Like checkPermission(['admin','editor'])"); + return false; + } +}; diff --git a/src/utils/service.ts b/src/utils/service.ts new file mode 100644 index 0000000..a0deeac --- /dev/null +++ b/src/utils/service.ts @@ -0,0 +1,122 @@ +import axios, { type AxiosInstance, type AxiosRequestConfig } from "axios"; +import { useUserStoreHook } from "@/store/modules/user"; +import { ElMessage } from "element-plus"; +import { get, merge } from "lodash-es"; +import { getToken } from "./cache/cookies"; + +/** 退出登录并强制刷新页面(会重定向到登录页) */ +function logout() { + useUserStoreHook().logout(); + location.reload(); +} + +/** 创建请求实例 */ +function createService() { + // 创建一个 axios 实例命名为 service + const service = axios.create(); + // 请求拦截 + service.interceptors.request.use( + (config) => config, + // 发送失败 + (error) => Promise.reject(error) + ); + // 响应拦截(可根据具体业务作出相应的调整) + service.interceptors.response.use( + (response) => { + // apiData 是 api 返回的数据 + const apiData = response.data; + // 二进制数据则直接返回 + const responseType = response.request?.responseType; + if (responseType === "blob" || responseType === "arraybuffer") return apiData; + // 这个 code 是和后端约定的业务 code + const code = apiData.code; + // 如果没有 code, 代表这不是项目后端开发的 api + if (code === undefined) { + ElMessage.error("非本系统的接口"); + return Promise.reject(new Error("非本系统的接口")); + } + switch (code) { + case 0: + // 本系统采用 code === 0 来表示没有业务错误 + return apiData; + case 401: + // Token 过期时 + return logout(); + default: + // 不是正确的 code + ElMessage.error(apiData.message || "Error"); + return Promise.reject(new Error("Error")); + } + }, + (error) => { + // status 是 HTTP 状态码 + const status = get(error, "response.status"); + switch (status) { + case 400: + error.message = "请求错误"; + break; + case 401: + // Token 过期时 + logout(); + break; + case 403: + error.message = "拒绝访问"; + break; + case 404: + error.message = "请求地址出错"; + break; + case 408: + error.message = "请求超时"; + break; + case 500: + error.message = "服务器内部错误"; + break; + case 501: + error.message = "服务未实现"; + break; + case 502: + error.message = "网关错误"; + break; + case 503: + error.message = "服务不可用"; + break; + case 504: + error.message = "网关超时"; + break; + case 505: + error.message = "HTTP 版本不受支持"; + break; + default: + break; + } + ElMessage.error(error.message); + return Promise.reject(error); + } + ); + return service; +} + +/** 创建请求方法 */ +function createRequest(service: AxiosInstance) { + return function (config: AxiosRequestConfig): Promise { + const token = getToken(); + const defaultConfig = { + headers: { + // 携带 Token + Authorization: token ? `Bearer ${token}` : undefined, + "Content-Type": "application/json" + }, + timeout: 5000, + baseURL: import.meta.env.VITE_BASE_API, + data: {} + }; + // 将默认配置 defaultConfig 和传入的自定义配置 config 进行合并成为 mergeConfig + const mergeConfig = merge(defaultConfig, config); + return service(mergeConfig); + }; +} + +/** 用于网络请求的实例 */ +const service = createService(); +/** 用于网络请求的方法 */ +export const request = createRequest(service); diff --git a/src/utils/validate.ts b/src/utils/validate.ts new file mode 100644 index 0000000..a00b7c0 --- /dev/null +++ b/src/utils/validate.ts @@ -0,0 +1,84 @@ +/** 判断是否为数组 */ +export const isArray = (arg: unknown) => { + return Array.isArray ? Array.isArray(arg) : Object.prototype.toString.call(arg) === "[object Array]"; +}; + +/** 判断是否为字符串 */ +export const isString = (str: unknown) => { + return typeof str === "string" || str instanceof String; +}; + +/** 判断是否为外链 */ +export const isExternal = (path: string) => { + const reg = /^(https?:|mailto:|tel:)/; + return reg.test(path); +}; + +/** 判断是否为网址(带协议) */ +export const isUrl = (url: string) => { + const reg = /^(((ht|f)tps?):\/\/)?([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[a-z]{2,6}\/?/; + return reg.test(url); +}; + +/** 判断是否为网址或 IP(带端口) */ +export const isUrlPort = (url: string) => { + const reg = /^((ht|f)tps?:\/\/)?[\w-]+(\.[\w-]+)+:\d{1,5}\/?$/; + return reg.test(url); +}; + +/** 判断是否为域名(不带协议) */ +export const isDomain = (domain: string) => { + const reg = /^([0-9a-zA-Z-]{1,}\.)+([a-zA-Z]{2,})$/; + return reg.test(domain); +}; + +/** 判断版本号格式是否为 X.Y.Z */ +export const isVersion = (version: string) => { + const reg = /^\d+(?:\.\d+){2}$/; + return reg.test(version); +}; + +/** 判断时间格式是否为 24 小时制(HH:mm:ss) */ +export const is24H = (time: string) => { + const reg = /^(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d$/; + return reg.test(time); +}; + +/** 判断是否为手机号(1 开头) */ +export const isPhoneNumber = (str: string) => { + const reg = /^(?:(?:\+|00)86)?1\d{10}$/; + return reg.test(str); +}; + +/** 判断是否为第二代身份证(18 位) */ +export const isChineseIdCard = (str: string) => { + const reg = /^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\d|30|31)\d{3}[\dXx]$/; + return reg.test(str); +}; + +/** 判断是否为 Email(支持中文邮箱) */ +export const isEmail = (email: string) => { + const reg = /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/; + return reg.test(email); +}; + +/** 判断是否为 MAC 地址 */ +export const isMAC = (mac: string) => { + const reg = + /^(([a-f0-9][0,2,4,6,8,a,c,e]:([a-f0-9]{2}:){4})|([a-f0-9][0,2,4,6,8,a,c,e]-([a-f0-9]{2}-){4}))[a-f0-9]{2}$/i; + return reg.test(mac); +}; + +/** 判断是否为 IPv4 地址 */ +export const isIPv4 = (ip: string) => { + const reg = + /^((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])(?::(?:[0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?$/; + return reg.test(ip); +}; + +/** 判断是否为车牌(兼容新能源车牌) */ +export const isLicensePlate = (str: string) => { + const reg = + /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$/; + return reg.test(str); +}; diff --git a/src/views/dashboard/components/Admin.vue b/src/views/dashboard/components/Admin.vue new file mode 100644 index 0000000..7964172 --- /dev/null +++ b/src/views/dashboard/components/Admin.vue @@ -0,0 +1,14 @@ + + + diff --git a/src/views/dashboard/components/Editor.vue b/src/views/dashboard/components/Editor.vue new file mode 100644 index 0000000..2f369d6 --- /dev/null +++ b/src/views/dashboard/components/Editor.vue @@ -0,0 +1,14 @@ + + + diff --git a/src/views/dashboard/index.vue b/src/views/dashboard/index.vue new file mode 100644 index 0000000..3b4d4c6 --- /dev/null +++ b/src/views/dashboard/index.vue @@ -0,0 +1,12 @@ + + + diff --git a/src/views/error-page/403.vue b/src/views/error-page/403.vue new file mode 100644 index 0000000..25eb20f --- /dev/null +++ b/src/views/error-page/403.vue @@ -0,0 +1,10 @@ + + + diff --git a/src/views/error-page/404.vue b/src/views/error-page/404.vue new file mode 100644 index 0000000..e95d5d8 --- /dev/null +++ b/src/views/error-page/404.vue @@ -0,0 +1,10 @@ + + + diff --git a/src/views/error-page/components/ErrorPageLayout.vue b/src/views/error-page/components/ErrorPageLayout.vue new file mode 100644 index 0000000..a0c2038 --- /dev/null +++ b/src/views/error-page/components/ErrorPageLayout.vue @@ -0,0 +1,25 @@ + + + diff --git a/src/views/hook-demo/use-fetch-select.vue b/src/views/hook-demo/use-fetch-select.vue new file mode 100644 index 0000000..221a969 --- /dev/null +++ b/src/views/hook-demo/use-fetch-select.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/views/hook-demo/use-fullscreen-loading.vue b/src/views/hook-demo/use-fullscreen-loading.vue new file mode 100644 index 0000000..87fad96 --- /dev/null +++ b/src/views/hook-demo/use-fullscreen-loading.vue @@ -0,0 +1,47 @@ + + + diff --git a/src/views/hook-demo/use-watermark.vue b/src/views/hook-demo/use-watermark.vue new file mode 100644 index 0000000..c7cd95c --- /dev/null +++ b/src/views/hook-demo/use-watermark.vue @@ -0,0 +1,47 @@ + + + + + diff --git a/src/views/login/index.vue b/src/views/login/index.vue new file mode 100644 index 0000000..5d50f9b --- /dev/null +++ b/src/views/login/index.vue @@ -0,0 +1,190 @@ + + + + + diff --git a/src/views/menu/menu1/index.vue b/src/views/menu/menu1/index.vue new file mode 100644 index 0000000..4215ad4 --- /dev/null +++ b/src/views/menu/menu1/index.vue @@ -0,0 +1,23 @@ + + + diff --git a/src/views/menu/menu1/menu1-1/index.vue b/src/views/menu/menu1/menu1-1/index.vue new file mode 100644 index 0000000..430d582 --- /dev/null +++ b/src/views/menu/menu1/menu1-1/index.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/views/menu/menu1/menu1-2/index.vue b/src/views/menu/menu1/menu1-2/index.vue new file mode 100644 index 0000000..79eb6d5 --- /dev/null +++ b/src/views/menu/menu1/menu1-2/index.vue @@ -0,0 +1,7 @@ + diff --git a/src/views/menu/menu1/menu1-2/menu1-2-1/index.vue b/src/views/menu/menu1/menu1-2/menu1-2-1/index.vue new file mode 100644 index 0000000..88747f8 --- /dev/null +++ b/src/views/menu/menu1/menu1-2/menu1-2-1/index.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/views/menu/menu1/menu1-2/menu1-2-2/index.vue b/src/views/menu/menu1/menu1-2/menu1-2-2/index.vue new file mode 100644 index 0000000..ae3e4cd --- /dev/null +++ b/src/views/menu/menu1/menu1-2/menu1-2-2/index.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/views/menu/menu1/menu1-3/index.vue b/src/views/menu/menu1/menu1-3/index.vue new file mode 100644 index 0000000..63f24aa --- /dev/null +++ b/src/views/menu/menu1/menu1-3/index.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/views/menu/menu2/index.vue b/src/views/menu/menu2/index.vue new file mode 100644 index 0000000..89cd53c --- /dev/null +++ b/src/views/menu/menu2/index.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/views/permission/components/SwitchRoles.vue b/src/views/permission/components/SwitchRoles.vue new file mode 100644 index 0000000..7b721e3 --- /dev/null +++ b/src/views/permission/components/SwitchRoles.vue @@ -0,0 +1,37 @@ + + + + + diff --git a/src/views/permission/directive.vue b/src/views/permission/directive.vue new file mode 100644 index 0000000..7b05de8 --- /dev/null +++ b/src/views/permission/directive.vue @@ -0,0 +1,62 @@ + + + + + diff --git a/src/views/permission/page.vue b/src/views/permission/page.vue new file mode 100644 index 0000000..8212d9e --- /dev/null +++ b/src/views/permission/page.vue @@ -0,0 +1,22 @@ + + + + + diff --git a/src/views/redirect/index.vue b/src/views/redirect/index.vue new file mode 100644 index 0000000..8eb277b --- /dev/null +++ b/src/views/redirect/index.vue @@ -0,0 +1,12 @@ + + + diff --git a/src/views/table/element-plus/index.vue b/src/views/table/element-plus/index.vue new file mode 100644 index 0000000..49f8ac5 --- /dev/null +++ b/src/views/table/element-plus/index.vue @@ -0,0 +1,256 @@ + + + + + diff --git a/src/views/table/vxe-table/index.vue b/src/views/table/vxe-table/index.vue new file mode 100644 index 0000000..219aaf1 --- /dev/null +++ b/src/views/table/vxe-table/index.vue @@ -0,0 +1,375 @@ + + + diff --git a/src/views/table/vxe-table/tsx/RoleColumnSolts.tsx b/src/views/table/vxe-table/tsx/RoleColumnSolts.tsx new file mode 100644 index 0000000..3d185d2 --- /dev/null +++ b/src/views/table/vxe-table/tsx/RoleColumnSolts.tsx @@ -0,0 +1,11 @@ +import { type VxeColumnPropTypes } from "vxe-table/types/column"; + +const solts: VxeColumnPropTypes.Slots = { + default: ({ row, column }) => { + const cellValue = row[column.field]; + const type = cellValue === "admin" ? "" : "warning"; + return [{cellValue}]; + } +}; + +export default solts; diff --git a/src/views/table/vxe-table/tsx/StatusColumnSolts.tsx b/src/views/table/vxe-table/tsx/StatusColumnSolts.tsx new file mode 100644 index 0000000..ca4ac8a --- /dev/null +++ b/src/views/table/vxe-table/tsx/StatusColumnSolts.tsx @@ -0,0 +1,11 @@ +import { type VxeColumnPropTypes } from "vxe-table/types/column"; + +const solts: VxeColumnPropTypes.Slots = { + default: ({ row, column }) => { + const cellValue = row[column.field]; + const [type, value] = cellValue ? ["success", "启用"] : ["danger", "禁用"]; + return [{value}]; + } +}; + +export default solts; diff --git a/src/views/unocss/index.vue b/src/views/unocss/index.vue new file mode 100644 index 0000000..9859ecb --- /dev/null +++ b/src/views/unocss/index.vue @@ -0,0 +1,13 @@ + diff --git a/tests/components/Notify.test.ts b/tests/components/Notify.test.ts new file mode 100644 index 0000000..9d0a692 --- /dev/null +++ b/tests/components/Notify.test.ts @@ -0,0 +1,34 @@ +import { shallowMount } from "@vue/test-utils"; +import { describe, expect, it } from "vitest"; +import Notify from "@/components/Notify/index.vue"; +import NotifyList from "@/components/Notify/NotifyList.vue"; + +describe("Notify", () => { + it("正常渲染", () => { + const wrapper = shallowMount(Notify); + expect(wrapper.classes("notify")).toBe(true); + }); +}); + +describe("NotifyList", () => { + it("List 长度为 0", () => { + const wrapper = shallowMount(NotifyList, { + props: { + list: [] + } + }); + expect(wrapper.find("el-empty").exists()).toBe(true); + }); + it("List 长度不为 0", () => { + const wrapper = shallowMount(NotifyList, { + props: { + list: [ + { + title: "" + } + ] + } + }); + expect(wrapper.find("el-empty").exists()).toBe(false); + }); +}); diff --git a/tests/demo.test.ts b/tests/demo.test.ts new file mode 100644 index 0000000..bdfbc07 --- /dev/null +++ b/tests/demo.test.ts @@ -0,0 +1,32 @@ +import { describe, expect, it } from "vitest"; + +/** + * @description 该文件所有示例均是为了向你演示 Vitest 最基本的用法 + * @link https://cn.vitest.dev/api + * @api describe: 形成一个作用域 + * @api test/it: 定义了一组关于测试期望的方法,它接收测试名称和一个含有测试期望的函数 + * @api expect: 用来创建断言 + * @api toBe: 可以用于断言原始类型是否相等,或者对象是否共享相同的引用 + * @api toEqual: 断言实际值是否等于接收到的值或具有相同的结构(如果是对象,则递归比较它们) + */ + +const author1 = { + name: "pany", + email: "939630029@qq.com", + url: "https://github.com/pany-ang" +}; + +const author2 = { + name: "pany", + email: "939630029@qq.com", + url: "https://github.com/pany-ang" +}; + +describe("这里填写作用域名称", () => { + it("测试基础数据类型", () => { + expect(1 + 1).toBe(2); + }); + it("测试引用类型", () => { + expect(author1).toEqual(author2); + }); +}); diff --git a/tests/utils/validate.test.ts b/tests/utils/validate.test.ts new file mode 100644 index 0000000..83be424 --- /dev/null +++ b/tests/utils/validate.test.ts @@ -0,0 +1,32 @@ +import { describe, expect, it } from "vitest"; +import { isArray } from "@/utils/validate"; + +describe("isArray", () => { + it("String", () => { + expect(isArray("")).toBe(false); + }); + it("Number", () => { + expect(isArray(1)).toBe(false); + }); + it("Boolean", () => { + expect(isArray(true)).toBe(false); + }); + it("Null", () => { + expect(isArray(null)).toBe(false); + }); + it("Undefined", () => { + expect(isArray(undefined)).toBe(false); + }); + it("Symbol", () => { + expect(isArray(Symbol())).toBe(false); + }); + it("BigInt", () => { + expect(isArray(BigInt(1))).toBe(false); + }); + it("Object", () => { + expect(isArray({})).toBe(false); + }); + it("Array Object", () => { + expect(isArray([])).toBe(true); + }); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..c28f2fc --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,48 @@ +{ + "compilerOptions": { + "target": "esnext", + /** https://cn.vitejs.dev/guide/features.html#typescript-compiler-options */ + "useDefineForClassFields": true, + "module": "esnext", + "moduleResolution": "bundler", + /** TS 严格模式 */ + "strict": true, + "jsx": "preserve", + "jsxImportSource": "vue", + "importHelpers": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "sourceMap": true, + "resolveJsonModule": true, + /** https://cn.vitejs.dev/guide/features.html#typescript-compiler-options */ + "isolatedModules": true, + "esModuleInterop": true, + "lib": ["esnext", "dom"], + "skipLibCheck": true, + "types": [ + "node", + "vite/client", + /** Element Plus 的 Volar 插件支持 */ + "element-plus/global", + "vitest" + ], + /** baseUrl 用来告诉编译器到哪里去查找模块,使用非相对模块时必须配置此项 */ + "baseUrl": ".", + /** 非相对模块导入的路径映射配置,根据 baseUrl 配置进行路径计算 */ + "paths": { + "@/*": ["src/*"] + } + }, + "include": [ + "src/**/*.ts", + "src/**/*.d.ts", + "src/**/*.tsx", + "src/**/*.vue", + "tests/**/*.ts", + "types/**/*.d.ts", + "vite.config.ts", + "vitest.config.ts" + ], + /** 编译器默认排除的编译文件 */ + "exclude": ["node_modules", "dist"] +} diff --git a/types/api.d.ts b/types/api.d.ts new file mode 100644 index 0000000..6dc8ac4 --- /dev/null +++ b/types/api.d.ts @@ -0,0 +1,6 @@ +/** 所有 api 接口的响应数据都应该准守该格式 */ +interface ApiResponseData { + code: number; + data: T; + message: string; +} diff --git a/types/env.d.ts b/types/env.d.ts new file mode 100644 index 0000000..b7d451d --- /dev/null +++ b/types/env.d.ts @@ -0,0 +1,11 @@ +/** 声明 vite 环境变量的类型(如果未声明则默认是 any) */ +declare interface ImportMetaEnv { + readonly VITE_APP_TITLE: string; + readonly VITE_BASE_API: string; + readonly VITE_ROUTER_HISTORY: "hash" | "html5"; + readonly VITE_PUBLIC_PATH: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/types/global-components.d.ts b/types/global-components.d.ts new file mode 100644 index 0000000..47db16e --- /dev/null +++ b/types/global-components.d.ts @@ -0,0 +1,10 @@ +import SvgIcon from "@/components/SvgIcon/index.vue"; + +/** 由 app.component 全局注册的组件需要在这里声明 TS 类型才能获得 Volar 插件提供的类型提示) */ +declare module "vue" { + export interface GlobalComponents { + SvgIcon: typeof SvgIcon; + } +} + +export {}; diff --git a/types/shims-vue.d.ts b/types/shims-vue.d.ts new file mode 100644 index 0000000..c83b34e --- /dev/null +++ b/types/shims-vue.d.ts @@ -0,0 +1,4 @@ +declare module "*.scss" { + const scss: Record; + export default scss; +} diff --git a/types/vue-router.d.ts b/types/vue-router.d.ts new file mode 100644 index 0000000..314f34f --- /dev/null +++ b/types/vue-router.d.ts @@ -0,0 +1,52 @@ +import "vue-router"; + +declare module "vue-router" { + interface RouteMeta { + /** + * 设置该路由在侧边栏和面包屑中展示的名字 + */ + title?: string; + /** + * 设置该路由的图标,记得将 svg 导入 @/icons/svg + */ + svgIcon?: string; + /** + * 设置该路由的图标,直接使用 Element Plus 的 Icon(与 svgIcon 同时设置时,svgIcon 将优先生效) + */ + elIcon?: string; + /** + * 默认 false,设置 true 的时候该路由不会在侧边栏出现 + */ + hidden?: boolean; + /** + * 设置该路由进入的权限,支持多个权限叠加 + */ + roles?: string[]; + /** + * 默认 true,如果设置为 false,则不会在面包屑中显示 + */ + breadcrumb?: boolean; + /** + * 默认 false,如果设置为 true,它则会固定在 tags-view 中 + */ + affix?: boolean; + /** + * 当一个路由下面的 children 声明的路由大于 1 个时,自动会变成嵌套的模式, + * 只有一个时,会将那个子路由当做根路由显示在侧边栏, + * 若想不管路由下面的 children 声明的个数都显示你的根路由, + * 可以设置 alwaysShow: true,这样就会忽略之前定义的规则,一直显示根路由 + */ + alwaysShow?: boolean; + /** + * 示例: activeMenu: "/xxx/xxx", + * 当设置了该属性进入路由时,则会高亮 activeMenu 属性对应的侧边栏。 + * 该属性适合使用在有 hidden: true 属性的路由上 + */ + activeMenu?: string; + /** + * 是否缓存该路由页面 + * 默认为 false,为 true 时代表需要缓存,此时该路由和该页面都需要设置一致的 Name + */ + keepAlive?: boolean; + } +} diff --git a/unocss.config.ts b/unocss.config.ts new file mode 100644 index 0000000..b9978cb --- /dev/null +++ b/unocss.config.ts @@ -0,0 +1,20 @@ +import { defineConfig, presetAttributify, presetUno } from "unocss"; + +export default defineConfig({ + /** 预设 */ + presets: [ + /** 属性化模式 & 无值的属性模式 */ + presetAttributify(), + /** 默认预设 */ + presetUno() + ], + /** 自定义规则 */ + rules: [["uno-padding-20", { padding: "20px" }]], + /** 自定义快捷方式 */ + shortcuts: { + "uno-wh-full": "w-full h-full", + "uno-flex-center": "flex justify-center items-center", + "uno-flex-x-center": "flex justify-center", + "uno-flex-y-center": "flex items-center" + } +}); diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..fac0832 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,100 @@ +/// + +import { type ConfigEnv, type UserConfigExport, loadEnv } from "vite"; +import path, { resolve } from "path"; +import vue from "@vitejs/plugin-vue"; +import vueJsx from "@vitejs/plugin-vue-jsx"; +import { createSvgIconsPlugin } from "vite-plugin-svg-icons"; +import svgLoader from "vite-svg-loader"; +import UnoCSS from "unocss/vite"; + +/** 配置项文档:https://cn.vitejs.dev/config */ +export default (configEnv: ConfigEnv): UserConfigExport => { + const viteEnv = loadEnv(configEnv.mode, process.cwd()) as ImportMetaEnv; + const { VITE_PUBLIC_PATH } = viteEnv; + return { + /** 打包时根据实际情况修改 base */ + base: VITE_PUBLIC_PATH, + resolve: { + alias: { + /** @ 符号指向 src 目录 */ + "@": resolve(__dirname, "./src") + } + }, + server: { + /** 设置 host: true 才可以使用 Network 的形式,以 IP 访问项目 */ + host: true, // host: "0.0.0.0" + /** 端口号 */ + port: 3333, + /** 是否自动打开浏览器 */ + open: false, + /** 跨域设置允许 */ + cors: true, + /** 端口被占用时,是否直接退出 */ + strictPort: false, + /** 接口代理 */ + proxy: { + "/api/v1": { + target: "https://mock.mengxuegu.com/mock/63218b5fb4c53348ed2bc212", + ws: true, + /** 是否允许跨域 */ + changeOrigin: true + } + }, + /** 预热常用文件,提高初始页面加载速度 */ + warmup: { + clientFiles: ["./src/layouts/**/*.vue"] + } + }, + build: { + /** 单个 chunk 文件的大小超过 2048KB 时发出警告 */ + chunkSizeWarningLimit: 2048, + /** 禁用 gzip 压缩大小报告 */ + reportCompressedSize: false, + /** 打包后静态资源目录 */ + assetsDir: "static", + rollupOptions: { + output: { + /** + * 分块策略 + * 1. 注意这些包名必须存在,否则打包会报错 + * 2. 如果你不想自定义 chunk 分割策略,可以直接移除这段配置 + */ + manualChunks: { + vue: ["vue", "vue-router", "pinia"], + element: ["element-plus", "@element-plus/icons-vue"], + vxe: ["vxe-table", "vxe-table-plugin-element", "xe-utils"] + } + } + } + }, + /** 混淆器 */ + esbuild: { + /** 打包时移除 console.log */ + pure: ["console.log"], + /** 打包时移除 debugger */ + drop: ["debugger"], + /** 打包时移除所有注释 */ + legalComments: "none" + }, + /** Vite 插件 */ + plugins: [ + vue(), + vueJsx(), + /** 将 SVG 静态图转化为 Vue 组件 */ + svgLoader({ defaultImport: "url" }), + /** SVG */ + createSvgIconsPlugin({ + iconDirs: [path.resolve(process.cwd(), "src/icons/svg")], + symbolId: "icon-[dir]-[name]" + }), + /** UnoCSS */ + UnoCSS() + ], + /** Vitest 单元测试配置:https://cn.vitest.dev/config */ + test: { + include: ["tests/**/*.test.ts"], + environment: "jsdom" + } + }; +};