插件

从3.0版开始,Pelican支持插件。插件是一种向Pelican添加特性而不必直接修改Pelican核心的方法。

如何使用插件

从4.5版开始,Pelican迁移到了一个新的插件结构中,利用命名空间包,可以很容易地通过 Pip. 支持此结构的插件将安装在命名空间包下 pelican.plugins 它可以被鹈鹕自动发现。要查看在您的环境中处于活动状态的Pip安装的命名空间插件的列表,请运行:

pelican-plugins

如果你离开 PLUGINS 设置为默认值 (None ),Pelican将自动发现命名空间插件并注册它们。另一方面,如果指定 PLUGINS 设置为插件列表,此自动发现将被禁用。此时,只注册您指定的插件,并且您必须显式列出任何命名空间插件。

如果您正在使用 PLUGINS 设置时,可以用两种方式指定插件。第一个方法将插件指定为字符串列表。命名空间插件可以通过其全名指定 (pelican.plugins.myplugin )或者他们的简称 (myplugin ):

PLUGINS = ['package.myplugin',
           'namespace_plugin1',
           'pelican.plugins.namespace_plugin2']

或者,您可以将它们导入设置文件并传递模块:

from package import myplugin
from pelican.plugins import namespace_plugin1, namespace_plugin2
PLUGINS = [myplugin, namespace_plugin1, namespace_plugin2]

注解

当尝试使用不同的插件(尤其是那些处理元数据和内容的插件)时,缓存可能会产生干扰,并且更改可能不可见。在这种情况下,使用禁用缓存 LOAD_CONTENT_CACHE = False 或者使用 --ignore-cache 命令行开关。

如果插件不在可导入路径中,则可以通过 PLUGIN_PATHS 设置。如以下示例所示,中的路径 PLUGIN_PATHS 列表可以是绝对的,也可以是相对于设置文件的:

PLUGIN_PATHS = ["plugins", "/srv/pelican/plugins"]
PLUGINS = ["assets", "liquid_tags", "sitemap"]

在哪里可以找到插件

命名空间插件可以在 pelican-plugins organization 作为单独的存储库。旧插件位于 pelican-plugins repository 并将逐步淘汰,取而代之的是命名空间版本。

请注意,虽然我们尽力检查和维护这些插件,但它们是由Pelican社区提交的,因此可能具有不同级别的支持和互操作性。

如何创建插件

插件基于信号的概念。鹈鹕发送信号,插件订阅这些信号。可用信号列表将在后续章节中记录。

插件要遵循的唯一规则是定义 register 可调用的,其中你可以将信号映射到你的插件逻辑。举个简单的例子:

import logging

from pelican import signals

log = logging.getLogger(__name__)

def test(sender):
    log.debug("%s initialized !!", sender)

def register():
    signals.initialized.connect(test)

注解

信号接收器被弱引用,因此不能在 register 否则它们将在信号发出之前被垃圾回收。

如果多个插件连接到同一信号,则无法保证或控制插件的执行顺序。这是继承自 Blinker, 鹈鹕用来实现信号的依赖关系。

命名空间插件结构

命名空间插件必须遵循特定的结构才能正常工作。它们需要是可安装的(即包含 setup.py 或等效文件)并具有如下文件夹结构:

myplugin
├── pelican
│   └── plugins
│       └── myplugin
│           ├── __init__.py
│           └── ...
├── ...
└── setup.py

至关重要的是 pelicanpelican/plugins 文件夹 not 包含一个 __init__.py 文件。事实上,除了上述结构中列出的文件夹之外,最好将这些文件夹清空,并将与插件相关的文件单独包含在 pelican/plugins/myplugin 文件夹以避免任何问题。

为了方便地设置适当的结构,a cookiecutter template for plugins 提供。有关如何使用它的说明,请参阅该项目的自述文件。

信号一览表

以下是当前实施的信号列表:

信号

争论

描述

已初始化

Pelican物体

定稿

Pelican物体

在执行所有生成器之后,在pelican退出之前调用,这对于自定义后处理操作非常有用,例如:-缩小js/css资产。-使用更新的网站地图通知/ping搜索引擎。

generator_init

生成器

在中调用 Generator.__init__

all_generators_finalized

生成器

在执行所有生成器之后和写入输出之前调用

readers_init

读者

在中调用 Readers.__init__

article_generator_context

项目生成器,元数据

article_generator_preread

article_generator

在读入文章之前调用ArticlesGenerator.generate_上下文;如果代码需要在解析每个项目之前执行某些操作,则使用

