From 1771b2457e81c4d5cd344a5fa34e4631c86b13ed Mon Sep 17 00:00:00 2001 From: Juri Leino Date: Thu, 18 Sep 2025 12:23:43 +0200 Subject: [PATCH] doc(templating): add legacy syntax, update examples fixes #1136 fixes #247 --- .../data/templating/listings/listing-12.txt | 20 ++-- .../data/templating/listings/listing-13.txt | 13 ++- .../data/templating/listings/listing-7.xml | 6 +- .../data/templating/templating.xml | 91 +++++++++++++------ 4 files changed, 86 insertions(+), 44 deletions(-) diff --git a/src/main/xar-resources/data/templating/listings/listing-12.txt b/src/main/xar-resources/data/templating/listings/listing-12.txt index 48a3c284..cbf27b1d 100644 --- a/src/main/xar-resources/data/templating/listings/listing-12.txt +++ b/src/main/xar-resources/data/templating/listings/listing-12.txt @@ -16,7 +16,8 @@ import module namespace templates="http://exist-db.org/xquery/html-templating"; import module namespace app="http://my.domain/myapp" at "app.xql"; declare option output:method "html"; -declare option output:html-version "5"; +declare option output:html-version "5.0"; +declare option output:media-type "text/html"; (: : We have to provide a lookup function to templates:apply to help it @@ -24,17 +25,16 @@ declare option output:html-version "5"; : module cannot see the application modules, but the inline function : below does see them. :) -let $lookup := function($functionName as xs:string, $arity as xs:int) { - try { - function-lookup(xs:QName($functionName), $arity) - } catch * { - () - } +declare variable $lookup := function($functionName as xs:string, $arity as xs:integer) as function(*)? { + function-lookup(xs:QName($functionName), $arity) } + (: : The HTML is passed in the request from the controller. : Run it through the templating framework and return the result. :) -let $content := request:get-data() -return - templates:apply($content, $lookup, ()) +templates:apply( + request:get-data(), + $lookup, + () (: the third parameter is the initial model :) +) diff --git a/src/main/xar-resources/data/templating/listings/listing-13.txt b/src/main/xar-resources/data/templating/listings/listing-13.txt index 1ac511c6..30e3393e 100644 --- a/src/main/xar-resources/data/templating/listings/listing-13.txt +++ b/src/main/xar-resources/data/templating/listings/listing-13.txt @@ -1,14 +1,17 @@ -(: Pass all requests to HTML files through view.xql, which handles HTML templating :) -if (ends-with($exist:resource, ".html")) then +(: Pass all requests to HTML files through view.xq, which handles HTML templating :) +if (ends-with($exist:resource, ".html")) then ( - + - + - \ No newline at end of file + +) else ( + (: do something with all other requests :) +) diff --git a/src/main/xar-resources/data/templating/listings/listing-7.xml b/src/main/xar-resources/data/templating/listings/listing-7.xml index b1421b85..a1481d03 100644 --- a/src/main/xar-resources/data/templating/listings/listing-7.xml +++ b/src/main/xar-resources/data/templating/listings/listing-7.xml @@ -1,8 +1,8 @@ -
+

Found - + hits

-
    +
