You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:46:39