You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
4.1 KiB
179 lines
4.1 KiB
(function () { |
|
|
|
if (typeof Prism === 'undefined' || typeof document === 'undefined') { |
|
return; |
|
} |
|
|
|
var callbacks = []; |
|
var map = {}; |
|
var noop = function () {}; |
|
|
|
Prism.plugins.toolbar = {}; |
|
|
|
/** |
|
* @typedef ButtonOptions |
|
* @property {string} text The text displayed. |
|
* @property {string} [url] The URL of the link which will be created. |
|
* @property {Function} [onClick] The event listener for the `click` event of the created button. |
|
* @property {string} [className] The class attribute to include with element. |
|
*/ |
|
|
|
/** |
|
* Register a button callback with the toolbar. |
|
* |
|
* @param {string} key |
|
* @param {ButtonOptions|Function} opts |
|
*/ |
|
var registerButton = Prism.plugins.toolbar.registerButton = function (key, opts) { |
|
var callback; |
|
|
|
if (typeof opts === 'function') { |
|
callback = opts; |
|
} else { |
|
callback = function (env) { |
|
var element; |
|
|
|
if (typeof opts.onClick === 'function') { |
|
element = document.createElement('button'); |
|
element.type = 'button'; |
|
element.addEventListener('click', function () { |
|
opts.onClick.call(this, env); |
|
}); |
|
} else if (typeof opts.url === 'string') { |
|
element = document.createElement('a'); |
|
element.href = opts.url; |
|
} else { |
|
element = document.createElement('span'); |
|
} |
|
|
|
if (opts.className) { |
|
element.classList.add(opts.className); |
|
} |
|
|
|
element.textContent = opts.text; |
|
|
|
return element; |
|
}; |
|
} |
|
|
|
if (key in map) { |
|
console.warn('There is a button with the key "' + key + '" registered already.'); |
|
return; |
|
} |
|
|
|
callbacks.push(map[key] = callback); |
|
}; |
|
|
|
/** |
|
* Returns the callback order of the given element. |
|
* |
|
* @param {HTMLElement} element |
|
* @returns {string[] | undefined} |
|
*/ |
|
function getOrder(element) { |
|
while (element) { |
|
var order = element.getAttribute('data-toolbar-order'); |
|
if (order != null) { |
|
order = order.trim(); |
|
if (order.length) { |
|
return order.split(/\s*,\s*/g); |
|
} else { |
|
return []; |
|
} |
|
} |
|
element = element.parentElement; |
|
} |
|
} |
|
|
|
/** |
|
* Post-highlight Prism hook callback. |
|
* |
|
* @param env |
|
*/ |
|
var hook = Prism.plugins.toolbar.hook = function (env) { |
|
// Check if inline or actual code block (credit to line-numbers plugin) |
|
var pre = env.element.parentNode; |
|
if (!pre || !/pre/i.test(pre.nodeName)) { |
|
return; |
|
} |
|
|
|
// Autoloader rehighlights, so only do this once. |
|
if (pre.parentNode.classList.contains('code-toolbar')) { |
|
return; |
|
} |
|
|
|
// Create wrapper for <pre> to prevent scrolling toolbar with content |
|
var wrapper = document.createElement('div'); |
|
wrapper.classList.add('code-toolbar'); |
|
pre.parentNode.insertBefore(wrapper, pre); |
|
wrapper.appendChild(pre); |
|
|
|
// Setup the toolbar |
|
var toolbar = document.createElement('div'); |
|
toolbar.classList.add('toolbar'); |
|
|
|
// order callbacks |
|
var elementCallbacks = callbacks; |
|
var order = getOrder(env.element); |
|
if (order) { |
|
elementCallbacks = order.map(function (key) { |
|
return map[key] || noop; |
|
}); |
|
} |
|
|
|
elementCallbacks.forEach(function (callback) { |
|
var element = callback(env); |
|
|
|
if (!element) { |
|
return; |
|
} |
|
|
|
var item = document.createElement('div'); |
|
item.classList.add('toolbar-item'); |
|
|
|
item.appendChild(element); |
|
toolbar.appendChild(item); |
|
}); |
|
|
|
// Add our toolbar to the currently created wrapper of <pre> tag |
|
wrapper.appendChild(toolbar); |
|
}; |
|
|
|
registerButton('label', function (env) { |
|
var pre = env.element.parentNode; |
|
if (!pre || !/pre/i.test(pre.nodeName)) { |
|
return; |
|
} |
|
|
|
if (!pre.hasAttribute('data-label')) { |
|
return; |
|
} |
|
|
|
var element; var template; |
|
var text = pre.getAttribute('data-label'); |
|
try { |
|
// Any normal text will blow up this selector. |
|
template = document.querySelector('template#' + text); |
|
} catch (e) { /* noop */ } |
|
|
|
if (template) { |
|
element = template.content; |
|
} else { |
|
if (pre.hasAttribute('data-url')) { |
|
element = document.createElement('a'); |
|
element.href = pre.getAttribute('data-url'); |
|
} else { |
|
element = document.createElement('span'); |
|
} |
|
|
|
element.textContent = text; |
|
} |
|
|
|
return element; |
|
}); |
|
|
|
/** |
|
* Register the toolbar with Prism. |
|
*/ |
|
Prism.hooks.add('complete', hook); |
|
}());
|
|
|