edytor 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +225 -5
- package/dist/block/block.svelte.d.ts +123 -0
- package/dist/block/block.svelte.js +430 -0
- package/dist/block/block.utils.d.ts +82 -0
- package/dist/block/block.utils.js +499 -0
- package/dist/block/content.svelte.d.ts +14 -0
- package/dist/block/content.svelte.js +40 -0
- package/dist/block/inlineBlock.svelte.d.ts +30 -0
- package/dist/block/inlineBlock.svelte.js +53 -0
- package/dist/components/Block.svelte +27 -0
- package/dist/components/Block.svelte.d.ts +7 -0
- package/dist/components/Content.svelte +44 -0
- package/dist/components/Content.svelte.d.ts +7 -0
- package/dist/components/Edytor.svelte +165 -0
- package/dist/components/Edytor.svelte.d.ts +33 -0
- package/dist/components/InlineBlock.svelte +17 -0
- package/dist/components/InlineBlock.svelte.d.ts +7 -0
- package/dist/components/Mark.svelte +38 -0
- package/dist/components/Mark.svelte.d.ts +11 -0
- package/dist/components/ReadonlyEditor.svelte +46 -0
- package/dist/components/ReadonlyEditor.svelte.d.ts +4 -0
- package/dist/components/Text.svelte +37 -0
- package/dist/components/Text.svelte.d.ts +7 -0
- package/dist/components/readonlyElements.svelte.d.ts +82 -0
- package/dist/components/readonlyElements.svelte.js +144 -0
- package/dist/constants.d.ts +4 -0
- package/dist/constants.js +4 -0
- package/dist/dnd.svelte.d.ts +17 -0
- package/dist/dnd.svelte.js +125 -0
- package/dist/edytor.svelte.d.ts +94 -0
- package/dist/edytor.svelte.js +262 -0
- package/dist/edytor.utils.d.ts +3 -0
- package/dist/edytor.utils.js +78 -0
- package/dist/events/onBeforeInput.d.ts +2 -2
- package/dist/events/onBeforeInput.js +338 -0
- package/dist/events/onKeyDown.d.ts +2 -69
- package/dist/events/onKeyDown.js +18 -0
- package/dist/hotkeys.d.ts +27 -0
- package/dist/hotkeys.js +282 -0
- package/dist/index.d.ts +7 -5
- package/dist/index.js +7 -8
- package/dist/localProvider.d.ts +82 -0
- package/dist/localProvider.js +267 -0
- package/dist/plugins/arrowMove/arrowMove.d.ts +2 -0
- package/dist/plugins/arrowMove/arrowMove.js +66 -0
- package/dist/plugins/code/CodePlugin.svelte +218 -0
- package/dist/plugins/code/CodePlugin.svelte.d.ts +23 -0
- package/dist/plugins/code/prism.css +141 -0
- package/dist/plugins/image/ImagePlugin.svelte +22 -0
- package/dist/plugins/image/ImagePlugin.svelte.d.ts +20 -0
- package/dist/plugins/index.d.ts +3 -0
- package/dist/plugins/index.js +3 -0
- package/dist/plugins/mention/MentionPlugin.svelte +40 -0
- package/dist/plugins/mention/MentionPlugin.svelte.d.ts +20 -0
- package/dist/plugins/richtext/RichTextPlugin.svelte +241 -0
- package/dist/plugins/richtext/RichTextPlugin.svelte.d.ts +26 -0
- package/dist/plugins.d.ts +202 -0
- package/dist/plugins.js +19 -0
- package/dist/selection/selection.svelte.d.ts +68 -0
- package/dist/selection/selection.svelte.js +391 -0
- package/dist/selection/selection.utils.d.ts +14 -0
- package/dist/selection/selection.utils.js +153 -0
- package/dist/text/deltas.d.ts +11 -0
- package/dist/text/deltas.js +109 -0
- package/dist/text/text.svelte.d.ts +70 -0
- package/dist/text/text.svelte.js +119 -0
- package/dist/text/text.utils.d.ts +40 -0
- package/dist/text/text.utils.js +174 -0
- package/dist/utils/json.d.ts +32 -0
- package/dist/utils/json.js +2 -0
- package/dist/utils/jsx.d.ts +25 -0
- package/dist/utils/jsx.js +66 -0
- package/dist/utils/serialize.d.ts +1 -0
- package/dist/utils/serialize.js +1 -0
- package/dist/utils.d.ts +6 -0
- package/dist/utils.js +19 -0
- package/package.json +81 -33
- package/dist/edytor.cjs.development.js +0 -1762
- package/dist/edytor.cjs.development.js.map +0 -1
- package/dist/edytor.cjs.production.min.js +0 -2
- package/dist/edytor.cjs.production.min.js.map +0 -1
- package/dist/edytor.esm.js +0 -1691
- package/dist/edytor.esm.js.map +0 -1
- package/dist/events/index.d.ts +0 -3
- package/dist/events/onDrop.d.ts +0 -3
- package/dist/operations/deleteText.d.ts +0 -7
- package/dist/operations/formatText.d.ts +0 -20
- package/dist/operations/index.d.ts +0 -9
- package/dist/operations/insertText.d.ts +0 -5
- package/dist/operations/merge.d.ts +0 -3
- package/dist/operations/moveNode.d.ts +0 -12
- package/dist/operations/nestNode.d.ts +0 -2
- package/dist/operations/removeEmptyText.d.ts +0 -2
- package/dist/operations/splitLeaf.d.ts +0 -2
- package/dist/operations/splitNode.d.ts +0 -9
- package/dist/types.d.ts +0 -140
- package/dist/utils/common.d.ts +0 -17
- package/dist/utils/dropper.d.ts +0 -26
- package/dist/utils/index.d.ts +0 -6
- package/dist/utils/leaves.d.ts +0 -34
- package/dist/utils/nodes.d.ts +0 -14
- package/dist/utils/selection.d.ts +0 -51
- package/dist/utils/yClasses/EdytorDoc.d.ts +0 -16
- package/dist/utils/yClasses/index.d.ts +0 -3
- package/dist/utils/yClasses/yLeaf.d.ts +0 -7
- package/dist/utils/yClasses/yNode.d.ts +0 -12
- package/dist/yjs/index.d.ts +0 -1
- package/dist/yjs/wsProvider.d.ts +0 -1
- package/index.ts +0 -1
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
import { Text } from '../text/text.svelte.js';
|
|
2
|
+
import { Edytor } from '../edytor.svelte.js';
|
|
3
|
+
import {} from '../utils/json.js';
|
|
4
|
+
import * as Y from 'yjs';
|
|
5
|
+
import { batch, removeInlineBlock, addChildBlock, insertBlockAfter, insertBlockBefore, pushContentIntoBlock, mergeBlockBackward, mergeBlockForward, nestBlock, removeBlock, setBlock, splitBlock, addChildBlocks, unNestBlock, moveBlock, normalizeContent, groupContent, addInlineBlock, acceptSuggestedText, suggestText, deleteContentAtRange } from './block.utils.js';
|
|
6
|
+
import { id } from '../utils.js';
|
|
7
|
+
import { climb } from '../selection/selection.utils.js';
|
|
8
|
+
import { InlineBlock } from './inlineBlock.svelte.js';
|
|
9
|
+
import { createReadonlyText } from '../components/readonlyElements.svelte.js';
|
|
10
|
+
import { createReadonlyInlineBlock } from '../components/readonlyElements.svelte.js';
|
|
11
|
+
export const getSetArray = (yBlock, key = 'children') => {
|
|
12
|
+
let yChildren = yBlock.get(key);
|
|
13
|
+
if (!yChildren) {
|
|
14
|
+
yChildren = new Y.Array();
|
|
15
|
+
yBlock.set(key, yChildren);
|
|
16
|
+
}
|
|
17
|
+
return yChildren;
|
|
18
|
+
};
|
|
19
|
+
export const getSetText = (yBlock) => {
|
|
20
|
+
let yText = yBlock.get('content');
|
|
21
|
+
if (!yText) {
|
|
22
|
+
yText = new Y.Text();
|
|
23
|
+
yBlock.set('content', yText);
|
|
24
|
+
}
|
|
25
|
+
return yText;
|
|
26
|
+
};
|
|
27
|
+
export class Block {
|
|
28
|
+
readonly = false;
|
|
29
|
+
edytor;
|
|
30
|
+
yBlock;
|
|
31
|
+
parent;
|
|
32
|
+
yChildren;
|
|
33
|
+
yContent;
|
|
34
|
+
children = $state([]);
|
|
35
|
+
content = $state([]);
|
|
36
|
+
id = $state(id('b'));
|
|
37
|
+
data = $state({});
|
|
38
|
+
node;
|
|
39
|
+
definition = $state({});
|
|
40
|
+
get selected() {
|
|
41
|
+
this.yBlock._item?.id;
|
|
42
|
+
return this.edytor.selection.selectedBlocks.has(this) || this.edytor.selection.hasSelectedAll;
|
|
43
|
+
}
|
|
44
|
+
get focused() {
|
|
45
|
+
return this.edytor.selection.focusedBlocks.has(this) && !this.selected;
|
|
46
|
+
}
|
|
47
|
+
get insideIsland() {
|
|
48
|
+
let insideIslands = false;
|
|
49
|
+
climb(this.parent, (block) => {
|
|
50
|
+
if (block.definition?.island) {
|
|
51
|
+
insideIslands = true;
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
return insideIslands;
|
|
56
|
+
}
|
|
57
|
+
get firstEditableText() {
|
|
58
|
+
if (this.content.length && this.content.some((part) => part instanceof Text && part.node)) {
|
|
59
|
+
return this.content.find((part) => part instanceof Text);
|
|
60
|
+
}
|
|
61
|
+
return this.children.at(0)?.firstEditableText;
|
|
62
|
+
}
|
|
63
|
+
get lastEditableText() {
|
|
64
|
+
if (this.content.length && this.content.some((part) => part instanceof Text && part.node)) {
|
|
65
|
+
return this.content.findLast((part) => part instanceof Text);
|
|
66
|
+
}
|
|
67
|
+
return this.children.at(-1)?.lastEditableText;
|
|
68
|
+
}
|
|
69
|
+
#index = $state(null);
|
|
70
|
+
get index() {
|
|
71
|
+
if (!this.parent) {
|
|
72
|
+
return 0;
|
|
73
|
+
}
|
|
74
|
+
if (this.#index === null) {
|
|
75
|
+
return this.parent.children.indexOf(this);
|
|
76
|
+
}
|
|
77
|
+
return this.#index;
|
|
78
|
+
}
|
|
79
|
+
set index(value) {
|
|
80
|
+
this.#index = value;
|
|
81
|
+
}
|
|
82
|
+
#type = $state('paragraph');
|
|
83
|
+
get type() {
|
|
84
|
+
return this.#type;
|
|
85
|
+
}
|
|
86
|
+
set type(value) {
|
|
87
|
+
this.yBlock.set('type', value);
|
|
88
|
+
this.#type = value;
|
|
89
|
+
this.definition = this.edytor.getBlockDefinition('block', value);
|
|
90
|
+
}
|
|
91
|
+
#depth = $state(null);
|
|
92
|
+
get depth() {
|
|
93
|
+
if (!this.parent) {
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
96
|
+
if (this.#depth === null) {
|
|
97
|
+
return this.parent.depth + 1;
|
|
98
|
+
}
|
|
99
|
+
return this.#depth;
|
|
100
|
+
}
|
|
101
|
+
get path() {
|
|
102
|
+
const start = [this.index];
|
|
103
|
+
let current = this.parent;
|
|
104
|
+
while (current instanceof Block && current.parent) {
|
|
105
|
+
start.push(current.index);
|
|
106
|
+
current = current.parent;
|
|
107
|
+
}
|
|
108
|
+
return start.toReversed();
|
|
109
|
+
}
|
|
110
|
+
get isRoot() {
|
|
111
|
+
return this === this.edytor.root;
|
|
112
|
+
}
|
|
113
|
+
#suggestions = $state(null);
|
|
114
|
+
get suggestions() {
|
|
115
|
+
if (!this.#suggestions) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
return this.#suggestions.map((suggestion) => {
|
|
119
|
+
if ('type' in suggestion) {
|
|
120
|
+
return createReadonlyInlineBlock({
|
|
121
|
+
block: suggestion,
|
|
122
|
+
edytor: this.edytor,
|
|
123
|
+
parent: this
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
return createReadonlyText({
|
|
128
|
+
value: suggestion,
|
|
129
|
+
parent: this,
|
|
130
|
+
edytor: this.edytor
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
set suggestions(value) {
|
|
136
|
+
this.#suggestions = value;
|
|
137
|
+
}
|
|
138
|
+
get nextBlock() {
|
|
139
|
+
if (!this.parent) {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
return this.parent.children[this.index + 1];
|
|
143
|
+
}
|
|
144
|
+
get previousBlock() {
|
|
145
|
+
if (!this.parent) {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
return this.parent.children[this.index - 1];
|
|
149
|
+
}
|
|
150
|
+
get closestPreviousBlock() {
|
|
151
|
+
const previousBlock = this.previousBlock;
|
|
152
|
+
if (this.index === 0) {
|
|
153
|
+
return this.parent instanceof Block ? this.parent : null;
|
|
154
|
+
}
|
|
155
|
+
else if (previousBlock) {
|
|
156
|
+
if (previousBlock?.children.length > 0) {
|
|
157
|
+
let closestPreviousBlock = previousBlock.children.at(-1) || null;
|
|
158
|
+
while (closestPreviousBlock && closestPreviousBlock?.children.length > 0) {
|
|
159
|
+
closestPreviousBlock = closestPreviousBlock.children.at(-1) || null;
|
|
160
|
+
}
|
|
161
|
+
return closestPreviousBlock || null;
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
return this.previousBlock;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
get closestNextBlock() {
|
|
170
|
+
if (this.hasChildren) {
|
|
171
|
+
return this.children.at(0) || null;
|
|
172
|
+
}
|
|
173
|
+
if (this.nextBlock || this.definition.island || this.definition.void) {
|
|
174
|
+
return this.nextBlock;
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
if (this.parent instanceof Block) {
|
|
178
|
+
let parent = this.parent;
|
|
179
|
+
let nextBlock = parent.nextBlock;
|
|
180
|
+
while (!nextBlock && parent instanceof Block) {
|
|
181
|
+
if (parent.parent instanceof Block) {
|
|
182
|
+
parent = parent.parent;
|
|
183
|
+
nextBlock = parent.nextBlock;
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return nextBlock;
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
get deepestChild() {
|
|
197
|
+
if (this.children.length) {
|
|
198
|
+
return this.children.at(-1).deepestChild;
|
|
199
|
+
}
|
|
200
|
+
return this;
|
|
201
|
+
}
|
|
202
|
+
get hasChildren() {
|
|
203
|
+
return this.children.length > 0;
|
|
204
|
+
}
|
|
205
|
+
get hasContent() {
|
|
206
|
+
return (this.content.length > 0 && this.content.some((part) => part instanceof Text && !part.isEmpty));
|
|
207
|
+
}
|
|
208
|
+
get isEmpty() {
|
|
209
|
+
return !this.hasContent && !this.hasChildren;
|
|
210
|
+
}
|
|
211
|
+
get value() {
|
|
212
|
+
const children = this.children.map((child) => child.value);
|
|
213
|
+
const content = this.content.map((part) => part.value).flat();
|
|
214
|
+
const value = {
|
|
215
|
+
type: this.type,
|
|
216
|
+
id: this.id,
|
|
217
|
+
children,
|
|
218
|
+
content
|
|
219
|
+
};
|
|
220
|
+
if (Object.keys(this.data).length > 0) {
|
|
221
|
+
value.data = this.data;
|
|
222
|
+
}
|
|
223
|
+
if (!children.length) {
|
|
224
|
+
delete value.children;
|
|
225
|
+
}
|
|
226
|
+
if (!content.length) {
|
|
227
|
+
delete value.content;
|
|
228
|
+
}
|
|
229
|
+
return value;
|
|
230
|
+
}
|
|
231
|
+
get firstText() {
|
|
232
|
+
if (this.content.length) {
|
|
233
|
+
return this.content.find((part) => part instanceof Text);
|
|
234
|
+
}
|
|
235
|
+
return this.children.at(0)?.firstText;
|
|
236
|
+
}
|
|
237
|
+
get lastText() {
|
|
238
|
+
if (this.content.length) {
|
|
239
|
+
return this.content.findLast((part) => part instanceof Text);
|
|
240
|
+
}
|
|
241
|
+
return this.children.at(0).lastText;
|
|
242
|
+
}
|
|
243
|
+
observeContent = observeContent.bind(this);
|
|
244
|
+
observeChildren = observeChildren.bind(this);
|
|
245
|
+
batch = batch.bind(this);
|
|
246
|
+
addChildBlock = this.batch('addChildBlock', addChildBlock.bind(this));
|
|
247
|
+
addChildBlocks = this.batch('addChildBlocks', addChildBlocks.bind(this));
|
|
248
|
+
insertBlockAfter = this.batch('insertBlockAfter', insertBlockAfter.bind(this));
|
|
249
|
+
insertBlockBefore = this.batch('insertBlockBefore', insertBlockBefore.bind(this));
|
|
250
|
+
splitBlock = this.batch('splitBlock', splitBlock.bind(this));
|
|
251
|
+
removeBlock = this.batch('removeBlock', removeBlock.bind(this));
|
|
252
|
+
unNestBlock = this.batch('unNestBlock', unNestBlock.bind(this));
|
|
253
|
+
mergeBlockBackward = this.batch('mergeBlockBackward', mergeBlockBackward.bind(this));
|
|
254
|
+
mergeBlockForward = this.batch('mergeBlockForward', mergeBlockForward.bind(this));
|
|
255
|
+
nestBlock = this.batch('nestBlock', nestBlock.bind(this));
|
|
256
|
+
setBlock = this.batch('setBlock', setBlock.bind(this));
|
|
257
|
+
moveBlock = this.batch('moveBlock', moveBlock.bind(this));
|
|
258
|
+
pushContentIntoBlock = this.batch('pushContentIntoBlock', pushContentIntoBlock.bind(this));
|
|
259
|
+
removeInlineBlock = this.batch('removeInlineBlock', removeInlineBlock.bind(this));
|
|
260
|
+
addInlineBlock = this.batch('addInlineBlock', addInlineBlock.bind(this));
|
|
261
|
+
normalizeContent = this.batch('normalizeContent', normalizeContent.bind(this));
|
|
262
|
+
suggestText = this.batch('suggestText', suggestText.bind(this));
|
|
263
|
+
acceptSuggestedText = this.batch('acceptSuggestedText', acceptSuggestedText.bind(this));
|
|
264
|
+
deleteContentAtRange = this.batch('deleteContentAtRange', deleteContentAtRange.bind(this));
|
|
265
|
+
void = (node) => {
|
|
266
|
+
node.setAttribute('data-edytor-void', `true`);
|
|
267
|
+
node.style.userSelect = 'none';
|
|
268
|
+
node.contentEditable = 'false';
|
|
269
|
+
};
|
|
270
|
+
constructor({ parent, block, yBlock, edytor }) {
|
|
271
|
+
this.parent = parent;
|
|
272
|
+
this.edytor = edytor;
|
|
273
|
+
this.id = (yBlock?.doc && yBlock?.get('id')) || id('b');
|
|
274
|
+
if (block !== undefined) {
|
|
275
|
+
this.#type = block.type;
|
|
276
|
+
this.data = block.data || {};
|
|
277
|
+
// Initialize children
|
|
278
|
+
this.children = (block.children || []).map((child, index) => {
|
|
279
|
+
const block = new Block({ parent: this, edytor, block: child });
|
|
280
|
+
block.index = index;
|
|
281
|
+
return block;
|
|
282
|
+
});
|
|
283
|
+
const groupedContent = groupContent(block.content);
|
|
284
|
+
if (!groupedContent.length) {
|
|
285
|
+
groupedContent.push([{ text: '' }]);
|
|
286
|
+
}
|
|
287
|
+
this.content = groupedContent.map((part, index) => {
|
|
288
|
+
const isInlineBlock = 'type' in part;
|
|
289
|
+
if (isInlineBlock) {
|
|
290
|
+
const block = new InlineBlock({ parent: this, block: part });
|
|
291
|
+
block.index = index;
|
|
292
|
+
return block;
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
const text = new Text({ parent: this, content: part });
|
|
296
|
+
text.index = index;
|
|
297
|
+
return text;
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
this.yChildren = Y.Array.from(this.children.map((child) => child.yBlock));
|
|
301
|
+
this.yContent = Y.Array.from(this.content.map((part) => (part instanceof Text ? part.yText : part.yBlock)));
|
|
302
|
+
// If the block is a root block we need to set the yBlock to the yRootBlock
|
|
303
|
+
if (block.type === 'root') {
|
|
304
|
+
this.yBlock = yBlock;
|
|
305
|
+
this.yBlock.set('id', this.id);
|
|
306
|
+
this.yBlock.set('type', block.type);
|
|
307
|
+
this.yBlock.set('data', this.data);
|
|
308
|
+
this.yBlock.set('children', this.yChildren);
|
|
309
|
+
this.yBlock.set('content', this.yContent);
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
this.yBlock = new Y.Map(Object.entries({
|
|
313
|
+
type: block.type,
|
|
314
|
+
id: this.id,
|
|
315
|
+
data: this.data,
|
|
316
|
+
children: this.yChildren,
|
|
317
|
+
content: this.yContent
|
|
318
|
+
}));
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
this.yBlock = yBlock;
|
|
323
|
+
this.#type = this.yBlock.get('type') || this.edytor.getDefaultBlock(parent);
|
|
324
|
+
this.data = this.yBlock.get('data') || {};
|
|
325
|
+
this.yChildren = getSetArray(this.yBlock);
|
|
326
|
+
this.yContent = getSetArray(this.yBlock, 'content');
|
|
327
|
+
this.children = this.yChildren.map((child, index) => {
|
|
328
|
+
const block = new Block({ parent: this, edytor, yBlock: child });
|
|
329
|
+
block.index = index;
|
|
330
|
+
return block;
|
|
331
|
+
});
|
|
332
|
+
this.normalizeContent();
|
|
333
|
+
this.content = this.yContent.map((part, index) => {
|
|
334
|
+
if (part instanceof Y.Map) {
|
|
335
|
+
const block = new InlineBlock({ parent: this, yBlock: part });
|
|
336
|
+
block.index = index;
|
|
337
|
+
return block;
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
const text = new Text({ parent: this, yText: part });
|
|
341
|
+
text.index = index;
|
|
342
|
+
return text;
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
this.definition = this.edytor.getBlockDefinition('block', this.#type);
|
|
347
|
+
this.edytor.idToBlock.set(this.id, this);
|
|
348
|
+
if (!this.edytor.readonly) {
|
|
349
|
+
this.yChildren.observe(this.observeChildren);
|
|
350
|
+
this.yContent.observe(this.observeContent);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
attach = (node) => {
|
|
354
|
+
this.node = node;
|
|
355
|
+
node.setAttribute('data-edytor-id', `${this.id}`);
|
|
356
|
+
node.setAttribute('data-edytor-block', `true`);
|
|
357
|
+
node.setAttribute('data-edytor-type', `${this.#type}`);
|
|
358
|
+
const pluginDestroy = this.edytor.plugins.reduce((acc, plugin) => {
|
|
359
|
+
const action = plugin.onBlockAttached?.({ node, block: this });
|
|
360
|
+
action && acc.push(action);
|
|
361
|
+
return acc;
|
|
362
|
+
}, []);
|
|
363
|
+
if (this.definition.void) {
|
|
364
|
+
this.void(node);
|
|
365
|
+
}
|
|
366
|
+
return {
|
|
367
|
+
destroy: () => {
|
|
368
|
+
this.yChildren.unobserve(this.observeChildren);
|
|
369
|
+
this.yContent.unobserve(this.observeContent);
|
|
370
|
+
this.edytor.idToBlock.delete(this.id);
|
|
371
|
+
pluginDestroy.forEach((destroy) => destroy());
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
export function observeChildren(event) {
|
|
377
|
+
let start = 0;
|
|
378
|
+
event.delta.forEach(({ retain, delete: _delete, insert }) => {
|
|
379
|
+
if (retain) {
|
|
380
|
+
start += retain;
|
|
381
|
+
}
|
|
382
|
+
if (_delete) {
|
|
383
|
+
this.children.splice(start, _delete);
|
|
384
|
+
}
|
|
385
|
+
if (Array.isArray(insert)) {
|
|
386
|
+
for (let i = 0; i < insert.length; i++) {
|
|
387
|
+
const yBlock = insert[i];
|
|
388
|
+
const block = this.edytor.idToBlock.get(yBlock.get('id')) ||
|
|
389
|
+
new Block({
|
|
390
|
+
parent: this,
|
|
391
|
+
edytor: this.edytor,
|
|
392
|
+
yBlock
|
|
393
|
+
});
|
|
394
|
+
this.children.splice(start, 0, block);
|
|
395
|
+
start += 1;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
this.children.forEach((child, index) => {
|
|
400
|
+
child.index = index;
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
export function observeContent(event) {
|
|
404
|
+
let start = 0;
|
|
405
|
+
event.delta.forEach(({ retain, delete: _delete, insert }) => {
|
|
406
|
+
if (retain) {
|
|
407
|
+
start += retain;
|
|
408
|
+
}
|
|
409
|
+
if (_delete) {
|
|
410
|
+
this.content.splice(start, _delete);
|
|
411
|
+
}
|
|
412
|
+
if (Array.isArray(insert)) {
|
|
413
|
+
for (let i = 0; i < insert.length; i++) {
|
|
414
|
+
const yElement = insert[i];
|
|
415
|
+
if (yElement instanceof Y.Text) {
|
|
416
|
+
const text = new Text({ parent: this, yText: yElement });
|
|
417
|
+
this.content.splice(start, 0, text);
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
const inlineBlock = new InlineBlock({ parent: this, yBlock: yElement });
|
|
421
|
+
this.content.splice(start, 0, inlineBlock);
|
|
422
|
+
}
|
|
423
|
+
start += 1;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
this.content.forEach((part, index) => {
|
|
428
|
+
part.index = index;
|
|
429
|
+
});
|
|
430
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Block } from './block.svelte.js';
|
|
2
|
+
import { Text } from '../text/text.svelte.js';
|
|
3
|
+
import type { JSONBlock, JSONInlineBlock, JSONText } from '../utils/json.js';
|
|
4
|
+
import { InlineBlock } from './inlineBlock.svelte.js';
|
|
5
|
+
export type BlockOperations = {
|
|
6
|
+
removeInlineBlock: {
|
|
7
|
+
index: number;
|
|
8
|
+
};
|
|
9
|
+
addChildBlock: {
|
|
10
|
+
block: JSONBlock;
|
|
11
|
+
index: number;
|
|
12
|
+
};
|
|
13
|
+
addChildBlocks: {
|
|
14
|
+
blocks: JSONBlock[];
|
|
15
|
+
index: number;
|
|
16
|
+
};
|
|
17
|
+
insertBlockAfter: {
|
|
18
|
+
block: JSONBlock;
|
|
19
|
+
};
|
|
20
|
+
insertBlockBefore: {
|
|
21
|
+
block: JSONBlock;
|
|
22
|
+
};
|
|
23
|
+
splitBlock: {
|
|
24
|
+
index: number;
|
|
25
|
+
text: Text;
|
|
26
|
+
};
|
|
27
|
+
removeBlock: {
|
|
28
|
+
keepChildren: boolean;
|
|
29
|
+
};
|
|
30
|
+
unNestBlock: {};
|
|
31
|
+
mergeBlockBackward: {};
|
|
32
|
+
mergeBlockForward: {};
|
|
33
|
+
nestBlock: {};
|
|
34
|
+
setBlock: {
|
|
35
|
+
value: JSONBlock;
|
|
36
|
+
};
|
|
37
|
+
addInlineBlock: {
|
|
38
|
+
index: number;
|
|
39
|
+
block: JSONInlineBlock;
|
|
40
|
+
text: Text;
|
|
41
|
+
};
|
|
42
|
+
moveBlock: {
|
|
43
|
+
path: number[];
|
|
44
|
+
};
|
|
45
|
+
pushContentIntoBlock: {
|
|
46
|
+
value: (Text | InlineBlock)[];
|
|
47
|
+
};
|
|
48
|
+
deleteContentForward: {
|
|
49
|
+
text: Text;
|
|
50
|
+
};
|
|
51
|
+
normalizeContent: {};
|
|
52
|
+
suggestText: {
|
|
53
|
+
value: (JSONText | JSONInlineBlock)[] | string | null;
|
|
54
|
+
};
|
|
55
|
+
acceptSuggestedText: {};
|
|
56
|
+
deleteContentAtRange: {
|
|
57
|
+
start: [number, number];
|
|
58
|
+
end: [number, number];
|
|
59
|
+
};
|
|
60
|
+
deleteContentWithinSelection: {};
|
|
61
|
+
};
|
|
62
|
+
export declare function batch<T extends (...args: any[]) => any, O extends keyof BlockOperations>(operation: O, func: T): T;
|
|
63
|
+
export declare function addChildBlock(this: Block, { block, index }: BlockOperations['addChildBlock']): Block;
|
|
64
|
+
export declare function addChildBlocks(this: Block, { blocks, index }: BlockOperations['addChildBlocks']): Block[];
|
|
65
|
+
export declare function insertBlockAfter(this: Block, { block }: BlockOperations['insertBlockAfter']): Block | null;
|
|
66
|
+
export declare function insertBlockBefore(this: Block, { block }: BlockOperations['insertBlockBefore']): Block | null;
|
|
67
|
+
export declare function splitBlock(this: Block, { index, text }: BlockOperations['splitBlock']): Block | null;
|
|
68
|
+
export declare function removeBlock(this: Block, { keepChildren }?: BlockOperations['removeBlock']): void;
|
|
69
|
+
export declare function mergeBlockBackward(this: Block): Block | null;
|
|
70
|
+
export declare function mergeBlockForward(this: Block): Block | null;
|
|
71
|
+
export declare function moveBlock(this: Block, { path }: BlockOperations['moveBlock']): Block | null;
|
|
72
|
+
export declare function unNestBlock(this: Block): Block | null;
|
|
73
|
+
export declare function nestBlock(this: Block): Block | null;
|
|
74
|
+
export declare function setBlock(this: Block, { value }: BlockOperations['setBlock']): void;
|
|
75
|
+
export declare function pushContentIntoBlock(this: Block, { value }: BlockOperations['pushContentIntoBlock']): void;
|
|
76
|
+
export declare function removeInlineBlock(this: Block, { index }: BlockOperations['removeInlineBlock']): void;
|
|
77
|
+
export declare const groupContent: (content?: (JSONText | JSONInlineBlock)[]) => (JSONText[] | JSONInlineBlock)[];
|
|
78
|
+
export declare function addInlineBlock(this: Block, { index, block, text }: BlockOperations['addInlineBlock']): Text;
|
|
79
|
+
export declare function normalizeContent(this: Block): void;
|
|
80
|
+
export declare function suggestText(this: Block, { value }: BlockOperations['suggestText']): void;
|
|
81
|
+
export declare function acceptSuggestedText(this: Block): void;
|
|
82
|
+
export declare function deleteContentAtRange(this: Block, { start, end }: BlockOperations['deleteContentAtRange']): void;
|