This commit is contained in:
8
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/defaultEmptyBlock.js
generated
vendored
Normal file
8
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/defaultEmptyBlock.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
function defaultEmptyBlock(text = '') {
|
||||
return {
|
||||
type: 'paragraph',
|
||||
children: [{ text }],
|
||||
};
|
||||
}
|
||||
|
||||
export default defaultEmptyBlock;
|
||||
56
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/events/keyDown.js
generated
vendored
Normal file
56
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/events/keyDown.js
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
import isHotkey from 'is-hotkey';
|
||||
import { Editor, Transforms } from 'slate';
|
||||
|
||||
import keyDownEnter from './keyDownEnter';
|
||||
import keyDownBackspace from './keyDownBackspace';
|
||||
import isCursorInNonDefaultBlock from '../locations/isCursorInNonDefaultBlock';
|
||||
import toggleBlock from './toggleBlock';
|
||||
import isCursorCollapsedAfterSoftBreak from '../locations/isCursorCollapsedAfterSoftBreak';
|
||||
|
||||
const HEADING_HOTKEYS = {
|
||||
'mod+1': 'heading-one',
|
||||
'mod+2': 'heading-two',
|
||||
'mod+3': 'heading-three',
|
||||
'mod+4': 'heading-four',
|
||||
'mod+5': 'heading-five',
|
||||
'mod+6': 'heading-six',
|
||||
};
|
||||
|
||||
function keyDown(event, editor) {
|
||||
if (!editor.selection) return;
|
||||
|
||||
for (const hotkey in HEADING_HOTKEYS) {
|
||||
if (isHotkey(hotkey, event)) {
|
||||
toggleBlock(editor, HEADING_HOTKEYS[hotkey]);
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (isHotkey('backspace', event) && isCursorCollapsedAfterSoftBreak(editor)) {
|
||||
const [, path] = Editor.previous(editor);
|
||||
Transforms.removeNodes(editor, { at: path });
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isCursorInNonDefaultBlock(editor)) return;
|
||||
|
||||
if (isHotkey('enter', event)) {
|
||||
const eventIntercepted = keyDownEnter(editor);
|
||||
if (eventIntercepted) {
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (isHotkey('backspace', event)) {
|
||||
const eventIntercepted = keyDownBackspace(editor);
|
||||
if (eventIntercepted) {
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default keyDown;
|
||||
27
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/events/keyDownBackspace.js
generated
vendored
Normal file
27
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/events/keyDownBackspace.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Transforms } from 'slate';
|
||||
|
||||
import unwrapIfCursorAtStart from '../transforms/unwrapIfCursorAtStart';
|
||||
import isCursorAtStartOfNonEmptyHeading from '../locations/isCursorAtStartOfNonEmptyHeading';
|
||||
import lowestMatchedAncestor from '../../matchers/lowestMatchedAncestor';
|
||||
import areCurrentAndPreviousBlocksOfType from '../locations/areCurrentAndPreviousBlocksOfType';
|
||||
import isCursorAtStartOfBlockType from '../locations/isCursorAtStartOfBlockType';
|
||||
|
||||
function keyDownBackspace(editor) {
|
||||
if (!editor.selection) return;
|
||||
|
||||
if (isCursorAtStartOfNonEmptyHeading(editor)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
isCursorAtStartOfBlockType(editor, 'quote') &&
|
||||
areCurrentAndPreviousBlocksOfType(editor, 'quote')
|
||||
) {
|
||||
Transforms.mergeNodes(editor, lowestMatchedAncestor(editor, 'quote'));
|
||||
return true;
|
||||
}
|
||||
|
||||
return unwrapIfCursorAtStart(editor, true);
|
||||
}
|
||||
|
||||
export default keyDownBackspace;
|
||||
26
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/events/keyDownEnter.js
generated
vendored
Normal file
26
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/events/keyDownEnter.js
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
import isCursorInBlockType from '../locations/isCursorInBlockType';
|
||||
import splitIntoParagraph from '../transforms/splitIntoParagraph';
|
||||
import unwrapIfCursorAtStart from '../transforms/unwrapIfCursorAtStart';
|
||||
import isCursorAtEndOfParagraph from '../locations/isCursorAtEndOfParagraph';
|
||||
|
||||
function keyDownEnter(editor) {
|
||||
if (!editor.selection) return;
|
||||
|
||||
if (isCursorInBlockType(editor, 'heading', true)) {
|
||||
return handleHeading(editor);
|
||||
}
|
||||
|
||||
return unwrapIfCursorAtStart(editor);
|
||||
}
|
||||
|
||||
function handleHeading(editor) {
|
||||
if (isCursorAtEndOfParagraph(editor)) {
|
||||
// split into paragraph if cursor is at the end of heading
|
||||
splitIntoParagraph(editor);
|
||||
return true;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
export default keyDownEnter;
|
||||
39
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/events/toggleBlock.js
generated
vendored
Normal file
39
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/events/toggleBlock.js
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
import { Range, Transforms } from 'slate';
|
||||
|
||||
import isCursorInBlockType from '../locations/isCursorInBlockType';
|
||||
import getListTypeAtCursor from '../locations/getListTypeAtCursor';
|
||||
import wrapListItemsInBlock from '../transforms/wrapListItemsInBlock';
|
||||
|
||||
function toggleBlock(editor, type) {
|
||||
const { selection } = editor;
|
||||
if (!selection) return;
|
||||
|
||||
const isHeading = type.startsWith('heading-');
|
||||
const isActive = isCursorInBlockType(editor, type, isHeading, Range.isExpanded(selection));
|
||||
const listType = getListTypeAtCursor(editor);
|
||||
|
||||
// headings do not contain paragraphs so they could be converted, not wrapped/unwrapped
|
||||
if (isHeading) {
|
||||
Transforms.setNodes(editor, { type: isActive ? 'paragraph' : type });
|
||||
return;
|
||||
}
|
||||
|
||||
const { focus, anchor } = selection;
|
||||
if (
|
||||
!isActive &&
|
||||
listType &&
|
||||
focus.path[focus.path.length - 3] != anchor.path[anchor.path.length - 3]
|
||||
) {
|
||||
return wrapListItemsInBlock(editor, type, listType);
|
||||
}
|
||||
|
||||
if (!isActive) {
|
||||
return Transforms.wrapNodes(editor, { type });
|
||||
}
|
||||
|
||||
Transforms.unwrapNodes(editor, { match: n => n.type === type });
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
export default toggleBlock;
|
||||
15
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/locations/areCurrentAndPreviousBlocksOfType.js
generated
vendored
Normal file
15
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/locations/areCurrentAndPreviousBlocksOfType.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Editor } from 'slate';
|
||||
|
||||
import lowestMatchedAncestor from '../../matchers/lowestMatchedAncestor';
|
||||
|
||||
function areCurrentAndPreviousBlocksOfType(editor, type) {
|
||||
const { selection } = editor;
|
||||
if (!selection) return false;
|
||||
|
||||
const [current] = Editor.nodes(editor, lowestMatchedAncestor(editor, 'block'));
|
||||
const previous = Editor.previous(editor, lowestMatchedAncestor(editor, type));
|
||||
|
||||
return current && previous && current[0].type === previous[0].type;
|
||||
}
|
||||
|
||||
export default areCurrentAndPreviousBlocksOfType;
|
||||
11
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/locations/getListTypeAtCursor.js
generated
vendored
Normal file
11
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/locations/getListTypeAtCursor.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Editor } from 'slate';
|
||||
|
||||
import lowestMatchedAncestor from '../../matchers/lowestMatchedAncestor';
|
||||
|
||||
function getListTypeAtCursor(editor) {
|
||||
const list = Editor.above(editor, lowestMatchedAncestor(editor, 'list'));
|
||||
if (!list) return null;
|
||||
return list[0].type;
|
||||
}
|
||||
|
||||
export default getListTypeAtCursor;
|
||||
14
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/locations/isCursorAtEndOfParagraph.js
generated
vendored
Normal file
14
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/locations/isCursorAtEndOfParagraph.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Editor } from 'slate';
|
||||
|
||||
import lowestMatchedAncestor from '../../matchers/lowestMatchedAncestor';
|
||||
|
||||
function isCursorAtEndOfParagraph(editor) {
|
||||
const { selection } = editor;
|
||||
if (!selection) return false;
|
||||
|
||||
const paragraph = Editor.above(editor, lowestMatchedAncestor(editor, 'paragraph'));
|
||||
|
||||
return !!paragraph && Editor.isEnd(editor, editor.selection.focus, paragraph[1]);
|
||||
}
|
||||
|
||||
export default isCursorAtEndOfParagraph;
|
||||
14
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/locations/isCursorAtStartOfBlockType.js
generated
vendored
Normal file
14
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/locations/isCursorAtStartOfBlockType.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Editor } from 'slate';
|
||||
|
||||
import lowestMatchedAncestor from '../../matchers/lowestMatchedAncestor';
|
||||
|
||||
function isCursorAtStartOfBlockType(editor, type) {
|
||||
const { selection } = editor;
|
||||
if (!selection) return false;
|
||||
|
||||
const block = Editor.above(editor, lowestMatchedAncestor(editor, type));
|
||||
|
||||
return !!block && Editor.isStart(editor, editor.selection.focus, block[1]);
|
||||
}
|
||||
|
||||
export default isCursorAtStartOfBlockType;
|
||||
22
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/locations/isCursorAtStartOfNonEmptyHeading.js
generated
vendored
Normal file
22
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/locations/isCursorAtStartOfNonEmptyHeading.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
import { Editor, Element } from 'slate';
|
||||
|
||||
function isCursorAtStartOfNonEmptyHeading(editor) {
|
||||
const { selection } = editor;
|
||||
if (!selection) return false;
|
||||
|
||||
const [match] = Array.from(
|
||||
Editor.nodes(editor, {
|
||||
match: n =>
|
||||
Element.isElement(n) && Editor.isBlock(editor, n) && `${n.type}`.startsWith('heading-'),
|
||||
mode: 'lowest',
|
||||
}),
|
||||
);
|
||||
|
||||
return (
|
||||
!!match &&
|
||||
Editor.isStart(editor, editor.selection.focus, match[1]) &&
|
||||
!Editor.isEmpty(editor, match[0])
|
||||
);
|
||||
}
|
||||
|
||||
export default isCursorAtStartOfNonEmptyHeading;
|
||||
13
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/locations/isCursorCollapsedAfterSoftBreak.js
generated
vendored
Normal file
13
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/locations/isCursorCollapsedAfterSoftBreak.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Editor, Range } from 'slate';
|
||||
|
||||
function isCursorCollapsedAfterSoftBreak(editor) {
|
||||
const { selection } = editor;
|
||||
if (!selection) return false;
|
||||
if (Range.isExpanded(selection)) return false;
|
||||
|
||||
const previous = Editor.previous(editor);
|
||||
|
||||
return previous && previous[0].type == 'break';
|
||||
}
|
||||
|
||||
export default isCursorCollapsedAfterSoftBreak;
|
||||
27
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/locations/isCursorInBlockType.js
generated
vendored
Normal file
27
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/locations/isCursorInBlockType.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Editor, Element } from 'slate';
|
||||
|
||||
function isCursorInBlockType(editor, type, ignoreHeadings, ignoreLists) {
|
||||
const { selection } = editor;
|
||||
if (!selection) return false;
|
||||
|
||||
const [match] = Array.from(
|
||||
Editor.nodes(editor, {
|
||||
match: n =>
|
||||
Element.isElement(n) &&
|
||||
Editor.isBlock(editor, n) &&
|
||||
n.type !== 'paragraph' &&
|
||||
n.type !== 'list-item' &&
|
||||
(ignoreHeadings || !`${n.type}`.startsWith('heading-')) &&
|
||||
(!ignoreLists || !`${n.type}`.endsWith('-list')),
|
||||
mode: 'lowest',
|
||||
}),
|
||||
);
|
||||
|
||||
return (
|
||||
!!match &&
|
||||
(match[0].type === type ||
|
||||
`${match[0].type}`.startsWith(`${type}-` || `${match[0].type}`.endsWith(`-${type}`)))
|
||||
);
|
||||
}
|
||||
|
||||
export default isCursorInBlockType;
|
||||
17
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/locations/isCursorInNonDefaultBlock.js
generated
vendored
Normal file
17
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/locations/isCursorInNonDefaultBlock.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import { Editor, Element } from 'slate';
|
||||
|
||||
function isCursorInNonDefaultBlock(editor) {
|
||||
const { selection } = editor;
|
||||
if (!selection) return false;
|
||||
|
||||
const [match] = Array.from(
|
||||
Editor.nodes(editor, {
|
||||
match: n => Element.isElement(n) && Editor.isBlock(editor, n) && n.type !== 'paragraph',
|
||||
mode: 'lowest',
|
||||
}),
|
||||
);
|
||||
|
||||
return !!match && !Editor.isEditor(match[0]);
|
||||
}
|
||||
|
||||
export default isCursorInNonDefaultBlock;
|
||||
13
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/transforms/splitIntoParagraph.js
generated
vendored
Normal file
13
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/transforms/splitIntoParagraph.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Editor, Transforms } from 'slate';
|
||||
|
||||
function splitIntoParagraph(editor) {
|
||||
Editor.withoutNormalizing(editor, () => {
|
||||
Transforms.splitNodes(editor, { always: true });
|
||||
Transforms.setNodes(editor, { type: 'paragraph' });
|
||||
});
|
||||
|
||||
Editor.normalize(editor, { force: true });
|
||||
return true;
|
||||
}
|
||||
|
||||
export default splitIntoParagraph;
|
||||
43
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/transforms/unwrapIfCursorAtStart.js
generated
vendored
Normal file
43
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/transforms/unwrapIfCursorAtStart.js
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
import { Editor, Transforms } from 'slate';
|
||||
|
||||
import lowestMatchedAncestor from '../../matchers/lowestMatchedAncestor';
|
||||
|
||||
function unwrapIfCursorAtStart(editor, mergeWithPrevious = false) {
|
||||
if (editor.selection.anchor.offset !== 0) return false;
|
||||
|
||||
let [node, path] = Editor.above(editor, lowestMatchedAncestor(editor, 'non-default'));
|
||||
|
||||
if (path.length == 0) return false;
|
||||
|
||||
const isHeading = `${node.type}`.startsWith('heading-');
|
||||
if (isHeading) {
|
||||
Transforms.setNodes(editor, { type: 'paragraph' });
|
||||
return false;
|
||||
}
|
||||
|
||||
const isBlock = Editor.isBlock(editor, node);
|
||||
const [parentBlock, parentBlockPath] = Editor.above(
|
||||
editor,
|
||||
lowestMatchedAncestor(editor, 'block'),
|
||||
);
|
||||
if (!isBlock) {
|
||||
if (!Editor.isStart(editor, path, parentBlockPath)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
[node, path] = [parentBlock, parentBlockPath];
|
||||
}
|
||||
|
||||
Editor.withoutNormalizing(editor, () => {
|
||||
Transforms.unwrapNodes(editor, { match: n => n.type === node.type, split: true });
|
||||
|
||||
if (mergeWithPrevious) {
|
||||
Transforms.mergeNodes(editor);
|
||||
}
|
||||
});
|
||||
|
||||
Editor.normalize(editor, { force: true });
|
||||
return true;
|
||||
}
|
||||
|
||||
export default unwrapIfCursorAtStart;
|
||||
11
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/transforms/wrapListItemsInBlock.js
generated
vendored
Normal file
11
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/transforms/wrapListItemsInBlock.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Editor, Transforms } from 'slate';
|
||||
|
||||
function wrapListItemsInBlock(editor, blockType, listType) {
|
||||
Editor.withoutNormalizing(editor, () => {
|
||||
Transforms.wrapNodes(editor, { type: listType });
|
||||
Transforms.wrapNodes(editor, { type: blockType }, { match: n => n.type === listType });
|
||||
Transforms.liftNodes(editor, { match: n => n.type === blockType });
|
||||
});
|
||||
Editor.normalize(editor, { force: true });
|
||||
}
|
||||
export default wrapListItemsInBlock;
|
||||
15
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/withBlocks.js
generated
vendored
Normal file
15
node_modules/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/withBlocks.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
import keyDown from './events/keyDown';
|
||||
import toggleBlock from './events/toggleBlock';
|
||||
|
||||
function withBlocks(editor) {
|
||||
if (editor.keyDownHandlers === undefined) {
|
||||
editor.keyDownHandlers = [];
|
||||
}
|
||||
editor.keyDownHandlers.push((event, editor) => keyDown(event, editor));
|
||||
|
||||
editor.toggleBlock = type => toggleBlock(editor, type);
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
export default withBlocks;
|
||||
Reference in New Issue
Block a user