gulp-fest-hardcore

3.0.0 • Public • Published

gulp-fest-hardcore

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

кастрированная версия

  • нет try-cache - надо оборачивать саму ф-ю вызова

  • нет неймспейса fest

  • нет контекста, внутри шаблона есть только params

  • выпилины конструкции:

    • template - контексты убраны
    • text - нецелесообразен
    • element - полигон для усложнений
    • attributes - нецелесообразен
    • attribute - нецелесообразен
    • each - заменён на for
    • choose - заменён на switch
    • when - заменён на case
    • otherwise - заменён на default
    • script - обычный html тег
    • var - заменен на vars
  • изменены параметры и значения по умолчанию

    • value output -> escape по умолчанию text, вместо html
    • for from="1" to="5" выпилено
  • добавлены

    • for in <- each
    • switch <- choose
    • case <- when
    • default <- otherwise
    • vars <- var
    • js, lua, xslate, only <- script
  • нада быть внимательным: формируемый шаблон условно делится на выражения и возвращаемое значения.

<!--antipatern-->
<value>
  (params.c = params.a + params.b, params.c)
</value>
<if test="params.c">
  fail
</if>
<!--
module.exports = function (params) {
  var __expr0__ = "";
  if (params.c) {
    __expr0__ = "fail"
  }
  return ((params.c = params.a + params.b, params.c)) + __expr0__
}
-->
<!--patern-->
<script>
params.d = params.a - params.b
</script>
<if test="params.d">
  good
</if>
<!--
module.exports = function (params) {
  params.d = params.a - params.b;
  var __expr1__ = "";
  if (params.d) {
    __expr1__ = "good"
  }
  return __expr1__
}
-->

Установка

npm install gulp-fest-hardcore

Введение

Шаблоны представляют собой псевдо XML документы, содержащие HTML, текстовые данные и управляющие конструкции.

  Hello, <value>params.name</value>!

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

Данные и вывод

value

Служит для вывода значения JavaScript выражения. Поддерживаем 4 режима вывода: text (по умолчанию), html, js и json. Использует глобальные функции: $.escapeHTML(value), $.escapeJS(value) - их следует определить самостоятельно, или использовать следующие:

