创作内容

文章和页面

Pelican将“文章”(article)视为有时间顺序的内容,例如博客上的博文就是文章。

“页面”(page)指的是不经常改变的内容,例如“关于”“联系我们”这样的。

在代码仓库的 samples/content/ 文件夹下有一些内容示例供您查看。(译者注:原文档中还有post与content的说法,一般既指代文章又指代页面,后文统一将其翻译为推文)

文件元数据

Pelican可以从文件系统中自动地获取一些信息(例如文章的分类),但是有些信息需要您以元数据的形式在文件中提供。

如果您用reStructuredText的格式进行内容创作,您可以按照下面的语法在文本文件中提供元数据(请给文本文件加上 .rst 后缀):

My super title
##############

:date: 2010-10-03 10:20
:modified: 2010-10-04 18:40
:tags: thats, awesome
:category: yeah
:slug: my-super-post
:authors: Alexis Metaireau, Conan Doyle
:summary: Short version for index and feeds

如果有多个作者或多个文章标签,需要将他们以分号分隔,这样就可以在作者或标签中使用逗号了:

:tags: pelican, publishing tool; pelican, bird
:authors: Metaireau, Alexis; Doyle, Conan

Pelican在reStructuredText上实现了 abbr HTML标签的使用支持。在正文部分按照下面的形式书写即可。

This will be turned into :abbr:`HTML (HyperText Markup Language)`.

Pelican同时也支持Markdown语法(文件的扩展名需要为 .md.markdown.mkd.mdown )要让Pelican进行Markdown的生成,需要先通过 pip install Markdown 安装 Python-Markdown

Pelican同样支持 Markdown扩展 ,可以是 Markdown 包自带的扩展,也可以是另外安装的,可以通过 MARKDOWN 配置项管理这些扩展。

Markdown中的元数据语法需要按照下面的格式书写:

Title: My super title
Date: 2010-12-03 10:20
Modified: 2010-12-05 19:30
Category: Python
Tags: pelican, publishing
Slug: my-super-post
Authors: Alexis Metaireau, Conan Doyle
Summary: Short version for index and feeds

This is the content of my super blog post.

您也可以定义自己的元数据类型(只要和保留的元数据关键字不冲突),这些自定义的元数据关键字可以用在自定义的模板中。下面的列出了所有保留的元数据关键字。

元数据类型

描述

title

文章或页面的标题

date

发布日期(需要以 YYYY-MM-DD HH:SS 的格式)

modified

最后修改日期(需要以 YYYY-MM-DD HH:SS 的格式)

tags

推文标签,以逗号分隔

keywords

推文关键字,以逗号分隔(只能在HTML内容中使用)

category

推文分类(只能归属到一个分类中,不支持多个)

slug

URL和翻译的唯一标识符

author

当只有一个作者时可以使用这个元数据

authors

当有多个作者时需要使用这个元数据

summary

简短的推文概要,会显示在首页上

lang

推文所用语言的ID(例如 enfrzh-cn 等)

translation

