diff --git a/src/BlogEngine/ClientLib/src/highlight-code.ts b/src/BlogEngine/ClientLib/src/highlight-code.ts index 8f5cd29..c4f08e7 100644 --- a/src/BlogEngine/ClientLib/src/highlight-code.ts +++ b/src/BlogEngine/ClientLib/src/highlight-code.ts @@ -1,10 +1,10 @@ import hljs from 'highlight.js' -import CopyButtonPlugin from 'highlightjs-copy' +import CopyButtonPlugin from './highlight-copy' import '../node_modules/highlight.js/styles/dark.css' import '../node_modules/highlightjs-copy/dist/highlightjs-copy.min.css' export function highlightCode() { - //hljs.addPlugin(CopyButtonPlugin); + hljs.addPlugin(new CopyButtonPlugin()); document.querySelectorAll('pre code').forEach((el : HTMLElement) => { hljs.highlightElement(el); diff --git a/src/BlogEngine/ClientLib/src/highlight-copy.js b/src/BlogEngine/ClientLib/src/highlight-copy.js new file mode 100644 index 0000000..6ff1f49 --- /dev/null +++ b/src/BlogEngine/ClientLib/src/highlight-copy.js @@ -0,0 +1,88 @@ +/** + * @file highlight-copy.js + * @author Arron Hunt + * @copyright Copyright 2021. All rights reserved. + */ + +/** + * Adds a copy button to highlightjs code blocks + */ +class CopyButtonPlugin { + /** + * Create a new CopyButtonPlugin class instance + * @param {Object} [options] - Functions that will be called when a copy event fires + * @param {CopyCallback} [options.callback] + * @param {Hook} [options.hook] + * @param {String} [options.lang] Defaults to the document body's lang attribute and falls back to "en" + */ + constructor(options = {}) { + self.hook = options.hook; + self.callback = options.callback; + self.lang = options.lang || document.documentElement.lang || "en"; + } + "after:highlightElement"({ el, text }) { + // Create the copy button and append it to the codeblock. + let button = Object.assign(document.createElement("button"), { + innerHTML: "Copy", + className: "hljs-copy-button", + }); + button.dataset.copied = false; + el.parentElement.classList.add("hljs-copy-wrapper"); + el.parentElement.appendChild(button); + + // Add a custom proprety to the code block so that the copy button can reference and match its background-color value. + el.parentElement.style.setProperty( + "--hljs-theme-background", + window.getComputedStyle(el).backgroundColor + ); + + button.onclick = function () { + if (!navigator.clipboard) return; + + let newText = text; + if (hook && typeof hook === "function") { + newText = hook(text, el) || text; + } + + navigator.clipboard + .writeText(newText) + .then(function () { + button.innerHTML = "Copied!"; + button.dataset.copied = true; + + let alert = Object.assign(document.createElement("div"), { + role: "status", + className: "hljs-copy-alert", + innerHTML: "Copied to clipboard", + }); + el.parentElement.appendChild(alert); + + setTimeout(() => { + button.innerHTML = "Copy"; + button.dataset.copied = false; + el.parentElement.removeChild(alert); + alert = null; + }, 2000); + }) + .then(function () { + if (typeof callback === "function") return callback(newText, el); + }); + }; + } + } + + export default CopyButtonPlugin + + /** + * @typedef {function} CopyCallback + * @param {string} text - The raw text copied to the clipboard. + * @param {HTMLElement} el - The code block element that was copied from. + * @returns {undefined} + */ + /** + * @typedef {function} Hook + * @param {string} text - The raw text copied to the clipboard. + * @param {HTMLElement} el - The code block element that was copied from. + * @returns {string|undefined} + */ + \ No newline at end of file