微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Draft-JS - 使用 convertFromHTML 将 <img> 翻译成原子块摆脱了 Entity

如何解决Draft-JS - 使用 convertFromHTML 将 <img> 翻译成原子块摆脱了 Entity

所以我一直在尝试使用方法 convertFromHTML 将图像转换为原子块,以便它可以与 draft-js-image-plugin 兼容,因为它需要类型为 atomic

给定一个带有一些文本和图像的简单 HTML 结构,convertFromHTML 生成contentState

{
  "blocks": [
    {
      "key": "82k8","text": "‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐","type": "unstyled","depth": 0,"inlinestyleRanges": [],"entityRanges": [],"data": {}
    },{
      "key": "9jbor","text": "On December 29,2020,5:20 PM EST  txwbi.nrjrtn@gmail.com wrote:","entityRanges": [{ "offset": 34,"length": 23,"key": 0 }],{
      "key": "anq8o","text": "?A bunch of text here to test out the body","inlinestyleRanges": [
        { "offset": 3,"length": 13,"style": "ITALIC" },{ "offset": 3,"style": "UNDERLINE" },{ "offset": 38,"length": 4,"style": "BOLD" }
      ],"entityRanges": [{ "offset": 0,"length": 1,"key": 1 }],"data": {}
    }
  ],"entityMap": {
    "0": {
      "type": "LINK","mutability": "MUTABLE","data": {
        "href": "mailto:txwbi.nrjrtn@gmail.com","rel": "noreferrer nofollow noopener","target": "_blank","url": "mailto:txwbi.nrjrtn@gmail.com"
      }
    },"1": {
      "type": "IMAGE","mutability": "IMMUTABLE","data": {
        "alt": "cory_emoji.png","height": "210","src": "data:image/png;base64,...BASE64ENCODEDIMAGE WOULD BE HERE I REMOVED BECAUSE OF CHAR LIMITS","width": "173"
      }
    }
  }
}

我们可以看到 img 标签采用了 unstyled 块,这不是我想要的。所以我创建了以下函数来扩展认的块渲染映射以解释 img 标签

const {
  EditorState,convertToRaw,DefaultDraftBlockRenderMap,ContentState,convertFromHTML,getSafeBodyFromHTML
} = require('draft-js');

const Immutable = require('immutable');

module.exports.editorStateFromHTML = htmlBody => {
  console.log('HTML ---> EDITOR ::: RAW BODY',htmlBody);
  const blockRenderMap = Immutable.Map({
    atomic: {
      element: 'figure',aliasedElements: ['img']
    }
  });

  const extendedBlockRenderMap = DefaultDraftBlockRenderMap.merge(
    blockRenderMap
  );

  const blocksFromHTML = convertFromHTML(
    htmlBody,getSafeBodyFromHTML,extendedBlockRenderMap
  );

  console.log(blocksFromHTML);
  const state = ContentState.createFromBlockArray(
    blocksFromHTML.contentBlocks,blocksFromHTML.entityMap
  );
  console.log(JSON.stringify(convertToRaw(state)));
  const newEditor = EditorState.createWithContent(state);
  return newEditor;
};

导致此内容状态:

{
  "blocks": [
    {
      "key": "fhgqd",{
      "key": "2nsnk",{
      "key": "7c7cu","text": "A bunch of text here to test out the body","inlinestyleRanges": [
        { "offset": 2,{ "offset": 2,{ "offset": 37,{
      "key": "f84vb","text": "","type": "atomic","url": "mailto:txwbi.nrjrtn@gmail.com"
      }
    }
  }
}

如您所见,entityMap 现在只有一个键,图像的所有数据都不再存在。我怎样才能让 img 标签成为原子块,同时仍然在 entityMap 中创建 IMAGE 实体???

解决方法

我的解决方法是遵循它有点丑但它有效并为我提供了正确的输出:

const {
  EditorState,convertToRaw,convertFromRaw,DefaultDraftBlockRenderMap,ContentState,convertFromHTML,getSafeBodyFromHTML
} = require('draft-js');

const Immutable = require('immutable');
const clone = require('rfdc')();

module.exports.editorStateFromHTML = htmlBody => {
  console.log('HTML ---> EDITOR ::: RAW BODY',htmlBody);
  const blockRenderMap = Immutable.Map({
    image: {
      element: 'img'
    }
  });

  const extendedBlockRenderMap = DefaultDraftBlockRenderMap.merge(
    blockRenderMap
  );

  const blocksFromHTML = convertFromHTML(
    htmlBody,getSafeBodyFromHTML,extendedBlockRenderMap
  );

  const state = ContentState.createFromBlockArray(
    blocksFromHTML.contentBlocks,blocksFromHTML.entityMap
  );
  const { blocks,entityMap } = convertToRaw(state);
  const imgCount = blocks.filter(b => b.type === 'image').length;

  if (imgCount > 0) {
    const fixedEntityMap = clone(entityMap);
    let arrKeys = Object.keys(fixedEntityMap);
    arrKeys = arrKeys.map(k => parseInt(k,10));
    const lastKey = Math.max(...arrKeys);
    let blockCounter = lastKey;

    const fixedContentBlocks = blocks.map(blck => {
      if (blck.type === 'image') {
        blockCounter += 1;
        return {
          ...blck,text: ' ',type: 'atomic',entityRanges: [{ offset: 0,length: 1,key: blockCounter }]
        };
      }
      return blck;
    });

    const blocksFromHTML2 = convertFromHTML(htmlBody);
    const state2 = ContentState.createFromBlockArray(
      blocksFromHTML2.contentBlocks,blocksFromHTML2.entityMap
    );
    const { entityMap: imgEntities } = convertToRaw(state2);

    let entityCounter = lastKey;
    // eslint-disable-next-line no-restricted-syntax
    for (const [key,value] of Object.entries(imgEntities)) {
      if (value.type === 'IMAGE') {
        entityCounter += 1;
        fixedEntityMap[entityCounter] = value;
      }
    }

    const editorDefaultValue = {
      blocks: fixedContentBlocks,entityMap: fixedEntityMap
    };
    return EditorState.createWithContent(convertFromRaw(editorDefaultValue));
  }

  return EditorState.createWithContent(state);
};

如果有人有更好的解决方案,我会全力以赴。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。