feat: 代码块语法高亮 + 语言选择 + 样式统一

- 引入 @tiptap/extension-code-block-lowlight + lowlight 实现代码语法高亮
- 工具栏新增语言下拉选择器,光标在代码块内时显示,支持 27 种常用语言
- 默认语言 text,高亮主题适配 MetaLab 深蓝背景 (#1a2332)
- 代码块语言标签用 JS 动态注入 DOM 元素(避免 ::before 在 overflow 容器中失效)
- 详情页同步代码块高亮和语言标签显示
- 编辑器与详情页样式统一:代码块暗色背景、引用蓝色边框、链接 accent 蓝
- sanitizePolicy 放行 data-language 属性和 hljs-* class
- 修复 import map 避免 keyed plugin 重复实例
- 修复详情页代码块开头空白行(移除多余的 padding-top)
- 修复语法错误(多余的闭合括号)
This commit is contained in:
2026-05-28 14:34:58 +08:00
parent 69ba2fb01b
commit 36b18c0ffe
5 changed files with 248 additions and 25 deletions

View File

@ -2,6 +2,7 @@ package service
import (
"fmt"
"regexp"
"metazone.cc/metalab/internal/common"
"metazone.cc/metalab/internal/config"
@ -12,11 +13,13 @@ import (
// sanitizePolicy Tiptap 输出 HTML 的消毒策略
// 前端 WYSIWYG 编辑器输出 HTML由 bluemonday UGC 策略消毒
// 显式放行 code/pre 的 class 属性以保留代码块样式
// 放行 img 的 src/alt 属性以保留图片
// 放行 code/pre 的 class/data-language 属性以保留代码高亮和语言标签
// 放行 span 的 class 属性以保留 highlight.js 的 hljs-* 高亮
// 放行 img 的 src/alt/title 属性以保留图片
var sanitizePolicy = func() *bluemonday.Policy {
p := bluemonday.UGCPolicy()
p.AllowAttrs("class").OnElements("code", "pre")
p.AllowAttrs("class", "data-language").OnElements("code", "pre")
p.AllowAttrs("class").Matching(regexp.MustCompile("^hljs-")).OnElements("span")
p.AllowAttrs("src", "alt", "title").OnElements("img")
return p
}()