Add custom font styles and theme enhancements
- Created a new CSS file for font imports and defined font families for base, mono, strong, em, and h1 elements. - Added a new JavaScript file to extend the default VitePress theme, incorporating a custom layout and a Vue component for enhanced functionality. - Integrated Mermaid diagram support and included the necessary styles for it.
This commit is contained in:
158
openwiki/config.mts
Normal file
158
openwiki/config.mts
Normal file
@@ -0,0 +1,158 @@
|
||||
import { defineConfig } from "vitepress";
|
||||
import { vitepressBeautifulMermaid } from "v-beautiful-mermaid";
|
||||
import { readdirSync, statSync, readFileSync } from "fs";
|
||||
import { join } from "path";
|
||||
import { load } from "js-yaml";
|
||||
|
||||
const siteConfig = load(
|
||||
readFileSync(join(__dirname, "../config.yaml"), "utf8"),
|
||||
) as {
|
||||
title?: string;
|
||||
description?: string;
|
||||
logo?: string;
|
||||
siteTitle?: false;
|
||||
appearance?: false;
|
||||
nav?: { text: string; link: string }[];
|
||||
footer?: { message: string; copyright: string };
|
||||
};
|
||||
|
||||
interface SidebarItem {
|
||||
text: string;
|
||||
link?: string;
|
||||
items?: SidebarItem[];
|
||||
}
|
||||
|
||||
function isDirectory(path: string): boolean {
|
||||
try {
|
||||
return statSync(path).isDirectory();
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function buildSidebarTree(root: string, basePath: string = ""): SidebarItem[] {
|
||||
const items: SidebarItem[] = [];
|
||||
const entries = readdirSync(root);
|
||||
|
||||
// Separate files and directories
|
||||
const files: string[] = [];
|
||||
const dirs: string[] = [];
|
||||
|
||||
for (const entry of entries) {
|
||||
if (entry === "index.md") continue;
|
||||
const fullPath = join(root, entry);
|
||||
if (isDirectory(fullPath)) {
|
||||
dirs.push(entry);
|
||||
} else if (entry.endsWith(".md")) {
|
||||
files.push(entry);
|
||||
}
|
||||
}
|
||||
|
||||
// Add files first
|
||||
for (const f of files.sort()) {
|
||||
const name = f.replace(/\.md$/, "");
|
||||
const linkPath = `/${root}/${name}`;
|
||||
items.push({
|
||||
text: name,
|
||||
link: linkPath,
|
||||
});
|
||||
}
|
||||
|
||||
// Add directories as submenus
|
||||
for (const d of dirs.sort()) {
|
||||
const subRoot = join(root, d);
|
||||
const subBasePath = basePath ? `${basePath}/${d}` : d;
|
||||
const subItems = buildSidebarTree(subRoot, subBasePath);
|
||||
if (subItems.length > 0) {
|
||||
items.push({
|
||||
text: d,
|
||||
items: subItems,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
function buildSidebarItems(root: string): SidebarItem[] {
|
||||
return buildSidebarTree(root);
|
||||
}
|
||||
|
||||
const sidebar = {
|
||||
"/": [
|
||||
{
|
||||
items: [
|
||||
{
|
||||
text: "主页",
|
||||
link: "/",
|
||||
},
|
||||
{
|
||||
text: "概览",
|
||||
link: "/overview",
|
||||
},
|
||||
{
|
||||
text: "变更日志",
|
||||
link: "/log",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
items: [{}],
|
||||
},
|
||||
],
|
||||
"/docs/": [
|
||||
{
|
||||
text: "记录",
|
||||
items: [{}],
|
||||
},
|
||||
{
|
||||
text: "工作空间",
|
||||
items: [{}],
|
||||
},
|
||||
],
|
||||
"/sources/": [
|
||||
{
|
||||
items: [{}],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
sidebar["/docs/"][0].items = buildSidebarItems("docs/notes");
|
||||
sidebar["/docs/"][1].items = buildSidebarItems("docs/subspaces");
|
||||
sidebar["/sources/"][0].items = buildSidebarItems("sources");
|
||||
sidebar["/"][1].items = buildSidebarItems("nodes");
|
||||
|
||||
// https://vitepress.dev/reference/site-config
|
||||
export default defineConfig({
|
||||
title: siteConfig.title,
|
||||
description: siteConfig.description,
|
||||
lang: "zh-CN",
|
||||
base: "/", // Replace with your repository name if deploying to GitHub Pages
|
||||
srcDir: ".",
|
||||
ignoreDeadLinks: true,
|
||||
appearance: siteConfig.appearance,
|
||||
themeConfig: {
|
||||
logo: siteConfig.logo,
|
||||
siteTitle: siteConfig.siteTitle,
|
||||
nav: [
|
||||
{ text: "知识库", link: "/overview" },
|
||||
{ text: "资料库", link: "/sources/" },
|
||||
{ text: "文档", link: "/docs/" },
|
||||
],
|
||||
sidebar,
|
||||
footer: siteConfig.footer,
|
||||
search: {
|
||||
provider: "local",
|
||||
},
|
||||
},
|
||||
markdown: {
|
||||
config: (md) => {
|
||||
md.use(vitepressBeautifulMermaid, {
|
||||
colorMode: "auto",
|
||||
renderOptions: {
|
||||
font: "LXGW WenKai Mono",
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
15
openwiki/package.json
Normal file
15
openwiki/package.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/node": "^25.6.0",
|
||||
"js-yaml": "^4.1.1",
|
||||
"v-beautiful-mermaid": "^0.0.3",
|
||||
"vitepress": "2.0.0-alpha.17"
|
||||
},
|
||||
"scripts": {
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
"dev": "vitepress dev",
|
||||
"build": "vitepress build",
|
||||
"preview": "vitepress preview"
|
||||
}
|
||||
}
|
||||
1967
openwiki/pnpm-lock.yaml
generated
Normal file
1967
openwiki/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
21
openwiki/templates/node.md
Normal file
21
openwiki/templates/node.md
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
name: "{知识点}"
|
||||
description: "{知识点描述}"
|
||||
aliases: # 别名、同义词、缩写、全名、翻译名等
|
||||
- {别称-1}
|
||||
- {别称-2}
|
||||
tags: # 仅分类标签,如:解剖、蛋白、现象、机制、人物、公司、产品等
|
||||
- {分类-1}
|
||||
- ...
|
||||
created_at: {YYYY-MM-DD} # 页面创建时间
|
||||
updated_at: {YYYY-MM-DD} # 页面更新时间
|
||||
---
|
||||
|
||||
# {知识点}
|
||||
|
||||
<!-- 正文内容 -->
|
||||
|
||||
## 相关资料
|
||||
|
||||
- [{资料摘要}](../sources/{资料摘要}.md)
|
||||
- ...
|
||||
21
openwiki/templates/overview.md
Normal file
21
openwiki/templates/overview.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# 知识库概览
|
||||
|
||||
{知识库描述}
|
||||
|
||||
{知识结构逻辑}
|
||||
|
||||
## 知识地图
|
||||
|
||||
{mermaid流程图}
|
||||
|
||||
<!-- 图表中出现节点的描述 -->
|
||||
|
||||
- **节点-1**
|
||||
- {描述-1}
|
||||
- {描述-2}
|
||||
- ...
|
||||
|
||||
- **节点-2**
|
||||
- {描述-1}
|
||||
- {描述-2}
|
||||
- ...
|
||||
22
openwiki/templates/source.md
Normal file
22
openwiki/templates/source.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
title: "{原始标题}" # 原始资料的原标题,不翻译。如:论文标题、网页文章标题
|
||||
abstract: "{原始摘要}" # 原始资料的原摘要、总结,不翻译。如:论文摘要、网页文章总结
|
||||
source: {原始地址} # 原始资料的文件路径或网址,并确保链接正常
|
||||
tags: # 仅分类标签,如:论文、专利、会议等
|
||||
- {分类-1}
|
||||
- ...
|
||||
created_at: {YYYY-MM-DD} # 页面创建时间
|
||||
updated_at: {YYYY-MM-DD} # 页面更新时间
|
||||
---
|
||||
|
||||
# {原始标题的中文翻译}
|
||||
|
||||
{原始摘要的中文翻译}
|
||||
|
||||
## 关键结论
|
||||
|
||||
- {结论-1}
|
||||
- {结论-2}
|
||||
- ...
|
||||
|
||||
<!-- 正文内容 -->
|
||||
22
openwiki/theme/Layout.vue
Normal file
22
openwiki/theme/Layout.vue
Normal file
@@ -0,0 +1,22 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useData } from 'vitepress'
|
||||
import DefaultTheme from 'vitepress/theme-without-fonts'
|
||||
import DocTags from './components/DocTags.vue'
|
||||
import DocMetaEx from './components/DocMetaEx.vue'
|
||||
|
||||
const { frontmatter } = useData()
|
||||
const tags = computed(() => frontmatter.value?.tags ?? [])
|
||||
const hasTags = computed(() => tags.value.length > 0)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DefaultTheme.Layout>
|
||||
<template #doc-before>
|
||||
<DocTags v-if="hasTags" style="margin-bottom: 24px;" />
|
||||
</template>
|
||||
<template #aside-outline-after>
|
||||
<DocMetaEx style="margin-top: 24px; padding-left: 16px;"/>
|
||||
</template>
|
||||
</DefaultTheme.Layout>
|
||||
</template>
|
||||
50
openwiki/theme/components/DocMetaEx.vue
Normal file
50
openwiki/theme/components/DocMetaEx.vue
Normal file
@@ -0,0 +1,50 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { useData } from "vitepress";
|
||||
|
||||
const { frontmatter } = useData();
|
||||
|
||||
const source = computed(() => frontmatter.value?.source ?? null);
|
||||
const title = computed(() => frontmatter.value?.title ?? null);
|
||||
const abstract = computed(() => frontmatter.value?.abstract ?? null);
|
||||
|
||||
const hasExtended = computed(
|
||||
() => source.value || title.value || abstract.value,
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="hasExtended" class="doc-meta-ex">
|
||||
<div v-if="title" class="doc-meta-title">标题:{{ title }}</div>
|
||||
<div v-if="source" class="doc-meta-source">
|
||||
来源:<a :href="source" target="_blank" rel="noopener noreferrer">{{
|
||||
source
|
||||
}}</a>
|
||||
</div>
|
||||
<div v-if="abstract" class="doc-meta-abstract">摘要:{{ abstract }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.doc-meta-ex {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
line-height: 1.8;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.doc-meta-source {
|
||||
font-size: 12px;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.doc-meta-title {
|
||||
font-size: 12px;
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.doc-meta-abstract {
|
||||
font-size: 12px;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
</style>
|
||||
90
openwiki/theme/components/DocTags.vue
Normal file
90
openwiki/theme/components/DocTags.vue
Normal file
@@ -0,0 +1,90 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { useData } from "vitepress";
|
||||
|
||||
const { frontmatter } = useData();
|
||||
|
||||
const tags = computed(() => frontmatter.value?.tags ?? []);
|
||||
const aliases = computed(() => frontmatter.value?.aliases ?? []);
|
||||
const createdAt = computed(() => frontmatter.value?.created_at ?? null);
|
||||
const updatedAt = computed(() => frontmatter.value?.updated_at ?? null);
|
||||
const hasTags = computed(() => tags.value.length > 0);
|
||||
const hasTime = computed(() => createdAt.value || updatedAt.value);
|
||||
|
||||
function formatDate(date: string | null): string {
|
||||
if (!date) return "";
|
||||
const d = new Date(date);
|
||||
if (isNaN(d.getTime())) return date as string;
|
||||
return d.toLocaleDateString("zh-CN", {
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="doc-tags-wrapper">
|
||||
<div v-if="hasTime" class="doc-meta-time">
|
||||
<span v-if="createdAt">创建于 {{ formatDate(createdAt) }}</span>
|
||||
<span v-if="createdAt && updatedAt"> · </span>
|
||||
<span v-if="updatedAt">更新于 {{ formatDate(updatedAt) }}</span>
|
||||
</div>
|
||||
<div v-if="hasTags" class="doc-tags">
|
||||
<span v-for="tag in tags" :key="tag" class="doc-tag"># {{ tag }}</span>
|
||||
</div>
|
||||
<div v-if="aliases.length > 0" class="doc-meta-aliases">
|
||||
<span v-for="alias in aliases" :key="alias" class="doc-meta-alias">{{
|
||||
alias
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.doc-tags-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.doc-meta-time {
|
||||
font-size: 12px;
|
||||
color: var(--vp-c-text-3);
|
||||
}
|
||||
|
||||
.doc-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.doc-meta-aliases {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.doc-meta-alias {
|
||||
display: inline-block;
|
||||
padding: 0 10px;
|
||||
line-height: 22px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
border-radius: 12px;
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
color: var(--vp-c-brand-1);
|
||||
border: 1px solid var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
.doc-tag {
|
||||
display: inline-block;
|
||||
padding: 0 10px;
|
||||
line-height: 22px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
border-radius: 12px;
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
</style>
|
||||
1454
openwiki/theme/components/Viewer.vue
Normal file
1454
openwiki/theme/components/Viewer.vue
Normal file
File diff suppressed because it is too large
Load Diff
22
openwiki/theme/fonts.css
Normal file
22
openwiki/theme/fonts.css
Normal file
@@ -0,0 +1,22 @@
|
||||
@import url("https://fontsapi.zeoseven.com/292/main/result.css");
|
||||
@import url("https://fontsapi.zeoseven.com/292/light/result.css");
|
||||
@import url("https://fontsapi.zeoseven.com/293/main/result.css");
|
||||
@import url("https://fontsapi.zeoseven.com/2/main/result.css");
|
||||
@import url("https://fontsapi.zeoseven.com/147/main/result.css");
|
||||
|
||||
:root {
|
||||
--vp-font-family-base: "LXGW WenKai";
|
||||
--vp-font-family-mono: "LXGW WenKai Mono";
|
||||
}
|
||||
|
||||
strong {
|
||||
font-family: "LXGW ZhenKai GB";
|
||||
}
|
||||
|
||||
em {
|
||||
font-family: "LXGW WenKai Light";
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: "JiangChengLvDongSong";
|
||||
}
|
||||
16
openwiki/theme/index.js
Normal file
16
openwiki/theme/index.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import DefaultTheme from "vitepress/theme-without-fonts";
|
||||
import { installMermaid } from "v-beautiful-mermaid/client";
|
||||
import Viewer from "./components/Viewer.vue";
|
||||
import Layout from "./Layout.vue";
|
||||
import "v-beautiful-mermaid/style.css";
|
||||
import "./fonts.css";
|
||||
|
||||
/** @type {import('vitepress').Theme} */
|
||||
export default {
|
||||
extends: DefaultTheme,
|
||||
Layout,
|
||||
enhanceApp({ app }) {
|
||||
installMermaid(app);
|
||||
app.component("Viewer", Viewer);
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user