第 09 篇:讓部落格支援 Markdown 語法和程式碼高亮

HelloGitHub發表於2019-08-21
作者:HelloGitHub-追夢人物

文中涉及的示例程式碼,已同步更新到 HelloGitHub-Team 倉庫

為了讓部落格文章具有良好的排版,顯示更加豐富的格式,我們使用 Markdown 語法來書寫博文。Markdown 是一種 HTML 文字標記語言,只要遵循它約定的語法格式,Markdown 的解析工具就能夠把 Markdown 文件轉換為標準的 HTML 文件,從而使文章呈現更加豐富的格式,例如標題、列表、程式碼塊等等 HTML 元素。由於 Markdown 語法簡單直觀,不用超過 5 分鐘就可以輕鬆掌握常用的標記語法,因此大家青睞使用 Markdown 書寫 HTML 文件。下面讓我們的部落格也支援使用 Markdown 寫作。

安裝 Python Markdown

將 Markdown 格式的文字解析成標準的 HTML 文件是一個複雜的工程,好在已有好心人幫我們完成了這些工作,直接拿來使用即可。首先安裝 Markdown,這是一個 Python 第三方庫,在專案根目錄下執行命令 pipenv install markdown

在 detail 檢視中解析 Markdown

將 Markdown 格式的文字解析成 HTML 文字非常簡單,只需呼叫這個庫的 markdown 方法。我們書寫的部落格文章內容存在 Postbody 屬性裡,回到我們的詳情頁檢視函式,對 postbody 的值做一下解析,把 Markdown 文字轉為 HTML 文字再傳遞給模板:

blog/views.py

import markdown
from django.shortcuts import get_object_or_404, render

from .models import Post

def detail(request, pk):
    post = get_object_or_404(Post, pk=pk)
    post.body = markdown.markdown(post.body,
                                  extensions=[
                                      'markdown.extensions.extra',
                                      'markdown.extensions.codehilite',
                                      'markdown.extensions.toc',
                                  ])
    return render(request, 'blog/detail.html', context={'post': post})
複製程式碼

這樣我們在模板中顯示 {{ post.body }} 的時候,就不再是原始的 Markdown 文字了,而是解析過後的 HTML 文字。注意這裡我們給 markdown 解析函式傳遞了額外的引數 extensions,它是對 Markdown 語法的擴充,這裡使用了三個擴充,分別是 extra、codehilite、toc。extra 本身包含很多基礎擴充,而 codehilite 是語法高亮擴充,這為後面的實現程式碼高亮功能提供基礎,而 toc 則允許自動生成目錄(在以後會介紹)。

來測試一下效果,進入後臺,這次我們釋出一篇用 Markdown 語法寫的測試文章看看,你可以使用以下的 Markdown 測試程式碼進行測試,也可以自己書寫你喜歡的 Markdown 文字。假設你是 Markdown 新手請參考一下這些教程,一定學一下,保證你可以在 5 分鐘內掌握常用的語法格式,而以後對你寫作受用無窮。可謂充電 5 分鐘,通話 2 小時。以下是我學習中的一些參考資料:

# 一級標題

## 二級標題

### 三級標題

- 列表項1
- 列表項2
- 列表項3

> 這是一段引用```python
def detail(request, pk):
    post = get_object_or_404(Post, pk=pk)
    post.body = markdown.markdown(post.body,
                                  extensions=[
                                      'markdown.extensions.extra',
                                      'markdown.extensions.codehilite',
                                      'markdown.extensions.toc',
                                  ])
    return render(request, 'blog/detail.html', context={'post': post})
​```
複製程式碼

如果你發現無法顯示程式碼塊,即程式碼無法換行,請檢查程式碼塊的語法是否書寫有誤。程式碼塊的語法如上邊的測試文字中最後一段所示。

你可能想在文章中插入圖片,目前能做的且推薦做的是使用外鏈引入圖片。比如將圖片上傳到七牛雲這樣的雲端儲存伺服器,然後通過 Markdown 的圖片語法將圖片引入。Markdown 引入圖片的語法為:![圖片說明](圖片連結)

safe 標籤

