UNPKG

4.2 kBJavaScriptView Raw
1(function () {
2
3 if (typeof Prism === 'undefined' || typeof document === 'undefined') {
4 return;
5 }
6
7 var callbacks = [];
8 var map = {};
9 var noop = function () {};
10
11 Prism.plugins.toolbar = {};
12
13 /**
14 * @typedef ButtonOptions
15 * @property {string} text The text displayed.
16 * @property {string} [url] The URL of the link which will be created.
17 * @property {Function} [onClick] The event listener for the `click` event of the created button.
18 * @property {string} [className] The class attribute to include with element.
19 */
20
21 /**
22 * Register a button callback with the toolbar.
23 *
24 * @param {string} key
25 * @param {ButtonOptions|Function} opts
26 */
27 var registerButton = Prism.plugins.toolbar.registerButton = function (key, opts) {
28 var callback;
29
30 if (typeof opts === 'function') {
31 callback = opts;
32 } else {
33 callback = function (env) {
34 var element;
35
36 if (typeof opts.onClick === 'function') {
37 element = document.createElement('button');
38 element.type = 'button';
39 element.addEventListener('click', function () {
40 opts.onClick.call(this, env);
41 });
42 } else if (typeof opts.url === 'string') {
43 element = document.createElement('a');
44 element.href = opts.url;
45 } else {
46 element = document.createElement('span');
47 }
48
49 if (opts.className) {
50 element.classList.add(opts.className);
51 }
52
53 element.textContent = opts.text;
54
55 return element;
56 };
57 }
58
59 if (key in map) {
60 console.warn('There is a button with the key "' + key + '" registered already.');
61 return;
62 }
63
64 callbacks.push(map[key] = callback);
65 };
66
67 /**
68 * Returns the callback order of the given element.
69 *
70 * @param {HTMLElement} element
71 * @returns {string[] | undefined}
72 */
73 function getOrder(element) {
74 while (element) {
75 var order = element.getAttribute('data-toolbar-order');
76 if (order != null) {
77 order = order.trim();
78 if (order.length) {
79 return order.split(/\s*,\s*/g);
80 } else {
81 return [];
82 }
83 }
84 element = element.parentElement;
85 }
86 }
87
88 /**
89 * Post-highlight Prism hook callback.
90 *
91 * @param env
92 */
93 var hook = Prism.plugins.toolbar.hook = function (env) {
94 // Check if inline or actual code block (credit to line-numbers plugin)
95 var pre = env.element.parentNode;
96 if (!pre || !/pre/i.test(pre.nodeName)) {
97 return;
98 }
99
100 // Autoloader rehighlights, so only do this once.
101 if (pre.parentNode.classList.contains('code-toolbar')) {
102 return;
103 }
104
105 // Create wrapper for <pre> to prevent scrolling toolbar with content
106 var wrapper = document.createElement('div');
107 wrapper.classList.add('code-toolbar');
108 pre.parentNode.insertBefore(wrapper, pre);
109 wrapper.appendChild(pre);
110
111 // Setup the toolbar
112 var toolbar = document.createElement('div');
113 toolbar.classList.add('toolbar');
114
115 // order callbacks
116 var elementCallbacks = callbacks;
117 var order = getOrder(env.element);
118 if (order) {
119 elementCallbacks = order.map(function (key) {
120 return map[key] || noop;
121 });
122 }
123
124 elementCallbacks.forEach(function (callback) {
125 var element = callback(env);
126
127 if (!element) {
128 return;
129 }
130
131 var item = document.createElement('div');
132 item.classList.add('toolbar-item');
133
134 item.appendChild(element);
135 toolbar.appendChild(item);
136 });
137
138 // Add our toolbar to the currently created wrapper of <pre> tag
139 wrapper.appendChild(toolbar);
140 };
141
142 registerButton('label', function (env) {
143 var pre = env.element.parentNode;
144 if (!pre || !/pre/i.test(pre.nodeName)) {
145 return;
146 }
147
148 if (!pre.hasAttribute('data-label')) {
149 return;
150 }
151
152 var element; var template;
153 var text = pre.getAttribute('data-label');
154 try {
155 // Any normal text will blow up this selector.
156 template = document.querySelector('template#' + text);
157 } catch (e) { /* noop */ }
158
159 if (template) {
160 element = template.content;
161 } else {
162 if (pre.hasAttribute('data-url')) {
163 element = document.createElement('a');
164 element.href = pre.getAttribute('data-url');
165 } else {
166 element = document.createElement('span');
167 }
168
169 element.textContent = text;
170 }
171
172 return element;
173 });
174
175 /**
176 * Register the toolbar with Prism.
177 */
178 Prism.hooks.add('complete', hook);
179}());