起因
本站的内容起初是使用Markdown编写的,在样式表中给p元素添加了首行缩进。文本转译成.html后,原本独立的img元素被包裹在p标签中。
这就导致:不符合语义;移动端显示时,图片因缩进,而溢出屏幕边界。
经过
解决方法不外乎:1、在文本中插入一个div元素;2、使用新的文本标记语言。
因为插入div元素不能彻底解决问题,所以将Markdown替换成reStructuredText(被用于编写Python文档)。reStructuredText可以通过include指令引用外部文档(如:代码片段),达到去除冗余的目的。
接下来,要做的只是:编写一个Jekyll Converters插件,通过管道调用外部的Python脚本,将文本由.rst格式转换成.html格式。
Docutils源码中提供了相应的工具:rst2html5.py脚本,但这个转换脚本将输出一个带有head部分的.html文本。publish_cmdline函数位于docutils目录下的core.py文件中,此文件内包含有一个Publisher类和多个以“publish”开头的函数。
通过阅读文档字符串,可以看到publish_parts函数返回:a dictionary of document parts(pub.writer.parts)。pub对象,又是通过调用publish_programmatically函数——实例化Publisher类——产生的。
查看docutils/writers目录下的_html_base.py文件,可以获悉一个.html文本究竟是由哪几部分构成:
visitor_attributes = (
'head_prefix', 'head', 'stylesheet', 'body_prefix',
'body_pre_docinfo', 'docinfo', 'body', 'body_suffix',
'title', 'subtitle', 'header', 'footer', 'meta', 'fragment',
'html_prolog', 'html_head', 'html_title', 'html_subtitle',
'html_body')
于是乎,我们可以编写出如下的.rst to .html转换函数:
settings = {'syntax_highlight': 'short',
'initial_header_level': 2,
'raw_enabled': False, }
def converter(source, part="html_body"):
parts = publish_parts(
source,
writer_name='html5',
settings_overrides=settings)
return parts.get(part, '')
Dracula for Pygments,请将样式表中的highlight类替换成code类。
结果
在Jekyll项目的_plugins/rst2html目录下,编写插件converter.rb和rst2html5.py。
converter.rb,代码如下:
module Jekyll
class RstConverter < Converter
safe true
priority :low
def matches(ext)
ext =~ /rst/i
end
def output_ext(ext)
".html"
end
def convert(content)
IO.popen("python #{File.expand_path(File.dirname(__FILE__))}/rst2html5.py", 'r+') do |pipe|
pipe.puts(content)
pipe.close_write
result = pipe.read
pipe.close_read
result
end
end
end
module Filters
def rst(input)
site = @context.registers[:site]
converter = site.find_converter_instance(::Jekyll::Converters::RstConverter)
converter.convert(input)
end
end
end
rst2html5.py,代码如下:
try:
import locale # module missing in Jython
locale.setlocale(locale.LC_ALL, '')
except locale.Error:
pass
import sys
from docutils.core import publish_parts
settings = {'syntax_highlight': 'short',
'initial_header_level': 2,
'raw_enabled': False, }
def converter(source, part="html_body"):
parts = publish_parts(
source,
writer_name='html5',
settings_overrides=settings)
return parts.get(part, '')
if __name__ == "__main__":
sys.stdout.write(converter(sys.stdin.read()))