工程知识Markdown排版

博客 Markdown 样式

2025-01-019 分钟

本文展示博客系统支持的所有 Markdown 格式,撰写新文章时可对照参考。


一、标题

正文可以直接使用 # 作为一级标题,## 作为二级标题(虽然页面级标题会独占 <h1> 标签,但正文中的 # 等标题会被渲染器顺延下调一级转为 <h2> 等标签并适配字号,符合 SEO 规范且不影响写作习惯)。

这是三级标题(###)


二、文字样式

  • 粗体:**粗体**
  • 斜体:*斜体*
  • 删除线:~~删除线~~
  • 粗体与 嵌套斜体 组合
  • 行内代码:`行内代码`

三、段落与换行

直接空一行即可产生新段落。

这是第二个段落。段落内的文字默认 leading-relaxed 行高,阅读体验舒适。


四、列表

无序列表

  • 第一项
  • 第二项
    • 嵌套子项 A
    • 嵌套子项 B
  • 第三项

有序列表

  1. 第一步:安装依赖
  2. 第二步:启动开发服务器
  3. 第三步:编写文章

任务列表(GFM)

  • 已完成的任务
  • 未完成的任务
  • 又一个已完成的任务

五、引用块

这是一段引用。引用块会显示左侧竖线和斜体样式,适合摘引原文或标注重点结论。

引用也可以多行。

继续引用内容。


六、代码块

代码块分为两类:真实代码块和展示型文本块。

  • 真实代码块:使用 python、typescript、bash、json 等语言标识,会使用黑色背景和语法高亮(基于 highlight.js,主题 github-dark)。
  • 展示型文本块:使用 text、txt、plain、plaintext 或不写语言标识,会使用柔和背景,适合展示流程、配置项、URL、命令输出或字段说明。

展示型文本块

当代码块只是为了展示信息,而不是强调“代码”本身时,推荐使用 text:

```text
本地图片 -> PicGo -> Cloudflare R2 Bucket -> 自定义域名访问
```

渲染效果如下:

本地图片 -> PicGo -> Cloudflare R2 Bucket -> 自定义域名访问

配置项、字段映射、链接样例也适合使用 text:

上传工具:PicGo
对象存储:Cloudflare R2
Bucket:blog-fig
访问域名:https://img.example.com
期望链接:https://img.example.com/img/xxx.jpg

真实代码块

写代码示例时请标注具体语言名,这样会启用黑底代码块和语法高亮。

Python

import torch
import torch.nn as nn

class MLP(nn.Module):
    def __init__(self, in_dim: int, out_dim: int):
        super().__init__()
        self.fc = nn.Linear(in_dim, out_dim)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        return torch.relu(self.fc(x))

model = MLP(128, 10)
print(model)

TypeScript

interface Post {
  slug: string;
  title: string;
  date: string;
  tags: string[];
}

const getLatest = (posts: Post[]): Post =>
  posts.sort((a, b) => b.date.localeCompare(a.date))[0];

Bash

# 安装依赖并启动
cd zcyeee.github.io/site
npm install
npm run dev

JSON

{
  "name": "zcyeee-site",
  "version": "0.0.0",
  "scripts": {
    "dev": "vite",
    "build": "tsc -b && vite build"
  }
}

七、数学公式

基于 KaTeX 渲染,支持行内公式和块级公式。

行内公式

爱因斯坦的质能方程 E=mc2E = mc^2 中,cc 为光速,约为 3×108 m/s3 \times 10^8 \text{ m/s}。

注意力机制的缩放点积为 Attention(Q,K,V)=softmax ⁣(QKTdk)V\text{Attention}(Q, K, V) = \text{softmax}\!\left(\frac{QK^T}{\sqrt{d_k}}\right)V。

块级公式

贝叶斯定理:

P(A∣B)=P(B∣A) P(A)P(B)P(A \mid B) = \frac{P(B \mid A)\, P(A)}{P(B)}

高斯分布的概率密度函数:

f(x)=1σ2πexp⁡ ⁣(−(x−μ)22σ2)f(x) = \frac{1}{\sigma\sqrt{2\pi}} \exp\!\left(-\frac{(x-\mu)^2}{2\sigma^2}\right)

多元微积分中的梯度下降更新规则:

θt+1=θt−η∇θL(θt)\theta_{t+1} = \theta_t - \eta \nabla_{\theta} \mathcal{L}(\theta_t)

矩阵求导链式法则(以 Softmax 为例):

∂ℓ∂zi=∑j∂ℓ∂pj⋅pj(δij−pi)\frac{\partial \ell}{\partial z_i} = \sum_j \frac{\partial \ell}{\partial p_j} \cdot p_j(\delta_{ij} - p_i)

八、表格

支持 GFM 扩展表格,可设置对齐方式。

插件功能备注
remark-gfmGFM 扩展(表格、任务列表、删除线)默认启用
remark-math解析 $...$ 和 $$...$$配合 rehype-katex
rehype-katex将数学公式渲染为 HTML需引入 katex CSS
rehype-highlight代码块语法高亮主题:github-dark

带对齐的表格

左对齐居中对齐右对齐
Apple苹果¥5
Banana香蕉¥3
Cherry樱桃¥18

九、链接与图片

超链接

访问 React 官网(在新标签页打开,带 noopener noreferrer)

图片

图片支持懒加载,alt 文字会作为图注显示在图片下方:

来自 Unsplash 的示例图片:山脉风景来自 Unsplash 的示例图片:山脉风景


十、分割线

使用 --- 插入分割线,渲染为 <hr>:


十一、可折叠块

使用 HTML 原生的 <details> / <summary> 标签实现,可在 Markdown 中直接书写:

点击展开:什么是 Transformer?

Transformer 是一种基于自注意力机制的深度学习架构,由 Vaswani 等人在 2017 年的论文 Attention Is All You Need 中提出。

核心公式:

Attention(Q,K,V)=softmax ⁣(QKTdk)V\text{Attention}(Q, K, V) = \text{softmax}\!\left(\frac{QK^T}{\sqrt{d_k}}\right)V

它完全抛弃了 RNN 的顺序计算,支持并行训练,现已成为 NLP、CV 等领域的主流架构。

点击展开:折叠代码示例
def attention(Q, K, V):
    import math
    d_k = Q.shape[-1]
    scores = Q @ K.T / math.sqrt(d_k)
    weights = softmax(scores)
    return weights @ V
点击展开:折叠表格示例
模型参数量发布年份
GPT-21.5B2019
GPT-3175B2020
LLaMA 270B2023

折叠块内支持所有 Markdown 语法,包括公式、代码块、表格等。注意 <details> 与内容之间需要空一行,否则内部 Markdown 可能不会被正确解析。


十二、内联 SVG 图表

流程图、结构图可以把 SVG 直接写在正文里(渲染器启用了 rehype-raw,原始 HTML 会被放行)。相比外链图片,它矢量清晰、能跟随深浅色主题、也不额外发请求。

<div style="overflow-x:auto">
<svg width="100%" style="max-width:520px;min-width:460px" viewBox="0 0 520 92" role="img">
<title>三段式推理流程</title>
<desc>输入经过模型处理后产生输出。</desc>
<defs>
<marker id="ar" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M2 1L8 5L2 9" fill="none" stroke="#888780" stroke-width="1.5" stroke-linecap="round"/>
</marker>
</defs>
<rect x="54" y="12" width="100" height="44" rx="8" fill="#EEEDFE" stroke="#534AB7" stroke-width="0.5"/>
<text x="104" y="34" font-size="15" text-anchor="middle" dominant-baseline="central" fill="#26215C">输入</text>
<path d="M158 34 L204 34" fill="none" stroke="#888780" stroke-width="1.5" marker-end="url(#ar)"/>
<rect x="210" y="12" width="100" height="44" rx="8" fill="#E6F1FB" stroke="#185FA5" stroke-width="0.5"/>
<text x="260" y="34" font-size="15" text-anchor="middle" dominant-baseline="central" fill="#042C53">模型</text>
<path d="M314 34 L360 34" fill="none" stroke="#888780" stroke-width="1.5" marker-end="url(#ar)"/>
<rect x="366" y="12" width="100" height="44" rx="8" fill="#E1F5EE" stroke="#0F6E56" stroke-width="0.5"/>
<text x="416" y="34" font-size="15" text-anchor="middle" dominant-baseline="central" fill="#04342C">输出</text>
<text x="54" y="80" font-size="13.5" fill="currentColor" opacity="0.65">说明文字用 currentColor,会跟随主题翻转</text>
</svg>
</div>

渲染效果如下:

三段式推理流程 输入经过模型处理后产生输出。 输入 模型 输出 说明文字用 currentColor,会跟随主题翻转

1. 整段 SVG 不能有空行

这是最容易踩的一条,而且规则和上一节的 <details> 正好相反:<details> 需要与内容空一行,SVG 内部则一个空行都不能有。

原因在 CommonMark 的分块规则里:svg 不属于 block-level 标签白名单,所以 <svg> 只能触发 type-7 HTML 块,而这种块遇到第一个空行就终止。后面的内容会被重新按 Markdown 解析、包进 <p>,而 HTML 解析器不允许 <svg> 里出现 <p>,于是那些图形元素被整体踢出 SVG。

结果是图只剩一个空框,所有内容退化成竖排文本。想分组请用缩进或注释,不要用空行。

2. 字号会被 viewBox 缩放

font-size 的单位是 viewBox 坐标,不是像素。实际字号 = 声明值 × (渲染宽度 ÷ viewBox 宽度)。

如果只写 width="100%",正文栏 910px 配 680 单位的 viewBox 会把所有字放大 1.34 倍;手机上又会缩到 0.52 倍。所以推荐固定套用上面例子里的写法:

外层 <div style="overflow-x:auto">      窄屏转为横向滚动
内层 style="max-width:{viewBox 宽度}"   缩放系数上限锁定为 1,声明值 = 实际像素
     style="min-width:{可读下限}"       防止窄屏缩到看不清

max-width 取和 viewBox 宽度相同的值,字号就所见即所得。

3. 裸文字和线条用 currentColor

站点有深色模式,背景会从近白切到近黑。画在背景上的文字若写死深色(如 fill="#2C2C2A"),深色模式下对比度只有 1.2:1,基本看不见。

  • 背景上的文字、分隔线:用 fill="currentColor" / stroke="currentColor",它会继承正文颜色并跟随主题翻转,弱化就配 opacity
  • 色块内部的文字:可以写死颜色,因为它落在自己的浅色底上,两种主题下都清晰

4. 无障碍与居中

加上 role="img" 并配 <title>、<desc>:

  • role="img" 让读屏软件把整张图当一个图片,否则图里每个 <text> 会被当成互不相干的文本碎片逐个念出来
  • <title> 作为图片名,桌面端鼠标悬停时还会显示为 tooltip
  • <desc> 作为详细描述

居中不用管,index.css 里已有 .prose svg[role="img"] 规则自动处理。

5. 几个不能用的写法

写法问题
class="xxx" 配 CSS正文里的 class 没有对应样式,Tailwind 的 content 配置也不扫 .md,须改用内联 style 或原生属性
stroke="context-stroke"Safari 与 iOS Safari 不支持,箭头会整个消失,请写死颜色
text-align:center 居中在 overflow-x:auto 容器里内容溢出时,左侧会被裁掉且滚不回去
写死 height="..."有 viewBox 时不写 height,高宽比才会自动保持;写死会在窄屏把图压扁

十三、注意事项

  1. 随意使用 # 标题:不用再避开一次标题啦!由于渲染层会自动适配级联下调(将 # 转为 <h2>,## 转为 <h3> 等),请放心从 # 起步写作。
  2. 数学公式:行内用 $...$,块级用 $$...$$,注意美元符号不要有多余空格
  3. 代码块语言标识:真实代码请写准确语言名(python、typescript、bash 等)以启用黑底高亮;展示流程、配置、URL 等普通文本时请用 text / plaintext
  4. 图片:推荐使用外链 CDN,alt 会作为图注展示
  5. 内联 SVG:整段不能出现空行;font-size 会被 viewBox 缩放,用 max-width 锁定;画在背景上的文字用 currentColor 以适配深色模式

参考资料

  1. CommonMark 规范
  2. GitHub Flavored Markdown 规范
  3. KaTeX 支持的函数列表
  4. highlight.js 支持的语言列表
Markdown排版