node package manager

jst_compiler

The client and server template engine in JavaScript

jst


Клиентский и серверный шаблонизатор на JavaScript.

Возможности:

  • быстрый — шаблоны компилируются в чистый JavaScript;
  • компактный — ядро шаблонизатора занимает менее 6 КБ;
  • безопасный — экранирование HTML по умолчанию;
  • монолитный — ядро и скомпилированные шаблоны помещаются в один файл;
  • расширяемый — добавлять свои фильтры, использовать наследование в шаблонах;
  • простой — 10 минут на изучение.

npm install jst_compiler -g

jst_compiler ./example.jst.html - компиляция одного шаблона в файл ./example.jst.js

jst_compiler ./example.jst.html ./file.jst.js - компиляция одного шаблона в файл ./file.jst.js

jst_compiler ./examples - компиляция папки с шаблонами в файл ./all.jst.js

jst_compiler ./examples ./examples.jst.js - компиляция папки с шаблонами в файл ./examples.jst.js

jst_compiler -w ./examples ./examples.jst.js - компиляция папки с шаблонами в файл ./examples.jst.js без jst-ядра

jst_compiler -h - вызов справки

jst_compiler -V - версия компилятора

gulp-jst_compiler

  • npm install jst_compiler -g
  • Создаём файл с расширением .jst.html - example.jst.html:
<template name="example">
    Hello world!
</template>
  • jst_compiler ./example.jst.html
<!-- Скомпилированные шаблоны и ядро -->
<script src="./all.jst.js"></script>
...
<div id="container"></div>
...
<script>
    // Обычный способ
    document.getElementById('container').innerHTML = jst('example');
 
    // для jQuery
    $('#container').jst('example');
</script>
require('./all.jst.js'); // Скомпилированные шаблоны и ядро 
...
var content = jst('example');

Для вывода данных в шаблоне используется запись<%= data %>. Значения null или undefined заменяются на пустую строку, HTML при вставки экранируется.

Для вставки без HTML-экранирования используется запись <%! data %>.

<template name="example" params="word">
    Hello <%= word %>! <!-- С экранированием HTML -->
</template>
 
<template name="example" params="word">
    Hello <%! word %>! <!-- Без экранирования HTML -->
</template>
<template name="example" params="title, str = 'world'">
    <h2><%= title %></h2>
    Hello <%= str %>!
</template>
<template name="example" params="x">
    <% if (x) { %>
        Yes
    <% } else { %>
        No
    <% } %>
</template>

Предпочтительное использование условий (тернарная версия):

<template name="example" params="x">
    <%= x ? 'Yes' : 'No' %>
</template>
<template name="example" params="x">
    <%! template('myAnotherTemplate', x) %>
</template>
 
<template name="myAnotherTemplate" params="x">
    ...
</template>
<template name="example" params="x">
    <block name="block1" params="y">
        ...
        <%= y %>
        ...
    </block>
    <block name="block2">
        ...
    </block>
 
    <%= block('block1', x) %> <!-- HTML экранируется -->
    <%! block('block2') %> <!-- HTML не экранируется -->
 
</template>
<template name="myTemplate" params="items">
    ...
    <%= each('myAnotherTemplate', items) %>
    ...
</template>
 
<template name="myAnotherTemplate" params="element, index">
    ...
    <%= element %>
    ...
</template>

Итерироваться можно как по массивам, так и по объектам.

// Обычный способ 
var content = jst.each('item', [1, 2, 3]);
 
// Для jQuery 
$('#content').jstEach('item', [1, 2, 3]);
<template name="myTemplate" params="items">
    <block name="myBlock" params="element, index">
        <%= element %>
    </block>
 
    <%= eachBlock('myBlock', items) %>
 
</template>
<script>
    // Обычный способ
    var content = jst.eachBlock('myTemplate', 'myBlock', [1, 2, 3]);
 
    // Для jQuery
    $('#content').jstEachBlock('myTemplate', 'myBlock', [1, 2, 3]);
</script>

Между шаблонами наследуются блоки. Механизм наследования в шаблонах основан на прототипах в JavaScript.

