Hướng dẫn thêm nút sao chép code với hightlight js nukeviet

Chủ nhật - 17/04/2022 04:09
Nút sao chép code trong <pre></pre> giúp cho người dùng có thể sao chép nội dung một cách dễ dàng, nhanh chóng, chính xác. Tránh trường hợp có thể xảy ra lỗi trong quá trình sao chép bằng tay
Để thêm tính năng sao chép code trong <pre> chúng ta cần chuẩn bị sau
HilightBadge
Truy cập trang //cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min.js để tải file highlight.min.js về
Tiến hành tạo file js có tên config-highlight.js
"use strict"; 
!function (e, o) { 
    "object" == typeof module && "object" == typeof module.exports ? module.exports = e.document ? o(e, !0) : function (e) { 
        if (!e.document) throw new Error("A window with a document is required"); return o(e) } : o(e) }("undefined" != typeof window ? window : this, function (y, e) { if ("boolean" != typeof o) var o = !1; function t(e) { var o, m = { templateSelector: "#CodeBadgeTemplate", contentSelector: "body", loadDelay: 0, copyIconClass: "fa fa-copy", copyIconContent: "", checkIconClass: "fa fa-check text-success", checkIconContent: "", onBeforeCodeCopied: null }; function t() { m.loadDelay ? setTimeout(n, loadDelay) : n() } function n() { if (!document.querySelector(m.templateSelector)) { var e = document.createElement("div"); e.innerHTML = function () { for (var e = ["<style>", "@media print {", "   .code-badge { display: none; }", "}", "    .code-badge-pre {", "        position: relative;", "    }", "    .code-badge {", "        display: flex;", "        flex-direction: row;", "        white-space: normal;", "        background: transparent;", "        background: #fff;", "        color: #333;", "        font-size: 0.875em;", "        opacity: 0.5;", "        transition: opacity linear 0.5s;", "        border-radius: 0 0 0 7px;", "        padding: 5px 8px 5px 8px;", "        position: absolute;", "        right: 0;", "        top: 0;", "    }", "    .code-badge.active {", "        opacity: 0.8;", "    }", "", "    .code-badge:hover {", "        opacity: .95;", "    }", "", "    .code-badge a,", "    .code-badge a:hover {", "        text-decoration: none;", "    }", "", "    .code-badge-language {", "        margin-right: 10px;", "        font-weight: 600;", "        color: goldenrod;", "    }", "    .code-badge-copy-icon {", "        font-size: 1.2em;", "        cursor: pointer;", "        padding: 0 7px;", "    }", "    .fa.text-success:{ color: limegreen !important }", "</style>", '<div id="CodeBadgeTemplate" style="display:none">', '    <div class="code-badge">', '        <div class="code-badge-language" >{{language}}</div>', '        <div  title="Copy to clipboard">', '            <i class="{{copyIconClass}} code-badge-copy-icon"></i></i></a>', "        </div>", "     </div>", "</div>"], o = "", t = 0; t < e.length; t++)o += e[t] + "\n"; return o }(); var o = e.querySelector("style"), t = e.querySelector(m.templateSelector); document.body.appendChild(o), document.body.appendChild(t) } for (var n = document.querySelector(m.templateSelector).innerHTML, c = document.querySelectorAll("pre>code.hljs"), a = 0; a < c.length; a++) { var r = c[a]; if (!r.querySelector(".code-badge")) { for (var d = "", l = 0; l < r.classList.length; l++) { var i = r.classList[l]; if ("language-" === i.substr(0, 9)) { d = r.classList[l].replace("language-", ""); break } if ("lang-" === i.substr(0, 5)) { d = r.classList[l].replace("lang-", ""); break } if (!d) for (var s = 0; s < r.classList.length; s++)if ("hljs" != r.classList[s]) { d = r.classList[s]; break } } "ps" == (d = d ? d.toLowerCase() : "text") ? d = "powershell" : "cs" == d ? d = "csharp" : "js" == d ? d = "javascript" : "ts" == d ? d = "typescript" : "fox" == d && (d = "foxpro"); var p = n.replace("{{language}}", d).replace("{{copyIconClass}}", m.copyIconClass).trim(), u = document.createElement("div"); u.innerHTML = p, u = u.querySelector(".code-badge"); var g = r.parentElement; g.classList.add("code-badge-pre"), m.copyIconContent && (u.querySelector(".code-badge-copy-icon").innerText = m.copyIconContent), g.insertBefore(u, r) } } document.querySelector(m.contentSelector).addEventListener("click", function (e) { return e.srcElement.classList.contains("code-badge-copy-icon") && (e.preventDefault(), e.cancelBubble = !0, function (e) { var o = e.srcElement.parentElement.parentElement.parentElement, t = o.querySelector("pre>code"), n = t.textContent || t.innerText; m.onBeforeCodeCopied && (n = m.onBeforeCodeCopied(n, t)); var c = document.createElement("textarea"); c.value = n.trim(), document.body.appendChild(c), c.style.display = "block", y.document.documentMode ? c.setSelectionRange(0, c.value.length) : c.select(); document.execCommand("copy"), document.body.removeChild(c), function (e) { var o = m.copyIconClass.split(" "), t = m.checkIconClass.split(" "), n = e.querySelector(".code-badge-copy-icon"); n.innerText = m.checkIconContent; for (var c = 0; c < o.length; c++)n.classList.remove(o[c]); for (c = 0; c < t.length; c++)n.classList.add(t[c]); setTimeout(function () { n.innerText = m.copyIconContent; for (var e = 0; e < t.length; e++)n.classList.remove(t[e]); for (e = 0; e < o.length; e++)n.classList.add(o[e]) }, 2e3) }(o) }(e)), !1 }) } o = e, Object.assign(m, o), "loading" == document.readyState ? document.addEventListener("DOMContentLoaded", t) : t() } y.highlightJsBadge = t, y.module && y.module.exports && (y.module.exports.highlightJsBadge = t), o && t() });

