Skip to content
This repository was archived by the owner on Oct 11, 2022. It is now read-only.

Commit 8df2a8d

Browse files
committed
merge
2 parents f3b06b3 + 6ce7a20 commit 8df2a8d

File tree

5 files changed

+130
-25
lines changed

5 files changed

+130
-25
lines changed

src/__test__/plugin.test.js

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import sinon from "sinon";
21
import Draft, { EditorState, SelectionState, ContentBlock } from "draft-js";
32
import {
43
CheckableListItem,
@@ -99,10 +98,12 @@ describe("draft-js-markdown-plugin", () => {
9998
it("is loaded", () => {
10099
expect(typeof createMarkdownPlugin).toBe("function");
101100
});
101+
102102
it("initialize", () => {
103103
plugin.initialize(store);
104104
expect(plugin.store).toEqual(store);
105105
});
106+
106107
describe("handleReturn", () => {
107108
beforeEach(() => {
108109
subject = () =>
@@ -172,6 +173,33 @@ describe("draft-js-markdown-plugin", () => {
172173
expect(subject()).toBe("not-handled");
173174
});
174175

176+
it("resets curent inline style", () => {
177+
currentRawContentState = {
178+
entityMap: {},
179+
blocks: [
180+
{
181+
key: "item1",
182+
text: "item1",
183+
type: "unstyled",
184+
depth: 0,
185+
inlineStyleRanges: [{ offset: 0, length: 5, style: "BOLD" }],
186+
entityRanges: [],
187+
data: {},
188+
},
189+
],
190+
};
191+
192+
currentSelectionState = currentSelectionState.merge({
193+
focusOffset: 5,
194+
anchorOffset: 5,
195+
});
196+
197+
expect(subject()).toBe("handled");
198+
expect(store.setEditorState).toHaveBeenCalled();
199+
newEditorState = store.setEditorState.mock.calls[0][0];
200+
expect(newEditorState.getCurrentInlineStyle().size).toBe(0);
201+
});
202+
175203
it("leaves from list", () => {
176204
createMarkdownPlugin.__Rewire__("leaveList", modifierSpy); // eslint-disable-line no-underscore-dangle
177205
currentRawContentState = {
@@ -192,6 +220,38 @@ describe("draft-js-markdown-plugin", () => {
192220
expect(modifierSpy).toHaveBeenCalledTimes(1);
193221
expect(store.setEditorState).toHaveBeenCalledWith(newEditorState);
194222
});
223+
224+
it("adds list item and transforms markdown", () => {
225+
// createMarkdownPlugin.__Rewire__("leaveList", modifierSpy); // eslint-disable-line no-underscore-dangle
226+
currentRawContentState = {
227+
entityMap: {},
228+
blocks: [
229+
{
230+
key: "item1",
231+
text: "**some bold text**",
232+
type: "unordered-list-item",
233+
depth: 0,
234+
inlineStyleRanges: [],
235+
entityRanges: [],
236+
data: {},
237+
},
238+
],
239+
};
240+
currentSelectionState = currentSelectionState.merge({
241+
focusOffset: 18,
242+
anchorOffset: 18,
243+
});
244+
expect(subject()).toBe("handled");
245+
// expect(modifierSpy).toHaveBeenCalledTimes(1);
246+
expect(store.setEditorState).toHaveBeenCalledTimes(1);
247+
newEditorState = store.setEditorState.mock.calls[0][0];
248+
const newRawContentState = Draft.convertToRaw(
249+
newEditorState.getCurrentContent()
250+
);
251+
expect(newRawContentState.blocks.length).toBe(2);
252+
expect(newEditorState.getCurrentInlineStyle().size).toBe(0);
253+
});
254+
195255
const testInsertNewBlock = type => () => {
196256
createMarkdownPlugin.__Rewire__("insertEmptyBlock", modifierSpy); // eslint-disable-line no-underscore-dangle
197257
currentRawContentState = {

src/index.js

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,19 @@ import {
66
CHECKABLE_LIST_ITEM,
77
} from "draft-js-checkable-list-item";
88

9-
import { Map } from "immutable";
10-
9+
import { Map, OrderedSet, is } from "immutable";
10+
import {
11+
getDefaultKeyBinding,
12+
Modifier,
13+
EditorState,
14+
RichUtils,
15+
DefaultDraftInlineStyle,
16+
} from "draft-js";
1117
import adjustBlockDepth from "./modifiers/adjustBlockDepth";
1218
import handleBlockType from "./modifiers/handleBlockType";
1319
import handleInlineStyle from "./modifiers/handleInlineStyle";
1420
import handleNewCodeBlock from "./modifiers/handleNewCodeBlock";
21+
import resetInlineStyle from "./modifiers/resetInlineStyle";
1522
import insertEmptyBlock from "./modifiers/insertEmptyBlock";
1623
import handleLink from "./modifiers/handleLink";
1724
import handleImage from "./modifiers/handleImage";
@@ -70,9 +77,11 @@ function checkReturnForState(editorState, ev) {
7077
const currentBlock = contentState.getBlockForKey(key);
7178
const type = currentBlock.getType();
7279
const text = currentBlock.getText();
80+
7381
if (/-list-item$/.test(type) && text === "") {
7482
newEditorState = leaveList(editorState);
7583
}
84+
7685
if (
7786
newEditorState === editorState &&
7887
(ev.ctrlKey ||
@@ -82,7 +91,15 @@ function checkReturnForState(editorState, ev) {
8291
/^header-/.test(type) ||
8392
type === "blockquote")
8493
) {
85-
newEditorState = insertEmptyBlock(editorState);
94+
// transform markdown (if we aren't in a codeblock that is)
95+
if (!inCodeBlock(editorState)) {
96+
newEditorState = checkCharacterForState(newEditorState, "\n");
97+
}
98+
if (newEditorState === editorState) {
99+
newEditorState = insertEmptyBlock(newEditorState);
100+
} else {
101+
newEditorState = RichUtils.toggleBlockType(newEditorState, type);
102+
}
86103
}
87104
if (
88105
newEditorState === editorState &&
@@ -165,19 +182,36 @@ const createMarkdownPlugin = (config = {}) => {
165182
handleReturn(ev, editorState, { setEditorState }) {
166183
if (inLink(editorState)) return "not-handled";
167184

168-
const selection = editorState.getSelection();
169185
let newEditorState = checkReturnForState(editorState, ev);
170-
if (editorState !== newEditorState) {
186+
const selection = newEditorState.getSelection();
187+
188+
// exit code blocks
189+
if (
190+
inCodeBlock(editorState) &&
191+
!is(editorState.getImmutable(), newEditorState.getImmutable())
192+
) {
171193
setEditorState(newEditorState);
172194
return "handled";
173195
}
174196

175-
// If we're in a code block don't add markdown to it
176-
if (inCodeBlock(editorState)) return "not-handled";
197+
newEditorState = checkCharacterForState(newEditorState, "\n");
198+
let content = newEditorState.getCurrentContent();
177199

178-
newEditorState = checkCharacterForState(editorState, "\n");
179-
if (editorState !== newEditorState) {
180-
setEditorState(newEditorState);
200+
// if there are actually no changes but the editorState has a
201+
// current inline style we want to split the block
202+
if (
203+
is(editorState.getImmutable(), newEditorState.getImmutable()) &&
204+
editorState.getCurrentInlineStyle().size > 0
205+
) {
206+
content = Modifier.splitBlock(content, selection);
207+
}
208+
209+
newEditorState = resetInlineStyle(newEditorState);
210+
211+
if (!is(editorState.getImmutable(), newEditorState.getImmutable())) {
212+
setEditorState(
213+
EditorState.push(newEditorState, content, "split-block")
214+
);
181215
return "handled";
182216
}
183217

src/modifiers/__test__/changeCurrentInlineStyle-test.js

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,18 +70,12 @@ describe("changeCurrentInlineStyle", () => {
7070
"\n"
7171
);
7272
expect(newEditorState).not.toEqual(editorState);
73-
expect(Draft.convertToRaw(newEditorState.getCurrentContent())).toEqual(
74-
rawContentState(
75-
"foo bar\n baz",
76-
[
77-
{
78-
length: 3,
79-
offset: 4,
80-
style: "CODE",
81-
},
82-
],
83-
"CODE"
84-
)
85-
);
73+
const contentState = Draft.convertToRaw(newEditorState.getCurrentContent());
74+
expect(contentState.blocks.length).toBe(2);
75+
expect(contentState.blocks[0].text).toEqual("foo bar");
76+
expect(contentState.blocks[0].inlineStyleRanges).toEqual([
77+
{ offset: 4, length: 3, style: "CODE" },
78+
]);
79+
expect(contentState.blocks[1].text).toEqual(" baz");
8680
});
8781
});

src/modifiers/changeCurrentInlineStyle.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,18 @@ const changeCurrentInlineStyle = (editorState, matchArr, style, character) => {
2121

2222
let newContentState = currentContent;
2323

24+
// if appendChar isn't defined add a space
25+
// if character is a newline - add empty string and later on - split block
26+
let appendChar = character == null ? " " : character;
27+
if (character == "\n") appendChar = "";
28+
2429
// remove markdown delimiter at end
2530
newContentState = Modifier.replaceText(
2631
newContentState,
2732
wordSelection.merge({
2833
anchorOffset: wordSelection.getFocusOffset() - markdownCharacterLength,
2934
}),
30-
character || " "
35+
appendChar
3136
);
3237

3338
let afterSelection = newContentState.getSelectionAfter();
@@ -56,6 +61,11 @@ const changeCurrentInlineStyle = (editorState, matchArr, style, character) => {
5661
style
5762
);
5863

64+
if (character == "\n") {
65+
newContentState = Modifier.splitBlock(newContentState, afterSelection);
66+
afterSelection = newContentState.getSelectionAfter();
67+
}
68+
5969
const newEditorState = EditorState.push(
6070
editorState,
6171
newContentState,

src/modifiers/resetInlineStyle.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { OrderedSet } from "immutable";
2+
import { EditorState } from "draft-js";
3+
4+
export default editorState =>
5+
editorState.getCurrentInlineStyle().size === 0
6+
? editorState
7+
: EditorState.setInlineStyleOverride(editorState, OrderedSet());

0 commit comments

Comments
 (0)