]> BookStack Code Mirror - bookstack/commitdiff
Got alignment buttons barely working for paragraphs
authorDan Brown <redacted>
Tue, 11 Jan 2022 18:58:24 +0000 (18:58 +0000)
committerDan Brown <redacted>
Tue, 11 Jan 2022 18:58:24 +0000 (18:58 +0000)
resources/js/editor/commands.js [new file with mode: 0644]
resources/js/editor/menu/index.js
resources/js/editor/menu/menu.js
resources/js/editor/schema-nodes.js
resources/views/editor-test.blade.php

diff --git a/resources/js/editor/commands.js b/resources/js/editor/commands.js
new file mode 100644 (file)
index 0000000..d77e750
--- /dev/null
@@ -0,0 +1,38 @@
+export function setBlockAttr(attrName, attrValue) {
+    return function (state, dispatch) {
+        const ref = state.selection;
+        const from = ref.from;
+        const to = ref.to;
+        let applicable = false;
+
+        state.doc.nodesBetween(from, to, function (node, pos) {
+            if (applicable) {
+                return false
+            }
+            if (!node.isTextblock || node.attrs[attrName] === attrValue) {
+                return
+            }
+
+            applicable = node.attrs[attrName] !== undefined;
+        });
+
+        if (!applicable) {
+            return false
+        }
+
+        if (dispatch) {
+            const tr = state.tr;
+            tr.doc.nodesBetween(from, to, function (node, pos) {
+                const nodeAttrs = Object.assign({}, node.attrs);
+                if (node.attrs[attrName] !== undefined) {
+                    nodeAttrs[attrName] = attrValue;
+                    tr.setBlockType(pos, pos+1, node.type, nodeAttrs)
+                }
+            });
+
+            dispatch(tr);
+        }
+
+        return true
+    }
+}
\ No newline at end of file
index 9fad417ba52fed3002f4f8574ff5dc5997cc819d..f29108849582b8cbf51bd9c186cb785930988f3b 100644 (file)
@@ -1,6 +1,6 @@
 import {
     MenuItem, Dropdown, DropdownSubmenu, renderGrouped, icons, joinUpItem, liftItem, selectParentNodeItem,
-    undoItem, redoItem, wrapItem, blockTypeItem
+    undoItem, redoItem, wrapItem, blockTypeItem, setAttrItem,
 } from "./menu"
 
 import {toggleMark} from "prosemirror-commands";
@@ -102,12 +102,28 @@ const formats = [
     ], { label: 'Callouts' }),
 ];
 
+const alignments = [
+    setAttrItem('align', 'left', {
+        label: 'Align Left'
+    }),
+    setAttrItem('align', 'right', {
+        label: 'Align Right'
+    }),
+    setAttrItem('align', 'center', {
+        label: 'Align Center'
+    }),
+    setAttrItem('align', 'justify', {
+        label: 'Align Justify'
+    }),
+];
+
 const menu = menuBar({
     floating: false,
     content: [
         [undoItem, redoItem],
         [new DropdownSubmenu(formats, { label: 'Formats' })],
         inlineStyles,
+        alignments,
     ],
 });
 
index ceba90fa9e91f8c5a4e55aee21f8929755203ab6..8386de5dc9ff090d9308f9c00d90f075b46670a8 100644 (file)
@@ -8,6 +8,7 @@
 import crel from "crelt"
 import {lift, joinUp, selectParentNode, wrapIn, setBlockType} from "prosemirror-commands"
 import {undo, redo} from "prosemirror-history"
+import {setBlockAttr} from "../commands";
 
 import {getIcon} from "./icons"
 
@@ -457,6 +458,21 @@ export function blockTypeItem(nodeType, options) {
   return new MenuItem(passedOptions)
 }
 
+export function setAttrItem(attrName, attrValue, options) {
+  const command = setBlockAttr(attrName, attrValue);
+  const passedOptions = {
+    run: command,
+    enable(state) { return command(state) },
+    active(state) {
+      const {$from, to, node} = state.selection
+      if (node) return node.attrs[attrValue] === attrValue;
+      return to <= $from.end() && $from.parent.attrs[attrValue] === attrValue;
+    }
+  }
+  for (const prop in options) passedOptions[prop] = options[prop]
+  return new MenuItem(passedOptions)
+}
+
 // Work around classList.toggle being broken in IE11
 function setClass(dom, cls, on) {
   if (on) dom.classList.add(cls)
index aa125cebde214f0d6efd1c6791b5a93c0a6e4b61..bc5c4c9d3c5e499697d5f1972d598702a5ce19bc 100644 (file)
@@ -1,5 +1,21 @@
 import {orderedList, bulletList, listItem} from "prosemirror-schema-list";
 
+const alignAttrFromDomNode = node => {
+    if (node.classList.contains('align-right')) {
+        return 'right';
+    }
+    if (node.classList.contains('align-left')) {
+        return 'left';
+    }
+    if (node.classList.contains('align-center')) {
+        return 'center';
+    }
+    if (node.classList.contains('align-justify')) {
+        return 'justify';
+    }
+    return null;
+};
+
 const doc = {
     content: "block+",
 };
@@ -7,9 +23,30 @@ const doc = {
 const paragraph = {
     content: "inline*",
     group: "block",
-    parseDOM: [{tag: "p"}],
-    toDOM() {
-        return ["p", 0];
+    parseDOM: [
+        {
+            tag: "p",
+            getAttrs(node) {
+                return {
+                    align: alignAttrFromDomNode(node),
+                };
+            }
+        }
+    ],
+    attrs: {
+        align: {
+            default: null,
+        }
+    },
+    toDOM(node) {
+        const attrs = {};
+        if (node.attrs.align === 'right') {
+            attrs['class'] = 'align-right';
+        }
+        if (node.attrs.align === 'left') {
+            attrs['class'] = 'align-left';
+        }
+        return ["p", attrs, 0];
     }
 };
 
@@ -18,6 +55,9 @@ const blockquote = {
     group: "block",
     defining: true,
     parseDOM: [{tag: "blockquote"}],
+    align: {
+        default: null,
+    },
     toDOM() {
         return ["blockquote", 0];
     }
@@ -32,7 +72,7 @@ const horizontal_rule = {
 };
 
 const heading = {
-    attrs: {level: {default: 1}},
+    attrs: {level: {default: 1}, align: {default: null}},
     content: "inline*",
     group: "block",
     defining: true,
@@ -103,6 +143,7 @@ const hard_break = {
 const callout = {
     attrs: {
         type: {default: 'info'},
+        align: {default: null},
     },
     content: "inline*",
     group: "block",
index aa79e79074adf14f9c7321a93016c9b31c8cf51a..5d1dc742984e95cb74e8d83d5c0d88e43742f578 100644 (file)
@@ -7,7 +7,7 @@
             <input id="markdown-toggle" type="checkbox">
         </div>
 
-        <div id="editor" class="bs-editor" style="margin-bottom: 23px"></div>
+        <div id="editor" class="bs-editor page-content" style="margin-bottom: 23px"></div>
 
         <div id="content" style="display: none;">
             <h2>This is an editable block</h2>
                 <li>Item B</li>
                 <li>Item C</li>
             </ul>
+
             <p>Lorem ipsum dolor sit amet.</p>
+            <p class="align-right">Lorem ipsum dolor sit amet.</p>
+
             <p class="callout info">
                 This is an info callout test!
             </p>