Handle img links!!!!!!!!

This commit is contained in:
soupette 2018-04-11 19:36:08 +02:00
parent 534a1099ac
commit cdc92607d6
4 changed files with 139 additions and 19 deletions

View File

@ -6,19 +6,26 @@
import React from 'react';
import PropTypes from 'prop-types';
import { includes } from 'lodash';
const Link = props => {
const { url } = props.contentState.getEntity(props.entityKey).getData();
const { url, aHref, aInnerHTML } = props.contentState.getEntity(props.entityKey).getData();
let content = aInnerHTML;
if (includes(aInnerHTML, '<img', 'src=')) {
const src = aInnerHTML.split('src="')[1].split('" ')[0];
content = <img src={src} alt="img" />;
}
return (
<a
href={url}
href={url || aHref}
onClick={() => {
window.open(url, '_blank');
window.open(url || aHref, '_blank');
}}
style={{ cursor: 'pointer' }}
>
{props.children}
{content || props.children}
</a>
);
};

View File

@ -6,13 +6,28 @@
import React from 'react';
import PropTypes from 'prop-types';
import { CompositeDecorator, ContentState, convertFromHTML, EditorState } from 'draft-js';
import {
CompositeDecorator,
ContentState,
convertFromHTML,
EditorState,
ContentBlock,
genKey,
Entity,
CharacterMetadata,
} from 'draft-js';
import { List, OrderedSet, Repeat, fromJS } from 'immutable';
import cn from 'classnames';
import { isEmpty } from 'lodash';
import { isEmpty, toArray } from 'lodash';
import WysiwygEditor from 'components/WysiwygEditor';
import converter from './converter';
import { findLinkEntities, findImageEntities, findVideoEntities } from './strategies';
import {
findAtomicEntities,
findLinkEntities,
findImageEntities,
findVideoEntities,
} from './strategies';
import Image from './image';
import Link from './link';
@ -55,8 +70,72 @@ const decorator = new CompositeDecorator([
strategy: findVideoEntities,
component: Video,
},
{
strategy: findAtomicEntities,
component: Link,
},
]);
const getBlockSpecForElement = aElement => ({
contentType: 'link',
aHref: aElement.href,
aInnerHTML: aElement.innerHTML,
});
const elementToBlockSpecElement = element => wrapBlockSpec(getBlockSpecForElement(element));
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;
};
const replaceElement = (oldEl, newEl) => {
if (!(newEl instanceof HTMLElement)) {
return;
}
const parentNode = oldEl.parentNode;
return parentNode.replaceChild(newEl, oldEl);
};
const aReplacer = aElement => replaceElement(aElement, elementToBlockSpecElement(aElement));
const createContentBlock = (blockData = {}) => {
const { key, type, text, data, inlineStyles, entityData } = blockData;
let blockSpec = {
type: type !== null && type !== undefined ? type : 'unstyled',
text: text !== null && text !== undefined ? text : '',
key: key !== null && key !== undefined ? 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 || ['LINK']);
const charData = CharacterMetadata.applyEntity(
CharacterMetadata.create({ style, entityKey }),
entityKey,
);
blockSpec.characterList = List(Repeat(charData, text.length));
}
return new ContentBlock(blockSpec);
};
class PreviewWysiwyg extends React.PureComponent {
state = { editorState: EditorState.createEmpty(), isMounted: false };
@ -101,26 +180,51 @@ class PreviewWysiwyg extends React.PureComponent {
previewHTML = rawContent => {
const initHtml = isEmpty(rawContent) ? '<p></p>' : rawContent;
const html = converter.makeHtml(initHtml);
// This action takes a long time
const blocksFromHTML = convertFromHTML(html);
const html = new DOMParser().parseFromString(converter.makeHtml(initHtml), 'text/html');
toArray(html.querySelectorAll('a')).forEach(aReplacer);
let blocksFromHTML = convertFromHTML(html.body.innerHTML);
// Make sure blocksFromHTML.contentBlocks !== null
if (blocksFromHTML.contentBlocks) {
const contentState = ContentState.createFromBlockArray(
blocksFromHTML.contentBlocks,
blocksFromHTML.entityMap,
);
blocksFromHTML = blocksFromHTML.contentBlocks.reduce((acc, block) => {
if (block.getType() === 'blockquote') {
try {
const { aHref, aInnerHTML } = JSON.parse(block.getText());
const entityData = {
type: 'LINK',
mutability: 'IMMUTABLE',
data: {
aHref,
aInnerHTML,
},
};
const blockSpec = Object.assign(
{ type: 'atomic', text: ' ', key: block.getKey() },
{ entityData },
);
const atomicBlock = createContentBlock(blockSpec);
return acc.concat([atomicBlock]);
} catch (err) {
return acc.concat(block);
}
}
return acc.concat(block);
}, []);
const contentState = ContentState.createFromBlockArray(blocksFromHTML);
return this.setState({ editorState: EditorState.createWithContent(contentState, decorator) });
}
// Prevent errors if value is empty
return this.setState({ editorState: EditorState.createEmpty() });
};
render() {
const { placeholder } = this.context;
// this.previewHTML2(this.props.data);
return (
<div className={this.getClassName()}>
<WysiwygEditor

View File

@ -1,3 +1,5 @@
/* eslint-disable no-unused-vars */
function findLinkEntities(contentBlock, callback, contentState) {
contentBlock.findEntityRanges(character => {
const entityKey = character.getEntity();
@ -5,6 +7,13 @@ function findLinkEntities(contentBlock, callback, contentState) {
}, callback);
}
function findAtomicEntities(contentBlock, callback, contentState) {
contentBlock.findEntityRanges(character => {
const entityKey = character.getEntity();
return entityKey !== null && contentBlock.getType() === 'atomic';
}, callback);
}
function findImageEntities(contentBlock, callback, contentState) {
contentBlock.findEntityRanges(character => {
const entityKey = character.getEntity();
@ -23,4 +32,4 @@ function findVideoEntities(contentBlock, cb, contentState) {
const isVideoType = (fileName) => /\.(mp4|mpg|mpeg|mov|avi)$/i.test(fileName);
export { findLinkEntities, findImageEntities, findVideoEntities };
export { findAtomicEntities, findLinkEntities, findImageEntities, findVideoEntities };

View File

@ -9,7 +9,7 @@ import { List } from 'immutable';
import { DEFAULT_INDENTATION } from './constants';
export function createNewBlock(text = '', type = 'unstyled', key = genKey()) {
return new ContentBlock({ key, type, text, charaterList: List([]) });
return new ContentBlock({ key, type, text, characterList: List([]) });
}
export function getNextBlocksList(editorState, startKey) {