diff --git a/docs/.vuepress/config.ts b/docs/.vuepress/config.ts index 91edf65e..a4cc36ae 100644 --- a/docs/.vuepress/config.ts +++ b/docs/.vuepress/config.ts @@ -3,6 +3,7 @@ import { themePlume } from '@vuepress-plume/vuepress-theme-plume' import { viteBundler } from '@vuepress/bundler-vite' import { webpackBundler } from '@vuepress/bundler-webpack' import { defineUserConfig } from '@vuepress/cli' +import notes from './notes' export default defineUserConfig({ base: '/', @@ -33,61 +34,22 @@ export default defineUserConfig({ twitter: 'https://baidu.com', linkedin: 'https://baidu.com', }, - notes: { - notes: [ - { - link: 'typescript', - dir: 'typescript', - text: 'Typescript', - sidebar: [ - '', - { - text: '123', - children: ['1', '2'], - }, - { - text: 'css', - dir: 'css', - children: ['1', '2'], - }, - ], - }, - { - link: '/interview-question', - text: '面试题解析', - dir: '面试题', - sidebar: [ - { - text: 'HTML', - dir: 'HTML', - children: [], - }, - { - text: 'CSS', - dir: 'CSS', - children: ['盒模型'], - }, - { - text: 'JavaScript', - dir: 'JavaScript', - children: [], - }, - ], - }, - ], - }, + notes, darkMode: true, navbar: [ { - text: '笔记', + text: 'VuePress', children: [ + { text: 'theme-plume', link: '/note/vuepress-theme-plume/' }, { - text: 'typescript', - link: '/note/typescript/', - }, - { - text: '面试题', - link: '/note/interview-question', + text: 'Plugin', + children: [ + { text: 'caniuse', link: '/note/vuepress-plugin/caniuse/' }, + { + text: 'netlify-functions', + link: '/note/vuepress-plugin/netlify-functions/', + }, + ], }, ], }, @@ -97,9 +59,6 @@ export default defineUserConfig({ content: '', }, themePlugins: { - caniuse: { - mode: 'embed', - }, search: { locales: { '/': { diff --git a/docs/.vuepress/notes.ts b/docs/.vuepress/notes.ts new file mode 100644 index 00000000..0d49d09c --- /dev/null +++ b/docs/.vuepress/notes.ts @@ -0,0 +1,47 @@ +import { definePlumeNotesConfig } from '@vuepress-plume/vuepress-theme-plume' + +export default definePlumeNotesConfig({ + notes: [ + { + text: '', + dir: 'vuepress-theme-plume', + link: '/vuepress-theme-plume/', + sidebar: [ + '', + { + text: '指南', + children: ['快速开始', '编写文章'], + }, + { + text: '配置', + children: [ + { + text: '主题配置', + link: '主题配置', + children: ['主题插件配置', 'notes配置'], + }, + '页面配置', + ], + }, + { + text: '功能', + children: ['基础功能', 'markdown增强'], + }, + ], + }, + { + dir: 'vuepress-plugin', + text: '', + link: '/vuepress-plugin/', + sidebar: [ + 'caniuse/README', + { + dir: 'netlify-functions', + text: 'plugin-netlify-functions', + link: 'netlify-functions', + children: ['', '介绍', '使用', '功能', 'API', 'functions开发指南'], + }, + ], + }, + ], +}) diff --git a/docs/notes/typescript/1.md b/docs/notes/typescript/1.md deleted file mode 100644 index bccf253e..00000000 --- a/docs/notes/typescript/1.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: md -createTime: 2022/04/04 01:56:31 -author: pengzhanbo -permalink: /note/typescript/5j2ggf0m ---- diff --git a/docs/notes/typescript/2.md b/docs/notes/typescript/2.md deleted file mode 100644 index 0b5eb37f..00000000 --- a/docs/notes/typescript/2.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: md -createTime: 2022/04/04 01:57:39 -author: pengzhanbo -permalink: /note/typescript/casr1ibn ---- diff --git a/docs/notes/typescript/README.md b/docs/notes/typescript/README.md deleted file mode 100644 index f31962d7..00000000 --- a/docs/notes/typescript/README.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: Typescript -createTime: 2022/04/04 09:45:31 -author: pengzhanbo -permalink: /note/typescript/ ---- - -## typescript - -### haha - -内容 - -::: tip -提示 -::: - -::: info -信息 -::: - -::: note -注释 -::: - -::: warning -警告 -::: - -::: danger -危险 -::: - -::: details -详情 -::: - - -- [ ] todo -- [x] todo diff --git a/docs/notes/typescript/css/1.md b/docs/notes/typescript/css/1.md deleted file mode 100644 index 93a4597e..00000000 --- a/docs/notes/typescript/css/1.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: md -createTime: 2022/04/12 12:09:10 -author: pengzhanbo -permalink: /note/typescript/g86ae1b3/ ---- diff --git a/docs/notes/typescript/css/2.md b/docs/notes/typescript/css/2.md deleted file mode 100644 index b5752767..00000000 --- a/docs/notes/typescript/css/2.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: md -createTime: 2022/04/12 12:09:15 -author: pengzhanbo -permalink: /note/typescript/vruetr0c/ ---- diff --git a/docs/notes/vuepress-plugin/caniuse/README.md b/docs/notes/vuepress-plugin/caniuse/README.md new file mode 100644 index 00000000..52d5c03d --- /dev/null +++ b/docs/notes/vuepress-plugin/caniuse/README.md @@ -0,0 +1,102 @@ +--- +title: plugin-caniuse +createTime: 2022/05/13 01:02:51 +author: pengzhanbo +permalink: /note/vuepress-plugin/caniuse/ +--- + +项目地址: [vuepress-plugin-caniuse](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/packages/plugin-caniuse) + +![npm version](https://badge.fury.io/js/@vuepress-plume%2Fvuepress-plugin-caniuse.svg) + +![npm download](https://img.shields.io/npm/dy/@vuepress-plume/vuepress-plugin-caniuse) + +## 指南 + +为你的 vuepress 站点,在编辑 技术文章时, 提供 嵌入 [can-i-use](https://caniuse.com/) WEB feature 各平台支持说明图标 的功能。 + +方便在描述某个 WEB feature 时,能更直观的表述 该特性的支持程度。 + +## 安装 + +:::: code-group +::: code-group-item npm +``` sh +npm install @vuepress-plume/vuepress-plugin-caniuse +``` +::: +::: code-group-item yarn:active +``` sh +yarn add @vuepress-plume/vuepress-plugin-caniuse +``` +::: +::: code-group-item pnpm +``` sh +pnpm add @vuepress-plume/vuepress-plugin-caniuse +``` +::: +:::: + +## 使用 + +### Step1:添加插件 + +将插件添加到你的 vuepress 项目的配置文件中: + +:::: code-group +::: code-group-item .vuepress/config.ts +``` ts {2,6} +import { defineUserConfig } from 'vuepress' +import { caniusePlugin } from '@vuepress-plume/vuepress-plugin-caniuse' + +export default defineUserConfig({ + plugins: [ + caniusePlugin() + ] +}) +``` +::: +::: code-group-item .vuepress/config.js +``` js {1,5} +const { caniusePlugin } = require('@vuepress-plume/vuepress-plugin-caniuse') + +module.exports = { + plugins: [ + caniusePlugin() + ] +} +``` +::: +:::: + +### Step2:在markdown中使用 + +在你的 文章 markdown文件中,使用以下格式: + +``` md +::: caniuse +::: +``` + +__示例: 获取 css 伪类选择器 `:dir()` 在各个浏览器的支持情况图标:__ + +``` md +::: caniuse css-matches-pseudo +::: +``` +效果: + +::: caniuse css-matches-pseudo +::: + +## Method + +`caniusePlugin([options])` + +插件注册函数 + +__options:__ `[CanIUsePluginOptions]` + +- `options.mode`: 配置 can-i-use 在 文章中的 嵌入模式, 默认: `image` + - `image`: 嵌入 特性图表图片 + - `embed`: 嵌入 iframe, 实时的,可交互的模式 diff --git a/docs/notes/vuepress-plugin/netlify-functions/API.md b/docs/notes/vuepress-plugin/netlify-functions/API.md new file mode 100644 index 00000000..59198b1a --- /dev/null +++ b/docs/notes/vuepress-plugin/netlify-functions/API.md @@ -0,0 +1,86 @@ +--- +title: API +createTime: 2022/05/13 05:49:14 +author: pengzhanbo +permalink: /note/vuepress-plugin/netlify-functions/api/ +--- + +## netlifyFunctionsPlugin(options) + +在 vuepress 项目中使用, 或者 开发vuepress-theme时使用,提供 netlify-functions 开发时服务。 + +该插件应该优先于其他有依赖该插件的其他插件之前调用。 + +``` js +netlifyFunctionsPlugin({ + sourceDirectory: '', + destDirectory: '', + proxyPrefix: '', +}) +``` + +### options + +__类型:__ `{ sourceDirectory: string, destDirectory: string, proxyPrefix: string }` + +- `options.sourceDirectory`: + + `functions` 开发时所在目录, 默认值: `app.dir.source('.vuepress/functions')`, + 即,如果你的vuepress项目源码目录是 `src`, 那么 `sourceDirectory` 默认为 `src/.vuepress/functions/` + +- `options.destDirectory`: + + `functions` 构建后输出目录,默认值: `app.dir.dest('functions')`, + 即,如果你的 vuepress项目配置的 `dest` 输出目录为 `docs`, 那么默认输出目录为 `docs/functions`, + 一般来说,这个配置不需要手动修改。 + +- `options.proxyPrefix`: + + 在开发环境中, `Netlify Functions` 服务的默认路径是 `/.netlify/functions/*`, 但这并不能保持开发环境和 + 生产部署环境一致,所以需要将路径重写。 + + 默认值: `/api` + + 即 `^/api/*` 的请求会被转发到 `/.netlify/functions/*` , + 如, `functions/my_function.ts` ,则请求 `/api/my_function` 将会转发到 `/.netlify/functions/my_function`。 + + + +## useNetlifyFunctionsPlugin(app, options) + +在开发 vuepress plugin 时使用,为插件提供 `netlify functiosn` 支持 + +``` ts +import { useNetlifyFunctionsPlugin } from '@vuepress-plume/vuepress-plugin-netlify-functions' + +const myPlugin = (): Plugin => { + return (app: App) => { + const { + // 请求前缀, 默认 /api + proxyPrefix, + preparePluginFunctions, + generatePluginFunctions + } = useNetlifyFunctionsPlugin(app, { + // 指定插件的functions目录,相关脚本在此目录中开发 + directory: path.resolve(__dirname, 'functions') + }) + return { + name: 'vuepress-plugin-myPlugin', + onPrepared:() => preparePluginFunctions(), + onGenerated: () => generatePluginFunctions(), + } + } +} +``` + +### options + +__类型:__ `{ directory: string }` + +- `options.directory` + + 插件中的 functions 开发目录。 + + 一般来说,它的值都设置为 `path.resolve(__dirname, 'functions')` + + diff --git a/docs/notes/vuepress-plugin/netlify-functions/README.md b/docs/notes/vuepress-plugin/netlify-functions/README.md new file mode 100644 index 00000000..940e3e6d --- /dev/null +++ b/docs/notes/vuepress-plugin/netlify-functions/README.md @@ -0,0 +1,41 @@ +--- +title: 指南 +createTime: 2022/05/13 01:28:38 +author: pengzhanbo +permalink: /note/vuepress-plugin/netlify-functions/ +--- + +项目地址: [vuepress-plugin-caniuse](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/packages/plugin-netlify-functions) + +![npm version](https://badge.fury.io/js/@vuepress-plume%2Fvuepress-plugin-netlify-functions.svg) + +![npm download](https://img.shields.io/npm/dy/@vuepress-plume/vuepress-plugin-netlify-functions) + +如果你的 vuepress 站点是部署在 netlify 的,而且希望能够使用netlify functions 来做 serverless。 + +那么你可能需要本插件提供支持。 + +本插件仅 提供 `Netlify Functions` 开发环境和 打包构建 支持,不提供具体的 `functions` 函数。 + +- 你可以基于此插件 在你的 vuepress 项目中 自定义 `functions` +- 也可以基于此插件作为你的 vuepress plugin 依赖,开发自定义 `functions` 提供给其他 vuepress项目使用。 + +## 安装 + +:::: code-group +::: code-group-item npm +``` sh +npm install @vuepress-plume/vuepress-plugin-netlify-functions +``` +::: +::: code-group-item yarn:active +``` sh +yarn add @vuepress-plume/vuepress-plugin-netlify-functions +``` +::: +::: code-group-item pnpm +``` sh +pnpm add @vuepress-plume/vuepress-plugin-netlify-functions +``` +::: +:::: diff --git a/docs/notes/vuepress-plugin/netlify-functions/functions开发指南.md b/docs/notes/vuepress-plugin/netlify-functions/functions开发指南.md new file mode 100644 index 00000000..6e8cbde5 --- /dev/null +++ b/docs/notes/vuepress-plugin/netlify-functions/functions开发指南.md @@ -0,0 +1,95 @@ +--- +title: functions开发指南 +createTime: 2022/05/13 05:45:24 +author: pengzhanbo +permalink: /note/vuepress-plugin/netlify-functions/develop-functions/ +--- + +## 说明 + +### 在一个 vuepress 项目中 + +在默认配置下,如果你 packages.json +``` json +{ + "scripts": { + "serve": "vuepress dev src", + "build": "vuepress build src" + } +} +``` +即, 你的 `sourceDir` 为 `src` 目录, 那么,你的functions目录则为 `src/.vuepress/functions`。 + +在这个目录下,直属的 `ts/js` 文件,均为一个个独立的 `function`, 不包括这个目录下的子目录。 + +``` sh +src/.vuepress/functions +├─my_function.ts # 这是一个function 通过 /api/my_function 调用 +├─verify_phone.ts # 这是一个 function, 通过 /api/verify_phone 调用 +└─utils # 子目录中的不会被识别为function + └─index.ts +``` + +### 在一个 vuepress plugin 项目中 + +以官方仓库插件的基本组织结构为例 +``` sh +src/node +├─functions +│ ├─my_function.ts # 这是一个function 通过 /api/my_function 调用 +│ ├─verify_phone.ts # 这是一个 function, 通过 /api/verify_phone 调用 +│ └─utils # 子目录中的不会被识别为function +│ └─index.ts +├─index.ts +└─plugin.ts # 在这个文件中配置了 directory 为 path.resolve(__dirname, 'functions') +``` + +## 依赖 + +如果你是使用 typescript 作为开发语言,那么可以引入 `@netlify/functions` 模块提供类型检查支持。 + +如果你的 function 依赖其他的第三方模块,请在配置在项目`package.json` 的 `dependencies` 字段中作为生产依赖。 + +如果你是通过插件提供 function,请在 插件的使用指南中 说明,你的插件function依赖了哪些第三方模块, +提醒使用者安装这些依赖。 + +## function + +`functions` 通过 导出一个 `handler` 函数 提供给 云函数服务调用。 + +一个 function 的内容一般如下: + +- 异步函数 + + 在异步函数中,支持直接返回一个对象作为 响应体报文 + + ``` ts + import { Handler } from '@netlify/functions' + export const handler: Handler = async function (event, context) { + // do something + return { + statusCode: 200, + body: JSON.stringify({}) + } + } + ``` + +- 非异步函数 + + 在非异步函数中,通过 `callback` 函数参数返回响应体报文 + + ``` ts + import { Handler } from '@netlify/functions' + export const handler: Handler = function (event, context, callback) { + // do something + callback{ + statusCode: 200, + body: JSON.stringify({}) + }) + } + ``` + +## 示例 + +[plugin-page-collection](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/packages/plugin-page-collection) +页面访问次数插件 diff --git a/docs/notes/vuepress-plugin/netlify-functions/介绍.md b/docs/notes/vuepress-plugin/netlify-functions/介绍.md new file mode 100644 index 00000000..758be541 --- /dev/null +++ b/docs/notes/vuepress-plugin/netlify-functions/介绍.md @@ -0,0 +1,62 @@ +--- +title: 介绍 +createTime: 2022/05/13 05:47:06 +author: pengzhanbo +permalink: /note/vuepress-plugin/netlify-functions/intro/ +--- + +## Why + +### Netlify + +[Netlify](https://www.netlify.com/) 是一个提供了免费部署静态站点的平台,可用于作为 `github page` 的替代工具。 + +在 `Netlify` 上面部署站点也非常方便,可以直接使用 `github` 仓库进行 构建并部署,同时支持 自定义域名。 + +还提供了 `Netlify Functions` 等工具,可以用于给站点提供 自定义云函数。 + +### VuePress + +`vuepress` 是一个很方便的静态网站构建工具,使我们可以直接书写 markdown后,构建为一个高可用的静态站点。 + +### 部署 + +一般情况下,当我们不希望购买一个服务器用于部署我们的站点时,通常都会选择使用 `github page` 来进行免费部署。 +`Netlify` 是一种替代方案,而且当使用 `Netlify` 部署时,还可以利用 `Netlify Functions` 提供的云函数功能, +使站点能够进行更为丰富的交互。 + +### 场景 + +通过 `Functions` 连接到 一些提供了 免费服务的 云存储服务,比如 `FireBase` ,`Lean Cloud` 等。 +虽然这些云存储服务提供了 Web 客户端直连服务的功能。但毕竟我们的站点源码是直接放在 `github`开源仓库中, +我们不希望将 这些 云存储服务 提供的一些 鉴权信息 直接 保存在 仓库代码中,带来某些安全风险。 + +在这种场景下,就可以借助 `Netlify Functions` ,将这些鉴权信息,作为 `环境变量` , +托管在 `Netlify Environment Variables` 中,然后通过 站点调用 `Functions` 来获取这些鉴权信息。 +或者进一步的,直接将 云存储服务的 连接、功能等,都在 `Netlify Functions` 中完成, +站点再调用 `Functions` 接口, 获取返回的数据。 + +有了 `Netlify Functions` 加上 一些 第三方的 云服务支持, 可以为我们的 vuepress 站点提供更强大的支持。 + + +## 如何整合? + +在基于以上的背景,下一步就是需要将 `Netlify Functions` 能够在 我们的 `Vuepress` 项目中进行 整合了。 + +- 如何使 `Netlify Functions` 能够在本地开发环境中进行调试。 +- 如何将 已开发好的 `Functions` 作为 `vuepress plugin` 提供给 其他 `vuepress theme` 或 `vuepress` 站点中使用。 + +### 开发环境 + +本插件在 vuepress 的开发服务的基础上, 启动了一个 由 `netlify-cli` 提供的 服务,并将该服务通过代理的方式, +代理到 vuepress开发服务上,统合开发环境。 + +并且监听 functions 内容变更,实现热更新。 + +### 打包 + +在打包阶段, 生成一个 `netlify.toml` 配置文件,配置 functions 相关内容。 + +并且将 所有 functions 添加在 vuepress 的构建包中。 + +如何使用插件,请查看 [使用文档](/note/vuepress-plugin/netlify-functions/usage/) diff --git a/docs/notes/vuepress-plugin/netlify-functions/使用.md b/docs/notes/vuepress-plugin/netlify-functions/使用.md new file mode 100644 index 00000000..42a92b55 --- /dev/null +++ b/docs/notes/vuepress-plugin/netlify-functions/使用.md @@ -0,0 +1,196 @@ +--- +title: 使用 +createTime: 2022/05/13 05:45:01 +author: pengzhanbo +permalink: /note/vuepress-plugin/netlify-functions/usage/ +--- + +## 安装 + +:::: code-group +::: code-group-item npm +``` sh +npm install @vuepress-plume/vuepress-plugin-netlify-functions +``` +::: +::: code-group-item yarn:active +``` sh +yarn add @vuepress-plume/vuepress-plugin-netlify-functions +``` +::: +::: code-group-item pnpm +``` sh +pnpm add @vuepress-plume/vuepress-plugin-netlify-functions +``` +::: +:::: + +## 在vuepress中使用 + + +### 添加插件 + +在vuepress 的配置文件中 引入并 在 `plugins` 字段中添加插件。 + +:::: code-group +::: code-group-item .vuepress/config.ts +``` ts +import { defineUserConfig } from 'vuepress' +import { netlifyFunctionsPlugin } from '@vuepress-plume/vuepress-plugin-netlify-functions' +export default defineUserConfig({ + //... + plugins: [ + netlifyFunctionsPlugin(), + ] + // ... +}) +``` +::: +::: code-group-item .vuepress/config.js +```js +const { netlifyFunctionsPlugin } = require('@vuepress-plume/vuepress-plugin-netlify-functions') +module.exports = { + //... + plugins: [ + netlifyFunctionsPlugin(), + ] + // ... +} +``` +::: +:::: + +### 编写 functions + +启动 vuepress 开发服务后, 就可以在你的 `.vuepress/functions/` 目录中,新建并开发你的 `function` + +[`functions` 开发指南](https://docs.netlify.com/functions/overview/) + + + +## 在 vuepress plugin 中使用 + +### 添加插件钩子 + +:::: code-group +::: code-group-item typescript +``` ts +import * as path from 'path' +import { App } from '@vuepress/core' +import { useNetlifyFunctionsPlugin } from '@vuepress-plume/vuepress-plugin-netlify-functions' + +const myPlugin = (): Plugin => { + return (app: App) => { + const { + // 请求前缀, 默认 /api + proxyPrefix, + preparePluginFunctions, + generatePluginFunctions + } = useNetlifyFunctionsPlugin(app, { + // 指定插件的functions目录,相关脚本在此目录中开发 + directory: path.resolve(__dirname, 'functions') + }) + return { + name: 'vuepress-plugin-myPlugin', + onPrepared:() => preparePluginFunctions(), + onGenerated: () => generatePluginFunctions(), + } + } +} +``` +::: +::: code-group-item javascript +``` js +const path = require('path') +const { useNetlifyFunctionsPlugin } = require('@vuepress-plume/vuepress-plugin-netlify-functions') + +const myPlugin = () => { + return (app) => { + const { + // 请求前缀, 默认 /api + proxyPrefix, + preparePluginFunctions, + generatePluginFunctions + } = useNetlifyFunctionsPlugin(app, { + // 指定插件的functions目录,相关脚本在此目录中开发 + directory: path.resolve(__dirname, 'functions') + }) + return { + name: 'vuepress-plugin-myPlugin', + onPrepared:() => preparePluginFunctions(), + onGenerated: () => generatePluginFunctions(), + } + } +} +``` +::: +:::: + +在你的插件开发目录,假如是以下结构: +``` sh +. +└─src # 开发目录 + ├─shared + └─node # node 端 + ├─functions # functions目录 + │ └─my_function.ts # functions脚本 + ├─plugin.ts + └─index.ts +``` + +那么,就在你的 `src/node/functions` 目录下进行 functions 开发 + +[`functions` 开发指南](https://docs.netlify.com/functions/overview/) + +如果你已经开发好了一个 `functions/my_function.ts` 的function。 + +那么你可以在 client端,通过以下方式调用: + +``` ts +async function fetchMyFunction() { + const result = await fetch('/api/my_functions') + // do something +} +``` +就像调用一个普通接口一个样简单。 + +## 环境变量 + +你可以在项目根目录中,新建一个 `.env` 文件,用于配置开发时环境变量 + +::: warning +这些环境变量仅用于开发环境时使用,部署生产时不会被加载。 + +是用于在开发环境中 代替 `Netlify Environment Variables` 。 +在生产环境中,应该使用 `Netlify Environment Variables` 设置这些环境变量。 + +如果你的 `.env` 文件中有比较私密的信息,建议将 `.env` 文件添加到 `.gitignore` 中,避免提交到 仓库中。 +::: + +:::: code-group +::: code-group-item .env +``` +YOUR_ENV_VAR='your env var' +``` +::: +::: code-group-item functions/my_function.ts +``` ts +const YOUR_ENV_VAR = process.env.YOUR_ENV_VAR +``` +::: +:::: + + +## 示例 + +如何使用本插件开发一个 提供 functions 的插件,这里提供了一个 例子: + +[plugin-page-collection](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/packages/plugin-page-collection) + +可以参考此例子进行插件开发。 + +该例子提供了以下功能: + +- 连接 `lean cloud` +- 记录页面访问次数,并上报到 `lean cloud` 数据库。 +- 查询 当前页面访问次数,并提供组件嵌入到页面中。 diff --git a/docs/notes/vuepress-plugin/netlify-functions/功能.md b/docs/notes/vuepress-plugin/netlify-functions/功能.md new file mode 100644 index 00000000..9f6ec622 --- /dev/null +++ b/docs/notes/vuepress-plugin/netlify-functions/功能.md @@ -0,0 +1,20 @@ +--- +title: 功能 +createTime: 2022/05/13 05:45:11 +author: pengzhanbo +permalink: /note/vuepress-plugin/netlify-functions/feature/ +--- + +## 功能 + +在启动 vuepress 开发环境后,`vuepress-plugin-netlify-functions` 插件会在 vuepress 开发服务中, +启动一个 `netlify-functions` 服务,然后,将通过 vuepress 开发服务代理该服务。 + +同时,启动对 `functions` 的文件监听,实现服务热更新,从而获得与 vuepress 开发服务环境一致的体验。 + +## 服务 + +考虑到通用性,本插件仅提供对于 `netlify functions` 的开发时和构建时支持,并不提供具体的 `functions`功能支持。 +一切`functions` 功能由插件使用者自定义。 + +同时,还提供了给其他插件使用本插件的钩子,这使得多个插件之间或者主题,能够共享 本插件提供的基础服务。 diff --git a/docs/notes/vuepress-theme-plume/README.md b/docs/notes/vuepress-theme-plume/README.md new file mode 100644 index 00000000..51ee7989 --- /dev/null +++ b/docs/notes/vuepress-theme-plume/README.md @@ -0,0 +1,110 @@ +--- +title: vuepress-theme-plume +createTime: 2022/04/08 08:52:12 +author: pengzhanbo +permalink: /note/vuepress-theme-plume/ +article: true +sticky: true +--- + +项目地址:[Vuepress-theme-plume](https://github.com/pengzhanbo/vuepress-theme-plume) + +![npm version](https://badge.fury.io/js/@vuepress-plume%2Fvuepress-theme-plume.svg) +![npm](https://img.shields.io/npm/dy/@vuepress-plume/vuepress-theme-plume?style=flat) + +__基于 `vuepress 2.0` 制作的 `Blog` 主题。__ + +::: warning 提示 + +基于 VuePress@v2, 仍处于 Beta 阶段。 + +这意味着功能和API尚未固定,在未来的更新中仍有概率出现破坏更改。 +::: + +- [快速开始](/note/vuepress-theme-plume/quick-start/) +- [配置](/note/vuepress-theme-plume/theme-config/) +- [编写文章](/note/vuepress-theme-plume/write-article/) + +## 功能 + +- 低配置化,安装后仅需少量的配置即可使用 +- markdown功能增强,支持 代码分组、嵌入代码demo、内容增强容器。 +- 支持 文章分类、标签、归档 +- 支持以文档形式整合同体系文章。 +- 支持搜索、评论 +- 自动生成文章永久链接 + +## 安装 + +:::: code-group +::: code-group-item yarn +``` sh +yarn add @vuepress-plume/vuepress-theme-plume +``` +::: +::: code-group-item npm +``` sh +npm i @vuepress-plume/vuepress-theme-plume +``` +::: +:::: + +## 使用 + +:::: code-group +::: code-group-item ts +``` ts +// .vuepress/config.ts +import { defineUserConfig } from 'vuepress' +import { themePlume } from '@vuepress-plume/vuepress-theme-plume' +export default defineUserConfig({ + theme: themePlume({ + // more... + }) +}) +``` +::: +::: code-group-item js +``` js +// .vuepress/config.js +import { themePlume } from '@vuepress-plume/vuepress-theme-plume' +module.exports = { + theme: themePlume({ + // more... + }) +} +``` +::: +:::: + +## 示例 + +- [鹏展博 的个人博客](https://pengzhanbo.cn) + +## 作者的话 + +### 背景 +开发本主题的原因,是在我个人学习 `vue@3`以及 `vite` 时,想做一个学习的笔记。 + +在我之前使用的 vuepress1时,发现版本挺长时间没升级了,想顺手做下升级,发现 `vuepress@2` 已经出于 beta阶段,而且还是在`vue3` 和`vite` 等的基础上做的重构,而且还是使用 `typescript` 编写的代码。 + +这刚好跟我的学习计划都撞上了,于是就开始阅读 `vuepress@2` 的相关源码,然后着手开始重构我的个人站点,并通过开发一款 主题的方式,熟悉 `vuepress2` 和 `vue3`的相关内容,简直是一举多得。 + +当然也由于本主题是 学习过程中的作品, 很多内容在一开始并没有做完备的规划,仅是一个大概的想法,然后就进行了开发,所以截止到目前阶段,项目代码还没有进行比较严格的整理,稍显散乱;部分功能也还没有完善,出于开发中,可能在使用过程中出现一些意外情况。 + +`vuepress`一直是我非常喜欢的一个静态文档站点制作工具,我用它在我工作中的不少项目中建立文档站点,以及编写自己的个人博客(虽然很懒经常没写...)。 + +### 想法 +开发这个主题,我一开始的想法是希望做一个能够尽可能的少配置化的,能够更关注于写作的主题。不需要去配置 navbar、不需要去关注链接,不需要去关注配置文件中怎么去编排文章。能够仅仅通过一些简单的约定,根据目录以及文件名称,自动生成文章列表,以及自动生成文章的默认配置。 + +以目前的进度,初期的想法基本都按照我的预期实现了,后续如果有新的想法,还会继续添加。 + +在达到一个合适的阶段后,会将重点放在代码的整理上,希望能够让本主题也称为喜欢`vuepress`并考虑自行开发一个主题或者插件的人,给到一个项目示例的参考。 + +::: tip 寄语 +欢迎各位使用本主题; + +也欢迎各位fork本主题后自行修改; + +也欢迎各位参考本主题,制作自己的主题。 +::: diff --git a/docs/notes/vuepress-theme-plume/markdown增强.md b/docs/notes/vuepress-theme-plume/markdown增强.md new file mode 100644 index 00000000..d9d455eb --- /dev/null +++ b/docs/notes/vuepress-theme-plume/markdown增强.md @@ -0,0 +1,571 @@ +--- +title: markdown增强 +createTime: 2022/04/09 06:43:32 +author: pengzhanbo +permalink: /note/vuepress-theme-plume/markdown-enhance/ +--- + +markdown 增强 由 [vuepress-plugin-md-enhance](https://vuepress-theme-hope.github.io/v2/md-enhance/zh) 提供支持。 + +## 内容容器 + +支持多种内容容器,更好的表达文章内容。 + +1. tip 提示 +2. note 注释 +3. info 信息 +4. warning 警告 +5. danger 危险 +6. details 详情 + +- 提示 + ``` md + ::: tip 提示 + 提示内容 + ::: + ``` + ::: tip 提示 + 提示内容 + ::: + +- 注释 + ``` md + ::: note 注释 + 注释内容 + ::: + ``` + ::: note 注释 + 注释内容 + ::: + +- 信息 + ``` md + ::: info 信息 + 信息内容 + ::: + ``` + ::: info 信息 + 信息内容 + ::: + +- 警告 + ``` md + ::: warning 警告 + 警告内容 + ::: + ``` + ::: warning 警告 + 警告内容 + ::: + +- 详情 + ``` md + ::: details 详情 + 详情信息 + ::: + ``` + ::: details 详情 + 详情信息 + ::: + +## 自定义对齐 + +- 左对齐 + ``` md + ::: left + 这是左对齐 + ::: + ``` + ::: left + 这是左对齐 + ::: +- 右对齐 + ``` md + ::: right + 这是右对齐 + ::: + ``` + ::: right + 这是右对齐 + ::: +- 居中 + ``` md + ::: center + 这是居中对齐 + ::: + ``` + ::: center + 这是居中对齐 + ::: + +## 任务列表 + +``` md +- [ ] todo1 +- [x] todo2 +``` +- [ ] todo1 +- [x] todo2 + +## 标记 + +``` md +将这个内容进行 ==标记== ,变成高亮。 +``` +将这个内容进行 ==标记== ,变成高亮。 + +## 代码块分组 + +你需要在 外围使用`code-group` 容器,内部使用`code-group-item` 将代码块进行包裹。 + +需要给 `code-group-item` 容器设置标题 + +如果需要给先让某个选项卡被激活,在标题后面补充`:active`后缀。 + +````md +:::: code-group + +::: code-group-item yarn +```sh +yarn version +``` +::: + +::: code-group-item npm:active +```sh +npm version +``` +::: + +:::: +```` + +:::: code-group +::: code-group-item yarn +``` sh +yarn version +``` +::: +::: code-group-item npm:active +``` sh +npm version +``` +::: +:::: + +## 代码演示 + +```` md +::: demo [类型] 可选的标题文字 + +```html + + + +``` + +```json +// json block 作为插件配置存放处 +{ + // 放置你的配置 (可选的) +} +``` + +::: +```` +::: tip 提示 +JSON 块是可选的,可用的配置详见[配置](https://vuepress-theme-hope.github.io/v2/md-enhance/zh/config.html) +::: + +插件支持三种类型 + +- normal(默认) +- vue +- react + +### 可用的语言 + +你可以在演示块中使用不同语言。 + +当你设置一些不能在浏览器上直接运行的语言时,由于插件无法解析它们,因此网页演示将被禁用。插件只显示代码。同时提供一个 "在 CodePen 中打开" 按钮允许用户直接在 CodePen 打开并浏览代码。 + +可用的 HTML 语言: + +- `"html"` (默认) +- `"slim"` +- `"haml"` +- `"markdown"` + +可用的 JS 语言: + +- `"javascript"` (default) +- `"coffeescript"` +- `"babel"` +- `"livescript"` +- `"typescript"` + +> 你也可以在代码块中使用 `js`, `ts`, `coffee` 和 `ls。` + +可用的 CSS 语言: + +- `"css"` (default) +- `"less"` +- `"scss"` +- `"sass"` +- `"stylus"` + +### 不支持的语言 + +::: demo 一个使用浏览器不支持解析语言 Demo + +```md +# 标题 + +十分强大 +``` + +```ts +const message: string = "VuePress Theme Hope"; + +document.querySelector("h1").innerHTML = message; +``` + +```scss +h1 { + font-style: italic; + + + p { + color: red; + } +} +``` + +::: + +:::: details 代码 +```` md +::: demo 一个使用浏览器不支持解析语言 Demo + +```md +# 标题 + +十分强大 +``` + +```ts +const message: string = "VuePress Theme Hope"; + +document.querySelector("h1").innerHTML = message; +``` + +```scss +h1 { + font-style: italic; + + + p { + color: red; + } +} +``` + +::: +```` +:::: + + +### 普通代码演示 +格式: +```` md +::: demo 可选的标题文字 + +```html + +``` + +```js +// js code +``` + +```css +/* css code */ +``` + +```json +// 配置 (可选) +{ + "jsLib": [ + ... + ], + "cssLib":[ + ... + ] +} +``` + +::: +```` +::: warning 注意事项 +我们使用 `"ShadowDOM"` 进行样式隔离,并已经将 `document` 替换为了 `shadowRoot` 对象。如果需要访问页面的 `document,请访问` `window.document`。 +::: + +#### 例子 + +::: demo Demo 演示 + +```html +

Hello Word!

+

非常强大!

+``` + +```js +document.querySelector("#very").addEventListener("click", () => { + alert("非常强大"); +}); +``` + +```css +span { + color: red; +} +``` + +::: + +:::: details 代码 +```` md +::: demo Demo 演示 + +```html +

Hello Word!

+

非常强大!

+``` + +```js +document.querySelector("#very").addEventListener("click", () => { + alert("非常强大"); +}); +``` + +```css +span { + color: red; +} +``` + +::: +```` +:::: + +### Vue 代码演示 + +#### 格式 +```` md +::: demo [vue] 可选的标题文字 + +```vue + + + + +``` + +```json +// 配置 (可选) +``` + +::: +```` + +::: warning 注意事项 +- 你只能使用 `Vue3`。 +- 必须将组件通过 `export default` 默认导出 +- 我们使用 `"ShadowDOM"` 进行样式隔离,并已经将 `document` 替换为了 `shadowRoot` 对象。如果需要访问页面的 `document`,请访问 `window.document`。 +::: + +#### 演示 + +::: demo [vue] 一个 Vue Composition 演示 + +```vue + + + +``` + +::: + +:::: details 代码 +```` md +::: demo [vue] 一个 Vue Composition 演示 + +```vue + + + +``` + +::: +```` +:::: + +### React 代码演示 + +#### 格式 + +```` md +::: demo [react] 可选的标题文字 + +```js +// 放置脚本,并通过 `export default` 导出你的 react 组件 +``` + +```css +/* 你的 css 内容 */ +``` + +```json +// 配置 (可选) +``` + +::: +```` + +::: warning 注意事项 +- 使用 React 的时候,为了解析 JSX 必须引入 Babel,此过程由插件自动完成。 +- 必须将组件通过 `export default` 默认导出 +- 我们使用 `"ShadowDOM"` 进行样式隔离,并已经将 `document` 替换为了 `shadowRoot` 对象。如果需要访问页面的 `document`,请访问 `window.document`。 +::: + +#### 演示 + +::: demo [react] 一个函数式 React Demo + +```js +const { useState } = React; + +export default () => { + const [message, setMessage] = useState(" 强大"); + + const handler = () => { + setMessage(`十分${message}`); + }; + + return ( +
+ Hello Word ! + + {message} + +
+ ); +}; +``` + +```css +.box #powerful { + color: blue; +} +``` + +::: + +:::: details 代码 +```` md +::: demo [react] 一个函数式 React Demo + +```js +const { useState } = React; + +export default () => { + const [message, setMessage] = useState(" 强大"); + + const handler = () => { + setMessage(`十分${message}`); + }; + + return ( +
+ Hello Word ! + + {message} + +
+ ); +}; +``` + +```css +.box #powerful { + color: blue; +} +``` + +::: +```` +:::: + +## 其他支持 + +更多支持请参考 [主题插件配置](/note/vuepress-theme-plume/plugins-config/#markdownenhance) diff --git a/docs/notes/vuepress-theme-plume/notes配置.md b/docs/notes/vuepress-theme-plume/notes配置.md new file mode 100644 index 00000000..7a9082df --- /dev/null +++ b/docs/notes/vuepress-theme-plume/notes配置.md @@ -0,0 +1,167 @@ +--- +title: notes配置 +createTime: 2022/04/09 02:48:41 +author: pengzhanbo +permalink: /note/vuepress-theme-plume/notes-config/ +--- + +`notes` 功能,是为了在本主题满足了 Blog的基本功能后,期望能够 以 `note` 或者 `book` 的形式聚合文章而形成的,形式上类似于 `vuepress` 默认主题的功能。同时也减少了配置的复杂度。 + +## 配置 +所有主题内部使用的插件, 均在 `notes` 字段中进行配置。 +``` js {3-5} +module.exports = { + themeConfig: { + notes: { + // this + } + } +} +``` + +## 配置字段 + +### dir + +- 类型: `string` +- 默认值: `'_notes'` +- 详情:所有notes存放的目录,该目录相对于`sourceDir`。 + + 示例 + ``` + ├─ {sourceDir} + │ ├─ _notes + │ │ └─ typescript学习笔记 + │ └─ README.md + ``` + +### link + +- 类型: `string` +- 默认值: `'/note/'` +- 详情: 作为notes内的文章链接的前缀。自定义是请以 `'/'` 开头 + +### notes + +- 类型: `PlumeThemeNotesItem[]` +- 默认值: `[]` +- 详情: note数组,配置多个 note + +#### `PlumeThemeNotesItem` +``` ts +interface PlumeThemeNotesItem { + /** + * note 标题 + */ + text: string + /* + * note 链接,相对于 前面配置的 link。 + * 如 /typescript-learn/ 映射到访问链接则为 /note//typescript-learn/ + */ + link: string + /* + * note 所在的目录,相对于 前面配置的 dir + * 如 typescript 则实际路径为 {sourceDir}/_notes/typescript + */ + dir: string + /* + * 当前 note 的sidebar配置 + */ + sidebar?: PlumeThemeSidebarConfigOptions | 'auto' +} +type PlumeThemeSidebarConfigOptions = (PlumeThemeNotesConfigItem | string)[] + +interface PlumeThemeNotesConfigItem { + text: string + link?: string + children: PlumeThemeNotesConfigItem[] +} +``` +### notes\[index\].sidebar + +这个字段是用于配置当前 note 的 sidebar 左侧导航栏 + +- 类型: `(PlumeThemeNotesConfigItem | string)[]` +- 详情: + - 如果子元素为字符串时,可以是相对于 dir目录的md文件路径,可以省略`.md`后缀,也可以是生成的文章,`frontmatter`中的 + `permalink`的链接, 如果为空,则表示当前文件夹下的 `README.md`文件 + - 如果子元素是`PlumeThemeNotesConfigItem`, 其中 `text` 表示 sidebar显示的文案, + `link` 等价于 上一条 string 的规则。 + `children` 可以继续嵌套`(PlumeThemeNotesConfigItem | string)` + +## 示例 + +在`_notes` 文件夹下用如下文件结构 +``` +_notes +└── vuepress-theme-plume + ├── README.md + ├── note配置.md + ├── 主题配置.md + ├── 快速开始.md + ├── 编写文章.md + ├── 页面配置.md + └── 主题插件配置.md +``` + +则可以进行如下配置: + +:::: code-group +::: code-group-item config.ts +``` ts +import { defineUserConfig } from 'vuepress' +import type {PlumeThemeOptions } from '@vuepress-plume/vuepress-theme-plume' +import notes from './notes.ts' +export default defineUserConfig({ + themeConfig: { + notes: { + dir: '_notes', + link: '/note/', + notes, + } + } +}) +``` +::: +::: code-group-item notes.ts +``` ts +export default [ + { + text: 'VuePress-theme-plume', + dir: 'vuepress-theme-plume', + link: '/vuepress-theme-plume', + sidebar: [ + '', + { + text: '指南', + children: [ + '快速开始', + '编写文章', + ] + }, + { + text: '配置', + children: [ + { + text: '主题配置', + link: '主题配置', + children: [ + '主题插件配置', + 'notes配置', + ] + }, + '页面配置', + ] + }, + { + text: '功能', + children: [] + } + ] + } +] +``` +::: +:::: + +其效果 即为 本文档 左侧 sidebar 展示效果。 diff --git a/docs/notes/vuepress-theme-plume/主题插件配置.md b/docs/notes/vuepress-theme-plume/主题插件配置.md new file mode 100644 index 00000000..7eb84cdd --- /dev/null +++ b/docs/notes/vuepress-theme-plume/主题插件配置.md @@ -0,0 +1,164 @@ +--- +title: 主题插件配置 +createTime: 2022/04/09 02:48:30 +author: pengzhanbo +permalink: /note/vuepress-theme-plume/plugins-config/ +--- + +主题内置的使用的插件,扩展了主题的众多功能,你可以在这个 字段中, 实现对内部使用的各个插件的自定义配置。 + +## 配置 +所有主题内部使用的插件, 均在 `themePlugins` 字段中进行配置。 +``` js {4-6} +import { themePlume } from '@vuepress-plume/vuepress-theme-plume' +module.exports = { + theme: themePlume({ + themePlugins: { + // this + } + }) +} +``` + +## 配置字段 + +### caniuse + +关联插件: [@vuepress-plume/vuepress-plugin-caniuse](https://www.npmjs.com/package/@vuepress-plume/vuepress-plugin-caniuse) + +- 类型: `false | CanIUsePluginOptions` +- 默认值: `{ mode: 'embed' }` +- 详情:该插件支持在你的文章中嵌入 [can I use](https://caniuse.com/) 特性支持图表。 + + 设置为 `false` 表示不启动该插件。 + - `caniuse.mode`: 图表嵌入模式, `embed`表示嵌入可交互式的图表, `image` 嵌入动态图片。 +- 配置示例: + ``` js + module.exports = { + theme: themePlume({ + themePlugins: { + caniuse: { + mode: 'embed' + }, + }, + }), + } + ``` + +### externalLinkIcon + +关联插件: [@vuepress/plugin-external-link-icon](https://v2.vuepress.vuejs.org/zh/reference/plugin/external-link-icon.html) + +- 类型: `false | string` +- 默认值: `''` +- 详情: 该插件会为你 Markdown 内容中的外部链接添加一个图标,即 + + 一般来说你不需要对它进行配置 + +### search + +网站内容搜索插件 + +关联插件: [@vuepress/plugin-search](https://v2.vuepress.vuejs.org/zh/reference/plugin/search.html) + +详细介绍与配置,请查阅 [官方文档](https://v2.vuepress.vuejs.org/zh/reference/plugin/search.html) + +- 默认配置: `''` + +### docsearch + +使用 [Algolia DocSearch](https://docsearch.algolia.com/) 提供支持的网站内容搜索插件 + +关联插件:[@vuepress/plugin-docsearch](https://v2.vuepress.vuejs.org/zh/reference/plugin/docsearch.html) + +详细介绍与配置,请查阅 [官方文档](https://v2.vuepress.vuejs.org/zh/reference/plugin/docsearch.html) + +- 默认配置: `''` + +::: info 提示 +请勿 同时配置 `search` 和 `docsearch` ,两者的功能是类似的,且同时配置仅会使用优先使用 `search`。 +::: + +### prismjs + +代码块语法高亮插件 + +关联插件: [@vuepress/plugin-prismjs](https://v2.vuepress.vuejs.org/zh/reference/plugin/prismjs.html) + +详细介绍与配置,请查阅 [官方文档](https://v2.vuepress.vuejs.org/zh/reference/plugin/prismjs.html) + +### nprogress + +页面切换时展示进度条。 + +关联插件: [@vuepress/plugin-nprogress](https://v2.vuepress.vuejs.org/zh/reference/plugin/nprogress.html) + +详细介绍与配置,请查阅 [官方文档](https://v2.vuepress.vuejs.org/zh/reference/plugin/nprogress.html) + +### copyCode + +代码拷贝插件 + +支持在代码块中进行代码复制 + +关联插件:[vuepress-plugin-copy-code2](https://vuepress-theme-hope.github.io/v2/copy-code/) + +详细介绍与配置,请查阅[官方文档](https://vuepress-theme-hope.github.io/v2/copy-code/) + +- 默认配置: + ``` js + module.exports = { + theme: themePlume({ + themePlugins: { + copyCode: { + selector: '.page-content div[class*="language-"] pre', + locales: { + '/': { + copy: '复制成功', + hint: '复制代码', + }, + }, + }, + }, + }), + } + ``` + +### markdownEnhance + +`Markdown` 功能扩展插件 + +关联插件:[vuepress-plugin-md-enhance](https://vuepress-theme-hope.github.io/v2/md-enhance/zh/) + +扩展支持:自定义容器、代码块分组、上下角标、自定义对齐、脚注、标记、任务列表、chart、流程图、代码演示 等功能。 + +相关介绍及配置,请查阅 [官方文档](https://vuepress-theme-hope.github.io/v2/md-enhance/zh/) + +- 默认配置: + ``` js + module.exports = { + theme: themePlume({ + themePlugins: { + markdownEnhance: { + container: true, // 自定义容器 info note tip warning danger details + codegroup: true, // 代码块分组 + align: true, // 自定义对齐 + mark: true, // 标记 + tasklist: true, // 任务列表 + demo: true, // 代码演示 + } + } + }) + } + ``` +### comment + +评论插件 + +关联插件: [vuepress-plugin-comment2](https://vuepress-theme-hope.github.io/v2/comment/zh/) + +支持使用 `giscus`、`twikoo`、`waline` 启用评论功能。 + +相关介绍及配置,请查阅 [官方文档](https://vuepress-theme-hope.github.io/v2/comment/zh/) + +- 默认配置:`''` diff --git a/docs/notes/vuepress-theme-plume/主题配置.md b/docs/notes/vuepress-theme-plume/主题配置.md new file mode 100644 index 00000000..705f79cf --- /dev/null +++ b/docs/notes/vuepress-theme-plume/主题配置.md @@ -0,0 +1,342 @@ +--- +title: 主题配置 +createTime: 2022/04/09 12:18:12 +author: pengzhanbo +permalink: /note/vuepress-theme-plume/theme-config/ +--- + +虽然本主题希望尽可能的少写配置,但还是有些配置是不可省略的,而且也是为了保证一定程度的可定制性。 + +## 配置文件 + +`Vuepress` 默认的配置文件是`.vuepress/config.ts`,可能你的项目配置如下, + +新建`.vuepress/config.ts`文件进行配置: +``` +├─ {sourceDir} +│ ├─ .vuepress +│ │ └─ config.js +│ └─ README.md +├─ .gitignore +└─ package.json +``` + +`VuePress` 支持的配置,请查阅 [官方文档](https://v2.vuepress.vuejs.org/zh/guide/configuration.html) + +在 `Vuepress@v2`中对于主题的配置,引入主题函数,在函数中进行配置 +:::: code-group +::: code-group-item ts +``` ts {3,6-8} +// .vuepress/config.ts +import { defineUserConfig } from 'vuepress' +import { themePlume } from '@vuepress-plume/vuepress-theme-plume' +export default defineUserConfig({ + theme: themePlume({ + // more... + }) +}) +``` +::: +::: code-group-item js +``` js {4-6} +// .vuepress/config.js +import { themePlume } from '@vuepress-plume/vuepress-theme-plume' +module.exports = { + theme: themePlume({ + // more... + }) +} +``` +::: +:::: + + +## 配置 + +### home + +- 类型: `false | NavLink` +- 默认值: `{ text: '首页', link: '/' }` +- 详情: + 首页的路径, 它将被用于: + - 导航栏中 logo的链接; + - 404页面的 *返回首页* 的链接; + - navbar 中 首页的链接。 + +### logo + +- 类型: `false | string` +- 默认值: `false` +- 详情: 导航栏中的logo。 + +### logoDark + +- 类型 `false | string` +- 默认值: `false` +- 详情: Dark模式下,导航栏中的logo。 + +### darkMode + +- 类型: `boolean` +- 默认值: `true` +- 详情: 是否启用 dark模式 + +### avatar + +- 类型: `PlumeThemeAvatar` +- 默认值: `{}` +- 详情:配置站点博主的个人信息 + - `avatar.url`: 头像地址,用于右侧博主信息展示 + - `avatar.name`: 名称, 用于右侧博主信息展示 + - `avatar.description`: 座右铭,个人描述,用于右侧博主信息展示 +- 示例: + ``` ts + export default { + theme: themePlume({ + avatar: { + url: '/avatar.jpg', + name: '张三', + description: '此处无银三百两,隔壁王二不曾偷', + } + }) + } + ``` + +### social + +- 类型: `false | PlumeThemeSocialOption` +- 默认值: `false` +- 详情: 个人社交信息配置。用于右侧博主信息展示,展示为社交图标。 + - `social.email`: 邮箱 + - `social.github`: 个人github地址 + - `social.QQ`: QQ账号 + - `social.weiBo`: 个人微博地址 + - `social.zhiHu`: 个人知乎地址 + - `social.facebook`: facebook地址 + - `social.twitter`: twitter 地址 + - `social.linkedin`: 领英 linkedin 地址 +- 示例: + ``` ts + export default { + theme: themePlume({ + social: { + email: 'me@email.com', + github: 'https://github.com/zhangsan', + QQ: '123456789', + } + }) + } + ``` + +### article + +- 类型: `string` +- 默认值: `/article/` +- 详情: 文章链接前缀 + +### tag + +- 类型: `NavLink` +- 默认值: `{ text: '标签', link: '/tag/' }` +- 详情: 标签页配置,与 navbar 配置 + +### category + +- 类型: `NavLink` +- 默认值: `{ text: '分类', link: '/category/ }` +- 详情: 分类页配置,与 navbar 配置 + +### archive + +- 类型: `NavLink` +- 默认值: `{ text: '归档', link: '/timeline/' }` +- 详情: 归档页配置,与 navbar 配置 + +### navbar + +- 类型: `(NavbarItem | NavbarGroup | string)[]` +- 默认值: `[]` +- 详情: 导航栏配置。 + + 为了配置导航栏元素,你可以将其设置为 导航栏数组 ,其中的每个元素是 `NavbarItem` 对象、 `NavbarGroup` 对象、或者字符串: + - `NavbarItem` 对象应该有一个 text 字段和一个 link 字段,还有一个可选的 `activeMatch` 字段。 + - `NavbarGroup` 对象应该有一个 `text` 字段和一个 `children` 字段。 `children` 字段同样是一个 导航栏数组 。 + - 字符串应为目标页面文件的路径。它将会被转换为 `NavbarItem` 对象,将页面标题作为 `text` ,将页面路由路径作为 `link` 。 +- 示例1: + ``` js + module.exports = { + theme: themePlume({ + navbar: [ + // NavbarItem + { + text: 'Foo', + link: '/foo/', + }, + // NavbarGroup + { + text: 'Group', + children: ['/group/foo.md', '/group/bar.md'], + }, + // 字符串 - 页面文件路径 + '/bar/README.md', + ], + }), + } + ``` +- 示例2: + ``` js + module.exports = { + theme: themePlume({ + navbar: [ + // 嵌套 Group - 最大深度为 2 + { + text: 'Group', + children: [ + { + text: 'SubGroup', + children: ['/group/sub/foo.md', '/group/sub/bar.md'], + }, + ], + }, + // 控制元素何时被激活 + { + text: 'Group 2', + children: [ + { + text: 'Always active', + link: '/', + // 该元素将一直处于激活状态 + activeMatch: '/', + }, + { + text: 'Active on /foo/', + link: '/not-foo/', + // 该元素在当前路由路径是 /foo/ 开头时激活 + // 支持正则表达式 + activeMatch: '^/foo/', + }, + ], + }, + ], + }), + } + ``` + +### footer + +- 类型: `false | { content: string; copyright: string }` +- 默认值: `false` +- 详情:页脚配置。 + +### notes + +- 类型: `false | PlumeThemeNotesOptions` +- 默认值: `{ link: '/note', dir: 'notes', notes: [] }` +- 详情: 笔记配置, 笔记中的文章默认不会出现在首页文章列表 + + 你可以将配置的notes 配置到 navbar中,以便浏览查看 + +详细配置请查看 [此文档](/note/vuepress-theme-plume/notes-config/) + +### themePlugins + +- 类型:`PlumeThemePluginOptions` +- 默认值: `{}` +- 详情: 对主题内使用的插件进行自定义配置。 + + 主题使用的插件默认已进行了配置,默认情况下不需要进行修改,如果需要使用到细致的定制化,请查阅 + [此文档](/note/vuepress-theme-plume/plugins-config/) + + +## 完整示例 + +:::: code-group +::: code-group-item ts +``` ts +import { defineUserConfig } from 'vuepress' +import { themePlume } from '@vuepress-plume/vuepress-theme-plume' + +export default defineUserConfig({ + lang: 'zh-CN', + locales: { + '/': { + lang: 'zh-CN', + title: 'Theme Plume', + description: 'The Theme for VuePress 2', + }, + }, + dest: 'docs', + head: [ + ['link', { rel: 'icon', href: '/g.gif' }], + ['meta', { 'http-equiv': 'X-UA-Compatible', content: 'id=edg' }], + ], + theme: themePlume({ + logo: '/g.gif', + darkMode: true, + avatar: { + name: 'theme plume', + url: '/images/blogger.png', + description: 'good good study, day day up !' + }, + social: { + email: 'me@email.com', + github: 'https://github.com/me', + QQ: '123456789', + }, + navbar: [{ text: 'Theme-Plume', link: '/note/vuepress-theme-plume' }], + notes: { + dir: 'notes', + link: '/note', + }, + footer: { + copyright: 'Copyright © 2022-present pengzhanbo', + content: '', + }, + }), +}) +``` +::: +::: code-group-item js +``` js +import { themePlume } from '@vuepress-plume/vuepress-theme-plume' +module.exports = { + lang: 'zh-CN', + locales: { + '/': { + lang: 'zh-CN', + title: 'Theme Plume', + description: 'The Theme for VuePress 2', + }, + }, + dest: 'docs', + head: [ + ['link', { rel: 'icon', href: '/g.gif' }], + ['meta', { 'http-equiv': 'X-UA-Compatible', content: 'id=edg' }], + ], + theme: themePlume({ + logo: '/g.gif', + darkMode: true, + avatar: { + name: 'theme plume', + url: '/images/blogger.jpg', + description: 'good good study, day day up !' + }, + social: { + email: 'me@email.com', + github: 'https://github.com/me', + QQ: '123456789', + }, + navbar: [{ text: 'Theme-Plume', link: '/note/vuepress-theme-plume' }], + notes: { + dir: 'notes', + link: '/note', + }, + footer: { + copyright: 'Copyright © 2022-present pengzhanbo', + content: '', + }, + }), +} +``` +::: +:::: diff --git a/docs/notes/vuepress-theme-plume/基础功能.md b/docs/notes/vuepress-theme-plume/基础功能.md new file mode 100644 index 00000000..208c1201 --- /dev/null +++ b/docs/notes/vuepress-theme-plume/基础功能.md @@ -0,0 +1,78 @@ +--- +title: 基础功能 +createTime: 2022/04/09 06:43:20 +author: pengzhanbo +permalink: /note/vuepress-theme-plume/basis-power/ +--- + +## 首页 + +### 文章列表 + +- 自动生成 文章列表,并支持文章分页功能。 +- 文章列表子项 支持显示 + - 标题 + - 作者 + - 分类 + - 标签 + - 创建时间 + - 文章内容截取 + +### 右侧博主信息展示 +- 头像 +- 名称 +- 个人简介/座右铭 +- 个人社交账号信息 + - Email + - github + - 微博 + - 知乎 + - QQ + - facebook + - twitter + - linkedin + +## 分类页 + +根据 `${sourceDir}` 中的 文章所在目录,自动生成文章分类。 + +并生成 分类页,可以根据分类查看文章。 + +## 标签页 + +支持配置 文章标签 + +并生成 标签页, 可以根据 标签筛选文章。 + +## 归档页 + +根据文章创建时间,生成 文章归档页面。 + +## 站内搜索 + +支持站内搜索相关文章。 + +## 深色模式 + +支持深色模式 + +## 主题定制 + +支持自定义样式。 + +该功能由 [@vuepress/plugin-palette](https://v2.vuepress.vuejs.org/zh/reference/plugin/palette.html) 提供支持。 + +请查阅 [官方文档](https://v2.vuepress.vuejs.org/zh/reference/plugin/palette.html) + +``` scss +:root { + // 主题颜色 + // brand color + --c-brand: #0095d9; + --c-brand-light: #2ca9e1; +} +``` + +## 文章评论 + +支持文章评论。 diff --git a/docs/notes/vuepress-theme-plume/快速开始.md b/docs/notes/vuepress-theme-plume/快速开始.md new file mode 100644 index 00000000..6b9fc2fa --- /dev/null +++ b/docs/notes/vuepress-theme-plume/快速开始.md @@ -0,0 +1,140 @@ +--- +title: 快速开始 +createTime: 2022/04/08 09:43:20 +author: pengzhanbo +permalink: /note/vuepress-theme-plume/quick-start/ +--- + +## 依赖环境 + +- [Node.js v12+](https://nodejs.org/en/) +- [Yarn v1 classic](https://classic.yarnpkg.com/en/) + +::: tip 提示 +- 使用 [pnpm](https://pnpm.io/zh/) 时,你需要在 `.npmrc` 文件中设置 `shamefully-hoist=true` 。 +- 使用 [Yarn 2](https://yarnpkg.com/) 时,你需要在 `.yarnrc.yml` 文件中设置 `nodeLinker: 'node-modules'` 。 +::: + +## 安装 +使用本主题,你需要首先新建一个项目,并安装`vuepress@next`以及本主题 + +- __步骤1:__ 创建一个新文件夹,并进入目录 + ``` sh + mkdir my-blog + cd my-blog + ``` + +- __步骤2:__ 初始化项目 + :::: code-group + ::: code-group-item yarn + ``` sh + git init + yarn init + ``` + ::: + ::: code-group-item npm + ``` sh + git init + npm init + ``` + ::: + :::: + +- __步骤3:__ 安装相关依赖 + + 安装 `vuepress@next`和`@vuepress-plume/vuepress-theme-plume`作为本地依赖。 + + 如果你是希望将已有的项目进行升级,请从 `步骤5` 开始 + :::: code-group + ::: code-group-item yarn + ``` sh + yarn add -D vuepress@next @vuepress-plume/vuepress-theme-plume + ``` + ::: + ::: code-group-item npm + ``` sh + npm i -D vuepress@next @vuepress-plume/vuepress-theme-plume + ``` + ::: + :::: + +- __步骤4:__ 在`package.json`中添加`script` + + 比如,你希望项目中的`src`目录作为你的文章的写作目录: + ``` json + { + "scripts": { + "dev": "vuepress dev src", + "build": "vuepress build src" + } + } + ``` +- __步骤5:__ 将默认的临时目录和缓存目录添加到`.gitignore` 文件中 + :::: code-group + ::: code-group-item sh + ``` sh + echo 'node_modules' >> .gitignore + echo '.temp' >> .gitignore + echo '.cache' >> .gitignore + ``` + ::: + ::: code-group-item .gitignore + ``` text + node_modules + .temp + .cache + ``` + :::: + +- __步骤6:__ 在 `.vuepress/config.ts` 中配置主题 + :::: code-group + ::: code-group-item ts + ``` ts {3,5-7} + // .vuepress/config.ts + import { defineUserConfig } from 'vuepress' + import { themePlume } from '@vuepress-plume/vuepress-theme-plume' + export default defineUserConfig({ + theme: themePlume({ + // theme config + }) + }) + ``` + ::: + ::: code-group-item js + ``` js {2,4-6} + // .vuepress/config.js + import { themePlume } from '@vuepress-plume/vuepress-theme-plume' + module.exports = { + theme: themePlume({ + // theme config + }) + } + ``` + ::: + :::: + +- __步骤7:__ 在`src` 目录下新建`README.md`文件 + + 声明首页配置。 + ``` md + --- + home: true + --- + ``` +- __步骤8:__ 在本地服务器启动你的文档站点 + :::: code-group + ::: code-group-item yarn + ``` sh + yarn dev + ``` + ::: + ::: code-group-item npm + ``` sh + npm run dev + ``` + ::: + :::: + + Vuepress 会在 [http://localhost:8080](http://localhost:8080) 。启动一个热重载的开发服务器。当你修改你的 Markdown 文件时,浏览器中的内容也会自动更新。 + + 现在,你应该已经有了一个简单可用的 VuePress Blog 网站。接下来,了解一下 [编写 Blog 文章](/note/vuepress-theme-plume/write-article/) 和 [主题配置](/note/vuepress-theme-plume/theme-config/) 的相关内容。 diff --git a/docs/notes/vuepress-theme-plume/编写文章.md b/docs/notes/vuepress-theme-plume/编写文章.md new file mode 100644 index 00000000..c5a1df40 --- /dev/null +++ b/docs/notes/vuepress-theme-plume/编写文章.md @@ -0,0 +1,55 @@ +--- +title: 编写文章 +createTime: 2022/04/09 12:13:56 +author: pengzhanbo +permalink: /note/vuepress-theme-plume/write-article/ +--- + +::: info 注释 +- 以下内容中,以`sourceDir` 表示 项目中用于保存 `Markdown`文件的目录。 + + 如 `package.json`的`scripts` 中 `vuepress dev src` 声明的`src`目录 +::: + +## 约定 + +使用本主题编写文章是一件很轻松的事情,你可以在 `sourceDir`目录中按照你的个人命名喜好新建任意名字的`Markdown`文件, +主题将会自动帮你生成一个文章永久链接,并保存在文章的配置中,以便随时修改。 + +但对于 `sourceDir` 中的文件夹命名,主题有一套简单的约定。 + +- 文件夹的名称将作为 `category` 即 __分类__。将会映射到 `navbar`作为分类的子项。 +- 允许多级目录,子级目录将作为父目录对应的分类的子项。 +- 如果目录名称 在 [主题配置 notes](/note/vuepress-theme-plume/theme-config/#notes) 中声明用于 notes 文章管理,则默认不作为 分类目录。 + +### 文件夹命名约定 + +由于文件夹名称将作为分类名称,且不在主题配置中进行排序配置,对于有排序需要的场景,使用以下规则进行命名 +``` ts +const dir = /\d+\.[^]+/ // 即 数字 + dot + 分类名称 +``` +数字将作为 __排序__ 的依据。 如果不带数字,则以默认的规则进行排序。 + +__example:__ +``` + .{sourceDir} + - 1.前端 + - 1.html + - 2.css + - 3.javascript + - 2.后端 + - 运维 +``` + +## 博客首页 +在 `sourceDir` 目录新建`README.md` 文件,并写入以下内容即可。 +``` md +--- +home: true +--- +``` +主题会解析该文件,并插入 文章列表,以及相关内容。 + +## 文章写作 + +你可以使用 `markdown` 语法开始编写你自己的文章了,关于 markdown 扩展的功能支持,请查看 [这个文档](/note/vuepress-theme-plume/markdown-enhance/)。 diff --git a/docs/notes/vuepress-theme-plume/页面配置.md b/docs/notes/vuepress-theme-plume/页面配置.md new file mode 100644 index 00000000..2ee0c7b8 --- /dev/null +++ b/docs/notes/vuepress-theme-plume/页面配置.md @@ -0,0 +1,136 @@ +--- +title: 页面配置 +createTime: 2022/04/09 01:24:17 +author: pengzhanbo +permalink: /note/vuepress-theme-plume/page-config/ +--- + +## 说明 + +页面配置是为了能够以更细小的颗粒度控制单个页面的行为。 + +在本主题中,当你启动本地服务器后,主题会在你新建 `markdown`文件时,自动在文件头部插入基本的配置,你可以随时修改它。 + +`markdown`中的配置形式,如下所示: +``` md +--- +title: 标题 +createTime: 2022/04/09 01:24:17 +author: You +permalink: /note/vuepress-theme-plume/page-config/ +tags: + - vuepress +--- +``` +配置内容是以 `YAML` 的格式进行书写的。 + +## 配置字段 + +### title + +- 类型: `string` +- 默认值: `''` +- 详情: + + 文章标题,启动本地服务器时,如果该字段为空,会根据当前文件名称自动生成。 + +### createTime + +- 类型: `DateString` 格式 `yyyy/MM/dd hh:mm:ss` +- 默认值: `''` +- 详情: + + 文章创建时间,启动本地服务器时,如果该字段为空,会根据当前文件的创建时间自动生成 + +### author + +- 类型: `string` +- 默认值: `''` +- 详情: + + 文章作者,启动本地服务器时,如果该字段为空,会根据当前项目`package.json`中的`author`字段生成 + +### permalink + +- 类型: `string` +- 默认值: `''` +- 详情: + + 文章永久链接,启动本地服务器时,如果该字段为空,会根据默认规则生成。 + + 在本主题中通过 `nanoid` 生成文章唯一链接。 + +### tags + +- 类型: `string[]` +- 默认值: `[]` +- 详情: + + 文章标签,可配置多个 +- 示例: + ``` md + --- + tags: + - html + - javascript + --- + ``` +### sticky + +- 类型: `boolean | number` +- 默认值: `false` +- 详情: + + 是否置顶当前文章。 + + 当同时配置多篇文章置顶,如果值为number,则number越大的文章越靠前。 + +### article + +- 类型: `boolean` +- 默认值: `true`, 在`notes` 中的文章,默认值为 `false` +- 详情: + + 是否将文章收录到 首页 文章列表 + +## 首页配置字段 + +### home + +- 类型: `boolean` +- 默认值: `true` +- 详情: + + 标记当前 md文件为博客首页,仅在 `{sourceDir}/README.md` 中配置即可 + +### banner + +- 类型: `string` +- 默认值: `''` +- 详情 + + 配置首页首屏大图 + + +### mobileBanner + +- 类型: `string` +- 默认值:`''` +- 详情 + + 配置首页首屏,在移动端设备中使用的大图 +### motto + +- 类型: `string` +- 默认值: `''` +- 详情 + + 座右铭,显示在首屏大图上 + +``` md +--- +home: true +banner: /images/big-banner.jpg +motto: 世间的美好总是不期而遇,恬静而自然。 +--- +``` diff --git a/docs/notes/面试题/CSS/盒模型.md b/docs/notes/面试题/CSS/盒模型.md deleted file mode 100644 index 5fb1951b..00000000 --- a/docs/notes/面试题/CSS/盒模型.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: 盒模型 -createTime: 2022/04/12 11:27:38 -author: pengzhanbo -permalink: /note/interview-question/sfnusib9/ ---- - -`CSS盒模型` 问题是 面试中比较常见的基础题型。提问的方式,可能包括以下: - -- 请简述 CSS 盒模型 -- 什么是 标准模式和 怪异模式 ? - - diff --git a/docs/notes/面试题/README.md b/docs/notes/面试题/README.md deleted file mode 100644 index 7f25285c..00000000 --- a/docs/notes/面试题/README.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: 面试题 -createTime: 2022/04/12 10:16:26 -author: pengzhanbo -permalink: /note/interview-question/ ---- - -### 说明 - -本笔记主要用于整理、记录,从个人角度尝试回答 可能会遇到的、跟其他人讨论过的 面试题目。 - -但本笔记 所收集的面试题, 主要是在 前端的范畴中,不涉及其他。 - -如果你准备找工作,想刷刷面试题,可以 以此作为参考, -但请不要作为标准答案,因为这些仅仅是我个人的理解, -并不一定百分百正确。 - -::: tip -如果这篇笔记对你有帮助,你有遇到不错的面试题,希望可以在本笔记的评论区提交你遇到的面试题与我分享,我不胜感激! - -如果你发现本笔记中有哪些错误,欢迎指出,我将虚心受教! -::: - -1 - -1 - -1 - - -1 - - -11 - - -1 - -1 - - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 diff --git a/packages/plugin-caniuse/src/client/clientAppEnhance.ts b/packages/plugin-caniuse/src/client/clientAppEnhance.ts index 0d740f36..2d1e37bf 100644 --- a/packages/plugin-caniuse/src/client/clientAppEnhance.ts +++ b/packages/plugin-caniuse/src/client/clientAppEnhance.ts @@ -10,7 +10,8 @@ const mode = __CAN_I_USE_INJECT_MODE__ export default defineClientAppEnhance(({ router }) => { if (__VUEPRESS_SSR__) return - router.afterEach((to) => { + router.afterEach((to, from) => { + if (to.path === from.path) return if (mode === 'embed') { setTimeout(() => resolveCanIUse(), 1500) } diff --git a/packages/theme/src/client/components/Archive.vue b/packages/theme/src/client/components/Archive.vue index a2ebe6aa..f7247ae4 100644 --- a/packages/theme/src/client/components/Archive.vue +++ b/packages/theme/src/client/components/Archive.vue @@ -90,8 +90,8 @@ const headers = computed(() => { &::before { content: ''; display: inline-block; - width: 12px; - height: 12px; + width: 0.75rem; + height: 0.75rem; background-color: var(--c-bg-container); border-radius: 6px; border: solid 2px var(--c-border-dark); @@ -117,8 +117,8 @@ const headers = computed(() => { &::before { content: ''; display: inline-block; - width: 10px; - height: 10px; + width: 0.625rem; + height: 0.625rem; background-color: var(--c-bg-container); border-radius: 5px; border: solid 2px var(--c-border-dark); diff --git a/packages/theme/src/client/components/BloggerInfo.vue b/packages/theme/src/client/components/BloggerInfo.vue index ff47a57a..d5d58da6 100644 --- a/packages/theme/src/client/components/BloggerInfo.vue +++ b/packages/theme/src/client/components/BloggerInfo.vue @@ -146,8 +146,8 @@ const postStat = usePostStat() .email-icon, .github-icon, .weiBo-icon { - width: 24px; - height: 24px; + width: 1.5rem; + height: 1.5rem; } } @@ -163,14 +163,14 @@ const postStat = usePostStat() text-align: center; color: var(--c-text-quote); .icon { - width: 32px; - height: 32px; + width: 2rem; + height: 2rem; color: var(--c-text-lightest); } span { display: inline-block; width: 100%; - font-size: 20px; + font-size: 1.25rem; font-weight: 500; } } diff --git a/packages/theme/src/client/components/HomeBigBanner.vue b/packages/theme/src/client/components/HomeBigBanner.vue index f55397bc..be1b7a96 100644 --- a/packages/theme/src/client/components/HomeBigBanner.vue +++ b/packages/theme/src/client/components/HomeBigBanner.vue @@ -67,6 +67,8 @@ const avatar = themeLocale.value.avatar || {} diff --git a/packages/theme/src/client/components/Page.vue b/packages/theme/src/client/components/Page.vue index 64de2072..26abe739 100644 --- a/packages/theme/src/client/components/Page.vue +++ b/packages/theme/src/client/components/Page.vue @@ -5,11 +5,10 @@ import Sidebar from '@theme-plume/Sidebar.vue' import { usePageData } from '@vuepress/client' import { computed } from 'vue' import type { PlumeThemePageData } from '../../shared' -import { useDarkMode, useThemeLocaleData } from '../composables' +import { useDarkMode } from '../composables' import Toc from './Toc' const page = usePageData() -const themeLocale = useThemeLocaleData() const isDarkMode = useDarkMode() const isNote = computed(() => { @@ -27,7 +26,7 @@ const enabledSidebar = computed(() => {
-
+

{{ page.title }}

@@ -68,6 +67,10 @@ const enabledSidebar = computed(() => { max-width: var(--content-width); padding: 0 2rem 1rem; margin: 0 auto; + + &.note-content { + max-width: var(--content-note-width); + } } img { diff --git a/packages/theme/src/client/components/PageFooter.vue b/packages/theme/src/client/components/PageFooter.vue index c71250e5..8c14fa3e 100644 --- a/packages/theme/src/client/components/PageFooter.vue +++ b/packages/theme/src/client/components/PageFooter.vue @@ -35,7 +35,7 @@ const footer = computed(() => { padding: 1.25rem; background-color: var(--c-bg-container); box-shadow: var(--shadow-footer); - font-size: 14px; + font-size: 0.875rem; text-align: center; .theme-plume-footer-content { diff --git a/packages/theme/src/client/components/Pagination.vue b/packages/theme/src/client/components/Pagination.vue index 6069d8de..989b3918 100644 --- a/packages/theme/src/client/components/Pagination.vue +++ b/packages/theme/src/client/components/Pagination.vue @@ -113,7 +113,7 @@ function handleJump(): void { justify-content: flex-start; align-items: center; text-align: center; - font-size: 14px; + font-size: 0.875rem; .pagination-container { flex: 1; @@ -132,8 +132,8 @@ function handleJump(): void { cursor: pointer; font-size: inherit; padding: 0 0.8rem; - height: 34px; - line-height: 34px; + height: 2.125rem; + line-height: 2.125rem; border: solid 1px transparent; color: var(--c-text); box-shadow: var(--shadow-sm); @@ -156,8 +156,8 @@ function handleJump(): void { &.btn-prev, &.btn-next { .icon { - width: 14px; - height: 14px; + width: 0.875rem; + height: 0.875rem; vertical-align: text-top; } } @@ -168,8 +168,8 @@ function handleJump(): void { font-size: inherit; padding: 0.5rem; width: 3.25rem; - height: 34px; - line-height: 34px; + height: 2.125rem; + line-height: 2.125rem; border: solid 1px transparent; color: var(--c-text); box-shadow: var(--shadow-sm); diff --git a/packages/theme/src/client/components/PostList.vue b/packages/theme/src/client/components/PostList.vue index 4d1ffc27..594a344d 100644 --- a/packages/theme/src/client/components/PostList.vue +++ b/packages/theme/src/client/components/PostList.vue @@ -108,7 +108,7 @@ const togglePage = (currentPage: number): void => { .post-banner { position: relative; - height: 300px; + height: 18.75rem; margin: -1.25rem -1.5rem 1.25rem -1.5rem; overflow: hidden; cursor: pointer; @@ -134,7 +134,7 @@ const togglePage = (currentPage: number): void => { left: 1.5rem; width: 0; height: 0; - border: solid 20px; + border: solid 1.25rem; border-color: transparent transparent var(--c-bg-container) transparent; z-index: 1; } diff --git a/packages/theme/src/client/components/Sidebar.vue b/packages/theme/src/client/components/Sidebar.vue index 59652129..0a44fda0 100644 --- a/packages/theme/src/client/components/Sidebar.vue +++ b/packages/theme/src/client/components/Sidebar.vue @@ -48,7 +48,7 @@ onMounted(() => { width: 18rem; height: calc(100vh - var(--navbar-height) - 1.25rem); border-right: solid 1px var(--c-border); - font-size: 18px; + font-size: 1.125rem; padding-left: 1.25rem; overflow-y: auto; scrollbar-width: thin; @@ -78,7 +78,7 @@ onMounted(() => { content: ''; position: absolute; left: -1.25rem; - bottom: -4px; + bottom: -0.25rem; right: 0; border-bottom: solid 4px var(--c-border); } diff --git a/packages/theme/src/client/components/SidebarItems.vue b/packages/theme/src/client/components/SidebarItems.vue index 724bb9ac..61636b44 100644 --- a/packages/theme/src/client/components/SidebarItems.vue +++ b/packages/theme/src/client/components/SidebarItems.vue @@ -116,16 +116,16 @@ const sidebarClick = (sidebar: SidebarListComputed): void => { p.sidebar-items-title { position: relative; margin: 0; - height: 40px; - line-height: 40px; + height: 2.5rem; + line-height: 2.5rem; cursor: pointer; .arrow-right-icon { position: absolute; left: -1.5rem; top: 8px; - width: 20px; - height: 20px; + width: 1.25rem; + height: 1.25rem; transform: rotate(0); transition: transform var(--t-color); color: var(--c-text-quote); diff --git a/packages/theme/src/client/composables/postIndex.ts b/packages/theme/src/client/composables/postIndex.ts index 55016b07..ec2055f2 100644 --- a/packages/theme/src/client/composables/postIndex.ts +++ b/packages/theme/src/client/composables/postIndex.ts @@ -3,6 +3,10 @@ import { ref } from 'vue' import type { Ref } from 'vue' import type { PostIndex } from '../../shared' +const isBoolean = (arg: unknown): boolean => { + return typeof arg === 'boolean' +} + export type PostIndexRef = Ref export const postIndex: PostIndexRef = ref(postIndexRaw) @@ -11,7 +15,19 @@ export const usePostAllIndex = (): PostIndexRef => postIndex // 在首页文章列表的,默认排除掉 note中的文章,除非显示声明 article export const usePostIndex = (): PostIndexRef => { - const postList = postIndex.value.filter((post) => { + const postIndexData = [ + ...postIndex.value + .filter((post) => post.sticky) + .sort((left, right) => { + const leftSticky = isBoolean(left.sticky) ? 1 : (left.sticky as number) + const rightSticky = isBoolean(right.sticky) + ? 1 + : (right.sticky as number) + return leftSticky < rightSticky ? 1 : -1 + }), + ...postIndex.value.filter((post) => !post.sticky), + ] + const postList = postIndexData.filter((post) => { if (post.isNote) { return post.article === true } else { diff --git a/packages/theme/src/client/styles/normalize.scss b/packages/theme/src/client/styles/normalize.scss index f0209e67..8fd91a1b 100644 --- a/packages/theme/src/client/styles/normalize.scss +++ b/packages/theme/src/client/styles/normalize.scss @@ -107,9 +107,10 @@ h1 { h2 { font-size: 1.65rem; - padding-bottom: 0.3rem; + padding-bottom: 0.5rem; border-bottom: solid 1px var(--c-border); transition: border-color var(--t-color); + margin-top: 2.75rem; } h3 { diff --git a/packages/theme/src/client/styles/toc.scss b/packages/theme/src/client/styles/toc.scss index 3d57d4a7..27ddd3c6 100644 --- a/packages/theme/src/client/styles/toc.scss +++ b/packages/theme/src/client/styles/toc.scss @@ -1,4 +1,3 @@ - .theme-plume-toc { border-left: solid 1px var(--c-border); max-height: calc(100vh - var(--navbar-height) - (1.25rem * 3)); @@ -13,7 +12,6 @@ } } - .theme-plume-toc-list { list-style: none; @@ -48,7 +46,7 @@ } .plume-theme-page-toc { - width: 200px; + width: 12.5rem; margin-left: 1.25rem; .theme-plume-toc { diff --git a/packages/theme/src/client/styles/vars.scss b/packages/theme/src/client/styles/vars.scss index 4003fa8b..dca41ad5 100644 --- a/packages/theme/src/client/styles/vars.scss +++ b/packages/theme/src/client/styles/vars.scss @@ -86,7 +86,8 @@ --navbar-padding-h: 1.5rem; --sidebar-width: 20rem; --sidebar-width-mobile: calc(var(--sidebar-width) * 0.82); - --content-width: 740px; + --content-width: 850px; + --content-note-width: 1000px; // search box vars --search-bg-color: transparent; diff --git a/packages/theme/src/node/prepared/postIndex.ts b/packages/theme/src/node/prepared/postIndex.ts index 755d8769..f57ebdb1 100644 --- a/packages/theme/src/node/prepared/postIndex.ts +++ b/packages/theme/src/node/prepared/postIndex.ts @@ -24,15 +24,11 @@ if (import.meta.hot) { } ` -const isBoolean = (arg: unknown): boolean => { - return typeof arg === 'boolean' -} - export const preparedPostIndex = ( app: App, localeOption: PlumeThemeLocaleOptions ): void => { - let postIndex: PostIndex = (app.pages as Page[]) + const postIndex: PostIndex = (app.pages as Page[]) .filter((page) => { return ( !!page.pathInferred && @@ -64,18 +60,6 @@ export const preparedPostIndex = ( banner: frontmatter.banner, } as PostItem }) - postIndex = [ - ...postIndex - .filter((post) => post.sticky) - .sort((left, right) => { - const leftSticky = isBoolean(left.sticky) ? 1 : (left.sticky as number) - const rightSticky = isBoolean(right.sticky) - ? 1 - : (right.sticky as number) - return leftSticky < rightSticky ? 1 : -1 - }), - ...postIndex.filter((post) => !post.sticky), - ] let content = ` export const postIndex = ${JSON.stringify(postIndex, null, 2)}