mirror of
https://github.com/urbit/shrub.git
synced 2024-12-14 20:02:51 +03:00
XML templating documentation
This commit is contained in:
parent
2f24750980
commit
1f09fe15b9
472
main/pub/src/doc/sail-moveme.md
Normal file
472
main/pub/src/doc/sail-moveme.md
Normal file
@ -0,0 +1,472 @@
|
|||||||
|
Structures
|
||||||
|
==========
|
||||||
|
|
||||||
|
The fundamental hoon structure used to generate XML is a manx. A manx is
|
||||||
|
composed of a `marx` and a `marl`, representing an XML node:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
++ manx ,[g=marx c=marl] :: XML node
|
||||||
|
++ marx ,[n=mane a=mart] :: XML tag
|
||||||
|
++ mane $|(@tas [@tas @tas]) :: XML name/space
|
||||||
|
```
|
||||||
|
|
||||||
|
Names, manes
|
||||||
|
------------
|
||||||
|
|
||||||
|
The most basic `manx` consists of an XML node name, called a `mane`, an empty
|
||||||
|
`marl`, and an empty `mart`:
|
||||||
|
|
||||||
|
```
|
||||||
|
~zod/try=> ;div
|
||||||
|
[[%div ~] ~]
|
||||||
|
~zod/try=> ;namespaced_div;
|
||||||
|
[[[%namespaced %div] ~] ~]
|
||||||
|
```
|
||||||
|
|
||||||
|
This represents an XML node, an opening and a closing tag with no attributes
|
||||||
|
nor children:
|
||||||
|
|
||||||
|
```
|
||||||
|
~zod/try=> (xmlt | ;div; "")
|
||||||
|
"<div></div>"
|
||||||
|
~zod/try=> (xmlt | ;namespaced_div; ~)
|
||||||
|
"<namespaced:div></namespaced:div>"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note**: `++xmlt` takes three arguments: a loobean determening whether text should be
|
||||||
|
xml-escaped, the `manx` to be rendered, and a tape onto which to append the
|
||||||
|
results. `<script>` and `<style>` tags are unescaped by default. For more
|
||||||
|
information, see the XML documentation in Volume 3, section 3bD.
|
||||||
|
|
||||||
|
However, `%gall` applications operate on nouns of the type `[%hymn manx]`,
|
||||||
|
making direct calls to `++xmlt` rare.
|
||||||
|
|
||||||
|
Attributes and child nodes
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
To represent XML nodes with children and/or attributes, `marl` and `mart` are
|
||||||
|
used respectively:
|
||||||
|
|
||||||
|
```
|
||||||
|
++ marl (list manx) :: XML node list
|
||||||
|
++ mart (list ,[n=mane v=tape]) :: XML attributes
|
||||||
|
```
|
||||||
|
|
||||||
|
Each child node is simply another manx, and attributes are pairs of key `mane`
|
||||||
|
to value `tape`. `marl` and `mart` are lists of these respective values.
|
||||||
|
|
||||||
|
Wide Form
|
||||||
|
=========
|
||||||
|
|
||||||
|
Children
|
||||||
|
--------
|
||||||
|
|
||||||
|
The XML templating syntax begins with a `';'` followed by a `term`.
|
||||||
|
In wide form, a child node is appended with a `':'`:
|
||||||
|
|
||||||
|
```
|
||||||
|
~zod/try=> ;div:p;
|
||||||
|
[[%div ~] [[%p ~] ~] ~]
|
||||||
|
~zod/try=> :poxo ;div:p;
|
||||||
|
<div><p></p></div>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:**`/~zod/try/1/bin/poxo/hoon` is a shell script that applies `(curr (cury xmlt |) ~)`
|
||||||
|
to a `manx`, rendering it as a `tape`.
|
||||||
|
|
||||||
|
Multiple nodes can be represented inside of parentheses, separated by single spaces:
|
||||||
|
|
||||||
|
```
|
||||||
|
~zod/try=> ;div:(p ul:(li li))
|
||||||
|
[[%div ~] [[%p ~] ~] [[%ul ~] [[%li ~] ~] [[%li ~] ~] ~] ~]
|
||||||
|
~zod/try=> :poxo ;div:(p ul:(li li))
|
||||||
|
<div><p></p><ul><li></li><li></li></ul></div>
|
||||||
|
```
|
||||||
|
|
||||||
|
Tags must always be closed. In wide form, this is done either with a `';'` if the
|
||||||
|
node contains no children, or with a `':'`, followed by one or more children.
|
||||||
|
|
||||||
|
In wide form, terminating `';'`s are implied: `;div:(p p p)` is equivalent to
|
||||||
|
`;div:(p; p; p;)`.
|
||||||
|
However, in instances where there are a chain of nodes where each node
|
||||||
|
contains only one child, as with `;div:p;`, it is good practice to include the
|
||||||
|
final `';'` to avoid confusion with an unclosed single tag.
|
||||||
|
|
||||||
|
Attributes
|
||||||
|
----------
|
||||||
|
|
||||||
|
Attributes are included as `','`-separated pairs of `mane` and and a `tape` producing twig. These
|
||||||
|
pairs are contained within parentheses, which immediately follow a `mane`:
|
||||||
|
|
||||||
|
```
|
||||||
|
~zod/try=> ;div(id "me", class "elem");
|
||||||
|
[[%div [%id "me"] [%class "elem"] ~] ~]
|
||||||
|
~zod/try=> :poxo ;div(class "elem", id "me"); ~))
|
||||||
|
<div class="elem" id="me"></div>
|
||||||
|
```
|
||||||
|
|
||||||
|
The characters `'.'`, `'#'`, and `'/'` are short forms of the attributes `class`,
|
||||||
|
`id`, and `href` respectively:
|
||||||
|
|
||||||
|
```
|
||||||
|
~zod/try=> ;div.elem#me;
|
||||||
|
[[%div [%id "me"] [%class "elem"] ~] ~]
|
||||||
|
~zod/try=> ;a/"//google.com";
|
||||||
|
[[%a [%href "//google.com"] ~] ~]
|
||||||
|
```
|
||||||
|
|
||||||
|
As demonstrated above, the short forms of both `class` and `id` accept unquoted
|
||||||
|
terms instead of tapes.
|
||||||
|
The resulting XML is, of course, identical:
|
||||||
|
|
||||||
|
```
|
||||||
|
~zod/try=> :poxo ;div.elem#me;
|
||||||
|
<div id="me" class="elem"></div>
|
||||||
|
```
|
||||||
|
|
||||||
|
Character data
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Nodes can also contain text:
|
||||||
|
|
||||||
|
```
|
||||||
|
~zod/try=> ;p:"contents of paragraph"
|
||||||
|
[[%p ~] [[%~. [%~. "contents of paragraph"] ~] ~] ~]
|
||||||
|
~zod/try=> :poxo ;p:"contents of paragraph"
|
||||||
|
<p>contents of paragraph</p>
|
||||||
|
```
|
||||||
|
|
||||||
|
Text is stored as a `mars` (a cdata node):
|
||||||
|
|
||||||
|
```
|
||||||
|
++ mars ,[t=[n=%$ a=[i=[n=%$ v=tape] t=~]] c=~] :: XML cdata
|
||||||
|
```
|
||||||
|
|
||||||
|
Techincally, a `mars` is a `manx` with an empty `mane`, one empty-named attribute
|
||||||
|
containing the text, and no children. Equivalently, it is a `_:/(*tape)`.
|
||||||
|
|
||||||
|
To insert text with newlines, it is surrounded in triple quotes:
|
||||||
|
|
||||||
|
```
|
||||||
|
;code:"""
|
||||||
|
block
|
||||||
|
with newlines
|
||||||
|
"""
|
||||||
|
```
|
||||||
|
|
||||||
|
This is rendered as:
|
||||||
|
|
||||||
|
```
|
||||||
|
<code>block
|
||||||
|
with newlines</code>
|
||||||
|
```
|
||||||
|
|
||||||
|
Interpolation
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Similar to the syntax for `tape` interpolation,
|
||||||
|
|
||||||
|
```
|
||||||
|
~zod/try=> "Tape with {(weld "inter" (trip %polate))}d text"
|
||||||
|
"Tape with interpolated text"
|
||||||
|
```
|
||||||
|
|
||||||
|
there exists a `manx` syntax to insert XML produced by twigs. The simplest form
|
||||||
|
is that of embedded nodes:
|
||||||
|
|
||||||
|
```
|
||||||
|
~zod/try=> ;p:"Text text ;{b "bolded text"} more text"
|
||||||
|
[ [%p ~]
|
||||||
|
[[%~. [%~. "Text text "] ~] ~]
|
||||||
|
[[%b ~] [[%~. [%~. "bolded text"] ~] ~] ~]
|
||||||
|
[[%~. [%~. " more text"] ~] ~]
|
||||||
|
~
|
||||||
|
]
|
||||||
|
~zod/try=> :poxo ;p:"Text text ;{b "bolded text"} more text"
|
||||||
|
<p>Text text <b>bolded text</b> more text</p>
|
||||||
|
```
|
||||||
|
|
||||||
|
Notice that the syntax calls for a `marx`, followed by zero or more wide-form children
|
||||||
|
`manx`, placed within `';{}'`.
|
||||||
|
|
||||||
|
Dynamic data can also be interpolated. This is done by prefixing the `{}` wrapped twig with one of the following glyphs: `-, +, *, or %`.
|
||||||
|
|
||||||
|
A `{}` prefixed by a `'-'` accepts a `tape`:
|
||||||
|
|
||||||
|
```
|
||||||
|
~zod/try=> ;p:"Paragraph with -{(weld "inter" (trip %polate))}d text"
|
||||||
|
[ [%p ~]
|
||||||
|
[[%~. [%~. "Paragraph with "] ~] ~]
|
||||||
|
[[%~. [%~. ~[~~i ~~n ~~t ~~e ~~r ~~p ~~o ~~l ~~a ~~t ~~e]] ~] ~]
|
||||||
|
[[%~. [%~. "d text"] ~] ~]
|
||||||
|
~
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
If no glyph prefix is present, a`'-'` is assumed:
|
||||||
|
|
||||||
|
```
|
||||||
|
~zod/try=> ;p:"Paragraph with {(weld "inter" (trip %polate))}d text"
|
||||||
|
[ [%p ~]
|
||||||
|
[[%~. [%~. "Paragraph with "] ~] ~]
|
||||||
|
[[%~. [%~. ~[~~i ~~n ~~t ~~e ~~r ~~p ~~o ~~l ~~a ~~t ~~e]] ~] ~]
|
||||||
|
[[%~. [%~. "d text"] ~] ~]
|
||||||
|
~
|
||||||
|
]
|
||||||
|
~zod/try=> :poxo ;p:"Paragraph with {(weld "inter" (trip %polate))}d text"
|
||||||
|
<p>Paragraph with interpolated text</p>
|
||||||
|
```
|
||||||
|
|
||||||
|
A prefix of `'+'` accepts a `manx`:
|
||||||
|
|
||||||
|
```
|
||||||
|
~zod/try=> ;p:"This text +{?:((gth 2 1) ;b:"be bold" ;i:"be scared")}"
|
||||||
|
[[%p ~] [[%~. [%~. "This text "] ~] ~] [[%b ~] [[%~. [%~. "be bold"] ~] ~] ~] ~]
|
||||||
|
~zod/try=> :poxo ;p:"This text +{?:((gth 2 1) ;b:"be bold" ;i:"be scared")}"
|
||||||
|
<p>This text <b>be bold</b></p>
|
||||||
|
```
|
||||||
|
|
||||||
|
A prefix of `'*'` accepts a `marl`:
|
||||||
|
|
||||||
|
```
|
||||||
|
~zod/try=> ;p:"Today *{(turn `wain`~[%live %love] |=(a=@tas ;span:"we {(trip a)}, "))}"
|
||||||
|
[ [%p ~]
|
||||||
|
[[%~. [%~. "Today "] ~] ~]
|
||||||
|
[ i=[[%span ~] [[%~. [%~. "we "] ~] ~] [[%~. [%~. "live"] ~] ~] [[%~. [%~. ", "] ~] ~] ~]
|
||||||
|
t
|
||||||
|
[ i=[[%span ~] [[%~. [%~. "we "] ~] ~] [[%~. [%~. "love"] ~] ~] [[%~. [%~. ", "] ~] ~] ~]
|
||||||
|
t=~
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
~zod/try=> :poxo ;p:"Today *{(turn `wain`~[%live %love] |=(a=@tas ;span:"we {(trip a)}, "))}"
|
||||||
|
<p>Today <span>we live, </span><span>we love, </span></p>
|
||||||
|
```
|
||||||
|
|
||||||
|
A prefix of `'%'` accepts `$+(marl marl)`, a gate with both a sample and product of `marl`. The gate is then slammed by the nodes that follow it:
|
||||||
|
|
||||||
|
```
|
||||||
|
~zod/try=> ;p:"%{|=(a=marl (weld a a))}dup"
|
||||||
|
[ [%p ~]
|
||||||
|
~[[g=[n=%$ a=~[[n=%$ v="dup"]]] c=~] [g=[n=%$ a=~[[n=%$ v="dup"]]] c=~]]
|
||||||
|
]
|
||||||
|
~zod/try=> :poxo ;p:"%{|=(a=marl (weld a a))}dup"
|
||||||
|
<p>dupdup</p>
|
||||||
|
```
|
||||||
|
|
||||||
|
Interpolation can be disabled by replacing double quotes with single quotes.
|
||||||
|
For example, `;unescaped:'Kel {}'` becomes `<unescaped>Kel {}</unescaped>`,
|
||||||
|
and:
|
||||||
|
|
||||||
|
```
|
||||||
|
;script:'''
|
||||||
|
function(){
|
||||||
|
console.log(42)
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
```
|
||||||
|
|
||||||
|
when rendered, is:
|
||||||
|
|
||||||
|
```
|
||||||
|
<script>function(){
|
||||||
|
console.log(42)
|
||||||
|
}</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
Tall form
|
||||||
|
==========
|
||||||
|
|
||||||
|
Most development is done in tall form:
|
||||||
|
|
||||||
|
```
|
||||||
|
;html
|
||||||
|
;head
|
||||||
|
;title
|
||||||
|
; Hi
|
||||||
|
==
|
||||||
|
==
|
||||||
|
;body
|
||||||
|
;p
|
||||||
|
; Hello world
|
||||||
|
==
|
||||||
|
==
|
||||||
|
==
|
||||||
|
```
|
||||||
|
|
||||||
|
This produces the `manx`:
|
||||||
|
|
||||||
|
```
|
||||||
|
g=[n=%html a=~]
|
||||||
|
c
|
||||||
|
~[
|
||||||
|
[ g=[n=%head a=~]
|
||||||
|
c=~[[g=[n=%title a=~] c=~[[g=[n=%$ a=~[[n=%$ v="Hi
|
||||||
|
"]]] c=~]]]]
|
||||||
|
]
|
||||||
|
[ g=[n=%body a=~]
|
||||||
|
c=~[[g=[n=%p a=~] c=~[[g=[n=%$ a=~[[n=%$ v="Hello world
|
||||||
|
"]]] c=~]]]]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
When the `manx` is rendered, it produces:
|
||||||
|
|
||||||
|
```
|
||||||
|
<html><head><title>Hi
|
||||||
|
</title></head><body><p>Hello world
|
||||||
|
</p></body></html>
|
||||||
|
```
|
||||||
|
|
||||||
|
As previously mentioned, a tag must always be closed. In tall form, this is accomplished by a `'=='`, which should align directly beneath it; any node in between the two is a subnnode.
|
||||||
|
|
||||||
|
As demonstrated in the example above, the tall form for character data
|
||||||
|
is opened by `'; '` (note the space). Unlike wide form, the text that follows
|
||||||
|
the `'; '` is not wrapped in quotes, but is instead terminated with a new
|
||||||
|
line. The syntax for interpolation remains the same.
|
||||||
|
|
||||||
|
The final way in which a tag may be closed is with `': '`, which is equivalent
|
||||||
|
to a `manx` with a single child declared by `'; '`. As with `'; '`, the text
|
||||||
|
declared by the `': '` is terminated by a new line:
|
||||||
|
|
||||||
|
```
|
||||||
|
;p: par contents
|
||||||
|
:: <p>par contents</p>
|
||||||
|
```
|
||||||
|
|
||||||
|
Another syntax that is unique to tall form is`';='`, which describes a `marl`
|
||||||
|
with no tag:
|
||||||
|
|
||||||
|
```
|
||||||
|
!:
|
||||||
|
=- [- (xmll | - ~)]
|
||||||
|
;=
|
||||||
|
;p: node
|
||||||
|
;node(with "attribute");
|
||||||
|
==
|
||||||
|
```
|
||||||
|
|
||||||
|
This produces the `marl`:
|
||||||
|
|
||||||
|
```
|
||||||
|
[[[%p ~] [[%~. [%~. "node"] ~] ~] ~] [[%node [%with "attribute"] ~] ~] ~]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Notice how this renders two XML nodes without an outer tag:
|
||||||
|
|
||||||
|
```
|
||||||
|
"<p>node</p><node with="attribute"></node>"
|
||||||
|
```
|
||||||
|
|
||||||
|
Tall interpolation
|
||||||
|
------------------
|
||||||
|
|
||||||
|
A ';' followed by an interpolation glyph(`-, +, *, or %`) and two or more spaces,
|
||||||
|
accepts a twig and interpolates it into the surrounding structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
;div#demo
|
||||||
|
;- "foo"
|
||||||
|
;+ ;p:"bar"
|
||||||
|
;* :- ;p:"baz"
|
||||||
|
?: &
|
||||||
|
~
|
||||||
|
~[;hi;]
|
||||||
|
;% |= a=marl
|
||||||
|
(weld a a)
|
||||||
|
; dup
|
||||||
|
==
|
||||||
|
```
|
||||||
|
|
||||||
|
This produces the `manx`:
|
||||||
|
|
||||||
|
```
|
||||||
|
[ g=[n=%div a=~[[n=%id v="demo"]]]
|
||||||
|
c
|
||||||
|
~[
|
||||||
|
[g=[n=%$ a=~[[n=%$ v="foo"]]] c=~]
|
||||||
|
[g=[n=%p a=~] c=~[[g=[n=%$ a=~[[n=%$ v="bar"]]] c=~]]]
|
||||||
|
[g=[n=%p a=~] c=~[[g=[n=%$ a=~[[n=%$ v="baz"]]] c=~]]]
|
||||||
|
[g=[n=%$ a=~[[n=%$ v="dup
|
||||||
|
"]]] c=~]
|
||||||
|
[g=[n=%$ a=~[[n=%$ v="dup
|
||||||
|
"]]] c=~]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
When the `manx` is rendered, it produces:
|
||||||
|
|
||||||
|
```
|
||||||
|
<div id="demo">foo<p>bar</p><p>baz</p>dup
|
||||||
|
dup
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
Attributes
|
||||||
|
----------
|
||||||
|
|
||||||
|
The tall form syntax for attributes is `'='` followed by a `mane` (the key), two
|
||||||
|
or more spaces, and a tall twig that produces a tape:
|
||||||
|
|
||||||
|
```
|
||||||
|
;div
|
||||||
|
=id "foo"
|
||||||
|
=class "bar"
|
||||||
|
;p: baz`
|
||||||
|
==
|
||||||
|
```
|
||||||
|
|
||||||
|
This produces the `manx`:
|
||||||
|
|
||||||
|
```
|
||||||
|
[ g=[n=%div a=~[[n=%id v="foo"] [n=%class v="bar"]]]
|
||||||
|
c=~[[g=[n=%p a=~] c=~[[g=[n=%$ a=~[[n=%$ v="baz"]]] c=~]]]]
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
When rendered, this `manx` produces:
|
||||||
|
|
||||||
|
```
|
||||||
|
<div id="foo" class="bar"><p>baz</p></div>
|
||||||
|
```
|
||||||
|
|
||||||
|
The tall-form syntax can be combined with the wide-form attribute syntax (and all of its short forms):
|
||||||
|
|
||||||
|
```
|
||||||
|
;html
|
||||||
|
;div#foo(tag "bar")
|
||||||
|
=attr "exceedingly value in here"
|
||||||
|
; tall form
|
||||||
|
;p: contents
|
||||||
|
==
|
||||||
|
==
|
||||||
|
```
|
||||||
|
|
||||||
|
This produces the `manx`:
|
||||||
|
|
||||||
|
```
|
||||||
|
[ [%html ~]
|
||||||
|
[ [%div [%id "foo"] [%tag "bar"] [%attr "hella long value in here"] ~]
|
||||||
|
[[%~. [%~. "tall form
|
||||||
|
"] ~] ~]
|
||||||
|
[[%p ~] [[%~. [%~. "contents"] ~] ~] ~]
|
||||||
|
~
|
||||||
|
]
|
||||||
|
~
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
When rendered, this `manx` produces:
|
||||||
|
|
||||||
|
```
|
||||||
|
"<html><div id="foo" tag="bar" attr="hella long value in here">tall form
|
||||||
|
<p>contents</p></div></html>"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user