Extending Acrylamid

Acrylamid is designed to easily integrate custom code and you can customize almost everything: transformation to the content, custom HTML layout or a new view of your posts. Acrylamid itself is using this API to implement different text parsers like Markdown or reStructuredText, hyphenation and the complete rendering of articles, single posts and paged listings.


class acrylamid.filters.Filter

All text transformation is done via filters. A filter takes some text and returns it modified or untouched. Per default custom filters are stored in filters/ directory inside your blog. On startup, Acrylamid will parse this plugin, report accidential syntax errors and uses this filter if required.

from acrylamid.filters import Filter

class Example(Filter):

    match = ['keyword', 'another']

    def transform(self, content, entry, *args):
        return content

This is a minimal filter implementation that does nothing but returning the content that you can apply with filter: keyword. A Filter may provide an init() that gets called once before we apply transform() to the content.


Current version of this filter. If you made fundamental changes to your filter you can increment the version and all cached entries using that filter will recompile automatically on next run.


A filter chain is sorted by priority, so if you do textual modification you should have a priority ≥ 70.0 (default for Markdown, reST and so on).


A list of strings or regular expressions (mixed works too) that will match this filter and uses this in the rendering process.


A list of strings (no regular expressions!) that describe conflicting Filters. For example conflicts Markdown with ['rst', 'plain', 'textile']. It is sufficient that one filter provides conflicting filters.

init(self, conf, env)

At demand initialization. A filter gets only initialized when he’s actually used. This part is executed only once before transform() and should be used to import plugins or set some constants. Note that you may also check explicitly for ImportErrors from a statement like import foo that will not throw an ImportError because we delay the actual import. Just make write foo.bar in init() and when it throws an ImportError, it is automatically handled.

Have a look at acrylamid/filters/md.py or acrylamid/filters/typography.py for example implementations.

  • confConfiguration dictionary
  • env – environment dictionary
transform(self, content, entry, *args)

Modify the content and return it. Each continuous transformation is automatically saved to disk (= caching). Don’t import modules here, use module space or init() for that.

  • content – a text you can modify
  • entry – current readers.Entry
  • args – a list of additional arguments


class acrylamid.views.View

A view generally takes a template and generates HTML/XML or other kinds of text. It may filter a list of entries by a given attribute, apply per view specific filters, handle path routes.

from acrylamid.views import View

class Raw(View):

    def init(self, conf, env, **kw):

    def context(self, conf, env, request):
        return env

    def generate(self, conf, env, request):
        yield 'Hello World', '/output/hello.txt'

Above implements a minimal view that outputs text to a given path to acrylamid.helpers.mkfile() that handles directory creation and event handling. Note, that a view must implement a skip-mechanism by itself. If you acrylamid.helpers.paginate() you get a modified for the current list of entries and you only need to check wether the template has changed:

from os.path import join

if exists(path) and not modified and not tt.modified:
    event.skip('ns', path)

See the source of acrylamid’s built-in views that all have implemented skipping. If you skip over entries you can take full advantage of lazy evaluation (no need to initialize filters, recompile/load from cache).

A valid view only requires a generate() method.


From 0.0 to 100.0, by default 50.0. Useful if you want to run a view at first or at last.


A list of filters you applied to this view in your Configuration, default list is empty.


A filtering condition from Configuration that gets always applied, defaults to no filtering.


The key to which you assign a configuration dict.

init(self, conf, env, **kwargs)

Initializing the view with configuration parameters. You can also load jinja/other templates here.

Parameters:kw – custom key/value pair from Configuration is available in here.
context(self, conf, env, request)

Add shared environment varialbes for all views, e.g. template filters and objects. You must return the environment.

  • env – environment object
  • request – reqest dictionary
generate(self, conf, env, data)

Render template and yield final output with full qualified path. If you don’t generate output, raise StopIteration. Make use of acrylamid.helpers especially acrylamid.helpers.expand(), acrylamid.helpers.joinurl() and acrylamid.helpers.union().

Load a template from env.engine and check wether it has changed:

>>> tt = self.env.engine.fromfile('articles.html')
>>> print tt.modified

If you skip over an entry make sure you acrylamid.helpers.event.skip() it, so Acrylamid can track this file to include it into your sitemap.

Parameters:request – request dictionary


Acrylamid depends deeply on the popular Jinja2 template engine written in pure python. To work with Acrylamid each template you get from the environment object has a special attribute called has_changed and indicates over the whole compilation process if this template has changed or not. If a template inherits a template, we also check wether this has changed and so on.

This allows us to write a simple statement wether we may skip a page or need to re-render it.

  • Jinja2 API docs
  • Jinja2 Designer Docs

Table Of Contents

Related Topics

This Page