From: Dan Brown Date: Tue, 11 Jan 2022 18:58:24 +0000 (+0000) Subject: Got alignment buttons barely working for paragraphs X-Git-Url: http://source.bookstackapp.com/bookstack/commitdiff_plain/6744ab2ff906db2aaff1ef583edf885845106b4c Got alignment buttons barely working for paragraphs --- diff --git a/resources/js/editor/commands.js b/resources/js/editor/commands.js new file mode 100644 index 000000000..d77e75026 --- /dev/null +++ b/resources/js/editor/commands.js @@ -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 diff --git a/resources/js/editor/menu/index.js b/resources/js/editor/menu/index.js index 9fad417ba..f29108849 100644 --- a/resources/js/editor/menu/index.js +++ b/resources/js/editor/menu/index.js @@ -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, ], }); diff --git a/resources/js/editor/menu/menu.js b/resources/js/editor/menu/menu.js index ceba90fa9..8386de5dc 100644 --- a/resources/js/editor/menu/menu.js +++ b/resources/js/editor/menu/menu.js @@ -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) diff --git a/resources/js/editor/schema-nodes.js b/resources/js/editor/schema-nodes.js index aa125cebd..bc5c4c9d3 100644 --- a/resources/js/editor/schema-nodes.js +++ b/resources/js/editor/schema-nodes.js @@ -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", diff --git a/resources/views/editor-test.blade.php b/resources/views/editor-test.blade.php index aa79e7907..5d1dc7429 100644 --- a/resources/views/editor-test.blade.php +++ b/resources/views/editor-test.blade.php @@ -7,7 +7,7 @@ -
+