]> BookStack Code Mirror - bookstack/blob - resources/js/editor/menu/icons.js
Started work on details/summary blocks
[bookstack] / resources / js / editor / menu / icons.js
1 /**
2  * This file originates from https://github.com/ProseMirror/prosemirror-menu
3  * and is hence subject to the MIT license found here:
4  * https://github.com/ProseMirror/prosemirror-menu/blob/master/LICENSE
5  * @copyright Marijn Haverbeke and others
6  */
7
8 // :: Object
9 // A set of basic editor-related icons. Contains the properties
10 // `join`, `lift`, `selectParentNode`, `undo`, `redo`, `strong`, `em`,
11 // `code`, `link`, `bulletList`, `orderedList`, and `blockquote`, each
12 // holding an object that can be used as the `icon` option to
13 // `MenuItem`.
14 export const icons = {
15   undo: {
16     width: 24, height: 24,
17     path: "M12.5 8c-2.65 0-5.05.99-6.9 2.6L2 7v9h9l-3.62-3.62c1.39-1.16 3.16-1.88 5.12-1.88 3.54 0 6.55 2.31 7.6 5.5l2.37-.78C21.08 11.03 17.15 8 12.5 8z"
18   },
19   redo: {
20     width: 24, height: 24,
21     path: "M18.4 10.6C16.55 8.99 14.15 8 11.5 8c-4.65 0-8.58 3.03-9.96 7.22L3.9 16c1.05-3.19 4.05-5.5 7.6-5.5 1.95 0 3.73.72 5.12 1.88L13 16h9V7l-3.6 3.6z"
22   },
23   strong: {
24     width: 24, height: 24,
25     path: "M15.6 10.79c.97-.67 1.65-1.77 1.65-2.79 0-2.26-1.75-4-4-4H7v14h7.04c2.09 0 3.71-1.7 3.71-3.79 0-1.52-.86-2.82-2.15-3.42zM10 6.5h3c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5h-3v-3zm3.5 9H10v-3h3.5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5z"
26   },
27   em: {
28     width: 24, height: 24,
29     path: "M10 4v3h2.21l-3.42 8H6v3h8v-3h-2.21l3.42-8H18V4z"
30   },
31   link: {
32     width: 24, height: 24,
33     path: "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"
34   },
35   bullet_list: {
36     width: 24, height: 24,
37     path: "M4 10.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0-6c-.83 0-1.5.67-1.5 1.5S3.17 7.5 4 7.5 5.5 6.83 5.5 6 4.83 4.5 4 4.5zm0 12c-.83 0-1.5.68-1.5 1.5s.68 1.5 1.5 1.5 1.5-.68 1.5-1.5-.67-1.5-1.5-1.5zM7 19h14v-2H7v2zm0-6h14v-2H7v2zm0-8v2h14V5H7z"
38   },
39   ordered_list: {
40     width: 24, height: 24,
41     path: "M2 17h2v.5H3v1h1v.5H2v1h3v-4H2v1zm1-9h1V4H2v1h1v3zm-1 3h1.8L2 13.1v.9h3v-1H3.2L5 10.9V10H2v1zm5-6v2h14V5H7zm0 14h14v-2H7v2zm0-6h14v-2H7v2z"
42   },
43   task_list: {
44     width: 24, height: 24,
45     path: "M22,7h-9v2h9V7z M22,15h-9v2h9V15z M5.54,11L2,7.46l1.41-1.41l2.12,2.12l4.24-4.24l1.41,1.41L5.54,11z M5.54,19L2,15.46 l1.41-1.41l2.12,2.12l4.24-4.24l1.41,1.41L5.54,19z"
46   },
47   underline: {
48     width: 24, height: 24,
49     path: "M12 17c3.31 0 6-2.69 6-6V3h-2.5v8c0 1.93-1.57 3.5-3.5 3.5S8.5 12.93 8.5 11V3H6v8c0 3.31 2.69 6 6 6zm-7 2v2h14v-2H5z"
50   },
51   strike: {
52     width: 24, height: 24,
53     path: "M10 19h4v-3h-4v3zM5 4v3h5v3h4V7h5V4H5zM3 14h18v-2H3v2z"
54   },
55   superscript: {
56     width: 24, height: 24,
57     path: "M22,7h-2v1h3v1h-4V7c0-0.55,0.45-1,1-1h2V5h-3V4h3c0.55,0,1,0.45,1,1v1C23,6.55,22.55,7,22,7z M5.88,20h2.66l3.4-5.42h0.12 l3.4,5.42h2.66l-4.65-7.27L17.81,6h-2.68l-3.07,4.99h-0.12L8.85,6H6.19l4.32,6.73L5.88,20z"
58   },
59   subscript: {
60     width: 24, height: 24,
61     path: "M22,18h-2v1h3v1h-4v-2c0-0.55,0.45-1,1-1h2v-1h-3v-1h3c0.55,0,1,0.45,1,1v1C23,17.55,22.55,18,22,18z M5.88,18h2.66 l3.4-5.42h0.12l3.4,5.42h2.66l-4.65-7.27L17.81,4h-2.68l-3.07,4.99h-0.12L8.85,4H6.19l4.32,6.73L5.88,18z"
62   },
63   text_color: {
64     width: 24, height: 24,
65     path: "M2,20h20v4H2V20z M5.49,17h2.42l1.27-3.58h5.65L16.09,17h2.42L13.25,3h-2.5L5.49,17z M9.91,11.39l2.03-5.79h0.12l2.03,5.79 H9.91z"
66   },
67   background_color: {
68     width: 24, height: 24,
69     path: "M16.56,8.94L7.62,0L6.21,1.41l2.38,2.38L3.44,8.94c-0.59,0.59-0.59,1.54,0,2.12l5.5,5.5C9.23,16.85,9.62,17,10,17 s0.77-0.15,1.06-0.44l5.5-5.5C17.15,10.48,17.15,9.53,16.56,8.94z M5.21,10L10,5.21L14.79,10H5.21z M19,11.5c0,0-2,2.17-2,3.5 c0,1.1,0.9,2,2,2s2-0.9,2-2C21,13.67,19,11.5,19,11.5z M2,20h20v4H2V20z"
70   },
71   align_left: {
72     width: 24, height: 24,
73     path: "M15 15H3v2h12v-2zm0-8H3v2h12V7zM3 13h18v-2H3v2zm0 8h18v-2H3v2zM3 3v2h18V3H3z"
74   },
75   align_right: {
76     width: 24, height: 24,
77     path: "M3 21h18v-2H3v2zm6-4h12v-2H9v2zm-6-4h18v-2H3v2zm6-4h12V7H9v2zM3 3v2h18V3H3z"
78   },
79   align_center: {
80     width: 24, height: 24,
81     path: "M7 15v2h10v-2H7zm-4 6h18v-2H3v2zm0-8h18v-2H3v2zm4-6v2h10V7H7zM3 3v2h18V3H3z"
82   },
83   align_justify: {
84     width: 24, height: 24,
85     path: "M3 21h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18V7H3v2zm0-6v2h18V3H3z"
86   },
87   horizontal_rule: {
88     width: 24, height: 24,
89     path: "m 4,11 h 16 v 2 H 4 Z"
90   },
91   format_clear: {
92     width: 24, height: 24,
93     path: "M3.27 5L2 6.27l6.97 6.97L6.5 19h3l1.57-3.66L16.73 21 18 19.73 3.55 5.27 3.27 5zM6 5v.18L8.82 8h2.4l-.72 1.68 2.1 2.1L14.21 8H20V5H6z"
94   },
95   close: {
96     width: 24, height: 24,
97     path: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z",
98   },
99   source_code: {
100     width: 24, height: 24,
101     path: "M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z",
102   },
103   table: {
104     width: 24, height: 24,
105     path: "M20 2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM8 20H4v-4h4v4zm0-6H4v-4h4v4zm0-6H4V4h4v4zm6 12h-4v-4h4v4zm0-6h-4v-4h4v4zm0-6h-4V4h4v4zm6 12h-4v-4h4v4zm0-6h-4v-4h4v4zm0-6h-4V4h4v4z",
106   },
107   iframe: {
108     width: 24, height: 24,
109     path: "m 22.71,18.43 c 0.03,-0.29 0.04,-0.58 0.01,-0.86 l 1.07,-0.85 c 0.1,-0.08 0.12,-0.21 0.06,-0.32 L 22.82,14.61 C 22.76,14.5 22.63,14.46 22.51,14.5 L 21.23,15 C 21,14.83 20.75,14.69 20.48,14.58 l -0.2,-1.36 C 20.26,13.09 20.16,13 20.03,13 h -2.07 c -0.12,0 -0.23,0.09 -0.25,0.21 l -0.2,1.36 c -0.26,0.11 -0.51,0.26 -0.74,0.42 l -1.28,-0.5 c -0.12,-0.05 -0.25,0 -0.31,0.11 l -1.03,1.79 c -0.06,0.11 -0.04,0.24 0.06,0.32 l 1.07,0.86 c -0.03,0.29 -0.04,0.58 -0.01,0.86 l -1.07,0.85 c -0.1,0.08 -0.12,0.21 -0.06,0.32 l 1.03,1.79 c 0.06,0.11 0.19,0.15 0.31,0.11 L 16.75,21 c 0.23,0.17 0.48,0.31 0.75,0.42 l 0.2,1.36 c 0.02,0.12 0.12,0.21 0.25,0.21 h 2.07 c 0.12,0 0.23,-0.09 0.25,-0.21 l 0.2,-1.36 c 0.26,-0.11 0.51,-0.26 0.74,-0.42 l 1.28,0.5 c 0.12,0.05 0.25,0 0.31,-0.11 l 1.03,-1.79 c 0.06,-0.11 0.04,-0.24 -0.06,-0.32 z M 19,19.5 c -0.83,0 -1.5,-0.67 -1.5,-1.5 0,-0.83 0.67,-1.5 1.5,-1.5 0.83,0 1.5,0.67 1.5,1.5 0,0.83 -0.67,1.5 -1.5,1.5 z M 15,12 9,8 v 8 z M 3,6 h 18 v 5 h 2 V 6 C 23,4.9 22.1,4 21,4 H 3 C 1.9,4 1,4.9 1,6 v 12 c 0,1.1 0.9,2 2,2 h 9 V 18 H 3 Z",
110   },
111   details: {
112     width: 24, height: 24,
113     path: "m 7,10 5,5 5,-5 z M 19,2.5 H 5 c -1.11,0 -2,0.9 -2,2 v 14 c 0,1.1 0.89,2 2,2 h 14 c 1.1,0 2,-0.9 2,-2 v -14 c 0,-1.1 -0.89,-2 -2,-2 z m 0,16 H 5 v -12 h 14 z",
114   }
115 };
116
117 const SVG = "http://www.w3.org/2000/svg"
118 const XLINK = "http://www.w3.org/1999/xlink"
119
120 const prefix = "ProseMirror-icon"
121
122 function hashPath(path) {
123   let hash = 0
124   for (let i = 0; i < path.length; i++)
125     hash = (((hash << 5) - hash) + path.charCodeAt(i)) | 0
126   return hash
127 }
128
129 export function getIcon(icon) {
130   let node = document.createElement("div")
131   node.className = prefix
132   if (icon.path) {
133     let name = "pm-icon-" + hashPath(icon.path).toString(16)
134     if (!document.getElementById(name)) buildSVG(name, icon)
135     let svg = node.appendChild(document.createElementNS(SVG, "svg"))
136     svg.style.width = (icon.width / icon.height) + "em"
137     let use = svg.appendChild(document.createElementNS(SVG, "use"))
138     use.setAttributeNS(XLINK, "href", /([^#]*)/.exec(document.location)[1] + "#" + name)
139   } else if (icon.dom) {
140     node.appendChild(icon.dom.cloneNode(true))
141   } else {
142     node.appendChild(document.createElement("span")).textContent = icon.text || ''
143     if (icon.css) node.firstChild.style.cssText = icon.css
144   }
145   return node
146 }
147
148 function buildSVG(name, data) {
149   let collection = document.getElementById(prefix + "-collection")
150   if (!collection) {
151     collection = document.createElementNS(SVG, "svg")
152     collection.id = prefix + "-collection"
153     collection.style.display = "none"
154     document.body.insertBefore(collection, document.body.firstChild)
155   }
156   let sym = document.createElementNS(SVG, "symbol")
157   sym.id = name
158   sym.setAttribute("viewBox", "0 0 " + data.width + " " + data.height)
159   let path = sym.appendChild(document.createElementNS(SVG, "path"))
160   path.setAttribute("d", data.path)
161   collection.appendChild(sym)
162 }