Skip to content

Commit

Permalink
Implement beforeHandleReturn
Browse files Browse the repository at this point in the history
  • Loading branch information
ngs committed Apr 28, 2017
1 parent ca3739e commit d1bb83f
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 30 deletions.
42 changes: 34 additions & 8 deletions demo/client/components/DemoEditor/index.js
Expand Up @@ -18,20 +18,25 @@ window.Draft = Draft;
const mentionPlugin = createMentionPlugin();
const { MentionSuggestions } = mentionPlugin;

const plugins = [
prismPlugin,
mentionPlugin,
createMarkdownShortcutsPlugin()
];

const contentState = ContentState.createFromText('');
const initialEditorState = EditorState.createWithContent(contentState);

export default class DemoEditor extends Component {
constructor(...args) {
super(...args);
this.plugins = [
prismPlugin,
createMarkdownShortcutsPlugin({
beforeHandleReturn: this.beforeHandleReturn
}),
mentionPlugin
];
}

state = {
editorState: initialEditorState,
suggestions: mentions
suggestions: mentions,
isSuggestionsOpened: false
};

componentDidMount = () => {
Expand Down Expand Up @@ -60,6 +65,25 @@ export default class DemoEditor extends Component {
// get the mention object selected
}

onCloseSuggestions = () => {
this.setState({
isSuggestionsOpened: false
});
}

onOpenSuggestions = () => {
this.setState({
isSuggestionsOpened: true
});
}

beforeHandleReturn = () => {
if (this.state.isSuggestionsOpened) {
return 'handled';
}
return 'not-handled';
}

focus = () => {
this.editor.focus();
};
Expand All @@ -74,14 +98,16 @@ export default class DemoEditor extends Component {
<Editor
editorState={editorState}
onChange={this.onChange}
plugins={plugins}
plugins={this.plugins}
spellCheck
ref={(element) => { this.editor = element; }}
/>
<MentionSuggestions
onSearchChange={this.onSearchChange}
suggestions={this.state.suggestions}
onAddMention={this.onAddMention}
onClose={this.onCloseSuggestions}
onOpen={this.onOpenSuggestions}
/>
</div>
</div>
Expand Down
50 changes: 38 additions & 12 deletions src/__test__/plugin-test.js
Expand Up @@ -35,6 +35,7 @@ describe('draft-js-markdown-shortcuts-plugin', () => {
[
[],
[{}],
[{ beforeHandleReturn: () => 'handled' }],
].forEach((args) => {
beforeEach(() => {
modifierSpy = sinon.spy(() => newEditorState);
Expand Down Expand Up @@ -90,6 +91,7 @@ describe('draft-js-markdown-shortcuts-plugin', () => {
expect(plugin.store).to.deep.equal(store);
});
describe('handleReturn', () => {
let hasBeforeHandleReturn = args[0] && args[0].beforeHandleReturn;
beforeEach(() => {
subject = () => plugin.handleReturn(event, store);
});
Expand Down Expand Up @@ -124,9 +126,15 @@ describe('draft-js-markdown-shortcuts-plugin', () => {
data: {}
}]
};
expect(subject()).to.equal('handled');
expect(modifierSpy).to.have.been.calledOnce();
expect(store.setEditorState).to.have.been.calledWith(newEditorState);
if (hasBeforeHandleReturn) {
expect(subject()).to.equal('not-handled');
expect(modifierSpy).not.to.have.been.called();
expect(store.setEditorState).not.to.have.been.called();
} else {
expect(subject()).to.equal('handled');
expect(modifierSpy).to.have.been.calledOnce();
expect(store.setEditorState).to.have.been.calledWith(newEditorState);
}
});
const testInsertNewBlock = (type) => () => {
createMarkdownShortcutsPlugin.__Rewire__('insertEmptyBlock', modifierSpy); // eslint-disable-line no-underscore-dangle
Expand All @@ -142,9 +150,15 @@ describe('draft-js-markdown-shortcuts-plugin', () => {
data: {}
}]
};
expect(subject()).to.equal('handled');
expect(modifierSpy).to.have.been.calledOnce();
expect(store.setEditorState).to.have.been.calledWith(newEditorState);
if (hasBeforeHandleReturn) {
expect(subject()).to.equal('not-handled');
expect(modifierSpy).not.to.have.been.called();
expect(store.setEditorState).not.to.have.been.called();
} else {
expect(subject()).to.equal('handled');
expect(modifierSpy).to.have.been.calledOnce();
expect(store.setEditorState).to.have.been.calledWith(newEditorState);
}
};
['one', 'two', 'three', 'four', 'five', 'six'].forEach((level) => {
describe(`on header-${level}`, () => {
Expand Down Expand Up @@ -175,9 +189,15 @@ describe('draft-js-markdown-shortcuts-plugin', () => {
data: {}
}]
};
expect(subject()).to.equal('handled');
expect(modifierSpy).to.have.been.calledOnce();
expect(store.setEditorState).to.have.been.calledWith(newEditorState);
if (hasBeforeHandleReturn) {
expect(subject()).to.equal('not-handled');
expect(modifierSpy).not.to.have.been.called();
expect(store.setEditorState).not.to.have.been.called();
} else {
expect(subject()).to.equal('handled');
expect(modifierSpy).to.have.been.calledOnce();
expect(store.setEditorState).to.have.been.calledWith(newEditorState);
}
});
it('insert new line char from code-block', () => {
createMarkdownShortcutsPlugin.__Rewire__('insertText', modifierSpy); // eslint-disable-line no-underscore-dangle
Expand All @@ -193,9 +213,15 @@ describe('draft-js-markdown-shortcuts-plugin', () => {
data: {}
}]
};
expect(subject()).to.equal('handled');
expect(modifierSpy).to.have.been.calledOnce();
expect(store.setEditorState).to.have.been.calledWith(newEditorState);
if (hasBeforeHandleReturn) {
expect(subject()).to.equal('not-handled');
expect(modifierSpy).not.to.have.been.called();
expect(store.setEditorState).not.to.have.been.called();
} else {
expect(subject()).to.equal('handled');
expect(modifierSpy).to.have.been.calledOnce();
expect(store.setEditorState).to.have.been.calledWith(newEditorState);
}
});
});
describe('blockStyleFn', () => {
Expand Down
30 changes: 20 additions & 10 deletions src/index.js
Expand Up @@ -19,6 +19,12 @@ import createImageDecorator from './decorators/image';
import { addText, addEmptyBlock } from './utils';

const INLINE_STYLE_CHARACTERS = [' ', '*', '_'];
const HANDLED = 'handled';
const NOT_HANDLED = 'not-handled';

const defaultConfig = {
beforeHandleReturn: () => NOT_HANDLED
};

function checkCharacterForState(editorState, character) {
let newEditorState = handleBlockType(editorState, character);
Expand Down Expand Up @@ -60,6 +66,7 @@ function checkReturnForState(editorState, ev) {
}

const createMarkdownShortcutsPlugin = (config = {}) => {
const { beforeHandleReturn } = { ...defaultConfig, ...config };
const store = {};
return {
store,
Expand Down Expand Up @@ -109,36 +116,39 @@ const createMarkdownShortcutsPlugin = (config = {}) => {
const newEditorState = adjustBlockDepth(editorState, ev);
if (newEditorState !== editorState) {
setEditorState(newEditorState);
return 'handled';
return HANDLED;
}
return 'not-handled';
return NOT_HANDLED;
},
handleReturn(ev, { setEditorState, getEditorState }) {
if (beforeHandleReturn() === HANDLED) {
return undefined;
}
const editorState = getEditorState();
const newEditorState = checkReturnForState(editorState, ev);
if (editorState !== newEditorState) {
setEditorState(newEditorState);
return 'handled';
return HANDLED;
}
return 'not-handled';
return NOT_HANDLED;
},
handleBeforeInput(character, { getEditorState, setEditorState }) {
if (character !== ' ') {
return 'not-handled';
return NOT_HANDLED;
}
const editorState = getEditorState();
const newEditorState = checkCharacterForState(editorState, character);
if (editorState !== newEditorState) {
setEditorState(newEditorState);
return 'handled';
return HANDLED;
}
return 'not-handled';
return NOT_HANDLED;
},
handlePastedText(text, html, { getEditorState, setEditorState }) {
const editorState = getEditorState();
let newEditorState = editorState;
let buffer = [];
for (let i = 0; i < text.length; i++) { // eslint-disable-line no-plusplus
for (let i = 0; i < text.length; i += 1) {
if (INLINE_STYLE_CHARACTERS.indexOf(text[i]) >= 0) {
newEditorState = addText(newEditorState, buffer.join('') + text[i]);
newEditorState = checkCharacterForState(newEditorState, text[i]);
Expand All @@ -158,9 +168,9 @@ const createMarkdownShortcutsPlugin = (config = {}) => {

if (editorState !== newEditorState) {
setEditorState(newEditorState);
return 'handled';
return HANDLED;
}
return 'not-handled';
return NOT_HANDLED;
}
};
};
Expand Down

0 comments on commit d1bb83f

Please sign in to comment.