` | `Sqrl.templates` |
You only need to modify it if you want to create environments with different caches.
## `defaultConfig`
`Sqrl.defaultConfig` returns the default configuration. See above.
## `getConfig`
`getConfig` takes some config options and merges them with the default. It optionally takes a third parameter, which it merges with the default first.
High-level APIs like `render` and `compile` call `getConfig` internally, but you should call lower-level APIs (like `compileToString`) with a valid config object, which you can get from this function.
### Syntax
[TypeDoc doc page](https://squirrellyjs.github.io/squirrelly/modules/_config_.html#getconfig)
### Example
```js
Sqrl.compileToString(myTemplate, Sqrl.getConfig({ tags: ["<%", "%>"] }));
```
# Containers
URL: /docs/api/containers
***
id: containers
title: Containers
-----------------
Templates, filters, helpers, and native helpers are all stored in storage objects (internally exposed as `Cacher`) with a similar syntax.
## Syntax
[TypeDoc doc page](https://squirrellyjs.github.io/squirrelly/classes/_storage_.cacher.html)
## TL;DR
To get a cache item, call `[cache].get('name')`. To define a cache item, run `[cache].define('name', value)`. To load an entire cache object, run `[cache].load(cacheObj)`. To reset a cache, run `[cache].clear()`.
## Examples
```js
Sqrl.templates.define("my-partial", Sqrl.compile("This is a partial speaking"));
console.log(Sqrl.templates.get("my-partial"));
Sqrl.filters.define("capitalize", function(str) {
return str.toUpperCase();
});
Sqrl.filters.clear();
```
# File Handling
URL: /docs/api/file-handling
***
id: file-handling
title: File Handling
--------------------
:::note
Squirrelly works out-of-the-box with Express.js.
```js
app.engine('html', require('squirrelly').renderFile)
// Or, if you want to use the .squirrelly file extension
app.set('view engine', 'squirrelly')
```
:::
## Syntax
```js
```
# Filters API
URL: /docs/api/filters
***
id: filter-api
title: Filters API
------------------
Filters let you pass a value through functions.
## Examples
**Simple example**
```js
var myTemplate = "Hi, my name is {{it.name | reverse}}";
Sqrl.filters.define("reverse", function(str) {
return s
.split("")
.reverse()
.join("");
});
Sqrl.render(myTemplate, { name: "Ben" });
// Hi, my name is neB
```
**With filter parameters**
```js
var myTemplate = "{{it.bio | replace('apples', 'watermelons') }}";
Sqrl.filters.define("replace", function(str, search, replace) {
return str.replace(search, replace);
});
Sqrl.render(myTemplate, { bio: "I like to eat apples" });
// I like to eat watermelons
```
# Helpers API
URL: /docs/api/helpers
***
id: helper-api
title: Helpers API
------------------
Helpers let you call external functions with portions of your template!
## Syntax
[TypeDoc doc page](https://squirrellyjs.github.io/squirrelly/modules/_containers_.html#helpers)
## Examples
*Here's the `extends` helper behind-the-scenes*
```js
Sqrl.helpers.define("extends", function(content, blocks, config) {
var data = content.params[1] || {};
data.content = content.exec();
// Loop through each block
for (var i = 0; i < blocks.length; i++) {
var currentBlock = blocks[i];
// set data[blockName] to the compiled value of the current block
data[currentBlock.name] = currentBlock.exec();
}
var template = config.storage.templates.get(content.params[0]);
if (!template) {
throw SqrlErr('Could not fetch template "' + content.params[0] + '"');
}
return template(data, config);
});
```
*Here's the `foreach` helper behind-the-scenes*
```js
Sqrl.helpers.define("foreach", function(content) {
var res = "";
var param = content.params[0];
// the first param is the object we want to loop over
for (var key in param) {
if (!hasOwnProp(param, key)) continue;
res += content.exec(key, param[key]);
}
return res;
});
```
# Native Helpers API
URL: /docs/api/native-helpers
***
id: native-helper-api
title: Native Helpers API
-------------------------
Native helpers let you output code directly into your template function.
:::caution
Native helpers are complicated and kind of messy. If you can implement
something with a regular helper, do that instead
:::
## Syntax
## Examples
*This is the `if` native helper, behind-the-scenes*
```js
Sqrl.nativeHelpers.define('if', function (buffer, env) {
// buffer.d is buffer content, in AST form
var returnStr =
'if(' + buffer.p + '){' + Sqrl.compileScope(buffer.d, env) + '}'
if (buffer.b) {
// b stands for blocks
// Loop through each helper block
for (var i = 0; i < buffer.b.length; i++) {
var currentBlock = buffer.b[i]
if (currentBlock.n === 'else') {
returnStr += 'else{' + Sqrl.compileScope(currentBlock.d, env) + '}'
} else if (currentBlock.n === 'elif') {
returnStr +=
'else if(' +
currentBlock.p +
'){' +
Sqrl.compileScope(currentBlock.d, env) +
'}'
}
}
}
return returnStr
})
```
# API Overview
URL: /docs/api/overview
***
id: overview
title: API Overview
-------------------
:::note
You can view the TypeDoc API documentation for Squirrelly at [https://squirrellyjs.github.io/squirrelly/modules/\_index\_.html](https://squirrellyjs.github.io/squirrelly/modules/_index_.html).
:::
## Big list of API options
* `__express` (alias for `renderFile`)
* `compile`
* `compileScope`
* `compileScopeIntoFunction`
* `compileToString`
* `defaultConfig`
* `filters`
* `getConfig`
* `helpers`
* `loadFile`
* `nativeHelpers`
* `parse` (see [Parsing](./parsing))
* `render` (see [Rendering](./rendering))
* `renderFile`
* `templates`
# Parsing
URL: /docs/api/parsing
***
id: parsing
title: Parsing
--------------
:::note
You won't need to use or understand Parsing unless you're writing native helpers or plugins.
:::
## Syntax
[TypeDoc doc page](https://squirrellyjs.github.io/squirrelly/modules/_parse_.html#parse)
## Examples
```js
var myTemplate = 'Hi, my name is {{it.name}}'
var compiled = Sqrl.parse(myTemplate)
//Returns a Squirrelly syntax tree (like an AST):
// ['Hi, my name is ', { f: [], c: 'it.name', t: 'r' }]
```
# Rendering
URL: /docs/api/rendering
***
id: rendering
title: Rendering
----------------
Rendering a template compiles a template and then calls it with the data you pass to it.
## Syntax
[TypeDoc doc page](https://squirrellyjs.github.io/squirrelly/modules/_render_.html#render)
## Example
```js
var myTemplate = "Hi, my name is {{it.name}}";
Sqrl.render(myTemplate, { name: "Johnny Appleseed" });
//Returns "Hi, my name is Johnny Appleseed"
```
# Partials & Layouts
URL: /docs/api/templates
***
id: templates-partials-layouts
title: Partials & Layouts
-------------------------
Templates, partials, and layouts are all stored in one object (exposed as `Sqrl.templates`).
## Loading templates / partials / layouts
If you just call `render` or `compile` with `name` or `filename` in options, Squirrelly will load your template.
## Defining Partials
```js
Sqrl.templates.define("my-partial", Sqrl.compile("This is a partial speaking"));
Sqrl.render('... {{@include("my-partial")/}}', {});
// ... This is a partial speaking
// To call a partial w/ data:
Sqrl.templates.define("my-partial-2", Sqrl.compile("Name: {{it.name}}"));
Sqrl.render(
'... {{@include("my-partial", {name: it.name})/}}',
// The 2nd argument passed to `include` is the data. You could also pass `it` to forward all data
{ name: "Ben" }
);
// ... Name: Ben
```
## Layouts
See [https://stackblitz.com/edit/squirrelly-layouts?file=index.js](https://stackblitz.com/edit/squirrelly-layouts?file=index.js) for an example of how to use layouts.
# Integrations
URL: /docs/resources/integrations
***
id: integrations
title: Integrations
-------------------
:::caution
None of these are:
* Officially supported
* Vetted for security
* Guaranteed to work
Use at your own risk!
:::
## Integrations
* [Consolidate.js](https://www.npmjs.com/package/consolidate) supports Squirrelly v7 and will soon support v8
* [fastify-squirrelly](https://github.com/scottkipfer/fastify-squirrelly) adds Squirrelly support to Fastify
# Async Support
URL: /docs/learn/async
***
id: async
title: Async Support
--------------------
:::note
Async support is still in-progress for environments not supporting `async`/`await`.
:::
## Syntax
```js
function resolveAfter2Seconds () {
return new Promise(resolve => {
setTimeout(() => {
resolve('HI FROM ASYNC')
}, 2000)
})
}
Sqrl.helpers.define('async-test', resolveAfter2Seconds)
async function doAsyncStuff () {
console.log(
await Sqrl.render(
'{{@async async-test()/}}',
{},
{ async: true, asyncHelpers: ['async-test'] }
)
)
// logs 'HI FROM ASYNC' after 2 seconds
}
// ALTERNATIVELY, WITH CALLBACKS:
Sqrl.render(
'{{@async async-test()/}}',
{},
{ async: true, asyncHelpers: ['async-test'] },
function (err, res) {
console.log(res)
// logs 'HI FROM ASYNC' after 2 seconds
}
)
```
# Async Helpers & Filters
URL: /docs/syntax/async
***
id: async
title: Async Helpers & Filters
------------------------------
Squirrelly supports optional async support using the `async` and `await` keywords (to support ES5 and lower, use a plugin or transpiler).
## Basic Syntax
Essentially, just put an `async` in front of a helper or filter name.
## Examples
```
{{@ async helpername(parameters) => var1 }}
{{/helpername}}
```
```
{{val | filter1 | async filter2}}
```
```
{{@async include("mypartial") /}}
```
# Auto XML-Escaping
URL: /docs/syntax/auto-escaping
***
id: auto-escaping
title: Auto XML-Escaping
------------------------
Auto-escaping is an important feature of Squirrelly. When it's enabled, every reference without the `safe` filter or `*` prefix will be HTML-escaped, to provide some protection against XSS.
:::caution
Squirrelly has **not** been vetted for security, and autoEscaping is probably not completely foolproof. We use the same function as many other template engines, like Mustache and Handlebars, but there's still the possibility that there's some vulnerability.
:::
```js
Sqrl.defaultConfig.autoEscape = true // Turns autoEscaping on
Sqrl.defaultConfig.autoEscape = false // Turns autoEscaping off
// autoEscaping is on by default
```
## Disabling
To avoid escaping a specific reference, you can pass it through the `safe` filter.
*Example*: `{{someref | safe}}`
You can also put an asterisk (`*`) after the opening delimiters and whitespace control tags.
*Examples*: `{{* someref}}`, `{{_ * someref}}`
:::note
Auto-escaping can be helpful, but it also negatively impacts performance. For best results, autoEscape data before you store it or attempt to render it in a template.
:::
# Built-in Helpers
URL: /docs/syntax/builtin-helpers
***
id: builtin-helpers
title: Built-in Helpers
-----------------------
Builtin helpers are helpers that come as part of the Squirrelly library. They can always be overwritten if desired, but they provide simple, no-setup logic within templates.
## if/else
```hbs
{{@if(it.somevalue === 1)}}
Display this
{{#else}}
Display this
{{/if}}
```
*This is a native helper*
## each
```hbs
{{@each(it.somearray) => val, index}}
Display this
The current array element is {{val}}
The current index is {{index}}
{{/each}}
```
### Helper References:
* `val`: the current array element
* `index`: the index of the array element
**Note that `val, index` are both optional and can be renamed. Ex. `=> item` or `=> item, number`**
## foreach
```hbs
{{@foreach(it.someobject) => key, val}}
This loops over each of an objects keys and values.
The value of the current child is {{val}}
The current key is {{key}}
{{/foreach}}
```
### Helper References:
* `key`: the key of the current object child
* `val`: the value of the current child
**Note that `val, index` are both optional and can be renamed. Ex. `=> item` or `=> item, number`**
## try-catch
```hbs
{{@try}}
This won't work: {{ *it.hi | validate}}
{{#catch => err}}
Uh-oh, error! Message was '{{err.message}}'
{{/try}}
```
### Helper References:
* `err`: the error
# Caveats
URL: /docs/syntax/caveats
***
id: caveats
title: Caveats
--------------
## Reserved variable names
*Don't use these variables in your templates*
* `it`
* `tR`
* `cb`
* `c`
## Parsing
* Using RegExp literals inside your templates has a high likelihood of making them fail. Please, put that logic in a helper or something. If you really must, use `new RegExp('a|b')` instead.
## Delimiters
* Delimiters have to be regular-expression escaped
* Your closing delimiter can't contain `(`, `)`, `|`, or `=>`. *This is due to our parsing algorithm needing to figure out when helper parameters have been closed, filters started, etc.*
# Cheatsheet
URL: /docs/syntax/cheatsheet
***
id: cheatsheet
title: Cheatsheet
-----------------
## Conditionals
```hbs
{{@if(it.someval === "someothervalue")}}
Display this!
{{#else}}
They don't equal
{{/if}}
```
## Looping over arrays
```hbs
{{@each(it.someArray) => val, index}}
The current array item is {{val}}, the current index is {{index}}
{{/each}}
```
## Looping over objects
```
{{@foreach(it.someObject) => key, val}}
The current object key is {{key}}, and the value is {{val}}
{{/foreach}}
```
## Logging to the console
```
{{!console.log("The value of it.num is: " + it.num);}}
```
**Note: you must include a semicolon (`;`) or template compilation will fail**
# Filters
URL: /docs/syntax/filters
***
id: filters
title: Filters
--------------
Filters let you pipe content through some predefined functions.
## Basic Syntax
```hbs
{{somereference | somefilter |anotherfilter}}
```
Squirrelly has a filter syntax similar to Nunjucks or Swig. Just put a `|` and then the filter name. You can pipe to multiple filters if you want.
Filters can also accept parameters.
## Example
```hbs
{{! /* Basic filters */}}
{{mystring | reverse | capitalize}}
{{! /* With Parameters */}}
{{it.someArray | join(", ")}}
```
:::note Defining Filters
Remember, you'll need to [define each filter](../api/filter-api) before you use it.
:::
## The `safe` flag
To disable autoescaping, you can write
```hbs
{{myreference | safe}}
```
This isn't a true filter, it just acts as a flag to let Squirrelly know not to autoescape.
# Helpers
URL: /docs/syntax/helpers
***
id: helpers
title: Helpers
--------------
Helpers are an easy way to include logic within a template. Conditionals, looping, and partials are all implemented using helpers.
## Basic Syntax
```
{{@helpername(parameters) => [var1, var2]}}
Content goes here
{{#helperblock}}
{{/helpername}}
```
You can have as many blocks as you want within a helper.
## Example
```
{{@portfolio( {userID: 3838357} )}}
Joe Edrick
{{#tagline}}
Cool Coder Person
{{#hobbies}}
Eating delicious food
{{#img}}
{{@user.img}}
{{/portfolio}}
```
## Self-Closing Helpers
Self-Closing Helpers are helpers that have no content, and are just called with parameters.
### Basic Syntax
```
{{@helpername(parameters) /}}
```
### Examples
```
{{@include("mypartial")/}}
```
# References (Interpolate)
URL: /docs/syntax/interpolate
***
id: interpolate
title: References (Interpolate)
-------------------------------
A reference (what doT would call an interpolation) outputs data into the template.
## Basic Syntax
```hbs
{{ reference }}
```
## Overview
Put a reference between the opening and closing delimiters (by default `{{`and `}}`).
**The data you call a template with is stored in an object named `it` by default.**
Since Squirrelly templates parse into JavaScript, you can write a reference using dot notation: `User's last name: {{it.user.lastName}}` or bracket notation: `
User's last name: {{it.user['lastName']}}`.
:::note
You can unescape a reference by putting `*` after the opening delimiters (ex. `{{* unescapedSomething }}`)
:::
:::caution
There can be spaces after the tag start (default `{{`) and before a tag close (default `}}`)
:::
# Native Code (Evaluate)
URL: /docs/syntax/native-code
***
id: native-code
title: Native Code (Evaluate)
-----------------------------
A native code tag inserts its contents into the template function. (It's what doT would call evaluation).
## Basic Syntax
```hbs
{{! ... }}
```
## Overview
Put valid JavaScript code between the tag delimiters.
## Comments
Comments are written with native code syntax.
*Example*:
```hbs
{{! /* this is a comment */}}
```
## Console.log
You can log to the console with native code syntax.
*Example*:
```hbs
{{! console.log("Hi"); }}
```
:::caution
Make sure you include semicolons when needed! Ex. `{{! console.log('x'); }}`
In general, semicolons are needed after calling functions.
:::
# Syntax Overview
URL: /docs/syntax/overview
***
id: overview
title: Syntax Overview
----------------------
## Definitions
We're going to call something between the set delimiters a tag. Ex: `{{...}}`, where `{{` and `}}` are called "delimiters"
## Language Items
There are 5 language items in Squirrelly:
* [Interpolation tags](interpolate) place the value of the code inside them into the rendered template.
*Example*: Rendering `Hi {{it.name}}` with `{name: "Ben"}` will return `"Hi Ben"`.
The data you call a template with is referenced using `it`, similarly to doT.js.
* [Evaluation tags](native-code) start with `!` and place the code inside them into the template function.
*Examples*: Comments are written using evaluation tags (`{{! /*comment */}}`), as are JS function calls (`{{! console.log('hi') }}`).
It's usually discouraged to use evaluation tags for complex functions and logic, which helpers are ideal for.
* [Helpers](helpers) start with `@` and are for logic in the template. Loops and conditionals are both implemented as native helpers, a special kind of helper that compiles into native JS code before rendering.
Helpers use blocks (that start with `#`) for logical separation.
*Examples*:
* If/Else:
```
{{ @if (it.number === 3) }}
Number is three
{{ #elif (it.number === 4) }}
Number is four
{{ #else }}
Number is five
{{ /if}}`
```
* [Filters](filters) are for post-processing values such as references and helpers. You can define your own that do anything from capitalizing letters to emojifying strings.
*Example*: `{{someref | capitalize}}`
## Inspiration
Squirrelly takes inspiration from Mustache, Handlebars, EJS, Nunjucks, Swig, doT.js, and many other great template engines.
# Partials and Template Inheritance
URL: /docs/syntax/partials
***
id: partials-layouts
title: Partials and Template Inheritance
----------------------------------------
## Partials
Partials are implemented behind-the-scenes as [native helpers](../api/native-helper-api), and the syntax is the same as a [self-closing helper](helpers#self-closing-helpers).
There are 2 types of partials: **registered partials** and **file partials**.
### Registered Partials
Registered partials work both in the browser and in Node.js. They must first be "registered", or defined, using `Sqrl.templates.define(...)`
**Syntax**
```
{{@include('mypartial', data) /}}
```
**Example**
Note that in this example we pass `it` as the data object to the partial. This allows it to access the data the template is called with.
```js
let mypartial = `My name is {{it.name}}`
Sqrl.templates.define('mypartial', Sqrl.compile(mypartial))
Sqrl.render("This is a partial: {{@include('mypartial', it) /}}", {
name: 'Ben',
})
// This is a partial: My name is Ben
```
### File Partials
File partials work only in Node.js. They do not have to be defined first.
**Syntax**
```
{{@includeFile('path-to-partial', data) /}}
```
**Example**
Note that in this example we pass `it` as the data object to the partial. This allows it to access the data the template is called with.
```handlebars
{{! /* src/partial.sqrl */}}
This is a partial speaking: "My name is {{it.name}}"
```
```js
// src/index.js
Sqrl.render("{{@includeFile('./partial', it) /}}", {
name: 'Ben',
})
// This is a partial speaking: "My name is {{it.name}}"
```
# Whitespace Control
URL: /docs/syntax/whitespace-trimming
***
id: whitespace-control
title: Whitespace Control
-------------------------
Squirrelly allows you to control the whitespace before or after tags.
:::note
Squirrelly borrows its whitespace control syntax from EJS
:::
## Basic Syntax
Opening delimiters can be followed with `-` or `_`, and closing delimiters can be prefixed with `-` or `_`
`_` at the beginning of a tag will trim all whitespace before it, and `_` at the end of a tag will trim all whitespace after it.
`-` at the beginning of a tag will trim 1 character of whitespace before it, and `-` at the end of a tag will trim 1 character of whitespace after it.
## Examples
```hbs
Hi
{{- it.myname }}
```
```hbs
{{_ ~if (it.num) _}}
{{/if}}
```
:::note Configuration
By default, Squirrelly removes the first whitespace character after each tag. This can be [configured](../api/configuration)
:::