vibe.d beta banner
get vibe.d
0.10.0

Asynchronous I/O that doesn’t get in your way, written in D

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
Example: A minimal HTML page

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 &lt;div&gt; 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.
Example: HTML tags using the various optional features
<!DOCTYPE html>
<html>
	<head>
		<title>This is the page title</title>
	</head>
	<body>
		<div id="main">
			This is a &lt;div&gt; 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>
Example: HTML output for the example

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.
Example: using text nodes to output multiple lines of text
<!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>
			&lt;D&gt; expressions
			And raw <u>HTML</u> output
			are possible.
		</p>
	</body>
</html>
Example: HTML output for the example

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
Example: using whitespace removal
<div>
	<span style="color:blue">[</span><span style="color:red">red</span><span style="color:blue">]</span>
</div>
<div><div><img/></div></div>
Example: HTML output for the example

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
Example: comments
<!DOCTYPE html><!-- I show up
-->
<html>
	<head>
	</head>
	<body><!-- You will see me too
	-->
	</body>
</html>
Example: HTML output for the example

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)
Example: different possibilities to embed D code
<!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>
Example: HTML output for the example

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) }
Example: string interpolations
<!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>
Example: HTML output for the string interpolations example

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
Example: main.dt
// otherfile.dt
h3 ... But In the other file and this
include yetanotherfile
Example: included otherfile.dt
// yetanotherfile.dt
h4 in yet anotherfile
Example: included yetanotherfile.dt
<!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>
Example: HTML output for the include-Example

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);
Example: Using local functions to generate parametrized blocks
<!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>
Example: HTML output for the example

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.
Example: Usage example for embedded filters
<!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>
Example: HTML output for the example

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       : (' ')*
Diet template language grammar