article_generator_init

article_generator

在中调用 ArticlesGenerator.__init__

article_generator_pretaxonomy

article_generator

在创建类别和标记列表之前调用,当修改要生成的项目列表以便删除的项目不会在类别或标记中泄漏时非常有用

article_generator_finalized

article_generator

在结束时调用ArticlesGenerator.generate_上下文

article_generator_write_article

文章生成器,内容

在编写每个文章之前调用,文章作为内容传递

article_writer_finalized

文章生成器,作者

在编写完所有文章和相关页面之后,但在关闭项目生成器之前调用。

get_generators

Pelican物体

在中调用Pelican.get_generator_类,可以返回一个生成器,或元组或列表中的多个生成器。

get_writer

Pelican物体

在中调用Pelican。get嫒作家,可以返回自定义写入程序。

page_generator_context

页面生成器,元数据

page_generator_preread

page_generator

在读入页之前调用PageGenerator.generate_上下文;如果代码需要在解析每个页面之前执行某些操作,则使用。

page_generator_init

page_generator

在中调用 PagesGenerator.__init__

page_generator_finalized

page_generator

在结束时调用PagesGenerator.generate_上下文

page_generator_write_page

页面生成器,内容

在编写每个页面之前调用,页面作为内容传递

page_writer_finalized

page_生成器,作者

在写入所有页之后,但在页生成器关闭之前调用。

static_generator_context

静态_生成器,元数据

static_generator_preread

static_generator

在读入静态文件之前调用StaticGenerator.generate_上下文;如果代码需要在将每个静态文件添加到staticfiles列表之前执行某些操作,则使用。

static_generator_init

static_generator

在中调用 StaticGenerator.__init__

static_generator_finalized

static_generator

在结束时调用StaticGenerator.generate_上下文

content_object_init

content_object

在结束时调用 Content.__init__

content_written

路径,上下文

每次写入内容文件时调用。

feed_generated

上下文,提要

每次生成提要时调用。可用于在写入提要对象之前对其进行修改。

feed_written

路径、上下文、提要

每次写入提要文件时调用。

警告

避免 content_object_init 如果你想读就发信号 summarycontent 内容对象的属性。可能导致无法解决的链接 链接到内部内容 (见 pelican-plugins bug #314 )使用 _summary_content 属性,或者在以后运行插件(例如。 all_generators_finalized

注解

Pelican3.2之后,信号名称被标准化。旧插件可能需要更新才能使用新名称:

旧名

新名称

article_generate_context

article_generator_context

article_generate_finalized

article_generator_finalized

article_generate_preread

article_generator_preread

pages_generate_context

page_generator_context

pages_generate_preread

page_generator_preread

pages_generator_finalized

page_generator_finalized

pages_generator_init

page_generator_init

static_generate_context

static_generator_context

static_generate_preread

static_generator_preread

食谱

我们最终意识到创建插件的一些方法最好在文档中的某个地方共享,所以它们就在这里!

如何创建新的阅读器

您可能希望添加对自己的输入格式的支持。虽然在Pelican core中添加这个特性是有意义的,但是我们明智地选择了避免这种情况,而是通过插件定义不同的阅读器。

这种选择背后的基本原理主要是插件确实很容易编写,并且当插件不活动时不会减慢Pelican本身的速度。

别再说了-这里有个例子:

from pelican import signals
from pelican.readers import BaseReader

# Create a new reader class, inheriting from the pelican.reader.BaseReader
class NewReader(BaseReader):
    enabled = True  # Yeah, you probably want that :-)

    # The list of file extensions you want this reader to match with.
    # If multiple readers were to use the same extension, the latest will
    # win (so the one you're defining here, most probably).
    file_extensions = ['yeah']

    # You need to have a read method, which takes a filename and returns
    # some content and the associated metadata.
    def read(self, filename):
        metadata = {'title': 'Oh yeah',
                    'category': 'Foo',
                    'date': '2012-12-01'}

        parsed = {}
        for key, value in metadata.items():
            parsed[key] = self.process_metadata(key, value)

        return "Some content", parsed

def add_reader(readers):
    readers.reader_classes['yeah'] = NewReader

# This is how pelican works.
def register():
    signals.readers_init.connect(add_reader)

添加新生成器

添加一个新的生成器也非常容易。你可能想看看 Pelican内部构件 有关如何创建自己的生成器的详细信息。

def get_generators(pelican_object):
    # define a new generator here if you need to
    return MyGenerator

def register():
    signals.get_generators.connect(get_generators)