npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

otvet-fest

v1.2.3

Published

js, lua, Xslate templator

Downloads

9

Readme

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 - выпилено