Markdown编辑器如何实现代码块高亮并保留缩进?
我在用Vue项目集成Markdown编辑器时卡住了。用了marked库渲染,代码块能显示但没有高亮,手动引入highlight.js后虽然能高亮了,但输入的缩进会被浏览器自动压缩成一个空格,代码看起来乱糟糟的。比如写:
<script>
function test() {
console.log('缩进全没了')
}
</script>
渲染后代码块里的缩进全变成单空格,而且高亮只对第一行生效。试过设置
标签的tabIndex属性和添加preserveSpaces配置,但都没用。搞不懂为啥marked和highlight.js配合时会出现这种情况,有没有更好的解决办法?
首先得明白为啥会这样。marked负责把markdown转成html,highlight.js负责给代码加高亮。问题出在marked生成的html结构可能不符合highlight.js的预期,而且浏览器默认会把连续空白符合并成一个空格。
解决方案分这几步走:
1. 确保marked生成正确的pre标签结构
2. 配置highlight.js正确识别代码块
3. 用css强制保留空白符
先看marked配置部分:
然后处理css部分,必须加这条规则:
white-space: pre是关键,它告诉浏览器保留所有空白和换行。tab-size控制缩进宽度,按你的习惯设置2或4。
还有个小坑要注意,vue的模板里如果用v-html渲染marked结果,记得处理转义:
如果还不行,可能是highlight.js的版本问题。可以试试手动初始化:
我上周刚在项目里解决过一模一样的问题,这么处理之后代码缩进和高亮都正常了。有时候前端这些小问题真的很磨人,特别是几个库配合用的时候。
首先,marked默认会把代码里的空格和制表符处理掉,得手动关掉这个行为。你初始化marked的时候要加个选项:
mangle: false和headerIds: false其实不关键,重点是你要确保传给marked的源文本里缩进是保留的,而且渲染时不要让DOM自动吃掉空白。真正的解法是配合CSS和正确的API调用顺序。先装好highlight.js,然后这么配marked:
注意这里直接返回了带pre包裹的结构,因为代码块必须在外层用pre才能保留空白。然后你在CSS里加上:
white-space设成pre或者pre-wrap是关键,不然浏览器会把多个空格合并。
还有个常见坑是你可能在Vue里用v-html直接插字符串,但数据流不对的话,highlight.js可能会在DOM更新前就跑完了。如果你发现高亮不生效,别用mounted里一次性调,改成用nextTick或者watch文本变化后手动触发一次highlight,或者干脆全交给marked在render阶段做完。
最后建议换prism.js也行,但它也有类似问题。最稳的方式还是我上面写的——在marked的code渲染钩子里直接调用highlight.js API完成高亮,这样流程可控,缩进也能保住。