Table of Contents
上一次迁移博客系统还是在上一次。。。 哈哈,不开玩笑,上次迁移大概还是在七年前(2015.10), 不知不觉我的博客也建立快八年时间,如果算上动态博客可能都快十年了,虽然也没写多少篇(其实本地草稿都攒了快200篇了, 也没好好整理), 但好歹可以记录自己的生活和想法,之前使用的博客系统是基于
Python的Pelican, 此次将博客迁移至 snow —— 一个轻量,简洁的基于Go开发的静态博客生成器
迁移列表
-
[X]内容文件(.md、.org、.html) -
[X]静态文件(.css、.js、.scss等) -
[X]配置文件(pelicanconf.py -> config.yaml) -
[X]主题文件-
[X]分类功能(子分类) -
[X]搜索功能 -
[X]加密功能
-
内容文件
由于 Snow 是我自己开发的, 功能上的实现本身就基于我原有的文件内容, 比如 markdown 和 orgmode 的支持,所以迁移上也很简单,有的甚至不用修改原有的内容
文件头
原来的 Pelican 使用三种文件头形式:
.md 和 .org
-
.mdTitle: 使用pelican搭建个人博客 Author: honmaple Date: 2015-12-22 Category: Python Tags: python,pelican Slug: 使用pelican搭建个人博客 ## pelican介绍
-
.org#+TITLE: 私人密码库Bitwarden搭建 #+AUTHOR: honmaple #+DATE: 2022-05-29 16:21:15 #+CATEGORY: Tech #+PROPERTY: MODIFIED 2022-05-29 16:27:05 #+PROPERTY: TAGS linux,bitwarden #+PROPERTY: SLUG 私人密码库Bitwarden搭建
在 Pelican 中的 Author 和 Category 是固定字段,如果需要指定多个可以使用英文逗号分隔,而在 Snow 中这两个字段是可选或者说是可配置的,无法知道指定的字段是一个列表还是一个完整的单词,所以这里需要修改为
- Category: Linux + categories: [Linux]
或者
- #+PROPERTY: TAGS linux,bitwarden + #+PROPERTY: TAGS [linux,bitwarden]
而在 markdown 中,因为 Snow 支持类似 Hugo 的文件头,如果想要一次性修改好,可以直接改成 yaml 或者 toml 格式
-
yaml--- categories: - Linux ... --- -
toml+++ categories = ["Linux"] ... +++
除了修改原来的文件外,我还在 Snow 中内置了一个 pelican 插件,只要在配置里添加
hooks:
- pelican
...
就能将 Category 字段转成 categories 列表, Author 转成 authors 列表, Tags 转成 tags 列表, 这样就不用修改原来的文件
.html
<html> <head> <title>Project</title> <meta name="tags" content="随意写写" /> <meta name="date" content="2015-12-22" /> <meta name="category" content="Life" /> <meta name="authors" content="honmaple" /> <meta name="slug" content="project" /> <meta name="custom_css" content="/static/css/project.css" /> <meta name="custom_js" content="https://cdn.bootcss.com/geopattern/1.2.3/js/geopattern.min.js" /> <meta name="custom_js" content="/static/js/project.js" /> </head> <body> ... </body> </html>
在 html 文件中,原来的 custom_css 和 custom_js 两个字段主要用于自定义css和js,也是利用我开发的一个pelican插件,把多条记录合并成一个列表,在 Snow 中,不用开发新的插件,但需要修改原来的内容
- <meta name="custom_css" content="/static/css/project.css" /> - <meta name="custom_js" content="https://cdn.bootcss.com/geopattern/1.2.3/js/geopattern.min.js" /> - <meta name="custom_js" content="/static/js/project.js" /> + <link type="text/css" href="/static/css/project.css" rel="stylesheet"/> + <script type="text/javascript" src="https://cdn.bootcss.com/geopattern/1.2.3/js/geopattern.min.js"></script> + <script type="text/javascript" src="/static/js/project.js"></script>
这样就能得到两个类型为列表的变量 custom_css 和 custom_js
忽略文件
Pelican 可以单独指定 content/posts 和 content/pages, 而在 Snow 中 无法指定 content 目录下的部分目录,但可以设置忽略文件, 这有两种方式
-
在需要忽略的目录下新建一个
_index.md, 并指定ingore_files字段--- # 忽略整个目录 ignore_files: ["*"] # 忽略目录下的README.md和所有js文件 ignore_files: - README.md - *.js ---
-
在配置里设置
sections.{目录名}.ignore_filessections: drafts: # 忽略{content_dir}/drafts目录 ignore_files: ["*"]
静态文件
favicon.ico
在 Pelican 中,类似 favicon.ico、robots.txt、CNAME 这些不需要修改的文件我原来是放到 content/extra 目录,但在 Snow 中,content 目录下的所有文件都会视为页面文件或者页面的资源文件, 所以需要把extra目录下的文件移动到static目录下,并设置
statics: static: ignore_files: # 排除所有static下的文件,不包括子目录的文件 - "^[^/]+$" - "^images/" static/CNAME: path: "CNAME" static/robots.txt: path: "robots.txt" static/favicon.ico: path: "favicon.ico" static/README.md: path: "README.md" content/pages/css: path: "static/css"
scss/css/js
在 Python 中有一个专门处理静态文件的 webassets,在 Pelican 中也有一个插件https://github.com/pelican-plugins/webassets, 而在 Snow 中同样支持静态文件的处理, 比如编译并压缩scss文件
params.assets.css: files: - "@theme/static/scss/common.scss" - "@theme/static/scss/entry.scss" - "@theme/static/scss/entry-tree.scss" filters: - libscss: path: ["themes/snow/static/scss/"] - cssmin: output: "static/lib/css/style.min.css"
其中 filters 支持 libscss,cssmin,jsmin(js处理有些问题,不要使用, 可以使用)
然后就可以在模版里使用
{%- assets "css" %}
<link href="{{ config.site.url }}/{{ asset_url }}" rel="stylesheet">
{%- endassets %}
配置文件
Pelican 使用 pelicanconf.py, 而 Snow 使用 config.yaml
site: url: "http://127.0.0.1:8000" title: "紅楓吟" subtitle: "风落花语风落天,花落风雨花落田." language: "zh" author: "honmaple" logo_name: "楓" mode.publish: site: url: "https://honmaple.me"
主题文件
Snow 的模版系统使用的是 https://github.com/flosch/pongo2, 从 Pelican 使用的 jinja2 迁移到 pongo2 除了相关变量的修改和各种大写外,还有部分区别
-
loop: pongo2 使用的是
forloop, 计数使用的forloop.Counter, 从1开始 -
marco: pongo2 想要加载并调用文件内的函数,需要添加
export{%- macro archive_list(pages) export %} ... -
super: pongo2 使用的是
block.Super
分类功能
在 Pelican 中,可以使用 page.tags[0].url 获取标签路径,而在 Snow 中想要获取标签路径, 需要使用 get_taxonomy_url
{%- for name in page.Meta.Get("tags") %}
<a href="{{ get_taxonomy_url("tags", name) }}">{{ name }}</a>
{%- endfor %}
子分类功能
原来的子分类是用我写的一个插件实现的,使用的是 . 作为分隔,如 Category: Life.Coding, 在 Snow 中原生支持子分类, 只需要把 . 改成 /, 比如 Python/Flask 和 Python/Ansible/Jinja2 会创建如下分类系统
- Categories
- Python
- Flask
- Ansible
- Jinja2
我的博客导航栏的实现就是基于该功能
{%- set categories = get_taxonomy("categories") %}
{%- if categories %}
{%- for term in categories.Terms %}
{%- if term.Children %}
<li class="dropdown">
<a href="{{ term.Permalink }}">{{ _(term.Name) }}</a>
<ul class="dropdown-menu">
{%- for child in term.Children %}
<li><a href="{{ child.Permalink }}">{{ _(child.Name) }}</a></li>
{%- endfor %}
</ul>
</li>
{%- else %}
<li><a href="{{ term.Permalink }}">{{ _(term.Name) }}</a></li>
{%- endif %}
{%- endfor %}
{%- endif %}
搜索功能
Snow 本身没有自带搜索,但可以输出 json 文件
-
search.md首先在{content_dir}目录下新建search.md文件--- title: Search path: search.html template: search.html filter: type="posts" paginate: 0 section: true formats: json: path: "index.json" template: "search.json" ---然后在字段
formats指定格式,路径和模版 -
search.json在{theme}/templates目录下或者templates(配置文件同级目录下) 建立{{- scratch.Set("newjson", slice()) | slient }} {%- for page in pages %} {{- scratch.Add("newjson", dict("index", forloop.Counter - 1, "permalink", page.Permalink, "summary", page.Summary, "title", page.Title, "content", page.Content | striptags)) | slient }} {%- endfor %} {{- scratch.JSON("newjson") | safe }}当写入到
/index.json后就可以利用其它的搜索库比如lunr来进行搜索
加密功能
文章加密也是我不用 Hugo 的一个重要原因,我不希望使用 snow build 之前还需要使用另外的程序对内容进行一个预处理,所以在 Snow 中,我内置了一个名为 encrypt 的插件
hooks:
- encrypt
...
注册插件后就可以在内容文件里使用 encrypt 的 shortcode代码,或者在模版里使用 encrypt 函数
-
全局加密: 只要在文件头添加
passowd: xxx,hello world, 其中xxx是输入的密码,hello world是显示的描述信息 -
局部加密: 使用 shortcode 进行加密
<shortcode _name="encrypt" password="xxx" description="hello world"> ... </shortcode>
-
模版加密:
<div> {{ page.Content | encrypt:"xxx" }} </div>
知识共享署名-非商业性使用-相同方式共享4.0国际许可协议