Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

convertFromHTML and inline images #208

Open
MamorukunBE opened this issue Apr 25, 2022 · 0 comments
Open

convertFromHTML and inline images #208

MamorukunBE opened this issue Apr 25, 2022 · 0 comments

Comments

@MamorukunBE
Copy link

MamorukunBE commented Apr 25, 2022

Hi everyone,

in draftjs I permits the users to add png smileys. They are added in the blockState as a special charater (⅋) linked to an entity holding the image data. At the render, a custom decorator permits me to display the smiley in place of the special character.

When I serialize the daftjs content, I use convertToHTML (to end up with a user-friendly html content), I transform that special character/entity into a usual <img /> whithin the text (ie. "This smiley <img src="..."> is quite pretty"), and all is fine.

The problem is when I try to deserialize that html content: using htmlToEntity, I end up with my smiley in its own atomic block cuting the text in two parts ; and using textToEntity I end up with my smiley no more linked to any character.

In other words, what I need, when deserializing my html, is to create the corresponding entity BUT ALSO to recreate that special character which will be the link to the created entity. Any hint on how to do this?

Thank you very much in advance :)

EDIT:
While waiting for an answer, I found some kind of trick to bypass draft-convert limitations on this matter: preprocess the html to replace all the smileys <img> tags by "⅋{{image_src}}" (which is not touched by convertFromHTML, and thus finishes in the contentState), then change all those entries in the said contentState manually with this functionnality:

export function InsertPngSmileys(editorState) {
  // Scan each block for inline smileys
  //-----------------------------------
  let workContentState = editorState.getCurrentContent();
  let smileysData = {};
  getAllBlocks(editorState).forEach((block, i) => {
    const blockKey = block.getKey();
    const blockText = block.getText();
    //-----
    Object.keys(smileysData).forEach(smileyKey => smileysData[smileyKey].positionsData = []);   // Clean previous block positions

    // Replace all the smileys entries by the png smileys anchor
    //----------------------------------------------------------
    let match = null, regex = RegExp(`${constants.PNG_SMILEY_ANCHOR}({{([^}]*)}})`, 'g');
    while ((match = regex.exec(blockText)) !== null) {
      let smileySrcId = hashString(match[2]);
      let dataStartPos = match.index + constants.PNG_SMILEY_ANCHOR.length;
      //-----
      if (!smileysData[smileySrcId])
        smileysData[smileySrcId] = { src: match[2], entityKey: null, positionsData: [] };
      smileysData[smileySrcId].positionsData.push({ anchorPos: match.index, dataStart: dataStartPos, dataEnd: dataStartPos + match[1].length
      });
    }

    // Then, if any, clean the smiley anchors, create the corresponding entities and link them
    //----------------------------------------------------------------------------------------
    let blockSelection = SelectionState.createEmpty(blockKey);
    for (let smileyData of Object.values(smileysData)) {
      // Create the entity, if not done yet
      //-----------------------------------
      if (!smileyData.entityKey) {
        workContentState = workContentState.createEntity('smiley', 'MUTABLE', { src: smileyData.src });
        smileyData.entityKey = workContentState.getLastCreatedEntityKey();
      }

      // Then processes all its positions. Do it in reverse order so
      // we don't have to recalculate the positions at each change
      //------------------------------------------------------------
      smileyData.positionsData.reverse().forEach(positionData => {
        // Clean the smiley anchor
        //------------------------
        blockSelection = blockSelection.merge({ anchorOffset: positionData.dataStart, focusOffset: positionData.dataEnd });
        workContentState = Modifier.replaceText(workContentState, blockSelection, '');

        // Link the entity to each position which needs it
        //------------------------------------------------
        const smileyAnchorPosition = SelectionState.createEmpty(blockKey).merge({ anchorOffset: positionData.anchorPos, focusOffset: positionData.dataStart })
        workContentState = Modifier.applyEntity(workContentState, smileyAnchorPosition, smileyData.entityKey);
      });
    }
  });

  // And finaly, create and return a new EditorState with the modified content
  //--------------------------------------------------------------------------
  return EditorState.createWithContent(workContentState);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant