]> BookStack Code Mirror - bookstack/commitdiff
Added bg-color mark, added color grid selectors
authorDan Brown <redacted>
Wed, 12 Jan 2022 15:33:59 +0000 (15:33 +0000)
committerDan Brown <redacted>
Wed, 12 Jan 2022 15:33:59 +0000 (15:33 +0000)
resources/js/editor/markdown-serializer.js
resources/js/editor/menu/ColorPickerGrid.js [new file with mode: 0644]
resources/js/editor/menu/index.js
resources/js/editor/menu/menu.js
resources/js/editor/schema-marks.js
resources/sass/_editor.scss

index c194ceaf7874c6552741fbaae1f7c87bb02702aa..5e1dfb33bdfa5672633d788c761a6f2d548f1c08 100644 (file)
@@ -30,6 +30,20 @@ marks.subscript = {
     close: '</sub>',
 };
 
+marks.text_color = {
+    open(state, mark, parent, index) {
+        return `<span style="color: ${mark.attrs.color};">`
+    },
+    close: '</span>',
+};
+
+marks.background_color = {
+    open(state, mark, parent, index) {
+        return `<span style="background-color: ${mark.attrs.color};">`
+    },
+    close: '</span>',
+};
+
 
 function writeNodeAsHtml(state, node) {
     const html = docToHtml({ content: [node] });
@@ -43,11 +57,11 @@ function writeNodeAsHtml(state, node) {
 // or element that cannot be represented in commonmark without losing
 // formatting or content.
 for (const [nodeType, serializerFunction] of Object.entries(nodes)) {
-    nodes[nodeType] = function(state, node) {
+    nodes[nodeType] = function(state, node, parent, index) {
         if (node.attrs.align) {
             writeNodeAsHtml(state, node);
         } else {
-            serializerFunction(state, node);
+            serializerFunction(state, node, parent, index);
         }
     }
 }
diff --git a/resources/js/editor/menu/ColorPickerGrid.js b/resources/js/editor/menu/ColorPickerGrid.js
new file mode 100644 (file)
index 0000000..91ea733
--- /dev/null
@@ -0,0 +1,40 @@
+import crel from "crelt"
+const prefix = "ProseMirror-menu"
+import {toggleMark} from "prosemirror-commands";
+
+class ColorPickerGrid {
+
+    constructor(markType, attrName, colors) {
+        this.markType = markType;
+        this.colors = colors
+        this.attrName = attrName;
+    }
+
+    // :: (EditorView) → {dom: dom.Node, update: (EditorState) → bool}
+    // Renders the submenu.
+    render(view) {
+
+        const colorElems = [];
+        for (const color of this.colors) {
+            const elem = crel("div", {class: prefix + "-color-grid-item", style: `background-color: ${color};`});
+            colorElems.push(elem);
+        }
+
+        const wrap = crel("div", {class: prefix + "-color-grid-container"}, colorElems);
+        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);
+            }
+        });
+
+        function update(state) {
+            return true;
+        }
+
+        return {dom: wrap, update}
+    }
+}
+
+export default ColorPickerGrid;
\ No newline at end of file
index ed6a1c25b875acab87e86b3a61b3bbdc17474d70..72d034b2ac4a393e85c7c527d9695d35b001fc7c 100644 (file)
@@ -2,6 +2,7 @@ import {
     MenuItem, Dropdown, DropdownSubmenu, renderGrouped, icons, joinUpItem, liftItem, selectParentNodeItem,
     undoItem, redoItem, wrapItem, blockTypeItem, setAttrItem,
 } from "./menu"
+import ColorPickerGrid from "./ColorPickerGrid";
 
 import {toggleMark} from "prosemirror-commands";
 import {menuBar} from "./menubar"
@@ -117,9 +118,15 @@ const alignments = [
     }),
 ];
 
+const colorOptions = ["#000000","#993300","#333300","#003300","#003366","#000080","#333399","#333333","#800000","#FF6600","#808000","#008000","#008080","#0000FF","#666699","#808080","#FF0000","#FF9900","#99CC00","#339966","#33CCCC","#3366FF","#800080","#999999","#FF00FF","#FFCC00","#FFFF00","#00FF00","#00FFFF","#00CCFF","#993366","#FFFFFF","#FF99CC","#FFCC99","#FFFF99","#CCFFCC","#CCFFFF","#99CCFF","#CC99FF"];
+
 const colors = [
-    markItem(schema.marks.text_color, {title: "Green", label: "Green", attrs: {color: '#00FF00'}}),
-    markItem(schema.marks.text_color, {title: "Blue", label: "Blue", attrs: {color: '#0000FF'}}),
+    new DropdownSubmenu([
+        new ColorPickerGrid(schema.marks.text_color, 'color', colorOptions),
+    ], {label: 'Text Color'}),
+    new DropdownSubmenu([
+        new ColorPickerGrid(schema.marks.background_color, 'color', colorOptions),
+    ], {label: 'Background Color'}),
 ];
 
 const menu = menuBar({
@@ -127,8 +134,8 @@ const menu = menuBar({
     content: [
         [undoItem, redoItem],
         [new DropdownSubmenu(formats, { label: 'Formats' })],
-        colors,
         inlineStyles,
+        colors,
         alignments,
     ],
 });
index 8386de5dc9ff090d9308f9c00d90f075b46670a8..a922f4540a6ce3d8e639e2bb1ae546f201fd2cc1 100644 (file)
@@ -6,7 +6,7 @@
  */
 
 import crel from "crelt"
-import {lift, joinUp, selectParentNode, wrapIn, setBlockType} from "prosemirror-commands"
+import {lift, joinUp, selectParentNode, wrapIn, setBlockType, toggleMark} from "prosemirror-commands"
 import {undo, redo} from "prosemirror-history"
 import {setBlockAttr} from "../commands";
 
@@ -321,6 +321,8 @@ function separator() {
   return crel("span", {class: prefix + "separator"})
 }
 
+
+
 // :: Object
 // A set of basic editor-related icons. Contains the properties
 // `join`, `lift`, `selectParentNode`, `undo`, `redo`, `strong`, `em`,
index 175d8bda89322a851ba0a193b32c9ee9b7772518..52335fac6da320feb2f737fe7c2beb0b26ed090a 100644 (file)
@@ -45,12 +45,28 @@ const text_color = {
     }
 };
 
+const background_color = {
+    attrs: {
+        color: {},
+    },
+    parseDOM: [{
+        style: 'background-color',
+        getAttrs(color) {
+            return {color}
+        }
+    }],
+    toDOM(node) {
+        return ['span', {style: `background-color: ${node.attrs.color};`}, 0];
+    }
+};
+
 const marks = baseMarks.append({
     underline,
     strike,
     superscript,
     subscript,
     text_color,
+    background_color,
 });
 
 export default marks;
\ No newline at end of file
index d24dfaec59150b242d4d6a82f6447d3bbb13a663..1a3ee165d20a1ec3bbf17ab59474a4263aaade9c 100644 (file)
@@ -365,4 +365,16 @@ img.ProseMirror-separator {
   outline: none;
 }
 
-.ProseMirror p { margin-bottom: 1em }
\ No newline at end of file
+.ProseMirror p { margin-bottom: 1em }
+
+.ProseMirror-menu-color-grid-container {
+  display: grid;
+  grid-template-columns: repeat(8, 1fr);
+}
+
+.ProseMirror-menu-color-grid-item {
+  width: 20px;
+  height: 20px;
+  border: 2px solid #FFF;
+  display: block;
+}
\ No newline at end of file