天,请注意时效性前言
之前搞了个 博客自动化流程,及后来的 2022 博客自动化流程 但是总的来说,还有以下痛点:
-
从 Github CI 上传从 Craft 拉的图片到腾讯云经常会遇到网络错误,流程不可控。
-
博客中图片传到腾讯云的时候,都被强制转为
png
,但是其实应该支持更多格式如gif
。 -
Craft 转 Markdown 的结果,有很多与标准 Markdown 不同的地方,如:
-
不支持嵌套列表。
-
引用块内嵌套列表的时候,渲染结果列表居然在外层。
-
Craft 的 「焦点」(block)和「块」(focus)只有后者被识别成 blockquote (引用块),预期应该是二者都是。
-
Craft 中的 bookmark 信息量很多,如页面描述、页面 title等,但是转成 Markdown 的之后,仅剩下一个段落中包裹着链接,相当于信息丢失了。
-
Craft 中图片本身就不支持图片说明。
-
Craft 生成的代码块,并不会自动在反引号之后添加语言,导致一些语言被识别为了
plaintext
没有高亮。
-
于是本次优化针对这些痛点,又又又又进行了改造。
优化一:使用自己的 CraftBlockToMarkdown 函数
因为给 Craft 反馈了他们的 craft.markdown.craftBlockToMarkdown
无法正确转换的问题:
但是官方似乎丝毫没有要解决的意思,于是自己写了一个简单的函数用来手动转换:
需要注意的是,该函数因为是自己用来适配 Jekyll 的来进行下一步处理的(见下面的优化三),因此特殊处理了 imageBlock
和 urlBlock
类型的 Block:
此函数已经被我放到官方插件开发者论坛了,欢迎交流:
优化二:将 Github CI 流程挪到本地
之前的流程,点击插件的发布按钮(当然,需要先填写 GitHub Token、填写 COS 等相关信息才行),然后等着就可以了。
本次优化,为了保持与之前流程的一致,于是又写了个 Craft 插件,点击后会获取文档内容,简单处理后(如获取 header-img 的图片版权信息到 meta 中),会调用特定链接,链接参数带上文档信息:
1
craft.editorApi.openURL(`xhelper://${btoa(unescape(encodeURIComponent(content)))}`)
而这个特定链接的作用,就是调用 Apple Script 写的 Application,置于如何写一个 Application 应用和如何响应链接调用,可以看我写的 这篇文档,里面会调用 node,执行的其实也是之前放到 Github CI 执行的代码,这里放一个简单的截图:
效果:
之前的流程因为我贪图简单,加上 Craft 上传的图片不一定都有后缀(如通过拖拽、图片上传等方式上传的图片,则有后缀,若通过复制粘贴来的或者 Web 上传的图片,则无后缀),于是我将所有图片都转成了 png
格式,本次我移除了这个逻辑,先判断如果自身带后缀则使用其后缀;如果没有后缀,则再将其强制转为 png
,推荐使用 Sharp
这个库,非~常~好~用~:
所以…上 Gif!
注:之前贪图方便(不用鉴权、不用固定 ip 的服务器),用了 微信云托管,还顺便实现了将摘要往微信公众号发送的逻辑。但是坑爹的是,这个服务器仅仅是我为了方便发布公众号而弄的,但是按我性子一般三个月就用一次,每次用的时候还是冷启动(它服务器默认 30 分钟无请求进来自动关闭实例,因为他们是按实例运行时间计费的),会经常性的失败,有这排查的功夫我都自己都复制粘贴文档到微信公众号的编辑器了。所以,我放弃了微信公众号,手动粘贴…也挺好!
优化三:实现 Craft 中的 Bookmark 和图片 Caption
能在基于 Jekyll 的博客系统来实现这个效果是因为我并没有直接用 Github 的 Jekyll 服务,而是自己用 Jekyll build 成 HTML 后,再 push 到仓库中实现的,原因及过程见 这里。
实现 Bookmark和图片 Caption 是利用了上一步生成的 Markdown 中含有的特殊 Jekyll 标签,配合自定义的 Jekyll 插件实现的,渲染 Bookmark 就用 render_bookmark
,渲染图片 caption 用 render_caption
实现(用了刚学了两小时的 ruby 脚本语言):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
module Jekyll
class RenderBookMarkBlock < Liquid::Block
def initialize(tag_name, attr, tokens)
super
attrs = attr.scan(/url\=\"(.*)\"\stitle\=\"(.*)\"\simg\=\"(.*)\"/)
@url = attrs[0][0]
@title = attrs[0][1]
@img = attrs[0][2]
@error = ""
end
def render(context)
@desc = super
"<p><a class='link-bookmark' href='#{@url}'><span><img src='#{@img}'/></span><span><span>#{@title}</span><span>#{@desc}</span><span>#{@url}</span></span></a></p>"
end
end
end
module Jekyll
class RenderImageCaptionBlock < Liquid::Block
def initialize(tag_name, attr, tokens)
super
attrs = attr.scan(/caption\=\"(.*)\"\simg\=\"(.*)\"/)
@caption = attrs[0][0]
@img = attrs[0][1]
end
def render(context)
text = super
"<p caption='#{@caption}'><img src='#{@img}' alt='#{@caption}' title='#{@caption}' /></p>"
end
end
end
Liquid::Template.register_tag('render_caption', Jekyll::RenderImageCaptionBlock)
Liquid::Template.register_tag('render_bookmark', Jekyll::RenderBookMarkBlock)
Jekyll 使用插件非常简单,在根目录新建一个 _plugins
目录,将用ruby
写的 Jekyll 插件放进去即可在 Jekyll Build 的时候加载该插件。
其他细节
之前的内容算是标准 Markdown 生成的 HTML,因此一些 RSS 阅读器抓取内容后格式良好,但是本次优化加了个 Bookmark 之后,RSS 格式就乱了(截图来自 Reeder 5):
于是又写了个 ruby 插件,过滤该标签,将其转成普通的 HTML 链接:
1
2
3
4
5
6
7
8
9
module Jekyll
module BookmarkFilter
def bookmark_filter(input)
input.gsub(/^\<p\>\<a\s+class=\"link-bookmark\"\shref=(.*)\starget=\"_blank\"\>\<span\>(.*)\<\/span\>\<span\>\<span\>(.*)\<\/span\>\<span\>\n(.*)\n\<\/span\>\<span\>(.*)\<\/span\>\<\/span\>\<\/a\>\<\/p\>$/, '<p><a href=\1 target="_blank">\4</a></p>');
end
end
end
Liquid::Template.register_filter(Jekyll::BookmarkFilter)
然后再在 feed.xml 中使用即可: post.content | bookmark_filter
。
欢迎交流!