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

https://github.com/mailru/fest

javascript templates
https://github.com/mailru/fest

Last synced: about 1 month ago
JSON representation

javascript templates

Awesome Lists containing this project

README

          

# Fest [![Build Status](https://travis-ci.org/mailru/fest.png?branch=0.8)](https://travis-ci.org/mailru/fest)

Fest — это шаблонизатор общего назначения, компилирующий XML шаблоны в самодостаточные JavaScript функции. Для установки требуется Node.js >= 0.8.

## Установка

```
npm install fest
```

## Введение

Шаблоны представляют собой XML документы, содержащие HTML, текстовые данные и управляющие конструкции. Шаблон задается парным элементом `` (с указанием пространства имен `http://fest.mail.ru`). Например:

```xml

Hello!

```

Данные передаваемые в шаблон, доступны через переменную с именем, указанным в атрибуте `context_name` элемента `fest:template`:

```xml

Hello, json.name!

```

Чтобы посмотреть результат работы, приведенных выше шаблонов, необходимо воспользоваться встроенной утилитой fest-render или API библиотеки.

### fest-render

Утилита `fest-render` используется для компиляции и последующего запуска скомпилированного шаблона из командной строки. В таком случае, для передачи данных в шаблон используется JSON-файл.

hello.json
```json
{"name": "John"}
```

hello.xml
```xml

Hello, json.name!

```

```
$ ./node_modules/.bin/fest-render --json=hello.json hello.xml
Hello,John!
```

_Замечание: начальные и конечные пробелы в текстовых узлах удаляются при компиляции. Если необходимо вывести символ пробела, можно вопспользоваться `fest:space`._

### render()

Функция `render()` API компилирует и исполняет шаблон с заданными параметрами.

hello.js
```javascript
var fest = require('fest');
console.log(fest.render('hello.xml'), {name: 'John'});
```

```
$ node ./hello.js
Hello,John!
```
## Данные и вывод

### fest:value

Служит для вывода значения JavaScript выражения. Поддерживаем 4 режима вывода: html (по умолчанию), text, js и json.

```xml
"';
]]>
value
value
value
value
```

### fest:var

Устаналивает локальную JavaScript переменную.

```xml
Ultimate Question of Life, The Universe, and Everything
question

answer
```

### fest:text

Выводит неформатированный текст.

```xml
"Hello"
```

### fest:space

Служит для вывода пробела. Необходим в тех случаях, когда пробел в тектовом узле удаляется при компиляции, например:

```xml
Hello,json.name!
```

### fest:set

Объявляет именованный подшаблон. Содержимое `fest:set` не будет выполнено до тех пор, пока не будет вызван блок с таким же имененем с помощью `fest:get`.

```xml
John
```

```xml

F. Kennedy

```

Для `fest:set` можно использовать атрибут `test`. Операция выполнится, если его значение (JavaScript выражение) истинно.

```xml
should not be set
```

Внутри `fest:set` доступен контекст `params`, передаваемый через `fest:get`.

```xml

Hello,params.username!

{username: "John"}
```

### fest:get

Выводит содержимое блока, объявленного через `fest:set`.

```xml

```

```xml
{'some': 'data'}
```

С помощью `fest:param` можно передавать в блок XML-данные.

```xml

html

{
title: json.title
}




json.title




params.doctype
params.title

params.content

```

Внутри атрибута `name` можно использовать JavaScript выражения для вычисления имени блока во время выполнения. Значения выражений, заключенных в фигурные скобки, объединяются с примыкающим текстом. Помимо этого, можно использовать атрибут `select`.

```xml

var name = 'foo'

foo
bar

```

### fest:element

Выводит HTML элемент с переменным именем.

```xml

var variable = 'table';

fest code

fest code

```

Результат:

```xml

fest code
fest code

```

### fest:attributes, fest:attribute

Добавляет атрибуты к родительскому элементы. Все `fest:attribute` должны быть внутри блока `fest:attributes`, который должен идти первым внутри элемента.

