Vditor 支持自定义渲染器,如果需要修改渲染结果的话可考虑使用该特性。
渲染流程
Vditor 通过 Lute 引擎进行 Markdown 解析,解析后将生成语法树,最后通过遍历语法树进行渲染。根据不同的渲染场景,Vditor 会触发不同的自定义渲染器回调。
目前支持的渲染回调场景如下:
HTML2Md:HTML 转 Markdown,v3.2.0 后改为HTML2VditorSVDOM。使用场景:options.mode为sv时,初始化编辑器内容- 调用
html2md方法 - 在
sv模式粘贴复制好的 HTML 时触发
HTML2VditorDOM:HTML 转 Vditor DOM,在wysiwyg模式粘贴 HTML 时触发HTML2VditorIRDOM:HTML 转 Vditor IR DOM,在ir模式粘贴 HTML 时触发HTML2VditorSVDOM:HTML 转 Vditor SV DOM,在sv模式粘贴 HTML 时触发Md2HTML:Markdown 转 HTML,v3.2.0 后改为Md2VditorSVDOM。使用场景:- 调用静态方法
md2html - 调用静态方法
previewRender
- 调用静态方法
Md2VditorDOM:Markdown 转 Vditor DOM,在wysiwyg模式粘贴纯文本时触发Md2VditorIRDOM:Markdown 转 Vditor IR DOM,在ir模式粘贴纯文本时触发Md2VditorSVDOM:Markdown 转 Vditor SV DOM,在sv模式粘贴纯文本时触发
自定义渲染器
通过接口 vditor.lute.SetJSRenderers 来设置自定义渲染器,参数格式如下:
(options?: {
renderers: {
HTML2VditorDOM?: ILuteRender,
HTML2VditorIRDOM?: ILuteRender,
HTML2Md?: ILuteRender,
Md2HTML?: ILuteRender,
Md2VditorDOM?: ILuteRender,
Md2VditorIRDOM?: ILuteRender,
},
}): void;
interface ILuteRender {
renderHeading?: ILuteRenderCallback;
renderLinkDest?: ILuteRenderCallback;
... // 参见渲染器函数列表
}
type ILuteRenderCallback = (node: {
TokensStr: () => string;
__internal_object__: {
Parent: {
Type: number,
},
HeadingLevel: string,
}
}, entering: boolean) => [string, number];
其中 Md2HTML 渲染回调场景中,渲染器函数是带有两个输入参数和两个返回值(合并在一个数组中)的函数,两个参数:
node:当前遍历到的节点。比如渲染器函数是renderHeading则 node 为标题节点,如果渲染器函数是renderLink则 node 为链接节点entering:遍历是否为进入节点。我们按深度优先算法来遍历语法树,在进入节点时为true,离开节点时为false
函数返回值为一个数组,包含两个元素:
- 第一个元素为
string:渲染的字符串,比如renderHeading返回<h2>foo</h2> - 第二个元素为
number:遍历状态,0:停止遍历,1:跳过子节点遍历,2:继续遍历
为了方便说明,下面插入 Lute 遍历实现部分的代码来帮助理解:
// WalkStatus 描述了遍历状态。
type WalkStatus int
const (
// WalkStop 意味着不需要继续遍历。
WalkStop = iota
// WalkSkipChildren 意味着不要遍历子节点。
WalkSkipChildren
// WalkContinue 意味着继续遍历。
WalkContinue
)
// Walker 函数定义了遍历节点 n 时需要执行的操作,进入节点设置 entering 为 true,离开节点设置为 false。
// 如果返回 WalkStop 或者 error 则结束遍历。
type Walker func(n *Node, entering bool) WalkStatus
// Walk 使用深度优先算法遍历指定的树节点 n。
func Walk(n *Node, walker Walker) {
var status WalkStatus
// 进入节点
status = walker(n, true)
if status == WalkStop {
return
}
if status != WalkSkipChildren {
// 递归遍历子节点
for c := n.FirstChild; nil != c; c = c.Next {
Walk(c, walker)
}
}
// 离开节点
status = walker(n, false)
return
}
其中 Walker 就是 renderXXX 渲染器函数内部实现的签名,在外部我们进行了包装,以方便返回渲染结果字符串,所以自定义渲染器函数的返回值是包含两个值的一个数组。
渲染器函数列表
Vditor 支持自定义如下渲染器函数,我们按元素类型分组介绍。
块级渲染器
renderDocument:渲染整个文档renderParagraph:渲染段落renderText:渲染文本renderCodeBlock:渲染代码块,相关渲染器包括renderCodeBlockOpenMarker、renderCodeBlockInfoMarker、renderCodeBlockCode和renderCodeBlockCloseMarkerrenderMathBlock:渲染数学公式块,相关渲染器包括renderMathBlockOpenMarker、renderMathBlockContent和renderMathBlockCloseMarkerrenderBlockquote:渲染块引用,相关渲染器包括renderBlockquoteMarkerrenderHeading:渲染标题,相关渲染器包括renderHeadingC8hMarkerrenderList:渲染列表renderListItem:渲染列表项,相关渲染器包括renderTaskListItemMarkerrenderThematicBreak:渲染分隔线renderHTML:渲染 HTML 块renderTable:渲染表格,相关渲染器包括renderTableHead、renderTableRow和renderTableCellrenderFootnotesDef:渲染脚注定义块
行级渲染器
renderCodeSpan:渲染代码,相关渲染器包括renderCodeSpanOpenMarker、renderCodeSpanContent和renderCodeSpanCloseMarkerrenderInlineMath:渲染行级数学公式,相关渲染器包括renderInlineMathOpenMarker、renderInlineMathContent和renderInlineMathCloseMarkerrenderEmphasis:渲染强调,相关渲染器包括renderEmAsteriskOpenMarker、renderEmAsteriskCloseMarker、renderEmUnderscoreOpenMarker和renderEmUnderscoreCloseMarkerrenderStrong:渲染加粗,相关渲染器包括renderStrongA6kOpenMarker、renderStrongA6kCloseMarker、renderStrongU8eOpenMarker和renderStrongU8eCloseMarkerrenderStrikethrough:渲染删除线,相关渲染器包括renderStrikethrough1OpenMarker、renderStrikethrough1CloseMarker、renderStrikethrough2OpenMarker和renderStrikethrough2CloseMarkerrenderHardBreak:渲染硬换行renderSoftBreak:渲染软换行renderInlineHTML:渲染行级 HTMLrenderLink:渲染链接,相关渲染器包括renderOpenBracket、renderCloseBracket、renderOpenParen、renderCloseParen、renderLinkText、renderLinkSpace、renderLinkDest和renderLinkTitlerenderImage:渲染图片,相关渲染器包括renderBang和renderLinkrenderEmoji:渲染 Emoji,相关渲染器包括renderEmojiUnicode、renderEmojiImg和renderEmojiAliasrenderToC:渲染页内目录renderFootnotesRef:渲染脚注引用renderBackslash:渲染反斜杆,相关渲染器包括renderBackslashContent
以上中的“相关渲染器”中的“相关”代表语法树节点结构的相关性,具体节点结构描述请参考 Markdown 解析原理详解和 Markdown AST 描述。
示例
完整示例可参见 demo。下面我们来看一下自定义渲染的代码示例。
const renderers = {
renderHeading: (node, entering) => {
if (entering) {
return [`<h${node.__internal_object__.HeadingLevel} class="vditor__heading"><span class="prefix"></span><span>`, Lute.WalkContinue];
} else {
return [`</span></h${node.__internal_object__.HeadingLevel}>`, Lute.WalkContinue];
}
},
}









欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于