Basics of syntax
One can think about WLX as a WL and plain HTML got extended to each other. It allows you to write Wolfram Language using XML tags, and building HTML template using Wolfram Expressions.
Unlike JSX, you can write a plain HTML inside WLX scripts with no restrictions.
Tags
It is easy to guess who is who
HTML tag
<div></div>
Wolfram Expression
<Div></Div>
There is no html
tags on Earth, that starts from the capital letter.
Ownvalues and Downvalues
Those types of assignments are most commonly used in Wolfram Language. Thankfully HTML/XML tag syntax allows to make it clear, which one is called
TextString[Now]
<TextString> <Now/> </TextString>
First child element is the first argument of a given function and etc. Any self-closing tags represent an own-value of a symbol.
Any Number or String can be embedded as tag as well
<Plus/><1.0/><1.0/></Plus>
Simple rules is the key
There are certain rules you should sticked to in order to write a valid WLX
Keep only one or zero root XML element
This implies that this one will be exported to the output, like in CompoundExpression
(* whatever WL code *)
Var = "Hello World!";
<body>
<Var/>
</body>
This is good 👍🏼
However it does not mean, you cannot have nested expressions
(* whatever WL code *)
Var = <h1>Hello World!</h1>;
<body>
<Var/>
</body>
This is also good 👍🏼
Always close any XML tags
Modern web-browsers are quite forgiving, when it comes to the syntax mistakes. All over the internet there is code like this
<img src="http://...">
This is wrong 👎🏼 according to the convention of XML.
WLX parser decodes the whole tree of XML and WL and, then, reconstructs it from AST. Therefore, always close tags explicitly
<img src="http://..."/>
Much better 👍🏼
Since WLX syntax is quite close to JSX, modern linters and syntax highlighting libraries can verify tags in WLX as well using JSX preset. Wolfram Expressions are quite hard to check, but in general, this comes very handy when you write a large script.
Avoid using @
, //
and wrap comments like in C (* /* */ *)
to reduce the number of warning from the JSX linter.
Passing HTML attributes
This is a crucial thing, when it comes to a markup. To maintain sort of compatibility with a well-established Handlebars, JSX curly braces with double quotes are used
URL = "https://upload.wikimedia.org/wikipedia/commons/7/70/Oftheunicorn.jpg"
<img width="300" src="{URL}"/>
Since this is anyway a string, you can use it as a template
URL = "upload.wikimedia.org/wikipedia/commons/7/70/Oftheunicorn.jpg"
<img width="300" src="https://{URL}"/>
Any Wolfram expressions are allowed inside the braces
URL = {"upload.wikimedia.org/wikipedia/commons/7/70/Oftheunicorn.jpg"}
<img width="300" src="https://{URL[[1]]}"/>
To reduce a load on a garbage collector, please, use With
With[{URL = "upload.wikimedia.org/wikipedia/commons/7/70/Oftheunicorn.jpg"},
<img width="300" src="https://{URL}"/>
]
This prevents WL Kernel from creating temporal symbols
How does it relate to a normal WL symbol?
What you have in those funky XML tags in the end is a normal WL definition. For example
AFunction[Any_] := <p><Any/></p>;
AFunction[329]
Once .wlx
is parsed, it becomes a global definition. However the latter (whether it is global or defined like in Module
with a lexical scoping) you can still control, see [[WLX/scoping]].
Iterators, branching?
HTML/XML
is a markup language by its nature. Therefore it is recommended not to use explicitly Table
or If
expressions inside XML tags, but rather utilize Wolfram Language for that
Columns[YourList__] := Table[
<div class="lg:pr-4">
<div class="text-base leading-7 text-gray-700 ">
<Child/>
</div>
</div>
, {Child, List[YourList]}];
<div class="col">
<Columns>
<p>This is column 1</p>
<p>This is column 2</p>
<p>This is column 3</p>
</Columns>
</div>
Here a multiple <p>
tags are substituted as a list of arguments to Columns
function, that iterates over them and forms a wrapper HTML structure. Then the result is substituted into the bottom div col
structure.
Or other there is another way to build lists from raw data
With[{
TableList = Table[
With[{SomeField = item["Field"]},
<li class="red"><SomeField/></li>
]
, {item, YouList}]
},
<ul>
<TableList/>
</ul>
]
Putting a plain text separated by multiple line breaks
<Element>
Line 1
Line 2
</Element>
counts as a single argument to the expression Element
. However
<Element>
Line 1
<p>Line 2</p>
</Element>
is already two arguments passed with a string type (atom).
XML attributes Options
Traditional Wolfram Language Options
can be passed as if it was an HTML attribute
<Heading title={"Some title"}/>
where
Heading[OptionsPattern[]] := With[{Title = OptionValue["title"]},
<h1>This is some <Title/></h1>
]
Options[Heading] = {"title" -> "Empty title"}
The only difference is you have to use curly braces unlike in traditional XML attributes for WL symbols.
This can be done for tags with child elements
<TagName option1={Wolfram Expression} option2={...}>
whatever
</TagName>
where all passed arguments go firstly and before the OptionsPattern
, i.e.
TagName[args__, OptionsPattern[]] := ...