代码块是怎么高亮的
代码高亮是在构建时完成的。Astro 内置了 Shiki,你写 ```js 这样的围栏,构建后拿到的就是一段已经上好色的 HTML——浏览器不需要下载任何高亮库,也就不存在闪烁和延迟。
双主题
因为站点支持深浅色切换,代码块也配了两套配色:
// astro.config.mjs
markdown: {
shikiConfig: {
themes: { light: 'github-light', dark: 'github-dark-default' },
defaultColor: false,
wrap: true,
},
},
defaultColor: false 会让 Shiki 输出 --shiki-light 和 --shiki-dark 两组 CSS 变量,而不是直接写死颜色。然后在样式表里根据 data-mode 挑一组用:
.astro-code,
.astro-code span {
color: var(--shiki-light);
background-color: var(--shiki-light-bg);
}
:root[data-mode='dark'] .astro-code,
:root[data-mode='dark'] .astro-code span {
color: var(--shiki-dark);
background-color: var(--shiki-dark-bg);
}
切主题时颜色立刻跟着变,不需要重新渲染代码。
复制按钮
Shiki 不负责复制按钮,那是几行原生 JavaScript 的事:
document.querySelectorAll('pre.astro-code').forEach((pre) => {
const btn = document.createElement('button');
btn.className = 'copy-btn';
btn.textContent = '复制';
btn.addEventListener('click', async () => {
await navigator.clipboard.writeText(pre.innerText);
btn.textContent = '已复制';
});
pre.appendChild(btn);
});
pre.innerText 拿到的是渲染后的纯文本,不会带上标签。
各种语言都试试
Python:
from dataclasses import dataclass
@dataclass
class Post:
title: str
tags: list[str]
def is_tagged(self) -> bool:
return len(self.tags) > 0
Bash:
npm run build
npx wrangler pages deploy dist --project-name=my-home
JSON:
{
"nickname": "林一",
"headline": "写字、放歌、换壁纸"
}
行内代码也一样,比如 npm run dev 或者 src/data/profile.json。
小提示:Shiki 支持的语言列表很长,写错语言名不会报错,只是不会高亮而已。