-
Notifications
You must be signed in to change notification settings - Fork 0
Static Python/Kid weblog generator with Maildir store
License
decklin/ennepe
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Introduction ============ Ennepe is a simple blogging system which generates static files. You provide it with some entries, which are stored in an ordinary Maildir, a layout, which is a directory tree indicating where these entries should go, and some styles, which are Kid templates that the layout can use to put pages together. The layout tree may contain ordinary files, such as images, stylesheets, or constant pages, and Python scripts, which will be used to generate variable pages, XML feeds, or anything else you want. Requirements ============ * Python, at least version 2.5. Ennepe was originally written using 2.3 and is currently being developed on 2.7. It will be ported to Python 3 in the future. * If you want to use reStructuredText to format entries as HTML, docutils. This is the default configuration, but you could also replace this with PyMarkdown, PyTextile, or nothing at all. * Kid, available at http://kid.lesscode.org/. This could probably be replaced as well, but it would be more work than swapping out reST. * Something that will allow you to create, add to and edit your Maildir. I use procmail and Mutt. Configuration ============= An Ennepe blog starts with a configuration file, which is a Python script. The example provided in ``examples/simple/config.py`` explains what it can do and what variables can be set. By default, Ennepe looks for this file in ``~/.ennepe/config.py``. Usage ===== To regenerate your blog, simply run ``ennepe``, or, if your config lives in a different location, ``ennepe path/to/config.py``. By default, only pages for which the applicable entries or layout have been changed since the page was last written will be evaluated; you can override this and rebuild the entire blog with the ``--force`` option. (At the moment, this is your only recourse if you change your styles.) Layout ====== Layout scripts are also written in Python; any file with the executable bit set will be executed and its output will be used to produce the corresponding output file. Apart from any local variables defined in the blog's configuration, layouts will be given the following: * ``muse``: a ``ennepe.mousa.Muse`` object, the thing that generates the blog. It contains these attributes (among others, of course, but you can safely ignore the rest): - ``muse.entries``: the list of all entries in the blog, not just the ones you are considering for this page. - ``muse.template(name, ...)``: a method that will look up the style ``name.kid`` in your configuration's style directory and initialize it for you with any keyword arguments provided; in almost all cases, you will want to give the style all your local variables by specifying ``**locals()``. * ``entries``: the subset of entries that apply to the particular file being generated. In an archive page, for example, this would be only the entries in that particular year, week, or whatever. This means all such entries, so you will want to choose a subset of them in most cases. Files in the top level directory of your layout will be evaluated with all the entries in the blog. However, you can create files or directories with a name like ``__year__``, and it will produce files (or, in this case, directories) named ``2006``, ``2007``, etc, which will be evaluated in turn with only the entries for that year. You can do the same thing for attributes which have multiple values, as well: for example, a directory named ``__tags__`` will be evaluated for each tag that appears on an entry, even if the tags are stored as a list. The directory tree in ``examples/simple/layout`` illustrates how to do each of these, and a basic Atom feed; you can of course be more creative. Entries ======= The values for all these expansions come from the attributes of ennepe's Entry class. Several useful ones, such as ``subject`` and ``tags``, are provided by default: if you wish to define more, you may add a mixin class to your configuration, with some specially-named methods. Attributes may be calculated at initialization or only when needed. When generating file or directory names, the attributes' repr() is used, so that dates, subject lines, and so on may be appropriately formatted and linked to. The ``ennepe.utils`` module provides the functions ``clean`` and ``cook``, to make creating useful values easier. This is just a matter of convention; it is not required, but it does ensure that all the formatting logic is in one place. Entry Details ============= For each entry ``e``, the following attributes (plus any you define) are available: * ``msg``: the message that the entry was created from. Initially, only the headers have been read; the rest is read when you access ``e.content``. * ``date``: a time-tuple indicating the date on the Date: header. * ``mtime``: a time-tuple indicating when the message's Maildir file was created. This is not the mtime of the file itself! Messing with Maildirs by hand is not recommended. To edit an entry, open the Maildir in mutt and hit the "e" key on its message. * ``content``: the body of the entry, processed with reStructuredText. Its repr() is the first 100 characters of the unprocessed body (suitable for perhaps a summary feed). * ``subject``: The contents of the Subject header. Its repr() is a URL-cleaned (at most 3 words) version of same, with a number appended to make each one unique within a given day: 'subject', 'subject-1', 'subject-2', etc. These are calculated on startup in chronological order so that they are always the same. * ``id``: The Message-Id: header. Its repr() is a tag: URL suitable for an Atom feed, as described in http://diveintomark.org/archives/2004/05/28/howto-atom-id. * ``author``: Name from the From: header. Its repr() is the URL-cleaned version, in case you want to categorize a multi-author blog by author name. * ``email``: Email address from the From: header. Its repr() is something like 'decklin at red dash bean dot com'. * ``tags``: A list of the contents of the X-Tags: header, split by commas. URL-cleaned repr()s for tag categorization. * ``year``, ``month``, ``day``: What the names imply. The values are ints; the repr()s are formatted with ``time.strftime``. Updating ======== The ``contrib`` directory contains some small scripts to facilitate updating your blog, and an example of how to put them together so that your blog can pick up PGP-signed mail at a public email address (or perhaps ordinary mail at an address internal to your own network) and automatically rebuild itself upon receipt. Future and Caveats ================== I intend to write an SQLite backend once someone complains that it takes too long to load their 10,000 entries. Be loquacious. At the moment, however, Ennepe depends on the Maildir really being a Maildir (for reliable modification times) and the standard ``email`` and ``mailbox`` modules, which are not perfect. A lot of the more magic stuff may not be particularly good style; where some clarity or brevity in Ennepe itself could be sacrificed to make the layout and styles easier to work with, it has been. About the Name ============== The word "ennepe" (ἔννεπε) is Ancient Greek for "tell". In the first line of the Odyssey, "moi ennepe Mousa" ("tell me, Muse") is IMHO most evocatively translated by Lombardo as "Speak, Memory—"; for this reason, Ennepe was originally called Mnemosyne (the muse of memory). However, this name was taken by another free software program which proved to be more popular. Author and Copyright ==================== Copyright 2006-2012 Decklin Foster <decklin@red-bean.com>. This program is free software; please see LICENSE for terms and conditions.
About
Static Python/Kid weblog generator with Maildir store
Resources
License
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published