Created
October 25, 2016 20:27
-
-
Save N1kto/6702e1c2d89a33a15a032c234fc4c34e to your computer and use it in GitHub Desktop.
DraftJS: Example of converting <img /> elements from HTML string to custom ContentBlocks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { ContentState, genKey, Entity, CharacterMetadata, ContentBlock, convertFromHTML } from 'draft-js' | |
| import { List, OrderedSet, Repeat, fromJS } from 'Immutable' | |
| import { compose, toArray, extend } from 'underscore' | |
| /* | |
| * Helpers | |
| */ | |
| // Prepares img meta data object based on img attributes | |
| const getBlockSpecForElement = (imgElement) => ({ | |
| contentType: 'image', | |
| imgSrc: imgElement.getAttribute('src') | |
| }) | |
| // Wraps meta data in HTML element which is 'understandable' by Draft, I used <blockquote />. | |
| const wrapBlockSpec = (blockSpec) => { | |
| if (blockSpec == null) { | |
| return null | |
| } | |
| const tempEl = document.createElement('blockquote') | |
| // stringify meta data and insert it as text content of temp HTML element. We will later extract | |
| // and parse it. | |
| tempEl.innerText = JSON.stringify(blockSpec) | |
| return tempEl | |
| } | |
| // Replaces <img> element with our temp element | |
| const replaceElement = (oldEl, newEl) => { | |
| if (!(newEl instanceof HTMLElement)) { | |
| return | |
| } | |
| const parentNode = oldEl.parentNode | |
| return parentNode.replaceChild(newEl, oldEl) | |
| } | |
| const elementToBlockSpecElement = compose(wrapBlockSpec, getBlockSpecForElement) | |
| const imgReplacer = (imgElement) => | |
| replaceElement(imgElement, elementToBlockSpecElement(imgElement)) | |
| // creates ContentBlock based on provided spec | |
| const createContentBlock = (blockData = {}) => { | |
| const { key, type, text, data, inlineStyles, entityData } = blockData | |
| let blockSpec = { | |
| type: type != null ? type : 'unstyled', | |
| text: text != null ? text : '', | |
| key: key != null ? key : genKey() | |
| } | |
| if (data) { | |
| blockSpec.data = fromJS(data) | |
| } | |
| if (inlineStyles || entityData) { | |
| let entityKey | |
| if (entityData) { | |
| const { type, mutability, data } = entityData | |
| entityKey = Entity.create(type, mutability, data) | |
| } else { | |
| entityKey = null | |
| } | |
| const style = OrderedSet(inlineStyles || []) | |
| const charData = CharacterMetadata.create({ style, entityKey }) | |
| blockSpec.characterList = List(Repeat(charData, text.length)) | |
| } | |
| return new ContentBlock(blockSpec) | |
| } | |
| /* | |
| * Main function | |
| */ | |
| // takes HTML string and returns DraftJS ContentState | |
| export default function customHTML2Content (HTML) { | |
| let tempDoc = new DOMParser().parseFromString(HTML, 'text/html') | |
| // replace all <img /> with <blockquote /> elements | |
| toArray(tempDoc.querySelectorAll('img')).forEach(imgReplacer) | |
| // use DraftJS converter to do initial conversion. I don't provide DOMBuilder and | |
| // blockRenderMap arguments here since it should fall back to its default ones, which are fine | |
| let contentBlocks = convertFromHTML(tempDoc.body.innerHTML) | |
| // now replace <blockquote /> ContentBlocks with 'atomic' ones | |
| contentBlocks = contentBlocks.reduce(function (contentBlocks, block) { | |
| if (block.getType() !== 'blockquote') { | |
| return contentBlocks.concat(block) | |
| } | |
| const { imgSrc } = JSON.parse(block.getText()) | |
| const entityData = { | |
| type: 'IMAGE', | |
| mutability: 'IMMUTABLE', | |
| data: { imgSrc } | |
| } | |
| const blockSpec = extend({ type: 'atomic', text: ' ' }, { entityData }) | |
| const atomicBlock = createContentBlock(blockSpec) | |
| const spacerBlock = createContentBlock() | |
| return contentBlocks.concat([ atomicBlock, spacerBlock ]) | |
| }, []) | |
| tempDoc = null | |
| return ContentState.createFromBlockArray(contentBlocks) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I follow your code, but when i run as this
Uncaught Invariant Violation: Unknown DraftEntity keythrow.could you help me to reslove this problem, Thank you.