如何在DraftJS编辑器中添加script标签及嵌入Gist类内容?
解决方案:在DraftJS中添加Gist类嵌入内容
我刚好之前踩过DraftJS处理嵌入内容的坑,先给你捋清楚核心问题:DraftJS默认会过滤HTML里的<script>标签(这是内置的安全防护机制),所以你直接手动编辑HTML再用convertFromHTML转换肯定行不通。下面给你几个实操性拉满的方案:
方案1:自定义HTML转换规则,针对性处理Gist
你可以通过convertFromHTML的自定义配置,识别Gist专属的嵌入代码,把它转换成DraftJS的嵌入实体(Entity),而不是硬保留script标签。
举个具体例子,假设你拿到的Gist代码是:
<script src="https://gist.github.com/your-gist-id.js"></script>
你可以这样自定义转换逻辑:
import { convertFromHTML, ContentState } from 'draft-js'; // 自定义实体转换器,专门识别Gist的script标签 const customEntityTransformers = { 'script': (node) => { // 判断是否为Gist的嵌入脚本 if (node.src?.includes('gist.github.com')) { return { type: 'EMBED_GIST', mutability: 'IMMUTABLE', data: { src: node.src } }; } // 非Gist的script标签直接忽略 return null; } }; // 执行转换 const blocksFromHTML = convertFromHTML(yourHtmlString, undefined, customEntityTransformers); const contentState = ContentState.createFromBlockArray( blocksFromHTML.contentBlocks, blocksFromHTML.entityMap );
方案2:直接创建嵌入实体(最推荐,可控性最强)
跳过HTML转换这一步,直接给编辑器插入Gist对应的实体,逻辑更清晰也更不容易出问题。
步骤1:写一个插入Gist的工具方法
import { EditorState, Modifier, Entity } from 'draft-js'; const insertGist = (editorState, gistSrc) => { const contentState = editorState.getCurrentContent(); // 创建Gist类型的实体 const entityKey = Entity.create( 'EMBED_GIST', 'IMMUTABLE', { src: gistSrc } ); // 在当前光标位置插入实体(需要占位文本,后续渲染会替换掉) const newContentState = Modifier.insertText( contentState, editorState.getSelection(), ' ', null, entityKey ); return EditorState.push(editorState, newContentState, 'insert-characters'); }; // 使用示例:比如用户输入Gist链接后调用 const newEditorState = insertGist(currentEditorState, 'https://gist.github.com/your-gist-id.js');
步骤2:自定义编辑器的渲染逻辑
DraftJS需要你告诉它怎么渲染EMBED_GIST类型的实体,所以要写个自定义渲染组件:
import { Editor } from 'draft-js'; import { useEffect, useRef } from 'react'; const MyRichEditor = ({ editorState, onChange }) => { // 自定义块渲染函数,识别Gist实体 const blockRendererFn = (contentBlock) => { const entityKey = contentBlock.getEntityAt(0); if (entityKey) { const entity = Entity.get(entityKey); if (entity.getType() === 'EMBED_GIST') { return { component: GistEmbed, props: { src: entity.getData().src } }; } } return null; }; return ( <Editor editorState={editorState} onChange={onChange} blockRendererFn={blockRendererFn} /> ); }; // Gist嵌入组件,解决script标签不自动执行的问题 const GistEmbed = ({ src }) => { const containerRef = useRef(null); useEffect(() => { if (!containerRef.current) return; // 动态创建script标签并插入,确保脚本执行 const script = document.createElement('script'); script.src = src; script.async = true; containerRef.current.appendChild(script); // 组件卸载时清理脚本,避免内存泄漏 return () => script.remove(); }, [src]); return <div ref={containerRef} className="gist-container"></div>; };
方案3:直接用现成的扩展库(偷懒必备)
如果不想自己写逻辑,可以用社区维护的draft-js-embed-plugin,它已经封装了Gist、YouTube等多种嵌入内容的处理,直接集成就能用,省掉不少重复工作。
内容的提问来源于stack exchange,提问作者Daniel Jamrozik
相关产品推荐
相关产品推荐

