Hrtml is a Rust Templating Markup Language. (HRTML)
Is it a recursive acronym? Yes.
This is a very new project.
RoadMap:
- Finalize Syntax.
- Lexer.
- Parser.
- Attribute Parsing.
- Template Parameters Aggregation.
- Template MetaData Aggregation.
- Parameters.
- Slices.
- Toggles.
- Slots.
- Match.
- Each.
- Imports
- Parameters.
- CodeGen.
Templates are compiled to rust code. There is two way to compile templates:
- Use the
build.rs
to build multiple templates into modules that you include using theinclude
macro. - Use the macros provided by the crate to include templates files one by one.
Both approaches have advantages an drawbacks. The first tends to break easily lsps but is less prone to module missplacement errors. The second is easier but tends to be more verbose if you have a lot of templates.
The methods are gated behind features.
HRTML aims to be as close as possible to classic html template syntax. It makes use of a few special tags to make the templating work. It also alows you to add classes and ids more easily with a syntax inspired by maud.
To import other templates use the import
void (self closing) tag with the from
attribute.
<!-- In Index.hrtml -->
<import from=`Hello`/>
<Hello> World! </Hello>
<!-- In Hello.hrtml -->
<p> Hello <slot/> </p>
<!-- Generates the folowing html. -->
<p> Hello World! </p>
Just like elements template can have children. To controll where children go in a template we use the slot
tag.
<!-- In Hello.hrtml -->
<p> Hello <slot/> </p>
Any chidren of the Hello
template element will be placed inside the slot.
But what if i want to put multiple child elements in different places in the template. Worry not we introduce identified slots.
To create a named slot simply add the id
attribute to your slot.
For example a two column template:
<!-- In TwoCols.hrtml -->
<div .left>
<slod id="left"/>
</div>
<div .right>
<slod id="right"/>
</div>
<!-- In Index.hrtml -->
<import from=`TwoCols`/>
<TwoCols>
<p slot-id="left">
I'm first on the left.
</p>
<p slot-id="right">
I'm first on the right.
</p>
<p slot-id="left">
I'm second on the left.
</p>
</TwoCols>
<!-- Expands to: -->
<div .left>
<p>
I'm first on the left.
</p>
<p>
I'm second on the left.
</p>
</div>
<div .right>
<p>
I'm first on the right.
</p>
</div>
Template parameters allows you to define types to control and render your templates. For a type to be a valid template parameter it must either:
- be an implementor of the
Render
trait or anIterator
ofRender
implementors. - be a value of
RawHtml
(output of Render::render). - be an implementor of the
Attribute
trait or anIterator
ofAtribute
implementors. - be an implementor of the
AttributeValue
trait or anIterator
ofAtribute
implementors. - be an implementor of the
Truthy
trait.
For a parameter to be rendered into the template the template must contains slot
elments with the attribute name
. The struct fields must correspond with the slot names. You can alternatively add a #[rename(new_name)]
attribute on a struct field to assign it to a slot. If the template is imported in another template you can use the slot-<name>=new_name
attribute on the template element to pass down a template attribute to the imported template.
Sometimes we want to add classes, ids or attributes conditionaly. It can be done with toggles. The syntax for toggles is as folows [template_param]thingtotoggle
. The template parameters in toggles must implement Truthy
.
<p
[toggle_italic].italic-txt
[toggle_id]#some-text
[toggle_red]style="color: red;"
>
This is text.
</p>
To enable a truthy parameter simply add it to the template element.
<!-- Text.hrtml -->
<p
[red]style="color: red;"
[green]style="color: green;"
>
This is text.
</p>
<!-- Index.hrtml -->
<import from="Text">
<Text red/>
<Text green/>
<!-- Expands to: -->
<p
style="color: red;"
>
This is text.
</p>
<p
style="color: green;"
>
This is text.
</p>
Sometimes we want to add classes, ids or attributes dynamicly. It can be done with splices. The params with splices must implement the Atribute
trait. The syntax for splices is as folows (template_param)
.
If a type implment Truthy
and Attribute
it can be used in a toggleable slice as folows [(template_param)]
.
For example Option<T>
is Truthy
if T
implements Attribute
.
To render html conditionaly we use the if
tag with the attribute cond
wich accepts a value from a Truthy
parameter.
<!-- Enable.hrtml -->
<if cond=enable>
<p>I'm enabled.</p>
</if>
<elseif cond=>
<p>I'
</elseif>
<else>
<p>I' disabled</p>
</else>
<!-- Index.hrtml -->
<import from="Enable">
<Enable enable/>
<Enable/>
<!-- Expands to: -->
<p>I'm enabled.</p>
<p>I' disabled</p>
The match
<match val=value>
<case pat="">
</case>
<case pat="">
</case>
</match>
The each
element allows you to render a parameter implementing Iterator
wich items are Render
. Effectively rendering reapeating patterns like cards.
<!-- Cards.hrtml -->
<each elems=cards>
<div>
<h1><slot name=title/></h1>
<p><slot name=date/></p>
<img src=(img_src) />
<p><slot name=summary/></p>
</div>
</each>
<!-- Expands to: -->
<div>
<h1>My last article.</h1>
<p>today</p>
<img src="data/imgs/lastarticle.png"/>
<p>The last article i've writen.</p>
</div>
<div>
<h1>An oler article.</h1>
<p>3days ago</p>
<img src="data/imgs/oldarticle.png"/>
<p>I don't remember what i said.</p>
</div>
Asumming the template is called with a parameter of type impl Iterator<Item = cards::Params>
and
mod cards::Params {
title: impl Render,
date: impl Render,
img_src: impl AttributeValue,
summary: impl Render,
}