aboutsummaryrefslogtreecommitdiffstats
path: root/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'README.md')
-rw-r--r--README.md84
1 files changed, 84 insertions, 0 deletions
diff --git a/README.md b/README.md
index 8ef3b5c..2f8d5f1 100644
--- a/README.md
+++ b/README.md
@@ -168,6 +168,13 @@ Here are the differences to be aware of:
a mess of the output if used; unlike CL-WHO, TL-WHO warns when they
are used in attributes.
+* TL-WHO provides a `deftag` macro for defining macro-expanding tags.
+ This is inspired by a `deftag` described in the
+ [Spinneret](https://github.com/ruricolist/spinneret) documentation.
+ Though ordinary macros can easily be used inside `with-html-output`,
+ `deftag` is an expansion mechanism which transforms the tag
+ markup, rather than embedded Lisp code. It is documented below.
+
* The CL-WHO `conc` function is missing. TXR Lisp has a function
like this, which is called `join`, and that is what is used in TL-WHO.
@@ -223,6 +230,83 @@ following issue: the CL-WHO documentation is not accurately maintained and
makes some references to material that no longer exists in CL-WHO, such as the
macro `show-html-expansion`, which was removed from CL-WHO in 2009.
+## The `deftag` macro
+
+### Syntax:
+
+ ::text
+ (deftag <keyword> <attr-param-list> <tag-body>
+ <body> ...)
+
+ <attr-param-list> ::= (<key-param>* [ . <rest-param>])
+
+ <key-param> := <symbol> | (<name> [<default> [<pres-var>]])
+
+### Description:
+
+A `deftag` macro rewrites HTML markup written in TL-WHO syntax
+into other markup.
+
+Simple example:
+
+ ::text
+ (deftag :boldface (. attrs) body
+ ^(:span :font "bold" ,*attrs ,*body))
+
+ (with-html-output-to-string (out)
+ (:boldface :id "hello-id" "Hello!"))
+
+ --> <span font='bold' id='hello-id'>Hello!</span>
+
+Complex example, adapted from Spinneret documentation:
+
+ ::text
+ (deftag :easy-input (label (name (gensym))
+ (id name) (type "text") . other-attrs) default
+ ^(progn
+ (:label :for ,name ,label)
+ (:input :name ,name :id ,id :type ,type
+ ,*other-attrs :value (progn ,*default))))
+
+Note that `progn` here isn't the Lisp `progn` operator; it is recognized
+by the `deftag` expansion mechanism as a way of producing multiple elements.
+To invoke `:easy-input`, we might do this:
+
+ ::text
+ 5> (with-html-output (*stdout* nil :indent t)
+ (:div :class "cls"
+ (:easy-input :name "foo" :id "foo-23"
+ :style "style" :label "lab" "123")))
+ <div class='cls'>
+ <label for='foo'>lab
+ </label>
+ <input name='foo' id='foo-23' type='text' style='style' value='123' />
+ </div>
+
+Note a small flexibility: the `body` argument `"123"` of `:easy-input` wasn't
+inserted as an element in the middle of the tag as in the simple example, but
+as an attribute value.
+
+Note that the `other-attrs` rest parameter of `:easy-input` received
+a list which only contained the `:style` attribute; all the others
+were captured by their respective keyword parameters.
+
+### Parameters:
+
+The `attr-param-list` is an implicit keyword parameter list
+which destructures attributes. It can specify default values for
+attributes that are not passed. Its rest parameter is bound
+to the remaining attributes that were not captured by the parameters.
+
+Each `key-param` is an ordinary TXR Lisp key parameter, implemented
+by the TXR Lisp `:key` parameter list macro. It may be just a
+name, or a name with `default` expression giving a value for
+the parameter if the corresponds keyword argument is missing,
+possibly followed by another variable name which, if present,
+will be a Boolean value indicating, if true, that the keyword
+argument was present, or if false that it was missing (and
+thus defaulted).
+
## Dependencies
TL-WHO has no external dependencies other than TXR itself.