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