]> BookStack Code Mirror - bookstack/commitdiff
Got md shortcuts working, marked actions for update
authorDan Brown <redacted>
Tue, 11 Apr 2023 10:48:58 +0000 (11:48 +0100)
committerDan Brown <redacted>
Tue, 11 Apr 2023 10:48:58 +0000 (11:48 +0100)
resources/js/code/index.mjs
resources/js/components/markdown-editor.js
resources/js/markdown/actions.js
resources/js/markdown/codemirror.js
resources/js/markdown/shortcuts.js

index 6cad052f42583cab397b72d3086a67e69d60f4ca..3fe4a6d86bd5107a30ee44388607243a5c9e738b 100644 (file)
@@ -1,4 +1,4 @@
-import {EditorView} from "@codemirror/view"
+import {EditorView, keymap} from "@codemirror/view"
 import Clipboard from "clipboard/dist/clipboard.min";
 
 // Modes
@@ -182,9 +182,10 @@ export function updateLayout(cmInstance) {
  * @param {HTMLElement} elem
  * @param {function} onChange
  * @param {object} domEventHandlers
+ * @param {Array} keyBindings
  * @returns {*}
  */
-export function markdownEditor(elem, onChange, domEventHandlers) {
+export function markdownEditor(elem, onChange, domEventHandlers, keyBindings) {
     const content = elem.textContent;
 
     // TODO - Change to pass something else that's useful, probably extension array?
@@ -199,20 +200,11 @@ export function markdownEditor(elem, onChange, domEventHandlers) {
                 onChange(v);
             }),
             EditorView.domEventHandlers(domEventHandlers),
+            keymap.of(keyBindings),
         ],
     });
 
     elem.style.display = 'none';
 
     return ev;
-}
-
-/**
- * Get the 'meta' key dependent on the user's system.
- * @returns {string}
- */
-export function getMetaKey() {
-    // TODO - Redo, Is needed? No CodeMirror instance to use.
-    const mac = CodeMirror.keyMap["default"] == CodeMirror.keyMap.macDefault;
-    return mac ? "Cmd" : "Ctrl";
 }
\ No newline at end of file
index 6b4682d1e5fbe65c8c472cb2e32d5703ee26c95d..922916701085851e7a90989cfd3676b45a93b599 100644 (file)
@@ -45,7 +45,7 @@ export class MarkdownEditor extends Component {
         window.$events.emitPublic(this.elem, 'editor-markdown::setup', {
             markdownIt: this.editor.markdown.getRenderer(),
             displayEl: this.display,
-            // TODO
+            // TODO - change to codeMirrorView?
             // codeMirrorInstance: this.editor.cm,
         });
     }
