Edgewall Software

Changes between Version 43 and Version 44 of TracDev/PortingFromGenshiToJinja


Ignore:
Timestamp:
Jan 30, 2017, 12:07:58 PM (7 years ago)
Author:
Christian Boos
Comment:

tag_ arguments no longer need |safe since fix of Jinja2 issue 490, + other improvements

Legend:

Unmodified
Added
Removed
Modified
  • TracDev/PortingFromGenshiToJinja

    v43 v44  
    88}}}
    99
    10 [[PageOutline(2-4)]]
     10[[PageOutline(2-5)]]
    1111= Porting Templates from Genshi to Jinja2
    1212
     
    506506The `html` extractor (i.e. the `trac.dist.extract_html` function) will be applied to all HTML files `**/templates/**.html`, while the `text` extractor (the `trac.dist.extract_text` function). wil be applied on the "text" files `**/templates/**.txt`.
    507507
    508 The HTML extractor "auto-detects" in a simple but effective way the presence of Genshi i18n directives, and will use the legacy Genshi extractor in that case. It is therefore safe to use this new way even before the integrality of the templates has been migrated to Jinja2.
    509 
    510 Note that as we have a dedicated mapping file anyway, we specify the extractors directly there, so we no longer needs to do that in the setup.py file:
     508The HTML extractor "auto-detects" in a simple but effective way the presence of Genshi i18n directives, and will use the legacy Genshi extractor in that case. It is therefore safe to use this new way during the migration process, when there's a mix of Jinja2 and Genshi templates.
     509
     510Note that as we have a dedicated mapping file anyway, we specify the extractors directly there, so we no longer need to do that in the setup.py file:
    511511{{{#!diff
    512512Index: setup.py
     
    630630Most of the time, the porting is a straightforward operation.
    631631
    632 ==== expand a variable
     632==== expand a variable (`${var}`)
    633633 - Genshi [[html+genshi(<b>$the_variable</b>)]]
    634634 - Jinja2 [[html+jinja(<b>${the_variable}</b>)]]
     
    641641}}}
    642642
    643 ==== expand a simple computation
     643==== expand a simple computation (`${Jinja2-expr}`)
    644644 - Genshi [[html+genshi(<b>${the_variable + 1}</b>)]]
    645645 - Jinja2 [[html+jinja(<b>${the_variable + 1}</b>)]]
     
    651651Another customization we made to Jinja2 is to avoid having a Python `None` value be expanded to the `"None"` string. Instead, we make it produce an empty string, like Genshi did.
    652652
    653 ==== include another template   #include
     653==== include another template (`include`) #include
    654654 - Genshi [[xml(<xi:include href="the_file.html"><xi:fallback/></xi:include>)]]
    655655 - Jinja2 [[xml(# include "the_file.html" ignore missing)]]
     
    693693
    694694
    695 ==== simple if...then (no else)  #if
     695==== simple conditional (`if` ... `endif`) #if
    696696 - Genshi [[xml(<py:if test="flag"><b>OK</b></py:if>)]] or simply: [[xml(<b py:if="flag">OK</b>)]]
    697697 - Jinja2
     
    704704See [http://jinja.pocoo.org/docs/dev/templates/#if if] doc.
    705705
    706 ==== if...then...else
     706==== conditional with multiple branches (`if` ... `elif` ... `else` ... `endif`)
    707707 - Genshi
    708708   {{{#!html+genshi
     
    716716</py:choose>
    717717   }}}
    718    or simply:
     718   or:
    719719   {{{#!html+genshi
    720720<py:choose>
    721721 <b py:when="flag">OK</b>
     722 <b py:when="other_flag">Maybe...</b>
    722723 <i py:otherwise="">!!!</i>
    723724</py:choose>
     
    732733 # endif
    733734   }}}
     735   or:
     736   {{{#!html+jinja
     737 # if flag:
     738 <b>OK</b>
     739 # elif other_flag:
     740 <b>Maybe...</b>
     741 # else:
     742 <i>!!!</i>
     743 # endif
     744   }}}
    734745
    735746If you really have to, you can also use the block style:
     
    739750However this goes against readability and processing via the [./Checker jinjachecker] tool,  so we really advise that you stick to the use of //[http://jinja.pocoo.org/docs/dev/templates/#line-statements line statements]//.
    740751
    741 ==== iterate over a collection   #for
     752==== iterate over a collection (`for` ... `endfor`) #for
    742753 - Genshi
    743754   {{{#!html+genshi
     
    764775See [http://jinja.pocoo.org/docs/dev/templates/#for for] doc.
    765776
    766 ===== No need for `enumerate`
     777===== no need for `enumerate`
    767778
    768779 - Genshi:
     
    787798See [http://jinja.pocoo.org/docs/dev/templates/#for loop] doc.
    788799
    789 ==== define a macro   #macro
     800==== define a macro (`macro` ... `endmacro`) #macro
    790801 - Genshi
    791802   {{{#!html+genshi
     
    802813See [http://jinja.pocoo.org/docs/dev/templates/#macros macros] doc.
    803814
    804 ==== set a variable
     815==== set a variable (`set`)
    805816 - Genshi
    806817   {{{#!html+genshi
     
    818829See [http://jinja.pocoo.org/docs/dev/templates/#tests tests] doc.
    819830
    820 ==== set several variables in a scope #with
     831==== set several variables in a scope (`with` ... `endwith`) #with
    821832
    822833 - Genshi
     
    848859
    849860
    850 ==== set HTML attributes   #htmlattr
     861==== set HTML attributes (`|htmlattr`) #htmlattr
    851862In Genshi, an attribute with a `None` value wouldn't be output. However, Jinja2 doesn't know what an attribute is (or anything else about HTML, XML for that matter), so we have to use a special filter, `htmlattr`, to reproduce this behavior:
    852863
     
    868879
    869880
    870 ==== set complex variables   #set
     881==== set complex variables (`set`) #set
    871882Note that Jinja2 expressions are a subset of Python expressions, and for the sake of simplicity the generator expressions are not part of that subset. This limitation often requires one to make creative use of [http://jinja.pocoo.org/docs/dev/templates/#filters filters], [http://jinja.pocoo.org/docs/dev/templates/#builtin-filters built-in] or custom (`min`, `max`, `trim`, `flatten`).
    872883
     
    897908     # endif
    898909   }}}
    899 If the repeated content is complex, one can use a //block assignment// (see below).
    900 
    901 ==== i18n   #trans
     910If the repeated content is complex, one can use a //block assignment// ([#set_endset see below]).
     911
     912==== i18n (`trans` ... `endtrans`) #trans
    902913
    903914Genshi had a pretty good notion of what was a piece of translatable text within an HTML template,
     
    949960
    950961Note that only direct variable expansions are supported in `trans` blocks, nothing more complex.
    951 So one way to deal with complex translatable content is to factor out the complex parts in variable blocks. See [http://jinja.pocoo.org/docs/dev/templates/#block-assignments block assignments] doc.
     962
     963So one way to deal with complex translatable content is to factor out the complex parts in variable blocks.
     964
     965===== assigning blocks of text to variables (`set` ... `endset`) #set_endset
     966
     967This feature is particularly useful in combination with `trans`, when dealing with complex expansions in translatable content.
     968See [http://jinja.pocoo.org/docs/dev/templates/#block-assignments block assignments] doc.
    952969 - Genshi:
    953970   {{{#!html+genshi
     
    982999   }}}
    9831000
    984 Note that another tricky case is when you want to use `gettext` and one of the variables is Markup. Using the `|safe` filter is needed, but that's not enough, as currently `gettext()` doesn't support Markup, you need to use `tgettext()` which is available with the `tag_` shortcut:
     1001===== translation of Markup content `tag_()`
     1002Note that another tricky case is when you want to use `gettext` and one of the variables is Markup. The `_()` and `gettext()` functions don't support Markup, you need to use `tgettext()` which is also available with the `tag_()` shortcut:
    9851003{{{#!html+jinja
    9861004  <em>
     
    9901008    # endset
    9911009    ${tag_("Set your email in %(preferences_link)s",
    992            preferences_link=preferences_link|safe)}
     1010           preferences_link=preferences_link)}
    9931011  </em>
    9941012}}}
     
    9991017 - when you need to output a plain "#" character at the beginning of a line, this will be parsed as a line statement; the trick here is to use an empty inline comment as a prefix: `{##}# ...` (see [61e8d9ec/cboos.git])
    10001018 - when you need to output indented text, this can be made difficult due to our `lstrip_block` configuration setting; you can work around this by embedding Python strings with the exact whitespace content you need in variable expressions: `    ${"\t  "}` (see [0fdef480/cboos.git])
    1001 
    1002