✨ docs时间和阅读耗时
This commit is contained in:
parent
199bbf2628
commit
5a4efad893
4
.gitignore
vendored
4
.gitignore
vendored
@ -18,3 +18,7 @@
|
|||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
|
||||||
|
my-website
|
||||||
|
.vscode
|
||||||
|
lib/
|
72
README.md
72
README.md
@ -1,48 +1,46 @@
|
|||||||
# BLOG
|
<h1 align="center"> 王一之的个人博客 </h1>
|
||||||
|
<p align="center">分享知识,记录生活,认识朋友</p>
|
||||||
好记性不如烂笔头,自从工作以后写得越来越少了,在大学时还时不时的写点,现在回顾起来,感觉不到工作后的任何积累,写作水平也比以前差了不少,实在惭愧。
|
|
||||||
|
|
||||||
自前段时间看了大佬们的博客,下定决心重新开写,重新整理了一下过往的文章,~~黑历史去掉~~,然后重新挑选了一个博客程序,你感兴趣的话可以看看[blog](https://github.com/codfrm/blog)仓库,这个仓库之前也有一些代码记录,已经移动到了[archive](./archive)目录下。
|
|
||||||
|
|
||||||
整理时,回头看之前的文章,能感受到自己的一些技术进步,也能看到之前的一些感悟和中二(~~黑历史~~),从当年的小白变成了现在的中白,等以后成为了老白,再回头看看,应该也会有不一样的感悟。
|
|
||||||
|
|
||||||
我将以前的一些我觉得有意义的文章搬到了这里,日期应该都是 **2024 年 03 月 17 日**,重新进行了分类:[`DEV`](./docs/dev/)编程语言、软件开发;[`OPS`](./docs/ops/)服务器运维、工具分享;[`随笔`](./docs/note/)日常生活、感悟。
|
|
||||||
|
|
||||||
写博客其实也不止是为了记录,更多的是为了学习、为了分享、为了交流,也是为了能够在互联网上留下一片足迹,希望能够坚持下去。
|
|
||||||
|
|
||||||
如果你对本博客程序有兴趣,可以看看我这篇文章:[我为什么换掉 Wordpress 而选择 Docusaurus?](./docs/note/为什么换掉Wordpress.md)
|
|
||||||
如果你有其它问题,欢迎在文章下面留言,或者在[GitHub](https://github.com/codfrm/blog)上提 issue,我会尽快回复。
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
```go title="main.go"
|
这里是我的个人博客,使用 docusaurus 构建,主要用于记录一些技术知识,生活感悟,以及一些有趣的事情。欢迎大家来访,也欢迎大家留言,一起交流。
|
||||||
fmt.Println("Hello, World!")
|
|
||||||
|
---
|
||||||
|
|
||||||
|
> 如果你想基于本仓库部署自己的博客,可以查看下面的内容。关于本博客对 docusaurus 的一些修改,你可以查看[我为什么换掉 Wordpress 选择 Docusaurus?](./docs/note//为什么换掉Wordpress.md)
|
||||||
|
|
||||||
|
## 运行
|
||||||
|
|
||||||
|
你可以直接克隆本仓库,然后在本地运行。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 克隆与进入仓库
|
||||||
|
git clone https://github.com/codfrm/blog.git
|
||||||
|
cd blog
|
||||||
|
# 安装依赖
|
||||||
|
npm i
|
||||||
|
# 运行
|
||||||
|
npm start
|
||||||
```
|
```
|
||||||
|
|
||||||
```ts title="main.ts"
|
## 目录结构
|
||||||
console.log("Hello, World!");
|
|
||||||
```
|
|
||||||
|
|
||||||
```php title="main.php"
|
你需要根据自己的需求来对一些文件进行修改,一些没有标注出来的文件可能是与 docuasaurus 相关的一些配置文件,你可以根据官方文档来进行修改。
|
||||||
echo "Hello, World!";
|
|
||||||
```
|
|
||||||
|
|
||||||
```python title="main.py"
|
- archive 我的个人归档,你需要将它删除
|
||||||
print('Hello, World!')
|
- docs 博客文章,你的文章需要放在这里
|
||||||
```
|
- packages 一些自定义的插件
|
||||||
|
- src
|
||||||
|
- components/Comments/index.tsx 评论组件,使用[Giscus](https://giscus.app/zh-CN)构建 如果你使用的话,你需要修改里面的配置
|
||||||
|
- pages/index.tsx 首页文件
|
||||||
|
- docuasaurus.config.js docuasaurus 的配置文件,包含了博客的标题、描述等内容,你需要根据自己的需求来修改
|
||||||
|
- sidebars.js 侧边栏配置文件,你需要根据自己的需求来修改
|
||||||
|
|
||||||
```c title="main.c"
|
## 部署
|
||||||
printf("Hello, World!");
|
|
||||||
```
|
|
||||||
|
|
||||||
```cpp title="main.cpp"
|
构建完成后,将构建好的静态文件部署到你的服务器上即可。你也可以选择 Github Pages、Vercel、Netlify 等等。
|
||||||
std::cout << "Hello, World!";
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash title="main.sh"
|
```bash
|
||||||
echo "Hello, World!"
|
# 构建静态文件
|
||||||
```
|
npm run build
|
||||||
|
|
||||||
```docker title="Dockerfile"
|
|
||||||
RUN echo "Hello, World!"
|
|
||||||
```
|
```
|
||||||
|
20
docs/blog.md
Normal file
20
docs/blog.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
title: BLOG
|
||||||
|
hide_title: true
|
||||||
|
sidebar_position: 1
|
||||||
|
---
|
||||||
|
|
||||||
|
# BLOG
|
||||||
|
|
||||||
|
好记性不如烂笔头,自从工作以后写得越来越少了,在大学时还时不时的写点,现在回顾起来,感觉不到工作后的任何积累,写作水平也比以前差了不少,实在惭愧。
|
||||||
|
|
||||||
|
自前段时间看了大佬们的博客,下定决心重新开写,重新整理了一下过往的文章,~~黑历史去掉~~,然后重新挑选了一个博客程序,你感兴趣的话可以看看[blog](https://github.com/codfrm/blog)仓库,这个仓库之前也有一些代码记录,已经移动到了[archive](https://github.com/CodFrm/blog/tree/main/archive)目录下。
|
||||||
|
|
||||||
|
整理时,回头看之前的文章,能感受到自己的一些技术进步,也能看到之前的一些感悟和中二(~~黑历史~~),从当年的小白变成了现在的中白,等以后成为了老白,再回头看看,应该也会有不一样的感悟。
|
||||||
|
|
||||||
|
我将以前的一些我觉得有意义的文章搬到了这里,日期应该都是 **2024 年 03 月 17 日**,重新进行了分类:[`DEV`](./dev/)编程语言、软件开发;[`OPS`](./ops/)服务器运维、工具分享;[`笔记`](./note/)日常生活、感悟。
|
||||||
|
|
||||||
|
写博客其实也不止是为了记录,更多的是为了学习、为了分享、为了交流,也是为了能够在互联网上留下一片足迹,希望能够坚持下去。
|
||||||
|
|
||||||
|
如果你对本博客程序有兴趣,可以看看我这篇文章:[我为什么换掉 Wordpress 选择 Docusaurus?](./note/为什么换掉Wordpress.md)
|
||||||
|
如果你有其它问题,欢迎在文章下面留言,或者在[GitHub](https://github.com/codfrm/blog)上提 issue,我会尽快回复。
|
@ -1,9 +0,0 @@
|
|||||||
---
|
|
||||||
title: BLOG
|
|
||||||
hide_title: true
|
|
||||||
sidebar_position: 1
|
|
||||||
---
|
|
||||||
|
|
||||||
import README from "../README.md";
|
|
||||||
|
|
||||||
<README />
|
|
@ -132,7 +132,7 @@ git push origin master
|
|||||||
|
|
||||||
#### Action
|
#### Action
|
||||||
|
|
||||||
是 github 最近推出的一项 CI/CD 服务, 具体可以去看我原来的文章:[github action 入门](../../ops/CI&CD/github-actions-入门)
|
是 github 最近推出的一项 CI/CD 服务, 具体可以去看我原来的文章:[github action 入门](../../ops/ci&cd/github-actions-入门)
|
||||||
|
|
||||||
#### project
|
#### project
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: 我为什么换掉Wordpress而选择Docusaurus?
|
title: 我为什么换掉Wordpress选择Docusaurus?
|
||||||
|
keyword: [笔记, 博客]
|
||||||
---
|
---
|
||||||
|
|
||||||
在此之前,我一直使用 Wordpress 来做我的博客,最近准备重新开始写,为什么决定换掉它呢?
|
在此之前,我一直使用 Wordpress 来做我的博客,最近准备重新开始写,为什么决定换掉它呢?
|
||||||
@ -41,14 +42,23 @@ SSG 是希望能够生成静态站点,这样就不需要配置 PHP、Mysql、N
|
|||||||
## Docusaurus 的定制
|
## Docusaurus 的定制
|
||||||
|
|
||||||
Docusaurus 是有 blog 功能的,但是 blog 不能支持左侧的目录树,然后 docs 又不支持文章时间,于是我写了一个 docs 时间生成的插件。
|
Docusaurus 是有 blog 功能的,但是 blog 不能支持左侧的目录树,然后 docs 又不支持文章时间,于是我写了一个 docs 时间生成的插件。
|
||||||
|
两种方式其实也对应两种不同的逻辑,至于哪种好,我也不好说,我只是觉得我大多时候应该是写偏向文档类型的文章,所以我选择了 docs,这样可以更方便检索,
|
||||||
|
不过可能写一些生活感悟这些和时间相关的就会再选择 blog 吧。
|
||||||
|
|
||||||
然后 Docuasaurus 也只是一个静态站点生成器,不支持评论、统计等等功能,需要一些外部依赖来实现。我主要改造如下,你也可以进入我的博客仓库查看:
|
然后 Docuasaurus 也只是一个静态站点生成器,不支持评论、统计等等功能,需要一些外部依赖来实现。我主要改造如下,你也可以进入我的博客仓库查看:
|
||||||
|
|
||||||
- 修改首页
|
- 修改首页
|
||||||
- 增加 Docs 文章时间排序
|
- 增加 Docs 文章时间排序
|
||||||
- 接入 giscus 评论
|
- 接入 giscus 评论
|
||||||
- 接入 Google Analytics 统计
|
- 接入 Google Analytics 统计
|
||||||
- 增加了 Markdown lint
|
- 增加了 Markdown lint(vscode插件)
|
||||||
|
|
||||||
在以后或许还会用 golang 写一个提供服务的后端,来实现其他更多的功能。
|
### docusaurus-plugin-docs-info 功能
|
||||||
|
|
||||||
|
- 生成最新文章列表
|
||||||
|
- 生成文章创建/更新时间
|
||||||
|
- 文章阅读时间
|
||||||
|
|
||||||
|
后续或许还会写一个后端,来实现其他更多的功能。
|
||||||
|
|
||||||
总之不同的博客程序都有不同的优势,也有不同的劣势,选择适合自己的就好。
|
总之不同的博客程序都有不同的优势,也有不同的劣势,选择适合自己的就好。
|
||||||
|
@ -2,4 +2,3 @@
|
|||||||
id: ci-cd
|
id: ci-cd
|
||||||
title: CI/CD
|
title: CI/CD
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -24,7 +24,18 @@ const config: Config = {
|
|||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
["@gracefullight/docusaurus-plugin-tailwind", {}],
|
["@gracefullight/docusaurus-plugin-tailwind", {}],
|
||||||
["docusaurus-plugin-docs-info", {}],
|
[
|
||||||
|
"docusaurus-plugin-content-docs",
|
||||||
|
{
|
||||||
|
routeBasePath: "/",
|
||||||
|
sidebarPath: "./sidebars.ts",
|
||||||
|
// Please change this to your repo.
|
||||||
|
// Remove this to remove the "edit this page" links.
|
||||||
|
editUrl: "https://github.com/CodFrm/blog/edit/main",
|
||||||
|
showLastUpdateTime: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
["docusaurus-plugin-docs-info", { debug: true }],
|
||||||
],
|
],
|
||||||
|
|
||||||
// Even if you don't use internationalization, you can use this field to set
|
// Even if you don't use internationalization, you can use this field to set
|
||||||
@ -39,14 +50,15 @@ const config: Config = {
|
|||||||
[
|
[
|
||||||
"classic",
|
"classic",
|
||||||
{
|
{
|
||||||
docs: {
|
docs: false,
|
||||||
routeBasePath: "/",
|
// docs: {
|
||||||
sidebarPath: "./sidebars.ts",
|
// routeBasePath: "/",
|
||||||
// Please change this to your repo.
|
// sidebarPath: "./sidebars.ts",
|
||||||
// Remove this to remove the "edit this page" links.
|
// // Please change this to your repo.
|
||||||
editUrl: "https://github.com/codfrm/blog",
|
// // Remove this to remove the "edit this page" links.
|
||||||
showLastUpdateTime: true,
|
// editUrl: "https://github.com/codfrm/blog",
|
||||||
},
|
// showLastUpdateTime: true,
|
||||||
|
// },
|
||||||
theme: {
|
theme: {
|
||||||
customCss: "./src/css/custom.css",
|
customCss: "./src/css/custom.css",
|
||||||
},
|
},
|
||||||
|
4578
package-lock.json
generated
4578
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -19,6 +19,7 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/core": "3.1.1",
|
"@docusaurus/core": "3.1.1",
|
||||||
|
"@docusaurus/plugin-content-docs": "^3.1.1",
|
||||||
"@docusaurus/plugin-sitemap": "^3.1.1",
|
"@docusaurus/plugin-sitemap": "^3.1.1",
|
||||||
"@docusaurus/preset-classic": "3.1.1",
|
"@docusaurus/preset-classic": "3.1.1",
|
||||||
"@giscus/react": "^3.0.0",
|
"@giscus/react": "^3.0.0",
|
||||||
@ -27,12 +28,13 @@
|
|||||||
"@mdx-js/react": "^3.0.0",
|
"@mdx-js/react": "^3.0.0",
|
||||||
"antd": "^5.15.2",
|
"antd": "^5.15.2",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
|
"dayjs": "^1.11.10",
|
||||||
|
"docusaurus-plugin-content-docs": "^1.0.0",
|
||||||
"docusaurus-plugin-docs-info": "^1.0.0",
|
"docusaurus-plugin-docs-info": "^1.0.0",
|
||||||
"gray-matter": "^4.0.3",
|
"gray-matter": "^4.0.3",
|
||||||
"prism-react-renderer": "^2.3.0",
|
"prism-react-renderer": "^2.3.0",
|
||||||
"react": "^18.0.0",
|
"react": "^18.0.0",
|
||||||
"react-dom": "^18.0.0",
|
"react-dom": "^18.0.0"
|
||||||
"simple-git": "^3.22.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@docusaurus/eslint-plugin": "^3.1.1",
|
"@docusaurus/eslint-plugin": "^3.1.1",
|
||||||
|
18
packages/docusaurus-plugin-content-docs/package.json
Normal file
18
packages/docusaurus-plugin-content-docs/package.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "docusaurus-plugin-content-docs",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "src/index.ts",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@docusaurus/core": "^3.1.1",
|
||||||
|
"@docusaurus/plugin-content-docs": "^3.1.1",
|
||||||
|
"dayjs": "^1.11.10",
|
||||||
|
"reading-time": "^1.5.0",
|
||||||
|
"simple-git": "^3.22.0"
|
||||||
|
}
|
||||||
|
}
|
106
packages/docusaurus-plugin-content-docs/src/index.ts
Normal file
106
packages/docusaurus-plugin-content-docs/src/index.ts
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
import docsPlugin, {
|
||||||
|
PluginOptions,
|
||||||
|
LoadedContent,
|
||||||
|
DocMetadata as OfficialDocMetadata,
|
||||||
|
} from "@docusaurus/plugin-content-docs";
|
||||||
|
import { Plugin, LoadContext } from "@docusaurus/types";
|
||||||
|
import matter from "gray-matter";
|
||||||
|
//@ts-ignore
|
||||||
|
export { validateOptions } from "@docusaurus/plugin-content-docs/src/index";
|
||||||
|
import path from "path";
|
||||||
|
import fs from "fs";
|
||||||
|
import simpleGit, { DefaultLogFields } from "simple-git";
|
||||||
|
import readingTime, { ReadTimeResults } from "reading-time";
|
||||||
|
|
||||||
|
export type DocMetadata = OfficialDocMetadata & { detail: Detail };
|
||||||
|
|
||||||
|
export interface Detail {
|
||||||
|
filename: string;
|
||||||
|
reading_time: ReadTimeResults;
|
||||||
|
create_date?: Date;
|
||||||
|
update_date?: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function pluginContentDocs(
|
||||||
|
context: LoadContext,
|
||||||
|
options: PluginOptions & { debug?: boolean }
|
||||||
|
): Promise<Plugin<LoadedContent>> {
|
||||||
|
const ret = (await docsPlugin.call(
|
||||||
|
this,
|
||||||
|
context,
|
||||||
|
options
|
||||||
|
)) as Plugin<LoadedContent>;
|
||||||
|
|
||||||
|
const themePath = path.resolve(__dirname, "./theme");
|
||||||
|
ret.getThemePath = () => {
|
||||||
|
return themePath;
|
||||||
|
};
|
||||||
|
|
||||||
|
const warpLoadContent = ret.loadContent;
|
||||||
|
ret.loadContent = async () => {
|
||||||
|
const ret = await warpLoadContent();
|
||||||
|
// 注入时间信息
|
||||||
|
const docs: DocMetadata[] = [];
|
||||||
|
const git = simpleGit();
|
||||||
|
ret.loadedVersions.forEach((version) => {
|
||||||
|
version.docs.forEach((doc) => {
|
||||||
|
docs.push(doc as any);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
docs.map(async (doc) => {
|
||||||
|
// 读取文件内容, 查看标题, 查看日期
|
||||||
|
const filename = doc.source.replace("@site", ".");
|
||||||
|
const meta = matter.read(filename);
|
||||||
|
const detail: Detail = {
|
||||||
|
filename: filename,
|
||||||
|
reading_time: readingTime(meta.content),
|
||||||
|
};
|
||||||
|
return new Promise<void>((resolve) => {
|
||||||
|
// 读取git log文件时间
|
||||||
|
git.log<DefaultLogFields>(
|
||||||
|
{
|
||||||
|
format: "%ad",
|
||||||
|
file: filename,
|
||||||
|
},
|
||||||
|
(_, data) => {
|
||||||
|
if (meta.data["create_date"]) {
|
||||||
|
detail.create_date = new Date(meta.data["create_date"]);
|
||||||
|
} else {
|
||||||
|
detail.create_date = data.all.length
|
||||||
|
? new Date(data.all[data.all.length - 1].date)
|
||||||
|
: new Date();
|
||||||
|
}
|
||||||
|
if (meta.data["update_date"]) {
|
||||||
|
detail.update_date = new Date(meta.data["update_date"]);
|
||||||
|
} else {
|
||||||
|
detail.update_date = data.latest
|
||||||
|
? new Date(data.latest.date)
|
||||||
|
: new Date();
|
||||||
|
}
|
||||||
|
doc.detail = detail;
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
// 排序创造时间列表
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
const warpContentLoaded = ret.contentLoaded;
|
||||||
|
|
||||||
|
ret.contentLoaded = async ({ content, actions, allContent }) => {
|
||||||
|
const ret = await warpContentLoaded({
|
||||||
|
content,
|
||||||
|
actions,
|
||||||
|
allContent,
|
||||||
|
});
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
1
packages/docusaurus-plugin-docs-info/node_modules/.bin/docusaurus
generated
vendored
1
packages/docusaurus-plugin-docs-info/node_modules/.bin/docusaurus
generated
vendored
@ -1 +0,0 @@
|
|||||||
../../../../node_modules/@docusaurus/core/bin/docusaurus.mjs
|
|
@ -10,6 +10,7 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/core": "^3.1.1",
|
"@docusaurus/core": "^3.1.1",
|
||||||
"dayjs": "^1.11.10"
|
"dayjs": "^1.11.10",
|
||||||
|
"reading-time": "^1.5.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,45 +1,21 @@
|
|||||||
import { Article } from "../..";
|
|
||||||
import { FullVersion } from "@docusaurus/plugin-content-docs/lib/types.d.ts";
|
import { FullVersion } from "@docusaurus/plugin-content-docs/lib/types.d.ts";
|
||||||
import { DocMetadata } from "@docusaurus/plugin-content-docs";
|
|
||||||
import { usePluginData } from "@docusaurus/useGlobalData";
|
import { usePluginData } from "@docusaurus/useGlobalData";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import Link from "@docusaurus/Link";
|
import Link from "@docusaurus/Link";
|
||||||
|
import { DocMetadata } from "docusaurus-plugin-content-docs/src";
|
||||||
|
|
||||||
const ArticleList: React.FC<{
|
const ArticleList: React.FC<{
|
||||||
list: Article[];
|
list: DocMetadata[];
|
||||||
}> = ({ list: data }) => {
|
}> = ({ list: data }) => {
|
||||||
const docsData = usePluginData("docusaurus-plugin-content-docs") as {
|
const docsData = usePluginData("docusaurus-plugin-content-docs") as {
|
||||||
versions: FullVersion[];
|
versions: FullVersion[];
|
||||||
};
|
};
|
||||||
const list: Array<Array<Article>> = [];
|
const list: Array<Array<DocMetadata>> = [];
|
||||||
const map: Map<string, DocMetadata> = new Map();
|
|
||||||
for (let i = 0; i < docsData.versions[0].docs.length; i++) {
|
|
||||||
// @ts-ignore
|
|
||||||
map.set(docsData.versions[0].docs[i].path, docsData.versions[0].docs[i]);
|
|
||||||
}
|
|
||||||
// 一行两个
|
// 一行两个
|
||||||
const num = 3;
|
const num = 3;
|
||||||
for (let i = 0; i < data.length && i < 8; i += num) {
|
for (let i = 0; i < data.length && i < 8; i += num) {
|
||||||
list.push(data.slice(i, i + num));
|
list.push(data.slice(i, i + num));
|
||||||
}
|
}
|
||||||
// 构建与docs的连接
|
|
||||||
for (let i = 0; i < list.length; i++) {
|
|
||||||
for (let j = 0; j < list[i].length; j++) {
|
|
||||||
const val = list[i][j];
|
|
||||||
let path = val.filename.replace(/\.(md|mdx)/, "").substring(4);
|
|
||||||
if (
|
|
||||||
val.filename.endsWith("index.md") ||
|
|
||||||
val.filename.endsWith("index.mdx")
|
|
||||||
) {
|
|
||||||
path = path.split("/").slice(0, -1).join("/") + "/";
|
|
||||||
}
|
|
||||||
const doc = map.get(path);
|
|
||||||
if (doc) {
|
|
||||||
// @ts-ignore
|
|
||||||
list[i][j].link = doc.path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -56,8 +32,7 @@ const ArticleList: React.FC<{
|
|||||||
>
|
>
|
||||||
<div className="card__header">
|
<div className="card__header">
|
||||||
<Link
|
<Link
|
||||||
// @ts-ignore
|
to={val.permalink}
|
||||||
to={val.link}
|
|
||||||
className="text-left"
|
className="text-left"
|
||||||
style={{
|
style={{
|
||||||
display: "block",
|
display: "block",
|
||||||
@ -79,7 +54,9 @@ const ArticleList: React.FC<{
|
|||||||
fontSize: "12px",
|
fontSize: "12px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<p>{dayjs(val.create_date).format("YYYY年MM月DD日")}</p>
|
<p>
|
||||||
|
{dayjs(val.detail.create_date).format("YYYY年MM月DD日")}
|
||||||
|
</p>
|
||||||
<Link
|
<Link
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
to={val.link}
|
to={val.link}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { usePluginData } from "@docusaurus/useGlobalData";
|
import { usePluginData } from "@docusaurus/useGlobalData";
|
||||||
import { Articles } from "../..";
|
import { Articles } from "docusaurus-plugin-docs-info";
|
||||||
import ArticleList from "../ArticleList";
|
import ArticleList from "../ArticleList";
|
||||||
import Link from "@docusaurus/Link";
|
import Link from "@docusaurus/Link";
|
||||||
|
|
||||||
|
@ -3,6 +3,9 @@ import fs from "fs";
|
|||||||
import simpleGit, { DefaultLogFields } from "simple-git";
|
import simpleGit, { DefaultLogFields } from "simple-git";
|
||||||
import matter from "gray-matter";
|
import matter from "gray-matter";
|
||||||
import { LoadContext, Plugin } from "@docusaurus/types";
|
import { LoadContext, Plugin } from "@docusaurus/types";
|
||||||
|
import readingTime, { ReadTimeResults } from "reading-time";
|
||||||
|
import { LoadedVersion } from "@docusaurus/plugin-content-docs";
|
||||||
|
import { DocMetadata } from "docusaurus-plugin-content-docs/src";
|
||||||
|
|
||||||
async function readDir(pathName: string) {
|
async function readDir(pathName: string) {
|
||||||
return new Promise<string[]>((resolve) => {
|
return new Promise<string[]>((resolve) => {
|
||||||
@ -32,12 +35,13 @@ async function readDir(pathName: string) {
|
|||||||
export interface Article {
|
export interface Article {
|
||||||
filename: string;
|
filename: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
reading_time: ReadTimeResults;
|
||||||
create_date?: Date;
|
create_date?: Date;
|
||||||
update_date?: Date;
|
update_date?: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Articles {
|
export interface Articles {
|
||||||
list: Article[];
|
list: DocMetadata[];
|
||||||
current: number;
|
current: number;
|
||||||
total: number;
|
total: number;
|
||||||
}
|
}
|
||||||
@ -52,7 +56,7 @@ export default function (
|
|||||||
getThemePath() {
|
getThemePath() {
|
||||||
return themePath;
|
return themePath;
|
||||||
},
|
},
|
||||||
async contentLoaded({ content, actions }): Promise<void> {
|
async contentLoaded({ content, actions, allContent }): Promise<void> {
|
||||||
const { addRoute, createData, setGlobalData } = actions;
|
const { addRoute, createData, setGlobalData } = actions;
|
||||||
const isProd = process.env.NODE_ENV === "production";
|
const isProd = process.env.NODE_ENV === "production";
|
||||||
if (!isProd && !options.debug) {
|
if (!isProd && !options.debug) {
|
||||||
@ -64,70 +68,22 @@ export default function (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 读取docs下文件
|
const docsData = allContent["docusaurus-plugin-content-docs"] as {
|
||||||
const files = await readDir("./docs");
|
default: { loadedVersions: LoadedVersion };
|
||||||
const git = simpleGit();
|
|
||||||
const articles = [];
|
|
||||||
|
|
||||||
await Promise.all(
|
|
||||||
files.map((file) => {
|
|
||||||
return new Promise<void>((resolve) => {
|
|
||||||
if (
|
|
||||||
!(
|
|
||||||
file.startsWith("_") ||
|
|
||||||
file.endsWith(".md") ||
|
|
||||||
file.endsWith(".mdx")
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return resolve();
|
|
||||||
}
|
|
||||||
// 读取文件内容, 查看标题, 查看日期
|
|
||||||
const meta = matter.read(file);
|
|
||||||
const article: Article = {
|
|
||||||
filename: file,
|
|
||||||
title:
|
|
||||||
meta.data["title"] ||
|
|
||||||
path.basename(file).split(".").slice(0, -1).join("."),
|
|
||||||
};
|
};
|
||||||
// 读取git log文件时间
|
let docs = docsData.default.loadedVersions[0].docs as DocMetadata[];
|
||||||
git.log<DefaultLogFields>(
|
// 文章时间排序
|
||||||
{
|
docs = docs.sort((a, b) => {
|
||||||
format: "%ad",
|
//@ts-ignore
|
||||||
file: file,
|
return b.detail.create_date.getTime() - a.detail.create_date.getTime();
|
||||||
},
|
|
||||||
(_, data) => {
|
|
||||||
if (meta.data["create_date"]) {
|
|
||||||
article.create_date = new Date(meta.data["create_date"]);
|
|
||||||
} else {
|
|
||||||
article.create_date = data.all.length
|
|
||||||
? new Date(data.all[data.all.length - 1].date)
|
|
||||||
: new Date();
|
|
||||||
}
|
|
||||||
if (meta.data["update_date"]) {
|
|
||||||
article.update_date = new Date(meta.data["update_date"]);
|
|
||||||
} else {
|
|
||||||
article.update_date = data.latest
|
|
||||||
? new Date(data.latest.date)
|
|
||||||
: new Date();
|
|
||||||
}
|
|
||||||
articles.push(article);
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
// 20篇为一页, 创建时间由新到旧
|
// 20篇为一页, 创建时间由新到旧
|
||||||
articles.sort((a, b) => {
|
|
||||||
return b.create_date.getTime() - a.create_date.getTime();
|
|
||||||
});
|
|
||||||
|
|
||||||
const pageSize = 21;
|
const pageSize = 21;
|
||||||
const latest = {
|
const latest = {
|
||||||
current: 1,
|
current: 1,
|
||||||
list: articles.slice(0, pageSize),
|
list: docs.slice(0, pageSize),
|
||||||
total: articles.length,
|
total: docs.length,
|
||||||
};
|
};
|
||||||
setGlobalData(latest);
|
setGlobalData(latest);
|
||||||
|
|
||||||
@ -144,14 +100,14 @@ export default function (
|
|||||||
exact: true,
|
exact: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
for (let i = 1; i < Math.ceil(articles.length / pageSize); i++) {
|
for (let i = 1; i < Math.ceil(docs.length / pageSize); i++) {
|
||||||
const page = i + 1;
|
const page = i + 1;
|
||||||
const pageData = await createData(
|
const pageData = await createData(
|
||||||
`timeline-${page}.json`,
|
`timeline-${page}.json`,
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
current: i + 1,
|
current: i + 1,
|
||||||
list: articles.slice(i * pageSize, (i + 1) * pageSize),
|
list: docs.slice(i * pageSize, (i + 1) * pageSize),
|
||||||
total: articles.length,
|
total: docs.length,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
addRoute({
|
addRoute({
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import Layout from "@theme/Layout";
|
import Layout from "@theme/Layout";
|
||||||
import { Article, Articles } from "../..";
|
import { Article, Articles } from "docusaurus-plugin-docs-info";
|
||||||
import ArticleList from "../../components/ArticleList";
|
|
||||||
import { Pagination } from "antd";
|
import { Pagination } from "antd";
|
||||||
import Link from "@docusaurus/Link";
|
import Link from "@docusaurus/Link";
|
||||||
|
import ArticleList from "../../components/ArticleList";
|
||||||
|
|
||||||
export interface TimelineProps {
|
export interface TimelineProps {
|
||||||
articles: Articles;
|
articles: Articles;
|
||||||
@ -30,8 +30,11 @@ function Timeline({ articles }: TimelineProps) {
|
|||||||
total={articles.total}
|
total={articles.total}
|
||||||
pageSize={20}
|
pageSize={20}
|
||||||
showSizeChanger={false}
|
showSizeChanger={false}
|
||||||
|
style={{
|
||||||
|
marginBottom: "10px",
|
||||||
|
}}
|
||||||
itemRender={(page, type, el) => {
|
itemRender={(page, type, el) => {
|
||||||
if (!page) {
|
if (type !== "page") {
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
if (page === 1) {
|
if (page === 1) {
|
||||||
|
28
src/theme/DocItem/index.tsx
Normal file
28
src/theme/DocItem/index.tsx
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { HtmlClassNameProvider } from "@docusaurus/theme-common";
|
||||||
|
import { DocProvider } from "@docusaurus/theme-common/internal";
|
||||||
|
import DocItemMetadata from "@theme/DocItem/Metadata";
|
||||||
|
import DocItemLayout from "@theme/DocItem/Layout";
|
||||||
|
import type { Props } from "@theme/DocItem";
|
||||||
|
|
||||||
|
export default function DocItem(props: Props): JSX.Element {
|
||||||
|
const docHtmlClassName = `docs-doc-id-${props.content.metadata.id}`;
|
||||||
|
const MDXComponent = props.content;
|
||||||
|
return (
|
||||||
|
<DocProvider content={props.content}>
|
||||||
|
<HtmlClassNameProvider className={docHtmlClassName}>
|
||||||
|
<DocItemMetadata />
|
||||||
|
<DocItemLayout>
|
||||||
|
<MDXComponent />
|
||||||
|
</DocItemLayout>
|
||||||
|
</HtmlClassNameProvider>
|
||||||
|
</DocProvider>
|
||||||
|
);
|
||||||
|
}
|
17
src/theme/Layout/Provider/antd.tsx
Normal file
17
src/theme/Layout/Provider/antd.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { ConfigProvider, theme } from "antd";
|
||||||
|
import { useColorMode } from "@docusaurus/theme-common";
|
||||||
|
|
||||||
|
export default function AntdProvider({ children }) {
|
||||||
|
const colorMode = useColorMode();
|
||||||
|
return (
|
||||||
|
<ConfigProvider
|
||||||
|
theme={{
|
||||||
|
algorithm: colorMode.isDarkTheme
|
||||||
|
? theme.darkAlgorithm
|
||||||
|
: theme.defaultAlgorithm,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</ConfigProvider>
|
||||||
|
);
|
||||||
|
}
|
33
src/theme/Layout/Provider/index.tsx
Normal file
33
src/theme/Layout/Provider/index.tsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { composeProviders } from "@docusaurus/theme-common";
|
||||||
|
import {
|
||||||
|
ColorModeProvider,
|
||||||
|
AnnouncementBarProvider,
|
||||||
|
DocsPreferredVersionContextProvider,
|
||||||
|
ScrollControllerProvider,
|
||||||
|
NavbarProvider,
|
||||||
|
PluginHtmlClassNameProvider,
|
||||||
|
} from "@docusaurus/theme-common/internal";
|
||||||
|
import type { Props } from "@theme/Layout/Provider";
|
||||||
|
import AntdProvider from "./antd";
|
||||||
|
|
||||||
|
const Provider = composeProviders([
|
||||||
|
ColorModeProvider,
|
||||||
|
AnnouncementBarProvider,
|
||||||
|
ScrollControllerProvider,
|
||||||
|
DocsPreferredVersionContextProvider,
|
||||||
|
PluginHtmlClassNameProvider,
|
||||||
|
NavbarProvider,
|
||||||
|
AntdProvider,
|
||||||
|
]);
|
||||||
|
|
||||||
|
export default function LayoutProvider({ children }: Props): JSX.Element {
|
||||||
|
return <Provider>{children}</Provider>;
|
||||||
|
}
|
43
src/theme/MDXComponents/Heading.tsx
Normal file
43
src/theme/MDXComponents/Heading.tsx
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import Heading from "@theme/Heading";
|
||||||
|
import type { Props } from "@theme/MDXComponents/Heading";
|
||||||
|
import { useDoc } from "@docusaurus/theme-common/internal";
|
||||||
|
import { Detail } from "packages/docusaurus-plugin-content-docs/src";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
export default function MDXHeading(props: Props): JSX.Element {
|
||||||
|
const doc = useDoc();
|
||||||
|
const detail = (doc.metadata as any).detail as Detail;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Heading
|
||||||
|
{...props}
|
||||||
|
style={{
|
||||||
|
marginBottom: "6px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{props.children}
|
||||||
|
</Heading>
|
||||||
|
{detail && (
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
display: "block",
|
||||||
|
fontSize: ".9rem",
|
||||||
|
fontWeight: "normal",
|
||||||
|
marginBottom: "1rem",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{dayjs(detail.create_date).format("YYYY年MM月DD日")} · 阅读需{" "}
|
||||||
|
{Math.ceil(detail.reading_time.minutes)} 分钟
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
0
src/utils/index.ts
Normal file
0
src/utils/index.ts
Normal file
Loading…
x
Reference in New Issue
Block a user