"use strict"; /* ---------------------------------------- highlightJs Badge ---------------------------------------- A copy code and language display badge for the highlightJs Syntax highlighter. by Rick Strahl, 2019-2020 License: MIT Make sure this script is loaded last in your script loading. Usage: ------ Load `highlightjs-badge.js` after `highlight.js`: ```js ``` The script contains the template and CSS so nothing else is needed to run it. Customization: -------------- This code automatically embeds styling and the template. If you want to customize you can either create a template in your HTML **using the code at the end of this file**. Alternately you can customize the `getTemplate()` function that renders the code from a string and keep it self contained within this script. Requirements: ------------- Uses some ES6 features so won't work in IE without shims: * Object.assign * String.trim */ // module header (function( global, factory ) { if ( typeof module === "object" && typeof module.exports === "object" ) { // For CommonJS and CommonJS-like environments where a proper `window` // is present, execute the factory module.exports = global.document ? factory( global, true ) : function( w ) { if ( !w.document ) { throw new Error( "A window with a document is required" ); } return factory( w ); }; } else { factory( global ); } // Pass this if window is not defined yet }(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { if (typeof highlightJsBadgeAutoLoad !== 'boolean') var highlightJsBadgeAutoLoad = false; function highlightJsBadge(opt) { var options = { // the selector for the badge template templateSelector: "#CodeBadgeTemplate", // base content selector that is searched for snippets contentSelector: "body", // Delay in ms used for `setTimeout` before badging is applied // Use if you need to time highlighting and badge application // since the badges need to be applied afterwards. // 0 - direct execution (ie. you handle timing loadDelay: 0, // CSS class(es) used to render the copy icon. copyIconClass: "fa fa-copy", // optional content for icons class ( or file_copy) copyIconContent: "", // CSS class(es) used to render the done icon. checkIconClass: "fa fa-check text-success", checkIconContent: "", // function called before code is placed on clipboard // Passed in text and returns back text function(text, codeElement) { return text; } onBeforeCodeCopied: null }; function initialize(opt) { Object.assign(options, opt); if (document.readyState == 'loading') document.addEventListener("DOMContentLoaded", load); else load(); } function load() { if (options.loadDelay) setTimeout(addCodeBadge, loadDelay); else addCodeBadge(); } function addCodeBadge() { // first make sure the template exists - if not we embed it if (!document.querySelector(options.templateSelector)) { var node = document.createElement("div"); node.innerHTML = getTemplate(); var style = node.querySelector("style"); var template = node.querySelector(options.templateSelector); document.body.appendChild(style); document.body.appendChild(template); } var hudText = document.querySelector(options.templateSelector).innerHTML; var $codes = document.querySelectorAll("pre>code.hljs"); for (var index = 0; index < $codes.length; index++) { var el = $codes[index]; if (el.querySelector(".code-badge")) continue; // already exists var lang = ""; for (var i = 0; i < el.classList.length; i++) { var cl = el.classList[i]; // class="hljs language-csharp" if (cl.substr(0, 9) === 'language-') { lang = el.classList[i].replace('language-', ''); break; } // class="hljs lang-cs" // docFx else if (cl.substr(0, 5) === 'lang-') { lang = el.classList[i].replace('lang-', ''); break; } // class="kotlin hljs" (auto detected) if (!lang) { for (var j = 0; j < el.classList.length; j++) { if (el.classList[j] == 'hljs') continue; lang = el.classList[j]; break; } } } if (lang) lang = lang.toLowerCase(); else lang = "text"; // Language Name overrides so it displays nicer if (lang == "ps") lang = "powershell"; else if (lang == "cs") lang = "csharp"; else if (lang == "js") lang = "javascript"; else if (lang == "ts") lang = "typescript"; else if (lang == "fox") lang = "foxpro"; else if (lang == "txt") lang = "text" var html = hudText.replace("{{language}}", lang) .replace("{{copyIconClass}}",options.copyIconClass) .trim(); // insert the Hud panel var $newHud = document.createElement("div"); $newHud.innerHTML = html; $newHud = $newHud.querySelector(".code-badge"); // make
 tag position:relative so positioning keeps pinned right
            // even with scroll bar scrolled
            var pre = el.parentElement;            
            pre.classList.add("code-badge-pre")

            if(options.copyIconContent)
              $newHud.querySelector(".code-badge-copy-icon").innerText = options.copyIconContent;

            pre.insertBefore($newHud, el);
        }

        var $content = document.querySelector(options.contentSelector);

        // single copy click handler
        $content.addEventListener("click",
            function (e) {                               
                var $clicked = e.srcElement;
                if ($clicked.classList.contains("code-badge-copy-icon")) {
                    e.preventDefault();
                    e.cancelBubble = true;
                    copyCodeToClipboard(e);
                }
                return false;
            });
    }


    function copyCodeToClipboard(e) {
        // walk back up to 
 tag
        var $origCode = e.srcElement.parentElement.parentElement.parentElement;
    
        // select the  tag and grab text
        var $code = $origCode.querySelector("pre>code");
        var text = $code.textContent || $code.innerText;
        
        if (options.onBeforeCodeCopied)
            text = options.onBeforeCodeCopied(text, $code);
                
        // Create a textblock and assign the text and add to document
        var el = document.createElement('textarea');
        el.value = text.trim();
        document.body.appendChild(el);
        el.style.display = "block";
    
        // select the entire textblock
        if (window.document.documentMode)
            el.setSelectionRange(0, el.value.length);
        else
            el.select();
        
        // copy to clipboard
        document.execCommand('copy');
        
        // clean up element
        document.body.removeChild(el);
        
        // show the check icon (copied) briefly
        swapIcons($origCode);     
    }

    function swapIcons($code) {
        var copyIcons = options.copyIconClass.split(' ');
        var checkIcons = options.checkIconClass.split(' ');
        
        var $fa = $code.querySelector(".code-badge-copy-icon");
        $fa.innerText = options.checkIconContent;

        for (var i = 0; i < copyIcons.length; i++)
            $fa.classList.remove(copyIcons[i]);
        
        for (var i = 0; i < checkIcons.length; i++)
            $fa.classList.add(checkIcons[i]);
        
        
        setTimeout(function () {
            $fa.innerText = options.copyIconContent;

            for (var i = 0; i < checkIcons.length; i++)
                $fa.classList.remove(checkIcons[i]);
            for (var i = 0; i < copyIcons.length; i++)
                $fa.classList.add(copyIcons[i]);
        }, 2000);
    }

    function getTemplate() {
      var stringArray =
      [
        "",
            "
", "
", "
{{language}}
", "
", " ", "
", "
", "
" ]; var t = ""; for (var i = 0; i < stringArray.length; i++) t += stringArray[i] + "\n"; return t; } initialize(opt); } // global reference Window window.highlightJsBadge = highlightJsBadge; // module export if (window.module && window.module.exports) window.module.exports.highlightJsBadge = highlightJsBadge; if (highlightJsBadgeAutoLoad) highlightJsBadge(); })); // You can embed the following into your HTML document // to provide your own custom styling. /* */