mirror of
https://github.com/sendevia/website.git
synced 2026-03-06 07:40:50 +08:00
Compare commits
7 Commits
26.2.25(29
...
26.2.28(30
| Author | SHA1 | Date | |
|---|---|---|---|
| 0493426eaa | |||
| 042342f923 | |||
| 13548b222e | |||
| adb804f249 | |||
| d91f8b90aa | |||
| 69d117152a | |||
| b6e7649a4f |
@@ -12,7 +12,8 @@ import { footnote } from "@mdit/plugin-footnote";
|
||||
import { tasklist } from "@mdit/plugin-tasklist";
|
||||
// https://mdit-plugins.github.io/img-mark.html
|
||||
import { imgMark } from "@mdit/plugin-img-mark";
|
||||
import { wrapHeadingsAsSections } from "./theme/utils/sectionWrapper";
|
||||
import { sectionWrapper } from "./theme/utils/mdSectionWrapper";
|
||||
import { table } from "./theme/utils/mdTable";
|
||||
|
||||
export default defineConfig({
|
||||
base: "/",
|
||||
@@ -42,9 +43,10 @@ export default defineConfig({
|
||||
config(md) {
|
||||
md.use(align);
|
||||
md.use(footnote);
|
||||
md.use(wrapHeadingsAsSections);
|
||||
md.use(sectionWrapper);
|
||||
md.use(tasklist, { label: true });
|
||||
md.use(imgMark);
|
||||
md.use(table);
|
||||
},
|
||||
image: {
|
||||
lazyLoading: true,
|
||||
|
||||
@@ -27,12 +27,6 @@ const siteVersion = theme.value.siteVersion;
|
||||
>
|
||||
</div>
|
||||
<div class="beian-info">
|
||||
<div class="beian-gongan">
|
||||
<img src="/assets/images/beian.webp" loading="eager" />
|
||||
<a href="https://beian.mps.gov.cn/#/query/webSearch?code=23020002230215" target="_blank"
|
||||
>黑公网安备23020002230215</a
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://beian.miit.gov.cn/" target="_blank">黑ICP备2024016516号-1</a>
|
||||
</div>
|
||||
|
||||
@@ -66,6 +66,10 @@ table {
|
||||
:is(td, th) {
|
||||
border: 1px solid var(--md-sys-color-outline);
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
code {
|
||||
padding-block: 0px !important;
|
||||
}
|
||||
|
||||
@@ -4,12 +4,7 @@ import type MarkdownIt from "markdown-it";
|
||||
* 将连续的标题块包裹为独立的 section(headline-block),便于样式与交互处理
|
||||
* @param mdit - MarkdownIt 实例
|
||||
*/
|
||||
export function wrapHeadingsAsSections(mdit: MarkdownIt): void {
|
||||
if (!mdit || !mdit.core || !mdit.core.ruler) {
|
||||
console.warn("Invalid MarkdownIt instance provided");
|
||||
return;
|
||||
}
|
||||
|
||||
export function sectionWrapper(mdit: MarkdownIt): void {
|
||||
mdit.core.ruler.before("inline", "group_sections", (state) => {
|
||||
const tokens = state.tokens;
|
||||
const newTokens: any[] = [];
|
||||
131
.vitepress/theme/utils/mdTable.ts
Normal file
131
.vitepress/theme/utils/mdTable.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
import type MarkdownIt from "markdown-it";
|
||||
type StateBlock = any;
|
||||
|
||||
/**
|
||||
* 一个简易的 markdown-it 表格插件
|
||||
* @param mdit MarkdownIt 实例
|
||||
*/
|
||||
export const table = (mdit: MarkdownIt) => {
|
||||
// 禁用原有的表格规则
|
||||
mdit.disable("table");
|
||||
|
||||
/** 表格块解析规则 */
|
||||
const tableBlock = (state: StateBlock, startLine: number, endLine: number, silent: boolean): boolean => {
|
||||
let nextLine = startLine;
|
||||
let lineText = state.getLines(nextLine, nextLine + 1, 0, false).trim();
|
||||
|
||||
// 检查是否包含表格分隔符
|
||||
if (!lineText.includes("|")) return false;
|
||||
|
||||
const rows: string[] = [];
|
||||
while (nextLine < endLine) {
|
||||
lineText = state.getLines(nextLine, nextLine + 1, 0, false).trim();
|
||||
if (!lineText.includes("|") && lineText !== "") break;
|
||||
if (lineText !== "") rows.push(lineText);
|
||||
nextLine++;
|
||||
}
|
||||
|
||||
if (rows.length < 1) return false;
|
||||
|
||||
if (silent) return true;
|
||||
|
||||
const token = state.push("simple_table", "table", 0);
|
||||
token.map = [startLine, nextLine];
|
||||
token.content = rows.join("\n");
|
||||
|
||||
state.line = nextLine;
|
||||
return true;
|
||||
};
|
||||
|
||||
mdit.block.ruler.before("paragraph", "simple_table", tableBlock);
|
||||
|
||||
// 渲染逻辑
|
||||
mdit.renderer.rules.simple_table = (tokens, idx) => {
|
||||
const content = tokens[idx].content;
|
||||
const lines = content.split("\n").filter((l) => l.trim() !== "");
|
||||
if (lines.length === 0) return "";
|
||||
|
||||
let html = "<table>\n";
|
||||
|
||||
// 检查第二行是否是分隔行
|
||||
const hasSeparator = lines.length > 1 && /^[|:\-\s]+$/.test(lines[1]) && lines[1].includes("-");
|
||||
|
||||
let headerLines: string[] = [];
|
||||
let bodyLines: string[] = [];
|
||||
|
||||
if (hasSeparator) {
|
||||
headerLines = [lines[0]];
|
||||
bodyLines = lines.slice(2);
|
||||
} else {
|
||||
// 如果没有分隔行,用第一行作为表头
|
||||
headerLines = [lines[0]];
|
||||
bodyLines = lines.slice(1);
|
||||
}
|
||||
|
||||
// 分割单元格并清理首尾空的装饰管线
|
||||
const getCells = (line: string) => {
|
||||
const cells = line.split("|");
|
||||
if (cells.length > 0 && cells[0].trim() === "") cells.shift();
|
||||
if (cells.length > 0 && cells[cells.length - 1].trim() === "") cells.pop();
|
||||
return cells.map((c) => c.trim());
|
||||
};
|
||||
|
||||
// 解析单元格中的属性
|
||||
const parseAttributes = (cellContent: string) => {
|
||||
const attrRegex = /\{([^{}]+)\}\s*$/;
|
||||
const match = cellContent.match(attrRegex);
|
||||
const attrs: Record<string, string> = {};
|
||||
let cleanedContent = cellContent;
|
||||
|
||||
if (match) {
|
||||
cleanedContent = cellContent.replace(attrRegex, "").trim();
|
||||
const attrString = match[1];
|
||||
const parts = attrString.split(/\s+/);
|
||||
parts.forEach((part) => {
|
||||
const [key, value] = part.split("=");
|
||||
if (key && (key === "colspan" || key === "rowspan")) {
|
||||
attrs[key] = value || "1";
|
||||
}
|
||||
});
|
||||
}
|
||||
return { cleanedContent, attrs };
|
||||
};
|
||||
|
||||
// 渲染表头
|
||||
if (headerLines.length > 0) {
|
||||
html += "<thead>\n";
|
||||
headerLines.forEach((line) => {
|
||||
html += "<tr>\n";
|
||||
getCells(line).forEach((cell) => {
|
||||
const { cleanedContent, attrs } = parseAttributes(cell);
|
||||
const attrStr = Object.entries(attrs)
|
||||
.map(([k, v]) => ` ${k}="${v}"`)
|
||||
.join("");
|
||||
html += `<th${attrStr}>${mdit.renderInline(cleanedContent)}</th>\n`;
|
||||
});
|
||||
html += "</tr>\n";
|
||||
});
|
||||
html += "</thead>\n";
|
||||
}
|
||||
|
||||
// 渲染表体
|
||||
if (bodyLines.length > 0) {
|
||||
html += "<tbody>\n";
|
||||
bodyLines.forEach((line) => {
|
||||
html += "<tr>\n";
|
||||
getCells(line).forEach((cell) => {
|
||||
const { cleanedContent, attrs } = parseAttributes(cell);
|
||||
const attrStr = Object.entries(attrs)
|
||||
.map(([k, v]) => ` ${k}="${v}"`)
|
||||
.join("");
|
||||
html += `<td${attrStr}>${mdit.renderInline(cleanedContent)}</td>\n`;
|
||||
});
|
||||
html += "</tr>\n";
|
||||
});
|
||||
html += "</tbody>\n";
|
||||
}
|
||||
|
||||
html += "</table>";
|
||||
return html;
|
||||
};
|
||||
};
|
||||
11
Dockerfile
11
Dockerfile
@@ -1,11 +0,0 @@
|
||||
FROM node:lts-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY . /app
|
||||
|
||||
RUN npm install
|
||||
|
||||
EXPOSE 4173
|
||||
|
||||
CMD ["npm", "run", "docs:preview"]
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "26.2.25(298)",
|
||||
"version": "26.2.28(305)",
|
||||
"scripts": {
|
||||
"update-version": "bash ./scripts/update-version.sh",
|
||||
"docs:dev": "vitepress dev",
|
||||
@@ -17,6 +17,7 @@
|
||||
"@mdit/plugin-footnote": "^0.23.0",
|
||||
"@mdit/plugin-img-mark": "^0.23.0",
|
||||
"@mdit/plugin-tasklist": "^0.23.0",
|
||||
"@waline/client": "^3.13.0",
|
||||
"markdown-it-anchor": "^9.2.0",
|
||||
"sass-embedded": "^1.97.3",
|
||||
"vitepress": "^2.0.0-alpha.16",
|
||||
|
||||
@@ -59,17 +59,17 @@ external_links:
|
||||
|
||||
下面是所有头信息的详解:
|
||||
|
||||
| name | | description | type | default |
|
||||
| ------------ | ------------- | ---------------- | ------- | --------------------------- |
|
||||
| 文章相关 | title | 文章标题 | text | 使用 `_config.yml` 中的配置 |
|
||||
| ^^ | description | 文章简介 | ^^ | ^^ |
|
||||
| ^^ | author | 文章作者 | ^^ | ^^ |
|
||||
| ^^ | color | 文章主题颜色 | ^^ | ^^ |
|
||||
| ^^ | impression | 文章头图 | ^^ | ^^ |
|
||||
| ^^ | categories | 目录分类 | list | 未定义 |
|
||||
| ^^ | tags | 文章标签 | ^^ | ^^ |
|
||||
| ^^ | published | 是否发布文章 | boolean | true |
|
||||
| ^^ | toc | 是否生成文章目录 | ^^ | true |
|
||||
| 页面导航相关 | segment_icon | 导航栏中的图标 | text | - |
|
||||
| ^^ | segment_title | 导航栏中的标题 | ^^ | ^^ |
|
||||
| ^^ | navigation | 是否在导航中显示 | boolean | ^^ |
|
||||
| name { colspan=2 } | | description | type | default |
|
||||
| -------------------------- | ------------- | ---------------- | --------------------- | ----------------------------------------- |
|
||||
| 文章相关 { rowspan=9 } | title | 文章标题 | text { rowspan=5 } | 使用 `_config.yml` 中的配置 { rowspan=5 } |
|
||||
| | description | 文章简介 | | |
|
||||
| | author | 文章作者 | | |
|
||||
| | color | 文章主题颜色 | | |
|
||||
| | impression | 文章头图 | | |
|
||||
| | categories | 目录分类 | list { rowspan=2 } | 未定义 { rowspan=2 } |
|
||||
| | tags | 文章标签 | | |
|
||||
| | published | 是否发布文章 | boolean { rowspan=2 } | true { rowspan=2 } |
|
||||
| | toc | 是否生成文章目录 | | |
|
||||
| 页面导航相关 { rowspan=3 } | segment_icon | 导航栏中的图标 | text { rowspan=2 } | - { rowspan=3 } |
|
||||
| | segment_title | 导航栏中的标题 | | |
|
||||
| | navigation | 是否在导航中显示 | boolean | |
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
Reference in New Issue
Block a user