手动指定当前内容是否是某个翻译版本(该元数据的值只能是 truefalse

status

推文的状态: drafthiddenskippublished

template

用于指定要使用的生成模板,只需要写模板的名字,不需要模板文件的后缀名

save_as

将内容保存到指定的相对文件路径

url

指定本篇文章或页面要使用的URL

对其他格式的支持(例如 AsciiDoc )可以通过插件实现,在 Pelican插件 集中可以查看所有插件。当然,在老的 pelican-plugins 仓库中也可以查看。

Pelican还能处理后缀名为 .html.htm 的HTML文件Pelican在解释转换HTML文件时用的方法非常直接,会从 meta HTML标签中获取元数据信息,从 title HTML标签中获取标题,从 body 标签中获取文章的正文内容:

<html>
    <head>
        <title>My super title</title>
        <meta name="tags" content="thats, awesome" />
        <meta name="date" content="2012-07-09 22:28" />
        <meta name="modified" content="2012-07-10 20:14" />
        <meta name="category" content="yeah" />
        <meta name="authors" content="Alexis Métaireau, Conan Doyle" />
        <meta name="summary" content="Short version for index and feeds" />
    </head>
    <body>
        This is the content of my super blog post.
    </body>
</html>

当使用HTML文件时,上述的众多元数据中有一个比较特殊的存在——tags。这个元数据在HTML文档中有两种方式可以指定,一种是Pelican中定义的 tags (上面的例子中用的就是这种);另一种是使用HTML中定义的 keywords (即将name属性的“tags”换成“keywords”)。

需要注意的是,除了title外,其他所有元数据都是可以缺省的。若未指定日期元数据并且将 DEFAULT_DATE 设为了 'fs',Pelican就会从文件的 “mtime” 时间戳中获取日期信息;文件所在目录的名称会被作为category。例如 python/foobar/myfoobar.rst 的category元数据值就会被设为 foobar 。如果您不希望子目录的名称成为category的值,则需要在设置中将 USE_FOLDER_AS_CATEGORY 设为 False 。进行日期元数据的解析时,Pelican支持W3C的 suggested subset ISO 8601 标准。

总而言之,标题是唯一必须指定的元数据。如果您甚至懒得写标题,也不用担心,Pelican会自动将文件名作为内容的标题。例如,Markdown源文件 Publishing via Pelican.md 的标题会自动设为 Publishing via Pelican。如果您希望启用这个特性,请在设置文件中添加下面这么一行:

FILENAME_METADATA = '(?P<title>.*)'

备注

在您尝试不同的设置时(特别是在设置元数据时),缓存可能会对您造成干扰,导致设置更改不起作用。若您遇到了这种问题,可以在配置文件中加上 LOAD_CONTENT_CACHE = False ,或是在使用命令行生成站点时加上 --ignore-cache 参数。

modified 元数据中应该为文章最后一次的修改时间,若没有指定,会自动与 date 保持一致。在您修改文章并将 modified 设为当前日期后,除了在模板中显示 modified 之外,feed阅读器中的feed条目也会自动更新。

authors 元数据中是文章作者的列表,各个作者之间用逗号分隔。若只有一个作者,可以使用 author

若您没有显式地指定summary元数据,Pelican会自动从推文开头截取 SUMMARY_MAX_LENGTH 指定长度的内容作为summary。另外,您也可以使用配置项 SUMMARY_MAX_PARAGRAPHS 指定推文开头前N段内容作为summary。若同时指定了这两个配置项,首先会考虑 SUMMARY_MAX_PARAGRAPHS ,若前N段的总长度超过 SUMMARY_MAX_LENGTH ,还是会按照 SUMMARY_MAX_LENGTH 进行截断。

您可以通过 FILENAME_METADATA 设置来使用正则表达式从文件名中提取元数据。正则匹配到的每个命名分组都被看成一个元数据。预设的 FILENAME_METADATA 只会从文件名中提取date和slug。例如,可以使用 '(?P<date>\d{4}-\d{2}-\d{2})_(?P<slug>.*)' 提取date和slug。

请注意,您在推文中直接指定的元数据的优先级是大于从文件名中提取的。

页面

如果您在content文件夹下创建了一个 pages 文件夹,那么Pelican会为其中的每个文件生成一个例如 关于联系我们 这样的静态页面。(具体可以看下面项目文件组织的例子)

您可以通过 DISPLAY_PAGES_ON_MENU 设置来决定页面是否被列在主导航菜单中(默认值为 True )。

如果您希望让某些页面不会被链接并且也不列在任何菜单中,可以为它加上元数据属性 status: hidden 。这在将错误页面适配到所用主题时很有用。

静态内容

静态文件与文章、页面不同,会原模原样地复制到输出文件夹中。当然,您也通过设置 STATIC_PATHS 更改复制时的目标文件夹。Pelican的默认配置中只包含了 images 一个文件夹,其他的需要手动添加。另外静态文件也包含那些被显式链接的(详见后文)。

备注

在默认配置下,所有后缀名有效的文件( .html.rst.md , ...)都会由文章/页面生成器处理,这是在静态文件处理之前完成的。若这些文件中的某一些是静态文件,可以合理使用 *_EXCLUDE 配置项将他们排除(例如 ARTICLE_EXCLUDESPAGE_EXCLUDES)。

在同一个目录下存放不同类型的内容

从Pelican 3.5开始,静态文件就可以和页面源文件安全地放在同一目录下了。这些包含了不同类型内容文件的目录需要添加到 STATIC_PATHSPAGE_PATHS 中(或者 STATIC_PATHSARTICLE_PATHS 中)。Pelican会正常地识别和处理文章和页面源文件,然后再把静态文件复制,和处理处于单独一个文件夹的静态文件行为一致。

请注意:Pelican不保证放在同一个源目录下的静态文件和内容文件在站点生成完后最终出现在同一个地方。要让他们出现在一个地方,可以使用 {attach} 链接语法(下面会提到)。此外,还可以通过设置 STATIC_SAVE_ASPAGE_SAVE_ASARTICLE_SAVE_AS (还有相应的 *_URL 设置)让不同类型的文件最终放在一起。

内部链接

从Pelican 3.1开始,站内链接可以在 源文件 层次下指定,而不是只能在 生成后的站点 层次下指定。当需要在当前推文链接到邻近位置的内容时,可以直接从源内容文件的位置开始链接(而不需要考虑在站点生成后文件会被放在哪儿)。

要链接到站内(即在 content 目录下的文件),使用下述的目标链接语法: {filename}path/to/file 。注意,在所有操作系统(当然也包括Windows)上,路径的分隔符都要使用正斜杠 /

例如,某Pelican项目的文件结构组织如下:

website/
├── content
│   ├── category/
│   │   └── article1.rst
│   ├── article2.md
│   └── pages
│       └── about.md
└── pelican.conf.py

在这个例子中, article1.rst 的内容如下:

The first article
#################

:date: 2012-12-01 10:02

See below intra-site link examples in reStructuredText format.

`a link relative to the current file <{filename}../article2.md>`_
`a link relative to the content root <{filename}/article2.md>`_

article2.md 的内容如下:

Title: The second article
Date: 2012-12-01 10:02

See below intra-site link examples in Markdown format.

[a link relative to the current file]({filename}category/article1.rst)
[a link relative to the content root]({filename}/category/article1.rst)

链接到静态文件

您可以通过 {static}path/to/file 链接到静态内容。使用这个指令链接的文件都会被自动复制到输出目录中,即使它没有包含在 STATIC_PATHS 中。

例如,某Pelican项目的文件结构组织如下:

content
├── images
│   └── han.jpg
├── pdfs
│   └── menu.pdf
└── pages
    └── test.md

test.md 的文件内容如下:

![Alt Text]({static}/images/han.jpg)
[Our Menu]({static}/pdfs/menu.pdf)

站点生成时会将 han.jpg 拷贝到 output/images/han.jpg 、将 menu.pdf 拷贝到 output/pdfs/menu.pdf ,同时也会自动把 test.md 中的相关链接都替换为正确的。

如果您使用 {static} 链接到文章或页面,会链接到他们的源文件而不是渲染后的文章或页面。

将静态文件作为附件

从Pelican 3.5开始,静态文件可以使用下述语法 “附” 在页面或文章上: {attach}path/to/file 。这和 {static} 语法很像,也会将静态文件重定位到文章或页面的对应输出目录中。当推文所链接的静态文件处于其源文件所在位置的子目录下时,这种父子关系在输出目录中会得以保留。否则,默认情况下,静态文件会和对应的文档输出到同一目录层级下。

这只在链接到静态文件时起作用。

例如,某Pelican项目的文件结构组织如下:

content
├── blog
│   ├── icons
│   │   └── icon.png
│   ├── photo.jpg
│   └── testpost.md
└── downloads
    └── archive.zip

例如对于某设置文件 pelicanconf.py

PATH = 'content'
ARTICLE_PATHS = ['blog']
ARTICLE_SAVE_AS = '{date:%Y}/{slug}.html'
ARTICLE_URL = '{date:%Y}/{slug}.html'

testpost.md 的内容如下:

Title: Test Post
Category: test
Date: 2014-10-31

![Icon]({attach}icons/icon.png)
![Photo]({attach}photo.jpg)
[Downloadable File]({attach}/downloads/archive.zip)

对应生成输出的站点目录结构如下:

output
└── 2014
    ├── archive.zip
    ├── icons
    │   └── icon.png
    ├── photo.jpg
    └── test-post.html

可以注意到,使用 {attach} 链接的文件要么和文章输出处于同级目录,要么就是在文章所在位置的子目录下。

若一个静态文件被多次链接, {attach} 只会在该静态文件第一次被链接时进行重定位处理(即按照上面的规则复制到对应目录)。之后使用 {attach} 进行的链接的效果就和 {static} 一模一样了。这样子就可以避免破坏已经生成好的链接。

当同一文件被多个推文链接时需要尤其小心: 第一次链接到文件时,Pelican就会确定其最终位置,而Pelican处理推文的顺序是不能确定的,因此多个推文使用 {attach} 链接到同一文件时,每一次站点生成后该文件的最终位置是无法确定的(这种情况发生与否取决于操作系统、文件系统、Pelican的版本、推文从项目中的添加修改移除)。当这种情况发生时,其他站点到本站点文件旧位置的链接就会损坏。因此,只有当静态文件只被一篇推文链接,或链接到某静态文件的推文都在同一目录下时才使用 {attach}。在这种情况下,该文件的输出位置在站点构建中不会变化。如果无法保证上述条件来预防链接损坏,可以考虑使用 {static} 来替换 {attach} 。如此,文件的最终位置就由 STATIC_SAVE_ASSTATIC_URL 来决定。(每个文件的 save_asurl 仍然可以通过更改 EXTRA_PATH_METADATA 设置来覆盖)

备注

当使用{attach}时, *_URL / *_SAVE_AS 设置中的所有父目录都应该互相对应。具体请参见 URL配置

链接到作者、分类、索引、标签

您可以通过 {author}name{category}foobar{index}{tag}tagname 这样的语法链接到作者、分类、索引和标签。

引入其他文件

Markdown和reStructuredText的语法中都提供了这种机制

下面是 reStructuredText 使用 include指令 的一些例子:

.. include:: file.rst

下面的例子,引入了一段用一对标识符分隔的文件片段,并指定以C++语法进行高亮显示。(同样支持通过行号指定片段)

.. include:: main.cpp
    :code: c++
    :start-after: // begin
    :end-before: // end

将一HTML文件(或者一个行内SVG)直接引入,并且不进行任何处理直接将其作为输出:

.. raw:: html
    :file: table.html

对于 Markdown ,若要进行文件引入,就必须使用扩展插件。例如可以使用 mdx_include plugin

```html
{! template.html !}
```

导入已有站点

您可以使用一个简单的脚本导入已有的站点(例如WordPress、Tumblr)。详见 导入已有站点

翻译

一篇文章可以有多个翻译版本。对于这类文章,您需要加上元数据属性 lang ,并且配置 DEFAULT_LANG (默认为[en])。完成上述配置后,文章列表中列出的是默认语言版本的文章,文章内容页中会列出所有可用的翻译版本供读者选择。

备注

Pelican的这个核心功能并不会给同一文章的不同语言版本创建子站点(例如 example.com/de )。但是如果需要创建子站点的话,可以使用扩展插件 i18n_subsites plugin

默认情况下,Pelican会使用文章的URL “slug” 来判断当前文档是否是同一篇文章的不同翻译版本。(这一点可以通过配置 ARTICLE_TRANSLATION_ID 来改变)slug可以通过元数据手动指定,若没有,Pelican会根据文章的标题(title)来自动生成slug。

以下的例子是一篇文章有英语和法语两个翻译版本的情况。

英语文章如下:

Foobar is not dead
##################

:slug: foobar-is-not-dead
:lang: en

That's true, foobar is still alive!

法语版本为:

Foobar n'est pas mort !
#######################

:slug: foobar-is-not-dead
:lang: fr

Oui oui, foobar est toujours vivant !

值得注意的是,以上两篇文章的slug是相同的,即slug作为唯一标识符存在。若您没有手动指定slug,那么请保证同一篇文章的不同翻译版本的标题是相同的。如此,由于slug会根据文章标题自动生成,它们隐含的slug会是相同的。

如果您不希望某篇文章的原始版本以 DEFAULT_LANG 翻译版本出现,可以使用 translation 元数据来指出本推文是一个非默认语言的翻译版本。(译者注:例如,设置的默认语言为zh_CN,如果某篇推文的原始版本是英文而不是中文,那么对于中文翻译版本的就可以指定其translations元数据为true,即对于该推文来说,中文版本是翻译后的版本)

Foobar is not dead
##################

:slug: foobar-is-not-dead
:lang: en
:translation: true

That's true, foobar is still alive!

语法高亮

您可以按照下面的约定在文件内容中添加代码块,Pelican可以完成五彩缤纷的语法高亮。

对于reStructuredText,使用 code-block 指令指定代码所使用的语言(此处以``python``为例):

.. code-block:: python

   print("Pelican is a static site generator.")

Markdown则使用 CodeHilite extension 扩展插件来完成语法高亮。在代码上方标记所用语言,同时将其与代码都进行缩进:

There are two ways to specify the identifier:

    :::python
    print("The triple-colon syntax will *not* show line numbers.")

To display line numbers, use a path-less shebang instead of colons:

    #!python
    print("The path-less shebang syntax *will* show line numbers.")

指定语言的标识符(例如 pythonruby)必须是在 可用列表 中列出的。

对于reStructuredText,下面列出的选项可以在 code-block 命令中使用:

选项

有效值

描述

anchorlinenos

N/A

指定行号是否显示在 <a> 标签中

classprefix

string

要添加到用于语法高亮的css类名前面的字符串

hl_lines

numbers

需要高亮的行号列表,行号之间以空格隔开。这与Sphinx中的 emphasize-lines 类似,但是不支持使用连字符和逗号指定行号范围。

lineanchors

string

用此处指定的字符串和 “-行号”给每一行都加上锚点。

linenos

string

开启此选项或将此选项设为“table”时,输出表格时会带上行号;如果设为“inline”,则内联输出行号;如果设为“none”,则不输出行号。

linenospecial

number

是否每隔几行就设置一行特殊的css样式类。

linenostart

number

起始行的行号。

linenostep

number

每隔几行输出一次

lineseparator

string

每行输出代码之间的输出字符串,默认为 'n'。

linespans

string

使用指定的字符串和“-行号”将每一行包装在一个span中。

nobackground

N/A

若设置,则不为元素输出背景颜色

nowrap

N/A

若设置,则不对token进行换行处理。

tagsfile

string

用于命名定义的ctags文件

tagurlformat

string

用于ctag链接的格式

请注意,由于版本的不同,Pygments模块可能不完全支持上述选项。请参考 Pygments文档HtmlFormatter 一节获取每个选项的详细信息。

举个例子,下面的代码块开启了行号显示,从153行开始输出,并且指定Pygments的CSS类以 pgcss 为前缀,使得类名更为独特并避免可能的CSS冲突:

.. code-block:: identifier
    :classprefix: pgcss
    :linenos: table
    :linenostart: 153

   <indented code block goes here>

您也可以在Pelican的配置文件中指定 PYGMENTS_RST_OPTIONS ,如此就可以让Pelican自动在每个代码块上使用指定的选项。

举个例子,若您希望每个代码块都显示行号,并且在CSS类名前都加上前缀pgcss,就可以像这样设置 PYGMENTS_RST_OPTIONS

PYGMENTS_RST_OPTIONS = {'classprefix': 'pgcss', 'linenos': 'table'}

若指定了 PYGMENTS_RST_OPTIONS ,同时也为代码块单独指定了一些选项,单独指定的会将 PYGMENTS_RST_OPTIONS 覆盖。

发布草稿

如果您想要以草稿的形式发布文章或页面(例如在正式发布前给朋友预览),可以添加元数据属性 Status: draft 。如此,文章就会输出到 drafts 文件夹中,并且不会被列在首页、分类或是标签页面中。

若您希望文章默认以草稿形式发布(可以防止在完成文章前不小心将其正式发布),可以将此status属性加在 DEFAULT_METADATA 中:

DEFAULT_METADATA = {
    'status': 'draft',
}

要发布当前处于 draft 状态的推文,更新推文的元数据,使其中包括 Status: published

隐藏推文

和页面一样,推文也能通过 Status: hidden 标记为隐藏状态。隐藏的推文会输出到 ARTICLE_SAVE_AS 指定的目录中,这些推文“不会被列出”,即不会在标签、分类、作者主页、feed中出现。

忽略推文

状态设为了 skip 的推文将会被完全忽略。也就是说,他们不会被处理,也不会输出到 ARTICLE_SAVE_AS 指定的目录中。同样,被忽略的推文不会出现在索引或者订阅源中。