Merge branch 'develop' of https://github.com/TriliumNext/Notes into develop

This commit is contained in:
Adorian Doran 2025-05-27 21:14:58 +03:00
commit eb6c122658
4 changed files with 109 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
* [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
* [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

View File

@ -23,6 +23,8 @@ declare global {
}
}
type Keystroke = string | string[];
declare module "ckeditor5" {
interface Editor {
getSelectedHtml(): string;
@ -30,13 +32,18 @@ declare module "ckeditor5" {
}
interface EditorConfig {
syntaxHighlighting: {
syntaxHighlighting?: {
loadHighlightJs: () => Promise<any>;
mapLanguageName(mimeType: string): string;
defaultMimeType: string;
enabled: boolean;
},
moveBlockUp?: {
keystroke: Keystroke;
},
moveBlockDown?: {
keystroke: Keystroke;
},
clipboard?: {
copy(text: string): void;
}

View File

@ -25,6 +25,7 @@ import "@triliumnext/ckeditor5-footnotes/index.css";
import "@triliumnext/ckeditor5-math/index.css";
import CodeBlockToolbar from "./plugins/code_block_toolbar.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.
@ -42,7 +43,8 @@ const TRILIUM_PLUGINS: typeof Plugin[] = [
Uploadfileplugin,
SyntaxHighlighting,
CodeBlockLanguageDropdown,
CodeBlockToolbar
CodeBlockToolbar,
MoveBlockUpDownPlugin
];
/**

View File

@ -0,0 +1,96 @@
/**
* 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', 'alt+arrowup'],
});
editor.config.define('moveBlockDown', {
keystroke: ['ctrl+arrowdown', 'alt+arrowdown'],
});
editor.commands.add('moveBlockUp', new MoveBlockUpCommand(editor));
editor.commands.add('moveBlockDown', new MoveBlockDownCommand(editor));
for (const keystroke of editor.config.get('moveBlockUp.keystroke') ?? []) {
editor.keystrokes.set(keystroke, 'moveBlockUp');
}
for (const keystroke of editor.config.get('moveBlockDown.keystroke') ?? []) {
editor.keystrokes.set(keystroke, '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;
}
}