Pelican内部机制¶
这一节描述了Pelican的内部运行机制。你会发现,Pelican的内部其实并不复杂。 :)
你可以在 Pelican的一些历史 一节中找到原作者用软件设计相关内容报告的节选。
总体结构¶
Pelican做的事情其实很简单:获取一个文件列表,并将它们处理为某种输出。通常,输入文件是reStructuredText和Markdown文件,输出是一个博客,但事实上输入和输出都可以是你想要的任何内容。
系统的整体逻辑可以分为几个不同的类和概念:
Writers 负责完成 html、RSS订阅源等等内容的文件写入。因为这些操作都是比较常用的,这个类只会被创建一次,然后再传给Generators。
Readers 用于读取不同格式的文件(目前支持HTML、Markdown、reStructuredText,但可以继续扩展)。向**Readers**输入一个文件,它会返回文档的元数据(作者、标签、分类等等)与HTML格式的文档正文内容。
Generators 用以生成不同的输出,Pelican自带了
ArticlesGenerator和PageGenerator。给定一套配置信息, Generators 可以做几乎任何事。但大多数情况下,它的工作就是从输入生成文件。Pelican使用了模板引擎,因此可以较为简单地编写自定义主题。模板语法使用的是易于学习的 Jinja2 ,因此快去构建你自己的主题吧。
如何实现一个新的reader?¶
若是希望为Pelican添加一个标记语言,只需要创建一个类,实现 read 方法,并在其中返回元数据和以HTML表示的正文内容。
可以看一看Markdown的reader:
from pelican.readers import BaseReader
from pelican.utils import pelican_open
from markdown import Markdown
class MarkdownReader(BaseReader):
enabled = True
def read(self, source_path):
"""Parse content and metadata of markdown files"""
with pelican_open(source_path) as text:
md_extensions = {'markdown.extensions.meta': {},
'markdown.extensions.codehilite': {}}
md = Markdown(extensions=md_extensions.keys(),
extension_configs=md_extensions)
content = md.convert(text)
metadata = {}
for name, value in md.Meta.items():
name = name.lower()
meta = self.process_metadata(name, value[0])
metadata[name] = meta
return content, metadata
是不是很简单呢?
如果新创建的reader需要额外的Python依赖,应该把 import 放在 try...except 块中。在reader类中,设置类属性 enabled 来标记import是否成功。这使得用户能继续使用他们喜欢的标记语言而无需安装用不到的模块。
如何实现一个新的generator?¶
generator有两个重要方法。不一定两个都要创建,若只创建了一个,就会自动调用存在的方法。
generate_context会优先被调用,其中可以完成任何你想要做的事,如果需要的话,还要更新全局上下文。全局上下文会在所有generator间共享,并在之后传给模板。例如PageGenerator的generate_context方法会找寻所有页面,并将他们转换为对象,再将上下文传入其中。注意,请 不要 在此阶段使用该上下文输出任何内容,因为其他generator还会继续影响上下文。generate_output会在generate_context之后被调用,用于生成要输出的内容。此时就需要使用上下文并调用writer对象的方法,此writer就是传入generate_output方法的第一个参数。PageGenerator的generate_output方法中,会使用writer的write_file方法为全局上下文中的每一个页面输出一个文件。