Creating a Theme¶
Creating a theme proceeds as documented in the Nikola reference. This document will focus on the template features that nti.nikola_chameleon provides. Make sure you’ve read Getting Started before reading this.
Your theme should be laid out according to the Nikola documentation.
You’ll need to specify nti.nikola_chameleon
as the engine
in
your theme meta file.
The only directory that nti.nikola_chameleon is interested in is your
templates/
folder.
There are three types of files that nti.nikola_chameleon will look for in this directory: templates, macros (helpers) and ZCML configuration. A complete them can be written just with template files and (optionally, but helpfully) macro files.
Note
This document will contain frequent mentions of the ways the
component architecture can be used to make themes
flexible and make changing and customizing them through
inheritance or configuration easier. You are not required to
use these features if you don’t want to. You can build an
entire theme just based on the files in the templates
directory and the Chameleon load:
expression.
Templates¶
Files in the templates directory that match the pattern *.tmpl.pt
are ZPT files that Nikola can directly use as templates (when stripped
of the .pt
suffix). For example, index.tmpl.pt
will be used
when Nikola requests index.tmpl
. Nikola maintains a list of the various
templates it may use by default (although a number of those templates,
such as base.tmpl
and archive_navigation_helper.tmpl
are
internal helpers specific to the default Nikola theme implementations,
even if they are not called out as such).
The most obvious way to create a theme, then, is to create a
.tmpl.pt
file for each standard template that Nikola uses and
populate it with your design.
Views for Sharing Macros¶
Each .tmpl.pt
file found in this directory is registered as a
default view with the same name so it can be found via traversal. This
is useful to be able to share macros and fill slots. For example, if
base.tmpl.pt
is the generic “layout” template and it defines the
macro base
with the slot content
, the story.tmpl.pt
may
take advantage of that layout by using that macro and filling in that
slot, finding the base.tmpl
macro via traversal:
<html metal:use-macro="context/@@base.tmpl/index/macros/base"
xmlns:i18n="http://xml.zope.org/namespaces/i18"
xmlns:metal="http://xml.zope.org/namespaces/metal">
<article metal:fill-slot="content">
My content template goes here
</article>
</html>
Although the standard Chameleon load:
expression type is available, the traversal based mechanism is much
more flexible because it allows themes that extend yours to provide a
new base.tmpl
view. It is also useful to provide different macros
depending on the context
object (or whatever objects you traverse
through). For more on that, see Leveraging the Component Architecture, Theme Inheritance
and ZCML.
Macros¶
Files in the templates directory that match the pattern *.macro.pt
are not used directly by Nikola as templates. Instead, they are parsed
to find all of the macros they define. Each macro is registered as the
default macro for its name so that the macro:
expression type from
z3c.macro can be used to
find it.
The most direct translation from the Nikola base template
implementations and documentations would be to have each
_helper.tmpl
become a .macro.pt
file, for example,
math_helper.macro.pt
and post_helper.macro.pt
for
math_helper.tmpl
and post_helper.tmpl
, respectively.
Continuing our story example above, suppose the file
post_helper.macro.pt
defined an html_title
macro:
<metal:block xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n">
<metal:block metal:define-macro="html_title">
<h1 class="p-name entry-title" itemprop="headline name"
tal:define="title options/title"
tal:condition="python:title and not context.meta('hidetitle')">
<a href="${context/permalink}" class="u-url">${context/title}</a>
</h1>
</metal:block>
</metal:block>
Our story.tmpl.pt
(and other files) could use this macro like so:
<html metal:use-macro="context/@@base.tmpl/index/macros/base"
xmlns:i18n="http://xml.zope.org/namespaces/i18"
xmlns:metal="http://xml.zope.org/namespaces/metal">
<article metal:fill-slot="content">
<header>
<h1 metal:use-macro="macro:html_title">Replaced by the title</h1>
</header>
My content template goes here
</article>
</html>
Now, we could have implemented that with the load:
expression
type:
<html metal:use-macro="context/@@base.tmpl/index/macros/base"
xmlns:i18n="http://xml.zope.org/namespaces/i18"
xmlns:metal="http://xml.zope.org/namespaces/metal">
<article metal:fill-slot="content">
<header tal:define="post_helper load:post_helper.macro.pt">
<h1 metal:use-macro="post_helper/macros/html_title">Replaced by the title</h1>
</header>
My content template goes here
</article>
</html>
However, as with templates, the use of the macro:
expression type
allows themes to extend us and replace that macro with their own
version, and it allows us to produce macros that do different things
depending on context. For more on that, see Leveraging the Component Architecture,
Theme Inheritance and ZCML.
Caution
If you implement a macro of the same name in two different files, nti.nikola_chameleon will warn you, and the one in the last file that defines it will be what is registered.
See also
ZCML¶
Finally, after registering all the templates and macros, if your
directory contains a theme.zcml
file, nti.nikola_chameleon will
load that file. It is a standard zope.configuration file.
You can use this file to replace any registrations that nti.nikola_chameleon makes by default. You can also use it to provide more specific versions of macros, tailored to particular types of objects, and you can use it to provide viewlets. (For more on viewlets see Using Viewlets.) You can also use it to rename entire templates or register more specific templates.
The theme.zcml
file is executed in the nti.nikola_chameleon
package. This means that you can easily refer to the various object
types with a simple . prefix.
If your theme extends another theme, the ZCML will be executed in order of theme inheritance; this allows themes to replace registrations from earlier themes. For more on theme inheritance, see Theme Inheritance.
Let’s take a look at an example. Don’t worry if much of it doesn’t make sense yet, we’ll cover those concepts later.
<!-- -*- mode: nxml -*- -->
<configure xmlns="http://namespaces.zope.org/zope"
xmlns:i18n="http://namespaces.zope.org/i18n"
xmlns:zcml="http://namespaces.zope.org/zcml"
xmlns:z3c="http://namespaces.zope.org/z3c"
xmlns:browser="http://namespaces.zope.org/browser"
>
<include package="z3c.macro" />
<include package="z3c.macro" file="meta.zcml" />
<include package="z3c.template" file="meta.zcml" />
<include package="zope.viewlet" file="meta.zcml" />
<include package="nti.nikola_chameleon" file="meta.zcml" />
<!-- Extra macros -->
<z3c:macro name="open_graph_metadata"
for=".interfaces.IPost"
view="*"
template="post_helper.pt"
layer="*" />
<!-- Viewlets and Viewlet managers -->
<!-- To extend, use a new name. To replace use the same name
with at least as specific a registration.
-->
<!-- Extra head -->
<!-- The normal extra head for a page is called 'default_extra_head' -->
<browser:viewletManager
name="extra_head"
provides=".interfaces.IHtmlHeadViewletManager"
class="zope.viewlet.manager.WeightOrderedViewletManager"
permission="zope.Public"
/>
<browser:viewlet
name="default_extra_head"
manager=".interfaces.IHtmlHeadViewletManager"
template="v_index_extra_head.pt"
permission="zope.Public"
layer=".interfaces.IIndexPageKind"
weight="0"
/>
<!--
We don't have files on disk that match all the template names
that Nikola likes to use by default. So lets set up some aliases
to the files that we *do* have that implement the required
functionality.
-->
<z3c:template
template="index.tmpl.pt"
name="archiveindex.tmpl"
layer=".interfaces.IArchiveIndexPageKind"
/>
<z3c:template
template="generic_post_list.pt"
name="tag.tmpl" />
<z3c:template
template="generic_post_list.pt"
name="author.tmpl" />
</configure>
Other Files¶
Any other files in this directory are ignored by nti.nikola_chameleon.
You can use plain .pt
files to implement additional macros or
entire templates. You can refer to them in your theme.zcml
file
(preferred) and access them via macro:
expressions or traversal,
or you could explicitly reference them using load:
expressions.