[svn] again some jinja updates
authorArmin Ronacher <armin.ronacher@active-4.com>
Mon, 19 Mar 2007 12:19:34 +0000 (13:19 +0100)
committerArmin Ronacher <armin.ronacher@active-4.com>
Mon, 19 Mar 2007 12:19:34 +0000 (13:19 +0100)
--HG--
branch : trunk

docs/src/frameworks.txt
docs/src/recipies.txt
jinja/filters.py
jinja/plugin.py
setup.py
tests/test_filters.py

index c180670bfbec91481a3d23180dd7b7afb4bbb72c..2cea2c964e717154918e24960d70d8099b211039 100644 (file)
@@ -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/
index f444f0075abef78ddd06f530fe251701ee1ec4e3..f8fa2847f0afdda5876a95483142020cefb78987 100644 (file)
@@ -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
+
+    <ul class="sitemap">
+    {% for item in sitemap recursive %}
+      <li><a href="{{ item.href|e }}">{{ item.caption|e }}</a>
+      {% if item.children %}<ul>{{ loop(item.children) }}</ul>{% endif %}</li>
+    {% endfor %}
+    </ul>
+
+Or by using a ``macro`` that calls itself:
+
+.. sourcecode:: html+jinja
+
+    {% macro render_sitemap items %}
+      {% for item in items %}
+        <li><a href="{{ item.href|e }}">{{ item.caption|e }}</a>
+        {% if item.children %}<ul>{{ render_sitemap(item.children) }}</ul>{% endif %}</li>
+      {% endfor %}
+    {% endmacro %}
+    <ul class="sitemap">{{ render_sitemap(sitemap) }}</ul>
+
+
+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
+
+    <html>
+      <head>
+        <title>{% filter capture('title') %}{%
+                  block title %}{% endblock %}{%
+                  endfilter %}</title>
+      </head>
+      <body>
+        <div class="head">{{ title }}</div>
+      </body>
+    </html>
+
+Or if you use the `capture` filter in `clean` mode:
+
+.. sourcecode:: html+jinja
+
+    {% filter capture('title', True)|trim %}
+      {% block title %}{% endblock %}
+    {% endfilter %}
+    <html>
+      <head>
+        <title>{{ title }}</title>
+      </head>
+      <body>
+        <div class="head">{{ title }}</div>
+      </body>
+    </html>
index 7de2176e45fd75fc24189d3252cde1b37323aa3f..481f9f5bccab712483bd52fdeb4f0d647c67e163 100644 (file)
@@ -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
 }
index db1b651931ec827c018e73c4bdb74c2effbc37cf..7c6b4bc0c287894e8fb3139c7a312461be2240c4 100644 (file)
@@ -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.
index 697fb4b0418a7ecba7ad7e40b699fd5b13692dd8..503dee46ef8c09a8339140cbd3740f1ed06abf29 100644 (file)
--- 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]
     '''
 )
index 53b142afb256987da57ce457226a072b9a8160af..83dfa82aa1e961e675cdf5fd0b8f393c37033765 100644 (file)
@@ -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,