• 一、从零开始搭建自己的静态博客 -- 基础篇


    前几天心血来潮,想要在GitHub Pages上搭建一个静态博客;之前,我也曾基于Django开发过自己的博客,并买了云主机部署,但是访问量感人,慢慢自己也不打理了,就把云主机退订了(去吃吨好的~~~);

    虽然搭建静态博客很简单,但是也想记录一下,如果恰好能对你有所帮助或启发,那我也觉的很开心了。

    搭建静态博客的工具多种多样,即有流行的WordPress,也有GitHub Pages官方推荐的Jekyll;其实,选用哪种工具不重要,关键是一步步的理解它,遇到问题、解决问题的思路和过程;

    因为我本人对Python比较熟悉,所以我选用基于Python开发的pelican,它基本满足我的需求:

    • 支持markdown的格式;
    • 提供自动化构建;
    • 足够的主题库和插件库,并且支持定制化;
    • ...

    本文主要涉及pelican的基本使用方法,最终在本地搭建一个简陋的博客网站;

    1. 准备环境

    选定工作目录,并使用pipenv创建一个虚拟环境:

    λ mkdir pelican-blog
    λ cd pelican-blog
    
    # 创建基于 Python 3 的虚拟环境 
    λ pipenv install --three
    
    # 查看虚拟环境中的 Python 版本
    λ pipenv run python --version
    Python 3.7.3
    

    在虚拟环境中安装必要的包:

    λ pipenv install Markdown pelican
    
    # 查看包之间的依赖关系
    λ pipenv graph
    Markdown==3.1.1
      - setuptools [required: >=36, installed: 41.6.0]
    pelican==4.2.0
      - blinker [required: Any, installed: 1.4]
      - docutils [required: Any, installed: 0.15.2]
      - feedgenerator [required: >=1.9, installed: 1.9]
        - pytz [required: >=0a, installed: 2019.3]
        - six [required: Any, installed: 1.13.0]
      - jinja2 [required: >=2.7, installed: 2.10.3]
        - MarkupSafe [required: >=0.23, installed: 1.1.1]
      - pygments [required: Any, installed: 2.4.2]
      - python-dateutil [required: Any, installed: 2.8.1]
        - six [required: >=1.5, installed: 1.13.0]
      - pytz [required: >=0a, installed: 2019.3]
      - six [required: >=1.4, installed: 1.13.0]
      - unidecode [required: Any, installed: 1.1.1]
    

    2. 新建项目

    pelican提供了一个命令行工具:pelican-quickstart,能够让我们快速地新建一个网站项目;

    它在执行的过程中,会交互式的询问一些配置项,如果你现在还不能确定的话,那就大胆的使用默认值吧,后面还可以在配置文件中修改;

    pelican-quickstart

    命令执行完成后,它会在我们的项目中新建如下的目录和文件:

    .
    ├── content         # 目录,存放原始博文和相关静态文件
    ├── output          # 目录,存放构建后的网站源码
    ├── Makefile        
    ├── pelicanconf.py  # 构建相关的配置文件
    ├── publishconf.py  # 发布相关的配置文件
    └── tasks.py
    

    其中,content/目录存放所有的markdown格式的文本,我们还可以再新建一个content/images/的子目录,用于存放所有的图片;

    注意:

    在自动构建的过程中,content/images/中的文件会被无损地拷贝到output/images/中,通过修改pelicanconf.py文件中STATIC_PATHS的配置项(默认值为['images'])可以改变这种行为;


    3. 第一篇博文

    现在我们在content/目录下添加第一篇markdown格式的文章,就以本文为例;

    pelican可以很“聪明”地从文章的元数据中提取需要的信息,所以我们以特定的格式编写文章的开头:

    Title: 一、从零开始搭建自己的静态博客 -- 基础篇
    Date: 2019-11-21 14:37
    Modified: 2019-11-22 11:09
    Category: 工具
    Tags: pelican
    Author: luizyao
    Slug: pelican-blog-chapter-1
    Summary: 本文简要的介绍 pelican 的基本用法
    Status: published
    
    <开始正文>
    

    注意:


    4. 修改配置文件

    在正式开始构建之前,我们需要完善一下配置文件pelicanconf.py

    # pelicanconf.py
    
    # 修改时区
    TIMEZONE = 'Asia/Shanghai'
    
    # 添加一个 GitHub 的“丝带”链接
    GITHUB_URL = 'https://github.com/luizyao'
    
    # 修改社交账号的展示
    SOCIAL = (
        ('GitHub', 'https://github.com/luizyao'),
    )
    
    # 修改默认的时间格式('%a %d %B %Y')
    DEFAULT_DATE_FORMAT = "%Y-%m-%d %H:%M"
    
    # 为元数据定义默认值
    DEFAULT_METADATA = {
        # 默认发布的文章都是草稿,除非在文章元数据中明确指定:Status: published
        'status': 'draft',
    }
    

    5. 本地构建和访问

    我们通过以下命令构建网站并自动适配文件的修改,通过http://localhost:8000访问:

    λ pipenv run pelican --autoreload --listen content/
    

    注意:

    • 不要忘记把文章元数据中的Status: draft改成Status: published,不然我们是看不到这篇文章的;

    • pelican默认使用notmyidea这个主题来构建网站;你可以通过pelican-themes命令查看已安装的主题:

      λ pipenv run pelican-themes --list
      notmyidea
      simple
      

      然后通过在pelicanconf.py中设定THEME = 'simple'或者构建时传入-t 'simple'选项来使用主题simple,实际上和纯文本差不多了;


    6. markdown解析异常

    • 这是一个列表:

      if 1:
          print('这是一段python代码')
      

    这个时候,如果你访问我们的网站,你会发现上面的markdown代码被展示成下面的形式,根本就不是我们想要的缩进代码块的效果:

    screenshot_markdown_error

    为什么会这样呢?我们又该如何解决这个问题?

    6.1. Markdown包的实现机制

    pelican使用Markdown包作为markdown文本的解释器,这个包严格实现了John Gruber’s Markdown语法,并提供一些扩展;

    John Grubermarkdown语法的发明者,他在2004发布了第一个版本的markdown语法,这一版本的语法有着明显的特点:

    • 不支持三个反引号('```')包裹代码的写法;
    • 不支持表格;
    • 定义了严格的嵌套缩进的格式,必须是4个空格;
    • ...

    虽然自从发布了第一版之后,就再也没有更新过,但是现在流行的各种markdown语法都是基于它的扩展和补充,例如:GitHub MarkdownPHP Markdown等;

    注意:

    虽然Markdown包严格实现了John Gruber’s Markdown语法,但是具体的实现还是有一些差别的,更多细节可以参考:https://python-markdown.github.io/#differences

    6.2. pelican默认使用的Markdown扩展

    上一节中我们提到,Markdown包同样提供一些扩展用于解析更多类型的语法,这些扩展又分为官方扩展和第三方扩展;

    通过查阅pelican的源码(或官方文档),可以看到其默认使用了以下扩展:

    # pelican/settings.py
    
    'MARKDOWN': {
        'extension_configs': {
            'markdown.extensions.codehilite': {'css_class': 'highlight'},
            'markdown.extensions.extra': {},
            'markdown.extensions.meta': {},
        },
        'output_format': 'html5',
    },
    

    首先,我们看一下markdown.extensions.extra扩展:

    它主要实现了大多数PHP Markdown的语法,是其它6个扩展的合集:

    扩展 文档 描述
    Abbreviations https://python-markdown.github.io/extensions/abbreviations/
    Attribute Lists https://python-markdown.github.io/extensions/attr_list/
    Definition Lists https://python-markdown.github.io/extensions/definition_lists/
    Fenced Code Blocks https://python-markdown.github.io/extensions/fenced_code_blocks/ 扩展了代码块的写法
    Footnotes https://python-markdown.github.io/extensions/footnotes/
    Tables https://python-markdown.github.io/extensions/tables/ 支持表格

    我们重点看一下Fenced Code Blocks,因为它支持了我常用的三个反引号包裹代码块的写法:

    GitHub‘s backtick (```) syntax is also supported:

    # more python code
    

    然后,我们再看一下markdown.extensions.codehilite扩展:

    它基于Pygments包为我们提供了代码的高亮显示,我们主要看一下它的一些可配置选项:

    • linenums:如果置为True,将会为代码块每行标上行号;
    • css_class:为<div>标签加上class属性,默认是codehilite;在这里,pelican使用的是highlight;

    最后,我们看一下markdown.extensions.meta

    它主要是pelican内部使用,还记得我们每个markdown文本的开头都要有特定的格式吗?就是通过这个扩展读取的;感兴趣的同学可以自己去看一下,这里我们就不多说了;

    6.3. 向第三方扩展寻求帮助

    看到现在,我们也没有找到想要的解决方案:对列表里缩进嵌套反引号包裹的代码块,进行正确的渲染;

    还好我们还有众多的第三方扩展供我们使用:https://github.com/Python-Markdown/markdown/wiki/Third-Party-Extensions

    我们找到一个pymdownx.extra的扩展貌似可以代替markdown.extensions.extra,来一起看一下吧:

    它和markdown.extensions.extra大部分是一样的,只是有以下不同:

    • 新包含了BetterEm扩展:优化粗体和斜体的展示(不关心);
    • 新包含了ExtraRawHTML扩展:增加了对原始HTML代码的处理(不关心);
    • 使用SuperFences扩展代替Fenced Code Blocks:加强版的markdown语法解析(看来正式我们想要的);

    其实,看到SuperFences文档的第一句话,我就知道妥了,嘻嘻;

    Allowing the nesting of fences under blockquotes, lists, or other block elements (see Limitations for more info).

    文档的内容很丰富,我们就不再这里一一解释了,有兴趣的同学可以自己去看一看,说不定有什么意外的收获呢!!!

    6.4. 解决问题

    现在,我们来实际解决这个问题:

    1. 安装必要的包:

      λ pipenv install pymdown-extensions
      
    2. 修改pelicanconf.py文件中MARKDOWN的默认配置:

      # 使用第三方扩展来增强对 markdown 语言的解析,但是首先要安装 pymdown-extensions 模块
      MARKDOWN = {
          'extension_configs': {
              'markdown.extensions.codehilite': {'css_class': 'highlight'},
              'pymdownx.extra': {},
              'markdown.extensions.meta': {},
          },
          'output_format': 'html5',
      }
      

    7. One more thing

    我在浏览SuperFences文档时,发现一个很有意思的章节:https://facelessuser.github.io/pymdown-extensions/extensions/superfences/#code-highlighting

    它推荐了pymdownx.highlight代替markdown.extensions.codehilite,那我们就来看看这到底是个什么鬼?

    在它的文档中有一句话大概能说明两者的关系:

    The Highlight extension is inspired by CodeHilite, but differs in features. PyMdown Extensions chooses not to implement special language headers for standard Markdown code blocks like CodeHilite does; PyMdown Extensions takes the position that language headers are better suited in fenced code blocks.

    更多实现上的细节,我们不再去深究,主要看看我们可以用来干什么?

    比如,为代码块每行加上行号:

    咦?markdown.extensions.codehilite也可以啊,它不是也有一个linenums的选项吗?置成True不就行了;

    说的对,不过丑。

    一般情况下,为代码块添加行号有两种样式:

    • table:默认的样式,创建一个表,第一列是行号;
    • inline:在每行代码的开头,但是复制代码会把行号一起复制,不方便;

    不过,pymdownx.highlight提供了第三种样式:pymdownx-inline,它和inline很像,只是复制时不会加上行号,因为实际上把行号元素渲染成下面这样:

    <span class="lineno" data-linenos="1 "></span>
    

    然后,我们通过以下的CSS样式去“激活”它:

    [data-linenos]:before {
      content: attr(data-linenos);
    }
    

    下面,我们来将它具体的应用到我们的项目中吧:

    首先,修改pelicanconf.py文件中MARKDOWN的默认配置:

    # 使用第三方扩展来增强对 markdown 语言的解析,但是首先要安装 pymdown-extensions 模块
    MARKDOWN = {
        'extension_configs': {
            'pymdownx.highlight': {
                'css_class': 'highlight',
                'linenums': True,
                'linenums_style': 'pymdownx-inline',
            },
            'pymdownx.extra': {},
            'markdown.extensions.meta': {},
        },
        'output_format': 'html5',
    }
    

    然后,在output/theme/css/main.css文件的末尾加上下面这段代码:

    [data-linenos]:before {
      content: attr(data-linenos);
    }
    

    最后重启下服务,就能看到效果了:

    Screenshot_full_site

    注意:

    这里有个问题,如果我们重新执行构建命令,output/theme/css/main.css文件又会被覆盖成原先的内容,我们这个效果就看不到了;

    不过这并不是我们最终的方案,所以我们也不在这里继续深究了。

    GitHub:https://github.com/luizyao/pelican-blog/tree/chapter-1

  • 相关阅读:
    Unique Binary Search Trees 解答
    Unique Paths II 解答
    Unique Paths 解答
    Maximum Subarray 解答
    Climbing Stairs 解答
    House Robber II 解答
    House Robber 解答
    Valid Palindrome 解答
    Container With Most Water 解答
    Remove Duplicates from Sorted List II 解答
  • 原文地址:https://www.cnblogs.com/luizyao/p/11910504.html
Copyright © 2020-2023  润新知