Skip to content

Commit 739dcd8

Browse files
committed
Support image
1 parent a6685d0 commit 739dcd8

File tree

8 files changed

+114
-3
lines changed

8 files changed

+114
-3
lines changed

src/components/Image/index.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import React from 'react';
2+
import { Entity } from 'draft-js';
3+
4+
const Image = ({ entityKey, children }) => {
5+
const { src, alt, title } = Entity.get(entityKey).getData();
6+
return (
7+
<span>
8+
{children}
9+
<img src={src} alt={alt} title={title} />
10+
</span>
11+
);
12+
};
13+
14+
export default Image;
File renamed without changes.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Entity } from 'draft-js';
2+
3+
const createImageStrategy = () => {
4+
const findImageEntities = (contentBlock, callback) => {
5+
contentBlock.findEntityRanges((character) => {
6+
const entityKey = character.getEntity();
7+
return (
8+
entityKey !== null &&
9+
Entity.get(entityKey).getType() === 'IMG'
10+
);
11+
}, callback);
12+
};
13+
return findImageEntities;
14+
};
15+
16+
export default createImageStrategy;

src/decorators/image/index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import createImageStrategy from './imageStrategy';
2+
import Image from '../../components/Image';
3+
4+
const createImageDecorator = (config, store) => ({
5+
strategy: createImageStrategy(config, store),
6+
component: Image,
7+
});
8+
9+
export default createImageDecorator;

src/decorators/link/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import createLinkStrategy from './linkStrategy';
2-
import Link from './components/Link';
2+
import Link from '../../components/Link';
33

44
const createLinkDecorator = (config, store) => ({
55
strategy: createLinkStrategy(config, store),

src/index.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,18 @@ import handleInlineStyle from './modifiers/handleInlineStyle';
88
import handleNewCodeBlock from './modifiers/handleNewCodeBlock';
99
import insertEmptyBlock from './modifiers/insertEmptyBlock';
1010
import handleLink from './modifiers/handleLink';
11+
import handleImage from './modifiers/handleImage';
1112
import createLinkDecorator from './decorators/link';
13+
import createImageDecorator from './decorators/image';
1214

1315
const createMarkdownShortcutsPlugin = (config = {}) => {
1416
const store = {};
1517
return {
1618
blockRenderMap,
17-
decorators: [createLinkDecorator(config, store)],
19+
decorators: [
20+
createLinkDecorator(config, store),
21+
createImageDecorator(config, store)
22+
],
1823
initialize({ setEditorState, getEditorState }) {
1924
store.setEditorState = setEditorState;
2025
store.getEditorState = getEditorState;
@@ -67,11 +72,14 @@ const createMarkdownShortcutsPlugin = (config = {}) => {
6772
const editorState = getEditorState();
6873
let newEditorState = handleBlockType(editorState, character);
6974
if (editorState === newEditorState) {
70-
newEditorState = handleInlineStyle(editorState, character);
75+
newEditorState = handleImage(editorState, character);
7176
}
7277
if (editorState === newEditorState) {
7378
newEditorState = handleLink(editorState, character);
7479
}
80+
if (editorState === newEditorState) {
81+
newEditorState = handleInlineStyle(editorState, character);
82+
}
7583
if (editorState !== newEditorState) {
7684
setEditorState(newEditorState);
7785
return 'handled';

src/modifiers/handleImage.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import insertImage from './insertImage';
2+
3+
const handleImage = (editorState, character) => {
4+
const re = /!\[([^\]]*)]\(([^)"]+)(?: "([^"]+)")?\)/g;
5+
const key = editorState.getSelection().getStartKey();
6+
const text = editorState.getCurrentContent().getBlockForKey(key).getText();
7+
const line = `${text}${character}`;
8+
let newEditorState = editorState;
9+
let matchArr;
10+
do {
11+
matchArr = re.exec(line);
12+
if (matchArr) {
13+
newEditorState = insertImage(newEditorState, matchArr);
14+
}
15+
} while (matchArr);
16+
return newEditorState;
17+
};
18+
19+
export default handleImage;

src/modifiers/insertImage.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { EditorState, RichUtils, SelectionState, Entity, Modifier } from 'draft-js';
2+
3+
4+
const insertLink = (editorState, matchArr) => {
5+
const currentContent = editorState.getCurrentContent();
6+
const selection = editorState.getSelection();
7+
const key = selection.getStartKey();
8+
const [
9+
matchText,
10+
alt,
11+
src,
12+
title
13+
] = matchArr;
14+
const { index } = matchArr;
15+
const focusOffset = index + matchText.length;
16+
const wordSelection = SelectionState.createEmpty(key).merge({
17+
anchorOffset: index,
18+
focusOffset
19+
});
20+
const entityKey = Entity.create(
21+
'IMG',
22+
'IMMUTABLE',
23+
{ alt, src, title }
24+
);
25+
let newContentState = Modifier.replaceText(
26+
currentContent,
27+
wordSelection,
28+
'\u200B',
29+
null,
30+
entityKey
31+
);
32+
newContentState = Modifier.insertText(
33+
newContentState,
34+
newContentState.getSelectionAfter(),
35+
' '
36+
);
37+
const newWordSelection = wordSelection.merge({
38+
focusOffset: index + 1
39+
});
40+
let newEditorState = EditorState.push(editorState, newContentState, 'insert-image');
41+
newEditorState = RichUtils.toggleLink(newEditorState, newWordSelection, entityKey);
42+
return EditorState.forceSelection(newEditorState, newContentState.getSelectionAfter());
43+
};
44+
45+
export default insertLink;

0 commit comments

Comments
 (0)