Flowtyping

This commit is contained in:
Tom Moor
2017-12-03 11:13:35 -08:00
parent 15e8e50601
commit 802f6e6594
23 changed files with 168 additions and 189 deletions

View File

@ -1,10 +1,5 @@
// @flow
import type { change } from 'slate-prop-types';
type KeyData = {
isMeta: boolean,
key: string,
};
import { Change } from 'slate';
const inlineShortcuts = [
{ mark: 'bold', shortcut: '**' },
@ -18,22 +13,19 @@ const inlineShortcuts = [
export default function MarkdownShortcuts() {
return {
/**
* On key down, check for our specific key shortcuts.
*/
onKeyDown(ev: SyntheticEvent, data: KeyData, change: change) {
switch (data.key) {
onKeyDown(ev: SyntheticKeyboardEvent, change: Change) {
switch (ev.key) {
case '-':
return this.onDash(ev, change);
case '`':
return this.onBacktick(ev, change);
case 'tab':
case 'Tab':
return this.onTab(ev, change);
case 'space':
case ' ':
return this.onSpace(ev, change);
case 'backspace':
case 'Backspace':
return this.onBackspace(ev, change);
case 'enter':
case 'Enter':
return this.onEnter(ev, change);
default:
return null;
@ -44,10 +36,10 @@ export default function MarkdownShortcuts() {
* On space, if it was after an auto-markdown shortcut, convert the current
* node into the shortcut's corresponding type.
*/
onSpace(ev: SyntheticEvent, change: change) {
const { state } = change;
if (state.isExpanded) return;
const { startBlock, startOffset } = state;
onSpace(ev: SyntheticKeyboardEvent, change: Change) {
const { value } = change;
if (value.isExpanded) return;
const { startBlock, startOffset } = value;
const chars = startBlock.text.slice(0, startOffset).trim();
const type = this.getType(chars);
@ -58,7 +50,7 @@ export default function MarkdownShortcuts() {
let checked;
if (chars === '[x]') checked = true;
if (chars === '[ ]') checked = false;
const change = state.change().setBlock({ type, data: { checked } });
change.setBlock({ type, data: { checked } });
if (type === 'list-item') {
if (checked !== undefined) {
@ -99,40 +91,32 @@ export default function MarkdownShortcuts() {
// if we have multiple tags then mark the text between as inline code
if (inlineTags.length > 1) {
const change = state.change();
const firstText = startBlock.getFirstText();
const firstCodeTagIndex = inlineTags[0];
const lastCodeTagIndex = inlineTags[inlineTags.length - 1];
change.removeTextByKey(
firstText.key,
lastCodeTagIndex,
shortcut.length
);
change.removeTextByKey(
firstText.key,
firstCodeTagIndex,
shortcut.length
);
change.moveOffsetsTo(
firstCodeTagIndex,
lastCodeTagIndex - shortcut.length
);
change.addMark(mark);
return change.collapseToEnd().removeMark(mark);
change
.removeTextByKey(firstText.key, lastCodeTagIndex, shortcut.length)
.removeTextByKey(firstText.key, firstCodeTagIndex, shortcut.length)
.moveOffsetsTo(
firstCodeTagIndex,
lastCodeTagIndex - shortcut.length
)
.addMark(mark)
.collapseToEnd()
.removeMark(mark);
}
}
},
onDash(ev: SyntheticEvent, change: change) {
const { state } = change;
if (state.isExpanded) return;
const { startBlock, startOffset } = state;
onDash(ev: SyntheticKeyboardEvent, change: Change) {
const { value } = change;
if (value.isExpanded) return;
const { startBlock, startOffset } = value;
const chars = startBlock.text.slice(0, startOffset).replace(/\s*/g, '');
if (chars === '--') {
ev.preventDefault();
return state
.change()
return change
.extendToStartOf(startBlock)
.delete()
.setBlock({
@ -144,16 +128,15 @@ export default function MarkdownShortcuts() {
}
},
onBacktick(ev: SyntheticEvent, change: change) {
const { state } = change;
if (state.isExpanded) return;
const { startBlock, startOffset } = state;
onBacktick(ev: SyntheticKeyboardEvent, change: Change) {
const { value } = change;
if (value.isExpanded) return;
const { startBlock, startOffset } = value;
const chars = startBlock.text.slice(0, startOffset).replace(/\s*/g, '');
if (chars === '``') {
ev.preventDefault();
return state
.change()
return change
.extendToStartOf(startBlock)
.delete()
.setBlock({
@ -162,20 +145,22 @@ export default function MarkdownShortcuts() {
}
},
onBackspace(ev: SyntheticEvent, change: change) {
const { state } = change;
if (change.isExpanded) return;
const { startBlock, selection, startOffset } = state;
onBackspace(ev: SyntheticKeyboardEvent, change: Change) {
const { value } = change;
if (value.isExpanded) return;
const { startBlock, selection, startOffset } = value;
// If at the start of a non-paragraph, convert it back into a paragraph
if (startOffset === 0) {
if (startBlock.type === 'paragraph') return;
ev.preventDefault();
const change = state.change().setBlock('paragraph');
change.setBlock('paragraph');
if (startBlock.type === 'list-item')
if (startBlock.type === 'list-item') {
change.unwrapBlock('bulleted-list');
}
return change;
}
@ -195,14 +180,12 @@ export default function MarkdownShortcuts() {
.reverse()
.takeUntil((v, k) => !v.marks.some(mark => mark.type === 'code'));
return state
.change()
.removeMarkByKey(
textNode.key,
change.startOffset - charsInCodeBlock.size,
change.startOffset,
'code'
);
change.removeMarkByKey(
textNode.key,
change.startOffset - charsInCodeBlock.size,
change.startOffset,
'code'
);
}
}
},
@ -211,15 +194,12 @@ export default function MarkdownShortcuts() {
* On tab, if at the end of the heading jump to the main body content
* as if it is another input field (act the same as enter).
*/
onTab(ev: SyntheticEvent, change: change) {
const { state } = change;
onTab(ev: SyntheticKeyboardEvent, change: Change) {
const { value } = change;
if (state.startBlock.type === 'heading1') {
if (value.startBlock.type === 'heading1') {
ev.preventDefault();
return state
.change()
.splitBlock()
.setBlock('paragraph');
change.splitBlock().setBlock('paragraph');
}
},
@ -227,10 +207,10 @@ export default function MarkdownShortcuts() {
* On return, if at the end of a node type that should not be extended,
* create a new paragraph below it.
*/
onEnter(ev: SyntheticEvent, change: change) {
const { state } = change;
if (state.isExpanded) return;
const { startBlock, startOffset, endOffset } = state;
onEnter(ev: SyntheticKeyboardEvent, change: Change) {
const { value } = change;
if (value.isExpanded) return;
const { startBlock, startOffset, endOffset } = value;
if (startOffset === 0 && startBlock.length === 0)
return this.onBackspace(ev, change);
if (endOffset !== startBlock.length) return;
@ -239,10 +219,7 @@ export default function MarkdownShortcuts() {
// insert a new paragraph
if (startBlock.type === 'image') {
ev.preventDefault();
return state
.change()
.collapseToEnd()
.insertBlock('paragraph');
return change.collapseToEnd().insertBlock('paragraph');
}
// Hitting enter in a heading or blockquote will split the node at that
@ -260,10 +237,7 @@ export default function MarkdownShortcuts() {
}
ev.preventDefault();
return state
.change()
.splitBlock()
.setBlock('paragraph');
change.splitBlock().setBlock('paragraph');
},
/**