An open API service indexing awesome lists of open source software.

https://github.com/sgolub/atat

šŸ— Fast and simple JavaScript template engine
https://github.com/sgolub/atat

express html javascript nodejs templating templating-engine typescript

Last synced: about 2 months ago
JSON representation

šŸ— Fast and simple JavaScript template engine

Awesome Lists containing this project

README

          


logo

# αtαt

Fast and simple asynchronous JavaScript template engine without dependencies and for any environment (:

[![Build Status](https://github.com/sgolub/atat/workflows/build/badge.svg)](https://github.com/sgolub/atat/actions)

## But why?

I wanted to create something simple for what you don't need to spend hours to read the documentation, something that you can start to use in a few minutes. The main idea is using pure JavaScript with pure HTML. You don't need to learn new syntax, just do everything like in JavaScript.

## Features

- Embedded JavaScript code
- Browser support
- Complies with Express
- Layouts, partials and sections
- No dependencies and very small size
- TypeScript support
- Easy to use

## Installation

Using yarn or npm:

```bash
$ yarn add atat
$ npm install --save atat
```

## Tests

Using yarn or npm:

```bash
$ yarn test
$ npm test
```

## Usage

```js
import { config, parse, loadAndRender, render, loadAndParse } from 'atat';

var atat = require('atat');
```

`atat` object has the following methods

- `config` to setup global configuration for all templates
- `parse` to parse a template, returns a render function
- `loadAndParse` the same with `parse` but allows a path to a template as the first argument
- `render` to parse and render a template, returns the result string
- `loadAndRender` the same with `render` but allows a path to a template as the first argument

```js
import { parse, loadAndRender, render, loadAndParse } from 'atat';

const render = await parse(templateString, options);
container.innerHTML = render(model);

container.innerHTML = await render(templateString, model, options);

const render = await loadAndParse(pathToTemplate, options);
container.innerHTML = render(model);

container.innerHTML = await loadAndRender(pathToTemplate, model, options);
```

If your environment doesn't support `async/await` sytax, use `Promise`

```js
render(templateString, options).then((err, result) => {
container.innerHTML = result;
});
```

### Options

- `it` models variable name, default `"it"`
- `$` helpers variable name, default `"$"`
- `helpers` extra helpers
- `loader` templates provider

```js
import { parse, render, config, DEFAULT_LOADER } from 'atat';
const options = {
it: "it",
$: "$",
helpers: { },
loader: DEFAULT_LOADER
};

// global config will be applied to all templates
config(options);

// also you can pass options to the parse and render methods
const tmpl = await parse(templateString, options);
const html = await render(templateString, { /* model */ }, options);
```

### Loaders

Loaders allow you to load templates asynchronously. There are two default loaders available right from the library:
- `DEFAULT_LOADER` - for Node.js, default loader, uses `fs` module
- `FETCH_LOADER` - for a browser, loads templates through `fetch` method

```js
import { loadAndRender, loadAndParse, config, FETCH_LOADER, DEFAULT_LOADER } from 'atat';

const html = await loadAndRender(
path.resolve(__dirname, './views/main.html'),
{ /* model */ },
{ loader: DEFAULT_LOADER },
);

// in a browser you must specify loader, at least FETCH_LOADER
const html = await loadAndRender(
'http://localhost:3000/views/main.html',
{ /* model */ },
{ loader: FETCH_LOADER },
);

// custom loader
config({
loader: async (path) => {
const template = await loadTemplate(path);
return template;
}
});
```

### Syntax

Encoded output

```html

@(it.user.firstName)@

```

Raw html output

```html

@!(it.rawHTML)@

```

Embedded JavaScript code

```html
@{
// Any JavaScript code is acceptable in this block
var firstName = it.user.firstName;
var secondName = it.user.secondName;
}@

@(firstName)@ @(secondName)@

```

**@if**

```html
@if (it.user != null) {

@(it.user.firstName)@


@(it.user.secondName)@


}@

```

**@if...else if...else**

```html
@if(it.user && it.user.firstName && it.user.secondName){

@(it.user.firstName)@


@(it.user.secondName)@


} else if (it.user && it.user.firstName) {

@(it.user.firstName)@


} else {

User is not defined


}@

```

**@for**

```html


    @for(var i = 0, l = it.users.length; i < l; i++){
  • @(it.users[i].firstName)@ @(it.users[i].secondName)@

  • }@

```

**@while**

```html


    @{ var i = 0, j = 5; }@
    @while (i < j) {
  • @(i++)@

  • }@

```

### Helpers

#### Custom helper

`@()@`

- `name` the valid name
- `args...` whatever you want

```js
const options = {
$: '$',
helpers: {
l10n: (lang, key) => resources[lang][key];
}
};

const result = await atat.render(template, { lang: 'en' }, options);
```

```html
@l10n(it.lang, "title")@
@('My Website - ' + $.l10n(it.lang, "title"))@

```

#### Default helpers

- `@json()@` returns a result of JSON stringify
- `@encode()@` the same as `@()@`
- `@join(, )@` joins the array with the separator (optional)
- `@upper()@` simple uppercase
- `@lower()@` simple lowercase

### Layout

`@layout()@`

- `path` the path to the layout file

**index.atat**

```html
@layout('/views/_layout.atat')@


Home page!

```

**/views/\_layout.atat**

```html




@!(body)@

```

Output:

```html





Home page!


```

### Patrial

Patrials allow you to reuse useful pieces of code in different places

`@partial(, )@`

- `path` path to partial a view file
- `model` model for a partial view (optional)

**views/\_menu.atat**

```html

```

**views/\_layout.atat**

```html
@{ const { $route } = it; }@



@partial('/views/_menu.atat', $route)@

@!(body)@

```

Output:

```html









```

### Section

Section allows you to pass HTML markup from a view to a layout level

Use the following syntax to specify a new section

```html
@section script {

document.addEventListener('DOMContentLoaded', function() {
// your code is here
});

}@
```

and another one to output the result anywhere

`@section()@`

- `name` sections name

**index.atat**

```html
@layout('/views/_layout.atat')@


Home page!

@section script {

document.addEventListener('DOMContentLoaded', function() {
// your code is here
});

}@
```

**/views/\_layout.atat**

```html




@!(body)@

@section('script')@

```

Output:

```html





Home page!



document.addEventListener('DOMContentLoaded', function() {
// your code is here
});

```

### ExpressJS Integration

Just set `'view engine'` value to `atat`

```js
const express = require('express');

const app = express();

app.set('views', './views');
app.set('view engine', 'atat');
```
Example available [here](https://github.com/sgolub/atat/tree/master/example)

### Demo

[Live demo](https://sgolub.github.io/atat)

## License

The JavaScript Templates script is released under the [MIT license](https://opensource.org/licenses/MIT).