<template name="one" params="x">
    <block name="block1" params="y">
        ...
        <%= y %>
        ...
    </block>
    <block name="block2">
        ...
    </block>
 
    <%= block('block1', x) %> <!-- HTML экранируется -->
    <%! block('block2') %> <!-- HTML не экранируется -->
 
</template>
 
<template name="two" params="x" extend="one">
    <%= block('block1', x) %>
</template>

Фильтр позволяет преобразовать данные перед их вставкой в шаблон.

По умолчанию на весь вывод данных накладывается фильтр _undef (замена null и undefined на пустую строку). При использовании записи вида <%! a %> html не экранируется, а при <%= a %> накладывается фильтр html.

Короткая запись фильтра - <%= data | trim %> Длинная - <%= filter.trim(data) %>

Можно указывать несколько фильтров, порядок выполнения - слева направо.
<%= data | stripTags | trim | truncate(8) %>
<%= filter.truncate(filter.trim(filter.stripTags(data), 8))) %>

Удалить пробелы с начала и конца строки:
<%= ' hello world! ' | trim %>hello world!

Удалить пробелы с начала строки:
<%= ' hello world! ' | ltrim %>hello world!

Удалить пробелы с конца строки:
<%= ' hello world! ' | rtrim %>hello world!

Обрезать строку до нужной длины:
<%= '1234567' | truncate(3) %>123

Перевести символы в верхний регистр:
<%= 'john' | upper %>JOHN

Перевести символы в нижний регистр:
<%= 'HoUsE' | lower %>house

Первый символ в верхний регистр:
<%= 'alice' | ucfirst %>Alice

Первый символ в нижний регистр:
<%= 'Dog' | lcfirst %>dog

Вывести первый элемент массива или первый символ строки:
<%= [2, 3, 4] | first %>2
<%= 'Cat' | first %>C

Вывести последний элемент массива или последний символ строки:
<%= [2, 3, 4] | last %>4
<%= 'Cat' | last %>t

Добавить строку перед значением:
<%= 'world!' | prepend('Hello ') %>Hello world!

Добавить строку после значения:
<%= 'Hello ' | append('world!') %>Hello world!

Повторить строку нужное количество раз:
<%= 'many ' | repeat(3) %>many many many

Удалить текст по регулярному выражению:
<%= 'hello world!' | remove('l') %>heo word!

Заменить текст по регулярному выражению:
<%= 'Hello boss!' | replace('boss', 'Duck') %>Hello Duck!

Удалить повторяющиеся пробелы:
<%= 'Dog' | collapse %>dog

Удалить HTML-теги:
<%= '<p>123</p>' | stripTags %>123

Склеить массив в строку:
<%= [1, 2, 3] | join(' ') %>1 2 3

Экранировать HTML:
<%= '<p>123</p>' %>&lt;p&gt;123&lt;/p&gt;
<%= '<p>123</p>' | html %>&amp;lt;p&amp;gt;123&amp;lt;/p&amp;gt; - двойное экранирование
<%! '<p>123</p>' %><p>123</p>
<%! '<p>123</p>' | html %>&lt;p&gt;123&lt;/p&gt;

Разэкранировать HTML:
<%= data | unhtml %>

Экранировать урл:
<%= myUrl | uri %>

Запретить вывод значения:
<%= data | void %>

jst.filter.myFilter = function (str, param) {
    //... 
    return str;
};
<template name="example" params="x, y">
    <%= 'x' %> hello world! <%= 'y' %> <!-- xhello world!y -->
    <%= 'x' +%> hello world!  <%= 'y' %> <!-- x hello world!y -->
    <%= 'x' +%> hello world!  <%=+ 'y' %> <!-- x hello world! y -->
</template>
<template name="example" params="word">
    Hello<% var b = word || 'world'; %> <%= b %>!
</template>
<template name="example" params="word">
    Hello <%# мой комментарий %>!
</template>
<template name="example" params="word">
    Hello <%# мой
    многострочный
    комментарий %>!
</template>

После компиляции каждый шаблон выполняется с помощью eval. В случае ошибки, шаблон в результирующий код не включается, вместо этого вставляется console.warn('...') с названием шаблона и описанием ошибки.

При вызове в коде неизвестного шаблона генерируется исключение.

Отладка в шаблонах:

<template name="example" params="data">
    <% console.log(data) %>
</template>

Лицензия

MIT License