修改 Blooger 顯示 markdown 程式碼區塊

之前因為想要在部落格上顯示程式碼, 所以在網上看了第一篇第二篇讓我的原始程式碼可以直接貼在上面. 可是換成用 markdown 寫部落格之後, 之前這招都不能用了. 雖然 StackEdit 支援 markdown extra 的 Fenced Code Blocks, StackEdit 也自動支援 Google Code Prettify, 但是 StackEdit 會把所有的程式碼改成完全支援 Google Code Prettify, 這樣讓整個輸出的 html 碼很亂, 也會讓我用 markdown 寫的文章跟舊的不一致, 為了讓風格一致, 我又把原本的東西做了點修改.

我看了一下 StackEdit 對於 markdown 程式碼區塊轉 html 的處理, 基本上它是把程式碼包在 <pre> <code> 裡面, 就像這樣

<pre><code>int i = 0;</code><pre>

所以看到這裡就大概有個方向可以改了, 就是把原來的 css 碼改一下就可以有 code block 的效果了. 修改如下:

.post .codeblock, pre code{
display: block; /* fixes a strange ie margin bug */
font-family: Courier New;
font-size: 10pt;
overflow:auto;
background: #f0f0f0 url(data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAASwCAYAAAAt7rCDAAAABHNCSVQICAgIfAhkiAAAAQJJREFUeJzt0kEKhDAMBdA4zFmbM+W0upqFOhXrDILwsimFR5pfMrXW5jhZr7PwRlxVX8//jNHrGhExjXzdu9c5IiIz+7iqVmB7Hwp4OMa2nhhwN/PRGEMBh3Zjt6KfpzPztxW9MSAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzB8HS+J9kUTvzEDMwAAAABJRU5ErkJggg==) left top repeat-y;
border: 1px solid #ccc;
padding: 10px 10px 10px 21px;
max-height:1000px;
line-height: 1.2em;
}

就只是在 .post .codeblock 後面加了 , pre code<pre> <code> 可以套用這個 css 而已.

這樣頭只洗了一半, 因為裡面的 code 還是沒有套用到 Google Code Prettify 啊! 為了達到要求只能繼續改下去.

Google Code Prettify 只要求要顯示的程式碼區塊 的 class 加入 “prettyprint” 就可以了. 例如:

<pre class="prettyprint">int i = 0;</pre>

但是 markdown 沒辦法加 class name, 這是要逼死誰啊? 幸好還可以用 JavaScript 補加. 關於第二篇有說新版的 Google Code Prettify 用了下列的語法讓網頁可以自動 loading 不用去改 <body> tag 了.

<script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js"></script>

你以為加了這行就天下太平, 王子跟公主從此就過著幸福快樂的生活了嗎? 當然不可能! 因為這招只適合靜態的網頁內容, 對於動態加入的內容是無效的.

所以為了因應我的需求, 我還是用了第一篇的方法來 load Google Code Prettify

<link href='http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css' type='text/css' rel='stylesheet' />
<script type='text/javascript' src='http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js'></script>

但是請勿修改 <body> tag, 待會會講如何不用改也可以跑.

接下來就是要加入一個 JavaScript 幫我動態補 class.

以下是 JavaScript 程式碼

<script type="text/javascript">
function hackDocument()
{
    var code_blocks = document.querySelectorAll('pre code');
    var prettyed = false;

    for (var i = 0; i < code_blocks.length ; i += 1)
    {
        var code = code_blocks[i];
        code.className += 'prettyprint';
        prettyed = true;
    }

    if (prettyed)
    {
        prettyPrint();
    }
}

window.onload = hackDocument;
</script>

首先我用 document.querySelectorAll('pre code') 找出所有有 <pre> <code> 的區塊, 然後再用個 for 迴圈把所有的區塊都加上 “prettyprint” class. prettyed 是用來判斷有沒有做過更動, 有的話到最後在一次讓 Google Code Prettify 執行美化工作. 至於 window.onload = hackDocument; 就是不用改 body 直接用 JavaScript 覆寫掉原來的 onload 方法. 用這招的時候最好是確定後面的區塊沒有用 JavaScript 覆寫 onload 方法, 不然區塊就不會美化了. 我建議是把自己寫的 JavaScript 都放在同一個區塊, 這樣出問題的時候比較好除錯.

2014/07/12 更新

之前直接複寫 window.onload 的方法一直覺得不是很好, 所以最近又 google 了一下, 發現有人提供了很好的做法. 所以我就參照了他的做法.

原來的 code

window.onload = hackDocument;

改成

var oldOnload = window.onload || function () {};
window.onload = function ()
{
    oldOnload();
    hackDocument();
}

留言

熱門文章