|
| 1 | +import assert from 'assert'; |
| 2 | + |
| 3 | +import { |
| 4 | + boxUtils, blockUtils, |
| 5 | +} from 'live-editor/client'; |
| 6 | + |
| 7 | +function getPrefixInfo(detail, prefix) { |
| 8 | + const block = detail.startBlock; |
| 9 | + if (!block || !prefix) { |
| 10 | + return { |
| 11 | + index: -1, |
| 12 | + keywords: '', |
| 13 | + count: 0, |
| 14 | + maxCount: 0, |
| 15 | + }; |
| 16 | + } |
| 17 | + // |
| 18 | + assert(block); |
| 19 | + // |
| 20 | + const data = blockUtils.saveData(block).text; |
| 21 | + assert(data); |
| 22 | + assert(detail.startOffset !== undefined); |
| 23 | + const left = data.split(detail.startOffset)[0].toPlainText(); |
| 24 | + if (left.endsWith(' ')) { // 3 spaces |
| 25 | + return { |
| 26 | + index: -1, |
| 27 | + keywords: '', |
| 28 | + count: 0, |
| 29 | + maxCount: 0, |
| 30 | + }; |
| 31 | + } |
| 32 | + const index = left.lastIndexOf(prefix); |
| 33 | + if (index === -1) { |
| 34 | + return { |
| 35 | + index: -1, |
| 36 | + keywords: '', |
| 37 | + count: 0, |
| 38 | + maxCount: 0, |
| 39 | + }; |
| 40 | + } |
| 41 | + const keywords = left.substr(index + 1); |
| 42 | + const count = detail.startOffset - index; |
| 43 | + const afterPrefix = data.split(index)[1]; |
| 44 | + let endIndex = afterPrefix.toPlainText().indexOf(' '); |
| 45 | + if (endIndex === -1) { |
| 46 | + endIndex = afterPrefix.toPlainText().length; |
| 47 | + } |
| 48 | + // |
| 49 | + return { |
| 50 | + index, |
| 51 | + keywords, |
| 52 | + count, |
| 53 | + maxCount: endIndex, |
| 54 | + }; |
| 55 | +} |
| 56 | + |
| 57 | +function insertImage(editor) { |
| 58 | + const input = document.createElement('input'); |
| 59 | + input.type = 'file'; |
| 60 | + input.accept = 'image/*'; |
| 61 | + input.onchange = () => { |
| 62 | + if (input.files && input.files.length > 0) { |
| 63 | + Array.from(input.files).forEach((file) => { |
| 64 | + editor.insertImage(null, file, -2); |
| 65 | + }); |
| 66 | + input.files = null; |
| 67 | + input.value = ''; |
| 68 | + } |
| 69 | + input.remove(); |
| 70 | + }; |
| 71 | + input.click(); |
| 72 | +} |
| 73 | + |
| 74 | +let insertMenuList = []; |
| 75 | + |
| 76 | +// eslint-disable-next-line import/prefer-default-export |
| 77 | +export function setInsertMenuList(list) { |
| 78 | + insertMenuList = list; |
| 79 | +} |
| 80 | + |
| 81 | +const quickInsertBlock = { |
| 82 | + createNode: (editor, data) => ({ |
| 83 | + classes: ['box-quick-insert'], |
| 84 | + children: [ |
| 85 | + { |
| 86 | + type: 'text', |
| 87 | + text: data.text, |
| 88 | + }, |
| 89 | + ], |
| 90 | + }), |
| 91 | + getItems: async (editor, keywords) => { |
| 92 | + assert(editor); |
| 93 | + // |
| 94 | + if (!keywords) { |
| 95 | + return insertMenuList; |
| 96 | + } |
| 97 | + return insertMenuList.filter((menu) => menu.id.toLowerCase().indexOf(keywords.toLowerCase()) !== -1); |
| 98 | + }, |
| 99 | + supportMarkdown: true, |
| 100 | + prefix: '+', |
| 101 | + handleBoxItemSelected(editor, item) { |
| 102 | + let detail = editor.getSelectionDetail(); |
| 103 | + if (!detail.startBlock) { |
| 104 | + const lastSelectionState = editor.saveSelectionState(); |
| 105 | + if (lastSelectionState) { |
| 106 | + editor.restoreSelectionState(lastSelectionState); |
| 107 | + detail = editor.getSelectionDetail(); |
| 108 | + } |
| 109 | + } |
| 110 | + assert(detail.startBlock); |
| 111 | + assert(detail.startBlock === detail.endBlock); |
| 112 | + const { index, maxCount } = getPrefixInfo(detail, '+'); |
| 113 | + if (index !== -1) { |
| 114 | + editor.deleteBlockText(detail.startBlock, index, index + maxCount); |
| 115 | + switch (item.id) { |
| 116 | + case 'link': |
| 117 | + editor.executeTextCommand('link'); |
| 118 | + break; |
| 119 | + case 'checkBox': |
| 120 | + editor.executeBlockCommand('toCheckbox'); |
| 121 | + break; |
| 122 | + case 'table': |
| 123 | + editor.insertTable(-2, 4, 4); |
| 124 | + break; |
| 125 | + case 'image': |
| 126 | + insertImage(editor); |
| 127 | + break; |
| 128 | + case 'codeBlock': |
| 129 | + editor.insertCode(-2); |
| 130 | + break; |
| 131 | + default: |
| 132 | + break; |
| 133 | + } |
| 134 | + } |
| 135 | + }, |
| 136 | +}; |
| 137 | + |
| 138 | +boxUtils.registerBoxType('quick-insert', quickInsertBlock); |
0 commit comments