/**
* Highlight.js
*/
document.addEventListener("DOMContentLoaded", (event) => {
    var pres = document.querySelectorAll("pre>code");
    for (var i = 0; i < pres.length; i++) {
        hljs.highlightBlock(pres[i]);
    }

    /* double click */
    for (var pres = document.querySelectorAll("pre,code,kbd,blockquote,td"), i = 0; i < pres.length; i++) pres[i].addEventListener("dblclick", function () {
        var e = getSelection(),
            t = document.createRange();
        t.selectNodeContents(this), e.removeAllRanges(), e.addRange(t)
    }, !1);

    var options = {
        contentSelector: ".blog-posts",
        loadDelay: 0,
        copyIconClass: "code-badge-copy-icon",
        checkIconClass: "code-badge-check-icon",
        onBeforeTextCopied: function (text, codeElement) {
            return text;
        }
    };
    window.highlightJsBadge(options);
});
Tiếp theo tạo nút sao chép với file highlight.css
    /**
* Highlight.js
*/
.code-badge-language {
    display: none
}

.code-badge-copy-icon {
    background: url('data:image/svg+xml;base64,PHN2ZyBhcmlhLWhpZGRlbj0idHJ1ZSIgZm9jdXNhYmxlPSJmYWxzZSIgZGF0YS1wcmVmaXg9ImZhciIgZGF0YS1pY29uPSJjb3B5IiBjbGFzcz0ic3ZnLWlubGluZS0tZmEgZmEtY29weSBmYS13LTE0IiByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGZpbGw9ImN1cnJlbnRDb2xvciIgZD0iTTQzMy45NDEgNjUuOTQxbC01MS44ODItNTEuODgyQTQ4IDQ4IDAgMCAwIDM0OC4xMTggMEgxNzZjLTI2LjUxIDAtNDggMjEuNDktNDggNDh2NDhINDhjLTI2LjUxIDAtNDggMjEuNDktNDggNDh2MzIwYzAgMjYuNTEgMjEuNDkgNDggNDggNDhoMjI0YzI2LjUxIDAgNDgtMjEuNDkgNDgtNDh2LTQ4aDgwYzI2LjUxIDAgNDgtMjEuNDkgNDgtNDhWOTkuODgyYTQ4IDQ4IDAgMCAwLTE0LjA1OS0zMy45NDF6TTI2NiA0NjRINTRhNiA2IDAgMCAxLTYtNlYxNTBhNiA2IDAgMCAxIDYtNmg3NHYyMjRjMCAyNi41MSAyMS40OSA0OCA0OCA0OGg5NnY0MmE2IDYgMCAwIDEtNiA2em0xMjgtOTZIMTgyYTYgNiAwIDAgMS02LTZWNTRhNiA2IDAgMCAxIDYtNmgxMDZ2ODhjMCAxMy4yNTUgMTAuNzQ1IDI0IDI0IDI0aDg4djIwMmE2IDYgMCAwIDEtNiA2em02LTI1NmgtNjRWNDhoOS42MzJjMS41OTEgMCAzLjExNy42MzIgNC4yNDMgMS43NTdsNDguMzY4IDQ4LjM2OGE2IDYgMCAwIDEgMS43NTcgNC4yNDNWMTEyeiI+PC9wYXRoPjwvc3ZnPg==');
    background-size: 100% 100%;
}

.code-badge>.code-badge-check-icon {
    background: green;
}

