為了讓部落格文章具有良好的排版,顯示更加豐富的格式,我們使用 markdown 文法來書寫我們的博文。markdown 是一種 html 文本标記語言,隻要遵循它約定的文法格式,markdown 的渲染器就能夠把我們寫的文章轉換為标準的 html 文檔,進而讓我們的文章呈現更加豐富的格式,例如标題、清單、代碼塊等等 html 元素。由于 markdown 文法簡單直覺,不用超過 5 分鐘就可以掌握常用的标記文法,是以大家青睐使用 markdown 書寫 html 文檔。下面讓我們的部落格也支援使用 markdown 書寫。
将 markdown 格式的文本渲染成标準的 html 文檔是一個複雜的工作,好在已有好心人幫我們完成了這些工作,我們直接使用即可。首先安裝 markdown,這是一個 python 第三方庫,激活虛拟環境,然後使用指令 <code>pip install markdown</code> 安裝即可。
将 markdown 格式的文本渲染成 html 文本非常簡單,隻需調用這個庫的 <code>markdown</code> 方法即可。我們書寫的部落格文章内容存在 <code>post</code> 的 <code>body</code> 屬性裡,回到我們的詳情頁視圖函數,對 <code>post</code> 的 <code>body</code> 的值做一下渲染,把 markdown 文本轉為 html 文本再傳遞給模闆:
這樣我們在模闆中展示 {{ post.body }} 的時候,就不再是原始的 markdown 文本了,而是渲染過後的 html 文本。注意這裡我們給 <code>markdown</code> 渲染函數傳遞了額外的參數 <code>extensions</code>,它是對 markdown 文法的拓展,這裡我們使用了三個拓展,分别是 extra、codehilite、toc。extra 本身包含很多拓展,而 codehilite 是文法高亮拓展,這為我們後面的實作代碼高亮功能提供基礎,而 toc 則允許我們自動生成目錄(在以後會介紹)。
來測試一下效果,進入背景,這次我們釋出一篇用 markdown 文法寫的測試文章看看,你可以使用以下的 markdown 測試代碼進行測試,也可以自己書寫你喜歡的 markdown 文本。假設你是 markdown 新手參考一下這些教程,一定學一下,保證你可以在 5 分鐘内掌握常用的文法格式,而以後對你寫作受用無窮。可謂充電五分鐘,通話 2 小時。以下是我學習中的一些參考資料:
<a href="http://www.jianshu.com/p/1e402922ee32/">markdown——入門指南</a>
<a href="http://www.appinn.com/markdown/">markdown 文法說明 (簡體中文版)</a>
如果你發現無法顯示代碼塊,即代碼無法換行,請檢查代碼塊的文法是否書寫有誤。代碼塊的文法如上邊的測試文本中最後一段所示。
你可能想在文章中插入圖檔,目前能做的且推薦做的是使用外鍊引入圖檔。比如将圖檔上傳到七牛雲這樣的雲存儲伺服器,然後通過 markdown 的圖檔文法将圖檔引入。markdown 引入圖檔的文法為:<code>![圖檔說明](圖檔連結)</code>。
我們在釋出的文章詳情頁沒有看到預期的效果,而是類似于一堆亂碼一樣的 html 标簽,這些标簽本應該在浏覽器顯示它本身的格式,但是 django 出于安全方面的考慮,任何的 html 代碼在 django 的模闆中都會被轉義(即顯示原始的 html 代碼,而不是經浏覽器渲染後的格式)。為了解除轉義,隻需在模闆标簽使用 <code>safe</code> 過濾器即可,告訴 django,這段文本是安全的,你什麼也不用做。在模闆中找到展示部落格文章主體的 {{ post.body }} 部分,為其加上 safe 過濾器,{{ post.body|safe }},大功告成,這下看到預期效果了。
safe 是 django 模闆系統中的過濾器(filter),可以簡單地把它看成是一種函數,其作用是作用于模闆變量,将模闆變量的值變為經過濾器處理過後的值。例如這裡 {{ post.body|safe }},本來 {{ post.body }} 經模闆系統渲染後應該顯示 body 本身的值,但是在後面加上 safe 過濾器後,渲染的值不再是body 本身的值,而是由 safe 函數處理後傳回的值。過濾器的用法是在模闆變量後加一個 | 管道符号,再加上過濾器的名稱。可以連續使用多個過濾器,例如 {{ var|filter1|filter2 }}。
程式員寫部落格免不了要插入一些代碼,markdown 的文法使我們容易地書寫代碼塊,但是目前來說,顯示的代碼塊裡的代碼沒有任何顔色,很不美觀,也難以閱讀,要是能夠像我們的編輯器裡一樣讓代碼高亮就好了。雖然我們在渲染時使用了 codehilite 拓展,但這隻是實作代碼高亮的第一步,還需要簡單的幾步才能達到我們的最終目的。
首先我們需要安裝 pygments,激活虛拟環境,運作: <code>pip install pygments</code> 安裝即可。
搞定了,雖然我們除了安裝了一下 pygments 什麼也沒做,但 markdown 使用 pygments 在背景為我們做了很多事。如果你打開部落格詳情頁,找到一段代碼段,在浏覽器檢視這段代碼段的 html 源代碼,可以發現 pygments 的工作原理是把代碼切分成一個個單詞,然後為這些單詞添加 css 樣式,不同的詞應用不同的樣式,這樣就實作了代碼顔色的區分,即高亮了文法。為此,還差最後一步,引入一個樣式檔案來給這些被添加了樣式的單詞定義顔色。
在項目的 blogstaticblogcsshighlights 目錄下應該能看到很多 .css 樣式檔案,這些檔案是用來提供代碼高亮樣式的。選擇一個你喜歡的樣式檔案,在 base.html 引入即可(别忘了使用 static 模闆标簽)。比如我比較喜歡 github.css 的樣式,那麼引入這個檔案:
這裡 + 号表示添加這行代碼。好了,看看效果,大功告成,終于可以愉快地貼代碼了。
注意:如果你按照教程中的方法做完後發現代碼依然沒有高亮,請依次檢查以下步驟:
確定在渲染文本時添加了 <code>markdown.extensions.codehilite</code> 拓展,詳情見上文。
確定安裝了 pygments。
確定代碼塊的 markdown 文法正确,特别是指明該代碼塊的語言類型,具體請參見上文中 markdown 的文法示例。
在浏覽器端代碼塊的源代碼,看代碼是否被 pre 标簽包裹,并且代碼的每一個單詞都被 span 标簽包裹,且有一個 class 屬性值。如果沒有,極有可能是前三步中某個地方出了問題。
確定用于代碼高亮的樣式檔案被正确地引入,具體請參見上文中引入樣式檔案的講解。
有些樣式檔案可能對代碼高亮沒有作用,首先嘗試用 github.css 樣式檔案做測試。
如果遇到問題,請通過下面的方式尋求幫助。
将問題的較長的描述通過郵件發送到 [email protected],一般會在 24 小時内回複。