--- /dev/null
+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
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";
], { 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,
],
});
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"
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)
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+",
};
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];
}
};
group: "block",
defining: true,
parseDOM: [{tag: "blockquote"}],
+ align: {
+ default: null,
+ },
toDOM() {
return ["blockquote", 0];
}
};
const heading = {
- attrs: {level: {default: 1}},
+ attrs: {level: {default: 1}, align: {default: null}},
content: "inline*",
group: "block",
defining: true,
const callout = {
attrs: {
type: {default: 'info'},
+ align: {default: null},
},
content: "inline*",
group: "block",
<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>