博客系统从Pelican迁移至Snow


上一次迁移博客系统还是在上一次。。。 哈哈,不开玩笑,上次迁移大概还是在七年前(2015.10), 不知不觉我的博客也建立快八年时间,如果算上动态博客可能都快十年了,虽然也没写多少篇(其实本地草稿都攒了快200篇了, 也没好好整理), 但好歹可以记录自己的生活和想法,之前使用的博客系统是基于 PythonPelican, 此次将博客迁移至 snow —— 一个轻量,简洁的基于Go开发的静态博客生成器

迁移列表

  • [X] 内容文件(.md、.org、.html)

  • [X] 静态文件(.css、.js、.scss等)

  • [X] 配置文件(pelicanconf.py -> config.yaml)

  • [X] 主题文件

    • [X] 分类功能(子分类)

    • [X] 搜索功能

    • [X] 加密功能

内容文件

由于 Snow 是我自己开发的, 功能上的实现本身就基于我原有的文件内容, 比如 markdownorgmode 的支持,所以迁移上也很简单,有的甚至不用修改原有的内容

文件头

原来的 Pelican 使用三种文件头形式:

.md.org

  • .md

    1Title: 使用pelican搭建个人博客
    2Author: honmaple
    3Date: 2015-12-22
    4Category: Python
    5Tags: python,pelican
    6Slug: 使用pelican搭建个人博客
    7
    8## pelican介绍
  • .org

    1#+TITLE: 私人密码库Bitwarden搭建
    2#+AUTHOR: honmaple
    3#+DATE: 2022-05-29 16:21:15
    4#+CATEGORY: Tech
    5#+PROPERTY: MODIFIED 2022-05-29 16:27:05
    6#+PROPERTY: TAGS linux,bitwarden
    7#+PROPERTY: SLUG 私人密码库Bitwarden搭建

Pelican 中的 AuthorCategory 是固定字段,如果需要指定多个可以使用英文逗号分隔,而在 Snow 中这两个字段是可选或者说是可配置的,无法知道指定的字段是一个列表还是一个完整的单词,所以这里需要修改为

1- Category: Linux
2+ categories: [Linux]

或者

1- #+PROPERTY: TAGS linux,bitwarden
2+ #+PROPERTY: TAGS [linux,bitwarden]

而在 markdown 中,因为 Snow 支持类似 Hugo 的文件头,如果想要一次性修改好,可以直接改成 yaml 或者 toml 格式

  • yaml

    1---
    2categories:
    3  - Linux
    4...
    5---
  • toml

    1+++
    2categories = ["Linux"]
    3...
    4+++

除了修改原来的文件外,我还在 Snow 中内置了一个 pelican 插件,只要在配置里添加

1hooks:
2  - pelican
3...

就能将 Category 字段转成 categories 列表, Author 转成 authors 列表, Tags 转成 tags 列表, 这样就不用修改原来的文件

.html

 1<html>
 2  <head>
 3    <title>Project</title>
 4    <meta name="tags" content="随意写写" />
 5    <meta name="date" content="2015-12-22" />
 6    <meta name="category" content="Life" />
 7    <meta name="authors" content="honmaple" />
 8    <meta name="slug" content="project" />
 9    <meta name="custom_css" content="/static/css/project.css" />
10    <meta name="custom_js" content="https://cdn.bootcss.com/geopattern/1.2.3/js/geopattern.min.js" />
11    <meta name="custom_js" content="/static/js/project.js" />
12  </head>
13  <body>
14    ...
15  </body>
16</html>

html 文件中,原来的 custom_csscustom_js 两个字段主要用于自定义css和js,也是利用我开发的一个pelican插件,把多条记录合并成一个列表,在 Snow 中,不用开发新的插件,但需要修改原来的内容

1- <meta name="custom_css" content="/static/css/project.css" />
2- <meta name="custom_js" content="https://cdn.bootcss.com/geopattern/1.2.3/js/geopattern.min.js" />
3- <meta name="custom_js" content="/static/js/project.js" />
4+ <link type="text/css" href="/static/css/project.css" rel="stylesheet"/>
5+ <script type="text/javascript" src="https://cdn.bootcss.com/geopattern/1.2.3/js/geopattern.min.js"></script>
6+ <script type="text/javascript" src="/static/js/project.js"></script>

这样就能得到两个类型为列表的变量 custom_csscustom_js

忽略文件

Pelican 可以单独指定 content/postscontent/pages, 而在 Snow 中 无法指定 content 目录下的部分目录,但可以设置忽略文件, 这有两种方式

  • 在需要忽略的目录下新建一个 _index.md, 并指定 ingore_files 字段

    1---
    2# 忽略整个目录
    3ignore_files: ["*"]
    4# 忽略目录下的README.md和所有js文件
    5ignore_files:
    6  - README.md
    7  - *.js
    8---
  • 在配置里设置 sections.{目录名}.ignore_files

    1sections:
    2  drafts:
    3    # 忽略{content_dir}/drafts目录
    4    ignore_files: ["*"]

静态文件

favicon.ico

Pelican 中,类似 favicon.icorobots.txtCNAME 这些不需要修改的文件我原来是放到 content/extra 目录,但在 Snow 中,content 目录下的所有文件都会视为页面文件或者页面的资源文件, 所以需要把extra目录下的文件移动到static目录下,并设置

 1statics:
 2  static:
 3    ignore_files:
 4      # 排除所有static下的文件,不包括子目录的文件
 5      - "^[^/]+$"
 6      - "^images/"
 7  static/CNAME:
 8    path: "CNAME"
 9  static/robots.txt:
