痞客邦部落格程式上色相關文章:
- Part1: SyntaxHighLighter
- Part2: highlight.js
- Part3: Prim.js
highlight.js 加行號
一開始在痞客邦套用 highlight.js 時, 沒有找到可以設定行號的功能. 隨後又在它的文件網站上看到作者希望保持原本 highlight.js 的設計初衷 "單純" (simplicity). 不只是程式上的單純化, 還有應用上的單純化, 簡單化. 因此原作者也就堅持不加上行號的功能(註一). 所以使用時也就沒有多想, 沒有行號就沒有行號唄.
後來 (2016/10/19) 不經意在 GitHub 上發現有人幫它寫了個加行號的 plugin(註二). 當時因為工作比較忙, 只是簡單的記錄下來, 想說以後有空再試吧. 沒想到一放就是好幾年, 今天清理未完成的貼文時看到它, 那就馬上來試試吧!
註一: 原文參見 https://highlightjs.readthedocs.io/en/latest/line-numbers.html.
註二: highlight.js line numbers Plugin 的 GitHub 網址: https://github.com/wcoder/highlightjs-line-numbers.js/
highlightjs-line-numbers.js 使用方法
使用時, 貼程式的地方和 highlight.js 一樣: 同樣的, 程式的第一行要緊接在 <code> tag 之後.
<div><pre>
<code class="C">從這裡開始寫你要上色的程式碼
...
你要上色的程式碼
...
</code>
</pre></div>
差別只在引入 highlight.js 之後, 多附加一行 (下例的 line 3) 引入 highlightjs-line-numbers.js. 還有, 執行 hljs.highlightAll(); 之後, 附加執行 hljs.initLineNumbersOnLoad(); (line 6). 同樣的痞客邦會阻斷我們執行自定義的 JS 程式, 所以我們必需將 JS 程式碼變成 HTML 註解 目前 (2024/10) 痞客邦已經放開執行自定義的 JS 程式的大部份限制, 我們已經無需將 JS 程式碼變成 HTML 註解:
- <script> tag 後面要加 <!--
- </script> tag 前面要加 -->
另外 hljs.initLineNumbersOnLoad(); 預設不會幫只有一行的程式段附加行號. 如果真的有這個需要, 可以附帶參數 {singleLine: true} 讓只有一行的程式段也可以附加行號 (v2.1 新增功能).
<link href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/night-owl.min.css" rel="stylesheet" />
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/highlight.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.8.0/highlightjs-line-numbers.min.js"></script>
<script><!--
hljs.highlightAll();
hljs.initLineNumbersOnLoad({singleLine: true});
--></script>
還有如果啟始行號不是 1 時, JS 可以使用 startFrom 指定 (v2.8 新增功能).
hljs.lineNumbersBlock(myCodeBlock, {
startFrom: 10
})
HTML 頁面, 則使用 data-ln-start-from 屬性指定.
<pre>
<code data-ln-start-from="10">
...
</code>
</pre>
如果你在套用 highlightjs-line-numbers.js 之後, 還有自己客製化的需要, 它也很貼心的為大家準備了一些 selector.
CSS selector | 描述 |
---|---|
.hljs-ln-line | 選擇整個上色的程式 (包含行號部份) |
.hljs-ln-line[data-line-number="i"] | 選擇第i行程式 (包含行號部份) |
.hljs-ln-numbers | 選擇整個行號部份 |
.hljs-ln-numbers[data-line-number="i"] | 選擇第i行行號 |
.hljs-ln-code | 選擇整個上色的程式 (不包含行號) |
.hljs-ln-code[data-line-number="i"] | 選擇第i行程式 (不包含行號) |
highlightjs-line-numbers.js 自定義 CSS
當然我們免不了有時會需要自定義 CSS. 但是這又會觸犯到痞客邦不給手機版自定義 CSS 的潛規則. 比較容易的方法是把以下的程式碼直接貼在文章的最後面:
<p id="myCSS"></p>
<script><!--
document.getElementById("myCSS").outerHTML=[
'<style type="text/css">'
,'.hljs-ln tr { background-color:inherit }'
,'.hljs-ln td { border:inherit }'
,'.hljs-ln td.hljs-ln-numbers { text-align:right; padding-right:4px}'
,'.hljs-ln td.hljs-ln-code { border-left:2px solid #999; padding-left:5px }'
,'</style>'].join('');
--></script>
其中, 第 5~8 行應該是大家都會需要的部份: 調整行高, 行號靠右, 還有行號和程式之間加一直槓.
這段小程式其實大家也可以用在為某一篇文章附加專用的 CSS.
CopyButtonPlugin 插件
今日 (2024/09/28) 不小心瞄了一下別人介紹 highlight.js 的文章, 提到有 Copy to Clipboard 的插件. 所以就順便研究了一下, 不過看完了之後覺得那個不好用. 於是又動手搜了一下, 並找到了這個: highlightjs-copy
它的使用方法也很簡單, 先引入 JS 及 CSS 檔.
<link href="//unpkg.com/highlightjs-copy/dist/highlightjs-copy.min.css" rel="stylesheet" />
<script src="//unpkg.com/highlightjs-copy/dist/highlightjs-copy.min.js"></script>
- 基礎用法:
hljs.addPlugin(new CopyButtonPlugin())
- 自動隠藏功能開關:
hljs.addPlugin( new CopyButtonPlugin({ autohide: false, // Always show the copy button }) )
- 附加 callback 函數:
hljs.addPlugin( new CopyButtonPlugin({ callback: (text, el) => console.log("Copied to clipboard", text), }) )
- 附加修改拷貝後文字的函數:
hljs.addPlugin( new CopyButtonPlugin({ hook: (text, el) => text + "\nCopied from my cool website.", }) )
- 本地化:
hljs.addPlugin( new CopyButtonPlugin({ lang: "zh-tw", }) );
目前支援十種語言: en, es, pt-BR, fr, de, ja, ko, ru, zh, zh-tw.
我在使用時唯一遇到的問題是: 按鈕有點大 (操作上方便些), 但是如果程式只有一行時, 就有點 '杯具' 了. 所以我把它的大小改小了一些.
.hljs-copy-button { font-size:.8em; top:.5em; right:.5em; width:2em; height:2em }
最後貼上我自己在 pixnet 痞客邦部落格使用 highlight.js 的 HTML 片段.
<link href="//unpkg.com/highlightjs-copy/dist/highlightjs-copy.min.css" rel="stylesheet" />
<script src="//unpkg.com/highlightjs-copy/dist/highlightjs-copy.min.js"></script>
<link href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/night-owl.min.css" rel="stylesheet" />
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/highlight.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.8.0/highlightjs-line-numbers.min.js"></script>
<p id='myCSS'></p>
<script>
document.getElementById('myCSS').outerHTML=[
'<style>'
,'.hljs-ln tr { background-color:inherit }'
,'.hljs-ln td { border:inherit }'
,'.hljs-ln td.hljs-ln-numbers { text-align:right; padding-right:4px}'
,'.hljs-ln td.hljs-ln-code { border-left:2px solid #999; padding-left:5px }'
,'.hljs-copy-button { font-size:.8em; top:.5em; right:.5em; width:2em; height:2em }'
,'</style>'].join('');
if (typeof(hljs) !== 'undefined') {
hljs.addPlugin(new CopyButtonPlugin({lang:'zh-tw'}))
hljs.highlightAll()
hljs.initLineNumbersOnLoad({singleLine: true})
}
</script>
更新 2024/10/17
今日收到作者在 github issue 的回覆, 問題已經解決了. 真是太好了. 所以就順便測了一下, 發現目前的版本將 copy icon 的 padding 變小了, 剛好可以放在一行裡, 同時也多了讓使用者自行客製化的設定.
不過, 也有個小缺點: 在行動裝置上它會有誤判的情形. 這主要是在痞客邦部落格上我的 CSS 整個是由 MS OneDrive 非同步載入 JS 再產生的. 但還沒輸到它執行, hljs 就準備好, 並開始執行了. 所以就這麼抓取到錯誤的設定. 正好 mergeHTMLPlugin 的問題也解決了, 於是乾脆都轉 v11 好了. 前面貼的 HTML 片斷的第 15 行也可以順便刪了, 換成下面這行好及時修正 CSS, 讓 CopyButtonPlugin 可以正確無誤.
,'.article-content-inner .hljs {line-height:1.25em; padding:.25em }'
為了大家閱讀上的方便, 我把原本貼在 "Syntax High Light (在 痞客邦部落格 中使用)" 後面, 介紹 highlight.js 的部份都搬過來了.
還有麻煩注意一下, 本文中所列的 JS 使用部落格舊編輯模擬器這個 plugin (在擴充管理功能裡安裝) 來修改你的貼文, 並且需要切換到純文字模式, 並勾選 "不要系統換行" 才能正常運作.
highlight.js
後來發現這個好像比較易用一些, 預設的調色組合也多一些. 8.6 版共支援 125 種語言及 63 種調色組合(styles)
比起 syntaxhighlighter, 它的缺點是:
- (內建功能) 不支援自動加行號
- C 語法有些許錯誤 (據稱 8.7 版已修正)
優點是:
- 這個功能由於資安漏洞在 v11 被取消了, 想要在 v11 裡繼續使用這個功能, 需要加掛一個插件: mergeHTMLPlugin, 細節請參看 "JavaScript: 客製化 highligh.js" 這一篇貼文.
要額外上色的文字段落可以帶有 <span></span>, 所以可加上一些自訂的變化, 如: 粗體, 加上刪除線, 自訂顏色... - 可以 HTML, CSS, Javascript 一起上色, syntaxhighlighter 一次只能套用一種 (有點機車)
下面例子的調色組合 night-owl
<link href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/night-owl.min.css" rel="stylesheet" />
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/highlight.min.js"></script>
<script><!--hljs.highlightAll();--></script>
<div><pre>
<code class="C++">從這裡開始寫你要上色的程式碼
...
你要上色的程式碼
...
</code>
</pre></div>
用法說明:
- 第一行到第三行是 highlight.js 的載入及執行.
- 第一行是載入調色組合, 可以依個人喜好把 "night-owl", 換成其他的調色組合. 調色組合請參看 https://highlightjs.org/static/demo/
- 第二行是載入主程式 (預設支援 28 種語言).
- 第三行是執行上色工作. 要注意這裡的寫法: 由於痞客邦會阻擋外部 JS 的執行, 所以需要用 <!-- 和 --> 把要執行的 JS 程式碼保護起來.
- 需要上色的程式碼要用 <pre><code> 與 </code></pre> 包住. 並指定 <code class="xxxx"> 或者 <code class="lang-xxxx"> 或者 <code class="language-xxxx">. 其中 xxxx 是指明用什麼語言, 如: C++, HTML, JavaScript, CSS, PHP, Perl...
- 另外程式的第一行必需緊接在 <pre><code> 的後面.
- 目前支援的語言列表請參看 https://github.com/highlightjs/highlight.js/blob/master/SUPPORTED_LANGUAGES.md
- 如何設定請參看 http://highlightjs.readthedocs.org/en/latest/css-classes-reference.html
- CDN 線上使用的頁面在 https://cdnjs.com/libraries/highlight.js/. 模組名稱和 CSS 檔名這裡都可以查得到.
- 離線使用的下載頁面在 https://highlightjs.org/download/
2015/10/06 更新
目前版本更新為 8.8.0 版共支援 135 種語言及 65 種調色組合(styles)
2016/10/19 更新
目前版本更新為 9.7.0 版共支援 166 種語言及 77 種調色組合(styles)
發現可以顯示行號的 plugin: https://github.com/wcoder/highlightjs-line-numbers.js/
2020/04/04 更新
目前版本更新為 9.18.1 版共支援 185 種語言及 91 種調色組合(styles)
痞客邦的手機版, 會破壞它的分行, 用 PC 看則沒有這個問題.
2020/04/18 更新
"痞客邦的手機版, 會破壞它的分行" 的部份已經查清楚且修復. 原因是手機版的 CSS 多了一個設定:
.article-content-inner{overflow-wrap:break-word;line-height:1.5}
問題就出在 overflow-wrap:break-word 由於這個屬性會繼承, 所以迼成 .article-content-inner 這個容器以下的許多元素都不產生 overflow 了, 尤其是 <code>, <pre> 這二個需要保持內文原樣的 HTML tag 也都發生了在不應該斷行的地方出現了斷行. 所以只要自訂一個 CSS 把它改回來即可. 不過會產一些副作用: 太長的英文字串如 URL 之類的不會在版面邊界折返, 而是在依符號, 英文單字邊界折返. 這會讓這類 URL 在手機直立版面時, 影響週邊, 使得文章不好閱讀.
.article-content-inner{overflow-wrap:normal}
插入上述 CSS 的辦法. 簡單的:
<p id='myCSS'></p>
<script><!--
document.getElementById("myCSS").outerHTML=[
'<style type="text/css">'
,'.article-content-inner{overflow-wrap:normal}'
,'</style>'].join('');
--></script>
複雜的: 請參考我的這一篇貼文 [置頂] 關於 痞客邦 的手機版廣告
2020/05/02 更新
目前版本更新為 10.0.1 版共支援 189 種語言及 91 種調色組合(styles)
2024/09/20 更新
目前版本更新為 11.10.0 版共支援 192 種語言及 498 種調色組合(themes)
2024/09/24 更新
修正 highlight.js使用方法: 改為 v11.10, 並因應 v11 改版改用新的啟動函數. 原始如下:
<link href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.1/styles/night-owl.min.css" rel="stylesheet" />
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.1/highlight.min.js" type="text/javascript"></script>
<script><!--hljs.initHighlightingOnLoad();--></script>
<div><pre>
<code class="C++">從這裡開始寫你要上色的程式碼
...
你要上色的程式碼
...
</code>
</pre></div>
修正後: 第 3 行的 hljs.initHighlightingOnLoad() 改為 hljs.highlightAll(), 並取消 HTML 註解 (因 Pixnet 放寬了 JS 的執行)
<link href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/night-owl.min.css" rel="stylesheet" />
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/highlight.min.js"></script>
<script>hljs.highlightAll();</script>
<div><pre>
<code class="C++">從這裡開始寫你要上色的程式碼
...
你要上色的程式碼
...
</code>
</pre></div>
修正 highlightjs-line-numbers.js使用方法: highlightjs-line-numbers.js 改為 v2.8. 原始如下:
<link href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.1/styles/night-owl.min.css" rel="stylesheet" />
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.1/highlight.min.js" type="text/javascript"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.7.0/highlightjs-line-numbers.min.js" type="text/javascript"></script>
<script><!--
hljs.initHighlightingOnLoad();
hljs.initLineNumbersOnLoad({singleLine: true});
--></script>
修正後:
<link href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/night-owl.min.css" rel="stylesheet" />
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/highlight.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.8.0/highlightjs-line-numbers.min.js"></script>
<script>
hljs.highlightAll();
hljs.initLineNumbersOnLoad({singleLine: true});
</script>