Pelican的一些历史

警告

此页面来自原作者(AlexisMétaireau)在2010年12月编写Pelican后撰写的报告。 这些信息可能不是最新的。

Pelican是一个简单的静态博客生成器。 它解析标记语言文件(目前支持Markdown和reStructuredText),然后生成包含所有相关文件的HTML文件夹。 我选择使用Python来实现Pelican,因为它似乎很简单并且符合我的需求。 我不想为每件事定义一个类,但仍然想让它们之间能松散耦合。事实证明,这正是我想要的。 感谢一些用户不时的反馈,我能花较少的时间来修复它。 到目前为止,我已经将Pelican代码重构了两次;每次花费不到30分钟。

用例

我之前使用的是WordPress,一种可以在Web服务器上托管的来管理你的博客的解决方案。 大多数时候,我更喜欢使用Markdown或reStructuredText等标记语言来写文章。 所以我写文章都是用vim。 我认为能够让人们选择他们偏好的工具来写文章很重要。 在我看来,一个博客管理系统应该允许你采取任何形式的输入并能将其转换为博客。 这就是Pelican所做的。 你可以使用你想用的工具和标记语言编写文章,然后生成静态HTML博客。

https://docs.getpelican.com/en/stable/_images/overall.png

为了足够灵活,Pelican支持模板,因此你可以根据需要轻松编写自己的主题。

设计过程

Pelican来自我的需要。 我首先创建了一个文件应用程序,然后使它不断成长,成长为支持它现在能做的事情。 要开始,我写了一篇关于我想做什么的文档。然后,我写了点要用来解析的内容(reStructuredText文件) 并开始尝试编写相应代码。 Pelican第一次可用时代码只有200行,其中包含大约10个函数和一个类。

我一直面临不同的问题,而且在使用Pelican时一直想给它添加功能。 我做的第一个更改是添加支持设置文件。虽然可以用选项参数传递给命令行来设置,但如果选项有很多时,这种方式会变得很乏味。 同样,随着时间的推移我陆续添加了支持其他不同内容:Atom订阅源,多主题,多种标记语言支持等。 在某些时候,似乎“只有一个文件”的口头禅对于Pelican来说还不够好, 所以 我决定重做一切,并将其拆分为多个不同的文件。

我已经将逻辑分离到不同的类和概念中:

  • Writers 负责文件的所有写入过程。它负责编写文件: .html文件, RSS源等。由于这些操作很常用,因此对象创建一次后将传递给生成器Generators。
  • Readers 用于读取各种格式 (目前是Markdown 和 reStructuredText格式,不过系统是可扩展的)。 给定一个文件,它们返回元数据(作者,标签,分类等)和内容(以HTML格式)。
  • Generators 生成不同的输出。例如,Pelican附带 ArticlesGeneratorPageGenerator 。 给定配置,它们可以做任何你想它们做的事情。大多数情况下,它们是根据输入的内容生成文件。

我还处理内容对象。这些对象可以是文章 Articles ,page页 Pages ,引用 Quotes 或任何你想要的东西。 它们在 contents.py 模块中定义,代表程序要使用的某些内容。

更多细节

下面是 Pelican 中涉及的类的概述。

https://docs.getpelican.com/en/stable/_images/uml.jpg

上面界面其实并不存在,我添加它只是为了澄清整个架构。我是使用鸭子类型的风格来写的,不是基于接口的形式。

在内部,遵循以下过程:

  • 首先,解析命令行,并使用用户的一些内容初始化不同的生成器对象
  • 创建一个上下文 context 。 它包含命令行中的设置和设置文件(如果提供有)。
  • 调用每个生成器的 generate_context 方法,更新上下文。
  • 编写器被创建并被赋予每个生成器的 generate_output 方法。

我进行了两次调用,因为当生成器生成输出时,上下文不会改变是很重要的。 换句话说,第一种方法 generate_context 应该修改上下文,而第二种 generate_output 方法则不应该。

然后,由生成器在 generate_contextgenerate_content 方法中执行所需的操作。 参考一下 ArticlesGenerator 类将有助于理解其他一些概念。 以下是调用 generate_context 方法时发生的事:

  • 读取文件夹 “path” ,查找reStructuredText文件,加载每个文件,然后用它构造一个内容对象( Article )。 这些功能用 Reader 对象实现。
  • 用所有这些文章更新 context

然后, generate_content 方法使用 contextwriter 来生成想要的输出。