2012-07-01 10:52:39 -07:00
|
|
|
|
Some history about Pelican
|
2011-11-30 21:11:50 +01:00
|
|
|
|
##########################
|
|
|
|
|
|
|
|
|
|
|
|
.. warning::
|
|
|
|
|
|
|
|
|
|
|
|
This page comes from a report the original author (Alexis Métaireau) wrote
|
2012-09-10 20:50:45 -07:00
|
|
|
|
right after writing Pelican, in December 2010. The information may not be
|
2012-07-01 10:52:39 -07:00
|
|
|
|
up-to-date.
|
2011-11-30 21:11:50 +01:00
|
|
|
|
|
2018-11-02 20:53:15 -06:00
|
|
|
|
Pelican is a simple static blog generator. It parses markup files (Markdown or
|
|
|
|
|
|
reStructuredText for now) and generates an HTML folder with all the files in
|
|
|
|
|
|
it. I've chosen to use Python to implement Pelican because it seemed to be
|
|
|
|
|
|
simple and to fit to my needs. I did not wanted to define a class for each
|
|
|
|
|
|
thing, but still wanted to keep my things loosely coupled. It turns out that it
|
|
|
|
|
|
was exactly what I wanted. From time to time, thanks to the feedback of some
|
|
|
|
|
|
users, it took me a very few time to provide fixes on it. So far, I've
|
|
|
|
|
|
re-factored the Pelican code by two
|
2012-07-01 10:52:39 -07:00
|
|
|
|
times; each time took less than 30 minutes.
|
2011-11-30 21:11:50 +01:00
|
|
|
|
|
|
|
|
|
|
Use case
|
|
|
|
|
|
========
|
|
|
|
|
|
|
2018-11-02 20:53:15 -06:00
|
|
|
|
I was previously using WordPress, a solution you can host on a web server to
|
|
|
|
|
|
manage your blog. Most of the time, I prefer using markup languages such as
|
|
|
|
|
|
Markdown or reStructuredText to type my articles. To do so, I use vim. I think
|
|
|
|
|
|
it is important to let the people choose the tool they want to write the
|
|
|
|
|
|
articles. In my opinion, a blog manager should just allow you to take any kind
|
|
|
|
|
|
of input and transform it to a weblog. That's what Pelican does. You can write
|
|
|
|
|
|
your articles using the tool you want, and the markup language you want, and
|
|
|
|
|
|
then generate a static HTML weblog.
|
2011-11-30 21:11:50 +01:00
|
|
|
|
|
|
|
|
|
|
.. image:: _static/overall.png
|
|
|
|
|
|
|
2012-07-01 10:52:39 -07:00
|
|
|
|
To be flexible enough, Pelican has template support, so you can easily write
|
|
|
|
|
|
your own themes if you want to.
|
2011-11-30 21:11:50 +01:00
|
|
|
|
|
|
|
|
|
|
Design process
|
|
|
|
|
|
==============
|
|
|
|
|
|
|
|
|
|
|
|
Pelican came from a need I have. I started by creating a single file
|
2018-11-02 20:53:15 -06:00
|
|
|
|
application, and I have make it grow to support what it does by now. To start,
|
|
|
|
|
|
I wrote a piece of documentation about what I wanted to do. Then, I created the
|
|
|
|
|
|
content I wanted to parse (the reStructuredText files) and started
|
|
|
|
|
|
experimenting with the code. Pelican was 200 lines long and contained almost
|
|
|
|
|
|
ten functions and one class when it was first usable.
|
|
|
|
|
|
|
|
|
|
|
|
I have been facing different problems all over the time and wanted to add
|
|
|
|
|
|
features to Pelican while using it. The first change I have done was to add the
|
|
|
|
|
|
support of a settings file. It is possible to pass the options to the command
|
|
|
|
|
|
line, but can be tedious if there is a lot of them. In the same way, I have
|
|
|
|
|
|
added the support of different things over time: Atom feeds, multiple themes,
|
|
|
|
|
|
multiple markup support, etc. At some point, it appears that the "only one
|
|
|
|
|
|
file" mantra was not good enough for Pelican, so I decided to rework a bit all
|
|
|
|
|
|
that, and split this in multiple different files.
|
2011-11-30 21:11:50 +01:00
|
|
|
|
|
|
|
|
|
|
I’ve separated the logic in different classes and concepts:
|
|
|
|
|
|
|
|
|
|
|
|
* *writers* are responsible of all the writing process of the files.
|
2018-11-02 20:53:15 -06:00
|
|
|
|
They are responsible of writing .html files, RSS feeds and so on. Since those
|
|
|
|
|
|
operations are commonly used, the object is created once, and then passed to
|
|
|
|
|
|
the generators.
|
2011-11-30 21:11:50 +01:00
|
|
|
|
|
2012-07-01 10:52:39 -07:00
|
|
|
|
* *readers* are used to read from various formats (Markdown and
|
2018-11-02 20:53:15 -06:00
|
|
|
|
reStructuredText for now, but the system is extensible). Given a file, they
|
|
|
|
|
|
return metadata (author, tags, category, etc) and content (HTML formatted).
|
2011-11-30 21:11:50 +01:00
|
|
|
|
|
2012-07-01 10:52:39 -07:00
|
|
|
|
* *generators* generate the different outputs. For instance, Pelican
|
2018-11-02 20:53:15 -06:00
|
|
|
|
comes with an ArticlesGenerator and PagesGenerator, into others. Given a
|
|
|
|
|
|
configuration, they can do whatever you want them to do. Most of the time
|
|
|
|
|
|
it's generating files from inputs (user inputs and files).
|
2011-11-30 21:11:50 +01:00
|
|
|
|
|
2012-07-01 10:52:39 -07:00
|
|
|
|
I also deal with contents objects. They can be ``Articles``, ``Pages``,
|
|
|
|
|
|
``Quotes``, or whatever you want. They are defined in the ``contents.py``
|
|
|
|
|
|
module and represent some content to be used by the program.
|
2011-11-30 21:11:50 +01:00
|
|
|
|
|
2012-07-01 10:52:39 -07:00
|
|
|
|
In more detail
|
|
|
|
|
|
==============
|
2011-11-30 21:11:50 +01:00
|
|
|
|
|
2012-07-01 10:52:39 -07:00
|
|
|
|
Here is an overview of the classes involved in Pelican.
|
2011-11-30 21:11:50 +01:00
|
|
|
|
|
|
|
|
|
|
.. image:: _static/uml.jpg
|
|
|
|
|
|
|
2012-07-01 10:52:39 -07:00
|
|
|
|
The interface does not really exist, and I have added it only to clarify the
|
|
|
|
|
|
whole picture. I do use duck typing and not interfaces.
|
2011-11-30 21:11:50 +01:00
|
|
|
|
|
|
|
|
|
|
Internally, the following process is followed:
|
|
|
|
|
|
|
2018-11-02 20:53:15 -06:00
|
|
|
|
* First of all, the command line is parsed, and some content from the user is
|
|
|
|
|
|
used to initialize the different generator objects.
|
2011-11-30 21:11:50 +01:00
|
|
|
|
|
2018-11-02 20:53:15 -06:00
|
|
|
|
* A ``context`` is created. It contains the settings from the command line and
|
|
|
|
|
|
a settings file if provided.
|
2012-07-01 10:52:39 -07:00
|
|
|
|
* The ``generate_context`` method of each generator is called, updating
|
2011-11-30 21:11:50 +01:00
|
|
|
|
the context.
|
2018-11-02 20:53:15 -06:00
|
|
|
|
* The writer is created and given to the ``generate_output`` method of each
|
|
|
|
|
|
generator.
|
2011-11-30 21:11:50 +01:00
|
|
|
|
|
2018-11-02 20:53:15 -06:00
|
|
|
|
I make two calls because it is important that when the output is generated by
|
|
|
|
|
|
the generators, the context will not change. In other words, the first method
|
|
|
|
|
|
``generate_context`` should modify the context, whereas the second
|
|
|
|
|
|
``generate_output`` method should not.
|
2011-11-30 21:11:50 +01:00
|
|
|
|
|
|
|
|
|
|
Then, it is up to the generators to do what the want, in the
|
2018-11-02 20:53:15 -06:00
|
|
|
|
``generate_context`` and ``generate_content`` method. Taking the
|
|
|
|
|
|
``ArticlesGenerator`` class will help to understand some others concepts. Here
|
|
|
|
|
|
is what happens when calling the ``generate_context`` method:
|
|
|
|
|
|
|
|
|
|
|
|
* Read the folder “path”, looking for restructured text files, load each of
|
|
|
|
|
|
them, and construct a content object (``Article``) with it. To do so, use
|
|
|
|
|
|
``Reader`` objects.
|
2012-07-01 10:52:39 -07:00
|
|
|
|
* Update the ``context`` with all those articles.
|
2011-11-30 21:11:50 +01:00
|
|
|
|
|
2018-11-02 20:53:15 -06:00
|
|
|
|
Then, the ``generate_content`` method uses the ``context`` and the ``writer``
|
|
|
|
|
|
to generate the wanted output.
|