Skip to content

Commit 6efefdf

Browse files
authored
Merge pull request #1145 from line-o/docs/templating
2 parents ab9756e + 1771b24 commit 6efefdf

File tree

4 files changed

+86
-44
lines changed

4 files changed

+86
-44
lines changed

src/main/xar-resources/data/templating/listings/listing-12.txt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,25 @@ import module namespace templates="http://exist-db.org/xquery/html-templating";
1616
import module namespace app="http://my.domain/myapp" at "app.xql";
1717

1818
declare option output:method "html";
19-
declare option output:html-version "5";
19+
declare option output:html-version "5.0";
20+
declare option output:media-type "text/html";
2021

2122
(:
2223
: We have to provide a lookup function to templates:apply to help it
2324
: find functions in the imported application modules. The templates
2425
: module cannot see the application modules, but the inline function
2526
: below does see them.
2627
:)
27-
let $lookup := function($functionName as xs:string, $arity as xs:int) {
28-
try {
29-
function-lookup(xs:QName($functionName), $arity)
30-
} catch * {
31-
()
32-
}
28+
declare variable $lookup := function($functionName as xs:string, $arity as xs:integer) as function(*)? {
29+
function-lookup(xs:QName($functionName), $arity)
3330
}
31+
3432
(:
3533
: The HTML is passed in the request from the controller.
3634
: Run it through the templating framework and return the result.
3735
:)
38-
let $content := request:get-data()
39-
return
40-
templates:apply($content, $lookup, ())
36+
templates:apply(
37+
request:get-data(),
38+
$lookup,
39+
() (: the third parameter is the initial model :)
40+
)
Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1-
(: Pass all requests to HTML files through view.xql, which handles HTML templating :)
2-
if (ends-with($exist:resource, ".html")) then
1+
(: Pass all requests to HTML files through view.xq, which handles HTML templating :)
2+
if (ends-with($exist:resource, ".html")) then (
33
<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
44
<view>
5-
<forward url="{$exist:controller}/modules/view.xql">
5+
<forward url="{$exist:controller}/modules/view.xq">
66
<set-attribute name="$exist:prefix" value="{$exist:prefix}"/>
77
<set-attribute name="$exist:controller" value="{$exist:controller}"/>
88
</forward>
99
</view>
1010
<error-handler>
1111
<forward url="{$exist:controller}/error-page.html" method="get"/>
12-
<forward url="{$exist:controller}/modules/view.xql"/>
12+
<forward url="{$exist:controller}/modules/view.xq"/>
1313
</error-handler>
14-
</dispatch>
14+
</dispatch>
15+
) else (
16+
(: do something with all other requests :)
17+
)
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
<div class="demo:search">
1+
<div data-template="demo:search">
22
<p>
33
Found
4-
<span class="demo:hit-count"/>
4+
<span data-template="demo:hit-count"/>
55
hits
66
</p>
7-
<ul class="demo:result-list"/>
7+
<ul data-template="demo:result-list"/>
88
</div>

src/main/xar-resources/data/templating/templating.xml

Lines changed: 65 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
xmlns:xlink="http://www.w3.org/1999/xlink">
66
<info>
77
<title>HTML Templating Module</title>
8-
<date>2Q21</date>
8+
<date>3Q25</date>
99
<keywordset>
1010
<keyword>application-development</keyword>
1111
</keywordset>
@@ -23,11 +23,12 @@
2323

2424
<para>The main goal of the HTML templating framework is a clean separation of concerns.
2525
Generating entire pages in XQuery is quick and dirty, but makes maintenance and code
26-
sharing difficult. Ideally people should be able to look at the HTML view of an
26+
sharing difficult. Ideally, people should be able to look at the HTML view of an
2727
application and modify its look and feel without knowing XQuery. The application logic,
2828
written in XQuery, should be kept separate. Likewise, the XQuery developer should only
2929
have to deal with the minimal amount of HTML (generated dynamically).</para>
30-
<para>The templating module also handles most of the HTTP processing an application
30+
<para>
31+
The templating module also handles most of the HTTP processing an application
3132
requires. It does so using sophisticated features like automatic parameter injection and
3233
type conversion. The goal was to remove repeating code like:</para>
3334
<programlisting language="xquery" xlink:href="listings/listing-1.txt"/>
@@ -45,39 +46,70 @@
4546
<sect1 xml:id="write-html">
4647
<title>Writing the HTML</title>
4748

48-
<para>The templating module is based mainly on conventions. Wherever possible it tries to
49+
<para>
50+
The templating module is based mainly on conventions. Wherever possible it tries to
4951
make a best guess instead of requiring additional code or annotations. This works as
50-
long as the conventions used are sufficiently clear.</para>
51-
<para>The input for the templating framework is always a plain HTML file. The module scans
52+
long as the conventions used are sufficiently clear.
53+
</para>
54+
<para>
55+
The input for the templating framework is always a plain HTML file. The module scans
5256
the HTML view for elements with <code>data-template</code> attributes
5357
following a simple convention and tries to translate them into XQuery
5458
function calls. By using <code>data-*</code> attributes, the HTML remains sufficiently clean and does
5559
not get messed up with application code. A web designer could take the HTML files and
56-
work on it without being bothered by the extra class names.</para>
57-
<para>To start with the usual "Hello world" example:</para>
60+
work on it without being bothered by the extra class names.
61+
</para>
62+
<para>
63+
To start with the usual "Hello world" example:
64+
</para>
5865
<programlisting language="xml" xlink:href="listings/listing-2.xml"/>
5966

60-
<para>When the module encounters <code>data-template="demo:hello"</code>, it will try to find a function named
67+
<para>
68+
When the module encounters <code>data-template="demo:hello"</code>, it will try to find a function named
6169
<literal>demo:hello</literal> in all the modules known within the current XQuery context. If a function is found and its signature
6270
follows a certain convention, it will be called and the <tag>div</tag> will
6371
either be replaced or enhanced by whatever the function returns.</para>
6472

65-
<para>The <literal>data-template</literal> attribute must follow the function naming pattern.
73+
<para>
74+
The <literal>data-template</literal> attribute must follow the function naming pattern.
6675
It is also possible to pass static parameters to a template call.
6776
Additional parameters go into one or more attributes
6877
<literal>data-template-*</literal>, where the * should be replace by the name of the parameter,
69-
e.g. <literal>data-template-path="menu.html"</literal>.</para>
78+
e.g. <literal>data-template-path="menu.html"</literal>.
79+
</para>
80+
<sect2 xml:id="legacy-template-syntax">
81+
<title>Legacy Template Syntax</title>
82+
<para>
83+
You might encounter older templates that use the class attribute to call template functions.
84+
Like <code>&lt;title class="app:title" /&gt;</code>
85+
</para>
86+
<para>
87+
This is considered <emphasis>legacy</emphasis> syntax and should be re-written to use <code>data-template</code>
88+
attributes instead.
89+
</para>
90+
<para>
91+
In fact, version 1.1.0 introduced a configuration option <literal>$templates:CONFIG_USE_CLASS_SYNTAX</literal>.
92+
Setting it to <literal>false()</literal> will cause all class attributes to be ignored when reading
93+
template files. This is necessary in order to use colons in class names, which some CSS frameworks tend to do.
94+
This option will likely be <emphasis>turned on by default</emphasis> with the next major release of this library.
95+
</para>
96+
</sect2>
7097
</sect1>
7198

7299
<!-- ================================================================== -->
73100

74101
<sect1 xml:id="templating">
75102
<title>Templating Functions</title>
76103

77-
<para>A templating function is an ordinary XQuery function in a module which takes at least
78-
two parameters of a specific type. Additional parameters are allowed. If a function does
79-
not follow this convention it will be ignored by the framework.</para>
80-
<para> For example, our "Hello world!" function could be defined as follows:</para>
104+
<para>
105+
A templating function is an ordinary XQuery function in a module. It <emphasis>must</emphasis> accept at least
106+
two parameters, <code>$node</code> and <code>$model</code>.
107+
Additional parameters are allowed. If a function does not follow this convention it will be
108+
ignored by the framework.
109+
</para>
110+
<para>
111+
For example, our "Hello world!" function could be defined as follows:
112+
</para>
81113
<programlisting language="xquery" xlink:href="listings/listing-5.txt"/>
82114
<para>The two required parameters are <code>$node</code> and <code>$model</code>: </para>
83115
<itemizedlist>
@@ -228,8 +260,7 @@
228260
<title>Important Note</title>
229261
<para>The old version of the templating module used to be part of the <emphasis>deprecated</emphasis>
230262
shared-resources package, while a <link xlink:href="https://github.com/eXist-db/templating/">new and improved version</link>
231-
is now available in its own
232-
expath package. We recommend to update to the new package with the short name
263+
is now available as its own expath library package. We recommend to update to the new package with the short name
233264
<emphasis>templating</emphasis>, available on the eXist-db dashboard. To update, follow the 3 steps below:</para>
234265
<orderedlist>
235266
<listitem>
@@ -241,31 +272,39 @@
241272
<programlisting language="xquery" xlink:href="listings/listing-15.txt"/>
242273
</listitem>
243274
<listitem>
244-
<para>New standard templating functions will go into a separate module, so you may want to add the following import in addition to the one above, which will give you access to the lib:parse-params template function (and others in the future):</para>
275+
<para>
276+
New standard templating functions will go into a separate module, so you may want to add the following import
277+
in addition to the one above, which will give you access to the lib:parse-params template function (and others in the future):
278+
</para>
245279
<programlisting language="xquery" xlink:href="listings/listing-16.txt"/>
246280
</listitem>
247281
</orderedlist>
248282
</sect2>
249283
<sect2 xml:id="main-xquery">
250284
<title>Calling the Templating from a Main XQuery</title>
251-
<para>A complete main module which calls the
252-
templating framework to process an HTML file passed in the HTTP request body could look
253-
as follows:</para>
285+
<para>
286+
A complete main module which calls the templating framework to process an HTML file passed
287+
in the HTTP request body could look as follows:
288+
</para>
254289
<programlisting language="xquery" xlink:href="listings/listing-12.txt"/>
255-
<para>This module would be called from the URL rewriting controller. For example, we could
290+
<para>This module can now be called from the URL rewriting controller. For example, we can
256291
add a rule to <literal>controller.xq</literal> to pass any .html resource to the above
257292
main query (saved to <literal>modules/view.xq</literal>):</para>
258293
<programlisting language="xquery" xlink:href="listings/listing-13.txt"/>
259-
<para>The only part of the main module code which might look a bit unusual is the inline
294+
<para>
295+
The only part of the main module code which might look a bit unusual is the inline
260296
lookup function: the templating module uses dynamic function calls to execute template
261297
functions in application modules. But unfortunately, XQuery modules can only "see"
262298
functions in their own context. There is therefore no way for the templating module to
263299
determine what functions are defined in application modules which are outside its
264300
context. So it needs to be "helped" by providing a callback function to resolve function
265301
references. The lookup function is defined in the main context and can access all the
266-
modules imported into the main module.</para>
267-
<para>Normally you can just copy and paste the main module code as given above. To adapt it
268-
to your own application, just import your application modules and you're done.</para>
302+
modules imported into the main module.
303+
</para>
304+
<para>
305+
Normally you can just copy and paste the main module code as given above. To adapt it
306+
to your own application, just import your application modules and you're done.
307+
</para>
269308
</sect2>
270309
</sect1>
271310

0 commit comments

Comments
 (0)