init commit

This commit is contained in:
2024-03-19 01:05:51 +08:00
commit 199bbf2628
393 changed files with 34883 additions and 0 deletions

View File

@ -0,0 +1 @@
../../../../node_modules/@docusaurus/core/bin/docusaurus.mjs

View File

@ -0,0 +1,15 @@
{
"name": "docusaurus-plugin-docs-info",
"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",
"dayjs": "^1.11.10"
}
}

View File

@ -0,0 +1,100 @@
import { Article } from "../..";
import { FullVersion } from "@docusaurus/plugin-content-docs/lib/types.d.ts";
import { DocMetadata } from "@docusaurus/plugin-content-docs";
import { usePluginData } from "@docusaurus/useGlobalData";
import dayjs from "dayjs";
import Link from "@docusaurus/Link";
const ArticleList: React.FC<{
list: Article[];
}> = ({ list: data }) => {
const docsData = usePluginData("docusaurus-plugin-content-docs") as {
versions: FullVersion[];
};
const list: Array<Array<Article>> = [];
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;
for (let i = 0; i < data.length && i < 8; 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 (
<>
{list.map((val, index) => (
<div className="row" key={"row-" + index}>
{val.map((val, index) => (
<div className="col col--4" key={"col-" + index}>
<div
className="card"
style={{
borderWidth: 1,
borderColor: "var(--ifm-color-primary)",
}}
>
<div className="card__header">
<Link
// @ts-ignore
to={val.link}
className="text-left"
style={{
display: "block",
fontSize: "18px",
maxWidth: "80%",
textOverflow: "ellipsis",
overflow: "hidden",
whiteSpace: "nowrap",
}}
>
{val.title}
</Link>
</div>
<div className="card__body">
<div
className="flex flex-row w-full items-center"
style={{
justifyContent: "space-between",
fontSize: "12px",
}}
>
<p>{dayjs(val.create_date).format("YYYY年MM月DD日")}</p>
<Link
// @ts-ignore
to={val.link}
>
<button className="button button--link"></button>
</Link>
</div>
</div>
</div>
</div>
))}
</div>
))}
</>
);
};
export default ArticleList;

View File

@ -0,0 +1,33 @@
import { usePluginData } from "@docusaurus/useGlobalData";
import { Articles } from "../..";
import ArticleList from "../ArticleList";
import Link from "@docusaurus/Link";
function LatestDocs() {
const data = usePluginData("docusaurus-plugin-docs-info") as Articles;
return (
<div
className="container flex flex-col"
style={{
gap: "1rem",
}}
>
<ArticleList list={data.list} />
<div
className="w-full"
style={{
textAlign: "right",
}}
>
<Link exact href="/timeline">
<button className="button button--primary button--lg">
</button>
</Link>
</div>
</div>
);
}
export default LatestDocs;

View File

@ -0,0 +1,168 @@
import path from "path";
import fs from "fs";
import simpleGit, { DefaultLogFields } from "simple-git";
import matter from "gray-matter";
import { LoadContext, Plugin } from "@docusaurus/types";
async function readDir(pathName: string) {
return new Promise<string[]>((resolve) => {
const filenames: Array<string> = [];
fs.readdir(pathName, async (_, files) => {
await Promise.all(
files.map((val) => {
return new Promise<void>((resolve) => {
const filename = path.join(pathName, val);
fs.stat(filename, async (_, stats) => {
if (stats.isFile()) {
filenames.push(filename);
} else {
const result = await readDir(filename);
filenames.push(...result);
}
resolve();
});
});
})
);
resolve(filenames);
});
});
}
export interface Article {
filename: string;
title: string;
create_date?: Date;
update_date?: Date;
}
export interface Articles {
list: Article[];
current: number;
total: number;
}
export default function (
context: LoadContext,
options: { debug?: boolean }
): Plugin {
const themePath = path.resolve(__dirname, "./theme");
return {
name: "docusaurus-plugin-docs-info",
getThemePath() {
return themePath;
},
async contentLoaded({ content, actions }): Promise<void> {
const { addRoute, createData, setGlobalData } = actions;
const isProd = process.env.NODE_ENV === "production";
if (!isProd && !options.debug) {
setGlobalData({
current: 1,
list: [],
total: 0,
});
return;
}
// 读取docs下文件
const files = await readDir("./docs");
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文件时间
git.log<DefaultLogFields>(
{
format: "%ad",
file: file,
},
(_, 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篇为一页, 创建时间由新到旧
articles.sort((a, b) => {
return b.create_date.getTime() - a.create_date.getTime();
});
const pageSize = 21;
const latest = {
current: 1,
list: articles.slice(0, pageSize),
total: articles.length,
};
setGlobalData(latest);
const pageData = await createData(
"timeline-1.json",
JSON.stringify(latest)
);
addRoute({
path: "/timeline",
component: "@theme/Timeline",
modules: {
articles: pageData,
},
exact: true,
});
for (let i = 1; i < Math.ceil(articles.length / pageSize); i++) {
const page = i + 1;
const pageData = await createData(
`timeline-${page}.json`,
JSON.stringify({
current: i + 1,
list: articles.slice(i * pageSize, (i + 1) * pageSize),
total: articles.length,
})
);
addRoute({
path: `/timeline/${page}`,
component: "@theme/Timeline",
modules: {
articles: pageData,
},
exact: true,
});
}
},
};
}

View File

@ -0,0 +1,49 @@
import Layout from "@theme/Layout";
import { Article, Articles } from "../..";
import ArticleList from "../../components/ArticleList";
import { Pagination } from "antd";
import Link from "@docusaurus/Link";
export interface TimelineProps {
articles: Articles;
}
function Timeline({ articles }: TimelineProps) {
return (
<Layout title={"最新文章 - 第" + articles.current + "页"}>
<div
className="container flex flex-col px-8"
style={{
paddingTop: "2rem",
gap: "1rem",
}}
>
<ArticleList list={articles.list} />
<div
className="flex flex-row"
style={{
justifyContent: "center",
}}
>
<Pagination
current={articles.current}
total={articles.total}
pageSize={20}
showSizeChanger={false}
itemRender={(page, type, el) => {
if (!page) {
return el;
}
if (page === 1) {
return <Link to={"/timeline"}>1</Link>;
}
return <Link to={"/timeline/" + page}>{page}</Link>;
}}
/>
</div>
</div>
</Layout>
);
}
export default Timeline;