From 7c6eaa1fe0cfd2af788ada29f4625a4f3a98e7e2 Mon Sep 17 00:00:00 2001 From: Luis Pereira Date: Tue, 20 Jan 2026 23:04:37 +0000 Subject: [PATCH] feat: adds templating system docs --- docs/TEMPLATING_SYSTEM.org | 160 +++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 docs/TEMPLATING_SYSTEM.org diff --git a/docs/TEMPLATING_SYSTEM.org b/docs/TEMPLATING_SYSTEM.org new file mode 100644 index 0000000..200130a --- /dev/null +++ b/docs/TEMPLATING_SYSTEM.org @@ -0,0 +1,160 @@ +#+TITLE: Templating System +#+AUTHOR: Asteroid Radio Development Team +#+DATE: 2026-01-17 + +* Introduction + +The radiance ecosystem includes an HTML templating system that is built on top of [[https://quickdocs.org/clip][Clip]] and [[https://shinmera.github.io/lquery/][lquery]] for advanced costumization. + +While =clip= enables conditional logic on rendering parts in an HTML document, re-using the same tag mechanics, =lquery= enables dynamically setting of element properties with some lisp integrations. + +Dominating these tools enables some smarter approaches on page content building with conditional rendering and code reuse. + +* Clip mechanics + +** Conditionals + +Clip uses HTML tags for its logic and has 3 simple conditional directives: =if=, =when= and =unless=, that work exactly as their lisp counterparts, having the =test= attribute as the validator for truthness. + +The =if= check is accomplished by the =c:if= tag, and requires a =c:then= tag for the body of its branch. It also has =c:else= and =c:elseif= to enable multiple branching: + +#+begin_src html + + + + + + + + +#+end_src + +The above example tests for the truthness of the variable =framesetp= and executes the associate branch based on that. The =test= argument can, naturally, receive any kind of lisp syntax. + +The =c:when= and =c:unless= directives, like their lisp counterparts, only have a branch that is executed when the check of =test= argument value is true or false accordingly. + +*Note:* Clip also has =c:case= and =c:cond= conditionals that should work like they lisp counterparts but I didn't need them until now so I'll not try to explain them. + +** Data usage + +Using a variable content in the template engine is accomplished by the =lquery= tag attribute, which will be explained later. But as this is a tag attribute, it requires an HTML tag to be attached. To enable the possibility of inserting something anywhere on the HTML document, Clip supplies the =c:splice= tag, a virtual HTML node that is removed after rendering, leaving only the content inserted by =lquery=. + +The follow example inserts a textual value of the =content= variable directly into the HTML page: + +#+begin_src html + +#+end_src + +Those two usages are so frequently that Clip supplies shorhand aliases for both as the =c:s= and =c:h= tags: + +#+begin_src html + +content + + +navbar +#+end_src + +A great usage of this feature is our new navbar reusable HTML partial, that can be loaded from a speficic lisp function on any page: + +#+begin_src html +(asteroid::load-template "partial/navbar") +#+end_src + +*Note:* As far as I understand, the templating engine works on a different package, so refering to the =asteroid= package is always required inside a template to use defined functions. + +** Clipboard environments + +Clip uses the concept of environment as the data that is available to be used in the templating system. + +The =c:let= directive lets define a new clipboard environment directly on the template. This will supersede the default clipboard, so any useful data needs to also be added to the clipboard for easy access: + +#+begin_src html + + + + + +#+end_src + +The above example defines a local =new-var= with the value ="hello"= and a local =forward= with the parent =var= variable content. + +Alternatively, if forwarding a variable to the new clipboard environment is not desired, the special =(** :var)= syntax can be used to access the parent clipboard. + +The =c:using= directive creates a new clipboard environment with the contents of an existing variable on the parent clipboard. + +#+begin_src html + + + + attribute1 + + +#+end_src + +The example creates a new clipboard environment inside the =c:using= attribute that has direct access to all properties of some structured variable =obj=. This tag transparently destructures any kind of composed data structure like =plists=, =alists= and =classes=. + +Like the simplicity of structural access of the =c:using= tag, the =clip= function enables the same easy of access in any template context. For example, the same splice of the previous example can be obtained with: + +#+begin_src html + +(clip obj :attribute1) + +#+end_src + +This approach is, clearly, more useful when a single value is wanted, while the previous when several values on the structured variable will be used. + +** Iterators + +Clip also has the =c:iterate= directive that iterates a sequence, and its body is rendered having the clipboard environment matching each element of that iteration. As I am yet to use this directive, I will leave its documentation to a later moment. + +* lquery mechanics + +The [[https://shinmera.github.io/lquery/][lquery]] library enables changing any property of an HTML node, being its =text= or =html= content, =css= styles, element attributes (=attr=) and assigned css classes. + +Its usage is very simple: an =lquery= attribute is added to an HTML document, and its value is a s-expression with an accepted funtion and the value for it to work on. + +The following topics present some basic accepted =lquery= functions in use on our templates. + +** HTML node content + +There are two basic =lquery= functions that change the content of the assigned HTML node: + - =html= renders HTML elements as child + - =text= sets a text content to the element + + +The =lquery= s-expression accepts variable or lisp calls for any of the referred functions. For example, the following example sets the content of the =script= tag to the result of the =(asteroid::get-auth-state-js-var)= function: + +#+begin_src html + +#+end_src + +*Note:* the template render process works on a different package, so call to application defined functions needs to include the package name. + +** HTML node styling + +=lquery= also grants easy styling customization of an HTML node. HTML styling can be accomplished in two ways: +- =css=, which sets the HTML =style= attribute of the element. It's called as a plist with all the properties to set. +- css classes that can be added (=add-class=) or removed (=remove-class=) + +The following example adds the =display= and =marging= style properties to the document when the variable =framesetp= is true (=margin= is overwriten in this case): + +#+begin_src html +
+#+end_src + +** HTML attributes + +The =attr= function of the =lquery= s-expression allows customization of any valid HTML node attribute. The following example sets two attributes of an anchor tag: +- =href=, which uses the =eval= function to evaluate some lisp call +- =target= which only has a value when the variable =framesetp= is true + +#+begin_src html + +#+end_src