Template Mechanism

Last modified by Vincent Massol on 2026/08/30 19:36

Explanation

The renderer carries no LaTeX of its own in Java. Exporting a page walks its XDOM, the tree of Blocks the wiki syntax was parsed into, and renders each Block with a Velocity template holding the LaTeX commands to produce. Which template that is is decided by name, and the name comes from the Block.

One Template per Block

A Block asks for the template bearing its own simple class name: a WordBlock is rendered by WordBlock, a ParagraphBlock by ParagraphBlock. The XDOM sitting at the root of the tree is a Block like the others, so it has a template too, XDOM, and that one stands for the whole document.

The templates the extension ships live inside its jar, as classloader resources under templates/latex/default/. Reading the one named after a Block is the shortest way to find out what that Block currently produces.

A Block whose template is found nowhere is not dropped: its children are processed in its place, and only the container's own LaTeX is lost.

Where a Template Is Looked Up

Every Block resolves to two paths, tried in that order: latex/<name>, which is yours, then latex/default/<name>, which is the extension's. The first that exists wins, so a latex/ParagraphBlock you supply replaces the shipped latex/default/ParagraphBlock for every paragraph of every export.

Each of the two paths is then resolved by XWiki's own template lookup, which searches three places in order:

  • The current skin. When the skin is a wiki page, an XWiki.XWikiSkinFileOverrideClass xobject whose path is that path, which is how you override a template, or an xproperty of its XWiki.XWikiSkins xobject named after the path — see the Skin Application. When the skin is on the filesystem, a file at that path under skins/<skin name>/.
  • The templates directory of the webapp, so templates/latex/<name> for the first path.
  • The classloader, again under templates/. This is where the shipped templates are found inside the extension's jar, and it is what makes WEB-INF/classes/templates/latex/<name> an override point that needs no skin at all.

The Document Template

The XDOM template is the frame everything else is rendered into:

\documentclass{$latex.properties.documentClass}

$latex.processor.render('Preamble')

\begin{document}$latex.processor.process($latex.block.getChildren())

\end{document}

Two things follow from it. Preamble is a template belonging to no Block at all: it exists only because the XDOM template renders it by name, which is what makes latex/Preamble the place to change everything between the document class and \begin{document}. And the class is not fixed — it comes from the export's documentClass option, falling back to article when that option is left empty.

The shipped template wraps these lines in the XDOM extension points, which is how an extension adds to the generated document without taking the template over.

Naming a Template on a Block

A Block can also ask for a template by name rather than by class, through a latex-template parameter. Here one table cell is rendered by the custom1 template:

|=Head1|=Head2
|cell1|(% latex-template="custom/custom1" %)cell2

The value is the path without the latex/ prefix, and it goes through the same two-path lookup as a class-derived name: latex/custom/custom1 first, then latex/default/custom/custom1.

Related

Get Connected