Skip to content

alejandrovrojas/nano

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

87 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Nano

Nano is an eval()-free template engine.


Usage

As with any template processor, the output is rendered by combining a string template and a data object.

import render from 'https://deno.land/x/nano/mod.ts';

const data = {
	message: 'Hello',
	shout: (value: string) => value + '!!!!',
};

const template = `<div>{shout(message)}</div>`;

const result = await render(template, data);

Result

<div>Hello!!!!</div>

Syntax

Expressions

<div>{2 + 2}</div>
<div>{my_variable}</div>
<div>{nested.property}</div>
<div>{nested['property'][0]}</div>
<div>{2 + 2 == 4 ? 'Yes' : 'No'}</div>
<div>{example_function(my_variable)}</div>
<div>{nested.function(other.variable)}</div>
<div>{nested(function(1, true, "foo", my_variable))}</div>

Blocks

{if condition_1}
	<!--foo-->
{else if condition_2}
	<!--bar-->
{else}
	<!--baz-->
{/if}
{for item in array_like}
	<div>{item}</div>
{/for}
{for item, index in array_like}
	<div>{item}</div>
{/for}
{for key, value in object_like}
	<div>{item}</div>
{/for}
{for character, index in "hello"}
	<div>{character}</div>
{/for}
{for number, index in 10}
	<div>{number - 1} equals {index}</div>
{/for}
{switch value}
	{case "a", "b", "c"}
		<!--match if value equals "a" or "b" or "c"-->
	{/case}

	{case 20 + 5}
		<!--or if value equals 20 + 5 (or any other expression)-->
	{/case}

	{default}
		<!--else-->
	{/default}
{/switch}

Imports

{import 'subfolder/other_file.html'}

The imported module will have access to the same data accessible to the scope it's being imported from:

<!-- list.html -->
{for fruit in fruits}
	{import 'list_item.html'}
{/for}

<!-- list_item.html -->
<li>{fruit}</li>

It's also possible to define/rewrite variables using the with keyword along with a list of (key: value) pairs

<!-- list.html -->
{for fruit, index in fruits}
	{import 'list_item.html' with (number: index + 1, other: "thing")}
{/for}

<!-- list_item.html -->
<li>{fruit} no. {number}</li>

Before reading a file from disk, the renderer will look for a matching template inside the data object first. If an object key matches the import path, the string value will be loaded as a template.

{import 'my_block.html'}
// data
{
  'my_block.html': '<div>...</div>'
}

Flags

If/for/expression blocks can be flagged with ! or # (or both) for removing whitespace around HTML tags or escape reserved HTML characters respectively.

Remove whitespace {!...}

In this example (with whitespace added for clarity), the following {for}

{for number in 10} ↩
	⇥ <span>{number}</span> ↩
{/for}

will output

↩
	⇥ <span>1</span> ↩
	⇥ <span>2</span> ↩
	⇥ <span>3</span> ↩
	⇥ <span>4</span>

however {!for}

{!for number in 10} ↩
	⇥ <span>{number}</span> ↩
{/for}

will output

<span>1</span><span>2</span><span>3</span><span>4</span>

Escape HTML {#...}

Similarly, for a variable named code with the value

'<script>/* test */</script>';

the tag {code} will output

<script>/* test */</script>

however {#code} will output

&lt;script&gt;&#x2F;* test *&#x2F;&lt;&#x2F;script&gt;

About

Old-fashioned (eval-free) template engine for Deno Deploy

Resources

License

Stars

Watchers

Forks