http.sh/docs/template-examples.md
2025-07-17 09:51:07 +02:00

4.7 KiB

HTTP.sh: template usage examples

Basic example

Create a new .shs file with the following contents:

#!/usr/bin/env bash
declare -A str
str[title]="Hello, world!"
str[test]="meow"

render str "templates/main.htm"

render is the core of the templating engine; it takes an assoc array, iterates over it, applies additional magic and outputs the response directly to stdout. It is likely the final thing you want to run in your script.

The script above has referenced an HTML file; For this example, we put it under app/templates/main.htm, but you're free to use any directory structure for this. An observant reader might have noticed the relative path; All paths are treated as relative to the namespace's directory. This behavior can be modified by setting template_relative_paths, which is described in greater detail by the main template documentation.

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8">
	<title>{{.title}}</title>
</head>
<body>
	{{.test}}
</body>
</html>

netscape 3.06 gold screenshot, showing our awesome page

Boolean if statements

Following is an example script which simulates a coin toss:

#!/usr/bin/env bash
declare -A str
str[title]="Coin flip!"

if (( RANDOM%2 == 0 )); then
	str[?random]=_
fi

render str "${cfg[namespace]}/templates/main.htm"

And the corresponding template:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8">
	<title>{{.title}}</title>
</head>
<body>
	{{start ?random}}
		It's heads!
	{{else ?random}}
		It's tails!
	{{end ?random}}
</body>
</html>

another netscape screenshot. the page is titled Coin flip! and it shows that it rolled heads

50% of the time the variable will be set, 50% it won't. Hence, it will display either heads or tails :)

Of note: if you hate repeating yourself, this template can be done inline:

It's {{start ?random}}heads{{else ?random}}tails{{end ?random}}!

The effect is exactly the same. This is quite useful for adding CSS classes.

Loop example

This API is pending a rewrite due to how convoluted it is.

#!/usr/bin/env bash
declare -A str
str[title]="foreach example"

nested_declare list # "array of arrays"
declare -A elem # temporary element
for i in {1..32}; do
	elem[item]="$i" # assign $i to the temporary element
	nested_add list elem # add elem to list; this creates a copy you can't modify
done
# once we have a full list of elements, assign it to the array passed to render
str[_list]=list

render str "templates/main.htm"

And the template...

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8">
	<title>{{.title}}</title>
</head>
<body>
	{{start _list}}
		{{.item}}<br>
	{{end _list}}
</body>
</html>

The result repeats the whole "subtemplate" between list start and end:

list so long that the numbers go off-screen!

This is very useful for rendering data in tables:

	<table>
		<tr>
			<th>number</th>
		</tr>
        {{start _list}}
            <tr>
                <td>{{.item}}</td>
                <td>whatever...</td>
            </tr>
        {{end _list}}
	</table>

our example, now rendered as a table

In this specific example the loop index is readily available; However, if your code iterates over a list of strings and you'd need to keep track of an additional index variable, the template engine can do it for you with {{-index}}:

	<table>
		<tr>
			<th>number</th>
		</tr>
        {{start _list}}
            <tr>
                <td>{{-index}}</td>
                <td>meow</td>
            </tr>
        {{end _list}}
	</table>

integration with notORM

notORM's data_iter function works great with nested_add; Body of a callback function can be treated as equal to a for loop:

declare -A elem
nested_declare list
x() {
	elem[ns]="${data[2]}"
	elem[domain]="${data[1]}"
	nested_add list elem
}
data_iter storage/zones.dat "$username" x

str[title]="SERVFAIL :: zone list"
str[_list]=list

date pretty-printing

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8">
	<title>{{.title}}</title>
</head>
<body>
	Current time is {{+time}}
</body>
</html>
#!/usr/bin/env bash
declare -A str
str[title]="time pretty-print"
str[+time]="$EPOCHSECONDS"

render str "templates/main.htm"

netscape displays the current date and time

If you get quirky with the <meta http-equiv="refresh" content="1">, you can even make it auto update! (don't)

oh gosh it refreshes now. whyyyyyyyyyyyyyyyy