[[PageOutline(2-4)]]
= TracDev/ApiChanges/0.11 =
'''Note: Development of Trac [milestone:0.11] has started with r3804 and the trunk now uses ''[http://genshi.edgewall.org/ Genshi]'' instead of ClearSilver, for its template engine.
Nevertheless, you should have in mind that the information in this page corresponds to a ''work in progress''.'''
== Migrating away from Clearsilver ==
ClearSilver has proven a bit uncomfortable to work with, and search for better alternatives were done a few months ago. The [http://kid-templating.org/ Kid] templating language was unanimously found appealing, to the point cmlenz did a porting of Trac to Kid, during the DrProject fork. This in turn was found painful, and prompted Christopher to start his own, enhanced, version of Kid currently maturing as [http://genshi.edgewall.org/ Genshi].
Migrating away from ClearSilver to use Genshi is scheduled for early [milestone:0.11], and is mostly complete in the source:sandbox/genshi branch at this point (r3728).
The following documentation is by no means a replacement for the excellent documentation you'll find in the Genshi site.
You should go there for a more in-depth understanding of how Genshi actually works and should be used. Here we'll focus on the differences with Clearsilver.
For migrating your own templates, a good way to start is to learn by example.
Compare the Clearsilver templates found in source:trunk/templates and their corresponding Genshi ones in source:sandbox/genshi/templates.
Then, in the same way, compare the various web_ui.py controllers you'll find in both branches.
=== Changes in the template syntax ===
Most of the time, the porting is a straightforward operation.
==== expand a variable ====
- Clearsilver [[xml()]]
- Genshi [[xml($the_variable)]]
==== expand a simple computation ====
- Clearsilver [[xml()]]
- Genshi [[xml(${the_variable+1})]]
==== include another template ====
- Clearsilver [[xml()]]
- Genshi [[xml()]]
==== simple if...then (no else) ====
- Clearsilver [[xml(OK)]]
- Genshi [[xml(OK)]] or simply [[xml(OK)]]
==== if...then...else ====
- Clearsilver
{{{
#!xml
OK
!!!
}}}
- Genshi
{{{
#!xml
OK
!!!
}}}
or simply:
{{{
#!xml
OK
!!!
}}}
The // is a bit heavy-weight for a simple if/else, but on the other hand, the construct is more general (think switch/case, or the equivalent choose/when/otherwise in XSLT).
==== iterate over a collection ====
- Clearsilver
{{{
#!xml
}}}
- Genshi
{{{
#!xml
}}}
or simply:
{{{
#!xml
}}}
==== define a macro ====
- Clearsilver
{{{
#!xml
}}}
- Genshi
{{{
#!xml
$key$val
}}}
As you can see, with Genshi it's also easy to specify default values for the macro arguments.
==== set a variable ====
- Clearsilver
{{{
#!xml
We have 10 ?>too much elements.
}}}
- Genshi
{{{
#!xml
We have ${count > 10 and 'too much' or count} elements.
}}}
Note that we had to use `>` in Genshi, instead of directly `>` as in Clearsilver.
==== Examples ====
Let's first take a simple full-contained example from the Trac source, the simple index.cs / index.html templates.
- Clearsilver [source:trunk/templates/index.cs@3725 index.cs]:
{{{
#!xml
Available Projects
Available Projects
}}}
- Genshi [source:sandbox/genshi/templates/index.html@3728 index.html]:
{{{
#!xml
Available Projects
Available Projects
}}}
Some remarks:
- Note the possible use of multiple genshi attributes in the same element
(in the above, the `` element has a `py:for` and a `py:choose` attribute).
- When there's only one element to output conditionally, one should use a genshi attribute
(the `py:for="project in projets"` and the `py:when="project.href"` in the above).
Otherwise, one should use a genshi element (here, the ``).
- In this small example, there's no common Trac layout used (as the index is a bit special).
For how a "normal" template looks like, see for example
[source:sandbox/genshi/templates/diff_form.html diff_form.html], another small template.
Note that a Genshi template can usually be rendered directly to have a taste of how it will look like:
----
{{{
#!html
Available Projects
}}}
----
This comes from an important property of Genshi templates: '''they must themselves be well-formed XML documents'''.
That was not a constraint in Clearsilver, and sometimes the logic in those templates took "advantage" of that, e.g. by conditionally inserting end/start pairs of tags. Such templates are the hardest to port, because you actually have to think a bit... See for example the [source:sandbox/genshi/templates/query.html query.html] template.
Of course, the great benefit of this constraint is that you'll end up quite naturally with well-formed content, which was far from being a trivial achievement using Clearsilver templates. Granted, you could still insert directly some non well-formed `Markup` data in your template, but again, if you use the [http://genshi.edgewall.org/wiki/Documentation/builder.html genshi.builder] ''tag'' facility for this, that's hardly a risk.
Another example from Trac, a bit more complex.
This illustrates how to use `` and ``, to convert a Clearsilver macro using `` and ``.
- Clearsilver
{{{
#!xml
def:browser_path_links(path, file) ?> class="first" title="Go to root directory" title="View " href="">/
$part.name
/
}}}
=== Changes in the controllers ===
==== Implementing the `IRequestHandler` interface ====
Previously, all the data fed to a template had to be placed inside the `req.hdf` HDF wrapper object.
With Genshi, the data for the template is basically a `dict`, which has to be returned by `process_request`
at the same time as the template name. Check [source:sandbox/genshi/trac/wiki/web_ui.py trac.wiki.web_ui] for an example.
==== Generating content ====
When one wants to directly render a template, the Chrome component facilities should be used.
Check the [source:sandbox/genshi/trac/web/chrome.py@3730#L422 Chrome.load_template]
and `render_method` methods. Note however that this API is still rapidly evolving.
Usage examples:
- Implementing [source:sandbox/genshi/trac/ticket/query.py@3725#L740 Ticket Query] macro (''table'' mode)
- Sending [source:sandbox/genshi/trac/notification.py@3725#L99 notification] e-mails