如何结合Tailwind Typography与Highlight.js实现代码语法高亮
结合Marked.js与Highlight.js实现代码语法高亮(搭配Tailwind Typography)
我正在用Tailwind Typography优化HTML展示样式,想给包含<code>标签的代码块实现语法高亮。目前用Marked.js把Markdown转成HTML标签,请问怎么结合Highlight.js完成带高亮的HTML解析?以下是我当前的实现代码:
<script setup> import { computed, watch } from "vue" import { marked} from "marked"; import { markedHighlight } from "marked-highlight"; import hljs from 'highlight.js'; const props = defineProps({ history: { type: Array, default: () => [], required: true, }, }) const processMarkdown = computed(()=>{ return marked("Certainly! Here is an example of a simple JavaScript function that takes in a number and returns its square:
function square(num) {
return num * num;
}
console.log(square(5)); // Output: 25
In this code, the `square` function takes in a single argument called `num`, which is passed into the function as an argument. The function then multiplies the value of `num` by itself (i.e., `num * num`) and returns the result. You can also define a function with multiple arguments like this:
function addMultipleNumbers(a, b, c) {
return a + b + c;
}
console.log(addMultipleNumbers(3, 4, 5)); // Output: 12
In this code, the `addMultipleNumbers` function takes in three arguments called `a`, `b`, and `c`. The function then adds all of these values together and returns the result. You can also use a function to perform more complex operations, such as calculating the area of a circle or finding the factorial of a number. Here is an example of a JavaScript function that calculates the area of a circle:
function areaOfCircle(radius) {
return Math.PI * radius ** 2;
}
console.log(areaOfCircle(5)); // Output: 78.53981633974483
In this code, the `areaOfCircle` function takes in a single argument called `radius`, which is passed into the function as an argument. The function then uses the mathematical formula for the area of a circle (`Math.PI * radius ** 2`) to calculate the area of the circle and returns the result. I hope these examples give you a better idea of how functions work in JavaScript! Let me know if you have any questions or need further clarification." , { highlight(md) { return hljs.highlightAll(md).value; } } ) }) watch(processMarkdown,(newValue) =>{ hljs.highlightAll(); }) const histories = computed(() => { console.log("History recompute") return props.history }) </script> <template> <div class="w-full h-full max-h-fit flex flex-col gap-2 overflow-auto"> <div class="max-h-fit w-full bg-black flex flex-row" alt="container" v-for="(history, index) in histories" :key="index" > <div class="avatar p-3 pt-6 max-h-28"> <div class="w-12 max-h-12 rounded"> <img src="https://media.newyorker.com/photos/59095bb86552fa0be682d9d0/master/pass/Monkey-Selfie.jpg" alt="" /> </div> </div> <div class="p-7 text-justify max-h-fit"> <div> {{ history.request.content }} </div> <div v-if="history.response.content === ''"> <span class="loading loading-ring loading-sm"></span> </div> <div v-else> <article class="prose"> <div v-html=" marked.parse(history.response.content)"></div> <div v-html="processMarkdown"></div> {{console.log(processMarkdown)}} </article> </div> </div> </div> </div> </template> <style></style>
当前代码的问题
- 未正确使用
markedHighlight插件集成Highlight.js,自定义的highlight函数写法错误 - 模板中存在重复解析Markdown的逻辑,同时使用了
marked.parse和processMarkdown hljs.highlightAll()是用于批量渲染DOM中的代码块,不能直接处理字符串- 未引入Highlight.js的样式文件,即使解析正确也看不到高亮效果
修正方案
1. 正确配置marked与highlight.js的集成
使用markedHighlight插件扩展marked,在配置中指定代码高亮的处理逻辑,同时支持指定语言的代码块。
2. 统一Markdown解析逻辑
封装解析函数,避免模板中直接调用marked.parse,保持代码整洁。
3. 移除冗余的watch监听
解析阶段已完成高亮处理,无需在watch中再次调用highlightAll。
4. 引入Highlight.js样式
必须导入高亮样式才能看到效果,可选择官方提供的任意样式。
完整修正代码
<script setup> import { computed } from "vue" import { marked } from "marked"; import { markedHighlight } from "marked-highlight"; import hljs from 'highlight.js'; // 导入Highlight.js样式,这里使用github风格,可替换为其他样式 import 'highlight.js/styles/github.css'; // 配置marked集成highlight.js marked.use(markedHighlight({ langPrefix: 'hljs language-', highlight(code, lang) { // 优先使用指定语言,不支持则自动检测或用纯文本 const targetLang = hljs.getLanguage(lang) ? lang : 'plaintext'; return hljs.highlight(code, { language: targetLang }).value; } })) const props = defineProps({ history: { type: Array, default: () => [], required: true, }, }) // 封装Markdown解析函数 const parseMarkdown = (content) => { return marked(content); } const histories = computed(() => { console.log("History recompute") return props.history }) </script> <template> <div class="w-full h-full max-h-fit flex flex-col gap-2 overflow-auto"> <div class="max-h-fit w-full bg-black flex flex-row" v-for="(history, index) in histories" :key="index" > <div class="avatar p-3 pt-6 max-h-28"> <div class="w-12 max-h-12 rounded"> <img src="https://media.newyorker.com/photos/59095bb86552fa0be682d9d0/master/pass/Monkey-Selfie.jpg" alt="" /> </div> </div> <div class="p-7 text-justify max-h-fit"> <div> {{ history.request.content }} </div> <div v-if="history.response.content === ''"> <span class="loading loading-ring loading-sm"></span> </div> <div v-else> <article class="prose"> <div v-html="parseMarkdown(history.response.content)"></div> </article> </div> </div> </div> </div> </template> <style></style>
补充说明
langPrefix配置确保生成的代码块标签带有hljs识别的类名,样式才能正确生效- 解析函数会自动处理带语言标识(如```js)和不带标识的代码块
- Tailwind Typography的
prose类会自动适配代码块的排版,与Highlight.js样式兼容
内容的提问来源于stack exchange,提问作者anina
相关产品推荐
相关产品推荐