.code-badge-check-icon {
    font-size: 1.2em;
    cursor: pointer;
    padding: 0 7px;
    background: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGFyaWEtaGlkZGVuPSJ0cnVlIiBmb2N1c2FibGU9ImZhbHNlIiBkYXRhLXByZWZpeD0iZmFzIiBkYXRhLWljb249ImNoZWNrIiBjbGFzcz0ic3ZnLWlubGluZS0tZmEgZmEtY2hlY2sgZmEtdy0xNiIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiIgc3R5bGU9IiYjMTA7ICAgIGNvbG9yOiAjMmFmZjMyOyYjMTA7Ij48cGF0aCBmaWxsPSJjdXJyZW50Q29sb3IiIGQ9Ik0xNzMuODk4IDQzOS40MDRsLTE2Ni40LTE2Ni40Yy05Ljk5Ny05Ljk5Ny05Ljk5Ny0yNi4yMDYgMC0zNi4yMDRsMzYuMjAzLTM2LjIwNGM5Ljk5Ny05Ljk5OCAyNi4yMDctOS45OTggMzYuMjA0IDBMMTkyIDMxMi42OSA0MzIuMDk1IDcyLjU5NmM5Ljk5Ny05Ljk5NyAyNi4yMDctOS45OTcgMzYuMjA0IDBsMzYuMjAzIDM2LjIwNGM5Ljk5NyA5Ljk5NyA5Ljk5NyAyNi4yMDYgMCAzNi4yMDRsLTI5NC40IDI5NC40MDFjLTkuOTk4IDkuOTk3LTI2LjIwNyA5Ljk5Ny0zNi4yMDQtLjAwMXoiLz48L3N2Zz4=');
    background-size: 100% 100%;
}

/* 
* hljs monokai 
* https://cdnjs.com/libraries/highlight.js/
*/
.hljs-ln-numbers {
    -webkit-touch-callout: none !important;
    -webkit-user-select: none !important;
    -khtml-user-select: none !important;
    -moz-user-select: none !important;
    -ms-user-select: none !important;
    user-select: none !important;
    text-align: center !important;
    color: #ccc !important;
    border-right: 1px solid #CCC !important;
    vertical-align: top !important;
    padding-right: 5px !important;
    /* your custom style here */
}

/* for block of code */
.hljs-ln-code {
    padding-left: 10px !important;
}

.hljs {
    display: block;
    overflow-x: auto;
    padding: 0.5em;
    background: #272822;
    color: #ddd;
}

.hljs-tag,
.hljs-keyword,
.hljs-selector-tag,
.hljs-literal,
.hljs-strong,
.hljs-name {
    color: #f92672;
}

.hljs-code {
    color: #66d9ef;
}

.hljs-class .hljs-title {
    color: white;
}

.hljs-attribute,
.hljs-symbol,
.hljs-regexp,
.hljs-link {
    color: #bf79db;
}

.hljs-string,
.hljs-bullet,
.hljs-subst,
.hljs-title,
.hljs-section,
.hljs-emphasis,
.hljs-type,
.hljs-built_in,
.hljs-builtin-name,
.hljs-selector-attr,
.hljs-selector-pseudo,
.hljs-addition,
.hljs-variable,
.hljs-template-tag,
.hljs-template-variable {
    color: #a6e22e;
}

.hljs-comment,
.hljs-quote,
.hljs-deletion,
.hljs-meta {
    color: #75715e;
}

.hljs-keyword,
.hljs-selector-tag,
.hljs-literal,
.hljs-doctag,
.hljs-title,
.hljs-section,
.hljs-type,
.hljs-selector-id {
    font-weight: bold;
}
Sau khi tạo xong các file chúng ta tiến hành upload các file vừa tạo lên hosting. Với file css chúng ta upload tới public_html/assets/css/, đối với file js chúng ta upload ở thư mục public_html/assets/js/clipboard/.
Upload xong chúng ta tiến hành gọi các file ra ngoài giao diện tại :
public_html/themes/[themes đang sử dụng]/theme.php
Đối với file css chúng ta gọi với đường dẫn :
    $html_links[] = [
        'rel' => 'stylesheet',
        'href' => NV_STATIC_URL . NV_ASSETS_DIR . '/css/highlight.css'
    ];
Đối với file js :
    $html_js[] = [
        'ext' => 1,
        'content' =>  NV_STATIC_URL . NV_ASSETS_DIR.'/js/clipboard/highlight.min.js'
    ];
    $html_js[] = [
        'ext' => 1,
        'content' =>  NV_STATIC_URL . NV_ASSETS_DIR.'/js/clipboard/config-highlight.js'
    ];
Sau khi gọi đường dẫn xong mọi người nên xóa lại cache, và f5 lại giao diện để trải nghiệm.
Mong bài viết giúp ích được các bạn phần nào trong thiết kế Website. Hãy nhấn nút like và share  để mọi người cùng học hỏi kiến thức mới nhé. Cảm ơn các bạn đã quan tâm VNCODE.

Tác giả: admin

Tổng số điểm của bài viết là: 0 trong 0 đánh giá

Click để đánh giá bài viết

  Ý kiến bạn đọc

Bạn đã không sử dụng Site, Bấm vào đây để duy trì trạng thái đăng nhập. Thời gian chờ: 60 giây