我們在釋出的文章詳情頁沒有看到預期的效果,而是類似於一堆亂碼一樣的 HTML 標籤,這些標籤本應該在瀏覽器顯示它自身的格式,但是 django 出於安全方面的考慮,任何的 HTML 程式碼在 django 的模板中都會被轉義(即顯示原始的 HTML 程式碼,而不是經瀏覽器渲染後的格式)。為了解除轉義,只需在模板變數後使用 safe 過濾器即可,告訴 django,這段文字是安全的,你什麼也不用做。在模板中找到展示部落格文章內容的 {{ post.body }} 部分,為其加上 safe 過濾器:{{ post.body|safe }},大功告成,這下看到預期效果了。

第 09 篇:讓部落格支援 Markdown 語法和程式碼高亮

safe 是 django 模板系統中的過濾器(Filter),可以簡單地把它看成是一種函式,其作用是作用於模板變數,將模板變數的值變為經過濾器處理過後的值。例如這裡 {{ post.body|safe }},本來 {{ post.body }}經模板系統渲染後應該顯示 body 本身的值,但是在後面加上 safe 過濾器後,渲染的值不再是 body 本身的值,而是由 safe 函式處理後返回的值。過濾器的用法是在模板變數後加一個 | 管道符號,再加上過濾器的名稱。可以連續使用多個過濾器,例如 {{ var|filter1|filter2 }}

程式碼高亮

程式設計師寫部落格免不了要插入一些程式碼,Markdown 的語法使我們容易地書寫程式碼塊,但是目前來說,顯示的程式碼塊裡的程式碼沒有任何顏色,很不美觀,也難以閱讀,要是能夠像程式碼編輯器裡一樣讓程式碼高亮就好了。

程式碼高亮我們藉助 js 外掛來實現,其原理就是 js 解析整個 html 頁面,然後找到程式碼塊元素,為程式碼塊中的元素新增樣式。我們使用的外掛叫做 highlight.js 和 highlightjs-line-numbers.js,前者提供基礎的程式碼高亮,後者為程式碼塊新增行號。

首先在 base.html 的 head 標籤裡引入程式碼高亮的樣式,有多種樣式供你選擇,這裡我們選擇 GitHub 主題的樣式。樣式檔案直接通過 CDN 引入,同時在 style 標籤裡自定義了一點元素樣式,使得程式碼塊的顯示效果更加完美。

<head>
  ...
  <link href="https://cdn.bootcss.com/highlight.js/9.15.8/styles/github.min.css" rel="stylesheet">

  <style>
    .codehilite {
      padding: 0;
    }

    /* for block of numbers */
    .hljs-ln-numbers {
      -webkit-touch-callout: none;
      -webkit-user-select: none;
      -khtml-user-select: none;
      -moz-user-select: none;
      -ms-user-select: none;
      user-select: none;

      text-align: center;
      color: #ccc;
      border-right: 1px solid #CCC;
      vertical-align: top;
      padding-right: 5px;
    }

    .hljs-ln-n {
      width: 30px;
    }

    /* for block of code */
    .hljs-ln .hljs-ln-code {
      padding-left: 10px;
      white-space: pre;
    }
  </style>
</head>
複製程式碼

然後是引入 js 檔案,因為應該等整個頁面載入完,外掛再去解析程式碼塊,所以把 js 檔案的引入放在 body 底部:

<body>
  <script src="https://cdn.bootcss.com/highlight.js/9.15.8/highlight.min.js"></script>
  <script src="https://cdn.bootcss.com/highlightjs-line-numbers.js/2.7.0/highlightjs-line-numbers.min.js"></script>
  <script>
    hljs.initHighlightingOnLoad();
    hljs.initLineNumbersOnLoad();
  </script>
</body>
複製程式碼

非常簡單,通過 CDN 引入 highlight.js 和 highlightjs-line-numbers.js,然後初始化了兩個外掛。再來看下效果,非常完美!

第 09 篇:讓部落格支援 Markdown 語法和程式碼高亮

第 09 篇:讓部落格支援 Markdown 語法和程式碼高亮
歡迎關注 HelloGitHub 公眾號,獲取更多開源專案的資料和內容

『講解開源專案系列』啟動——讓對開源專案感興趣的人不再畏懼、讓開源專案的發起者不再孤單。跟著我們的文章,你會發現程式設計的樂趣、使用和發現參與開源專案如此簡單。歡迎聯絡我們給我們投稿,讓更多人愛上開源、貢獻開源~

相關文章