@blocknote/core 0.47.0 → 0.47.2
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/dist/BlockNoteExtension-BWw0r8Gy.cjs.map +1 -1
- package/dist/BlockNoteExtension-C2X7LW-V.js.map +1 -1
- package/dist/{BlockNoteSchema-DT4bdXj5.cjs → BlockNoteSchema-CCs_V3lo.cjs} +2 -2
- package/dist/{BlockNoteSchema-DT4bdXj5.cjs.map → BlockNoteSchema-CCs_V3lo.cjs.map} +1 -1
- package/dist/{BlockNoteSchema-1r-ln0Q0.js → BlockNoteSchema-ooiKsd5B.js} +2 -2
- package/dist/{BlockNoteSchema-1r-ln0Q0.js.map → BlockNoteSchema-ooiKsd5B.js.map} +1 -1
- package/dist/{TrailingNode-DZag-Nvu.js → TrailingNode-GzE59m_7.js} +588 -416
- package/dist/TrailingNode-GzE59m_7.js.map +1 -0
- package/dist/TrailingNode-n0WdMPUl.cjs +2 -0
- package/dist/TrailingNode-n0WdMPUl.cjs.map +1 -0
- package/dist/blocknote.cjs +4 -4
- package/dist/blocknote.cjs.map +1 -1
- package/dist/blocknote.js +1206 -955
- package/dist/blocknote.js.map +1 -1
- package/dist/blocks.cjs +1 -1
- package/dist/blocks.js +2 -2
- package/dist/comments.cjs.map +1 -1
- package/dist/comments.js.map +1 -1
- package/dist/defaultBlocks-Dg9kQWXm.cjs +6 -0
- package/dist/defaultBlocks-Dg9kQWXm.cjs.map +1 -0
- package/dist/{defaultBlocks-BSOEW3GR.js → defaultBlocks-ZzGbYgQn.js} +627 -543
- package/dist/defaultBlocks-ZzGbYgQn.js.map +1 -0
- package/dist/extensions.cjs +1 -1
- package/dist/extensions.cjs.map +1 -1
- package/dist/extensions.js +33 -54
- package/dist/extensions.js.map +1 -1
- package/dist/locales.cjs +1 -1
- package/dist/locales.cjs.map +1 -1
- package/dist/locales.js +25 -24
- package/dist/locales.js.map +1 -1
- package/dist/style.css +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/webpack-stats.json +1 -1
- package/package.json +1 -10
- package/src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.ts +33 -7
- package/src/api/exporters/html/util/serializeBlocksExternalHTML.ts +7 -1
- package/src/blocks/Heading/block.ts +48 -1
- package/src/blocks/ListItem/ToggleListItem/block.ts +51 -1
- package/src/blocks/Paragraph/block.ts +1 -1
- package/src/blocks/getDetailsContent.ts +77 -0
- package/src/comments/threadstore/TipTapThreadStore.ts +5 -5
- package/src/comments/threadstore/tiptap/types.ts +131 -0
- package/src/editor/Block.css +6 -0
- package/src/editor/BlockNoteEditor.ts +9 -14
- package/src/editor/managers/ExtensionManager/symbol.ts +0 -1
- package/src/editor/managers/SelectionManager.ts +3 -1
- package/src/extensions/Collaboration/YCursorPlugin.ts +3 -1
- package/src/extensions/DropCursor/DropCursor.ts +262 -25
- package/src/extensions/DropCursor/utils.ts +195 -0
- package/src/extensions/SuggestionMenu/SuggestionMenu.test.ts +191 -0
- package/src/extensions/SuggestionMenu/SuggestionMenu.ts +28 -11
- package/src/extensions/tiptap-extensions/KeyboardShortcuts/KeyboardShortcutsExtension.ts +438 -53
- package/src/i18n/locales/fa.ts +4 -21
- package/src/i18n/locales/index.ts +1 -1
- package/src/i18n/locales/ru.ts +1 -1
- package/src/i18n/locales/uz.ts +22 -4
- package/src/index.ts +1 -0
- package/src/schema/blocks/createSpec.ts +35 -45
- package/src/schema/blocks/types.ts +101 -1
- package/types/src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.d.ts +5 -0
- package/types/src/blocks/getDetailsContent.d.ts +19 -0
- package/types/src/comments/threadstore/TipTapThreadStore.d.ts +1 -1
- package/types/src/comments/threadstore/tiptap/types.d.ts +73 -0
- package/types/src/editor/BlockNoteEditor.d.ts +6 -9
- package/types/src/extensions/DropCursor/DropCursor.d.ts +42 -5
- package/types/src/extensions/DropCursor/utils.d.ts +48 -0
- package/types/src/extensions/SuggestionMenu/SuggestionMenu.d.ts +12 -3
- package/types/src/extensions/SuggestionMenu/SuggestionMenu.test.d.ts +1 -0
- package/types/src/index.d.ts +1 -0
- package/types/src/schema/blocks/createSpec.d.ts +3 -3
- package/types/src/schema/blocks/types.d.ts +31 -1
- package/dist/TrailingNode-DZag-Nvu.js.map +0 -1
- package/dist/TrailingNode-tesI8f7N.cjs +0 -2
- package/dist/TrailingNode-tesI8f7N.cjs.map +0 -1
- package/dist/defaultBlocks-BSOEW3GR.js.map +0 -1
- package/dist/defaultBlocks-D049Pbme.cjs +0 -6
- package/dist/defaultBlocks-D049Pbme.cjs.map +0 -1
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { Extension } from "@tiptap/core";
|
|
2
|
-
|
|
2
|
+
import { Fragment, Node } from "prosemirror-model";
|
|
3
3
|
import { TextSelection } from "prosemirror-state";
|
|
4
|
+
|
|
4
5
|
import {
|
|
5
6
|
getBottomNestedBlockInfo,
|
|
7
|
+
getNextBlockInfo,
|
|
8
|
+
getParentBlockInfo,
|
|
6
9
|
getPrevBlockInfo,
|
|
7
10
|
mergeBlocksCommand,
|
|
8
11
|
} from "../../../api/blockManipulation/commands/mergeBlocks/mergeBlocks.js";
|
|
@@ -10,7 +13,10 @@ import { nestBlock } from "../../../api/blockManipulation/commands/nestBlock/nes
|
|
|
10
13
|
import { fixColumnList } from "../../../api/blockManipulation/commands/replaceBlocks/util/fixColumnList.js";
|
|
11
14
|
import { splitBlockCommand } from "../../../api/blockManipulation/commands/splitBlock/splitBlock.js";
|
|
12
15
|
import { updateBlockCommand } from "../../../api/blockManipulation/commands/updateBlock/updateBlock.js";
|
|
13
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
getBlockInfoFromResolvedPos,
|
|
18
|
+
getBlockInfoFromSelection,
|
|
19
|
+
} from "../../../api/getBlockInfoFromPos.js";
|
|
14
20
|
import { BlockNoteEditor } from "../../../editor/BlockNoteEditor.js";
|
|
15
21
|
import { FormattingToolbarExtension } from "../../FormattingToolbar/FormattingToolbar.js";
|
|
16
22
|
import { FilePanelExtension } from "../../FilePanel/FilePanel.js";
|
|
@@ -83,6 +89,21 @@ export const KeyboardShortcutsExtension = Extension.create<{
|
|
|
83
89
|
}
|
|
84
90
|
const { bnBlock: blockContainer, blockContent } = blockInfo;
|
|
85
91
|
|
|
92
|
+
const prevBlockInfo = getPrevBlockInfo(
|
|
93
|
+
state.doc,
|
|
94
|
+
blockInfo.bnBlock.beforePos,
|
|
95
|
+
);
|
|
96
|
+
// If the previous block has no inline content, it can't be merged.
|
|
97
|
+
// It's instead deleted, which is done later in the chan, so we
|
|
98
|
+
// return early here.
|
|
99
|
+
if (
|
|
100
|
+
!prevBlockInfo ||
|
|
101
|
+
!prevBlockInfo.isBlockContainer ||
|
|
102
|
+
prevBlockInfo.blockContent.node.type.spec.content !== "inline*"
|
|
103
|
+
) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
|
|
86
107
|
const selectionAtBlockStart =
|
|
87
108
|
state.selection.from === blockContent.beforePos + 1;
|
|
88
109
|
const selectionEmpty = state.selection.empty;
|
|
@@ -98,9 +119,46 @@ export const KeyboardShortcutsExtension = Extension.create<{
|
|
|
98
119
|
|
|
99
120
|
return false;
|
|
100
121
|
}),
|
|
122
|
+
// If the previous block is a columnList, moves the current block to
|
|
123
|
+
// the end of the last column in it.
|
|
124
|
+
() =>
|
|
125
|
+
commands.command(({ state, tr, dispatch }) => {
|
|
126
|
+
const blockInfo = getBlockInfoFromSelection(state);
|
|
127
|
+
if (!blockInfo.isBlockContainer) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const prevBlockInfo = getPrevBlockInfo(
|
|
132
|
+
state.doc,
|
|
133
|
+
blockInfo.bnBlock.beforePos,
|
|
134
|
+
);
|
|
135
|
+
if (!prevBlockInfo || prevBlockInfo.isBlockContainer) {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (dispatch) {
|
|
140
|
+
const columnAfterPos = prevBlockInfo.bnBlock.afterPos - 1;
|
|
141
|
+
const $blockAfterPos = tr.doc.resolve(columnAfterPos - 1);
|
|
142
|
+
|
|
143
|
+
tr.delete(
|
|
144
|
+
blockInfo.bnBlock.beforePos,
|
|
145
|
+
blockInfo.bnBlock.afterPos,
|
|
146
|
+
);
|
|
147
|
+
tr.insert($blockAfterPos.pos, blockInfo.bnBlock.node);
|
|
148
|
+
tr.setSelection(
|
|
149
|
+
TextSelection.near(tr.doc.resolve($blockAfterPos.pos + 1)),
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return false;
|
|
156
|
+
}),
|
|
157
|
+
// If the block is the first in a column, moves it to the end of the
|
|
158
|
+
// previous column. If there is no previous column, moves it above the
|
|
159
|
+
// columnList.
|
|
101
160
|
() =>
|
|
102
161
|
commands.command(({ state, tr, dispatch }) => {
|
|
103
|
-
// when at the start of a first block in a column
|
|
104
162
|
const blockInfo = getBlockInfoFromSelection(state);
|
|
105
163
|
if (!blockInfo.isBlockContainer) {
|
|
106
164
|
return false;
|
|
@@ -116,7 +174,6 @@ export const KeyboardShortcutsExtension = Extension.create<{
|
|
|
116
174
|
|
|
117
175
|
const prevBlock = $pos.nodeBefore;
|
|
118
176
|
if (prevBlock) {
|
|
119
|
-
// should be no previous block
|
|
120
177
|
return false;
|
|
121
178
|
}
|
|
122
179
|
|
|
@@ -130,31 +187,22 @@ export const KeyboardShortcutsExtension = Extension.create<{
|
|
|
130
187
|
const columnListPos = $columnPos.before();
|
|
131
188
|
|
|
132
189
|
if (dispatch) {
|
|
133
|
-
const fragment = tr.doc.slice(
|
|
134
|
-
blockInfo.bnBlock.beforePos,
|
|
135
|
-
blockInfo.bnBlock.afterPos,
|
|
136
|
-
).content;
|
|
137
|
-
|
|
138
190
|
tr.delete(
|
|
139
191
|
blockInfo.bnBlock.beforePos,
|
|
140
192
|
blockInfo.bnBlock.afterPos,
|
|
141
193
|
);
|
|
194
|
+
fixColumnList(tr, columnListPos);
|
|
142
195
|
|
|
143
|
-
if ($columnPos.
|
|
144
|
-
|
|
145
|
-
fixColumnList(tr, columnListPos);
|
|
146
|
-
tr.insert(columnListPos, fragment);
|
|
196
|
+
if ($columnPos.pos === columnListPos + 1) {
|
|
197
|
+
tr.insert(columnListPos, blockInfo.bnBlock.node);
|
|
147
198
|
tr.setSelection(
|
|
148
199
|
TextSelection.near(tr.doc.resolve(columnListPos)),
|
|
149
200
|
);
|
|
150
201
|
} else {
|
|
151
|
-
|
|
152
|
-
// `columnList`.
|
|
153
|
-
tr.insert($columnPos.pos - 1, fragment);
|
|
202
|
+
tr.insert($columnPos.pos - 1, blockInfo.bnBlock.node);
|
|
154
203
|
tr.setSelection(
|
|
155
|
-
TextSelection.near(tr.doc.resolve($columnPos.pos
|
|
204
|
+
TextSelection.near(tr.doc.resolve($columnPos.pos)),
|
|
156
205
|
);
|
|
157
|
-
fixColumnList(tr, columnListPos);
|
|
158
206
|
}
|
|
159
207
|
}
|
|
160
208
|
|
|
@@ -208,12 +256,8 @@ export const KeyboardShortcutsExtension = Extension.create<{
|
|
|
208
256
|
} else if (
|
|
209
257
|
prevBlockInfo.blockContent.node.type.spec.content === ""
|
|
210
258
|
) {
|
|
211
|
-
const nonEditableBlockContentStartPos =
|
|
212
|
-
prevBlockInfo.blockContent.afterPos -
|
|
213
|
-
prevBlockInfo.blockContent.node.nodeSize;
|
|
214
|
-
|
|
215
259
|
chainedCommands = chainedCommands.setNodeSelection(
|
|
216
|
-
|
|
260
|
+
prevBlockInfo.blockContent.beforePos,
|
|
217
261
|
);
|
|
218
262
|
} else {
|
|
219
263
|
const blockContentStartPos =
|
|
@@ -242,8 +286,7 @@ export const KeyboardShortcutsExtension = Extension.create<{
|
|
|
242
286
|
const blockInfo = getBlockInfoFromSelection(state);
|
|
243
287
|
|
|
244
288
|
if (!blockInfo.isBlockContainer) {
|
|
245
|
-
|
|
246
|
-
throw new Error(`todo`);
|
|
289
|
+
return false;
|
|
247
290
|
}
|
|
248
291
|
|
|
249
292
|
const selectionAtBlockStart =
|
|
@@ -262,8 +305,7 @@ export const KeyboardShortcutsExtension = Extension.create<{
|
|
|
262
305
|
);
|
|
263
306
|
|
|
264
307
|
if (!bottomBlock.isBlockContainer) {
|
|
265
|
-
|
|
266
|
-
throw new Error(`todo`);
|
|
308
|
+
return false;
|
|
267
309
|
}
|
|
268
310
|
|
|
269
311
|
const prevBlockNotTableAndNoContent =
|
|
@@ -294,50 +336,393 @@ export const KeyboardShortcutsExtension = Extension.create<{
|
|
|
294
336
|
]);
|
|
295
337
|
|
|
296
338
|
const handleDelete = () =>
|
|
297
|
-
this.editor.commands.first(({ commands }) => [
|
|
339
|
+
this.editor.commands.first(({ chain, commands }) => [
|
|
298
340
|
// Deletes the selection if it's not empty.
|
|
299
341
|
() => commands.deleteSelection(),
|
|
342
|
+
// Deletes the first child block and un-nests its children, if the
|
|
343
|
+
// selection is empty and at the end of the current block. If both the
|
|
344
|
+
// parent and child blocks have inline content, the child block's
|
|
345
|
+
// content is appended to the parent's. The child block's own children
|
|
346
|
+
// are unindented before it's deleted.
|
|
347
|
+
() =>
|
|
348
|
+
commands.command(({ state }) => {
|
|
349
|
+
const blockInfo = getBlockInfoFromSelection(state);
|
|
350
|
+
if (!blockInfo.isBlockContainer || !blockInfo.childContainer) {
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
353
|
+
const { blockContent, childContainer } = blockInfo;
|
|
354
|
+
|
|
355
|
+
const selectionAtBlockEnd =
|
|
356
|
+
state.selection.from === blockContent.afterPos - 1;
|
|
357
|
+
const selectionEmpty = state.selection.empty;
|
|
358
|
+
|
|
359
|
+
const firstChildBlockInfo = getBlockInfoFromResolvedPos(
|
|
360
|
+
state.doc.resolve(childContainer.beforePos + 1),
|
|
361
|
+
);
|
|
362
|
+
if (!firstChildBlockInfo.isBlockContainer) {
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if (selectionAtBlockEnd && selectionEmpty) {
|
|
367
|
+
const firstChildBlockContent =
|
|
368
|
+
firstChildBlockInfo.blockContent.node;
|
|
369
|
+
const firstChildBlockHasInlineContent =
|
|
370
|
+
firstChildBlockContent.type.spec.content === "inline*";
|
|
371
|
+
const blockHasInlineContent =
|
|
372
|
+
blockContent.node.type.spec.content === "inline*";
|
|
373
|
+
|
|
374
|
+
return (
|
|
375
|
+
chain()
|
|
376
|
+
// Un-nests child block's children if necessary.
|
|
377
|
+
.insertContentAt(
|
|
378
|
+
firstChildBlockInfo.bnBlock.afterPos,
|
|
379
|
+
firstChildBlockInfo.childContainer?.node.content ||
|
|
380
|
+
Fragment.empty,
|
|
381
|
+
)
|
|
382
|
+
.deleteRange(
|
|
383
|
+
// Deletes whole child container if there's only one child.
|
|
384
|
+
childContainer.node.childCount === 1
|
|
385
|
+
? {
|
|
386
|
+
from: childContainer.beforePos,
|
|
387
|
+
to: childContainer.afterPos,
|
|
388
|
+
}
|
|
389
|
+
: {
|
|
390
|
+
from: firstChildBlockInfo.bnBlock.beforePos,
|
|
391
|
+
to: firstChildBlockInfo.bnBlock.afterPos,
|
|
392
|
+
},
|
|
393
|
+
)
|
|
394
|
+
// Appends inline content from child block if possible.
|
|
395
|
+
.insertContentAt(
|
|
396
|
+
state.selection.from,
|
|
397
|
+
firstChildBlockHasInlineContent && blockHasInlineContent
|
|
398
|
+
? firstChildBlockContent.content
|
|
399
|
+
: null,
|
|
400
|
+
)
|
|
401
|
+
.setTextSelection(state.selection.from)
|
|
402
|
+
.scrollIntoView()
|
|
403
|
+
.run()
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return false;
|
|
408
|
+
}),
|
|
300
409
|
// Merges block with the next one (at the same nesting level or lower),
|
|
301
410
|
// if one exists, the block has no children, and the selection is at the
|
|
302
411
|
// end of the block.
|
|
303
412
|
() =>
|
|
304
413
|
commands.command(({ state }) => {
|
|
305
|
-
// TODO: Change this to not rely on offsets & schema assumptions
|
|
306
414
|
const blockInfo = getBlockInfoFromSelection(state);
|
|
307
415
|
if (!blockInfo.isBlockContainer) {
|
|
308
416
|
return false;
|
|
309
417
|
}
|
|
310
|
-
const {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
418
|
+
const { bnBlock: blockContainer, blockContent } = blockInfo;
|
|
419
|
+
|
|
420
|
+
const nextBlockInfo = getNextBlockInfo(
|
|
421
|
+
state.doc,
|
|
422
|
+
blockInfo.bnBlock.beforePos,
|
|
423
|
+
);
|
|
424
|
+
if (!nextBlockInfo || !nextBlockInfo.isBlockContainer) {
|
|
425
|
+
return false;
|
|
426
|
+
}
|
|
315
427
|
|
|
316
|
-
const { depth } = state.doc.resolve(blockContainer.beforePos);
|
|
317
|
-
const blockAtDocEnd =
|
|
318
|
-
blockContainer.afterPos === state.doc.nodeSize - 3;
|
|
319
428
|
const selectionAtBlockEnd =
|
|
320
429
|
state.selection.from === blockContent.afterPos - 1;
|
|
321
430
|
const selectionEmpty = state.selection.empty;
|
|
322
|
-
const hasChildBlocks = childContainer !== undefined;
|
|
323
431
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
432
|
+
const posBetweenBlocks = blockContainer.afterPos;
|
|
433
|
+
|
|
434
|
+
if (selectionAtBlockEnd && selectionEmpty) {
|
|
435
|
+
return chain()
|
|
436
|
+
.command(mergeBlocksCommand(posBetweenBlocks))
|
|
437
|
+
.scrollIntoView()
|
|
438
|
+
.run();
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
return false;
|
|
442
|
+
}),
|
|
443
|
+
// If the previous block is a columnList, moves the current block to
|
|
444
|
+
// the end of the last column in it.
|
|
445
|
+
() =>
|
|
446
|
+
commands.command(({ state, tr, dispatch }) => {
|
|
447
|
+
const blockInfo = getBlockInfoFromSelection(state);
|
|
448
|
+
if (!blockInfo.isBlockContainer) {
|
|
449
|
+
return false;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
const nextBlockInfo = getNextBlockInfo(
|
|
453
|
+
state.doc,
|
|
454
|
+
blockInfo.bnBlock.beforePos,
|
|
455
|
+
);
|
|
456
|
+
if (!nextBlockInfo || nextBlockInfo.isBlockContainer) {
|
|
457
|
+
return false;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
if (dispatch) {
|
|
461
|
+
const columnBeforePos = nextBlockInfo.bnBlock.beforePos + 1;
|
|
462
|
+
const $blockBeforePos = tr.doc.resolve(columnBeforePos + 1);
|
|
463
|
+
|
|
464
|
+
tr.delete(
|
|
465
|
+
$blockBeforePos.pos,
|
|
466
|
+
$blockBeforePos.pos + $blockBeforePos.nodeAfter!.nodeSize,
|
|
467
|
+
);
|
|
468
|
+
fixColumnList(tr, nextBlockInfo.bnBlock.beforePos);
|
|
469
|
+
tr.insert(blockInfo.bnBlock.afterPos, $blockBeforePos.nodeAfter!);
|
|
470
|
+
tr.setSelection(
|
|
471
|
+
TextSelection.near(tr.doc.resolve($blockBeforePos.pos)),
|
|
472
|
+
);
|
|
473
|
+
|
|
474
|
+
return true;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
return false;
|
|
478
|
+
}),
|
|
479
|
+
// If the block is the last in a column, moves it to the start of the
|
|
480
|
+
// next column. If there is no next column, moves it below the
|
|
481
|
+
// columnList.
|
|
482
|
+
() =>
|
|
483
|
+
commands.command(({ state, tr, dispatch }) => {
|
|
484
|
+
const blockInfo = getBlockInfoFromSelection(state);
|
|
485
|
+
if (!blockInfo.isBlockContainer) {
|
|
486
|
+
return false;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
const selectionAtBlockEnd =
|
|
490
|
+
tr.selection.from === blockInfo.blockContent.afterPos - 1;
|
|
491
|
+
if (!selectionAtBlockEnd) {
|
|
492
|
+
return false;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
const $pos = tr.doc.resolve(blockInfo.bnBlock.afterPos);
|
|
496
|
+
|
|
497
|
+
const nextBlock = $pos.nodeAfter;
|
|
498
|
+
if (nextBlock) {
|
|
499
|
+
return false;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
const parentBlock = $pos.node();
|
|
503
|
+
if (parentBlock.type.name !== "column") {
|
|
504
|
+
return false;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
const $blockEndPos = tr.doc.resolve(blockInfo.bnBlock.afterPos);
|
|
508
|
+
const $columnEndPos = tr.doc.resolve($blockEndPos.after());
|
|
509
|
+
const columnListEndPos = $columnEndPos.after();
|
|
510
|
+
|
|
511
|
+
if (dispatch) {
|
|
512
|
+
// Position before first block in next column, or first block
|
|
513
|
+
// after columnList if there is no next column.
|
|
514
|
+
const nextBlockBeforePos =
|
|
515
|
+
$columnEndPos.pos === columnListEndPos - 1
|
|
516
|
+
? columnListEndPos
|
|
517
|
+
: $columnEndPos.pos + 1;
|
|
518
|
+
const nextBlockInfo = getBlockInfoFromResolvedPos(
|
|
519
|
+
tr.doc.resolve(nextBlockBeforePos),
|
|
520
|
+
);
|
|
521
|
+
|
|
522
|
+
tr.delete(
|
|
523
|
+
nextBlockInfo.bnBlock.beforePos,
|
|
524
|
+
nextBlockInfo.bnBlock.afterPos,
|
|
525
|
+
);
|
|
526
|
+
fixColumnList(
|
|
527
|
+
tr,
|
|
528
|
+
columnListEndPos - $columnEndPos.node().nodeSize,
|
|
529
|
+
);
|
|
530
|
+
tr.insert($blockEndPos.pos, nextBlockInfo.bnBlock.node);
|
|
531
|
+
tr.setSelection(
|
|
532
|
+
TextSelection.near(tr.doc.resolve(nextBlockBeforePos)),
|
|
533
|
+
);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
return true;
|
|
537
|
+
}),
|
|
538
|
+
// Deletes the next block at either the same or lower nesting level, if
|
|
539
|
+
// the selection is empty and at the end of the block. If both the
|
|
540
|
+
// current and next blocks have inline content, the next block's
|
|
541
|
+
// content is appended to the current block's. The next block's own
|
|
542
|
+
// children are unindented before it's deleted.
|
|
543
|
+
() =>
|
|
544
|
+
commands.command(({ state }) => {
|
|
545
|
+
const blockInfo = getBlockInfoFromSelection(state);
|
|
546
|
+
if (!blockInfo.isBlockContainer) {
|
|
547
|
+
return false;
|
|
548
|
+
}
|
|
549
|
+
const { blockContent } = blockInfo;
|
|
550
|
+
|
|
551
|
+
const selectionAtBlockEnd =
|
|
552
|
+
state.selection.from === blockContent.afterPos - 1;
|
|
553
|
+
const selectionEmpty = state.selection.empty;
|
|
554
|
+
|
|
555
|
+
if (selectionAtBlockEnd && selectionEmpty) {
|
|
556
|
+
const getNextBlockInfoAtAnyLevel = (
|
|
557
|
+
doc: Node,
|
|
558
|
+
beforePos: number,
|
|
559
|
+
) => {
|
|
560
|
+
const nextBlockInfo = getNextBlockInfo(doc, beforePos);
|
|
561
|
+
if (nextBlockInfo) {
|
|
562
|
+
return nextBlockInfo;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
const parentBlockInfo = getParentBlockInfo(doc, beforePos);
|
|
566
|
+
if (!parentBlockInfo) {
|
|
567
|
+
return undefined;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
return getNextBlockInfoAtAnyLevel(
|
|
571
|
+
doc,
|
|
572
|
+
parentBlockInfo.bnBlock.beforePos,
|
|
573
|
+
);
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
const nextBlockInfo = getNextBlockInfoAtAnyLevel(
|
|
577
|
+
state.doc,
|
|
578
|
+
blockInfo.bnBlock.beforePos,
|
|
579
|
+
);
|
|
580
|
+
if (!nextBlockInfo || !nextBlockInfo.isBlockContainer) {
|
|
581
|
+
return false;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
const nextBlockContent = nextBlockInfo.blockContent.node;
|
|
585
|
+
const nextBlockHasInlineContent =
|
|
586
|
+
nextBlockContent.type.spec.content === "inline*";
|
|
587
|
+
const blockHasInlineContent =
|
|
588
|
+
blockContent.node.type.spec.content === "inline*";
|
|
589
|
+
|
|
590
|
+
return (
|
|
591
|
+
chain()
|
|
592
|
+
// Un-nests next block's children if necessary.
|
|
593
|
+
.insertContentAt(
|
|
594
|
+
nextBlockInfo.bnBlock.afterPos,
|
|
595
|
+
nextBlockInfo.childContainer?.node.content ||
|
|
596
|
+
Fragment.empty,
|
|
597
|
+
)
|
|
598
|
+
.deleteRange({
|
|
599
|
+
from: nextBlockInfo.bnBlock.beforePos,
|
|
600
|
+
to: nextBlockInfo.bnBlock.afterPos,
|
|
601
|
+
})
|
|
602
|
+
// Appends inline content from child block if possible.
|
|
603
|
+
.insertContentAt(
|
|
604
|
+
state.selection.from,
|
|
605
|
+
nextBlockHasInlineContent && blockHasInlineContent
|
|
606
|
+
? nextBlockContent.content
|
|
607
|
+
: null,
|
|
608
|
+
)
|
|
609
|
+
.setTextSelection(state.selection.from)
|
|
610
|
+
.scrollIntoView()
|
|
611
|
+
.run()
|
|
612
|
+
);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
return false;
|
|
616
|
+
}),
|
|
617
|
+
// Deletes the current block if it's an empty block with inline content,
|
|
618
|
+
// and moves the selection to the next block.
|
|
619
|
+
() =>
|
|
620
|
+
commands.command(({ state }) => {
|
|
621
|
+
const blockInfo = getBlockInfoFromSelection(state);
|
|
622
|
+
if (!blockInfo.isBlockContainer) {
|
|
623
|
+
return false;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
const blockEmpty =
|
|
627
|
+
blockInfo.blockContent.node.childCount === 0 &&
|
|
628
|
+
blockInfo.blockContent.node.type.spec.content === "inline*";
|
|
629
|
+
|
|
630
|
+
if (blockEmpty) {
|
|
631
|
+
const nextBlockInfo = getNextBlockInfo(
|
|
632
|
+
state.doc,
|
|
633
|
+
blockInfo.bnBlock.beforePos,
|
|
634
|
+
);
|
|
635
|
+
if (!nextBlockInfo || !nextBlockInfo.isBlockContainer) {
|
|
636
|
+
return false;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
let chainedCommands = chain();
|
|
640
|
+
|
|
641
|
+
if (
|
|
642
|
+
nextBlockInfo.blockContent.node.type.spec.content ===
|
|
643
|
+
"tableRow+"
|
|
644
|
+
) {
|
|
645
|
+
const tableBlockStartPos = blockInfo.bnBlock.afterPos + 1;
|
|
646
|
+
const tableBlockContentStartPos = tableBlockStartPos + 1;
|
|
647
|
+
const firstRowStartPos = tableBlockContentStartPos + 1;
|
|
648
|
+
const firstCellStartPos = firstRowStartPos + 1;
|
|
649
|
+
const firstCellParagraphStartPos = firstCellStartPos + 1;
|
|
650
|
+
|
|
651
|
+
chainedCommands = chainedCommands.setTextSelection(
|
|
652
|
+
firstCellParagraphStartPos,
|
|
653
|
+
);
|
|
654
|
+
} else if (
|
|
655
|
+
nextBlockInfo.blockContent.node.type.spec.content === ""
|
|
656
|
+
) {
|
|
657
|
+
chainedCommands = chainedCommands.setNodeSelection(
|
|
658
|
+
nextBlockInfo.blockContent.beforePos,
|
|
659
|
+
);
|
|
660
|
+
} else {
|
|
661
|
+
chainedCommands = chainedCommands.setTextSelection(
|
|
662
|
+
nextBlockInfo.blockContent.beforePos + 1,
|
|
663
|
+
);
|
|
338
664
|
}
|
|
339
665
|
|
|
340
|
-
return
|
|
666
|
+
return chainedCommands
|
|
667
|
+
.deleteRange({
|
|
668
|
+
from: blockInfo.bnBlock.beforePos,
|
|
669
|
+
to: blockInfo.bnBlock.afterPos,
|
|
670
|
+
})
|
|
671
|
+
.scrollIntoView()
|
|
672
|
+
.run();
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
return false;
|
|
676
|
+
}),
|
|
677
|
+
// Deletes next block if it contains no content and isn't a table,
|
|
678
|
+
// when the selection is empty and at the end of the block. Moves the
|
|
679
|
+
// current block into the deleted block's place.
|
|
680
|
+
() =>
|
|
681
|
+
commands.command(({ state }) => {
|
|
682
|
+
const blockInfo = getBlockInfoFromSelection(state);
|
|
683
|
+
|
|
684
|
+
if (!blockInfo.isBlockContainer) {
|
|
685
|
+
return false;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
const selectionAtBlockEnd =
|
|
689
|
+
state.selection.from === blockInfo.blockContent.afterPos - 1;
|
|
690
|
+
const selectionEmpty = state.selection.empty;
|
|
691
|
+
|
|
692
|
+
const nextBlockInfo = getNextBlockInfo(
|
|
693
|
+
state.doc,
|
|
694
|
+
blockInfo.bnBlock.beforePos,
|
|
695
|
+
);
|
|
696
|
+
if (!nextBlockInfo) {
|
|
697
|
+
return false;
|
|
698
|
+
}
|
|
699
|
+
if (!nextBlockInfo.isBlockContainer) {
|
|
700
|
+
return false;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
if (nextBlockInfo && selectionAtBlockEnd && selectionEmpty) {
|
|
704
|
+
const nextBlockNotTableAndNoContent =
|
|
705
|
+
nextBlockInfo.blockContent.node.type.spec.content === "" ||
|
|
706
|
+
(nextBlockInfo.blockContent.node.type.spec.content ===
|
|
707
|
+
"inline*" &&
|
|
708
|
+
nextBlockInfo.blockContent.node.childCount === 0);
|
|
709
|
+
|
|
710
|
+
if (nextBlockNotTableAndNoContent) {
|
|
711
|
+
const childBlocks =
|
|
712
|
+
nextBlockInfo.bnBlock.node.lastChild!.content;
|
|
713
|
+
return chain()
|
|
714
|
+
.deleteRange({
|
|
715
|
+
from: nextBlockInfo.bnBlock.beforePos,
|
|
716
|
+
to: nextBlockInfo.bnBlock.afterPos,
|
|
717
|
+
})
|
|
718
|
+
.insertContentAt(
|
|
719
|
+
blockInfo.bnBlock.afterPos,
|
|
720
|
+
nextBlockInfo.bnBlock.node.childCount === 2
|
|
721
|
+
? childBlocks
|
|
722
|
+
: null,
|
|
723
|
+
)
|
|
724
|
+
.run();
|
|
725
|
+
}
|
|
341
726
|
}
|
|
342
727
|
|
|
343
728
|
return false;
|
package/src/i18n/locales/fa.ts
CHANGED
|
@@ -81,7 +81,7 @@ export const fa = {
|
|
|
81
81
|
check_list: {
|
|
82
82
|
title: "بازینه",
|
|
83
83
|
subtext: "فهرست با جعبه انتخاب",
|
|
84
|
-
aliases: ["چک لیست", "لیست انجام کار", "لیست تیک دار","بازینه"],
|
|
84
|
+
aliases: ["چک لیست", "لیست انجام کار", "لیست تیک دار", "بازینه"],
|
|
85
85
|
group: "بلوکهای پایه",
|
|
86
86
|
},
|
|
87
87
|
paragraph: {
|
|
@@ -111,36 +111,19 @@ export const fa = {
|
|
|
111
111
|
image: {
|
|
112
112
|
title: "تصویر",
|
|
113
113
|
subtext: "تصویر با قابلیت تغییر اندازه و زیرنویس",
|
|
114
|
-
aliases: [
|
|
115
|
-
"تصویر",
|
|
116
|
-
"عکس",
|
|
117
|
-
"آپلود تصویر",
|
|
118
|
-
"مدیا",
|
|
119
|
-
"لینک عکس",
|
|
120
|
-
],
|
|
114
|
+
aliases: ["تصویر", "عکس", "آپلود تصویر", "مدیا", "لینک عکس"],
|
|
121
115
|
group: "رسانه",
|
|
122
116
|
},
|
|
123
117
|
video: {
|
|
124
118
|
title: "ویدیو",
|
|
125
119
|
subtext: "ویدیو با قابلیت تغییر اندازه و زیرنویس",
|
|
126
|
-
aliases: [
|
|
127
|
-
"ویدیو",
|
|
128
|
-
"فیلم",
|
|
129
|
-
"آپلود ویدیو",
|
|
130
|
-
"مدیا",
|
|
131
|
-
],
|
|
120
|
+
aliases: ["ویدیو", "فیلم", "آپلود ویدیو", "مدیا"],
|
|
132
121
|
group: "رسانه",
|
|
133
122
|
},
|
|
134
123
|
audio: {
|
|
135
124
|
title: "صوتی",
|
|
136
125
|
subtext: "فایل صوتی جاسازی شده با زیرنویس",
|
|
137
|
-
aliases: [
|
|
138
|
-
"صوتی",
|
|
139
|
-
"صدا",
|
|
140
|
-
"آهنگ",
|
|
141
|
-
"موسیقی",
|
|
142
|
-
"آپلود صدا",
|
|
143
|
-
],
|
|
126
|
+
aliases: ["صوتی", "صدا", "آهنگ", "موسیقی", "آپلود صدا"],
|
|
144
127
|
group: "رسانه",
|
|
145
128
|
},
|
|
146
129
|
file: {
|
package/src/i18n/locales/ru.ts
CHANGED