# Migrating from Genshi

Kajiki uses syntax derived from the syntax of Genshi. In particular, the following directives are supported, with semantics intended to be nearly identical to those of Genshi.

> - `py:def`

> - `py:choose` – renamed `py:with`

> - `py:when` – renamed `py:case`

> - `py:otherwise` – renamed `py:else`

> - `py:for`

> - `py:if`

> - `py:with`

> - `py:replace`

> - `py:content`

> - `py:attrs`

> - `py:strip`

> - `xi:include` – renamed `py:include`

Note that, in particular, `py:match` is not supported. But Kajiki supports the following additional directives:

> - `py:extends` - indicates that this is an extension template. The parent template will be read in and used for layout, with any `py:block` directives in the child template overriding the `py:block` directives defined in the parent.

> - `py:block` - used to name a replaceable ‘slot’ in a parent template, or to specify a slot override in a child template. The `py:block` semantics are modeled after the `{% block %}` semantics of Jinja2.

Generally, migration consists of a few steps that can be simple or quite difficult based on your fondness of the `py:match` directive in Genshi. In simple cases where you have one `master.html` template with a few `py:match` directives that is `xi:included` into all your page templates, the following steps should suffice:

> - Rename tags and attributes as indicated above; e.g. `xi:include` becomes `py:include`.

> - Rewrite your include directives to use Kajiki’s module naming system and relative imports.

> - In a simple case where you have only a few `py:match` directives, all of which are in a `master.html` template that is being included from child templates, I recommend that you rewrite the `master.html` as `layout.html`, defining named `py:block` regions that will be overridden in child templates.

> - In your child templates, remove the `<xi:include href="master.html">` that probably lurks near the top. Then add a `py:extends` directive to the top-level tag (usually `<html>`). The tag the parts of the child template that are intended to override parts of the parent template with the `py:block` directive.

Kajiki also provides some helper functions of Genshi:

- `defined('some_variable')` (which returns True if ‘some_variable’ exists in the template context),

- `value_of('name', default_value)`, and

- `Markup(some_string)` (which marks a string so it won’t be escaped in the output), though Kajiki prefers to call this `literal(some_string)`.

## Example Migration

Suppose you have a couple of Genshi templates, one of which called `master.html` and one of which is `index.html`. (TurboGears developers may recognize these files as slightly modified versions of the default templates deposited in a TG quickstarted project.) The contents of `master.html` are:

     1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     2                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     3<html xmlns="http://www.w3.org/1999/xhtml"
     4      xmlns:py="http://genshi.edgewall.org/"
     5      xmlns:xi="http://www.w3.org/2001/XInclude"
     6      py:strip="">
     7    <xi:include href="header.html" />
     8    <xi:include href="sidebars.html" />
     9    <xi:include href="footer.html" />
    10<head py:match="head" py:attrs="select('@*')">
    11    <meta content="text/html; charset=UTF-8" http-equiv="content-type" py:replace="''"/>
    12    <title py:replace="''">Your title goes here</title>
    13    <meta py:replace="select('*')"/>
    14    <link rel="stylesheet" type="text/css" media="screen" href="${tg.url('/css/style.css')}" />
    15    <link rel="stylesheet" type="text/css" media="screen" href="${tg.url('/css/admin.css')}" />
    16</head>
    17
    18<body py:match="body" py:attrs="select('@*')">
    19  ${header()}
    20  <ul id="mainmenu">
    21    <li class="first"><a href="${tg.url('/')}" class="${('', 'active')[defined('page') and page=='index']}">Welcome</a></li>
    22        <li><a href="${tg.url('/about')}" class="${('', 'active')[defined('page') and page=='about']}">About</a></li>
    23        <li py:if="tg.auth_stack_enabled"><a href="${tg.url('/auth')}" class="${('', 'active')[defined('page') and page=='auth']}">Authentication</a></li>
    24        <li><a href="${tg.url('/environ')}" class="${('', 'active')[defined('page') and page=='environ']}">WSGI Environment</a></li>
    25        <li><a href="http://groups.google.com/group/turbogears">Contact</a></li>
    26    <span py:if="tg.auth_stack_enabled" py:strip="True">
    27        <li py:if="not request.identity" id="login" class="loginlogout"><a href="${tg.url('/login')}">Login</a></li>
    28        <li py:if="request.identity" id="login" class="loginlogout"><a href="${tg.url('/logout_handler')}">Logout</a></li>
    29        <li py:if="request.identity" id="admin" class="loginlogout"><a href="${tg.url('/admin')}">Admin</a></li>
    30    </span>
    31  </ul>
    32  <div id="content">
    33    <py:if test="defined('page')">
    34    <div class="currentpage">
    35     Now Viewing: <span py:replace="page"/>
    36     </div>
    37    </py:if>
    38    <py:with vars="flash=tg.flash_obj.render('flash', use_js=False)">
    39        <div py:if="flash" py:content="XML(flash)" />
    40    </py:with>
    41    <div py:replace="select('*|text()')"/>
    42    <!-- End of main_content -->
    43    ${footer()}
    44  </div>
    45</body>
    46</html>

