https://github.com/mailru/fest
javascript templates
https://github.com/mailru/fest
Last synced: about 1 month ago
JSON representation
javascript templates
- Host: GitHub
- URL: https://github.com/mailru/fest
- Owner: mailru
- License: other
- Created: 2012-01-30T07:31:47.000Z (over 13 years ago)
- Default Branch: 0.9
- Last Pushed: 2019-01-28T21:30:09.000Z (over 6 years ago)
- Last Synced: 2025-08-19T03:34:32.892Z (about 2 months ago)
- Language: JavaScript
- Homepage:
- Size: 1.33 MB
- Stars: 130
- Watchers: 35
- Forks: 28
- Open Issues: 27
-
Metadata Files:
- Readme: README.md
- Changelog: changelog
- License: LICENSE.md
Awesome Lists containing this project
README
# Fest [](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
```xmlHello, 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
questionanswer
```### 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 codefest 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>>><strong>G</strong>ary</p>
<p>>><strong>M</strong>ary</p>
<p>>><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
```