第 09 篇:让博客支持 Markdown 语法和代码高亮

做者:HelloGitHub- 追梦人物

文中涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库css

为了让博客文章具备良好的排版,显示更加丰富的格式,咱们使用 Markdown 语法来书写博文。Markdown 是一种 HTML 文本标记语言,只要遵循它约定的语法格式,Markdown 的解析工具就可以把 Markdown 文档转换为标准的 HTML 文档,从而使文章呈现更加丰富的格式,例如标题、列表、代码块等等 HTML 元素。因为 Markdown 语法简单直观,不用超过 5 分钟就能够轻松掌握经常使用的标记语法,所以你们青睐使用 Markdown 书写 HTML 文档。下面让咱们的博客也支持使用 Markdown 写做。html

安装 Python Markdown

将 Markdown 格式的文本解析成标准的 HTML 文档是一个复杂的工程,好在已有好心人帮咱们完成了这些工做,直接拿来使用便可。首先安装 Markdown,这是一个 Python 第三方库,在项目根目录下运行命令 pipenv install markdownpython

在 detail 视图中解析 Markdown

将 Markdown 格式的文本解析成 HTML 文本很是简单,只需调用这个库的 markdown 方法。咱们书写的博客文章内容存在 Postbody 属性里,回到咱们的详情页视图函数,对 postbody 的值作一下解析,把 Markdown 文本转为 HTML 文本再传递给模板:git

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 小时。如下是我学习中的一些参考资料:github

# 一级标题

## 二级标题

### 三级标题

- 列表项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}) ​``` 复制代码

若是你发现没法显示代码块,即代码没法换行,请检查代码块的语法是否书写有误。代码块的语法如上边的测试文本中最后一段所示。web

你可能想在文章中插入图片,目前能作的且推荐作的是使用外链引入图片。好比将图片上传到七牛云这样的云存储服务器,而后经过 Markdown 的图片语法将图片引入。Markdown 引入图片的语法为:![图片说明](图片连接)django

safe 标签

咱们在发布的文章详情页没有看到预期的效果,而是相似于一堆乱码同样的 HTML 标签,这些标签本应该在浏览器显示它自身的格式,可是 django 出于安全方面的考虑,任何的 HTML 代码在 django 的模板中都会被转义(即显示原始的 HTML 代码,而不是经浏览器渲染后的格式)。为了解除转义,只需在模板变量后使用 safe 过滤器便可,告诉 django,这段文本是安全的,你什么也不用作。在模板中找到展现博客文章内容的 {{ post.body }} 部分,为其加上 safe 过滤器:{{ post.body|safe }},大功告成,这下看到预期效果了。编程

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,而后初始化了两个插件。再来看下效果,很是完美!

欢迎关注 HelloGitHub 公众号,获取更多开源项目的资料和内容

『讲解开源项目系列』启动——让对开源项目感兴趣的人再也不畏惧、让开源项目的发起者再也不孤单。跟着咱们的文章,你会发现编程的乐趣、使用和发现参与开源项目如此简单。欢迎联系咱们给咱们投稿,让更多人爱上开源、贡献开源~

相关文章
相关标签/搜索