From 00b85759d907dfc4b630d480472031e95254bba9 Mon Sep 17 00:00:00 2001 From: "A. Jesse Jiryu Davis" Date: Sun, 7 Feb 2016 07:00:14 -0500 Subject: [PATCH] Update the "Adding Field Type" howto. Closes #48. --- content/docs/api/db/type/contents.lr | 3 + content/docs/plugins/howto/contents.lr | 96 +++++++++++++++----------- 2 files changed, 57 insertions(+), 42 deletions(-) diff --git a/content/docs/api/db/type/contents.lr b/content/docs/api/db/type/contents.lr index 3c69f01a..0b1a9e90 100644 --- a/content/docs/api/db/type/contents.lr +++ b/content/docs/api/db/type/contents.lr @@ -41,3 +41,6 @@ def setup_env(self, **extra): ``` For more information see [value_from_raw :ref](value-from-raw/). + +There is a more complete example in the +[Plugin How To :ref](../../../plugins/howto/#adding-new-field-types). diff --git a/content/docs/plugins/howto/contents.lr b/content/docs/plugins/howto/contents.lr index 16c808ca..638181df 100644 --- a/content/docs/plugins/howto/contents.lr +++ b/content/docs/plugins/howto/contents.lr @@ -114,64 +114,76 @@ function we also track the plugin's filename to rebuild if the plugin changes. ## Adding New Field Types -Let's say you want to add a "datetime" type to the set of -[field types :ref](../../api/db/types/) used in your models, because the -built-in "date" type has no time component. You might update `blog-post.ini` -from the [blog guide :ref](../../guides/blog) like so: +Let's say you want to add an "asciidoc" +[field type :ref](../../api/db/types/) so you can write with [AsciiDoc](http://www.methods.co.nz/asciidoc) markup. + +First [install AsciiDoc](http://www.methods.co.nz/asciidoc/INSTALL.html) so its command-line program is available. Then update `blog-post.ini` from the [blog guide :ref](../../guides/blog) like so: ```ini -[fields.pub_date] -label = Publication date -type = datetime # Custom "datetime" type. +[fields.body] +label = Body +type = asciidoc # Custom type. ``` -In a blog post's `contents.lr`, specify its publication date like: +In a blog post's `contents.lr`, write some AsciiDoc like: ``` -pub_date: 2016-01-02 12:34:56 +body: + +== Header 1 + +Some text. + +----- +code here +----- ``` -You can add your "datetime" type to Lektor with a plugin: +You can add your "asciidoc" type to Lektor with a plugin: ```python -from datetime import datetime +from subprocess import PIPE, Popen + from lektor.pluginsystem import Plugin from lektor.types import Type -class DatetimeType(Type): + +def asciidoc_to_html(text): + # The "-" at the end tells asciidoc to read from stdin. + p = Popen( + ['asciidoc', '--no-header-footer', + '--backend=html5', '-'], + stdin=PIPE, stdout=PIPE, stderr=PIPE) + + out, err = p.communicate(text) + if p.returncode != 0: + raise RuntimeError('asciidoc: "%s"' % err) + + return out + + +# Wrapper with an __html__ method prevents +# Lektor from escaping HTML tags. +class HTML(object): + def __init__(self, html): + self.html = html + + def __html__(self): + return self.html + + +class AsciiDocType(Type): + widget = 'multiline-text' + def value_from_raw(self, raw): - return datetime.strptime(raw.value, '%Y-%m-%d %H:%M:%S') + return HTML(asciidoc_to_html(raw.value or u'')) -def strftime_filter(dt, fmt='%B %-d, %Y'): - return dt.strftime(fmt) -class DatetimeTypePlugin(Plugin): - name = u'datetime type' - description = u'Adds a new field type, "datetime".' +class AsciiDocPlugin(Plugin): + name = u'AsciiDoc' + description = u'Adds AsciiDoc field type to Lektor.' def on_setup_env(self, **extra): - self.env.types['datetime'] = DatetimeType - self.env.jinja_env.filters['strftime'] = strftime_filter -``` - -This plugin also adds a `strftime` filter to Jinja. -Render a datetime with the default format in a template like: - -```html+jinja -Published on {{ this.pub_date|strftime }} -``` - -Or a custom format: - -```html+jinja -Published on {{ this.pub_date|strftime('%Y-%m-%d') }} -``` - -Python datetime objects implement the standard comparison protocol, so -ordering still works without modifying `blog.ini`: - -```ini -[children] -model = blog-post -order_by = -pub_date, title + # Derives type name "asciidoc" from class name. + self.env.add_type(AsciiDocType) ```