```xml


json.href

Some link

```

Существует быстрый способ вывести значение в атрибут:

```xml
Some link
```

Имена атрибутов можно вычислять в момент исполнения шаблона:

```xml






```

## Управляющие конструкции

### fest:each

Предоставляет механизм итерации по объекту.

```xml
var obj = {"foo": "bar"}

i=obj[i]

i=v

```

### fest:for

Выполняет итерацию по массиву или числовому ряду.

```xml
json.items = ['a', 'b', 'c']

json.items[i]

v

i

```

### fest:if

Условный оператор.

```xml

It's true!

```

### fest:choose, fest:when, fest:otherwise

Ветвление. Если ни у одного `fest:when` условие не выполнено, будет выбрана ветвь `fest:otherwise`.

```xml


one


two


More than 2

```

## Остальные конструкции

### fest:cdata

Служит для вывода блока CDATA.

```xml

<fest:cdata>
<![CDATA[alert ("2" < 3);]]>
</fest:cdata>

```

### fest:comment

Выводит HTML комментарий.

```xml
comment
```

### fest:doctype

Задает DOCTYPE генерируемой страницы.

```xml
html
```

### fest:script

Служит для выполнения произвольного JavaScript.

```xml

```

Содержимое `fest:script` можно загрузить из файла, указав в атрибуте `src` путь к нему.

```xml

```

### fest:include

Вставляет содержимое другого шаблона с заданным контекстом.

```xml
json.list = ['a', 'b', 'c'];

```

### fest:insert

Выводит содержимое файла:

```xml

<fest:insert src="style.css"/>
<style>
```

# Примеры

## Использование

Компиляция с помощью compile():
```javascript
var fest = require('fest');

var data = {name: 'Jack "The Ripper"'},
template = './templates/basic.xml';

var compiled = fest.compile(template, {beautify: false}),
template = (new Function('return ' + compiled))();

console.log(template(data));
```

Компиляция с последующей отрисовкой с помощью render():
```javascript
var fest = require('fest');

var data = {name: 'Jack "The Ripper"'},
template = './templates/basic.xml';

console.log(fest.render(template, data, {beautify: false}));
```

basic.xml
```xml
<?xml version="1.0"?>
<fest:template xmlns:fest="http://fest.mail.ru" context_name="json">
<h1>Hello,<fest:space/><fest:value output="text">json.name</fest:value></h1>
<!-- По умолчанию все значения fest:value экранируются -->
<!--
Необходимо использовать fest:space или
fest:text для явного указания строк с пробелами
-->
</fest:template>
```

Результат:

```html
<h1>Hello, Jack "The Ripper"</h1>
```

## Вложенные шаблоны

Данные на вход:
```javascript
var data = {
people: [
{name: 'John', age: 20},
{name: 'Mary', age: 21},
{name: 'Gary', age: 55}
],
append: '>>'
}
```

foreach.xml (основной шаблон):
```xml
<?xml version="1.0"?>
<fest:template xmlns:fest="http://fest.mail.ru" context_name="json">

<!-- Контекст можно передавать во вложенные шаблоны -->
<fest:include context_name="json" src="./person.xml"/>

<!-- Значением iterate может быть любое js-выражение -->
<fest:for iterate="json.people.reverse()" index="i">
<!-- Передаваемые значения будут доступны в контексте params -->
<fest:get name="person">json.people[i]</fest:get>
</fest:for>
</fest:template>
```

person.xml:
```xml
<?xml version="1.0"?>
<fest:template xmlns:fest="http://fest.mail.ru" context_name="json">

<!--
Используем set для объявления блока,
который используем в родительском шаблоне
-->
<fest:set name="person">
<p>
<fest:script><![CDATA[
var first = params.name[0],
other = params.name.slice(1);
]]></fest:script>
<fest:value>json.append</fest:value>
<strong>
<fest:value>first</fest:value>
</strong>
<fest:value>other</fest:value>
</p>
</fest:set>
</fest:template>
```

