]> BookStack Code Mirror - bookstack/blob - resources/js/editor/menu/icons.js
fc9edffc1fc521e2e032b01ab96bb6ad235b4820
[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   join: {
16     width: 800, height: 900,
17     path: "M0 75h800v125h-800z M0 825h800v-125h-800z M250 400h100v-100h100v100h100v100h-100v100h-100v-100h-100z"
18   },
19   lift: {
20     width: 1024, height: 1024,
21     path: "M219 310v329q0 7-5 12t-12 5q-8 0-13-5l-164-164q-5-5-5-13t5-13l164-164q5-5 13-5 7 0 12 5t5 12zM1024 749v109q0 7-5 12t-12 5h-987q-7 0-12-5t-5-12v-109q0-7 5-12t12-5h987q7 0 12 5t5 12zM1024 530v109q0 7-5 12t-12 5h-621q-7 0-12-5t-5-12v-109q0-7 5-12t12-5h621q7 0 12 5t5 12zM1024 310v109q0 7-5 12t-12 5h-621q-7 0-12-5t-5-12v-109q0-7 5-12t12-5h621q7 0 12 5t5 12zM1024 91v109q0 7-5 12t-12 5h-987q-7 0-12-5t-5-12v-109q0-7 5-12t12-5h987q7 0 12 5t5 12z"
22   },
23   selectParentNode: {text: "\u2b1a", css: "font-weight: bold"},
24   undo: {
25     width: 24, height: 24,
26     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"
27   },
28   redo: {
29     width: 24, height: 24,
30     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"
31   },
32   strong: {
33     width: 24, height: 24,
34     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"
35   },
36   em: {
37     width: 24, height: 24,
38     path: "M10 4v3h2.21l-3.42 8H6v3h8v-3h-2.21l3.42-8H18V4z"
39   },
40   code: {
41     width: 896, height: 1024,
42     path: "M608 192l-96 96 224 224-224 224 96 96 288-320-288-320zM288 192l-288 320 288 320 96-96-224-224 224-224-96-96z"
43   },
44   link: {
45     width: 951, height: 1024,
46     path: "M832 694q0-22-16-38l-118-118q-16-16-38-16-24 0-41 18 1 1 10 10t12 12 8 10 7 14 2 15q0 22-16 38t-38 16q-8 0-15-2t-14-7-10-8-12-12-10-10q-18 17-18 41 0 22 16 38l117 118q15 15 38 15 22 0 38-14l84-83q16-16 16-38zM430 292q0-22-16-38l-117-118q-16-16-38-16-22 0-38 15l-84 83q-16 16-16 38 0 22 16 38l118 118q15 15 38 15 24 0 41-17-1-1-10-10t-12-12-8-10-7-14-2-15q0-22 16-38t38-16q8 0 15 2t14 7 10 8 12 12 10 10q18-17 18-41zM941 694q0 68-48 116l-84 83q-47 47-116 47-69 0-116-48l-117-118q-47-47-47-116 0-70 50-119l-50-50q-49 50-118 50-68 0-116-48l-118-118q-48-48-48-116t48-116l84-83q47-47 116-47 69 0 116 48l117 118q47 47 47 116 0 70-50 119l50 50q49-50 118-50 68 0 116 48l118 118q48 48 48 116z"
47   },
48   bullet_list: {
49     width: 24, height: 24,
50     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"
51   },
52   ordered_list: {
53     width: 24, height: 24,
54     path: "M2 17h2v.5H3v1h1v.5H2v1h3v-4H2v1zm1-9h1V4H2v1h1v3zm-1 3h1.8L2 13.1v.9h3v-1H3.2L5 10.9V10H2v1zm5-6v2h14V5H7zm0 14h14v-2H7v2zm0-6h14v-2H7v2z"
55   },
56   task_list: {
57     width: 24, height: 24,
58     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"
59   },
60   blockquote: {
61     width: 640, height: 896,
62     path: "M0 448v256h256v-256h-128c0 0 0-128 128-128v-128c0 0-256 0-256 256zM640 320v-128c0 0-256 0-256 256v256h256v-256h-128c0 0 0-128 128-128z"
63   },
64   underline: {
65     width: 24, height: 24,
66     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"
67   },
68   strike: {
69     width: 24, height: 24,
70     path: "M10 19h4v-3h-4v3zM5 4v3h5v3h4V7h5V4H5zM3 14h18v-2H3v2z"
71   },
72   superscript: {
73     width: 24, height: 24,
74     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"
75   },
76   subscript: {
77     width: 24, height: 24,
78     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"
79   },
80   text_color: {
81     width: 24, height: 24,
82     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"
83   },
84   background_color: {
85     width: 24, height: 24,
86     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"
87   },
88   align_left: {
89     width: 24, height: 24,
90     path: "M15 15H3v2h12v-2zm0-8H3v2h12V7zM3 13h18v-2H3v2zm0 8h18v-2H3v2zM3 3v2h18V3H3z"
91   },
92   align_right: {
93     width: 24, height: 24,
94     path: "M3 21h18v-2H3v2zm6-4h12v-2H9v2zm-6-4h18v-2H3v2zm6-4h12V7H9v2zM3 3v2h18V3H3z"
95   },
96   align_center: {
97     width: 24, height: 24,
98     path: "M7 15v2h10v-2H7zm-4 6h18v-2H3v2zm0-8h18v-2H3v2zm4-6v2h10V7H7zM3 3v2h18V3H3z"
99   },
100   align_justify: {
101     width: 24, height: 24,
102     path: "M3 21h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18V7H3v2zm0-6v2h18V3H3z"
103   },
104   horizontal_rule: {
105     width: 24, height: 24,
106     path: "m 4,11 h 16 v 2 H 4 Z"
107   },
108 };
109
110 const SVG = "http://www.w3.org/2000/svg"
111 const XLINK = "http://www.w3.org/1999/xlink"
112
113 const prefix = "ProseMirror-icon"
114
115 function hashPath(path) {
116   let hash = 0
117   for (let i = 0; i < path.length; i++)
118     hash = (((hash << 5) - hash) + path.charCodeAt(i)) | 0
119   return hash
120 }
121
122 export function getIcon(icon) {
123   let node = document.createElement("div")
124   node.className = prefix
125   if (icon.path) {
126     let name = "pm-icon-" + hashPath(icon.path).toString(16)
127     if (!document.getElementById(name)) buildSVG(name, icon)
128     let svg = node.appendChild(document.createElementNS(SVG, "svg"))
129     svg.style.width = (icon.width / icon.height) + "em"
130     let use = svg.appendChild(document.createElementNS(SVG, "use"))
131     use.setAttributeNS(XLINK, "href", /([^#]*)/.exec(document.location)[1] + "#" + name)
132   } else if (icon.dom) {
133     node.appendChild(icon.dom.cloneNode(true))
134   } else {
135     node.appendChild(document.createElement("span")).textContent = icon.text || ''
136     if (icon.css) node.firstChild.style.cssText = icon.css
137   }
138   return node
139 }
140
141 function buildSVG(name, data) {
142   let collection = document.getElementById(prefix + "-collection")
143   if (!collection) {
144     collection = document.createElementNS(SVG, "svg")
145     collection.id = prefix + "-collection"
146     collection.style.display = "none"
147     document.body.insertBefore(collection, document.body.firstChild)
148   }
149   let sym = document.createElementNS(SVG, "symbol")
150   sym.id = name
151   sym.setAttribute("viewBox", "0 0 " + data.width + " " + data.height)
152   let path = sym.appendChild(document.createElementNS(SVG, "path"))
153   path.setAttribute("d", data.path)
154   collection.appendChild(sym)
155 }