@@ -58,7 +58,7 @@ export class MarkdownEditor extends Component {
             if (button === null) return;
 
             const action = button.getAttribute('data-action');
-            if (action === 'insertImage') this.editor.actions.insertImage();
+            if (action === 'insertImage') this.editor.actions.showImageInsert();
             if (action === 'insertLink') this.editor.actions.showLinkSelector();
             if (action === 'insertDrawing' && (event.ctrlKey || event.metaKey)) {
                 this.editor.actions.showImageManager();
index 666998723ef16236b5f462bef293a244112d6fe0..dfbe89c5a302f94979ea5547770821786e875f38 100644 (file)
@@ -28,7 +28,8 @@ export class Actions {
         return this.lastContent;
     }
 
-    insertImage() {
+    showImageInsert() {
+        // TODO
         const cursorPos = this.editor.cm.getCursor('from');
         /** @type {ImageManager} **/
         const imageManager = window.$components.first('image-manager');
@@ -42,7 +43,17 @@ export class Actions {
         }, 'gallery');
     }
 
+    insertImage() {
+        // TODO
+        const selectedText = this.editor.cm.getSelection();
+        const newText = `![${selectedText}](http://)`;
+        const cursorPos = this.editor.cm.getCursor('from');
+        this.editor.cm.replaceSelection(newText);
+        this.editor.cm.setCursor(cursorPos.line, cursorPos.ch + newText.length -1);
+    }
+
     insertLink() {
+        // TODO
         const cursorPos = this.editor.cm.getCursor('from');
         const selectedText = this.editor.cm.getSelection() || '';
         const newText = `[${selectedText}]()`;
@@ -53,6 +64,7 @@ export class Actions {
     }
 
     showImageManager() {
+        // TODO
         const cursorPos = this.editor.cm.getCursor('from');
         /** @type {ImageManager} **/
         const imageManager = window.$components.first('image-manager');
@@ -63,6 +75,7 @@ export class Actions {
 
     // Show the popup link selector and insert a link when finished
     showLinkSelector() {
+        // TODO
         const cursorPos = this.editor.cm.getCursor('from');
         /** @type {EntitySelectorPopup} **/
         const selector = window.$components.first('entity-selector-popup');
@@ -77,6 +90,7 @@ export class Actions {
 
     // Show draw.io if enabled and handle save.
     startDrawing() {
+        // TODO
         const url = this.editor.config.drawioUrl;
         if (!url) return;
 
@@ -101,6 +115,7 @@ export class Actions {
     }
 
     insertDrawing(image, originalCursor) {
+        // TODO
         const newText = `<div drawio-diagram="${image.id}"><img src="${image.url}"></div>`;
         this.editor.cm.focus();
         this.editor.cm.replaceSelection(newText);
@@ -109,6 +124,7 @@ export class Actions {
 
     // Show draw.io if enabled and handle save.
     editDrawing(imgContainer) {
+        // TODO
         const drawioUrl = this.editor.config.drawioUrl;
         if (!drawioUrl) {
             return;
@@ -145,6 +161,7 @@ export class Actions {
     }
 
     handleDrawingUploadError(error) {
+        // TODO
         if (error.status === 413) {
             window.$events.emit('error', this.editor.config.text.serverUploadLimit);
         } else {
@@ -155,6 +172,7 @@ export class Actions {
 
     // Make the editor full screen
     fullScreen() {
+        // TODO
         const container = this.editor.config.container;
         const alreadyFullscreen = container.classList.contains('fullscreen');
         container.classList.toggle('fullscreen', !alreadyFullscreen);
@@ -163,6 +181,7 @@ export class Actions {
 
     // Scroll to a specified text
     scrollToText(searchText) {
+        // TODO
         if (!searchText) {
             return;
         }
@@ -189,6 +208,7 @@ export class Actions {
     }
 
     focus() {
+        // TODO
         this.editor.cm.focus();
     }
 
@@ -197,6 +217,7 @@ export class Actions {
      * @param {String} content
      */
     insertContent(content) {
+        // TODO
         this.editor.cm.replaceSelection(content);
     }
 
@@ -205,6 +226,7 @@ export class Actions {
      * @param {String} content
      */
     prependContent(content) {
+        // TODO
         const cursorPos = this.editor.cm.getCursor('from');
         const newContent = content + '\n' + this.editor.cm.getValue();
         this.editor.cm.setValue(newContent);
@@ -217,6 +239,7 @@ export class Actions {
      * @param {String} content
      */
     appendContent(content) {
+        // TODO
         const cursorPos = this.editor.cm.getCursor('from');
         const newContent = this.editor.cm.getValue() + '\n' + content;
         this.editor.cm.setValue(newContent);
@@ -228,6 +251,7 @@ export class Actions {
      * @param {String} content
      */
     replaceContent(content) {
+        // TODO
         this.editor.cm.setValue(content);
     }
 
@@ -236,6 +260,7 @@ export class Actions {
      * @param {String} replace
      */
     findAndReplaceContent(search, replace) {
+        // TODO
         const text = this.editor.cm.getValue();
         const cursor = this.editor.cm.listSelections();
         this.editor.cm.setValue(text.replace(search, replace));
@@ -247,6 +272,7 @@ export class Actions {
      * @param {String} newStart
      */
     replaceLineStart(newStart) {
+        // TODO
         const cursor = this.editor.cm.getCursor();
         let lineContent = this.editor.cm.getLine(cursor.line);
         const lineLen = lineContent.length;
@@ -279,6 +305,7 @@ export class Actions {
      * @param {String} end
      */
     wrapLine(start, end) {
+        // TODO
         const cursor = this.editor.cm.getCursor();
         const lineContent = this.editor.cm.getLine(cursor.line);
         const lineLen = lineContent.length;
@@ -300,6 +327,7 @@ export class Actions {
      * @param {String} end
      */
     wrapSelection(start, end) {
+        // TODO
         const selection = this.editor.cm.getSelection();
         if (selection === '') return this.wrapLine(start, end);
 
@@ -324,6 +352,7 @@ export class Actions {
     }
 
     replaceLineStartForOrderedList() {
+        // TODO
         const cursor = this.editor.cm.getCursor();
         const prevLineContent = this.editor.cm.getLine(cursor.line - 1) || '';
         const listMatch = prevLineContent.match(/^(\s*)(\d)([).])\s/) || [];
@@ -341,6 +370,7 @@ export class Actions {
      * Creates a callout block if none existing, and removes it if cycling past the danger type.
      */
     cycleCalloutTypeAtSelection() {
+        // TODO
         const selectionRange = this.editor.cm.listSelections()[0];
         const lineContent = this.editor.cm.getLine(selectionRange.anchor.line);
         const lineLength = lineContent.length;
@@ -379,6 +409,7 @@ export class Actions {
      * @param {File} file
      */
     uploadImage(file) {
+        // TODO
         if (file === null || file.type.indexOf('image') !== 0) return;
         let ext = 'png';
 
@@ -436,6 +467,7 @@ export class Actions {
      * @param {Number} posY
      */
     insertTemplate(templateId, posX, posY) {
+        // TODO
         const cursorPos = this.editor.cm.coordsChar({left: posX, top: posY});
         this.editor.cm.setCursor(cursorPos);
         window.$http.get(`/templates/${templateId}`).then(resp => {
@@ -449,6 +481,7 @@ export class Actions {
      * @param {File[]} images
      */
     insertClipboardImages(images) {
+        // TODO
         const cursorPos = this.editor.cm.coordsChar({left: event.pageX, top: event.pageY});
         this.editor.cm.setCursor(cursorPos);
         for (const image of images) {
index dad999e7a64e4d8be764abc57cb4faa67828123b..cd620137d5accf6103d7384b9390f876f6d0cf02 100644 (file)
@@ -1,4 +1,4 @@
-import {provide as provideShortcuts} from "./shortcuts";
+import {provideKeyBindings} from "./shortcuts";
 import {debounce} from "../services/util";
 import Clipboard from "../services/clipboard";
 
@@ -28,15 +28,17 @@ export async function init(editor) {
         scroll: (event) => syncActive && onScrollDebounced(event)
     }
 
-    const cm = Code.markdownEditor(editor.config.inputEl, onViewUpdate, domEventHandlers);
+    const cm = Code.markdownEditor(
+        editor.config.inputEl,
+        onViewUpdate,
+        domEventHandlers,
+        provideKeyBindings(editor),
+    );
     window.cm = cm;
 
     // Will force to remain as ltr for now due to issues when HTML is in editor.
     // TODO
     // cm.setOption('direction', 'ltr');
-    // Register shortcuts
-    // TODO
-    // cm.setOption('extraKeys', provideShortcuts(editor, Code.getMetaKey()));
 
 
     // Handle image paste
index 17ffe2fb3a6fc69d94654fdcc63cc631d0af21f6..08841e6c231593d2d6e265e42a91988c660b637f 100644 (file)
@@ -1,48 +1,57 @@
 /**
- * Provide shortcuts for the given codemirror instance.
+ * Provide shortcuts for the editor instance.
  * @param {MarkdownEditor} editor
- * @param {String} metaKey
  * @returns {Object<String, Function>}
  */
-export function provide(editor, metaKey) {
+function provide(editor) {
     const shortcuts = {};
 
     // Insert Image shortcut
-    shortcuts[`${metaKey}-Alt-I`] = function(cm) {
-        const selectedText = cm.getSelection();
-        const newText = `![${selectedText}](http://)`;
-        const cursorPos = cm.getCursor('from');
-        cm.replaceSelection(newText);
-        cm.setCursor(cursorPos.line, cursorPos.ch + newText.length -1);
-    };
+    shortcuts['Mod-Alt-i'] = () => editor.actions.insertImage();
 
     // Save draft
-    shortcuts[`${metaKey}-S`] = cm => window.$events.emit('editor-save-draft');
+    shortcuts['Mod-s'] = cm => window.$events.emit('editor-save-draft');
 
     // Save page
-    shortcuts[`${metaKey}-Enter`] = cm => window.$events.emit('editor-save-page');
+    shortcuts['Mod-Enter'] = cm => window.$events.emit('editor-save-page');
 
     // Show link selector
-    shortcuts[`Shift-${metaKey}-K`] = cm => editor.actions.showLinkSelector();
+    shortcuts['Shift-Mod-k'] = cm => editor.actions.showLinkSelector();
 
     // Insert Link
-    shortcuts[`${metaKey}-K`] = cm => editor.actions.insertLink();
+    shortcuts['Mod-k'] = cm => editor.actions.insertLink();
 
     // FormatShortcuts
-    shortcuts[`${metaKey}-1`] = cm => editor.actions.replaceLineStart('##');
-    shortcuts[`${metaKey}-2`] = cm => editor.actions.replaceLineStart('###');
-    shortcuts[`${metaKey}-3`] = cm => editor.actions.replaceLineStart('####');
-    shortcuts[`${metaKey}-4`] = cm => editor.actions.replaceLineStart('#####');
-    shortcuts[`${metaKey}-5`] = cm => editor.actions.replaceLineStart('');
-    shortcuts[`${metaKey}-D`] = cm => editor.actions.replaceLineStart('');
-    shortcuts[`${metaKey}-6`] = cm => editor.actions.replaceLineStart('>');
-    shortcuts[`${metaKey}-Q`] = cm => editor.actions.replaceLineStart('>');
-    shortcuts[`${metaKey}-7`] = cm => editor.actions.wrapSelection('\n```\n', '\n```');
-    shortcuts[`${metaKey}-8`] = cm => editor.actions.wrapSelection('`', '`');
-    shortcuts[`Shift-${metaKey}-E`] = cm => editor.actions.wrapSelection('`', '`');
-    shortcuts[`${metaKey}-9`] = cm => editor.actions.cycleCalloutTypeAtSelection();
-    shortcuts[`${metaKey}-P`] = cm => editor.actions.replaceLineStart('-')
-    shortcuts[`${metaKey}-O`] = cm => editor.actions.replaceLineStartForOrderedList()
+    shortcuts['Mod-1'] = cm => editor.actions.replaceLineStart('##');
+    shortcuts['Mod-2'] = cm => editor.actions.replaceLineStart('###');
+    shortcuts['Mod-3'] = cm => editor.actions.replaceLineStart('####');
+    shortcuts['Mod-4'] = cm => editor.actions.replaceLineStart('#####');
+    shortcuts['Mod-5'] = cm => editor.actions.replaceLineStart('');
+    shortcuts['Mod-d'] = cm => editor.actions.replaceLineStart('');
+    shortcuts['Mod-6'] = cm => editor.actions.replaceLineStart('>');
+    shortcuts['Mod-q'] = cm => editor.actions.replaceLineStart('>');
+    shortcuts['Mod-7'] = cm => editor.actions.wrapSelection('\n```\n', '\n```');
+    shortcuts['Mod-8'] = cm => editor.actions.wrapSelection('`', '`');
+    shortcuts['Shift-Mod-e'] = cm => editor.actions.wrapSelection('`', '`');
+    shortcuts['Mod-9'] = cm => editor.actions.cycleCalloutTypeAtSelection();
+    shortcuts['Mod-p'] = cm => editor.actions.replaceLineStart('-')
+    shortcuts['Mod-o'] = cm => editor.actions.replaceLineStartForOrderedList()
 
     return shortcuts;
+}
+
+/**
+ * Get the editor shortcuts in CodeMirror keybinding format.
+ * @param {MarkdownEditor} editor
+ * @return {{key: String, run: function, preventDefault: boolean}[]}
+ */
+export function provideKeyBindings(editor) {
+    const shortcuts= provide(editor);
+    const keyBindings = [];
+
+    for (const [shortcut, action] of Object.entries(shortcuts)) {
+        keyBindings.push({key: shortcut, run: action, preventDefault: true});
+    }
+
+    return keyBindings;
 }
\ No newline at end of file
Morty Proxy This is a proxified and sanitized view of the page, visit original site.