Likewise, the contents of `index.html` are as follows:

     1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     2                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     3<html xmlns="http://www.w3.org/1999/xhtml"
     4      xmlns:py="http://genshi.edgewall.org/"
     5      xmlns:xi="http://www.w3.org/2001/XInclude">
     6
     7  <xi:include href="master.html" />
     8
     9<head>
    10  <meta content="text/html; charset=UTF-8" http-equiv="content-type" py:replace="''"/>
    11  <title>Welcome to TurboGears 2.0, standing on the
    12  shoulders of giants, since 2007</title>
    13</head>
    14
    15<body>
    16    ${sidebar_top()}
    17  <div id="getting_started">
    18    <h2>Presentation</h2>
    19    <p>TurboGears 2 is rapid web application development toolkit designed to make your life easier.</p>
    20    <ol id="getting_started_steps">
    21      <li class="getting_started">
    22        <h3>Code your data model</h3>
    23        <p> Design your data model, Create the database, and Add some bootstrap data.</p>
    24      </li>
    25      <li class="getting_started">
    26        <h3>Design your URL architecture</h3>
    27        <p> Decide your URLs, Program your controller methods, Design your
    28            templates, and place some static files (CSS and/or JavaScript). </p>
    29      </li>
    30      <li class="getting_started">
    31        <h3>Distribute your app</h3>
    32        <p> Test your source, Generate project documents, Build a distribution.</p>
    33      </li>
    34    </ol>
    35  </div>
    36  <div class="clearingdiv" />
    37  <div class="notice"> Thank you for choosing TurboGears.
    38  </div>
    39</body>
    40</html>

In order to perform our kajiki migration, we begin by creating two empty templates. The first one will replace our `master.html`, and we will call it `layout.html`:

     1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     2                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     3<html>
     4    <py:include href="header" />
     5    <py:include href="footer" />
     6
     7    <head>
     8      <title py:block="title">Your title goes here</title>
     9      <py:block name="head_content">
    10        <link rel="stylesheet" type="text/css" media="screen" href="${tg.url('/css/style.css')}" />
    11        <link rel="stylesheet" type="text/css" media="screen" href="${tg.url('/css/admin.css')}" />
    12      </py:block>
    13    </head>
    14
    15    <body>
    16      <py:block name="body_header"><h1>My Header</h1></py:block>
    17      <ul py:block="mainmenu" id="mainmenu">
    18        <li class="first"><a href="${tg.url('/')}" class="${('', 'active')[defined('page') and page=='index']}">Welcome</a></li>
    19        <li><a href="${tg.url('/about')}" class="${('', 'active')[defined('page') and page=='about']}">About</a></li>
    20        <li py:if="tg.auth_stack_enabled"><a href="${tg.url('/auth')}" class="${('', 'active')[defined('page') and page=='auth']}">Authentication</a></li>
    21        <li><a href="${tg.url('/environ')}" class="${('', 'active')[defined('page') and page=='environ']}">WSGI Environment</a></li>
    22        <li><a href="http://groups.google.com/group/turbogears">Contact</a></li>
    23      </ul>
    24      <div id="content">
    25        <py:if test="defined('page')">
    26          <div class="currentpage">
    27            Now Viewing: <span py:replace="page"/>
    28          </div>
    29        </py:if>
    30        <py:with vars="flash=tg.flash_obj.render('flash', use_js=False)">
    31          <div py:if="flash" py:content="XML(flash)" />
    32        </py:with>
    33        <py:block name="body_text">Your body text goes here</py:block>
    34        <py:block name="bodyfooter">${footer()}</py:block>
    35      </div>
    36    </body>
    37</html>

Note the introduction of the `py:block` directive, and the disappearance of the `py:match` directives from `master.html`. `py:block` mimics the behavior of Jinja2 “blocks”, providing a name to a construct in a parent template which can be replaced by the contents of `py:block` -named constructs in child templates. For instance, the “title” slot in `layout.html`:

    1      <title py:block="title">Your title goes here</title>

can be replaced by a similarly-named slot in the child document `index_kajiki.html`:

    1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    2                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    3<html py:extends="layout">
    4    <py:include href="sidebars" />
    5
    6    <title py:block="title">Welcome to TurboGears 2.0, standing on the
    7      shoulders of giants, since 2007</title>

We also provide a way of including the contents of the parent template’s slot in a child template’s slot using `${parent_block()}`. The following slot in `layout.html`:

    1      <py:block name="body_header"><h1>My Header</h1></py:block>

can be replaced in `include/index_kajiki.html` with:

    1    <py:block name="body_header">
    2      ${parent_block()}
    3      <h1>Some extra header data</h1>
    4    </py:block>

Yielding the following html once rendered:

    1 <h1>My Header</h1>
    2 <h1>Some extra header data</h1>