[[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
  • $element
}}} or simply: {{{ #!xml
  • $element
}}} ==== 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

  • : Error
    ()
}}} - 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