一鍵生成通用高亮程式碼塊到剪貼簿,快捷貼上相容 TT/WX/BJ 編輯器

2022-10-11 15:00:49

有些線上圖文編輯器不支援直接插入程式碼塊,但可以直接貼上 HTML 格式的高亮程式碼塊。

花了一點時間研究了一下各家的編輯器,規則卻各不相同。有的要求程式碼塊被包含於 <code> ... </code> 或者 <pre> <code> ... </code> </pre> , 有些要求 class 屬性裡包含 "code" 關鍵詞,或者要求程式碼塊裡必須包含至少一個 <br> 。如果不符合這些要求,不是變成普通文字,就是丟失換行縮排,或者丟失顏色樣式。

所以,這就難了。先得找個支援程式碼高亮的編輯器,仔細地選擇並複製程式碼塊,複製完還得編輯剪貼簿裡的 HTML 。這就不如干脆寫個轉換工具了。

因為瀏覽器作業系統剪貼簿可能不太方便,下面用 aardio 寫一個工具軟體。

先看軟體成品演示:

 

軟體用法:

1、輸入程式語言名稱(支援自動完成)。

2、然後在輸入框中貼上要轉換的程式設計程式碼。

3、點選「複製高亮程式碼塊」按鈕。

然後我們就可以開啟線上圖文編輯器直接貼上生成的高亮程式碼塊了,相容  TT、WX、BJ 編輯器。

下面是這個軟體的 aardio 原始碼:

import win.ui;
/*DSG{{*/
var winform = win.form(text="HTML 程式碼塊生成工具 - 本工具使用 aardio 語言編寫";right=1055;bottom=674;bgcolor=16777215)
winform.add(
button={cls="button";text="複製高亮程式碼塊";left=633;top=609;right=1000;bottom=665;bgcolor=16777215;color=14120960;db=1;dr=1;font=LOGFONT(h=-14);note="可在網頁編輯器直接貼上";z=4};
cmbLangs={cls="combobox";left=262;top=625;right=446;bottom=651;db=1;dl=1;edge=1;items={"javascript"};mode="dropdown";z=2};
editCode={cls="edit";left=1;top=4;right=1052;bottom=599;db=1;dl=1;dr=1;dt=1;edge=1;hscroll=1;multiline=1;vscroll=1;z=5};
static={cls="static";text="請選擇語言:";left=70;top=629;right=248;bottom=649;align="right";db=1;dl=1;transparent=1;z=3};
webCtrl={cls="custom";text="自定義控制元件";left=8;top=10;right=1048;bottom=604;db=1;dl=1;dr=1;dt=1;hide=1;z=1}
)
/*}}*/

import web.view;
var wb = web.view(winform.webCtrl);

import win.clip.html;
wb.export({ 
    onHighlight = function(html,background,foreground){
        html = `<pre class="code" style="overflow-x:auto;text-align:left;box-shadow: rgba(216, 216, 216, 0.5) 0px 0px 0px 1px inset;padding:10px;border-radius:3px;background-color:`+background+`;color:`+foreground+`;white-space:pre;word-break:break-all;display:block;font-size:14px;font-style:normal;font-variant-ligatures:normal;font-variant-caps: normal;font-family: "Consolas", Consolas, "Liberation Mono", Menlo, Courier, monospace"><code>`
            + html + `</code></pre>`;

        html,count = string.replace(html,'\n',"<br>");
        if(!count){
            html = string.replace(html,`\</code\>\</pre\>$`,`<br></code></pre>`);
        }
        var cb = win.clip.html();
        cb.write(html); 

        winform.setTimeout( 
            function(){
                winform.editCode.show(true);
                winform.webCtrl.show(false);
                winform.text = "HTML 程式碼塊生成工具 - 已複製高亮程式碼塊到剪貼簿,可在網頁直接貼上";
            },1000); 
    };
    setLanguages = function(langs){
        winform.languages = langs;
    }  
})


winform.cmbLangs.onEditChange = function(){ 

    var text = string.lower(winform.cmbLangs.text);
    var items = table.filter( winform.languages : {}, lambda(v) string.startWith(v,text) ); 
    winform.cmbLangs.autoComplete(items);  
}
winform.cmbLangs.editBox.disableInputMethod();

import web.prism;
import wsock.tcp.asynHttpServer;
var httpServer = wsock.tcp.asynHttpServer(); 
httpServer.run(web.prism,{
    ["/index.html"] = /*****
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" /> 
    <link href="prism.css" rel="stylesheet" />
  </head>
  <body>
    <pre id="code-pre"><code id="code" class="lang-javascript"></code></pre>
    <script src="prism.js"></script>
    <script>
   function computedColorStyle(element, options = {}) {

        Array.prototype.forEach.call(element.children,child => {
            computedColorStyle(child, options);
        });

        const computedStyle = getComputedStyle(element);
        element.style["color"] = computedStyle.getPropertyValue("color");  
    }

    highlight = function(code,language){
        var html = Prism.highlight(code, Prism.languages[language], language);

        var codeEle = document.getElementById("code");
        codeEle.innerHTML = html;
        computedColorStyle(codeEle);

        const computedStyle = getComputedStyle(codeEle);  
        onHighlight(codeEle.innerHTML
            ,getComputedStyle(document.getElementById("code-pre")).getPropertyValue("background-color")
            ,computedStyle.getPropertyValue("color"));
    }

    setLanguages( Object.keys(Prism.languages) );
    </script>
  </body> 
</html> 
    *****/
});

wb.go( httpServer.getUrl("/index.html"));

winform.button.oncommand = function(id,event){
    winform.text = "HTML 程式碼塊生成工具 - 本工具使用 aardio 語言編寫"
    winform.editCode.show(false);
    winform.webCtrl.show(true);

    wb.xcall("highlight",winform.editCode.text,winform.cmbLangs.text);
}


winform.show();
win.loopMessage();

開啟 aardio 建立工程,然後複製貼上上面的程式碼到 main.aardio 裡面就可以直接執行,或生成獨立 EXE 檔案:

這個軟體的原理:

1、首先通過 WebView2 呼叫 Prism.js 高亮程式碼。為了可以記憶體載入 Prism.js ( 支援生成獨立 EXE ),我寫了一個 aardio 擴充套件庫 web.prism 。

關於 WebView2 請參考:放棄 Electron,擁抱 WebView2!JavaScript 快速開發獨立 EXE 程式

2、因為 Prism.js 生成的 HTML 程式碼塊都是使用 class 屬性指定樣式,所以我們需要呼叫 getComputedStyle 獲取最終渲染的字型顏色屬性。

3、最後在 JavaScript 裡呼叫 aardio 函數處理生成的 HTML 程式碼塊,aardio 的任務是將 HTML 修改為更合適直接貼上的格式,並儘可能地處理各圖文編輯器的相容問題。然後呼叫 win.clip.html 將處理好的 HTML 複製到系統剪貼簿:

import win.clip.html;

var cb = win.clip.html();
cb.write(html); 

然後只要愉快地貼上程式碼塊就可以。

如果是 aardio 程式碼不需要用這個工具,在 aardio 編輯器裡右鍵直接點『 複製全部到 HTML 程式碼塊 』就可以了:

 注意按住 Ctrl 鍵再點 『 複製全部到 HTML 程式碼塊 』 生成的高亮程式碼塊會啟用自動換行。