Diet templates
Introduction
Note that the original implementation of Diet templates has been superseded by the DietNG package, which supports a number of additional features. An updated version of the specification is located in SPEC.md of the GitHub repository.
This document is work-in-progress - please use the Pug documentation for any section that is not filled with content, Diet templates are kept as compatible as possible to Pug templates.
Diet templates are HTML templates which are statically compiled down to native D code. Dynamic pages thus have almost no runtime overhead and are often even faster than static pages on disk, because they are just written directly from RAM to the HTTP connection.
The syntax equals that ofPugtemplates with the exception of some of the advanced syntax features. Since there is no official syntax reference written yet, you can use the Pug documentationas a replacement. The main difference is that you write D expressions and statements instead of JavaScript.
Basic structure
The general structure uses indentation to manage nesting of HTML tags, similar to what Python does. The indentation style of a document is enforced to be consistent and can either be tabs or any number of spaces. The indentation style is inferred from the first line that is indented. Note that indentation levels may never be skipped, so that the first indented line must always be indented by exactly one tab stop.
Right now, it is necessary to begin the document with an HTML 5 header. This restriction will be removed in the future.
doctype html html head title Hello, World body h1 Hello World
Content elements
HTML elements
The most basic elements are HTML tags. Every element that does not have a special meaning and begins with a letter and contains only letters, numbers, colons, dashes or underscores is treated as an HTML tag. Tags with no content such as <br> or <link> are recognized and output accordingly. The tag name can also be completely omitted, in which case a <div> is assumed.
After each tag, an id, multiple class names, and a list of attributes can follow. Ids are prefixed with '#' and class names with '.'. The attribute list is a comma separated list or key/value pairs delimited by clamps. The string value of an attribute can containstring interpolations.
The rest of the line contains the nodes text contents. By default, the text is output HTML encoded and can containstring interpolations. If the text is prefixed with '=', it is interpreted as a D expression. The outcome of this expression is converted to a string and HTML encoded. Prefixing with '!=' will output the bare string without HTML encoding.
doctype html html head title This is the page title body #main This is a <div> with the id 'main'. p#first This paragraph has the id 'first'. p.second.red This paragraph has the classes 'second' and 'red' assigned. p The following paragraph will have an '8' as its content: p= 5+3 p It's also possible to output raw HTML from a D expression: p!= "<u>Underlined text</u>" p(style="color:red", title='Attribute example') HTML attributes can be specified. p#second.test(style="color:green") Id, classes and attributes can also be combined.
<!DOCTYPE html> <html> <head> <title>This is the page title</title> </head> <body> <div id="main"> This is a <div> with the id 'main'. <p id="first">This paragraph has the id 'first'.</p> <p class="second red">This paragraph has the classes 'second' and 'red' assigned.</p> <p>The following paragraph will have an '8' as its content:</p> <p>8</p> <p>It's also possible to output raw HTML from a D expression:</p> <p><u>Underlined text</u></p> <p style="color:red" title="Attribute example">HTML attributes can be specified.</p> <p id="second" class="test" style="color:green">Id, classes and attributes can also be combined.</p> </div> </body> </html>
Plain text
There is a special plain text node for the cases where you want to split up text over multiple lines, for example because you are outputting preformatted text or because you want to mix text with html nodes. The tag is started with a pipe '|' and can be followed by '=' or '!=' just as HTML nodes. Consecutive text nodes are output as separate lines in the HTML output with their indentation removed.
doctype html html head title Plain text test body pre |This is some multi-line | preformatted | text p This is an example containing a a(href="https://vibed.org/") link | mixed with text. p |= "<D> expressions" |!= "And raw <u>HTML</u> output" | are possible.
<!DOCTYPE html> <html> <head> <title>Plain text test</title> </head> <body> <pre>This is some multi-line preformatted text</pre> <p> This is an example containing a <a href="https://vibed.org/">link</a> mixed with text. </p> <p> <D> expressions And raw <u>HTML</u> output are possible. </p> </body> </html>
Whitespace removal
> and < give you more control over the whitespace near a tag. > will remove all whitespace surrounding a tag, while < will remove all whitespace immediately within a tag. You can think of them as alligators eating the whitespace: > faces out of the tag and eats the whitespace on the outside, and < faces into the tag and eats the whitespace on the inside. They're placed at the end of a tag definition, after class, id, and attribute declarations but before =.
div span(style="color:blue") [ span(style="color:red")> red span(style="color:blue") ] div div>< img
<div> <span style="color:blue">[</span><span style="color:red">red</span><span style="color:blue">]</span> </div> <div><div><img/></div></div>
Comments
WIP
Comments in diet-templates are like c99-"//" comments they show up in the result as HTML comments. If such behavior is not wanted use "//-". Thoose do not show up on the page
doctype html html // I show up head //-title there is no title body // You will see me too //- I am just visible in the template source
<!DOCTYPE html><!-- I show up --> <html> <head> </head> <body><!-- You will see me too --> </body> </html>
TODO #if
Embedded D source code
Procedural content
TODO
Statements
D statements can be embedded into templates by prefixing a line with a dash '-'. The statement will be execute after everything before it has been output and before anything after it will be output. Block statements such as loops and if statements are possible, as well as import statements. Note that variable declarations and imports are only visible inside the parent node in which they occur.
Please note that you should never use braces to nest D statements inside other D statements. These may give unexpected results. Instead simply indent the nested lines just as you would do with HTML tags and other nodes. Inside of a single line, however, using braces is allowed and will work as expected.
If a tag is followed by an equal sign '=' then the plain text of the tag is a D expression. The value of this expression is placed in the output.
doctype html html head title D statement test body - import std.algorithm : min; p Four items ahead: - foreach( i; 0 .. 4 ) - auto num = i+1; p Item b= num p Prints 8: p= min(10, 2*6, 8)
<!DOCTYPE html> <html> <head> <title>D statement test</title> </head> <body> <p>Four items ahead:</p> <p>Item <b>1</b> </p> <p>Item <b>2</b> </p> <p>Item <b>3</b> </p> <p>Item <b>4</b> </p> <p>Prints 8:</p> <p>8</p> </body> </html>
String interpolations
With string interpolations you can output the value of an expression inside plain text or an attribute value. You only need to surround your expression with #{ and }.
The value of the expression is HTML escaped before it is printed into the output. If you need unescaped output then you have to use !{ instead of #{.
doctype html html head title D string interpolations test body - import std.algorithm : min; p Four items ahead: - foreach( i; 0 .. 4 ) - auto num = i+1; p Item #{ num } //- Unescaped output p Prints 8: !{ min(10, 2*6, 8) }
<!DOCTYPE html> <html> <head> <title>D string interpolations test</title> </head> <body> <p>Four items ahead:</p> <p>Item 1 </p> <p>Item 2 </p> <p>Item 3 </p> <p>Item 4 </p> <p>Prints 8: 8</p> </body> </html>
Component templates
Blocks and Extensions
TODO
Includes
With includes it is possible to embed one template in another. The included template gets pasted at the position of the include-keyword. The Indention of the include-postion will propagate, to the included template.
// main.dt doctype html html head title includeExample body h2 the following content is not in this file ... include otherfile
// otherfile.dt h3 ... But In the other file and this include yetanotherfile
// yetanotherfile.dt h4 in yet anotherfile
<!DOCTYPE html> <html> <head> <title>includeExample</title> </head> <body> <h2> the following content is not in this file ... </h2> <h3> ... But In the other file and this </h3> <h4> in yet another file </h4> </body> </html>
Functions
In any place where normal HTML tags are allowed, it is also possible to define functions in standard D syntax. All child tags will be output whenever the function is called. This functionality is very similar to the "mixin" feature of Pug.
- void css(string file) link(rel= 'stylesheet', type='text/css', href='styles/#{file}.css') doctype html html head title Function test page - css("common"); - css("home"); body - foreach(c; ["red", "green", "blue"]) - void repeat(string c) |#{c}-#{c}-#{c} p span(style='color: red;') - repeat(c); span(style='color: green;') - repeat(c);
<!DOCTYPE html> <html> <head> <title>Function test page</title> <link rel="stylesheet" type="text/css" href="styles/common.css"/> <link rel="stylesheet" type="text/css" href="styles/home.css"/> </head> <body> <p> <span style="color: red;">red-red-red</span> <span style="color: green;">red-red-red</span> <span style="color: red;">green-green-green</span> <span style="color: green;">green-green-green</span> <span style="color: red;">blue-blue-blue</span> <span style="color: green;">blue-blue-blue</span> </p> </body> </html>
Filters
TODO
Standard filters:
-
:css
-
:javascript
-
:markdown
-
:htmlescape
doctype html html head title Filter test page :css body { background-color: gray; } body :markdown This is a test paragraph in [markdown](https://daringfireball.net/projects/markdown/) syntax.
<!DOCTYPE html> <html> <head> <title>Filter test page</title> <style type="text/css"><!-- body { background-color: gray; } --></style> </head> <body> <p>This is a test paragraph in <a href="https://daringfireball.net/projects/markdown/">markdown</a> syntax.</p> </body> </html>
Grammar
The following listing shows the language grammar for a single line of a Diet template. Note that the grammar has been derived manually from the source code and may not be 100% accurate.
content_line : indent (html_node | text_node | comment_node | special_node)
html_node : (empty | html_tag) ['#' html_ident] ('.' html_ident)*
[html_attr_list] node_content
html_attr : letter (letter|digit|':'|'-')*
html_ident : letter (letter|digit|'-')*
html_tag : letter (letter|digit|':'|'-'|'_')*
html_arrt_list : '(' OPT_WS html_attr ')'
| '(' OPT_WS html_attr OPT_WS '=' OPT_WS string
( ',' OPT_WS html_attr OPT_WS '=' OPT_WS string )*
OPT_WS ')'
text_node : '|' node_content
comment_node : '//' text | '//-' text | '//if' text
special_node : code_node | block_node | include_node
code_node : '-' text
block_node : 'block ' text
include_node : 'include ' text
node_content : (empty | '=' | '!=') text
string : '"' ((^ '"') | '\' ? )* '"'
letter : ('a'-'z' | 'A'-'Z')
digit : '0'-'9'
OPT_WS : (' ')*