diff --git a/apps/client/src/widgets/type_widgets/abstract_code_type_widget.ts b/apps/client/src/widgets/type_widgets/abstract_code_type_widget.ts index babe02f69..4cd477eba 100644 --- a/apps/client/src/widgets/type_widgets/abstract_code_type_widget.ts +++ b/apps/client/src/widgets/type_widgets/abstract_code_type_widget.ts @@ -1,5 +1,5 @@ import TypeWidget from "./type_widget.js"; -import CodeMirror from "@triliumnext/codemirror"; +import CodeMirror, { type EditorConfig } from "@triliumnext/codemirror"; /** * An abstract {@link TypeWidget} which implements the CodeMirror editor, meant to be used as a parent for @@ -26,18 +26,19 @@ export default class AbstractCodeTypeWidget extends TypeWidget { async #initEditor() { this.codeEditor = new CodeMirror({ parent: this.$editor[0], + ...this.getExtraOpts() }); } - // /** - // * Can be extended in derived classes to add extra options to the CodeMirror constructor. The options are appended - // * at the end, so it is possible to override the default values introduced by the abstract editor as well. - // * - // * @returns the extra options to be passed to the CodeMirror constructor. - // */ - // getExtraOpts(): Partial { - // return {}; - // } + /** + * Can be extended in derived classes to add extra options to the CodeMirror constructor. The options are appended + * at the end, so it is possible to override the default values introduced by the abstract editor as well. + * + * @returns the extra options to be passed to the CodeMirror constructor. + */ + getExtraOpts(): Partial { + return {}; + } /** * Called as soon as the CodeMirror library has been loaded and the editor was constructed. Can be extended in diff --git a/apps/client/src/widgets/type_widgets/editable_code.ts b/apps/client/src/widgets/type_widgets/editable_code.ts index 0a3312edd..91047876e 100644 --- a/apps/client/src/widgets/type_widgets/editable_code.ts +++ b/apps/client/src/widgets/type_widgets/editable_code.ts @@ -7,6 +7,7 @@ import AbstractCodeTypeWidget from "./abstract_code_type_widget.js"; import appContext from "../../components/app_context.js"; import type { TouchBarItem } from "../../components/touch_bar.js"; import { hasTouchBar } from "../../services/utils.js"; +import type { EditorConfig } from "@triliumnext/codemirror"; const TPL = /*html*/`
@@ -41,6 +42,12 @@ export default class EditableCodeTypeWidget extends AbstractCodeTypeWidget { super.doRender(); } + getExtraOpts(): Partial { + return { + onContentChanged: () => this.spacedUpdate.scheduleUpdate() + } + } + // getExtraOpts(): Partial { // return { // keyMap: options.is("vimKeymapEnabled") ? "vim" : "default", @@ -52,10 +59,6 @@ export default class EditableCodeTypeWidget extends AbstractCodeTypeWidget { // }; // } - onEditorInitialized() { - // this.codeEditor.on("change", () => this.spacedUpdate.scheduleUpdate()); - } - async doRefresh(note: FNote) { const blob = await this.note?.getBlob(); @@ -72,8 +75,7 @@ export default class EditableCodeTypeWidget extends AbstractCodeTypeWidget { getData() { return { - // content: this.codeEditor.getValue() - content: "" + content: this.codeEditor.getText() }; } diff --git a/packages/codemirror/src/index.ts b/packages/codemirror/src/index.ts index 20c76b227..dd904817a 100644 --- a/packages/codemirror/src/index.ts +++ b/packages/codemirror/src/index.ts @@ -1,15 +1,45 @@ import { defaultKeymap } from "@codemirror/commands"; -import { EditorView, keymap, lineNumbers, type EditorViewConfig } from "@codemirror/view"; +import { EditorView, keymap, lineNumbers, ViewUpdate, type EditorViewConfig } from "@codemirror/view"; + +type ContentChangedListener = () => void; + +export interface EditorConfig extends EditorViewConfig { + onContentChanged?: ContentChangedListener; +} export default class CodeMirror extends EditorView { - constructor(config: EditorViewConfig) { + + private config: EditorConfig; + + constructor(config: EditorConfig) { + let extensions = [ + keymap.of(defaultKeymap), + lineNumbers() + ]; + + if (Array.isArray(config.extensions)) { + extensions = [...extensions, ...config.extensions]; + } + + if (config.onContentChanged) { + extensions.push(EditorView.updateListener.of((v) => this.#onDocumentUpdated(v))); + } + super({ ...config, - extensions: [ - keymap.of(defaultKeymap), - lineNumbers() - ] + extensions }); + this.config = config; + } + + #onDocumentUpdated(v: ViewUpdate) { + if (v.docChanged) { + this.config.onContentChanged?.(); + } + } + + getText() { + return this.state.doc.toString(); } setText(content: string) {