JS生成可自定义语法高亮HTMLcode

cnblogs @ Orcim   



!deprecated!

这里有更好的方案,具体看我的这篇博客博客代码高亮的另一种思路


这篇文章介绍了如何在博客里插入一段 pretty 代码框的方法(以博客园为例),主要是因为实在是受不了博客园以及其他一些博客自带代码框的样子了w~

这篇文章很长很长,你可以直接点击这里,直接跳到源代码处,复制代码,或者滑到文章最底部查看使用方法。

原 理是利用 VSCode Copy With Syntax Highlighting 这个自带的功能,其实很多 IDE 都具有此类功能:

Ctrl + 逗号,打开设置,搜索找到上图中的选项就可以开启高亮语法复制为 HTML 代码的这个功能了,当然现在直接粘贴并不能直接获取到 剪切板内 TEXT 文本,也无法获取带高亮样式的内 HTML 文本。

其实是可以获取剪切板的 HTML 文本的,js 提供了一个 onpaste 事件,可以在函数事件的 event 参数中获取到剪切板的内容了。

event.clipboardData.getData( Format: String )

如果要获取剪切板的纯文本,String 为 “text/plan”,如果是 HTML 文本,String 为 “text/html”:

 
CODE01.js
12345
document.onpaste = function (e){
    var cb_data = e.clipboardData.getData("text\/html");
    // var cb_data = e.clipboardData.getData("text\/plain");
    console.log(cb_data);
}
 

然后,在 IDE 里面复制一段高亮显示着的代码,浏览器里面 Ctrl + V,控制台会 log 出来一堆东西:

