]> BookStack Code Mirror - bookstack/blob - resources/js/editor/menu/index.js
591878f7c6939b780763e1bf06ea47311de527cf
[bookstack] / resources / js / editor / menu / index.js
1 import {
2     MenuItem, Dropdown, DropdownSubmenu, renderGrouped, icons, joinUpItem, liftItem, selectParentNodeItem,
3     undoItem, redoItem, wrapItem, blockTypeItem
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 ];
60
61 const formats = [
62     blockTypeItem(schema.nodes.heading, {
63         label: "Header Large",
64         attrs: {level: 2}
65     }),
66     blockTypeItem(schema.nodes.heading, {
67         label: "Header Medium",
68         attrs: {level: 3}
69     }),
70     blockTypeItem(schema.nodes.heading, {
71         label: "Header Small",
72         attrs: {level: 4}
73     }),
74     blockTypeItem(schema.nodes.heading, {
75         label: "Header Tiny",
76         attrs: {level: 5}
77     }),
78     blockTypeItem(schema.nodes.paragraph, {
79         label: "Paragraph",
80         attrs: {}
81     }),
82     new DropdownSubmenu([
83         blockTypeItem(schema.nodes.callout, {
84             label: "Info Callout",
85             attrs: {type: 'info'}
86         }),
87         blockTypeItem(schema.nodes.callout, {
88             label: "Danger Callout",
89             attrs: {type: 'danger'}
90         }),
91         blockTypeItem(schema.nodes.callout, {
92             label: "Success Callout",
93             attrs: {type: 'success'}
94         }),
95         blockTypeItem(schema.nodes.callout, {
96             label: "Warning Callout",
97             attrs: {type: 'warning'}
98         })
99     ], { label: 'Callouts' }),
100 ];
101
102 const menu = menuBar({
103     floating: false,
104     content: [
105         [undoItem, redoItem],
106         [new DropdownSubmenu(formats, { label: 'Formats' })],
107         inlineStyles,
108     ],
109 });
110
111 export default menu;
112
113 // !! This module defines a number of building blocks for ProseMirror
114 // menus, along with a [menu bar](#menu.menuBar) implementation.
115
116 // MenuElement:: interface
117 // The types defined in this module aren't the only thing you can
118 // display in your menu. Anything that conforms to this interface can
119 // be put into a menu structure.
120 //
121 //   render:: (pm: EditorView) → {dom: dom.Node, update: (EditorState) → bool}
122 //   Render the element for display in the menu. Must return a DOM
123 //   element and a function that can be used to update the element to
124 //   a new state. The `update` function will return false if the
125 //   update hid the entire element.