]> BookStack Code Mirror - bookstack/blob - resources/js/editor/menu/index.js
Got alignment buttons barely working for paragraphs
[bookstack] / resources / js / editor / menu / index.js
1 import {
2     MenuItem, Dropdown, DropdownSubmenu, renderGrouped, icons, joinUpItem, liftItem, selectParentNodeItem,
3     undoItem, redoItem, wrapItem, blockTypeItem, setAttrItem,
4 } from "./menu"
5
6 import {toggleMark} from "prosemirror-commands";
7 import {menuBar} from "./menubar"
8 import schema from "../schema";
9
10
11 function cmdItem(cmd, options) {
12     const passedOptions = {
13         label: options.title,
14         run: cmd
15     };
16     for (const prop in options) {
17         passedOptions[prop] = options[prop];
18     }
19     if ((!options.enable || options.enable === true) && !options.select) {
20         passedOptions[options.enable ? "enable" : "select"] = function (state) {
21             return cmd(state);
22         };
23     }
24
25     return new MenuItem(passedOptions)
26 }
27
28 function markActive(state, type) {
29     const ref = state.selection;
30     const from = ref.from;
31     const $from = ref.$from;
32     const to = ref.to;
33     const empty = ref.empty;
34     if (empty) {
35         return type.isInSet(state.storedMarks || $from.marks())
36     } else {
37         return state.doc.rangeHasMark(from, to, type)
38     }
39 }
40
41 function markItem(markType, options) {
42     const passedOptions = {
43         active: function active(state) {
44             return markActive(state, markType)
45         },
46         enable: true
47     };
48     for (const prop in options) {
49         passedOptions[prop] = options[prop];
50     }
51
52     return cmdItem(toggleMark(markType), passedOptions)
53 }
54
55 const inlineStyles = [
56     markItem(schema.marks.strong, {title: "Bold", icon: icons.strong}),
57     markItem(schema.marks.em, {title: "Italic", icon: icons.em}),
58     markItem(schema.marks.underline, {title: "Underline", label: 'U'}),
59     markItem(schema.marks.strike, {title: "Strikethrough", label: '-S-'}),
60     markItem(schema.marks.superscript, {title: "Superscript", label: 'sup'}),
61     markItem(schema.marks.subscript, {title: "Subscript", label: 'sub'}),
62 ];
63
64 const formats = [
65     blockTypeItem(schema.nodes.heading, {
66         label: "Header Large",
67         attrs: {level: 2}
68     }),
69     blockTypeItem(schema.nodes.heading, {
70         label: "Header Medium",
71         attrs: {level: 3}
72     }),
73     blockTypeItem(schema.nodes.heading, {
74         label: "Header Small",
75         attrs: {level: 4}
76     }),
77     blockTypeItem(schema.nodes.heading, {
78         label: "Header Tiny",
79         attrs: {level: 5}
80     }),
81     blockTypeItem(schema.nodes.paragraph, {
82         label: "Paragraph",
83         attrs: {}
84     }),
85     new DropdownSubmenu([
86         blockTypeItem(schema.nodes.callout, {
87             label: "Info Callout",
88             attrs: {type: 'info'}
89         }),
90         blockTypeItem(schema.nodes.callout, {
91             label: "Danger Callout",
92             attrs: {type: 'danger'}
93         }),
94         blockTypeItem(schema.nodes.callout, {
95             label: "Success Callout",
96             attrs: {type: 'success'}
97         }),
98         blockTypeItem(schema.nodes.callout, {
99             label: "Warning Callout",
100             attrs: {type: 'warning'}
101         })
102     ], { label: 'Callouts' }),
103 ];
104
105 const alignments = [
106     setAttrItem('align', 'left', {
107         label: 'Align Left'
108     }),
109     setAttrItem('align', 'right', {
110         label: 'Align Right'
111     }),
112     setAttrItem('align', 'center', {
113         label: 'Align Center'
114     }),
115     setAttrItem('align', 'justify', {
116         label: 'Align Justify'
117     }),
118 ];
119
120 const menu = menuBar({
121     floating: false,
122     content: [
123         [undoItem, redoItem],
124         [new DropdownSubmenu(formats, { label: 'Formats' })],
125         inlineStyles,
126         alignments,
127     ],
128 });
129
130 export default menu;
131
132 // !! This module defines a number of building blocks for ProseMirror
133 // menus, along with a [menu bar](#menu.menuBar) implementation.
134
135 // MenuElement:: interface
136 // The types defined in this module aren't the only thing you can
137 // display in your menu. Anything that conforms to this interface can
138 // be put into a menu structure.
139 //
140 //   render:: (pm: EditorView) → {dom: dom.Node, update: (EditorState) → bool}
141 //   Render the element for display in the menu. Must return a DOM
142 //   element and a function that can be used to update the element to
143 //   a new state. The `update` function will return false if the
144 //   update hid the entire element.