为方便查看把这串从 VSCode剪切板 里面得到的内容 Prettify 一下,其实很有规律:

 
CODE02.html
12345678910111213141516171819
<!--StartFragment-->
<div style="color: #d4d4d4;background-color: #1e1e1e;font-family: Meslo LG L DZ, Microsoft YaHei;font-weight: 200;font-size: 16px;line-height: 34px;white-space: pre;">
    <div>
        <span style="color: #9cdcfe;">document</span>
        <span style="color: #d4d4d4;">.</span>
        <span style="color: #dcdcaa;">onpaste</span>
        <span style="color: #d4d4d4;"> = </span>
        <span style="color: #569cd6;">function</span>
        <span style="color: #d4d4d4;"> (</span>
        <span style="color: #9cdcfe;">e</span>
        <span style="color: #d4d4d4;">){</span>
    </div>
    <div>
        <span style="color: #d4d4d4;">    </span>
        <span style="color: #569cd6;">var</span>
        ........
    </div>
</div>
<!--EndFragment-->
 

可能你也发现了规律了吧,其实这就是大多数 IDE 的语法高亮显示功能的原理,整个编辑器就相当于浏览器的窗口,窗口中每段文字都被特定样式的标签包裹起来……每行一个 div 又包裹很多 span 的行内元素,就这样一行一行堆砌,然后就实现了这个功能。

得到的这些 HTML 文本基本上就可以复制到各大博客的编辑器来用了,但是我们除了去设置整个编辑器的样式这个方法之外,没有其他更简便的办法去改变高亮的样式了,而且如果剪切板中 HTML 标签内为 制表符或者是一些空白字符的话,编辑器通常会将其忽略,就没有代码缩进显示,比如我在博客园的编辑器中直接复制 CODE02 的代码到 HTML 编辑文本域里面,代码的缩进全部都没有了,于是就想到对这些剪切板里面的内容处理一下,可以灵活输出自己想要展示 Code 的 HTML。

于是花了一天的时间,从最初的 HTML模板布局 到整个功能的实现,以及 JS 代码修改,最后完善了整个程序。直接给大家看 demo,其实前面的代码框就是演示……,上面的两个代码展示框就是 JS 生成的(普通的字符串的处理),加入了行数标识以及标题标识功能,之后还添加了一个 light 主题,两者样式兼容移动端:

 
theme.js
12345678910111213141516
var themes = {
    "dark": {
        c_title_bg: "#252525", 
        c_title_fg: "#ededed",
        c_editor_bg: "#1e1e1e",
        c_sideNum_bg: "#1e1e1e",
        c_sideNum_fg: "#727272"
    }, 
    "light": {
        c_title_bg: "#dcdcdc", 
        c_title_fg: "#999",
        c_editor_bg: "#f5f5f5",
        c_sideNum_bg: "#e5e5e5",
        c_sideNum_fg: "#999"
    }
};
 

这里就不卖关子了,直接贴代码吧,里面有注释。

-(紧凑的分割线)-

源代码

HTML 代码,便于最后的自定义样式的代码框输出

 
copyAsHTML.html
12345678910111213141516171819202122232425262728293031323334353637
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>CopyAsHtmlFromVScode</title>
</head>
<body>
    <div id="codePart">
        <div id="codeBox" style='width: 100%; height: auto; line-height: 34px; position: relative; font-family: "Meslo LG L DZ", "monospace";'>
            <!-- 标题一栏 -->
            <div id="banner" style="width: 100%; height: 34px; position: absolute; top: 0; left: 0; background: rgba(0, 0, 0, .1); border-top-left-radius: 8px; border-top-right-radius: 8px; box-sizing: border-box; border-bottom: 1px solid rgba(0, 0, 0, .15)">
                <!-- 
                    生成的代码框左上角用于标识文件类型的圆,颜色集合变量名:stampColors
                    html -> 红
                    css -> 蓝
                    js -> 黄
                    txt -> 黑灰
                 -->
                <div id="bannerStamp" style="height: 34px; width: 34px; float: left; display: flex; align-items: center; justify-content: center"><span style="display: block; width: 60%; height: 60%; -webkit-border-radius: 50%; background: green">&nbsp;</span></div>
                <!-- 标题名 -->
                <div style="height: 34px; float: left; font-size: 16px; line-height: 34px; display: flex; align-items: center;"><span style="display: block; font-family: sans-serif" id="bannerTitle">123.html</span></div>
            </div>
            <div class="side" id="vsSide" style="width: 50px; background: none; float: left; padding: 40px 0 30px; background: #f5f5f5; border-top-left-radius: 8px; border-bottom-left-radius: 8px;">
                <!-- 侧边行数一列 -->
            </div>
            <div id="containerOuter" style="width: calc(100% - 70px); float: left; white-space: nowrap; background: #f5f5f5; overflow: auto; padding: 40px 0 30px 20px; border-bottom-right-radius: 8px; border-top-right-radius: 8px;">
                <!-- 代码高亮的展示 HTML -->
                <div id="_containerBox"></div>
            </div>
                <!-- 防止高度坍塌 -->
            <div style="clear: both;"></div>
        </div>
    </div>
</body>
</html>
 

JS 代码,直接复制放在 body 标签后的 script 标签里面,这里分开展示是为了方便排版和阅读~

 
copyAsHTML.js
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
var themes = { // 主题,自己定义了两种,可以自己加~
    "dark": {
        c_title_bg: "#252525", // 标题栏背景色
        c_title_fg: "#ededed", // 前景色(文字颜色)
        c_editor_bg: "#1e1e1e", // 代码区背景
        c_sideNum_bg: "#1e1e1e", // 行数栏背景
        c_sideNum_fg: "#727272" // 前景色
    }, 
    "light": {
        c_title_bg: "#dcdcdc", 
        c_title_fg: "#999",
        c_editor_bg: "#f5f5f5",
        c_sideNum_bg: "#e5e5e5",
        c_sideNum_fg: "#999"
    }
};
var config = { // 调整基本样式
    "theme": "dark", // 主题名
    "fontFamily": '"Meslo LG L DZ", "monospace"', 
    "lineHeight": "25px",
    "fontSize": "15px",
    "fileName": "copyAsHTML.js", // 标题名称
    "stampColor": "" // 留空会根据文件拓展名设置圆点的颜色
};
document.onpaste = function(e){
    format(); // 初始化代码外框模板
    var cb_str = e.clipboardData.getData('text\/html'); // 获取从 VSCode 里面复制的含 html 标签的代码
    var tmpDiv = document.createElement("div");
    tmpDiv.innerHTML = cb_str;
    var containerBox = tmpDiv.children[0];
 
    var arrLineDiv = containerBox.children;
    var HollowArr = [];
    for(var i=0; i<arrLineDiv.length; i++){
        var arrLineSpanChar = arrLineDiv[i].children;
        var tmp_arrLine = [];
        for(var j=0; j<arrLineSpanChar.length; j++){
            var arrEmpty = [];
            arrEmpty[0] = arrLineSpanChar[j].style.color;
            // 空格替换为 HTML 转义符
            arrEmpty[1] = arrLineSpanChar[j].innerHTML.replace(/ /g, "&nbsp;");
            tmp_arrLine.push(arrEmpty);
        }
        HollowArr.push(tmp_arrLine);
    }
 
    var _containerBox = document.getElementById("_containerBox");
    var _sideNums = document.getElementById("vsSide");
    for(var l=0; l<HollowArr.length; l++){
        _containerBox.append(returnLine(HollowArr[l]));
        var tmpSpan = returnSpan("", l+1);
        tmpSpan.style = "display: block; width: 40px; text-align: right; padding-right: 10px; float: left; font-size: 14px; height: " + config.lineHeight;
        _sideNums.append(tmpSpan);
    }
    var g_Span = _sideNums.querySelectorAll("span");
    if(_sideNums.innerHTML) g_Span[g_Span.length - 1].style.borderBottomRightRadius = "4px";
    // 最终结果在浏览器控制台处输出查看
    console.log(document.getElementById("codePart").innerHTML); 
 
    function returnLine(array){
        var oDiv = document.createElement("div");
        oDiv.style = "height: " + config.lineHeight + "; line-height: " + config.lineHeight + "; font-size: " + config.fontSize + ";";
        for(var k=0; k<array.length; k++){
            tspan = returnSpan(array[k][0], array[k][1]);
            tspan.style.lineHeight = "100%";
            oDiv.append(tspan);
        }
        var groupSpan = oDiv.querySelectorAll("span");
        if(oDiv.innerHTML) groupSpan[groupSpan.length - 1].style.paddingRight = "20px";
        return oDiv;
    }
    function returnSpan(cr, ct){
        var oSpan = document.createElement("span");
        oSpan.innerHTML = ct;
        if(!cr) return oSpan;
        oSpan.style.color = cr;
        return oSpan;
    } 
    function format(){
        var stampColors = { // 左上角圆点颜色主题集合
            "html": "#d13239", 
            "css": "#4286f4", 
            "js": "#fbb507", 
            "txt": "#303030", 
        }
        var oCodeBox = document.getElementById("codeBox");
        var oBanner = document.getElementById("banner");
        var bannerStamp = document.getElementById("bannerStamp");
        var bannerTitle = document.getElementById("bannerTitle");
        var oVsSide = document.getElementById("vsSide");
        var oOuter = document.getElementById("containerOuter");
        var theStampColor = config.stampColor;
        var configTheme = config.theme;
 
        if(!config.stampColor) theStampColor = stampColors[config.fileName.split(".").pop()];
        oCodeBox.style.fontFamily = config.fontFamily;
        oCodeBox.style.lineHeight = config.lineHeight;
        bannerTitle.innerText = config.fileName;
        bannerStamp.querySelector("span").style.backgroundColor = theStampColor;
        oBanner.style.backgroundColor = themes[configTheme].c_title_bg;
        bannerTitle.style.color = themes[configTheme].c_title_fg;
        oOuter.style.backgroundColor = themes[configTheme].c_editor_bg;
        oVsSide.style.backgroundColor = themes[configTheme].c_sideNum_bg;
        oVsSide.style.color = themes[configTheme].c_sideNum_fg;
    }
}
 

使用方法

  1. 在 copyAsHTML.html 中引入 copyAsHTML.js
  2. 打开 VSCode,并在设置中确保已勾选 控制在复制时是否同时复制语法高亮 选项
  3. Ctrl + C 复制一段编辑器的代码
  4. Chrome 打开 copyAsHTML.html,页面空白区 Ctrl + V 粘贴
  5. F12 打开 控制台,Copy 输出的所有内容
  6. 粘贴 HTML 代码到 HTML 编辑器中,即可

Advance

添加复制功能和展开/收起功能:

 
advancedHighLight.html
COPY EXPAND
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>CopyAsHtmlFromVScode</title>
    <style>
    </style>
</head>
<body>
    <div id="codePart">
        <div id="codeBox" class="codeBox" style='width: 100%; height: auto; line-height: 34px; position: relative; font-family: "Meslo LG L DZ", "monospace";'>
            <div id="banner" class="banner" style="width: 100%; height: 34px; position: absolute; top: 0; left: 0; background: rgba(0, 0, 0, .1); border-top-left-radius: 8px; border-top-right-radius: 8px; box-sizing: border-box; border-bottom: 1px solid rgba(0, 0, 0, .15)">
                <div id="bannerStamp" style="height: 34px; width: 34px; float: left; display: flex; align-items: center; justify-content: center">
                    <span style="display: block; width: 60%; height: 60%; border-radius: 50%; background: green">&nbsp;</span>
                </div>
                <div style="height: 34px; float: left; font-size: 16px; line-height: 34px; display: flex; align-items: center;">
                    <span style="display: block; font-family: sans-serif" id="bannerTitle">123.html</span>
                </div>
                <div style="height: 34px; float: right; font-size: 16px; line-height: 34px; display: flex; align-items: center; justify-content: center;">
                    <span style="display: block; background: rgba(255, 255, 255, .65); font-family: sans-serif; padding: 0 5px; margin-right: 10px;" data-clipboard-target="">COPY</span>
                    <span class="expandBtn" style="display: block; background: rgba(255, 0, 0, .65); color: #f5f5f5; font-family: sans-serif; padding: 0 5px; margin-right: 10px;">EXPAND</span>
                </div>
            </div>
            <div class="side" id="vsSide" style="width: 50px; background: none; float: left; padding: 40px 0 30px; background: #f5f5f5; border-top-left-radius: 8px; border-bottom-left-radius: 8px;">
            </div>
            <div id="containerOuter" style="width: calc(100% - 70px); float: left; white-space: nowrap; background: #f5f5f5; overflow: auto; padding: 40px 0 30px 20px; border-bottom-right-radius: 8px; border-top-right-radius: 8px;">
                <div id="_containerBox">
 
                </div>
            </div>
            <div style="clear: both;">
            </div>
        </div>
    </div>
</body>
</html>
<script src="./clipBoard.js"></script>
<script>
var themes = { // 主题,自己定义了两种,可以自己加~
    "dark": {
        c_title_bg: "#252525", // 标题栏背景色
        c_title_fg: "#ededed", // 前景色(文字颜色)
        c_editor_bg: "#1e1e1e", // 代码区背景
        c_sideNum_bg: "#1e1e1e", // 行数栏背景
        c_sideNum_fg: "#727272" // 前景色
    }, 
    "light": {
        c_title_bg: "#dcdcdc", 
        c_title_fg: "#999",
        c_editor_bg: "#f5f5f5",
        c_sideNum_bg: "#e5e5e5",
        c_sideNum_fg: "#999"
    }
};
var config = { // 调整基本样式
    "theme": "dark", // 主题名
    "fontFamily": '"Meslo LG L DZ", "monospace"', 
    "lineHeight": "25px",
    "fontSize": "15px",
    "fileName": "advancedHighLight.html", // 标题名称
    "stampColor": "", // 留空会根据文件拓展名设置圆点的颜色
    "maxHeight": 400, // 限制高度,px
    "highLight": [true, "#569cd6"]
};
 
/* 兼容 IE, getComputedStyle */
if (!window.getComputedStyle) {
    window.getComputedStyle = function(el, pseudo) {
        this.el = el;
        this.getPropertyValue = function(prop) {
            var re = /(\-([a-z]){1})/g;
            if (prop == 'float') prop = 'styleFloat';
            if (re.test(prop)) {
                prop = prop.replace(re, function () {
                    return arguments[2].toUpperCase();
                });
            }
            return el.currentStyle[prop] ? el.currentStyle[prop] : null;
        }
        return this;
    }
};
document.onpaste = function(e){
    format(); // 初始化代码外框模板
    var cb_str = e.clipboardData.getData('text\/html') || e.clipboardData.getData('text\/plain'); // 获取从 VSCode 里面复制的含 html 标签的代码
    console.log(cb_str)
    var tmpDiv = document.createElement("div");
    tmpDiv.innerHTML = cb_str;
    var containerBox = tmpDiv.children[0];
 
    var arrLineDiv = containerBox.children;
    var HollowArr = [];
    for(var i=0; i<arrLineDiv.length; i++){
        var arrLineSpanChar = arrLineDiv[i].children;
        var tmp_arrLine = [];
        for(var j=0; j<arrLineSpanChar.length; j++){
            var arrEmpty = [];
            arrEmpty[0] = arrLineSpanChar[j].style.color;
            // 空格替换为 HTML 转义符
            arrEmpty[1] = arrLineSpanChar[j].innerHTML.replace(/ /g, "&nbsp;");
            tmp_arrLine.push(arrEmpty);
        }
        HollowArr.push(tmp_arrLine);
    }
 
    var _containerBox = document.getElementById("_containerBox");
    var stamp = new Date().getTime();
    _containerBox.id = "d" + stamp;
    document.querySelector("[data-clipboard-target]").dataset.clipboardTarget = "#d" + stamp;
    var _sideNums = document.getElementById("vsSide");
    for(var l=0; l<HollowArr.length; l++){
        _containerBox.append(returnLine(HollowArr[l]));
        var tmpSpan = returnSpan("", l+1);
        tmpSpan.style = "display: block; width: 40px; text-align: right; padding-right: 10px; float: left; font-size: 14px; height: " + config.lineHeight;
        _sideNums.append(tmpSpan);
    }
    var g_Span = _sideNums.querySelectorAll("span");
    if(_sideNums.innerHTML) g_Span[g_Span.length - 1].style.borderBottomRightRadius = "4px";
    
    var cb = document.getElementById("codeBox");
    var codeHeight = parseFloat(window.getComputedStyle(codeBox, "").getPropertyValue("height"));
    console.log(codeHeight)
    var expandBtn = document.querySelector(".expandBtn");
    var tog = {
        "expand": function(){
            document.getElementById("banner").style.borderTopRightRadius = "8px";
            // cb.style.maxHeight = codeHeight + "px";
            cb.style.overflow = "auto";
            return "SHRINK";
        },
        "shrink": function(){
            document.getElementById("banner").style.borderTopRightRadius = 0;
            // cb.style.maxHeight = config.maxHeight + "px";
            cb.style.overflow = "auto";
            return "EXPAND";
        }
    };
    if(codeHeight > config.maxHeight){
        expandBtn.style.display = "block";
        tog["shrink"]();
        expandBtn.onclick = function(){
            var lbl = this.innerHTML;
            this.innerHTML = (lbl === "EXPAND" ? tog["expand"]() : tog["shrink"]());
        }
    }else{
        expandBtn.style.display = "none";
    }
    // 最终结果在看控制台处输出查看
    console.log(document.getElementById("codePart").innerHTML); 
 
    function returnLine(array){
        var oDiv = document.createElement("div");
        var bFill = config.highLight[0];
        oDiv.style = "height: " + config.lineHeight + "; line-height: " + config.lineHeight + "; font-size: " + config.fontSize + ";";
        if(!bFill) oDiv.style.color = config.highLight[1];
        for(var k=0; k<array.length; k++){
            tspan = returnSpan(array[k][0], array[k][1], bFill);
            tspan.style.lineHeight = "100%";
            oDiv.append(tspan);
        }
        var groupSpan = oDiv.querySelectorAll("span");
        if(oDiv.innerHTML) groupSpan[groupSpan.length - 1].style.paddingRight = "20px";
        return oDiv;
    }
    function returnSpan(cr, ct, fill = true){
        var oSpan = document.createElement("span");
        oSpan.innerHTML = ct;
        if(!cr) return oSpan;
        if(fill) oSpan.style.color = cr;
        return oSpan;
    } 
    function format(){
        var stampColors = { // 左上角圆点颜色主题集合
            "html": "#d13239", 
            "css": "#4286f4", 
            "js": "#fbb507", 
            "txt": "#373a41", 
            "plist": "#8bc34a"
        }
        var oCodeBox = document.getElementById("codeBox");
        var oBanner = document.getElementById("banner");
        var bannerStamp = document.getElementById("bannerStamp");
        var bannerTitle = document.getElementById("bannerTitle");
        var oVsSide = document.getElementById("vsSide");
        var oOuter = document.getElementById("containerOuter");
        var theStampColor = config.stampColor;
        var configTheme = config.theme;
 
        if(config.maxHeight){
            oCodeBox.dataset.maxHeight = config.maxHeight;
        };
        if(!config.stampColor) theStampColor = stampColors[config.fileName.split(".").pop()];
        oCodeBox.style.fontFamily = config.fontFamily;
        oCodeBox.style.lineHeight = config.lineHeight;
        bannerTitle.innerText = config.fileName;
        bannerStamp.querySelector("span").style.backgroundColor = theStampColor;
        oBanner.style.backgroundColor = themes[configTheme].c_title_bg;
        bannerTitle.style.color = themes[configTheme].c_title_fg;
        oOuter.style.backgroundColor = themes[configTheme].c_editor_bg;
        oVsSide.style.backgroundColor = themes[configTheme].c_sideNum_bg;
        oVsSide.style.color = themes[configTheme].c_sideNum_fg;
    }
}
new ClipboardJS('[data-clipboard-target]');
 
</script>
 

Advance Ver2.0

增加代码框盒子bottom处的复制按钮和展开/收起按钮。

 
advancedHighLight_ver_2_0.html
COPY EXPAND
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>CopyAsHtmlFromVScode</title>
    <style>
    </style>
</head>
<body>
    <div id="codePart">
        <div id="codeBox" class="codeBox" style='width: 100%; height: auto; line-height: 34px; position: relative; font-family: "Meslo LG L DZ", "monospace";'>
            <div id="banner" class="banner" style="width: 100%; height: 34px; position: absolute; top: 0; left: 0; background: rgba(0, 0, 0, .1); border-top-left-radius: 8px; border-bottom-left-radius: 8px; box-sizing: border-box; border-bottom: 1px solid rgba(0, 0, 0, .15)">
                <div id="bannerStamp" style="height: 34px; width: 34px; float: left; display: flex; align-items: center; justify-content: center">
                    <span style="display: block; width: 60%; height: 60%; border-radius: 50%; background: green">&nbsp;</span>
                </div>
                <div style="height: 34px; float: left; font-size: 16px; line-height: 34px; display: flex; align-items: center;">
                    <span style="display: block; font-family: sans-serif" id="bannerTitle">123.html</span>
                </div>
                <div style="height: 34px; float: right; font-size: 16px; line-height: 34px; display: flex; align-items: center; justify-content: center;">
                    <span style="display: block; background: rgba(255, 255, 255, .65); font-family: sans-serif; padding: 0 5px; margin-right: 10px;" data-clipboard-target="">COPY</span>
                    <span class="expandBtn" style="display: block; background: rgba(255, 0, 0, .65); color: #f5f5f5; font-family: sans-serif; padding: 0 5px; margin-right: 10px;">EXPAND</span>
                </div>
            </div>
            <div class="side" id="vsSide" style="width: 50px; background: none; float: left; padding: 40px 0 45px; background: #f5f5f5; border-top-left-radius: 8px; border-bottom-left-radius: 8px;">
            </div>
            <div id="containerOuter" style="width: calc(100% - 70px); float: left; white-space: nowrap; background: #f5f5f5; overflow: auto; padding: 40px 0 45px 20px; border-bottom-right-radius: 8px; border-top-right-radius: 8px;">
                <div id="_containerBox">
 
                </div>
            </div>
            <div class="banner" style="width: 100%; height: 34px; position: absolute; bottom: 55px; left: 0; box-sizing: border-box; border-bottom: 1px solid rgba(0, 0, 0, .15)">
                <div style="height: 34px; float: right; font-size: 16px; line-height: 34px; display: flex; align-items: center; justify-content: center;">
                    <span style="display: block; background: rgba(255, 255, 255, .65); font-family: sans-serif; padding: 0 5px; margin-right: 10px;" data-clipboard-target="">COPY</span>
                    <span class="expandBtn" style="display: block; background: rgba(255, 0, 0, .65); color: #f5f5f5; font-family: sans-serif; padding: 0 5px; margin-right: 10px;">EXPAND</span>
                </div>
            </div>
            <div style="clear: both;">
            </div>
        </div>
    </div>
</body>
</html>
<script src="./clipBoard.js"></script>
<script>
var themes = { // 主题,自己定义了两种,可以自己加~
    "dark": {
        c_title_bg: "#252525", // 标题栏背景色
        c_title_fg: "#ededed", // 前景色(文字颜色)
        c_editor_bg: "#1e1e1e", // 代码区背景
        c_sideNum_bg: "#1e1e1e", // 行数栏背景
        c_sideNum_fg: "#727272" // 前景色
    }, 
    "light": {
        c_title_bg: "#dcdcdc", 
        c_title_fg: "#999",
        c_editor_bg: "#f5f5f5",
        c_sideNum_bg: "#e5e5e5",
        c_sideNum_fg: "#999"
    }
};
var config = { // 调整基本样式
    "theme": "dark", // 主题名
    "fontFamily": '"Meslo LG L DZ", "monospace"', 
    "lineHeight": "25px",
    "fontSize": "15px",
    "fileName": "advancedHighLight_ver_2_0.html", // 标题名称
    "stampColor": "", // 留空会根据文件拓展名设置圆点的颜色
    "maxHeight": 400, // 限制高度,px
    "highLight": [true, "#569cd6"]
};
 
/* 兼容 IE, getComputedStyle */
if (!window.getComputedStyle) {
    window.getComputedStyle = function(el, pseudo) {
        this.el = el;
        this.getPropertyValue = function(prop) {
            var re = /(\-([a-z]){1})/g;
            if (prop == 'float') prop = 'styleFloat';
            if (re.test(prop)) {
                prop = prop.replace(re, function () {
                    return arguments[2].toUpperCase();
                });
            }
            return el.currentStyle[prop] ? el.currentStyle[prop] : null;
        }
        return this;
    }
};
document.onpaste = function(e){
    format(); // 初始化代码外框模板
    var cb_str = e.clipboardData.getData('text\/html') || e.clipboardData.getData('text\/plain'); // 获取从 VSCode 里面复制的含 html 标签的代码
    console.log(cb_str)
    var tmpDiv = document.createElement("div");
    tmpDiv.innerHTML = cb_str;
    var containerBox = tmpDiv.children[0];
 
    var arrLineDiv = containerBox.children;
    var HollowArr = [];
    for(var i=0; i<arrLineDiv.length; i++){
        var arrLineSpanChar = arrLineDiv[i].children;
        var tmp_arrLine = [];
        for(var j=0; j<arrLineSpanChar.length; j++){
            var arrEmpty = [];
            arrEmpty[0] = arrLineSpanChar[j].style.color;
            // 空格替换为 HTML 转义符
            arrEmpty[1] = arrLineSpanChar[j].innerHTML.replace(/ /g, "&nbsp;");
            tmp_arrLine.push(arrEmpty);
        }
        HollowArr.push(tmp_arrLine);
    }
 
    var _containerBox = document.getElementById("_containerBox");
    var stamp = new Date().getTime();
    _containerBox.id = "d" + stamp;
    var clipBoard_tars = document.querySelectorAll("[data-clipboard-target]");
    for(var c=0; c<clipBoard_tars.length; c++) clipBoard_tars[c].dataset.clipboardTarget = "#d" + stamp;
    var _sideNums = document.getElementById("vsSide");
    for(var l=0; l<HollowArr.length; l++){
        _containerBox.append(returnLine(HollowArr[l]));
        var tmpSpan = returnSpan("", l+1);
        tmpSpan.style = "display: block; width: 40px; text-align: right; padding-right: 10px; float: left; font-size: 14px; height: " + config.lineHeight;
        _sideNums.append(tmpSpan);
    }
    var g_Span = _sideNums.querySelectorAll("span");
    if(_sideNums.innerHTML) g_Span[g_Span.length - 1].style.borderBottomRightRadius = "4px";
    
    var cb = document.getElementById("codeBox");
    var codeHeight = parseFloat(window.getComputedStyle(codeBox, "").getPropertyValue("height"));
    console.log(codeHeight)
    var expandBtn = document.querySelector(".expandBtn");
    var tog = {
        "expand": function(){
            document.getElementById("banner").style.borderTopRightRadius = "8px";
            // cb.style.maxHeight = codeHeight + "px";
            cb.style.overflow = "auto";
            return "SHRINK";
        },
        "shrink": function(){
            document.getElementById("banner").style.borderTopRightRadius = 0;
            // cb.style.maxHeight = config.maxHeight + "px";
            cb.style.overflow = "auto";
            return "EXPAND";
        }
    };
    if(codeHeight > config.maxHeight){
        expandBtn.style.display = "block";
        tog["shrink"]();
        expandBtn.onclick = function(){
            var lbl = this.innerHTML;
            this.innerHTML = (lbl === "EXPAND" ? tog["expand"]() : tog["shrink"]());
        }
    }else{
        expandBtn.style.display = "none";
    }
    // 最终结果在看控制台处输出查看
    console.log(document.getElementById("codePart").innerHTML); 
 
    function returnLine(array){
        var oDiv = document.createElement("div");
        var bFill = config.highLight[0];
        oDiv.style = "height: " + config.lineHeight + "; line-height: " + config.lineHeight + "; font-size: " + config.fontSize + ";";
        if(!bFill) oDiv.style.color = config.highLight[1];
        for(var k=0; k<array.length; k++){
            tspan = returnSpan(array[k][0], array[k][1], bFill);
            tspan.style.lineHeight = "100%";
            oDiv.append(tspan);
        }
        var groupSpan = oDiv.querySelectorAll("span");
        if(oDiv.innerHTML) groupSpan[groupSpan.length - 1].style.paddingRight = "20px";
        return oDiv;
    }
    function returnSpan(cr, ct, fill = true){
        var oSpan = document.createElement("span");
        oSpan.innerHTML = ct;
        if(!cr) return oSpan;
        if(fill) oSpan.style.color = cr;
        return oSpan;
    } 
    function format(){
        var stampColors = { // 左上角圆点颜色主题集合
            "html": "#d13239", 
            "css": "#4286f4", 
            "js": "#fbb507", 
            "txt": "#373a41", 
            "plist": "#8bc34a"
        }
        var oCodeBox = document.getElementById("codeBox");
        var oBanner = document.getElementById("banner");
        var bannerStamp = document.getElementById("bannerStamp");
        var bannerTitle = document.getElementById("bannerTitle");
        var oVsSide = document.getElementById("vsSide");
        var oOuter = document.getElementById("containerOuter");
        var theStampColor = config.stampColor;
        var configTheme = config.theme;
 
        if(config.maxHeight){
            oCodeBox.dataset.maxHeight = config.maxHeight;
        };
        if(!config.stampColor) theStampColor = stampColors[config.fileName.split(".").pop()];
        oCodeBox.style.fontFamily = config.fontFamily;
        oCodeBox.style.lineHeight = config.lineHeight;
        bannerTitle.innerText = config.fileName;
        bannerStamp.querySelector("span").style.backgroundColor = theStampColor;
        oBanner.style.backgroundColor = themes[configTheme].c_title_bg;
        bannerTitle.style.color = themes[configTheme].c_title_fg;
        oOuter.style.backgroundColor = themes[configTheme].c_editor_bg;
        oVsSide.style.backgroundColor = themes[configTheme].c_sideNum_bg;
        oVsSide.style.color = themes[configTheme].c_sideNum_fg;
    }
}
new ClipboardJS('[data-clipboard-target]');
 
</script>
COPY EXPAND
 

Copy As HTML From VSCode的更多相关文章

  1. 编写一个Open Live Writer的VSCode代码插件

    起因 又是一年多没有更新过博客了,最近用Arduino做了一点有意思的东西,准备写一篇博客.打开尘封许久的博客园,发现因为Windows Live Writer停止更新,博客园推荐的客户端变为了Ope ...

  2. HEC-ResSim原文档

              HEC-ResSim Reservoir System Simulation             User's Manual       Version 3.1 May 201 ...

  3. shift Alt + up(down) copy current line ! ctrl + j show the control # vscode key

    shift Alt + up(down) copy current line ! ctrl + j show the control # vscode key

  4. vscode restclient 插件

    使用步骤: 1.vscode 安装restclient 扩展 2.创建  .http 或 .rest 文件 ,编写相应内容 同一个文件内 可以通过 ### 分割多个请求 可以通过 @hostname ...

  5. vscode之常用快捷键

    原文章地址: vscode: Visual Studio Code 常用快捷键 官方快捷键说明:Key Bindings for Visual Studio Code 主命令框 F1 或 Ctrl+S ...

  6. vscode c++ cmake template project

    VSCode configure C++ dev environment claim use CMake to build the project. For debugging, VSCode's C ...

  7. vscode 集成 cygwin 的注意事项

    vscode 集成 cygwin vscode 现在是我的主力开发编辑器,它自带 terminal 不需要我各种切换,我还想要在 windows 下执行一些简单的 .sh 文件.所以,我希望有一款工具 ...

  8. win10 添加项目右键用vscode打开

    1.新建reg文件:在vscode安装目录下新建一个文本文件,然后将文件后缀改为:*.reg,文件名任意,例如:vsCodeOpenFolder.reg. 2.编写文本文件内容.将下面的内容Copy到 ...

  9. 使用VSCode调试单个PHP文件

    突然发现是可以使用 VSCode 调试单个 PHP 文件的,今天之前一直没有弄成功,还以为 VSCode 是不能调试单文件呢.这里记录一下今天这个"突然发现"的过程. 开始,是在看 ...

随机推荐

  1. 记录学习docker命令的随笔

    docker安装与启动 安装docker yum包更新到最新  sudo yum update 安装需要的软件包  sudo yum install -y yum-utils device-mappe ...

  2. Unity调用PC摄像头

    转载于Unity3d圣典里面,具体哪位大侠写的我忘咯. using UnityEngine; using System.Collections; public class CameraTest : M ...

  3. C++ —— 输出100以内的质数

    代码如下: #include<iostream> #include<math.h> using namespace std; int main() { int i; for(i ...

  4. 区间查询与等效minus查询

    --表结构 create table hy_emp( id number(4,0) primary key, name nvarchar2(20) not null, edate date) --充值 ...

  5. 设置logback的log文件地址为程序运行的当前目录

    这个需求虽然怪异,却也不是无事生非,在以jar包为执行主体的程序中就会遇到. 设置方法就是指定Log_HOME为./,其在如下配置文件的第四行: <?xml version="1.0& ...

  6. C#开发PACS医学影像处理系统(一):开发背景和说明

    本系列文章将从以下模块和大家分享和讨论使用C#开发医学软件PACS和RIS系统, 国内相关资料比较少,也借此机会丰富一下医学软件开发生态,讨论技术难点,希望大家互相帮助共同进步. 章节介绍及截图预览: ...

  7. 5 分钟带你掌握 Makefile 分析

    摘要:Makefile是一个名为GNU-Make软件所需要的脚本文件,该脚本文件可以指导Make软件控制arm-gcc等工具链去编译工程文件最终得到可执行文件,几乎所有的Linux发行版都内置了GNU ...

  8. [LeetCode] 79. 单词搜索(DFS,回溯)

    题目 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻"单元格是那些水平相邻或垂直相邻的单元格.同一个单元格 ...

  9. [剑指Offer]65-不用加减乘除做加法

    题目 写一个函数,求两个整数之和,要求在函数体内不得使用+.-.*./四则运算符号. 题解 用位运算模拟加法的三步: 无进位加法:异或运算. 进位:与运算再左移一位. 直到进位为0结束. 代码 pub ...

  10. 被喷了!聊聊我开源的RPC框架那些事

    前段时间利用业余时间写了一个简单的 RPC 框架,花费了不少精力.开源出来之后,少部分不太友好的技术人站在上帝视角说了风凉话.就很难受,兄弟,谁还没有一个玻璃心. 简单吐槽一波,给大家聊聊关于 gui ...