From 566295e4d4211b3317621e7bb587217245955ee5 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Mon, 19 Mar 2007 13:19:34 +0100 Subject: [PATCH] [svn] again some jinja updates --HG-- branch : trunk --- docs/src/frameworks.txt | 30 +---------- docs/src/recipies.txt | 116 ++++++++++++++++++++++++++++++++++++++++ jinja/filters.py | 30 +++++++++-- jinja/plugin.py | 5 +- setup.py | 2 +- tests/test_filters.py | 6 +++ 6 files changed, 155 insertions(+), 34 deletions(-) diff --git a/docs/src/frameworks.txt b/docs/src/frameworks.txt index c180670..2cea2c9 100644 --- a/docs/src/frameworks.txt +++ b/docs/src/frameworks.txt @@ -53,34 +53,8 @@ specify the extension. Otherwise use the dotted notation: TurboGears ---------- -Integrating Jinja into TurboGears works pretty much the same. - -Basically all you have to do is to edit the application configuration file at -``application/config/app.cfg`` and change `global.tg.defaultview` and -provide the jinja options: - -.. sourcecode:: ini - - [global] - tg.defaultview = 'jinja' - jinja.init_callback = yourapplication.yourmodule.setup_function - -Now you have to edit the file `yourapplication.yourmodule` and add a -`setup_function` callback that creates an environment: - -.. sourcecode:: python - - from jinja import Environment, FileSystemLoader - - def setup_function(options): - return Environment(loader=FileSystemLoader('path/to/templates')) - -This solution isn't the best but currently the only thing you can do. There is -a discussion about improving the plugin interface so that this can be solved -in a more elegant way. - -Also here exists the same limitation regarding dotted notation, see the -snipped and information in the pylons section. +The TurboGears template plugin interface is broken by design and +there is currently no way to embed Jinja templates in TurboGears. .. _TurboGears: http://www.turbogears.org/ diff --git a/docs/src/recipies.txt b/docs/src/recipies.txt index f444f00..f8fa284 100644 --- a/docs/src/recipies.txt +++ b/docs/src/recipies.txt @@ -22,6 +22,7 @@ list you can use the ``cycle`` tag: tag is encountered the next item from the list is rendered. If you pass it just one argument it's meant to be a sequence. + Active Menu Item ================ @@ -53,3 +54,118 @@ of ``blocks`` are global you can do something like this: {% extends "layout.html" %} {% set active_page = "index" %} + + +Sitemap +======= + +To create a sitemap you can either use the ``for`` tag or a ``macro`` +that calls itself. The datastructures should look like this: + +.. sourcecode:: python + + {'sitemap': [ + dict( + caption='Pages', + children=[ + dict(href='index.html', caption='Index'), + dict(href='downloads.html', caption='Downloads'), + dict( + caption='Users', + children=[ + dict(href='peter.html', + caption='Peter'), + dict(href='max.html', + caption='Max'), + dict(href='suzan.html', + caption='Suzan') + ] + ), + dict( + caption='Files', + children=[ + dict( + caption='Images', + children=[ + dict(href='vienna.html', + caption='Vienna'), + dict(href='roma.html', + caption='Roma'), + dict(href='tokyo.html', + caption='Tokyo') + ] + ), + dict( + caption='Videos', + children=[ + dict(href='party.html', + caption='Party') + ] + ) + ] + ) + ] + ), + dict(caption='Foo', href='foo.html') + dict(caption='About', href='about.html') + ]} + +Now you can create a sitemap using ``for``: + +.. sourcecode:: html+jinja + + + +Or by using a ``macro`` that calls itself: + +.. sourcecode:: html+jinja + + {% macro render_sitemap items %} + {% for item in items %} +
  • {{ item.caption|e }} + {% if item.children %}{% endif %}
  • + {% endfor %} + {% endmacro %} + + + +Using A Block Multiple Times +============================ + +Blocks have the small disadvantage that they work both ways which is a problem +if you want to render a block two times on a page. Here a nice little +workaround for this limitation: + +.. sourcecode:: html+jinja + + + + {% filter capture('title') %}{% + block title %}{% endblock %}{% + endfilter %} + + +
    {{ title }}
    + + + +Or if you use the `capture` filter in `clean` mode: + +.. sourcecode:: html+jinja + + {% filter capture('title', True)|trim %} + {% block title %}{% endblock %} + {% endfilter %} + + + {{ title }} + + +
    {{ title }}
    + + diff --git a/jinja/filters.py b/jinja/filters.py index 7de2176..481f9f5 100644 --- a/jinja/filters.py +++ b/jinja/filters.py @@ -565,7 +565,15 @@ def do_format(*args): return wrapped -def do_capture(name='captured'): +def do_trim(value): + """ + Strip leading and trailing whitespace. + """ + return value.strip() +do_trim = stringfilter(do_trim) + + +def do_capture(name='captured', clean=False): """ Store the value in a variable called ``captured`` or a variable with the name provided. Useful for filter blocks: @@ -573,12 +581,27 @@ def do_capture(name='captured'): .. sourcecode:: jinja {% filter capture('foo') %} - .... + ... + {% endfilter %} + {{ foo }} + + This will output "..." two times. One time from the filter block + and one time from the variable. If you don't want the filter to + output something you can use it in `clean` mode: + + .. sourcecode:: jinja + + {% filter capture('foo', True) %} + ... {% endfilter %} {{ foo }} """ + if not isinstance(name, unicode): + raise FilterArgumentError('You can only capture into variables') def wrapped(env, context, value): context[name] = value + if clean: + return Undefined return value return wrapped @@ -619,5 +642,6 @@ FILTERS = { 'string': do_string, 'urlize': do_urlize, 'format': do_format, - 'capture': do_capture + 'capture': do_capture, + 'trim': do_trim } diff --git a/jinja/plugin.py b/jinja/plugin.py index db1b651..7c6b4bc 100644 --- a/jinja/plugin.py +++ b/jinja/plugin.py @@ -3,8 +3,9 @@ jinja.plugin ~~~~~~~~~~~~ - Provide a bridge to buffet. Buffet is used by some frameworks (namely - CherryPy, TurboGears and Pylons) to load templates. + This module proides a bridge to buffed so that you can use Jinja + in pylons. Note that this doesn't work with turbogears because their + buffet implementation is broken. :copyright: 2007 by Armin Ronacher. :license: BSD, see LICENSE for more details. diff --git a/setup.py b/setup.py index 697fb4b..503dee4 100644 --- a/setup.py +++ b/setup.py @@ -33,6 +33,6 @@ setup( extras_require = {'plugin': ['setuptools>=0.6a2']}, entry_points=''' [python.templating.engines] - jinja = jinja.bakerplugin:JinjaPlugin[plugin] + jinja = jinja.plugin:JinjaPlugin[plugin] ''' ) diff --git a/tests/test_filters.py b/tests/test_filters.py index 53b142a..83dfa82 100644 --- a/tests/test_filters.py +++ b/tests/test_filters.py @@ -42,6 +42,7 @@ RANDOM = '''{{ seq|random }}''' REVERSE = '''{{ "foobar"|reverse }}|{{ [1, 2, 3]|reverse }}''' STRING = '''{{ range(10)|string }}''' TITLE = '''{{ "foo bar"|title }}''' +TRIM = '''{{ " foo "|trim }}''' TRUNCATE = '''{{ data|truncate(15, true, ">>>") }}|\ {{ data|truncate(15, false, ">>>") }}|\ {{ smalldata|truncate(15) }}''' @@ -178,6 +179,11 @@ def test_title(env): assert tmpl.render() == "Foo Bar" +def test_truncate(env): + tmpl = env.from_string(TRUNCATE) + assert tmpl.render() == 'foo' + + def test_truncate(env): tmpl = env.from_string(TRUNCATE) out = tmpl.render(data='foobar baz bar' * 1000, -- 2.26.2