From 36613cd17bd56508f38f9ba5918a3fb2ada6fdf5 Mon Sep 17 00:00:00 2001 From: fonghehe <331002675@qq.com> Date: Fri, 19 Aug 2022 18:23:00 +0800 Subject: [PATCH] docs: init document --- .github/workflows/deploy.yml | 25 ++ .gitignore | 1 + README.md | 496 +++++++++++++++++++++ docs/.vitepress/config.js | 99 +++++ docs/.vitepress/theme/custom.css | 61 +++ docs/.vitepress/theme/index.js | 4 + docs/guide/edit.md | 19 + docs/guide/index.md | 23 + docs/guide/start.md | 17 + docs/guide/vue2/alias.md | 19 + docs/guide/vue2/axios.md | 106 +++++ docs/guide/vue2/base.md | 36 ++ docs/guide/vue2/bundle.md | 22 + docs/guide/vue2/chunks.md | 45 ++ docs/guide/vue2/console.md | 34 ++ docs/guide/vue2/env.md | 84 ++++ docs/guide/vue2/externals.md | 84 ++++ docs/guide/vue2/ie.md | 30 ++ docs/guide/vue2/lint.md | 165 +++++++ docs/guide/vue2/proxy.md | 36 ++ docs/guide/vue2/rem.md | 69 +++ docs/guide/vue2/router.md | 34 ++ docs/guide/vue2/sass.md | 104 +++++ docs/guide/vue2/start.md | 17 + docs/guide/vue2/vant.md | 49 +++ docs/guide/vue2/vuex.md | 45 ++ docs/guide/vue2/vw.md | 61 +++ docs/guide/vue3/alias.md | 21 + docs/guide/vue3/axios.md | 67 +++ docs/guide/vue3/base.md | 45 ++ docs/guide/vue3/env.md | 13 + docs/guide/vue3/lint.md | 3 + docs/guide/vue3/pinia.md | 22 + docs/guide/vue3/proxy.md | 13 + docs/guide/vue3/router.md | 29 ++ docs/guide/vue3/start.md | 14 + docs/guide/vue3/ui.md | 58 +++ docs/guide/vue3/viewport.md | 76 ++++ docs/guide/vue3/vite.md | 17 + docs/index.md | 34 ++ package.json | 10 + pnpm-lock.yaml | 710 +++++++++++++++++++++++++++++++ 42 files changed, 2917 insertions(+) create mode 100644 .github/workflows/deploy.yml create mode 100644 .gitignore create mode 100644 README.md create mode 100644 docs/.vitepress/config.js create mode 100644 docs/.vitepress/theme/custom.css create mode 100644 docs/.vitepress/theme/index.js create mode 100644 docs/guide/edit.md create mode 100644 docs/guide/index.md create mode 100644 docs/guide/start.md create mode 100644 docs/guide/vue2/alias.md create mode 100644 docs/guide/vue2/axios.md create mode 100644 docs/guide/vue2/base.md create mode 100644 docs/guide/vue2/bundle.md create mode 100644 docs/guide/vue2/chunks.md create mode 100644 docs/guide/vue2/console.md create mode 100644 docs/guide/vue2/env.md create mode 100644 docs/guide/vue2/externals.md create mode 100644 docs/guide/vue2/ie.md create mode 100644 docs/guide/vue2/lint.md create mode 100644 docs/guide/vue2/proxy.md create mode 100644 docs/guide/vue2/rem.md create mode 100644 docs/guide/vue2/router.md create mode 100644 docs/guide/vue2/sass.md create mode 100644 docs/guide/vue2/start.md create mode 100644 docs/guide/vue2/vant.md create mode 100644 docs/guide/vue2/vuex.md create mode 100644 docs/guide/vue2/vw.md create mode 100644 docs/guide/vue3/alias.md create mode 100644 docs/guide/vue3/axios.md create mode 100644 docs/guide/vue3/base.md create mode 100644 docs/guide/vue3/env.md create mode 100644 docs/guide/vue3/lint.md create mode 100644 docs/guide/vue3/pinia.md create mode 100644 docs/guide/vue3/proxy.md create mode 100644 docs/guide/vue3/router.md create mode 100644 docs/guide/vue3/start.md create mode 100644 docs/guide/vue3/ui.md create mode 100644 docs/guide/vue3/viewport.md create mode 100644 docs/guide/vue3/vite.md create mode 100644 docs/index.md create mode 100644 package.json create mode 100644 pnpm-lock.yaml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..892455c --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,25 @@ +name: deployment + +on: + push: + branches: ["docs"] + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v3 + with: + node-version: 16 + cache: yarn + - run: yarn install --frozen-lockfile + + - name: Build + run: yarn docs:build + + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: docs/.vitepress/dist diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..ed7ccc3 --- /dev/null +++ b/README.md @@ -0,0 +1,496 @@ +# vue-h5-template + +基于 vue3 + vite + (nutui or varlet or vant) + sass + viewport 适配方案 +axios 封装,构建手机端模板脚手架 + +如果你不熟悉 vue3,想继续使用 vue2 开发的,可以[点这里](https://github.com/sunniejs/vue-h5-template/tree/vue2-h5-template)来获取 vue2-h5-template + +掘金: [移动端适配方案](https://juejin.cn/post/7018433228591595550) + +

+ +

+ +### Node 版本要求 + +推荐你使用 NodeJs 14+的版本,毕竟技术日新月异。你可以使用 [nvm](https://github.com/nvm-sh/nvm) 或 [nvm-windows](https://github.com/coreybutler/nvm-windows) 在同一台电脑中管理多个 Node 版本。 + +本示例 Node.js 14.19.0 + +### 启动项目(强烈推荐使用 yarn) + +```bash + +git clone https://github.com/sunniejs/vue-h5-template.git + +cd vue-h5-template + +yarn install + +yarn dev +``` + +目录 + +- [√ vite](#vite) +- [√ 配置多环境变量](#env) +- [√ viewport 适配方案](#viewport) +- [√ 多 UI 组件库供选择](#ui) +- [√ Pinia 状态管理](#Pinia) +- [√ vue-router 4](#router) +- [√ axios 封装及接口管理](#axios) +- [√ vite.config.ts 基础配置](#base) +- [√ alias](#alias) +- [√ proxy 跨域](#proxy) +- [√ Eslint+Pettier+stylelint 统一开发规范 ](#lint) + +### ✅ vite + +基于原生 ES 模块提供了丰富的内建功能,如速度快到惊人的模块热更新(HMR),使用 Rollup 打包你的代码,并且它是预配置的,可输出用于生产环境的高度优化过的静态资源。更多关于[vite](https://cn.vitejs.dev/guide/) + +模版集成了如下的 vite 插件 + +- unplugin-auto-import(按需加载,自动引入) +- unplugin-vue-components(按需加载,自动引入组件) +- vite-plugin-compression(开启.gz 压缩) +- vite-plugin-eruda(控制台,方便移动端调试) +- vite-plugin-imagemin(图片压缩) +- vite-plugin-mock(引入 mockjs,本地模拟接口) +- vite-plugin-pages(动态生成路由) +- vite-plugin-progress(构建显示进度条) +- vite-plugin-restart(监听配置文件修改自动重启 Vite) +- vite-plugin-style-import(按需引入样式文件) +- vite-plugin-svg-icons(加载 SVG 文件,自动引入) + +### ✅ 配置多环境变量 + +`package.json` 里的 `scripts` 配置 `dev` `dev:test` `dev:prod` ,通过 `--mode xxx` 来执行不同环境 + +- 通过 `yarn dev` 启动本地环境参数 , 执行 `development` +- 通过 `yarn dev:test` 启动测试环境参数 , 执行 `test` +- 通过 `yarn dev:prod` 启动正式环境参数 , 执行 `prod` + +```javascript +"scripts": { + "dev": "vite", + "dev:test": "vite --mode test", + "dev:prod": "vite --mode production", +} +``` + +[▲ 回顶部](#top) + +### ✅ viewport 适配方案 + +不用担心,项目已经配置好了 `viewport` 适配,下面仅做介绍: + +- [cnjm-postcss-px-to-viewport](https://github.com/cnjm/postcss-px-to-viewport) 是一款 `postcss` 插件,用于将单位转化为 `vw`, 现在很多浏览器对`vw`的支持都很好,适配首选方案。 + +##### PostCSS 配置 + +下面提供了一份基本的 `postcss` 配置,可以在此配置的基础上根据项目需求进行修改 + +```javascript +// https://github.com/michael-ciniawsky/postcss-load-config +module.exports = { + plugins: { + autoprefixer: { overrideBrowserslist: ['Android 4.1', 'iOS 7.1', 'Chrome > 31', 'ff > 31', 'ie >= 8'] }, + 'cnjm-postcss-px-to-viewport': { + unitToConvert: 'px', // 要转化的单位 + viewportWidth: 750, // UI设计稿的宽度 + unitPrecision: 6, // 转换后的精度,即小数点位数 + propList: ['*'], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换 + viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw + fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw + minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换 + mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false + replace: true, // 是否转换后直接更换属性值 + include: [], + exclude: [], // 设置忽略文件,用正则做目录名匹配 + customFun: ({ file }) => { + // 这个自定义的方法是针对处理vant组件下的设计稿为375问题 + const designWidth = judgeComponent(file) ? 375 : 750; + return designWidth; + }, + }, +}; +``` + +**新手必看,老鸟跳过** + +很多小伙伴会问我,适配的问题, 因为我们使用的是 Vant UI,所以必须根据 Vant UI 375 的设计规范走,一般我们的设计会将 UI 图上传到蓝湖,我们就可以需要的尺寸了。下面就大搞普及一下 rem。 + +我们知道 `1rem` 等于 `html` 根元素设定的 `font-size` 的 `px` 值。Vant UI 设置 `rootValue: 37.5` , 你可以看到在 iPhone 6 下看到 ( `1rem 等于 37.5px` ): + +```html + +``` + +切换不同的机型,根元素可能会有不同的 `font-size` 。当你写 css px 样式时,会被程序换算成 `rem` 达到适配。 + +因为我们用了 Vant 的组件,需要按照 `rootValue: 37.5` 来写样式。 + +举个例子:设计给了你一张 750px \* 1334px 图片,在 iPhone6 上铺满屏幕, 其他机型适配。 + +- 当`rootValue: 75` , 样式 `width: 750px;height: 1334px;` 图片会撑满 iPhone6 屏幕,这个时候切换其他机型,图片也会跟着撑满。 +- 当`rootValue: 37.5` 的时候,样式 `width: 375px;height: 667px;` 图片会撑满 iPhone6 屏幕。 + +也就是 iphone 6 下 375px 宽度写 CSS。其他的你就可以根据你设计图,去写对应的样式就可以了。 + +当然,想要撑满屏幕你可以使用 100%,这里只是举例说明。 + +```html + + + +``` + +[▲ 回顶部](#top) + +### ✅ 多 UI 组件库供选择 + +Vite 构建工具,使用 vite-plugin-style-import 和 unplugin-vue-components/vite 实现按需引入。 + +#### 安装插件 + +```bash +yarn add vite-plugin-style-import -D +yarn add unplugin-vue-components/vite -D +``` + +#### 使用组件库 + +nutUI 没有按需加载的 resolvers,style 需要自己配置按需加载 + +在 `config/vite/plugins/styleImport.ts` 设置 + +```javascript + // 按需加载样式文件 + ... + createStyleImportPlugin({ + resolves: [NutuiResolve()], + }), + ... +``` + +项目在 `src/plugins/nutUI.ts` 下统一管理组件,用哪个引入哪个,无需在页面里重复引用 + +```javascript +// 按需全局引入nutUI组件 +import Vue from 'vue'; +import { Button, Cell, CellGroup } from '@nutui/nutui'; +export const nutUiComponents = [Button, Cell, CellGroup]; + +// 在main.ts文件中引入 +nutUiComponents.forEach((item) => { + app.use(item); +}); +``` + +vant 和 varlet 可以使用组件按需加载 + +在`config/vite/plugins/component.ts`下 + +```javascript +import { VueUseComponentsResolver, VantResolver, VarletUIResolver } from 'unplugin-vue-components/resolvers'; +... +resolvers: [VantResolver(), VarletUIResolver()], +... +``` + +#### 不需要某个组件库 + +nutUI 需删除`src/plugins/nutUI.ts`和`main.ts`文件下的引入 + +vant 和 varlet 只需删除对应的 resolvers 即可 + +删除后需全局搜索删除不需要的组件,避免报错 + +[▲ 回顶部](#top) + +### ✅ Pinia 状态管理 + +下一代 vuex,使用极其方便,ts 兼容好 + +目录结构 + +```bash +├── store +│ ├── modules +│ │ └── user.js +│ ├── index.js +``` + +使用 + +```html + +``` + +[▲ 回顶部](#top) + +### ✅ Vue-router + +本案例采用 `hash` 模式,开发者根据需求修改 `mode` `base` + +**注意**:如果你使用了 `history` 模式, `vue.config.js` 中的 `publicPath` 要做对应的**修改** + +前往:[vue.config.js 基础配置](#base) + +```javascript +import Vue from 'vue'; +import { createRouter, createWebHistory, Router } from 'vue-router'; + +Vue.use(Router); +export const router = [ + { + name: 'root', + path: '/', + redirect: '/home', + component: () => import('@/layout/basic/index.vue'), + }, +]; + +const router: Router = createRouter({ + history: createWebHistory(), + routes: routes, +}); + +export default router; +``` + +更多:[Vue Router](https://router.vuejs.org/zh/introduction.html) + +[▲ 回顶部](#top) + +### ✅ Axios 封装及接口管理 + +`utils/request.js` 封装 axios , 开发者需要根据后台接口做修改。 + +- `service.interceptors.request.use` 里可以设置请求头,比如设置 `token` +- `config.hideloading` 是在 api 文件夹下的接口参数里设置,下文会讲 +- `service.interceptors.response.use` 里可以对接口返回数据处理,比如 401 删除本地信息,重新登录 + +```javascript +import axios from 'axios'; +import store from '@/store'; +import { Toast } from 'vant'; +// 根据环境不同引入不同api地址 +import { baseApi } from '@/config'; +// create an axios instance +const service = axios.create({ + baseURL: baseApi, // url = base api url + request url + withCredentials: true, // send cookies when cross-domain requests + timeout: 5000, // request timeout +}); + +// request 拦截器 request interceptor +service.interceptors.request.use( + (config) => { + // 不传递默认开启loading + if (!config.hideloading) { + // loading + Toast.loading({ + forbidClick: true, + }); + } + if (store.getters.token) { + config.headers['X-Token'] = ''; + } + return config; + }, + (error) => { + // do something with request error + console.log(error); // for debug + return Promise.reject(error); + }, +); +// respone拦截器 +service.interceptors.response.use( + (response) => { + Toast.clear(); + const res = response.data; + if (res.status && res.status !== 200) { + // 登录超时,重新登录 + if (res.status === 401) { + store.dispatch('FedLogOut').then(() => { + location.reload(); + }); + } + return Promise.reject(res || 'error'); + } else { + return Promise.resolve(res); + } + }, + (error) => { + Toast.clear(); + console.log('err' + error); // for debug + return Promise.reject(error); + }, +); +export default service; +``` + +#### 接口管理 + +在 `src/api` 文件夹下统一管理接口 + +- 你可以建立多个模块对接接口, 比如 `home.js` 里是首页的接口这里讲解 `user.js` +- `url` 接口地址,请求的时候会拼接上 `config` 下的 `baseApi` +- `method` 请求方法 +- `data` 请求参数 `qs.stringify(params)` 是对数据系列化操作 +- `hideloading` 默认 `false`, 设置为 `true` 后,不显示 loading ui 交互中有些接口不需要让用户感知 + +```javascript +import qs from 'qs'; +// axios +import request from '@/utils/request'; +//user api + +// 用户信息 +export function getUserInfo(params) { + return request({ + url: '/user/userinfo', + method: 'post', + data: qs.stringify(params), + hideloading: true, // 隐藏 loading 组件 + }); +} +``` + +#### 如何调用 + +```javascript +// 请求接口 +import { getUserInfo } from '@/api/user.js'; + +const params = { + user: 'sunnie', +}; +getUserInfo(params) + .then(() => {}) + .catch(() => {}); +``` + +[▲ 回顶部](#top) + +### ✅ vite.config.ts 基础配置 + +如果你的 `Vue Router` 模式是 hash + +```javascript +publicPath: './', +``` + +如果你的 `Vue Router` 模式是 history 这里的 publicPath 和你的 `Vue Router` `base` **保持一致** + +```javascript +publicPath: '/app/', +``` + +```javascript +export default function ({ command }: ConfigEnv): UserConfigExport { + const isProduction = command === 'build'; + return { + server: { + host: '0.0.0.0', + }, + plugins: [ + vue(), + vueJsx(), + createStyleImportPlugin({ + resolves: [NutuiResolve()], + }), + eruda(), + viteMockServe({ + mockPath: './src/mock', + localEnabled: command === 'serve', + logger: true, + }), + ], + css: { + preprocessorOptions: { + scss: { + // 配置 nutui 全局 scss 变量 + additionalData: `@import "@nutui/nutui/dist/styles/variables.scss";`, + }, + }, + }, + }; +} +``` + +[▲ 回顶部](#top) + +### ✅ 配置 alias 别名 + +```javascript +resolve: { + alias: [{ + find: 'vue-i18n', + replacement: 'vue-i18n/dist/vue-i18n.cjs.js', + }, + // /@/xxxx => src/xxxx + { + find: /\/@\//, + replacement: pathResolve('src') + '/', + }, + // /#/xxxx => types/xxxx + { + find: /\/#\//, + replacement: pathResolve('types') + '/', + }, + ], +}, +``` + +[▲ 回顶部](#top) + +### ✅ 配置 proxy 跨域 + +```javascript +server: { + proxy: { + '/api': { + target: 'https://baidu.com', + changeOrigin: true, + rewrite: (path) => path.replace(/^\/api/, '') + } + } +}, +``` + +[▲ 回顶部](#top) + +### ✅ Eslint+Pettier+stylelint 统 ˜ 开发规范 + +根目录下的`.eslintrc.js`、`.stylelint.config.js`、`.prettier.config.js`内置了 lint 规则,帮助你规范地开发代码,有助于提高团队的代码质量和协作性,可以根据团队的规则进行修改 + +# 关于我 + +扫描添加下方的微信并备注加交流群,交流学习,及时获取代码最新动态。 + +

