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
和renderCodeBlockCloseMarker
renderMathBlock
:渲染数学公式块,相关渲染器包括renderMathBlockOpenMarker
、renderMathBlockContent
和renderMathBlockCloseMarker
renderBlockquote
:渲染块引用,相关渲染器包括renderBlockquoteMarker
renderHeading
:渲染标题,相关渲染器包括renderHeadingC8hMarker
renderList
:渲染列表renderListItem
:渲染列表项,相关渲染器包括renderTaskListItemMarker
renderThematicBreak
:渲染分隔线renderHTML
:渲染 HTML 块renderTable
:渲染表格,相关渲染器包括renderTableHead
、renderTableRow
和renderTableCell
renderFootnotesDef
:渲染脚注定义块
行级渲染器
renderCodeSpan
:渲染代码,相关渲染器包括renderCodeSpanOpenMarker
、renderCodeSpanContent
和renderCodeSpanCloseMarker
renderInlineMath
:渲染行级数学公式,相关渲染器包括renderInlineMathOpenMarker
、renderInlineMathContent
和renderInlineMathCloseMarker
renderEmphasis
:渲染强调,相关渲染器包括renderEmAsteriskOpenMarker
、renderEmAsteriskCloseMarker
、renderEmUnderscoreOpenMarker
和renderEmUnderscoreCloseMarker
renderStrong
:渲染加粗,相关渲染器包括renderStrongA6kOpenMarker
、renderStrongA6kCloseMarker
、renderStrongU8eOpenMarker
和renderStrongU8eCloseMarker
renderStrikethrough
:渲染删除线,相关渲染器包括renderStrikethrough1OpenMarker
、renderStrikethrough1CloseMarker
、renderStrikethrough2OpenMarker
和renderStrikethrough2CloseMarker
renderHardBreak
:渲染硬换行renderSoftBreak
:渲染软换行renderInlineHTML
:渲染行级 HTMLrenderLink
:渲染链接,相关渲染器包括renderOpenBracket
、renderCloseBracket
、renderOpenParen
、renderCloseParen
、renderLinkText
、renderLinkSpace
、renderLinkDest
和renderLinkTitle
renderImage
:渲染图片,相关渲染器包括renderBang
和renderLink
renderEmoji
:渲染 Emoji,相关渲染器包括renderEmojiUnicode
、renderEmojiImg
和renderEmojiAlias
renderToC
:渲染页内目录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];
}
},
}
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于