TPL Syntax Documentation (text mode only release) - MrStonedOne/dmtemplate GitHub Wiki

DmTemplate .tpl Syntax Documentation

Notice: Pre-release document

The following is a pre-release document, the below spec is starting to finalize and was briefly tested against code and seems to work properly, but said code has not been fully tested, and may require further modifications to finalize. The syntax is subject to change or expansion.

The branch for this has not been pushed up yet.

Introduction

.tpl templates files contain literal text interspersed with dynamically computed tokens.
Tokens are contained within double curly brackets {{ }}
Some tokens take arguments. These are seperated by whitespace, with quotes being used to enclose multiple words into one argument.

All template parsing starts with an associated list of data that is passed the parser by the caller, each key becomes top level variables that contain their value. eg list("mode" = "Kill", "target" = "Clowns") would set the variable mode to the string Kill and the variable target to the string Clowns within the template.

Variable access

The most basic token type simply accesses dynamic data. (all other tokens start with some signifying special character.)

{{var_name}} - Inserts the contents/value of var_name at the location. Sanitizing behavior controlled at runtime based on how the parser was invoked (defaults to no sanitizing)

{{&var_name}} - Inserts the contents of var_name at the location. sanitized for use in html. (To remember, think of & from html escape sequences)

{{%var_name}} - Inserts the contents of var_name at the location. sanitized for use in urls. (To remember, think of % from url escape sequences)

{{\var_name}} - Inserts the contents of var_name at the location. roughly sanitized for use in sdql2 (not safe for untrusted user input). (To remember, think of \ from url escape sequences)

{{*var_name}} - Inserts the contents of var_name at the location. Is not sanitized

Variable names must not start with a number or any character that byond could confuse with a number part (., -, +), nor can they start with any of the special characters used to signify other tokens or sanitizing behavior (*, &, !, #, /, \). and should not contain whitespace or any of the following characters: (\, ], ,, ", }).

List access

{{var_name["key"][5][other_var_name]}} - You can work with lists using roughly the same syntax as in byond.

Constants

The following constants are supported for places that expect variables:

TRUE = 1
FALSE = 0
null = null

They have the same meaning as in byond.

Strings

Any place that expects a variable can take a string inside quotes.

Strings can contain embedded variable accesses using [].

Within strings the \ character can be used to escape syntax. The \n sequence is also supported.

Escaping syntax

{{"{{"}} - If you need to use double curly opening brackets within the template html without it being treated as a token start, you can place them inside a token that outputs a string.

{{!#if blah}} - For convenience, Starting a valid token with ! will cause it to be treated as an escaped string containing the token sans the !. ie: {{#if blah}}.

Conditionals

{{#if var_name}} {{/if}} - Parses the contents only if the value is defined, not-null, and not false. (equivalent to doing if (var_name) dostuff in byond.)

{{#if! var_name}} {{/if}} - Does the reverse of the above

Eg: {{#if %name}}{{name}}{{/if}}{{#if! %name}}Person{{/if}}</h2>

You can also use a limited amount of comparison operators, but you can not nest or chain them as an expression:
{{#if right operator left}}

{{#if var_name == "string constant"}} {{/if}}
{{#if var_name == 0.12}} {{/if}}
{{#if var_name >= 0.12}} {{/if}}
{{#if var_name < 0.12}} {{/if}}
{{#if var_name["key"][1] != ""}} {{/if}}
{{#if var_name & other_var}} {{/if}}

Standard operators (!=, ==, >, <, >=, <=, &, |, %, ^, in, ~=, ~!) They have the same meaning as in byond.

Non-standard operators:

list contains string - Like in but with the arguments reversed.

*Note: White space between operators, keywords, and variables/constants matter. {{#ifvar_name<0.12}} will fail to parse

{{#ifempty var_name}} {{/ifempty}} - Parses the contents if the value is an empty or invalid list.

{{#ifempty! var_name}} {{/ifempty}} - Does the reverse of the above

{{#if ...}}...{{#else ...}}the thing{{/if]} - Does the thing if the previous check failed, can include another check.

{{#switch varname}} {{#case "value"}} {{/case}} {{case "value"}} {{/case}} {{default}}{{/default}} {{/switch}} - Switch statements. All values must be constant strings or numbers, as a hashtable is generated. (does not fall through).

*Note: the {{/}} token does not parse the contents after the / character, meaning nothing keeps an {{/case}} from closing an {{#if}} if the coder made a mistake. Unclosed or Unmatched conditionals however do trigger an error.

Comments

{{#if}}Comments here{{/if}} - The conditional tokens do not require any args to be passed to them, allowing you to use blank ifs as a way of inserting comments in your template that are not output to the end user.

Looping through lists (for each)

For each blocks have a few different formats depending on how you want to work with the values being iterated over:

{{#foreach var_name index}} {{/foreach}} - A foreach block (Implicit form), The contents are re-parsed for each item in the list, the list must contain associated lists of variables that become top level variables for the scope of the block (overriding any variables with the same name). The index arg is optional, if given it is the name of a variable that will hold the index of the current item in the list (overriding any variables of the same name).

{{#foreach var_name index value}} {{/foreach}} - A foreach block (Explicit form), The contents are re-parsed for each item in the list. The index and value arguments are the names of variables you would like to hold the current index and the value (value = var_name[index]) inside the block.

{{#foreach var_name index key value}} {{/foreach}} - A foreach block (Explicit form), The contents are re-parsed for each item in the list. The index, key, and value arguments are the names of variables you would like to hold the current index, the key at that index (key = var_name[index]) and the value associated with that key (value = var_name[key]) inside the block.

*Note: {{#foreach}} blocks inherent from {{#ifempty!}} blocks, and are only computed if given a valid non-empty list.

Examples:

Explicit form

{{#ifempty! message}}
	<P>You have new messages!</P>
	{{#foreach messages index message}}
		{{#if index % 2}}
			<span class="message-odd">
		{{else}}
			<span class="message-even">
		{{/if}}
		<P><b>Message</b> #{{index}}</P>
		<P><b>From:</b> {{message["author"]}}</P>
		<P><b>Contents:</b> {{message["text"]}}</P>
		<br>
		</span>
	{{/foreach}}
{{else}}
	<P>You have no new messages.</P>
{{/ifempty}}

Implicit form

{{#ifempty! message}}
	<P>You have new messages!</P>
	{{#foreach messages index}}
		{{#if index % 2}}
			<span class="message-odd">
		{{else}}
			<span class="message-even">
		{{/if}}
		<P><b>Message</b> #{{index}}</P>
		<P><b>From:</b> {{author}}</P>
		<P><b>Contents:</b> {{text}}</P>
		</span>
		<br>
	{{/foreach}}
{{else}}}
	<P>You have no new messages.</P>
{{/ifempty}}

Quirks

Because of how switch statements process numbers, the following two case statements are equal and would generate a duplicate case statement error

{{#case 5}}{{/case}}
{{#case "{{CASE_NUMBER \"5\"}}"}}{{/case}}

The following however are not considered equal:

{{#case 5}}{{/case}}
{{#case "5"}}{{/case}}
⚠️ **GitHub.com Fallback** ⚠️