]> BookStack Code Mirror - bookstack/commitdiff
Shared link mark update logic with color controls
authorDan Brown <redacted>
Wed, 19 Jan 2022 23:54:59 +0000 (23:54 +0000)
committerDan Brown <redacted>
Wed, 19 Jan 2022 23:54:59 +0000 (23:54 +0000)
resources/js/editor/menu/ColorPickerGrid.js
resources/js/editor/menu/item-anchor-button.js
resources/js/editor/util.js

index c5eacc3354605a06386b15846a1b6e91c2004624..306c65c5688a7676f40a2129f9585bec948f7c4b 100644 (file)
@@ -1,6 +1,8 @@
 import crel from "crelt"
 import {prefix} from "./menu-utils";
-import {toggleMark} from "prosemirror-commands";
+import {TextSelection} from "prosemirror-state"
+import {expandSelectionToMark} from "../util";
+
 
 class ColorPickerGrid {
 
@@ -24,8 +26,7 @@ class ColorPickerGrid {
         wrap.addEventListener('click', event => {
             if (event.target.classList.contains(prefix + "-color-grid-item")) {
                 const color = event.target.style.backgroundColor;
-                const attrs = {[this.attrName]: color};
-                toggleMark(this.markType, attrs)(view.state, view.dispatch, view, event);
+                this.onColorSelect(view, color);
             }
         });
 
@@ -35,6 +36,27 @@ class ColorPickerGrid {
 
         return {dom: wrap, update}
     }
+
+    onColorSelect(view, color) {
+        const attrs = {[this.attrName]: color};
+        const selection = view.state.selection;
+        const {from, to} = expandSelectionToMark(view.state, selection, this.markType);
+        const tr = view.state.tr;
+
+        const currentColorMarks = selection.$from.marksAcross(selection.$to) || [];
+        const activeRelevantMark = currentColorMarks.filter(mark => {
+            return mark.type === this.markType;
+        })[0];
+        const colorIsActive = activeRelevantMark && activeRelevantMark.attrs[this.attrName] === color;
+
+        tr.removeMark(from, to, this.markType);
+        if (!colorIsActive) {
+            tr.addMark(from, to, this.markType.create(attrs));
+        }
+
+        tr.setSelection(TextSelection.create(tr.doc, from, to));
+        view.dispatch(tr);
+    }
 }
 
 export default ColorPickerGrid;
\ No newline at end of file
index 405d3ab4d610b2fc9eb6239ecfe8ff9241900fae..0fa819c195c32b4860fb27512e78d7badb67e47a 100644 (file)
@@ -6,7 +6,7 @@ import schema from "../schema";
 
 import {MenuItem} from "./menu";
 import {icons} from "./icons";
-import {markRangeAtPosition, nullifyEmptyValues} from "../util";
+import {expandSelectionToMark, nullifyEmptyValues} from "../util";
 
 /**
  * @param {PmMarkType} markType
@@ -74,17 +74,7 @@ function applyLink(formData, state, dispatch) {
     if (!dispatch) return true;
 
     const tr = state.tr;
-    const noRange = (selection.from - selection.to === 0);
-    let from = selection.from;
-    let to = selection.to;
-
-    if (noRange) {
-        const linkRange = markRangeAtPosition(state, schema.marks.link, selection.from);
-        if (linkRange.from !== -1) {
-            from = linkRange.from;
-            to = linkRange.to;
-        }
-    }
+    const {from, to} = expandSelectionToMark(state, selection, schema.marks.link);
 
     if (attrs.href) {
         tr.addMark(from, to, schema.marks.link.create(attrs));
index e1746a72517c0c599a3fcc338ac1c54436e068ee..ad077b923cb62a84e1e9a5512a1027b85d51d761 100644 (file)
@@ -45,6 +45,25 @@ export function nullifyEmptyValues(object) {
     return clean;
 }
 
+/**
+ * @param {PmEditorState} state
+ * @param {PmSelection} selection
+ * @param {PmMarkType} markType
+ * @return {{from: Number, to: Number}}
+ */
+export function expandSelectionToMark(state, selection, markType) {
+    let {from, to} = selection;
+    const noRange = (from === to);
+    if (noRange) {
+        const markRange = markRangeAtPosition(state, markType, from);
+        if (markRange.from !== -1) {
+            from = markRange.from;
+            to = markRange.to;
+        }
+    }
+    return {from, to};
+}
+
 /**
  * @param {PmEditorState} state
  * @param {PmMarkType} markType
@@ -54,7 +73,7 @@ export function nullifyEmptyValues(object) {
 export function markRangeAtPosition(state, markType, pos) {
     const $pos = state.doc.resolve(pos);
 
-    const { parent, parentOffset } = $pos;
+    const {parent, parentOffset} = $pos;
     const start = parent.childAfter(parentOffset);
     if (!start.node) return {from: -1, to: -1};
 
@@ -73,7 +92,7 @@ export function markRangeAtPosition(state, markType, pos) {
         endPos += parent.child(endIndex).nodeSize;
         endIndex += 1;
     }
-    return { from: startPos, to: endPos };
+    return {from: startPos, to: endPos};
 }
 
 /**