diff --git a/src/main/xar-resources/data/templating/templating.xml b/src/main/xar-resources/data/templating/templating.xml index c6abb8d1..e04bcb30 100644 --- a/src/main/xar-resources/data/templating/templating.xml +++ b/src/main/xar-resources/data/templating/templating.xml @@ -5,7 +5,7 @@ xmlns:xlink="http://www.w3.org/1999/xlink"> HTML Templating Module - 2Q21 + 3Q25 application-development @@ -23,11 +23,12 @@ The main goal of the HTML templating framework is a clean separation of concerns. Generating entire pages in XQuery is quick and dirty, but makes maintenance and code - sharing difficult. Ideally people should be able to look at the HTML view of an + sharing difficult. Ideally, people should be able to look at the HTML view of an application and modify its look and feel without knowing XQuery. The application logic, written in XQuery, should be kept separate. Likewise, the XQuery developer should only have to deal with the minimal amount of HTML (generated dynamically). - The templating module also handles most of the HTTP processing an application + + The templating module also handles most of the HTTP processing an application requires. It does so using sophisticated features like automatic parameter injection and type conversion. The goal was to remove repeating code like: @@ -45,28 +46,54 @@ Writing the HTML - The templating module is based mainly on conventions. Wherever possible it tries to + + The templating module is based mainly on conventions. Wherever possible it tries to make a best guess instead of requiring additional code or annotations. This works as - long as the conventions used are sufficiently clear. - The input for the templating framework is always a plain HTML file. The module scans + long as the conventions used are sufficiently clear. + + + The input for the templating framework is always a plain HTML file. The module scans the HTML view for elements with data-template attributes following a simple convention and tries to translate them into XQuery function calls. By using data-* attributes, the HTML remains sufficiently clean and does not get messed up with application code. A web designer could take the HTML files and - work on it without being bothered by the extra class names. - To start with the usual "Hello world" example: + work on it without being bothered by the extra class names. + + + To start with the usual "Hello world" example: + - When the module encounters data-template="demo:hello", it will try to find a function named + + When the module encounters data-template="demo:hello", it will try to find a function named demo:hello in all the modules known within the current XQuery context. If a function is found and its signature follows a certain convention, it will be called and the div will either be replaced or enhanced by whatever the function returns. - The data-template attribute must follow the function naming pattern. + + The data-template attribute must follow the function naming pattern. It is also possible to pass static parameters to a template call. Additional parameters go into one or more attributes data-template-*, where the * should be replace by the name of the parameter, - e.g. data-template-path="menu.html". + e.g. data-template-path="menu.html". + + + Legacy Template Syntax + + You might encounter older templates that use the class attribute to call template functions. + Like <title class="app:title" /> + + + This is considered legacy syntax and should be re-written to use data-template + attributes instead. + + + In fact, version 1.1.0 introduced a configuration option $templates:CONFIG_USE_CLASS_SYNTAX. + Setting it to false() will cause all class attributes to be ignored when reading + template files. This is necessary in order to use colons in class names, which some CSS frameworks tend to do. + This option will likely be turned on by default with the next major release of this library. + + @@ -74,10 +101,15 @@ Templating Functions - A templating function is an ordinary XQuery function in a module which takes at least - two parameters of a specific type. Additional parameters are allowed. If a function does - not follow this convention it will be ignored by the framework. - For example, our "Hello world!" function could be defined as follows: + + A templating function is an ordinary XQuery function in a module. It must accept at least + two parameters, $node and $model. + Additional parameters are allowed. If a function does not follow this convention it will be + ignored by the framework. + + + For example, our "Hello world!" function could be defined as follows: + The two required parameters are $node and $model: @@ -228,8 +260,7 @@ Important Note The old version of the templating module used to be part of the deprecated shared-resources package, while a new and improved version - is now available in its own - expath package. We recommend to update to the new package with the short name + is now available as its own expath library package. We recommend to update to the new package with the short name templating, available on the eXist-db dashboard. To update, follow the 3 steps below: @@ -241,31 +272,39 @@ - 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): + + 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): + Calling the Templating from a Main XQuery - A complete main module which calls the - templating framework to process an HTML file passed in the HTTP request body could look - as follows: + + A complete main module which calls the templating framework to process an HTML file passed + in the HTTP request body could look as follows: + - This module would be called from the URL rewriting controller. For example, we could + This module can now be called from the URL rewriting controller. For example, we can add a rule to controller.xq to pass any .html resource to the above main query (saved to modules/view.xq): - The only part of the main module code which might look a bit unusual is the inline + + The only part of the main module code which might look a bit unusual is the inline lookup function: the templating module uses dynamic function calls to execute template functions in application modules. But unfortunately, XQuery modules can only "see" functions in their own context. There is therefore no way for the templating module to determine what functions are defined in application modules which are outside its context. So it needs to be "helped" by providing a callback function to resolve function references. The lookup function is defined in the main context and can access all the - modules imported into the main module. - Normally you can just copy and paste the main module code as given above. To adapt it - to your own application, just import your application modules and you're done. + modules imported into the main module. + + + Normally you can just copy and paste the main module code as given above. To adapt it + to your own application, just import your application modules and you're done. +