Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | 1x 1x 1x 5x 2x 1x 2x 2x 2x 1x 2x 2x 2x 4x 2x 1x 2x 2x 2x 2x 2x 2x 2x 1x 1x 1x 1x 1x 1x 1x 2x 2x 1x 6x 9x 6x 1x 6x 6x 1x 1x 1x 6x | import {Editor, Element as SlateElement, Node, Path, Transforms} from 'slate';
import {insertVoidBlock} from './voidInsert';
import type {CustomElement, CustomText, FileElement} from '../types';
export const isFileElement = (node: unknown): node is FileElement =>
SlateElement.isElement(node) && (node as any).type === 'file';
const createParagraphElement = (): CustomElement => ({
type: 'p',
children: [{text: ''}] as CustomText[],
});
const createFileElement = (thingId: string, caption?: string): FileElement => {
const el: FileElement = {
type: 'file',
'@thing': thingId,
children: [{text: ''}] as CustomText[],
};
if (caption && caption.trim()) el.caption = caption.trim();
return el;
};
const getActiveFileEntry = (editor: Editor): [FileElement, Path] | undefined => {
const {selection} = editor;
Iif (!selection) return;
const match = Editor.above(editor, {
at: Editor.unhangRange(editor, selection),
match: (node) => isFileElement(node),
});
return (match as [FileElement, Path] | undefined) ?? void 0;
};
const insertParagraphNearActiveFile = (editor: Editor, position: 'above' | 'below' = 'below'): Path | null => {
const entry = getActiveFileEntry(editor);
Iif (!entry) return null;
const [, path] = entry;
const targetPath = position === 'above' ? path : Path.next(path);
Transforms.insertNodes(editor, createParagraphElement(), {at: targetPath});
Transforms.select(editor, Editor.start(editor, targetPath));
return targetPath;
};
export const removeFileAtPath = (editor: Editor, path: Path): boolean => {
Iif (!Node.has(editor, path)) return false;
const node = Node.get(editor, path);
Iif (!isFileElement(node)) return false;
Transforms.removeNodes(editor, {at: path});
return true;
};
export const insertFile = (editor: Editor, thingId: string, caption?: string): FileElement | null => {
Iif (!thingId) return null;
return insertVoidBlock(editor, createFileElement(thingId, caption));
};
export const withFile = <T extends Editor>(editor: T): T => {
const {isVoid, insertBreak, insertSoftBreak, insertText} = editor;
editor.isVoid = (element) => ((element as any).type === 'file' ? true : isVoid(element));
editor.insertBreak = () => {
Eif (insertParagraphNearActiveFile(editor, 'below')) return;
insertBreak();
};
editor.insertSoftBreak = () => {
if (insertParagraphNearActiveFile(editor, 'above')) return;
insertSoftBreak();
};
editor.insertText = (text) => {
Eif (text && insertParagraphNearActiveFile(editor, 'below')) {
insertText(text);
return;
}
insertText(text);
};
return editor;
};
|