Astro 构建时能高亮 Markdown 里的代码块。如果正文是从 CMS 拉出来,再用 Vue 的 v-html 渲染,代码块要在正文插入 DOM 后交给 Prism。
文章本身是 Markdown
Astro 默认使用 Shiki,换配色通常只需要改主题。如果想用 Prism,可在 Astro 配置中选择:
// astro.config.mjs
import { defineConfig } from 'astro/config'
export default defineConfig({
markdown: { syntaxHighlight: 'prism' },
})
Prism 输出语法标记和 CSS 类。记得在公共布局加载主题,比如把 prism-okaidia.css 放到 public/styles/,再用 <link rel="stylesheet" href="/styles/prism-okaidia.css"> 引入。构建时已高亮的正文无需在浏览器里再扫描一次。
正文来自 CMS,通过 Vue 渲染
pnpm add prismjs
pnpm add -D @types/prismjs
<script setup lang="ts">
import { ref, onMounted, watch } from 'vue'
import Prism from 'prismjs'
import 'prismjs/themes/prism-okaidia.css'
import 'prismjs/components/prism-json'
import 'prismjs/components/prism-yaml'
const props = defineProps<{ html: string }>()
const article = ref<HTMLElement | null>(null)
function highlight() {
if (article.value) Prism.highlightAllUnder(article.value)
}
onMounted(highlight)
watch(() => props.html, highlight, { flush: 'post' })
</script>
<template>
<div ref="article" v-html="props.html"></div>
</template>
传给 v-html 的正文要可信,外部提交的 HTML 先做清洗。Astro 渲染这个组件时加 client:load,让 onMounted 在浏览器运行。highlightAllUnder 把扫描范围限制在正文里。
没有颜色时怎么查
- 确认
<pre><code>上有language-yaml之类的语言标记,且对应语法已加载。 - 看 DOM 是否生成
span.token。有标记但没有颜色,就查主题 CSS。 - 首次进入正常、换文章后无效,检查高亮是否发生在正文更新之后。
flush: 'post'会在 DOM 更新后执行。