+ +

+ +

+ +

+ +如果对你有帮助送我一颗珍贵的小星星(づ ̄3 ̄)づ╭❤~ diff --git a/docs/.vitepress/config.js b/docs/.vitepress/config.js new file mode 100644 index 0000000..953e2ad --- /dev/null +++ b/docs/.vitepress/config.js @@ -0,0 +1,99 @@ +module.exports = { + lang: "zh-CN", + title: "Vue-H5-Template", + base: "/fastool/", + description: "一个开箱即用的vue h5脚手架", + lastUpdated: true, + head: [ + // 添加图标 + ["link", { rel: "icon", href: "/favicon.ico" }], + ], + themeConfig: { + nav: nav(), + sidebar: { + "/guide/": sidebarGuide(), + }, + socialLinks: [ + { icon: "github", link: "https://github.com/tobe-fe-dalao/fastool" }, + ], + editLink: { + pattern: "https://github.com/tobe-fe-dalao/fastool/tree/doc/docs/:path", + text: "在GitHub编辑此页", + }, + footer: { + message: "Released under the MIT License.", + copyright: "Copyright © 2022-present Fonghehe", + }, + algolia: { + appId: "5ZHOMUV2DI", + apiKey: "d1de686f0fd4404abc0897093c246ffb", + indexName: "vue-h5-template", + }, + }, +}; + +function nav() { + return [ + { text: "介绍", link: "/guide/" }, + { text: "掘金", link: "https://juejin.cn/user/3016715636842622" }, + { text: "加入我们", link: "https://github.com/tobe-fe-dalao/fastool" }, + ]; +} + +function sidebarGuide() { + return [ + { + text: "介绍", + collapsible: true, + items: [ + { text: "介绍", link: "/guide/" }, + { text: "快速上手", link: "/guide/start" }, + { text: "参与编辑", link: "/guide/edit" }, + ], + }, + { + text: "vue3-template", + collapsible: true, + items: [ + { text: "vite", link: "/guide/vue3/vite" }, + { text: "配置多环境变量", link: "/guide/vue3/env" }, + { text: "viewport 适配方案", link: "/guide/vue3/viewport" }, + { text: "多UI组件库供选择", link: "/guide/vue3/ui" }, + { text: "Pinia 状态管理", link: "/guide/vue3/pinia" }, + { text: "vue-router", link: "/guide/vue3/router" }, + { text: "axios 封装及接口管理", link: "/guide/vue3/axios" }, + { text: "vite.config.ts 基础配置", link: "/guide/vue3/base" }, + { text: "alias", link: "/guide/vue3/base" }, + { text: "proxy 跨域", link: "/guide/vue3/base" }, + { + text: "Eslint+Pettier+stylelint 统一开发规范", + link: "/guide/vue3/lint", + }, + ], + }, + { + text: "vue2-template", + collapsible: false, + items: [ + { text: "启动项目", link: "/guide//vue2/start" }, + { text: "配置多环境变量", link: "/guide/vue2/env" }, + { text: "rem 适配方案", link: "/guide/vue2/rem" }, + { text: "vw 适配方案", link: "/guide/vue2/vw" }, + { text: "VantUI 组件按需加载", link: "/guide/vue2/vant" }, + { text: "Sass 全局样式", link: "/guide/vue2/sass" }, + { text: "Vuex 状态管理", link: "/guide/vue2/vuex" }, + { text: "Vue-router", link: "/guide/vue2/router" }, + { text: "Axios 封装及接口管理", link: "/guide/vue2/axios" }, + { text: "vue.config.js 基础配置", link: "/guide/vue2/base" }, + { text: "配置 alias 别名", link: "/guide/vue2/alias" }, + { text: "配置 proxy 跨域", link: "/guide/vue2/proxy" }, + { text: "配置 打包分析", link: "/guide/vue2/bundle" }, + { text: "配置 externals 引入 cdn 资源", link: "/guide/vue2/externals" }, + { text: "去掉 console.log", link: "/guide/vue2/console" }, + { text: "splitChunks 单独打包第三方模块", link: "/guide/vue2/chunks" }, + { text: "添加 IE 兼容", link: "/guide/vue2/ie" }, + { text: "Eslint+Pettier 统一开发规范", link: "/guide/vue2/lint" }, + ], + }, + ]; +} diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/custom.css new file mode 100644 index 0000000..f35cccc --- /dev/null +++ b/docs/.vitepress/theme/custom.css @@ -0,0 +1,61 @@ +:root { + --vp-c-brand: #16c5fe; + --vp-c-green: #16c5fe; + --vp-c-green-light: #109ef7; + --vp-c-green-lighter: #109ef7; + --vp-c-green-dark: #109ef7; + --vp-c-green-darker: #109ef7; +} + +.dark { + --vp-c-bg: #000; + --vp-code-block-bg: #111; + --vp-c-bg-alt: rgba(0, 0, 0, 0.5); +} + +@media (min-width: 960px) { + .dark .VPNavBar.has-sidebar .content[data-v-d84f2262] { + background: rgba(36, 36, 36, 0.1); + } +} + +.Layout::before { + content: ""; + background-size: 100% 100%; + background-position: right; + background-repeat: no-repeat; + opacity: 1; + max-width: 100%; + height: 100%; + width: 50%; + position: fixed; + top: -20%; + right: -10%; + display: block; +} + +.Layout::after { + content: ""; + background-size: 100% 100%; + background-position: right; + background-repeat: no-repeat; + opacity: 1; + max-width: 100%; + height: 100%; + width: 50%; + position: fixed; + bottom: -20%; + left: -10%; + display: block; + z-index: -1; +} + +@media (min-width: 960px) { + .title { + font-size: 24px !important; + } +} + +.image-src { + max-width: 220px !important; +} diff --git a/docs/.vitepress/theme/index.js b/docs/.vitepress/theme/index.js new file mode 100644 index 0000000..c495bc1 --- /dev/null +++ b/docs/.vitepress/theme/index.js @@ -0,0 +1,4 @@ +import DefaultTheme from "vitepress/theme"; +import "./custom.css"; + +export default DefaultTheme; diff --git a/docs/guide/edit.md b/docs/guide/edit.md new file mode 100644 index 0000000..30c1d32 --- /dev/null +++ b/docs/guide/edit.md @@ -0,0 +1,19 @@ +# 参与编辑 + +欢迎各位有意愿参与到开源当中的朋友加入文档的编写,书写文档不仅是教会别人知识,更是用自己的表达方式概括自己所学习的知识,这对个人来说是一种不多的成长机会 + +```js + +// 拉取项目 +git clone https://github.com/sunniejs/vue-h5-template + +// 切换分支 +git checkout -b docs origin/docs + +// 安装依赖 +yarn install + +// 启动项目 +yarn start + +``` diff --git a/docs/guide/index.md b/docs/guide/index.md new file mode 100644 index 0000000..5a04d86 --- /dev/null +++ b/docs/guide/index.md @@ -0,0 +1,23 @@ +# Vue-H5-Template + +[Vue-H5-Template](https://github.com/sunniejs/vue-h5-template),是基于 vite + vue3 + pinia + ( Vant or Varlet or NutUI ) + viewport 适配方案 ,构建移动端开发脚手架 + +## 特点 + +### 最新技术栈 + +- 框架选型基于当下流行的 vue + vite + ts 模式,精选社区经典的 ui 框架和 vite 插件 + +### 基于 TypeScript + +- typescript 越来越被大型的 js 项目所需要,明确的类型定义可以省下不少的维护成本 + +### 轻量级 + +- 不同于集成解决方案,尽量做到轻量不冗杂,只引入高频次、需求高的插件和清晰的示例 +- 轻装上阵,便于拓展开发 + +### 通俗易懂的文档 + +- 基于最新 VitePress 构建的文档,更快,更便捷 +- 更快的热更新 diff --git a/docs/guide/start.md b/docs/guide/start.md new file mode 100644 index 0000000..a888210 --- /dev/null +++ b/docs/guide/start.md @@ -0,0 +1,17 @@ +# 快速上手 + +## node 版本要求 + +推荐 14.19.0+以上的版本,毕竟 2022 年了,别掐着 12+的版本了,你也可以使用[nvm](https://github.com/nvm-sh/nvm)或[nvm-windows](https://github.com/coreybutler/nvm-windows)在同一台电脑上管理多个 node 版本 + +## 包管理器 + +尽量使用 yarn 或者 pnpm,本项目仅保证在 yarn 或 pnpm 下正确运行,npm 涉及到网络环境等各种情况的限制不做过多考虑。 + +## 启动项目 + +项目中包含 vue2 和 vue3 两套模版 + +如你使用的是 vue2-template,请参考[vue2 项目启动]() + +如你使用的是 vue3-template,请参考[vue3 项目启动]() diff --git a/docs/guide/vue2/alias.md b/docs/guide/vue2/alias.md new file mode 100644 index 0000000..7b89520 --- /dev/null +++ b/docs/guide/vue2/alias.md @@ -0,0 +1,19 @@ +# 配置 alias 别名 + +```javascript +const path = require("path"); +const resolve = (dir) => path.join(__dirname, dir); +const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV); + +module.exports = { + chainWebpack: (config) => { + // 添加别名 + config.resolve.alias + .set("@", resolve("src")) + .set("assets", resolve("src/assets")) + .set("api", resolve("src/api")) + .set("views", resolve("src/views")) + .set("components", resolve("src/components")); + }, +}; +``` diff --git a/docs/guide/vue2/axios.md b/docs/guide/vue2/axios.md new file mode 100644 index 0000000..2416ead --- /dev/null +++ b/docs/guide/vue2/axios.md @@ -0,0 +1,106 @@ +### ✅ Axios 封装及接口管理 + +`utils/request.js` 封装 axios ,开发者需要根据后台接口做修改。 + +- `service.interceptors.request.use` 里可以设置请求头,比如设置 `token` +- `config.hideloading` 是在 api 文件夹下的接口参数里设置,下文会讲 +- `service.interceptors.response.use` 里可以对接口返回数据处理,比如 401 删除本地信息,重新登录 + +```javascript +import axios from 'axios' +import store from '@/store' +import { Toast } from 'vant' +// 根据环境不同引入不同api地址 +import { baseApi } from '@/config' +// create an axios instance +const service = axios.create({ + baseURL: baseApi, // url = base api url + request url + withCredentials: true, // send cookies when cross-domain requests + timeout: 5000, // request timeout +}) + +// request 拦截器 request interceptor +service.interceptors.request.use( + config => { + // 不传递默认开启loading + if (!config.hideloading) { + // loading + Toast.loading({ + forbidClick: true, + }) + } + if (store.getters.token) { + config.headers['X-Token'] = '' + } + return config + }, + error => { + // do something with request error + console.log(error) // for debug + return Promise.reject(error) + } +) +// respone拦截器 +service.interceptors.response.use( + response => { + Toast.clear() + const res = response.data + if (res.status && res.status !== 200) { + // 登录超时,重新登录 + if (res.status === 401) { + store.dispatch('FedLogOut').then(() => { + location.reload() + }) + } + return Promise.reject(res || 'error') + } else { + return Promise.resolve(res) + } + }, + error => { + Toast.clear() + console.log('err' + error) // for debug + return Promise.reject(error) + } +) +export default service +``` + +#### 接口管理 + +在`src/api` 文件夹下统一管理接口 + +- 你可以建立多个模块对接接口, 比如 `home.js` 里是首页的接口这里讲解 `user.js` +- `url` 接口地址,请求的时候会拼接上 `config` 下的 `baseApi` +- `method` 请求方法 +- `data` 请求参数 `qs.stringify(params)` 是对数据系列化操作 +- `hideloading` 默认 `false`,设置为 `true` 后,不显示 loading ui 交互中有些接口不需要让用户感知 + +```javascript +import qs from 'qs' +// axios +import request from '@/utils/request' +//user api + +// 用户信息 +export function getUserInfo(params) { + return request({ + url: '/user/userinfo', + method: 'post', + data: qs.stringify(params), + hideloading: true, // 隐藏 loading 组件 + }) +} +``` + +#### 如何调用 + +```javascript +// 请求接口 +import { getUserInfo } from '@/api/user.js' + +const params = { user: 'sunnie' } +getUserInfo(params) + .then(() => {}) + .catch(() => {}) +``` diff --git a/docs/guide/vue2/base.md b/docs/guide/vue2/base.md new file mode 100644 index 0000000..098cd9f --- /dev/null +++ b/docs/guide/vue2/base.md @@ -0,0 +1,36 @@ +### ✅ Webpack 4 vue.config.js 基础配置 + +如果你的 `Vue Router` 模式是 hash + +```javascript +publicPath: './', +``` + +如果你的 `Vue Router` 模式是 history 这里的 publicPath 和你的 `Vue Router` `base` **保持一直** + +```javascript +publicPath: '/app/', +``` + +```javascript +const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV) + +module.exports = { + publicPath: './', // 署应用包时的基本 URL。 vue-router hash 模式使用 + // publicPath: '/app/', // 署应用包时的基本 URL。 vue-router history模式使用 + outputDir: 'dist', // 生产环境构建文件的目录 + assetsDir: 'static', // outputDir的静态资源(js、css、img、fonts)目录 + lintOnSave: !IS_PROD, + productionSourceMap: false, // 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。 + devServer: { + port: 9020, // 端口号 + open: false, // 启动后打开浏览器 + overlay: { + // 当出现编译器错误或警告时,在浏览器中显示全屏覆盖层 + warnings: false, + errors: true, + }, + // ... + }, +} +``` diff --git a/docs/guide/vue2/bundle.md b/docs/guide/vue2/bundle.md new file mode 100644 index 0000000..50a8011 --- /dev/null +++ b/docs/guide/vue2/bundle.md @@ -0,0 +1,22 @@ +### ✅ 配置 打包分析 + +```javascript +const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin + +module.exports = { + chainWebpack: config => { + // 打包分析 + if (IS_PROD) { + config.plugin('webpack-report').use(BundleAnalyzerPlugin, [ + { + analyzerMode: 'static', + }, + ]) + } + }, +} +``` + +```bash +npm run build +``` diff --git a/docs/guide/vue2/chunks.md b/docs/guide/vue2/chunks.md new file mode 100644 index 0000000..f4c21cd --- /dev/null +++ b/docs/guide/vue2/chunks.md @@ -0,0 +1,45 @@ +### ✅ splitChunks 单独打包第三方模块 + +```javascript +module.exports = { + chainWebpack: config => { + config.when(IS_PROD, config => { + config + .plugin('ScriptExtHtmlWebpackPlugin') + .after('html') + .use('script-ext-html-webpack-plugin', [ + { + // 将 runtime 作为内联引入不单独存在 + inline: /runtime\..*\.js$/, + }, + ]) + .end() + config.optimization.splitChunks({ + chunks: 'all', + cacheGroups: { + // cacheGroups 下可以可以配置多个组,每个组根据test设置条件,符合test条件的模块 + commons: { + name: 'chunk-commons', + test: resolve('src/components'), + minChunks: 3, // 被至少用三次以上打包分离 + priority: 5, // 优先级 + reuseExistingChunk: true, // 表示是否使用已有的 chunk,如果为 true 则表示如果当前的 chunk 包含的模块已经被抽取出去了,那么将不会重新生成新的。 + }, + node_vendors: { + name: 'chunk-libs', + chunks: 'initial', // 只打包初始时依赖的第三方 + test: /[\\/]node_modules[\\/]/, + priority: 10, + }, + vantUI: { + name: 'chunk-vantUI', // 单独将 vantUI 拆包 + priority: 20, // 数字大权重到,满足多个 cacheGroups 的条件时候分到权重高的 + test: /[\\/]node_modules[\\/]_?vant(.*)/, + }, + }, + }) + config.optimization.runtimeChunk('single') + }) + }, +} +``` diff --git a/docs/guide/vue2/console.md b/docs/guide/vue2/console.md new file mode 100644 index 0000000..aa11db2 --- /dev/null +++ b/docs/guide/vue2/console.md @@ -0,0 +1,34 @@ +### ✅ 去掉 console.log + +保留了测试环境和本地环境的 `console.log` + +```bash +npm i -D babel-plugin-transform-remove-console +``` + +在 babel.config.js 中配置 + +```javascript +// 获取 VUE_APP_ENV 非 NODE_ENV,测试环境依然 console +const IS_PROD = ['production', 'prod'].includes(process.env.VUE_APP_ENV) +const plugins = [ + [ + 'import', + { + libraryName: 'vant', + libraryDirectory: 'es', + style: true, + }, + 'vant', + ], +] +// 去除 console.log +if (IS_PROD) { + plugins.push('transform-remove-console') +} + +module.exports = { + presets: [['@vue/cli-plugin-babel/preset', { useBuiltIns: 'entry' }]], + plugins, +} +``` diff --git a/docs/guide/vue2/env.md b/docs/guide/vue2/env.md new file mode 100644 index 0000000..9c5818c --- /dev/null +++ b/docs/guide/vue2/env.md @@ -0,0 +1,84 @@ +### ✅ 配置多环境变量 + +`package.json` 里的 `scripts` 配置 `serve` `stage` `build`,通过 `--mode xxx` 来执行不同环境 + +- 通过 `npm run serve` 启动本地 , 执行 `development` +- 通过 `npm run stage` 打包测试 , 执行 `staging` +- 通过 `npm run build` 打包正式 , 执行 `production` + +```javascript +"scripts": { + "serve": "vue-cli-service serve --open", + "stage": "vue-cli-service build --mode staging", + "build": "vue-cli-service build", +} +``` + +##### 配置介绍 + +  以 `VUE_APP_` 开头的变量,在代码中可以通过 `process.env.VUE_APP_` 访问。 +  比如,`VUE_APP_ENV = 'development'` 通过`process.env.VUE_APP_ENV` 访问。 +  除了 `VUE_APP_*` 变量之外,在你的应用代码中始终可用的还有两个特殊的变量`NODE_ENV` 和`BASE_URL` + +在项目根目录中新建`.env.*` + +- .env.development 本地开发环境配置 + +```bash +NODE_ENV='development' +# must start with VUE_APP_ +VUE_APP_ENV = 'development' + +``` + +- .env.staging 测试环境配置 + +```bash +NODE_ENV='production' +# must start with VUE_APP_ +VUE_APP_ENV = 'staging' +``` + +- .env.production 正式环境配置 + +```bash + NODE_ENV='production' +# must start with VUE_APP_ +VUE_APP_ENV = 'production' +``` + +这里我们并没有定义很多变量,只定义了基础的 VUE_APP_ENV `development` `staging` `production` +变量我们统一在 `src/config/env.*.js` 里进行管理。 + +这里有个问题,既然这里有了根据不同环境设置变量的文件,为什么还要去 config 下新建三个对应的文件呢? +**修改起来方便,不需 +要重启项目,符合开发习惯。** + +config/index.js + +```javascript +// 根据环境引入不同配置 process.env.NODE_ENV +const config = require('./env.' + process.env.VUE_APP_ENV) +module.exports = config +``` + +配置对应环境的变量,拿本地环境文件 `env.development.js` 举例,用户可以根据需求修改 + +```javascript +// 本地环境配置 +module.exports = { + title: 'vue-h5-template', + baseUrl: 'http://localhost:9018', // 项目地址 + baseApi: 'https://test.xxx.com/api', // 本地api请求地址 + APPID: 'xxx', + APPSECRET: 'xxx', +} +``` + +根据环境不同,变量就会不同了 + +```javascript +// 根据环境不同引入不同baseApi地址 +import { baseApi } from '@/config' +console.log(baseApi) +``` diff --git a/docs/guide/vue2/externals.md b/docs/guide/vue2/externals.md new file mode 100644 index 0000000..810a78f --- /dev/null +++ b/docs/guide/vue2/externals.md @@ -0,0 +1,84 @@ +### ✅ 配置 externals 引入 cdn 资源 + +这个版本 CDN 不再引入,我测试了一下使用引入 CDN 和不使用,不使用会比使用时间少。网上不少文章测试 CDN 速度块,这个开发者可 +以实际测试一下。 + +另外项目中使用的是公共 CDN 不稳定,域名解析也是需要时间的(如果你要使用请尽量使用同一个域名) + +因为页面每次遇到` + <% } %> +``` diff --git a/docs/guide/vue2/ie.md b/docs/guide/vue2/ie.md new file mode 100644 index 0000000..3bec6a6 --- /dev/null +++ b/docs/guide/vue2/ie.md @@ -0,0 +1,30 @@ +### ✅ 添加 IE 兼容 + +之前的方式 会报 `@babel/polyfill` is deprecated. Please, use required parts of `core-js` and +`regenerator-runtime/runtime` separately + +`@babel/polyfill` 废弃,使用 `core-js` 和 `regenerator-runtime` + +```bash +npm i --save core-js regenerator-runtime +``` + +在 `main.js` 中添加 + +```javascript +// 兼容 IE +// https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md#babelpolyfill +import 'core-js/stable' +import 'regenerator-runtime/runtime' +``` + +配置 `babel.config.js` + +```javascript +const plugins = [] + +module.exports = { + presets: [['@vue/cli-plugin-babel/preset', { useBuiltIns: 'usage', corejs: 3 }]], + plugins, +} +``` diff --git a/docs/guide/vue2/lint.md b/docs/guide/vue2/lint.md new file mode 100644 index 0000000..8f46dd7 --- /dev/null +++ b/docs/guide/vue2/lint.md @@ -0,0 +1,165 @@ +### ✅ Eslint + Pettier 统一开发规范 + +VScode (版本 1.47.3)安装 `eslint` `prettier` `vetur` 插件 `.vue` 文件使用 vetur 进行格式化,其他使用`prettier`,后面会 +专门写个如何使用配合使用这三个玩意 + +在文件 `.prettierrc` 里写 属于你的 pettier 规则 + +```bash +{ + "printWidth": 120, + "tabWidth": 2, + "singleQuote": true, + "trailingComma": "none", + "semi": false, + "wrap_line_length": 120, + "wrap_attributes": "auto", + "proseWrap": "always", + "arrowParens": "avoid", + "bracketSpacing": false, + "jsxBracketSameLine": true, + "useTabs": false, + "overrides": [{ + "files": ".prettierrc", + "options": { + "parser": "json" + } + }] +} +``` + +Vscode setting.json 设置 + +```bash + { + // 将设置放入此文件中以覆盖默认设置 + "files.autoSave": "off", + // 控制字体系列。 + "editor.fontFamily": "Consolas, 'Courier New', monospace,'宋体'", + "terminal.integrated.shell.windows": "C:\\Program Files\\Git\\bin\\bash.exe", + // 以像素为单位控制字号。 + "editor.fontSize": 16, + // 控制选取范围是否有圆角 + "editor.roundedSelection": false, + // 建议小组件的字号 + "editor.suggestFontSize": 16, + // 在“打开的编辑器”窗格中显示的编辑器数量。将其设置为 0 可隐藏窗格。 + "explorer.openEditors.visible": 0, + // 是否已启用自动刷新 + "git.autorefresh": true, + // 以像素为单位控制终端的字号,这是 editor.fontSize 的默认值。 + "terminal.integrated.fontSize": 14, + // 控制终端游标是否闪烁。 + "terminal.integrated.cursorBlinking": true, + // 一个制表符等于的空格数。该设置在 `editor.detectIndentation` 启用时根据文件内容进行重写。 + // Tab Size + "editor.tabSize": 2, + // By default, common template. Do not modify it!!!!! + "editor.formatOnType": true, + "window.zoomLevel": 0, + "editor.detectIndentation": false, + "css.fileExtensions": ["css", "scss"], + "files.associations": { + "*.string": "html", + "*.vue": "vue", + "*.wxss": "css", + "*.wxml": "wxml", + "*.wxs": "javascript", + "*.cjson": "jsonc", + "*.js": "javascript" + }, + // 为指定的语法定义配置文件或使用带有特定规则的配置文件。 + "emmet.syntaxProfiles": { + "vue-html": "html", + "vue": "html" + }, + "search.exclude": { + "**/node_modules": true, + "**/bower_components": true + }, + //保存时eslint自动修复错误 + "editor.formatOnSave": true, + // Enable per-language + //配置 ESLint 检查的文件类型 + "editor.quickSuggestions": { + "strings": true + }, + // 添加 vue 支持 + // 这里是针对vue文件的格式化设置,vue的规则在这里生效 + "vetur.format.options.tabSize": 2, + "vetur.format.options.useTabs": false, + "vetur.format.defaultFormatter.html": "js-beautify-html", + "vetur.format.defaultFormatter.css": "prettier", + "vetur.format.defaultFormatter.scss": "prettier", + "vetur.format.defaultFormatter.postcss": "prettier", + "vetur.format.defaultFormatter.less": "prettier", + "vetur.format.defaultFormatter.js": "vscode-typescript", + "vetur.format.defaultFormatter.sass": "sass-formatter", + "vetur.format.defaultFormatter.ts": "prettier", + "vetur.format.defaultFormatterOptions": { + "js-beautify-html": { + "wrap_attributes": "aligned-multiple", // 超过150折行 + "wrap-line-length": 150 + }, + // #vue组件中html代码格式化样式 + "prettier": { + "printWidth": 120, + "tabWidth": 2, + "singleQuote": false, + "trailingComma": "none", + "semi": false, + "wrap_line_length": 120, + "wrap_attributes": "aligned-multiple", // 超过150折行 + "proseWrap": "always", + "arrowParens": "avoid", + "bracketSpacing": true, + "jsxBracketSameLine": true, + "useTabs": false, + "overrides": [ + { + "files": ".prettierrc", + "options": { + "parser": "json" + } + } + ] + } + }, + // Enable per-language + "[json]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "vetur.validation.template": false, + "html.format.enable": false, + "json.format.enable": false, + "javascript.format.enable": false, + "typescript.format.enable": false, + "javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, + "[html]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[jsonc]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[vue]": { + "editor.defaultFormatter": "octref.vetur" + }, + "emmet.includeLanguages": { + "wxml": "html" + }, + "[typescriptreact]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + // 开启eslint自动修复js/ts功能 + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true + }, + "minapp-vscode.disableAutoConfig": true, + "javascript.implicitProjectConfig.experimentalDecorators": true, + "editor.maxTokenizationLineLength": 200000 +} + +``` diff --git a/docs/guide/vue2/proxy.md b/docs/guide/vue2/proxy.md new file mode 100644 index 0000000..d38002e --- /dev/null +++ b/docs/guide/vue2/proxy.md @@ -0,0 +1,36 @@ +### ✅ 配置 proxy 跨域 + +如果你的项目需要跨域设置,你需要打来 `vue.config.js` `proxy` 注释 并且配置相应参数 + +**!!!注意:你还需要将 `src/config/env.development.js` 里的 `baseApi` 设置成 '/'** + +```javascript +module.exports = { + devServer: { + // .... + proxy: { + //配置跨域 + '/api': { + target: 'https://test.xxx.com', // 接口的域名 + // ws: true, // 是否启用websockets + changOrigin: true, // 开启代理,在本地创建一个虚拟服务端 + pathRewrite: { + '^/api': '/', + }, + }, + }, + }, +} +``` + +使用 例如: `src/api/home.js` + +```javascript +export function getUserInfo(params) { + return request({ + url: '/api/userinfo', + method: 'post', + data: qs.stringify(params), + }) +} +``` diff --git a/docs/guide/vue2/rem.md b/docs/guide/vue2/rem.md new file mode 100644 index 0000000..b6acfd2 --- /dev/null +++ b/docs/guide/vue2/rem.md @@ -0,0 +1,69 @@ +### ✅ rem 适配方案 + +不用担心,项目已经配置好了 `rem` 适配, 下面仅做介绍: + +Vant 中的样式默认使用`px`作为单位,如果需要使用`rem`单位,推荐使用以下两个工具: + +- [postcss-pxtorem](https://github.com/cuth/postcss-pxtorem) 是一款 `postcss` 插件,用于将单位转化为 `rem` +- [lib-flexible](https://github.com/amfe/lib-flexible) 用于设置 `rem` 基准值 + +##### PostCSS 配置 + +下面提供了一份基本的 `postcss` 配置,可以在此配置的基础上根据项目需求进行修改 + +```javascript +// https://github.com/michael-ciniawsky/postcss-load-config +module.exports = { + plugins: { + autoprefixer: { + overrideBrowserslist: ['Android 4.1', 'iOS 7.1', 'Chrome > 31', 'ff > 31', 'ie >= 8'] + }, + 'postcss-pxtorem': { + rootValue: 37.5, + propList: ['*'] + } + } +} +``` + +更多详细信息: [vant](https://youzan.github.io/vant/#/zh-CN/quickstart#jin-jie-yong-fa) + +**新手必看,老鸟跳过** + +很多小伙伴会问我,适配的问题,因为我们使用的是 Vant UI,所以必须根据 Vant UI 375 的设计规范走,一般我们的设计会将 UI 图上传到蓝湖,我们就可以需要的尺寸了。下面就大搞普及一下 rem。 + +我们知道 `1rem` 等于`html` 根元素设定的 `font-size` 的 `px` 值。Vant UI 设置 `rootValue: 37.5`,你可以看到在 iPhone 6 下看到 (`1rem 等于 37.5px`): + +```html + +``` + +切换不同的机型,根元素可能会有不同的`font-size`。当你写 css px 样式时,会被程序换算成 `rem` 达到适配。 + +因为我们用了 Vant 的组件,需要按照 `rootValue: 37.5` 来写样式。 + +举个例子:设计给了你一张 750px \* 1334px 图片,在 iPhone6 上铺满屏幕,其他机型适配。 + +- 当`rootValue: 70` , 样式 `width: 750px;height: 1334px;` 图片会撑满 iPhone6 屏幕,这个时候切换其他机型,图片也会跟着撑满。 +- 当`rootValue: 37.5` 的时候,样式 `width: 375px;height: 667px;` 图片会撑满 iPhone6 屏幕。 + +也就是 iphone 6 下 375px 宽度写 CSS。其他的你就可以根据你设计图,去写对应的样式就可以了。 + +当然,想要撑满屏幕你可以使用 100%,这里只是举例说明。 + +```html + + + +``` diff --git a/docs/guide/vue2/router.md b/docs/guide/vue2/router.md new file mode 100644 index 0000000..d883335 --- /dev/null +++ b/docs/guide/vue2/router.md @@ -0,0 +1,34 @@ +### ✅ Vue-router + +本案例采用 `hash` 模式,开发者根据需求修改 `mode` `base` + +**注意**:如果你使用了 `history` 模式,`vue.config.js` 中的 `publicPath` 要做对应的**修改** + +前往:[vue.config.js 基础配置](#base) + +```javascript +import Vue from 'vue' +import Router from 'vue-router' + +Vue.use(Router) +export const router = [ + { + path: '/', + name: 'index', + component: () => import('@/views/home/index'), // 路由懒加载 + meta: { + title: '首页', // 页面标题 + keepAlive: false, // keep-alive 标识 + }, + }, +] +const createRouter = () => + new Router({ + // mode: 'history', // 如果你是 history模式 需要配置 vue.config.js publicPath + // base: '/app/', + scrollBehavior: () => ({ y: 0 }), + routes: router, + }) + +export default createRouter() +``` diff --git a/docs/guide/vue2/sass.md b/docs/guide/vue2/sass.md new file mode 100644 index 0000000..fab2845 --- /dev/null +++ b/docs/guide/vue2/sass.md @@ -0,0 +1,104 @@ +### ✅ Sass 全局样式 + +首先 你可能会遇到 `node-sass` 安装不成功,别放弃多试几次!!! + +每个页面自己对应的样式都写在自己的 .vue 文件之中 `scoped` 它顾名思义给 css 加了一个域的概念。 + +```html + + + +``` + +#### 目录结构 + +vue-h5-template 所有全局样式都在 `@/src/assets/css` 目录下设置 + +```bash +├── assets +│ ├── css +│ │ ├── index.scss # 全局通用样式 +│ │ ├── mixin.scss # 全局mixin +│ │ └── variables.scss # 全局变量 +``` + +#### 自定义 vant-ui 样式 + +现在我们来说说怎么重写 `vant-ui` 样式。由于 `vant-ui` 的样式我们是在全局引入的,所以你想在某个页面里面覆盖它的样式就不能加 `scoped`,但你又想只覆盖这个页面的 `vant` 样式,你就可在它的父级加一个 `class`,用命名空间来解决问题。 + +```css +.about-container { + /* 你的命名空间 */ + .van-button { + /* vant-ui 元素*/ + margin-right: 0px; + } +} +``` + +#### 父组件改变子组件样式 深度选择器 + +当你子组件使用了 `scoped` 但在父组件又想修改子组件的样式可以 通过 `>>>` 来实现: + +```css + +``` +#### 全局变量 + +`vue.config.js` 配置使用 `css.loaderOptions` 选项,注入 `sass` 的 `mixin` `variables` 到全局,不需要手动引入 ,配置`$cdn`通过变量形式引入 cdn 地址,这样向所有 Sass/Less 样式传入共享的全局变量: + +```javascript +const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV) +const defaultSettings = require('./src/config/index.js') +module.exports = { + css: { + extract: IS_PROD, + sourceMap: false, + loaderOptions: { + // 给 scss-loader 传递选项 + scss: { + // 注入 `sass` 的 `mixin` `variables` 到全局, $cdn可以配置图片cdn + // 详情: https://cli.vuejs.org/guide/css.html#passing-options-to-pre-processor-loaders + prependData: ` + @import "assets/css/mixin.scss"; + @import "assets/css/variables.scss"; + $cdn: "${defaultSettings.$cdn}"; + `, + }, + }, + }, +} +``` + +设置 js 中可以访问 `$cdn`,`.vue` 文件中使用`this.$cdn`访问 + +```javascript +// 引入全局样式 +import '@/assets/css/index.scss' + +// 设置 js中可以访问 $cdn +// 引入cdn +import { $cdn } from '@/config' +Vue.prototype.$cdn = $cdn +``` + +在 css 和 js 使用 + +```html + + +``` diff --git a/docs/guide/vue2/start.md b/docs/guide/vue2/start.md new file mode 100644 index 0000000..4e2c3bc --- /dev/null +++ b/docs/guide/vue2/start.md @@ -0,0 +1,17 @@ +# 启动项目 + +```js + +// 拉取项目 +git clone https://github.com/sunniejs/vue-h5-template + +// 切换分支 +git checkout -b vue2-h5-template origin/vue2-h5-template + +// 安装依赖 +yarn install + +// 启动项目 +yarn serve + +``` diff --git a/docs/guide/vue2/vant.md b/docs/guide/vue2/vant.md new file mode 100644 index 0000000..f276212 --- /dev/null +++ b/docs/guide/vue2/vant.md @@ -0,0 +1,49 @@ +### ✅ VantUI 组件按需加载 + +项目采 +用[Vant 自动按需引入组件 (推荐)](https://youzan.github.io/vant/#/zh-CN/quickstart#fang-shi-yi.-zi-dong-an-xu-yin-ru-zu-jian-tui-jian)下 +面安装插件介绍: + +[babel-plugin-import](https://github.com/ant-design/babel-plugin-import) 是一款 `babel` 插件,它会在编译过程中将 +`import` 的写法自动转换为按需引入的方式 + +#### 安装插件 + +```bash +npm i babel-plugin-import -D +``` + +在`babel.config.js` 设置 + +```javascript +// 对于使用 babel7 的用户,可以在 babel.config.js 中配置 +const plugins = [ + [ + 'import', + { + libraryName: 'vant', + libraryDirectory: 'es', + style: true, + }, + 'vant', + ], +] +module.exports = { + presets: [['@vue/cli-plugin-babel/preset', { useBuiltIns: 'usage', corejs: 3 }]], + plugins, +} +``` + +#### 使用组件 + +项目在 `src/plugins/vant.js` 下统一管理组件,用哪个引入哪个,无需在页面里重复引用 + +```javascript +// 按需全局引入 vant组件 +import Vue from 'vue' +import { Button, List, Cell, Tabbar, TabbarItem } from 'vant' +Vue.use(Button) +Vue.use(Cell) +Vue.use(List) +Vue.use(Tabbar).use(TabbarItem) +``` diff --git a/docs/guide/vue2/vuex.md b/docs/guide/vue2/vuex.md new file mode 100644 index 0000000..df7d400 --- /dev/null +++ b/docs/guide/vue2/vuex.md @@ -0,0 +1,45 @@ +### ✅ Vuex 状态管理 + +目录结构 + +```bash +├── store +│ ├── modules +│ │ └── app.js +│ ├── index.js +│ ├── getters.js +``` + +`main.js` 引入 + +```javascript +import Vue from 'vue' +import App from './App.vue' +import store from './store' +new Vue({ + el: '#app', + router, + store, + render: h => h(App), +}) +``` + +使用 + +```html + +``` diff --git a/docs/guide/vue2/vw.md b/docs/guide/vue2/vw.md new file mode 100644 index 0000000..38f07ae --- /dev/null +++ b/docs/guide/vue2/vw.md @@ -0,0 +1,61 @@ +### ✅ vm 适配方案 + +本项目使用的是 `rem` 的 适配方案,其实无论你使用哪种方案,都不需要你去计算 12px 是多少 `rem` 或者 `vw`, 会有专门的工具去帮你做 +。如果你想用 `vw`,你可以按照下面的方式切换。 + +#### 1.安装依赖 + +```bash + +npm install postcss-px-to-viewport -D + +``` + +#### 2.修改 .postcssrc.js + +将根目录下 .postcssrc.js 文件修改如下 + +```javascript +// https://github.com/michael-ciniawsky/postcss-load-config +module.exports = { + plugins: { + autoprefixer: { + overrideBrowserslist: [ + "Android 4.1", + "iOS 7.1", + "Chrome > 31", + "ff > 31", + "ie >= 8", + ], + }, + "postcss-px-to-viewport": { + viewportWidth: 375, // 视窗的宽度,对应的是我们设计稿的宽度,一般是750 + unitPrecision: 3, // 指定`px`转换为视窗单位值的小数位数(很多时候无法整除) + viewportUnit: "vw", // 指定需要转换成的视窗单位,建议使用vw + selectorBlackList: [".ignore", ".hairlines"], // 指定不转换为视窗单位的类,可以自定义,可以无限添加,建议定义一至两个通用的类名 + minPixelValue: 1, // 小于或等于`1px`不转换为视窗单位,你也可以设置为你想要的值 + mediaQuery: false, // 允许在媒体查询中转换`px` + }, + }, +}; +``` + +#### 3.删除原来的 rem 相关代码 + +src/main.js 删除如下代码 + +```javascript +// 移动端适配 +import "lib-flexible/flexible.js"; +``` + +package.json 删除如下代码 + +```javascript +"lib-flexible": "^0.3.2", +"postcss-pxtorem": "^5.1.1", +``` + +运行起来,F12 元素 css style 就是 vw 单位了 + +[▲ 回顶部](#top) diff --git a/docs/guide/vue3/alias.md b/docs/guide/vue3/alias.md new file mode 100644 index 0000000..a17616f --- /dev/null +++ b/docs/guide/vue3/alias.md @@ -0,0 +1,21 @@ +# alias + +```javascript +resolve: { + alias: [{ + find: 'vue-i18n', + replacement: 'vue-i18n/dist/vue-i18n.cjs.js', + }, + // /@/xxxx => src/xxxx + { + find: /\/@\//, + replacement: pathResolve('src') + '/', + }, + // /#/xxxx => types/xxxx + { + find: /\/#\//, + replacement: pathResolve('types') + '/', + }, + ], +}, +``` diff --git a/docs/guide/vue3/axios.md b/docs/guide/vue3/axios.md new file mode 100644 index 0000000..67fbd44 --- /dev/null +++ b/docs/guide/vue3/axios.md @@ -0,0 +1,67 @@ +# axios 封装及接口管理 + +`utils/request.js` 封装 axios , 开发者需要根据后台接口做修改。 + +- `service.interceptors.request.use` 里可以设置请求头,比如设置 `token` +- `config.hideloading` 是在 api 文件夹下的接口参数里设置,下文会讲 +- `service.interceptors.response.use` 里可以对接口返回数据处理,比如 401 删除本地信息,重新登录 + +```javascript +import axios from "axios"; +import store from "@/store"; +import { Toast } from "vant"; +// 根据环境不同引入不同api地址 +import { baseApi } from "@/config"; +// create an axios instance +const service = axios.create({ + baseURL: baseApi, // url = base api url + request url + withCredentials: true, // send cookies when cross-domain requests + timeout: 5000, // request timeout +}); + +// request 拦截器 request interceptor +service.interceptors.request.use( + (config) => { + // 不传递默认开启loading + if (!config.hideloading) { + // loading + Toast.loading({ + forbidClick: true, + }); + } + if (store.getters.token) { + config.headers["X-Token"] = ""; + } + return config; + }, + (error) => { + // do something with request error + console.log(error); // for debug + return Promise.reject(error); + } +); +// respone拦截器 +service.interceptors.response.use( + (response) => { + Toast.clear(); + const res = response.data; + if (res.status && res.status !== 200) { + // 登录超时,重新登录 + if (res.status === 401) { + store.dispatch("FedLogOut").then(() => { + location.reload(); + }); + } + return Promise.reject(res || "error"); + } else { + return Promise.resolve(res); + } + }, + (error) => { + Toast.clear(); + console.log("err" + error); // for debug + return Promise.reject(error); + } +); +export default service; +``` diff --git a/docs/guide/vue3/base.md b/docs/guide/vue3/base.md new file mode 100644 index 0000000..8941b5a --- /dev/null +++ b/docs/guide/vue3/base.md @@ -0,0 +1,45 @@ +# vite.config.ts 基础配置 + +如果你的 `Vue Router` 模式是 hash + +```javascript +publicPath: './', +``` + +如果你的 `Vue Router` 模式是 history 这里的 publicPath 和你的 `Vue Router` `base` **保持一致** + +```javascript +publicPath: '/app/', +``` + +```javascript +export default function ({ command }: ConfigEnv): UserConfigExport { + const isProduction = command === "build"; + return { + server: { + host: "0.0.0.0", + }, + plugins: [ + vue(), + vueJsx(), + createStyleImportPlugin({ + resolves: [NutuiResolve()], + }), + eruda(), + viteMockServe({ + mockPath: "./src/mock", + localEnabled: command === "serve", + logger: true, + }), + ], + css: { + preprocessorOptions: { + scss: { + // 配置 nutui 全局 scss 变量 + additionalData: `@import "@nutui/nutui/dist/styles/variables.scss";`, + }, + }, + }, + }; +} +``` diff --git a/docs/guide/vue3/env.md b/docs/guide/vue3/env.md new file mode 100644 index 0000000..262644f --- /dev/null +++ b/docs/guide/vue3/env.md @@ -0,0 +1,13 @@ +`package.json` 里的 `scripts` 配置 `dev` `dev:test` `dev:prod` ,通过 `--mode xxx` 来执行不同环境 + +- 通过 `yarn dev` 启动本地环境参数 , 执行 `development` +- 通过 `yarn dev:test` 启动测试环境参数 , 执行 `test` +- 通过 `yarn dev:prod` 启动正式环境参数 , 执行 `prod` + +```javascript +"scripts": { + "dev": "vite", + "dev:test": "vite --mode test", + "dev:prod": "vite --mode production", +} +``` diff --git a/docs/guide/vue3/lint.md b/docs/guide/vue3/lint.md new file mode 100644 index 0000000..57c0f2e --- /dev/null +++ b/docs/guide/vue3/lint.md @@ -0,0 +1,3 @@ +# Eslint+Pettier+stylelint 统一开发规范 + +根目录下的.eslintrc.js、.stylelint.config.js、.prettier.config.js 内置了 lint 规则,帮助你规范地开发代码,有助于提高团队的代码质量和协作性,可以根据团队的规则进行修改 diff --git a/docs/guide/vue3/pinia.md b/docs/guide/vue3/pinia.md new file mode 100644 index 0000000..27eece4 --- /dev/null +++ b/docs/guide/vue3/pinia.md @@ -0,0 +1,22 @@ +# Pinia 状态管理 + +下一代 vuex,使用极其方便,ts 兼容好 + +目录结构 + +```bash +├── store +│ ├── modules +│ │ └── user.js +│ ├── index.js +``` + +使用 + +```html + +``` diff --git a/docs/guide/vue3/proxy.md b/docs/guide/vue3/proxy.md new file mode 100644 index 0000000..ede077d --- /dev/null +++ b/docs/guide/vue3/proxy.md @@ -0,0 +1,13 @@ +# proxy 跨域 + +```javascript +server: { + proxy: { + '/api': { + target: 'https://baidu.com', + changeOrigin: true, + rewrite: (path) => path.replace(/^\/api/, '') + } + } +}, +``` diff --git a/docs/guide/vue3/router.md b/docs/guide/vue3/router.md new file mode 100644 index 0000000..485ba08 --- /dev/null +++ b/docs/guide/vue3/router.md @@ -0,0 +1,29 @@ +# vue-router + +本案例采用 `hash` 模式,开发者根据需求修改 `mode` `base` + +**注意**:如果你使用了 `history` 模式, `vue.config.js` 中的 `publicPath` 要做对应的**修改** + +前往:[vue.config.js 基础配置](#base) + +```javascript +import Vue from "vue"; +import { createRouter, createWebHistory, Router } from "vue-router"; + +Vue.use(Router); +export const router = [ + { + name: "root", + path: "/", + redirect: "/home", + component: () => import("@/layout/basic/index.vue"), + }, +]; + +const router: Router = createRouter({ + history: createWebHistory(), + routes: routes, +}); + +export default router; +``` diff --git a/docs/guide/vue3/start.md b/docs/guide/vue3/start.md new file mode 100644 index 0000000..9bb2a27 --- /dev/null +++ b/docs/guide/vue3/start.md @@ -0,0 +1,14 @@ +# 启动项目 + +```js + +// 拉取项目 +git clone https://github.com/sunniejs/vue-h5-template + +// 安装依赖 +yarn install + +// 启动项目 +yarn dev + +``` diff --git a/docs/guide/vue3/ui.md b/docs/guide/vue3/ui.md new file mode 100644 index 0000000..c1b5e67 --- /dev/null +++ b/docs/guide/vue3/ui.md @@ -0,0 +1,58 @@ +# 多 UI 组件库供选择 + +Vite 构建工具,使用 vite-plugin-style-import 和 unplugin-vue-components/vite 实现按需引入。 + +## 安装插件 + +```bash +yarn add vite-plugin-style-import -D +yarn add unplugin-vue-components/vite -D +``` + +## 使用组件库 + +nutUI 没有按需加载的 resolvers,style 需要自己配置按需加载 + +在 `config/vite/plugins/styleImport.ts` 设置 + +```javascript + // 按需加载样式文件 + ... + createStyleImportPlugin({ + resolves: [NutuiResolve()], + }), + ... +``` + +项目在 `src/plugins/nutUI.ts` 下统一管理组件,用哪个引入哪个,无需在页面里重复引用 + +```javascript +// 按需全局引入nutUI组件 +import Vue from "vue"; +import { Button, Cell, CellGroup } from "@nutui/nutui"; +export const nutUiComponents = [Button, Cell, CellGroup]; + +// 在main.ts文件中引入 +nutUiComponents.forEach((item) => { + app.use(item); +}); +``` + +vant 和 varlet 可以使用组件按需加载 + +在`config/vite/plugins/component.ts`下 + +```javascript +import { VueUseComponentsResolver, VantResolver, VarletUIResolver } from 'unplugin-vue-components/resolvers'; +... +resolvers: [VantResolver(), VarletUIResolver()], +... +``` + +## 不需要某个组件库 + +nutUI 需删除`src/plugins/nutUI.ts`和`main.ts`文件下的引入 + +vant 和 varlet 只需删除对应的 resolvers 即可 + +删除后需全局搜索删除不需要的组件,避免报错 diff --git a/docs/guide/vue3/viewport.md b/docs/guide/vue3/viewport.md new file mode 100644 index 0000000..f1daced --- /dev/null +++ b/docs/guide/vue3/viewport.md @@ -0,0 +1,76 @@ +# viewport 适配方案 + +不用担心,项目已经配置好了 `viewport` 适配,下面仅做介绍: + +- [cnjm-postcss-px-to-viewport](https://github.com/cnjm/postcss-px-to-viewport) 是一款 `postcss` 插件,用于将单位转化为 `vw`, 现在很多浏览器对`vw`的支持都很好,适配首选方案。 + +## PostCSS 配置 + +下面提供了一份基本的 `postcss` 配置,可以在此配置的基础上根据项目需求进行修改 + +```javascript +// https://github.com/michael-ciniawsky/postcss-load-config +module.exports = { + plugins: { + autoprefixer: { overrideBrowserslist: ['Android 4.1', 'iOS 7.1', 'Chrome > 31', 'ff > 31', 'ie >= 8'] }, + 'cnjm-postcss-px-to-viewport': { + unitToConvert: 'px', // 要转化的单位 + viewportWidth: 750, // UI设计稿的宽度 + unitPrecision: 6, // 转换后的精度,即小数点位数 + propList: ['*'], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换 + viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw + fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw + minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换 + mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false + replace: true, // 是否转换后直接更换属性值 + include: [], + exclude: [], // 设置忽略文件,用正则做目录名匹配 + customFun: ({ file }) => { + // 这个自定义的方法是针对处理vant组件下的设计稿为375问题 + const designWidth = judgeComponent(file) ? 375 : 750; + return designWidth; + }, + }, +}; +``` + +**新手必看,老鸟跳过** + +很多小伙伴会问我,适配的问题, 因为我们使用的是 Vant UI,所以必须根据 Vant UI 375 的设计规范走,一般我们的设计会将 UI 图上传到蓝湖,我们就可以需要的尺寸了。下面就大搞普及一下 rem。 + +我们知道 `1rem` 等于 `html` 根元素设定的 `font-size` 的 `px` 值。Vant UI 设置 `rootValue: 37.5` , 你可以看到在 iPhone 6 下看到 ( `1rem 等于 37.5px` ): + +```html + +``` + +切换不同的机型,根元素可能会有不同的 `font-size` 。当你写 css px 样式时,会被程序换算成 `rem` 达到适配。 + +因为我们用了 Vant 的组件,需要按照 `rootValue: 37.5` 来写样式。 + +举个例子:设计给了你一张 750px \* 1334px 图片,在 iPhone6 上铺满屏幕, 其他机型适配。 + +- 当`rootValue: 75` , 样式 `width: 750px;height: 1334px;` 图片会撑满 iPhone6 屏幕,这个时候切换其他机型,图片也会跟着撑满。 +- 当`rootValue: 37.5` 的时候,样式 `width: 375px;height: 667px;` 图片会撑满 iPhone6 屏幕。 + +也就是 iphone 6 下 375px 宽度写 CSS。其他的你就可以根据你设计图,去写对应的样式就可以了。 + +当然,想要撑满屏幕你可以使用 100%,这里只是举例说明。 + +```html + + + +``` diff --git a/docs/guide/vue3/vite.md b/docs/guide/vue3/vite.md new file mode 100644 index 0000000..ce7682e --- /dev/null +++ b/docs/guide/vue3/vite.md @@ -0,0 +1,17 @@ +# vite + +基于原生 ES 模块提供了丰富的内建功能,如速度快到惊人的模块热更新(HMR),使用 Rollup 打包你的代码,并且它是预配置的,可输出用于生产环境的高度优化过的静态资源。更多关于[vite](https://cn.vitejs.dev/guide/) + +模版集成了如下的 vite 插件 + +- unplugin-auto-import(按需加载,自动引入) +- unplugin-vue-components(按需加载,自动引入组件) +- vite-plugin-compression(开启.gz 压缩) +- vite-plugin-eruda(控制台,方便移动端调试) +- vite-plugin-imagemin(图片压缩) +- vite-plugin-mock(引入 mockjs,本地模拟接口) +- vite-plugin-pages(动态生成路由) +- vite-plugin-progress(构建显示进度条) +- vite-plugin-restart(监听配置文件修改自动重启 Vite) +- vite-plugin-style-import(按需引入样式文件) +- vite-plugin-svg-icons(加载 SVG 文件,自动引入) diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..7ede175 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,34 @@ +--- +layout: home + +title: Vue-H5-Template +titleTemplate: 一个快速开发的vue h5移动端脚手架 + +hero: + name: Vue-H5-Template + text: 一个快速开发的Vue H5移动端脚手架 + image: + src: http://www.sunniejs.cn/static/weapp/logo.png + alt: sunnie + actions: + - theme: brand + text: 开始 + link: /guide/ + - theme: alt + text: Github仓库 + link: https://github.com/sunniejs/vue-h5-template + +features: + - icon: 💡 + title: 开箱即用 + details: 集成vue2、vue3的移动端快速开发模版,学习成本低,易上手 + - icon: 📦 + title: 代码规范 + details: 完整的eslint、prettier、stylelint规范,加上husky,帮助你更好的管理代码 + - icon: 🛠️ + title: 配置优化 + details: 完整配置的vue脚手架插件和优化,让你专注于业务开发,更高效 + - icon: ⚙️ + title: More + details: 加入我们,更多能力等你挖掘.... +--- diff --git a/package.json b/package.json new file mode 100644 index 0000000..496c511 --- /dev/null +++ b/package.json @@ -0,0 +1,10 @@ +{ + "devDependencies": { + "vitepress": "^1.0.0-alpha.8", + "vue": "^3.2.37" + }, + "scripts": { + "start": "vitepress dev docs --host 0.0.0.0", + "build": "vitepress build docs" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..fd1acac --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,710 @@ +lockfileVersion: 5.3 + +specifiers: + vitepress: ^1.0.0-alpha.8 + vue: ^3.2.37 + +devDependencies: + vitepress: 1.0.0-alpha.8 + vue: 3.2.37 + +packages: + + /@algolia/autocomplete-core/1.7.1: + resolution: {integrity: sha512-eiZw+fxMzNQn01S8dA/hcCpoWCOCwcIIEUtHHdzN5TGB3IpzLbuhqFeTfh2OUhhgkE8Uo17+wH+QJ/wYyQmmzg==} + dependencies: + '@algolia/autocomplete-shared': 1.7.1 + dev: true + + /@algolia/autocomplete-preset-algolia/1.7.1_algoliasearch@4.14.2: + resolution: {integrity: sha512-pJwmIxeJCymU1M6cGujnaIYcY3QPOVYZOXhFkWVM7IxKzy272BwCvMFMyc5NpG/QmiObBxjo7myd060OeTNJXg==} + peerDependencies: + '@algolia/client-search': ^4.9.1 + algoliasearch: ^4.9.1 + dependencies: + '@algolia/autocomplete-shared': 1.7.1 + algoliasearch: 4.14.2 + dev: true + + /@algolia/autocomplete-shared/1.7.1: + resolution: {integrity: sha512-eTmGVqY3GeyBTT8IWiB2K5EuURAqhnumfktAEoHxfDY2o7vg2rSnO16ZtIG0fMgt3py28Vwgq42/bVEuaQV7pg==} + dev: true + + /@algolia/cache-browser-local-storage/4.14.2: + resolution: {integrity: sha512-FRweBkK/ywO+GKYfAWbrepewQsPTIEirhi1BdykX9mxvBPtGNKccYAxvGdDCumU1jL4r3cayio4psfzKMejBlA==} + dependencies: + '@algolia/cache-common': 4.14.2 + dev: true + + /@algolia/cache-common/4.14.2: + resolution: {integrity: sha512-SbvAlG9VqNanCErr44q6lEKD2qoK4XtFNx9Qn8FK26ePCI8I9yU7pYB+eM/cZdS9SzQCRJBbHUumVr4bsQ4uxg==} + dev: true + + /@algolia/cache-in-memory/4.14.2: + resolution: {integrity: sha512-HrOukWoop9XB/VFojPv1R5SVXowgI56T9pmezd/djh2JnVN/vXswhXV51RKy4nCpqxyHt/aGFSq2qkDvj6KiuQ==} + dependencies: + '@algolia/cache-common': 4.14.2 + dev: true + + /@algolia/client-account/4.14.2: + resolution: {integrity: sha512-WHtriQqGyibbb/Rx71YY43T0cXqyelEU0lB2QMBRXvD2X0iyeGl4qMxocgEIcbHyK7uqE7hKgjT8aBrHqhgc1w==} + dependencies: + '@algolia/client-common': 4.14.2 + '@algolia/client-search': 4.14.2 + '@algolia/transporter': 4.14.2 + dev: true + + /@algolia/client-analytics/4.14.2: + resolution: {integrity: sha512-yBvBv2mw+HX5a+aeR0dkvUbFZsiC4FKSnfqk9rrfX+QrlNOKEhCG0tJzjiOggRW4EcNqRmaTULIYvIzQVL2KYQ==} + dependencies: + '@algolia/client-common': 4.14.2 + '@algolia/client-search': 4.14.2 + '@algolia/requester-common': 4.14.2 + '@algolia/transporter': 4.14.2 + dev: true + + /@algolia/client-common/4.14.2: + resolution: {integrity: sha512-43o4fslNLcktgtDMVaT5XwlzsDPzlqvqesRi4MjQz2x4/Sxm7zYg5LRYFol1BIhG6EwxKvSUq8HcC/KxJu3J0Q==} + dependencies: + '@algolia/requester-common': 4.14.2 + '@algolia/transporter': 4.14.2 + dev: true + + /@algolia/client-personalization/4.14.2: + resolution: {integrity: sha512-ACCoLi0cL8CBZ1W/2juehSltrw2iqsQBnfiu/Rbl9W2yE6o2ZUb97+sqN/jBqYNQBS+o0ekTMKNkQjHHAcEXNw==} + dependencies: + '@algolia/client-common': 4.14.2 + '@algolia/requester-common': 4.14.2 + '@algolia/transporter': 4.14.2 + dev: true + + /@algolia/client-search/4.14.2: + resolution: {integrity: sha512-L5zScdOmcZ6NGiVbLKTvP02UbxZ0njd5Vq9nJAmPFtjffUSOGEp11BmD2oMJ5QvARgx2XbX4KzTTNS5ECYIMWw==} + dependencies: + '@algolia/client-common': 4.14.2 + '@algolia/requester-common': 4.14.2 + '@algolia/transporter': 4.14.2 + dev: true + + /@algolia/logger-common/4.14.2: + resolution: {integrity: sha512-/JGlYvdV++IcMHBnVFsqEisTiOeEr6cUJtpjz8zc0A9c31JrtLm318Njc72p14Pnkw3A/5lHHh+QxpJ6WFTmsA==} + dev: true + + /@algolia/logger-console/4.14.2: + resolution: {integrity: sha512-8S2PlpdshbkwlLCSAB5f8c91xyc84VM9Ar9EdfE9UmX+NrKNYnWR1maXXVDQQoto07G1Ol/tYFnFVhUZq0xV/g==} + dependencies: + '@algolia/logger-common': 4.14.2 + dev: true + + /@algolia/requester-browser-xhr/4.14.2: + resolution: {integrity: sha512-CEh//xYz/WfxHFh7pcMjQNWgpl4wFB85lUMRyVwaDPibNzQRVcV33YS+63fShFWc2+42YEipFGH2iPzlpszmDw==} + dependencies: + '@algolia/requester-common': 4.14.2 + dev: true + + /@algolia/requester-common/4.14.2: + resolution: {integrity: sha512-73YQsBOKa5fvVV3My7iZHu1sUqmjjfs9TteFWwPwDmnad7T0VTCopttcsM3OjLxZFtBnX61Xxl2T2gmG2O4ehg==} + dev: true + + /@algolia/requester-node-http/4.14.2: + resolution: {integrity: sha512-oDbb02kd1o5GTEld4pETlPZLY0e+gOSWjWMJHWTgDXbv9rm/o2cF7japO6Vj1ENnrqWvLBmW1OzV9g6FUFhFXg==} + dependencies: + '@algolia/requester-common': 4.14.2 + dev: true + + /@algolia/transporter/4.14.2: + resolution: {integrity: sha512-t89dfQb2T9MFQHidjHcfhh6iGMNwvuKUvojAj+JsrHAGbuSy7yE4BylhLX6R0Q1xYRoC4Vvv+O5qIw/LdnQfsQ==} + dependencies: + '@algolia/cache-common': 4.14.2 + '@algolia/logger-common': 4.14.2 + '@algolia/requester-common': 4.14.2 + dev: true + + /@babel/parser/7.18.11: + resolution: {integrity: sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==} + engines: {node: '>=6.0.0'} + hasBin: true + dev: true + + /@docsearch/css/3.2.1: + resolution: {integrity: sha512-gaP6TxxwQC+K8D6TRx5WULUWKrcbzECOPA2KCVMuI+6C7dNiGUk5yXXzVhc5sld79XKYLnO9DRTI4mjXDYkh+g==} + dev: true + + /@docsearch/js/3.2.1: + resolution: {integrity: sha512-H1PekEtSeS0msetR2YGGey2w7jQ2wAKfGODJvQTygSwMgUZ+2DHpzUgeDyEBIXRIfaBcoQneqrzsljM62pm6Xg==} + dependencies: + '@docsearch/react': 3.2.1 + preact: 10.10.3 + transitivePeerDependencies: + - '@algolia/client-search' + - '@types/react' + - react + - react-dom + dev: true + + /@docsearch/react/3.2.1: + resolution: {integrity: sha512-EzTQ/y82s14IQC5XVestiK/kFFMe2aagoYFuTAIfIb/e+4FU7kSMKonRtLwsCiLQHmjvNQq+HO+33giJ5YVtaQ==} + peerDependencies: + '@types/react': '>= 16.8.0 < 19.0.0' + react: '>= 16.8.0 < 19.0.0' + react-dom: '>= 16.8.0 < 19.0.0' + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + react-dom: + optional: true + dependencies: + '@algolia/autocomplete-core': 1.7.1 + '@algolia/autocomplete-preset-algolia': 1.7.1_algoliasearch@4.14.2 + '@docsearch/css': 3.2.1 + algoliasearch: 4.14.2 + transitivePeerDependencies: + - '@algolia/client-search' + dev: true + + /@esbuild/linux-loong64/0.14.54: + resolution: {integrity: sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + dev: true + optional: true + + /@types/web-bluetooth/0.0.15: + resolution: {integrity: sha512-w7hEHXnPMEZ+4nGKl/KDRVpxkwYxYExuHOYXyzIzCDzEZ9ZCGMAewulr9IqJu2LR4N37fcnb1XVeuZ09qgOxhA==} + dev: true + + /@vitejs/plugin-vue/3.0.3_vite@3.0.8+vue@3.2.37: + resolution: {integrity: sha512-U4zNBlz9mg+TA+i+5QPc3N5lQvdUXENZLO2h0Wdzp56gI1MWhqJOv+6R+d4kOzoaSSq6TnGPBdZAXKOe4lXy6g==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^3.0.0 + vue: ^3.2.25 + dependencies: + vite: 3.0.8 + vue: 3.2.37 + dev: true + + /@vue/compiler-core/3.2.37: + resolution: {integrity: sha512-81KhEjo7YAOh0vQJoSmAD68wLfYqJvoiD4ulyedzF+OEk/bk6/hx3fTNVfuzugIIaTrOx4PGx6pAiBRe5e9Zmg==} + dependencies: + '@babel/parser': 7.18.11 + '@vue/shared': 3.2.37 + estree-walker: 2.0.2 + source-map: 0.6.1 + dev: true + + /@vue/compiler-dom/3.2.37: + resolution: {integrity: sha512-yxJLH167fucHKxaqXpYk7x8z7mMEnXOw3G2q62FTkmsvNxu4FQSu5+3UMb+L7fjKa26DEzhrmCxAgFLLIzVfqQ==} + dependencies: + '@vue/compiler-core': 3.2.37 + '@vue/shared': 3.2.37 + dev: true + + /@vue/compiler-sfc/3.2.37: + resolution: {integrity: sha512-+7i/2+9LYlpqDv+KTtWhOZH+pa8/HnX/905MdVmAcI/mPQOBwkHHIzrsEsucyOIZQYMkXUiTkmZq5am/NyXKkg==} + dependencies: + '@babel/parser': 7.18.11 + '@vue/compiler-core': 3.2.37 + '@vue/compiler-dom': 3.2.37 + '@vue/compiler-ssr': 3.2.37 + '@vue/reactivity-transform': 3.2.37 + '@vue/shared': 3.2.37 + estree-walker: 2.0.2 + magic-string: 0.25.9 + postcss: 8.4.16 + source-map: 0.6.1 + dev: true + + /@vue/compiler-ssr/3.2.37: + resolution: {integrity: sha512-7mQJD7HdXxQjktmsWp/J67lThEIcxLemz1Vb5I6rYJHR5vI+lON3nPGOH3ubmbvYGt8xEUaAr1j7/tIFWiEOqw==} + dependencies: + '@vue/compiler-dom': 3.2.37 + '@vue/shared': 3.2.37 + dev: true + + /@vue/devtools-api/6.2.1: + resolution: {integrity: sha512-OEgAMeQXvCoJ+1x8WyQuVZzFo0wcyCmUR3baRVLmKBo1LmYZWMlRiXlux5jd0fqVJu6PfDbOrZItVqUEzLobeQ==} + dev: true + + /@vue/reactivity-transform/3.2.37: + resolution: {integrity: sha512-IWopkKEb+8qpu/1eMKVeXrK0NLw9HicGviJzhJDEyfxTR9e1WtpnnbYkJWurX6WwoFP0sz10xQg8yL8lgskAZg==} + dependencies: + '@babel/parser': 7.18.11 + '@vue/compiler-core': 3.2.37 + '@vue/shared': 3.2.37 + estree-walker: 2.0.2 + magic-string: 0.25.9 + dev: true + + /@vue/reactivity/3.2.37: + resolution: {integrity: sha512-/7WRafBOshOc6m3F7plwzPeCu/RCVv9uMpOwa/5PiY1Zz+WLVRWiy0MYKwmg19KBdGtFWsmZ4cD+LOdVPcs52A==} + dependencies: + '@vue/shared': 3.2.37 + dev: true + + /@vue/runtime-core/3.2.37: + resolution: {integrity: sha512-JPcd9kFyEdXLl/i0ClS7lwgcs0QpUAWj+SKX2ZC3ANKi1U4DOtiEr6cRqFXsPwY5u1L9fAjkinIdB8Rz3FoYNQ==} + dependencies: + '@vue/reactivity': 3.2.37 + '@vue/shared': 3.2.37 + dev: true + + /@vue/runtime-dom/3.2.37: + resolution: {integrity: sha512-HimKdh9BepShW6YozwRKAYjYQWg9mQn63RGEiSswMbW+ssIht1MILYlVGkAGGQbkhSh31PCdoUcfiu4apXJoPw==} + dependencies: + '@vue/runtime-core': 3.2.37 + '@vue/shared': 3.2.37 + csstype: 2.6.20 + dev: true + + /@vue/server-renderer/3.2.37_vue@3.2.37: + resolution: {integrity: sha512-kLITEJvaYgZQ2h47hIzPh2K3jG8c1zCVbp/o/bzQOyvzaKiCquKS7AaioPI28GNxIsE/zSx+EwWYsNxDCX95MA==} + peerDependencies: + vue: 3.2.37 + dependencies: + '@vue/compiler-ssr': 3.2.37 + '@vue/shared': 3.2.37 + vue: 3.2.37 + dev: true + + /@vue/shared/3.2.37: + resolution: {integrity: sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw==} + dev: true + + /@vueuse/core/9.1.0_vue@3.2.37: + resolution: {integrity: sha512-BIroqvXEqt826aE9r3K5cox1zobuPuAzdYJ36kouC2TVhlXvFKIILgFVWrpp9HZPwB3aLzasmG3K87q7TSyXZg==} + dependencies: + '@types/web-bluetooth': 0.0.15 + '@vueuse/metadata': 9.1.0 + '@vueuse/shared': 9.1.0_vue@3.2.37 + vue-demi: 0.13.8_vue@3.2.37 + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: true + + /@vueuse/metadata/9.1.0: + resolution: {integrity: sha512-8OEhlog1iaAGTD3LICZ8oBGQdYeMwByvXetOtAOZCJOzyCRSwqwdggTsmVZZ1rkgYIEqgUBk942AsAPwM21s6A==} + dev: true + + /@vueuse/shared/9.1.0_vue@3.2.37: + resolution: {integrity: sha512-pB/3njQu4tfJJ78ajELNda0yMG6lKfpToQW7Soe09CprF1k3QuyoNi1tBNvo75wBDJWD+LOnr+c4B5HZ39jY/Q==} + dependencies: + vue-demi: 0.13.8_vue@3.2.37 + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: true + + /algoliasearch/4.14.2: + resolution: {integrity: sha512-ngbEQonGEmf8dyEh5f+uOIihv4176dgbuOZspiuhmTTBRBuzWu3KCGHre6uHj5YyuC7pNvQGzB6ZNJyZi0z+Sg==} + dependencies: + '@algolia/cache-browser-local-storage': 4.14.2 + '@algolia/cache-common': 4.14.2 + '@algolia/cache-in-memory': 4.14.2 + '@algolia/client-account': 4.14.2 + '@algolia/client-analytics': 4.14.2 + '@algolia/client-common': 4.14.2 + '@algolia/client-personalization': 4.14.2 + '@algolia/client-search': 4.14.2 + '@algolia/logger-common': 4.14.2 + '@algolia/logger-console': 4.14.2 + '@algolia/requester-browser-xhr': 4.14.2 + '@algolia/requester-common': 4.14.2 + '@algolia/requester-node-http': 4.14.2 + '@algolia/transporter': 4.14.2 + dev: true + + /body-scroll-lock/4.0.0-beta.0: + resolution: {integrity: sha512-a7tP5+0Mw3YlUJcGAKUqIBkYYGlYxk2fnCasq/FUph1hadxlTRjF+gAcZksxANnaMnALjxEddmSi/H3OR8ugcQ==} + dev: true + + /csstype/2.6.20: + resolution: {integrity: sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==} + dev: true + + /esbuild-android-64/0.14.54: + resolution: {integrity: sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + dev: true + optional: true + + /esbuild-android-arm64/0.14.54: + resolution: {integrity: sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + dev: true + optional: true + + /esbuild-darwin-64/0.14.54: + resolution: {integrity: sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + dev: true + optional: true + + /esbuild-darwin-arm64/0.14.54: + resolution: {integrity: sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + dev: true + optional: true + + /esbuild-freebsd-64/0.14.54: + resolution: {integrity: sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + dev: true + optional: true + + /esbuild-freebsd-arm64/0.14.54: + resolution: {integrity: sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + dev: true + optional: true + + /esbuild-linux-32/0.14.54: + resolution: {integrity: sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + dev: true + optional: true + + /esbuild-linux-64/0.14.54: + resolution: {integrity: sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + dev: true + optional: true + + /esbuild-linux-arm/0.14.54: + resolution: {integrity: sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + dev: true + optional: true + + /esbuild-linux-arm64/0.14.54: + resolution: {integrity: sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + dev: true + optional: true + + /esbuild-linux-mips64le/0.14.54: + resolution: {integrity: sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + dev: true + optional: true + + /esbuild-linux-ppc64le/0.14.54: + resolution: {integrity: sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + dev: true + optional: true + + /esbuild-linux-riscv64/0.14.54: + resolution: {integrity: sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + dev: true + optional: true + + /esbuild-linux-s390x/0.14.54: + resolution: {integrity: sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + dev: true + optional: true + + /esbuild-netbsd-64/0.14.54: + resolution: {integrity: sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + dev: true + optional: true + + /esbuild-openbsd-64/0.14.54: + resolution: {integrity: sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + dev: true + optional: true + + /esbuild-sunos-64/0.14.54: + resolution: {integrity: sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + dev: true + optional: true + + /esbuild-windows-32/0.14.54: + resolution: {integrity: sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + dev: true + optional: true + + /esbuild-windows-64/0.14.54: + resolution: {integrity: sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + dev: true + optional: true + + /esbuild-windows-arm64/0.14.54: + resolution: {integrity: sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + dev: true + optional: true + + /esbuild/0.14.54: + resolution: {integrity: sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/linux-loong64': 0.14.54 + esbuild-android-64: 0.14.54 + esbuild-android-arm64: 0.14.54 + esbuild-darwin-64: 0.14.54 + esbuild-darwin-arm64: 0.14.54 + esbuild-freebsd-64: 0.14.54 + esbuild-freebsd-arm64: 0.14.54 + esbuild-linux-32: 0.14.54 + esbuild-linux-64: 0.14.54 + esbuild-linux-arm: 0.14.54 + esbuild-linux-arm64: 0.14.54 + esbuild-linux-mips64le: 0.14.54 + esbuild-linux-ppc64le: 0.14.54 + esbuild-linux-riscv64: 0.14.54 + esbuild-linux-s390x: 0.14.54 + esbuild-netbsd-64: 0.14.54 + esbuild-openbsd-64: 0.14.54 + esbuild-sunos-64: 0.14.54 + esbuild-windows-32: 0.14.54 + esbuild-windows-64: 0.14.54 + esbuild-windows-arm64: 0.14.54 + dev: true + + /estree-walker/2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + dev: true + + /fsevents/2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + dev: true + optional: true + + /function-bind/1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: true + + /has/1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: true + + /is-core-module/2.10.0: + resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==} + dependencies: + has: 1.0.3 + dev: true + + /jsonc-parser/3.1.0: + resolution: {integrity: sha512-DRf0QjnNeCUds3xTjKlQQ3DpJD51GvDjJfnxUVWg6PZTo2otSm+slzNAxU/35hF8/oJIKoG9slq30JYOsF2azg==} + dev: true + + /magic-string/0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + dependencies: + sourcemap-codec: 1.4.8 + dev: true + + /nanoid/3.3.4: + resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + + /path-parse/1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /picocolors/1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true + + /postcss/8.4.16: + resolution: {integrity: sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.4 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: true + + /preact/10.10.3: + resolution: {integrity: sha512-Gwwh0o531izatQQZu0yEX4mtfxVYsZJ4TT/o2VK3UZ/UuAWAWFnzsEfpZvad32vY3TKoRnSY2WqiDz2rH/viWQ==} + dev: true + + /resolve/1.22.1: + resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} + hasBin: true + dependencies: + is-core-module: 2.10.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /rollup/2.77.3: + resolution: {integrity: sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==} + engines: {node: '>=10.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /shiki/0.11.1: + resolution: {integrity: sha512-EugY9VASFuDqOexOgXR18ZV+TbFrQHeCpEYaXamO+SZlsnT/2LxuLBX25GGtIrwaEVFXUAbUQ601SWE2rMwWHA==} + dependencies: + jsonc-parser: 3.1.0 + vscode-oniguruma: 1.6.2 + vscode-textmate: 6.0.0 + dev: true + + /source-map-js/1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map/0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /sourcemap-codec/1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + dev: true + + /supports-preserve-symlinks-flag/1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /vite/3.0.8: + resolution: {integrity: sha512-AOZ4eN7mrkJiOLuw8IA7piS4IdOQyQCA81GxGsAQvAZzMRi9ZwGB3TOaYsj4uLAWK46T5L4AfQ6InNGlxX30IQ==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + less: '*' + sass: '*' + stylus: '*' + terser: ^5.4.0 + peerDependenciesMeta: + less: + optional: true + sass: + optional: true + stylus: + optional: true + terser: + optional: true + dependencies: + esbuild: 0.14.54 + postcss: 8.4.16 + resolve: 1.22.1 + rollup: 2.77.3 + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /vitepress/1.0.0-alpha.8: + resolution: {integrity: sha512-kTRN5DCagvMqr9OjylSV9/waGg0IHrxL0hBVuJoz7ykleZq2qR02n5CaiFq5QrSB/VRBGqiVsFQzet9vJsXS8g==} + hasBin: true + dependencies: + '@docsearch/css': 3.2.1 + '@docsearch/js': 3.2.1 + '@vitejs/plugin-vue': 3.0.3_vite@3.0.8+vue@3.2.37 + '@vue/devtools-api': 6.2.1 + '@vueuse/core': 9.1.0_vue@3.2.37 + body-scroll-lock: 4.0.0-beta.0 + shiki: 0.11.1 + vite: 3.0.8 + vue: 3.2.37 + transitivePeerDependencies: + - '@algolia/client-search' + - '@types/react' + - '@vue/composition-api' + - less + - react + - react-dom + - sass + - stylus + - terser + dev: true + + /vscode-oniguruma/1.6.2: + resolution: {integrity: sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==} + dev: true + + /vscode-textmate/6.0.0: + resolution: {integrity: sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ==} + dev: true + + /vue-demi/0.13.8_vue@3.2.37: + resolution: {integrity: sha512-Vy1zbZhCOdsmvGR6tJhAvO5vhP7eiS8xkbYQSoVa7o6KlIy3W8Rc53ED4qI4qpeRDjv3mLfXSEpYU6Yq4pgXRg==} + 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.2.37 + dev: true + + /vue/3.2.37: + resolution: {integrity: sha512-bOKEZxrm8Eh+fveCqS1/NkG/n6aMidsI6hahas7pa0w/l7jkbssJVsRhVDs07IdDq7h9KHswZOgItnwJAgtVtQ==} + dependencies: + '@vue/compiler-dom': 3.2.37 + '@vue/compiler-sfc': 3.2.37 + '@vue/runtime-dom': 3.2.37 + '@vue/server-renderer': 3.2.37_vue@3.2.37 + '@vue/shared': 3.2.37 + dev: true