fix: moving tables/blockQuote

This commit is contained in:
SiriusXT 2025-06-10 18:50:32 +08:00
parent e6c2f729f4
commit 3a56a16a58

View File

@ -2,8 +2,7 @@
* https://github.com/TriliumNext/Notes/issues/1002 * https://github.com/TriliumNext/Notes/issues/1002
*/ */
import { Command, DocumentSelection, Element, Node, Plugin } from 'ckeditor5'; import { Command, DocumentSelection, Element, Node, Plugin, Range } from 'ckeditor5';
export default class MoveBlockUpDownPlugin extends Plugin { export default class MoveBlockUpDownPlugin extends Plugin {
init() { init() {
@ -81,36 +80,54 @@ abstract class MoveBlockUpDownCommand extends Command {
} }
} }
// Restore selection to all items if many have been moved // Restore selection
if ( let range: Range;
startOffset <= (firstBlock.maxOffset ?? Infinity) && const maxStart = firstBlock.maxOffset ?? startOffset;
endOffset <= (lastBlock.maxOffset ?? Infinity) const maxEnd = lastBlock.maxOffset ?? endOffset;
) { // If original offsets valid within bounds, restore partial selection
writer.setSelection( if (startOffset <= maxStart && endOffset <= maxEnd) {
writer.createRange( const clampedStart = Math.min(startOffset, maxStart);
writer.createPositionAt(firstBlock, startOffset), const clampedEnd = Math.min(endOffset, maxEnd);
writer.createPositionAt(lastBlock, endOffset) range = writer.createRange(
) writer.createPositionAt(firstBlock, clampedStart),
writer.createPositionAt(lastBlock, clampedEnd)
);
} else { // Fallback: select entire moved blocks (handles tables)
range = writer.createRange(
writer.createPositionBefore(firstBlock),
writer.createPositionAfter(lastBlock)
); );
} }
writer.setSelection(range);
this.editor.editing.view.focus();
this.scrollToSelection(); this.scrollToSelection();
}); });
} }
getSelectedBlocks(selection: DocumentSelection) { getSelectedBlocks(selection: DocumentSelection) {
const blocks = [...selection.getSelectedBlocks()]; const blocks = [...selection.getSelectedBlocks()];
const resolved: Element[] = [];
// If the selected block is an object, such as a block quote or admonition, return the entire block. // Selects elements (such as Mermaid) when there are no blocks
if (blocks.length === 1) { if (!blocks.length) {
const block = blocks[0]; const selectedObj = selection.getSelectedElement();
const parent = block.parent; if (selectedObj) {
if (!parent?.name?.startsWith('$')) { return [selectedObj];
return [parent as Element];
} }
} }
return blocks; for (const block of blocks) {
let el: Element = block;
// Traverse up until the parent is the root ($root) or there is no parent
while (el.parent && el.parent.name !== '$root') {
el = el.parent as Element;
}
resolved.push(el);
}
// Deduplicate adjacent duplicates (e.g., nested selections resolving to same block)
return resolved.filter((blk, idx) => idx === 0 || blk !== resolved[idx - 1]);
} }
scrollToSelection() { scrollToSelection() {