]> BookStack Code Mirror - bookstack/blobdiff - resources/js/components/markdown-editor.js
Attachments: Hid edit/delete controls where lacking permission
[bookstack] / resources / js / components / markdown-editor.js
index 373fedf487db79c5d3eb715304efb8f95f2d39d4..ad5bcf09030184532a337d37de258f943ee333d1 100644 (file)
@@ -1,6 +1,4 @@
-import {debounce} from "../services/util";
-import {Component} from "./component";
-import {init as initEditor} from "../markdown/editor";
+import {Component} from './component';
 
 export class MarkdownEditor extends Component {
 
@@ -14,20 +12,26 @@ export class MarkdownEditor extends Component {
 
         this.display = this.$refs.display;
         this.input = this.$refs.input;
-        this.settingContainer = this.$refs.settingContainer;
+        this.divider = this.$refs.divider;
+        this.displayWrap = this.$refs.displayWrap;
+
+        const {settingContainer} = this.$refs;
+        const settingInputs = settingContainer.querySelectorAll('input[type="checkbox"]');
 
         this.editor = null;
-        initEditor({
-            pageId: this.pageId,
-            container: this.elem,
-            displayEl: this.display,
-            inputEl: this.input,
-            drawioUrl: this.getDrawioUrl(),
-            text: {
-                serverUploadLimit: this.serverUploadLimitText,
-                imageUploadError: this.imageUploadErrorText,
-            },
-            settings: this.loadSettings(),
+        window.importVersioned('markdown').then(markdown => {
+            return markdown.init({
+                pageId: this.pageId,
+                container: this.elem,
+                displayEl: this.display,
+                inputEl: this.input,
+                drawioUrl: this.getDrawioUrl(),
+                settingInputs: Array.from(settingInputs),
+                text: {
+                    serverUploadLimit: this.serverUploadLimitText,
+                    imageUploadError: this.imageUploadErrorText,
+                },
+            });
         }).then(editor => {
             this.editor = editor;
             this.setupListeners();
@@ -41,19 +45,18 @@ export class MarkdownEditor extends Component {
         window.$events.emitPublic(this.elem, 'editor-markdown::setup', {
             markdownIt: this.editor.markdown.getRenderer(),
             displayEl: this.display,
-            codeMirrorInstance: this.editor.cm,
+            cmEditorView: this.editor.cm,
         });
     }
 
     setupListeners() {
-
         // Button actions
         this.elem.addEventListener('click', event => {
-            let button = event.target.closest('button[data-action]');
+            const button = event.target.closest('button[data-action]');
             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();
@@ -76,30 +79,34 @@ export class MarkdownEditor extends Component {
             toolbarLabel.closest('.markdown-editor-wrap').classList.add('active');
         });
 
-        // Setting changes
-        this.settingContainer.addEventListener('change', e => {
-            const actualInput = e.target.parentNode.querySelector('input[type="hidden"]');
-            const name = actualInput.getAttribute('name');
-            const value = actualInput.getAttribute('value');
-            window.$http.patch('/preferences/update-boolean', {name, value});
-            this.editor.settings.set(name, value === 'true');
-        });
-
-        // Refresh CodeMirror on container resize
-        const resizeDebounced = debounce(() => this.editor.cm.refresh(), 100, false);
-        const observer = new ResizeObserver(resizeDebounced);
-        observer.observe(this.elem);
+        this.handleDividerDrag();
     }
 
-    loadSettings() {
-        const settings = {};
-        const inputs = this.settingContainer.querySelectorAll('input[type="hidden"]');
-
-        for (const input of inputs) {
-            settings[input.getAttribute('name')] = input.value === 'true';
+    handleDividerDrag() {
+        this.divider.addEventListener('pointerdown', () => {
+            const wrapRect = this.elem.getBoundingClientRect();
+            const moveListener = event => {
+                const xRel = event.pageX - wrapRect.left;
+                const xPct = Math.min(Math.max(20, Math.floor((xRel / wrapRect.width) * 100)), 80);
+                this.displayWrap.style.flexBasis = `${100 - xPct}%`;
+                this.editor.settings.set('editorWidth', xPct);
+            };
+            const upListener = () => {
+                window.removeEventListener('pointermove', moveListener);
+                window.removeEventListener('pointerup', upListener);
+                this.display.style.pointerEvents = null;
+                document.body.style.userSelect = null;
+            };
+
+            this.display.style.pointerEvents = 'none';
+            document.body.style.userSelect = 'none';
+            window.addEventListener('pointermove', moveListener);
+            window.addEventListener('pointerup', upListener);
+        });
+        const widthSetting = this.editor.settings.get('editorWidth');
+        if (widthSetting) {
+            this.displayWrap.style.flexBasis = `${100 - widthSetting}%`;
         }
-
-        return settings;
     }
 
     scrollToTextIfNeeded() {
@@ -123,4 +130,13 @@ export class MarkdownEditor extends Component {
         return drawioAttrEl.getAttribute('drawio-url') || '';
     }
 
+    /**
+     * Get the content of this editor.
+     * Used by the parent page editor component.
+     * @return {Promise<{html: String, markdown: String}>}
+     */
+    async getContent() {
+        return this.editor.actions.getContent();
+    }
+
 }