10    path: "robots.txt"
11  static/favicon.ico:
12    path: "favicon.ico"
13  static/README.md:
14    path: "README.md"
15  content/pages/css:
16    path: "static/css"

scss/css/js

在 Python 中有一个专门处理静态文件的 webassets,在 Pelican 中也有一个插件https://github.com/pelican-plugins/webassets, 而在 Snow 中同样支持静态文件的处理, 比如编译并压缩scss文件

 1params.assets.css:
 2  files:
 3    - "@theme/static/scss/common.scss"
 4    - "@theme/static/scss/entry.scss"
 5    - "@theme/static/scss/entry-tree.scss"
 6  filters:
 7    - libscss:
 8        path: ["themes/snow/static/scss/"]
 9    - cssmin:
10  output: "static/lib/css/style.min.css"

其中 filters 支持 libscss,cssmin,jsmin(js处理有些问题,不要使用, 可以使用)

然后就可以在模版里使用

1{%- assets "css" %}
2<link href="{{ config.site.url }}/{{ asset_url }}" rel="stylesheet">
3{%- endassets %}

配置文件

Pelican 使用 pelicanconf.py, 而 Snow 使用 config.yaml

 1site:
 2  url: "http://127.0.0.1:8000"
 3  title: "紅楓吟"
 4  subtitle: "风落花语风落天,花落风雨花落田."
 5  language: "zh"
 6  author: "honmaple"
 7  logo_name: "楓"
 8
 9mode.publish:
10  site:
11    url: "https://honmaple.me"

主题文件

Snow 的模版系统使用的是 https://github.com/flosch/pongo2, 从 Pelican 使用的 jinja2 迁移到 pongo2 除了相关变量的修改和各种大写外,还有部分区别

  • loop: pongo2 使用的是 forloop, 计数使用的 forloop.Counter, 从1开始

  • marco: pongo2 想要加载并调用文件内的函数,需要添加 export

    1{%- macro archive_list(pages) export %}
    2...
  • super: pongo2 使用的是 block.Super

分类功能

Pelican 中,可以使用 page.tags[0].url 获取标签路径,而在 Snow 中想要获取标签路径, 需要使用 get_taxonomy_url

1{%- for name in page.Meta.Get("tags") %}
2<a href="{{ get_taxonomy_url("tags", name) }}">{{ name }}</a>
3{%- endfor %}

子分类功能

原来的子分类是用我写的一个插件实现的,使用的是 . 作为分隔,如 Category: Life.Coding, 在 Snow 中原生支持子分类, 只需要把 . 改成 /, 比如 Python/FlaskPython/Ansible/Jinja2 会创建如下分类系统

1- Categories
2  - Python
3    - Flask
4    - Ansible
5      - Jinja2

我的博客导航栏的实现就是基于该功能

 1{%- set categories = get_taxonomy("categories") %}
 2{%- if categories %}
 3  {%- for term in categories.Terms %}
 4    {%- if term.Children %}
 5      <li class="dropdown">
 6        <a href="{{ term.Permalink }}">{{ _(term.Name) }}</a>
 7        <ul class="dropdown-menu">
 8          {%- for child in term.Children %}
 9            <li><a href="{{ child.Permalink }}">{{ _(child.Name) }}</a></li>
10          {%- endfor %}
11        </ul>
12      </li>
13    {%- else %}
14      <li><a href="{{ term.Permalink }}">{{ _(term.Name) }}</a></li>
15    {%- endif %}
16  {%- endfor %}
17{%- endif %}

搜索功能

Snow 本身没有自带搜索,但可以输出 json 文件

  • search.md 首先在 {content_dir} 目录下新建 search.md 文件

     1---
     2title: Search
     3path: search.html
     4template: search.html
     5filter: type="posts"
     6paginate: 0
     7section: true
     8formats:
     9  json:
    10    path: "index.json"
    11    template: "search.json"
    12---

    然后在字段 formats 指定格式,路径和模版

  • search.json{theme}/templates 目录下或者 templates (配置文件同级目录下) 建立

    1{{- scratch.Set("newjson", slice()) | slient }}
    2{%- for page in pages %}
    3{{- scratch.Add("newjson", dict("index", forloop.Counter - 1, "permalink", page.Permalink, "summary", page.Summary, "title", page.Title, "content", page.Content | striptags)) | slient }}
    4{%- endfor %}
    5{{- scratch.JSON("newjson") | safe }}

    当写入到 /index.json 后就可以利用其它的搜索库比如 lunr 来进行搜索

加密功能

文章加密也是我不用 Hugo 的一个重要原因,我不希望使用 snow build 之前还需要使用另外的程序对内容进行一个预处理,所以在 Snow 中,我内置了一个名为 encrypt 的插件

1hooks:
2  - encrypt
3...

注册插件后就可以在内容文件里使用 encrypt 的 shortcode代码,或者在模版里使用 encrypt 函数

  • 全局加密: 只要在文件头添加 passowd: xxx,hello world, 其中 xxx 是输入的密码,hello world 是显示的描述信息

  • 局部加密: 使用 shortcode 进行加密

    1<shortcode _name="encrypt" password="xxx" description="hello world">
    2...
    3</shortcode>
  • 模版加密:

    1<div>
    2  {{ page.Content | encrypt:"xxx" }}
    3</div>

示例:为pelican添加文章加密功能

作者: honmaple
链接: https://honmaple.me/articles/2023/02/博客系统从Pelican迁移至Snow.html
版权: CC BY-NC-SA 4.0 知识共享署名-非商业性使用-相同方式共享4.0国际许可协议
wechat
alipay

加载评论