$.escapeHTML = function (s) {
  if (typeof s === 'string') {
    if (/[&<>"]/.test(s)) {
      return s.replace(/[&<>"]/g, function(chr) {
        return {
          '&': '&amp;',
          '<': '&lt;',
          '>': '&gt;',
          '\"': '&quot;'
        }[chr]
      });
    }
  } else if (typeof s === 'undefined') {
    return '';
  }
  return s;
}

$.escapeJS = function (s) {
  if (typeof s==="string") {
    if (/[\\'"\/\n\r\t\b\f<>]/g.test(s)) {
      return s.replace(/[\\'"\/\n\r\t\b\f<>]/g, function (chr){
        return {
          '"': '\"',
          '\\': '\\',
          '/' : '\\/',
          '\n': '\\n',
          '\r': '\\r',
          '\t': '\\t',
          '\b': '\\b',
          '\f': '\\f',
          '\'' : '\\\'',
          '<' : '\\u003C',
          '>' : '\\u003E'
        }[chr];
      });
    }
  } else if (typeof s==="undefined") {
    return "";
  }
  return s;
}

$.extend = function (original, extended) {
  extended = extended || {};
  for (var key in extended) {
    original[key] = extended[key];
  }
  return original;
}
return {
  escapeHTML = function (s)
    if s == nil then return '' end
    local esc, i = s:gsub('&', '&amp;')
                    :gsub('<', '&lt;')
                    :gsub('>', '&gt;')
                    :gsub('\"', '&quot;')
    return esc
  end,
  escapeJS = function (s)
    if s == nil then return '' end
    local esc, i = s:gsub('"', '\"')
                    :gsub('\\', '\\')
                    :gsub('/' , '\\/')
                    :gsub('\n', '\\n')
                    :gsub('\r', '\\r')
                    :gsub('\t', '\\t')
                    :gsub('\b', '\\b')
                    :gsub('\f', '\\f')
                    :gsub('\'' , '\\\'')
                    :gsub('<' , '\\u003C')
                    :gsub('>' , '\\u003E')
    return esc
  end,
  extend = function (destination, source)
    for k,v in pairs(source) do
      destination[k] = v
    end 
    return destination
  end
}
<vars value='"<script/>"' />
<value>value</value><!-- "<script/>" -->
<value escape="html">value</value><!-- &quot;&lt;script/&gt;&quot; -->
<value escape="js">value</value><!-- \"\u003Cscript\/\u003E\" -->

vars

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

<vars Illegar="1" question="'Ultimate Question of Life, The Universe, and Everything'" answer="question.length - 13" />
<value>Illegar</value><!-- undefined -->
<value>illegar</value><!-- 1 -->
<value>question</value><!-- Ultimate Question of Life, The Universe, and Everything -->
<value>answer</value><!-- 42  -->

space

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

Hello,<space/><value>json.name</value>!<!-- Hello, John! -->

require

Вызывает через require модуль с параметрами по аналогии с get

<require name="name0">{some: 'data'}</require>
<!--
var __params0__ = {some: 'data'};
require("name0")(__params0__);
-->

<require name="name1">
  <params>
    {a: 1, b:2}
  </params>
  <param name="html">
  <div class="a">1</div>
  </param>
</require>
<!--
var __params1__ = {};
$.extend(__params1__, {a: 1, b:2});
__params1__.html = '<div class="a">1</div>';
require("name1")(__params1__);
-->

<require name="name2" params="{a:1, b:2}" />
<!--
var __params2__ = {a:1, b:2};
require("name2")(__params2__);
-->

<require name="name3" params="{a:1, b:2}">
  {a:2,b:3,c:4}
</require>
<!--
var __params3__ = {a:1, b:2};
$.extend(__params3__, {a:2,b:3,c:4});
require("name3")(__params3__);
-->

set

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

<set name="name">John</set>
<set name="full_name">
    <get name="name"/><space/>F. Kennedy
</set>

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

<set name="line">
  Hello,<space/><value>params.username</value>!
</set>
<get name="line">{username: "John"}</get><!-- Hello, John! -->

get

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

<get name="name" />
<get name="name">{'some': 'data'}</get>
<get name="test">
  {a: 1, b:2}
</get>

<get name="test">
  <params>
    {a: 1, b:2}
  </params>
  <param name="html">
  <div class="a">1</div>
  </param>
</get>

<get name="test" params="{a:1, b:2}" />

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

<vars name="'foo'" />
<get select="name"/><!-- foo -->
<set name="foo">foo</set>
<set name="bar">bar</set>
<get name="b{true?'a':''}r"/><!-- bar -->

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

<a href="{params.href}">Some link</a>

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

for

Выполняет итерацию по массиву или числовому ряду. неявно оборачивается if который проверяет iterate и его length, в связи с этим можно после закрытия </for> пришпилить elseif или else как в обычном if стеке

<!-- params.items = ['a', 'b', 'c'] -->
<for iterate="params.items" index="i" value="v">
  <value>params.items[i]</value>
</for><!-- abc -->

<!-- params.items = ['a', 'b', 'c'] -->
<for var="v" of="params.items">
  <value>v</value>
</for><!-- abc -->

<!-- params.items = ['a', 'b', 'c'] -->
<!--  спорно: в принципе там следует ожидать индекс, а не значение -->
<for var="v" in="params.items">
  <value>v</value>
</for><!-- abc -->

<!-- if (params.items && params.items.length)-->
  <for iterate="params.items" index="i" value="v">
    <value>v</value>
  </for><!-- abc -->
<!-- /if -->
<elseif test="foo">
  foo text
</elseif>
<elseif test="bar">
  bar text
</elseif>
<else>
  else text
</else>

if, elseif, else

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

<if test="var0">
  <value>var0</value>
</if>
<elseif test="var2">
   <value>var2</value>
</elseif>
<else>
  ELSE
</else>

switch case default

<switch test="var0">
  <case is="1">
    var is 1
  </case>
  <case is="'2'">
    var is '2'
  </case>
  <case is="a">
    var is `a`
  </case>
  <default>
    var is not 1 or 2
  </default>
</switch>

Если нужно

switch (z) {
  case 'a':
  case 'b':
  case 'c':
    domagick;
  break;
  case 'd':
    doD;
  break;
  default:
    'docommon'
}

пользуй аттрибут any и сепаратор значений |. не нужен break? пользуй аттрибут nobreak

<switch test="z">
  <case any="'a' | 'b' | 'c'">
    <value>domagick</value>
  </case>
  <case is="'c'">
    <value>doD</value>
  </case>
  <default nobreak="1">
    docommon
  </default>
</switch>

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

cdata

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

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

comment

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

<comment>comment</comment><!-- <!--comment--> -->

doctype

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

<doctype>html</doctype><!-- <!doctype html> -->

include

выпилено

insert

Вставить файл напрямую в шаблон src - относителен к текущему файлу (его папке)

<style type="text/css">
  <insert src="style.css"/>
<style>
<script>
  <insert src="inline-script.js"/>
</script>

js lua xslate only script

Раньше в script запихивалась js-магия, нужно было разделить эту магию на js, lua и xslate, когда шаблонизатор начал поддерживать эти языки. так появился only с аттрибутом for. далее появильсь более простые обёртки, в виде тегов смысл которых идентичен:

<script><insert src="inline.js" /></script><!-- <script>#контент файла inline.js#</script>  -->

<js>
  var i = function(...){...}
</js>

<lua>
  <vars cjson="require 'cjson'" />
  <script>
    console.log(<value>cjson.encode(params)</value>)
  </script>
</lua>

<xslate>
  my i = include inc::html ->{}
</xslate>

<only for="js">
var i = function(...){...}
</only>

continue

break

return

вставляют в текущий стек выражений соответствующую конструкцию

Примеры

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

var parser = new Parser(options);
parser.write(file.contents.toString('utf8'), file.path);
file.contents = parser.getSource();

gulp:

var festHardcore = require('gulp-fest-hardcore');
gulp.src('src/**/*.xml')
    .pipe(festHardcore())
    .pipe(beautify({
      indentSize: 2
    }))
    .pipe(gulp.dest('build/templates'))

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

<set name="host">http://e.mail.ru</set>
<set name="all">msglist</set>
<set name="new">sentmsg?compose</set>

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

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

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

fest:plural - выпилено

Readme

Keywords

Package Sidebar

Install

npm i gulp-fest-hardcore

Weekly Downloads

31

Version

3.0.0

License

MIT

Last publish

Collaborators

  • ikuznetsov