QuillJS添加自定义Blot支持Freemarker标签的问题求助
问题
已集成Quill编辑器作为在线模板编辑器,后端采用Freemarker处理模板,需要Quill支持Freemarker标签(如<#list>)。目前设置了自定义按钮切换至纯HTML视图编辑标记,添加模板内容切回Quill后,标签会被转义且包裹在<p>标签中。尝试过如下自定义Blot但无效,#符号始终被转义:
class FMListBlot extends InlineBlot {} FMListBlot.blotName = "fmlist"; FMListBlot.tagName = "#list"; FMListBlot.scope = Scope.INLINE; Quill.register(FMListBlot);
需求:允许Quill保留自定义Freemarker标签,无需可视化展示,只要不清理转义即可。
解决方案
核心问题说明
Quill的默认HTML解析器会过滤非标准HTML标签(标签名含#属于非法HTML),且自定义Blot的标签名必须符合HTML规范,因此直接用#list作为tagName无法被识别。以下是可行的实现方案:
方案1:自定义Blot+Clipboard处理(推荐)
通过合法HTML标签承载Freemarker内容,自定义Clipboard模块处理标签转换,避免Quill转义清理。
1. 定义自定义Inline Blot
用标准<span>标签承载Freemarker标签,添加类名标识:
import Quill from 'quill'; const Inline = Quill.import('blots/inline'); class FMListBlot extends Inline { static create(value) { const node = super.create(); node.innerHTML = value; node.classList.add('fm-freemarker-tag'); return node; } static value(node) { return node.innerHTML; } } FMListBlot.blotName = 'freemarkerTag'; FMListBlot.tagName = 'SPAN'; Quill.register(FMListBlot);
2. 自定义Clipboard模块处理HTML转换
在粘贴或切换回富文本视图时,自动将<#list>标签转换为自定义Blot对应的<span>:
const Clipboard = Quill.import('modules/clipboard'); class FMClipboard extends Clipboard { // 处理粘贴事件 onPaste(e) { const html = e.clipboardData?.getData('text/html'); if (!html) return super.onPaste(e); // 将所有Freemarker标签包裹到自定义span中 const processedHtml = html.replace( /<#([a-z]+)([^>]*)>([\s\S]*?)<\/#\1>/g, '<span class="fm-freemarker-tag"><#$1$2>$3</#$1></span>' ); // 替换编辑器内容 this.quill.scroll.deleteAt(0, this.quill.getLength()); this.quill.clipboard.dangerouslyPasteHTML(0, processedHtml); e.preventDefault(); } // 手动处理HTML视图返回的内容(配合你的切换按钮使用) processRawHtml(rawHtml) { return rawHtml.replace( /<#([a-z]+)([^>]*)>([\s\S]*?)<\/#\1>/g, '<span class="fm-freemarker-tag"><#$1$2>$3</#$1></span>' ); } } // 替换默认Clipboard模块 Quill.register('modules/clipboard', FMClipboard, true);
3. 输出时还原Freemarker标签
将编辑器内容导出给后端前,把自定义<span>转换回原始Freemarker标签:
const editorHtml = quill.root.innerHTML; const finalTemplate = editorHtml.replace( /<span class="fm-freemarker-tag">(<#[a-z]+[^>]*>[\s\S]*?<\/#[\w]+>)<\/span>/g, '$1' ); // 将finalTemplate传给后端
方案2:关闭Quill内容 sanitize(不推荐公共环境)
如果场景不存在XSS风险,可直接关闭Quill的内容清理,但仍需处理非法标签的解析问题:
const quill = new Quill('#editor', { theme: 'snow', sanitize: false, // 关闭默认内容清理 modules: { // 其他模块配置 } });
此方法仅能避免Quill主动转义,但浏览器仍会将<#list>视为无效标签,最终可能被包裹到<p>中,因此仍需结合方案1的Clipboard处理才能稳定保留标签。
内容的提问来源于stack exchange,提问作者David Fariña
相关产品推荐
相关产品推荐