Результат:
```html
<p>&gt;&gt;<strong>G</strong>ary</p>
<p>&gt;&gt;<strong>M</strong>ary</p>
<p>&gt;&gt;<strong>J</strong>ohn</p>
```

## Использование set и get

```xml
<?xml version="1.0"?>
<fest:template xmlns:fest="http://fest.mail.ru" context_name="json">
<fest:set name="host">http://e.mail.ru</fest:set>
<fest:set name="all">msglist</fest:set>
<fest:set name="new">sentmsg?compose</fest:set>

<fest:set name="all_link">
<fest:get name="host"/>/<fest:get name="all"/>
</fest:set>

<fest:set name="new_link">
<fest:get name="host"/>/<fest:get name="new"/>
</fest:set>

<ul>
<!-- fest:attribute добавляет параметр к родительскому тегу -->
<li><a>
<fest:attributes>
<fest:attribute name="href"><fest:get name="all_link"/></fest:attribute>
</fest:attributes>
Все сообщения
</a></li>

<li><a>
<fest:attributes>
<fest:attribute name="href"><fest:get name="new_link"/></fest:attribute>
</fest:attributes>
Написать письмо
</a></li>
</ul>
</fest:template>
```

Результат:

```html
<ul>
<li><a href="http://e.mail.ru/msglist">Все сообщения</a></li>
<li><a href="http://e.mail.ru/sentmsg?compose">Написать письмо</a></li>
</ul>
```

## Интернационализация

### fest:plural

По умолчанию доступна поддержка плюрализации для русского и английского языка. В параметрах `fest.compile` можно передать любую другую функцию плюрализации.

```xml
<fest:plural select="json.n">один рубль|%s рубля|%s рублей</fest:plural>
```
Или англоязычный вариант:

```xml
<fest:plural select="json.n">one ruble|%s rubles</fest:plural>
```

Чтобы вывести символ “%” внутри тега `fest:plural` используйте “%%”:

```xml
<fest:plural select="json.n">…1%%…|…%s%%…|…%s%%…</fest:plural>
```

### fest:message и fest:msg

Позволяет указать границы фразы для перевода и контекст для снятия многозначности. Например,

```xml
<fest:message context="растение">Лук</fest:message>
<fest:message context="оружие">Лук</fest:message>
```

Для каждого `fest:message`, `fest:msg`, обычного текста, заключенного между XML тегами (опция `auto_message`), или текстового значения некоторых атрибутов компилятор вызывает функцию `events.message` (если такая была указана в параметрах). Данный механизм используется в `fest-build` утилите для построения оригинального PO-файла.

Пример вызова `fest-build` для создания PO-файла:

```
$ fest-build --dir=fest --po=ru_RU.po --compile.auto_message=true
```

Пример компиляции локализованных шаблонов:

```
$ fest-build --dir=fest --translate=en_US.po
```

Пример компиляции одного шаблона:

```
$ fest-compile path/to/template.xml
$ fest-compile --out=path/to/compiled.js path/to/template.xml
$ fest-compile --out=path/to/compiled.js --translate=path/to/en_US.po path/to/template.xml
```

## Contribution

Необходимо установить [Grunt](http://gruntjs.com):

```
$ git clone git@github.com:mailru/fest.git
$ cd fest
$ sudo npm install -g grunt-cli
$ npm install
$ grunt
```

Grunt используется для валидации JS (тестов) и запуска тестов. Перед отправкой пулл-риквеста убедись, что успешно выполнены `git rebase master` и `grunt`.

Если необходимо пересобрать шаблоны spec/expected, то выполните:

```
$ ./bin/fest-build --dir=spec/templates --exclude='*error*' --compile.beautify=true --out=spec/expected/build/initial
$ ./bin/fest-build --dir=spec/templates --exclude='*error*' --compile.beautify=true --out=spec/expected/build/translated --translate=spec/templates/en_US.po
```