feat(editor): allow moving blocks up/down

This commit is contained in:
Elian Doran 2025-05-27 20:36:57 +03:00
parent 541897b1d0
commit 27d1a87fb0
No known key found for this signature in database
4 changed files with 106 additions and 3 deletions

View File

@ -55,6 +55,7 @@
* [Math in text notes: equations can now be displayed on multiple lines](https://github.com/TriliumNext/Notes/pull/2003) by @SiriusXT * [Math in text notes: equations can now be displayed on multiple lines](https://github.com/TriliumNext/Notes/pull/2003) by @SiriusXT
* [Metrics endpoint](https://github.com/TriliumNext/Notes/pull/2024) by @perfectra1n * [Metrics endpoint](https://github.com/TriliumNext/Notes/pull/2024) by @perfectra1n
* Docker: Rootless [Dockerfiles are now available](https://github.com/TriliumNext/Notes/pull/1923/files) by @perfectra1n * Docker: Rootless [Dockerfiles are now available](https://github.com/TriliumNext/Notes/pull/1923/files) by @perfectra1n
* [Text notes: add a way to move up and down text lines via a keyboard shortcut](https://github.com/TriliumNext/Notes/issues/1002) by @dogfuntom
## 📖 Documentation ## 📖 Documentation

View File

@ -30,13 +30,18 @@ declare module "ckeditor5" {
} }
interface EditorConfig { interface EditorConfig {
syntaxHighlighting: { syntaxHighlighting?: {
loadHighlightJs: () => Promise<any>; loadHighlightJs: () => Promise<any>;
mapLanguageName(mimeType: string): string; mapLanguageName(mimeType: string): string;
defaultMimeType: string; defaultMimeType: string;
enabled: boolean; enabled: boolean;
}, },
moveBlockUp?: {
keystroke: string;
},
moveBlockDown?: {
keystroke: string;
},
clipboard?: { clipboard?: {
copy(text: string): void; copy(text: string): void;
} }

View File

@ -25,6 +25,7 @@ import "@triliumnext/ckeditor5-footnotes/index.css";
import "@triliumnext/ckeditor5-math/index.css"; import "@triliumnext/ckeditor5-math/index.css";
import CodeBlockToolbar from "./plugins/code_block_toolbar.js"; import CodeBlockToolbar from "./plugins/code_block_toolbar.js";
import CodeBlockLanguageDropdown from "./plugins/code_block_language_dropdown.js"; import CodeBlockLanguageDropdown from "./plugins/code_block_language_dropdown.js";
import MoveBlockUpDownPlugin from "./plugins/move_block_updown.js";
/** /**
* Plugins that are specific to Trilium and not part of the CKEditor 5 core, included in both text editors but not in the attribute editor. * Plugins that are specific to Trilium and not part of the CKEditor 5 core, included in both text editors but not in the attribute editor.
@ -42,7 +43,8 @@ const TRILIUM_PLUGINS: typeof Plugin[] = [
Uploadfileplugin, Uploadfileplugin,
SyntaxHighlighting, SyntaxHighlighting,
CodeBlockLanguageDropdown, CodeBlockLanguageDropdown,
CodeBlockToolbar CodeBlockToolbar,
MoveBlockUpDownPlugin
]; ];
/** /**

View File

@ -0,0 +1,95 @@
/**
* https://github.com/TriliumNext/Notes/issues/1002
*/
import { Command, DocumentSelection, Element, Plugin } from 'ckeditor5';
export default class MoveBlockUpDownPlugin extends Plugin {
init() {
const editor = this.editor;
editor.config.define('moveBlockUp', {
keystroke: 'ctrl+arrowup',
});
editor.config.define('moveBlockDown', {
keystroke: 'ctrl+arrowdown',
});
const keystrokeUp = editor.config.get('moveBlockUp.keystroke')!;
const keystrokeDown = editor.config.get('moveBlockDown.keystroke')!;
editor.commands.add('moveBlockUp', new MoveBlockUpCommand(editor));
editor.commands.add('moveBlockDown', new MoveBlockDownCommand(editor));
editor.keystrokes.set(keystrokeUp, 'moveBlockUp');
editor.keystrokes.set(keystrokeDown, 'moveBlockDown');
}
}
abstract class MoveBlockUpDownCommand extends Command {
abstract getSelectedBlocks(selection: DocumentSelection);
abstract getSibling(selectedBlock: Element);
abstract get offset(): "before" | "after";
refresh() {
const selection = this.editor.model.document.selection;
const selectedBlocks = this.getSelectedBlocks(selection);
this.isEnabled = true;
for (const selectedBlock of selectedBlocks) {
if (!this.getSibling(selectedBlock)) this.isEnabled = false;
}
}
execute() {
const model = this.editor.model;
const selection = model.document.selection;
const selectedBlocks = this.getSelectedBlocks(selection);
model.change((writer) => {
for (const selectedBlock of selectedBlocks) {
const sibling = this.getSibling(selectedBlock);
if (sibling) {
const range = model.createRangeOn(selectedBlock);
writer.move(range, sibling, this.offset);
}
}
});
}
}
class MoveBlockUpCommand extends MoveBlockUpDownCommand {
getSelectedBlocks(selection: DocumentSelection) {
return [...selection.getSelectedBlocks()];
}
getSibling(selectedBlock: Element) {
return selectedBlock.previousSibling;
}
get offset() {
return "before" as const;
}
}
class MoveBlockDownCommand extends MoveBlockUpDownCommand {
/** @override */
getSelectedBlocks(selection: DocumentSelection) {
return [...selection.getSelectedBlocks()].reverse();
}
/** @override */
getSibling(selectedBlock: Element) {
return selectedBlock.nextSibling;
}
/** @override */
get offset() {
return "after" as const;
}
}