Тема: Snakeskin
Показать сообщение отдельно
  #25 (permalink)  
Старый 25.06.2013, 19:08
Аватар для kobezzza
Быдлокодер;)
Отправить личное сообщение для kobezzza Посмотреть профиль Найти все сообщения от kobezzza
 
Регистрация: 19.11.2010
Сообщений: 4,338

Фух, вроде закончил работу на версией 2.3. На обновление доки сегодня наверно уже сил не хватит, отложу на завтра

Итак, почти 5 полных дней (рабочих ) я потратил на разработку новой версии Snakeskin, что было сделано:
1) Полностью переписана часть, отвечающая за анализ и обработку параметров директив:

В прошлых версиях директива with работала крайне криво и только на выводе значений (теперь её поддерживаю почти все директивы),
т.е. конструкция ниже не работала бы

{with myObj}
    {a + b}
{end}


Теперь же with работает ровно так, как от него этого ожидают, т.е. можно использовать сложные выражения и т.д.,
а также появилась возможность указать модификаторы, проще показать:

{with myObj}
    {with foo}
        {with deep}
            {a} /// эквивалентно myObj.foo.deep.a
            
            {#a}  /// эквивалентно myObj.foo.a
            {#2a} /// эквивалентно myObj.a
            {#3a} /// эквивалентно a
            
            {@a}  /// эквивалентно a
            {@@a} /// доступ к супер-глобальной переменной, об этом чуть позже
        {end}
    {end}
{end}


Как видите, теперь появилась возможность точно указывать контекст поиска: модификатор # указывает на то,
что искать свойство нужно на один with блок вверх, а если после решётки указать цифру, например, #2, то на два блока вверх и т.д.
Следует заметить, что # - это более короткая запись #1.
Модификатор @ позволяет сказать, что поиск значения объекта должен осуществляться вне блоков with.

Также теперь в выражениях появилась возможность использовать составные фильтры, т.е.
/// Для переменной a и b отдельно применяется фильтр ucfirst,
/// а затем ко всему выражению фильтр truncate
{(a|ucfirst) + (b|ucfirst) |truncate}


Чтобы ввести составной фильтр, нужно просто взять его декларацию в круглые скобки,
как это сделано на примере выше. Как и с глобальными фильтрами можно использовать несколько фильтров подряд, а также передавать значения в фильтр:

{(a|ucfirst|remove 'foo') + (b|ucfirst) |truncate}
{e = ('foo'|ucfirst)}


В догонку к фильтрам: исправлена ошибка при использовании побитового ИЛИ (|),
теперь считается, что если после | идёт или цифра или пробел, то это операция ИЛИ, а не фильтр:

{0|1} {0 | 1} /// ИЛИ

{a = 1}
{0| a} {0 | a} /// ИЛИ

{0|round} {0 |round} /// Фильтр


2) Супер-глобальные переменные. На самом деле эта фича существовала уже давно, но сейчас я её немного облагородил. Если вкратце:

/// Объявляем супер глобальную переменную
{a = 1}

{template foo()}
    {@a} /// Получаем значение супер глобальной переменной
    
    {with ...}
        {@@a} /// Получаем значение супер глобальной переменной внутри
    {end}
    
    // Объявляем супер глобальную переменную внутри шаблона
    {@e = 1}
{end}


Такие переменные хранятся в Snakeskin.Vars.

3) Директива var. Эта директива позволяет объявлять переменные внутри шаблона.
В отличии от констант переменные могут менять значение в ходе программы, но не могут явно переопределятся в дочернем шаблоне, как константы.

{template foo()}
    {var a = 1}
    {a = 2}
    {a = 3}
{end}


4) Директивы циклов: for, while, repeat/until

{for var i = 0; i < 10; i++}
    ...
{end}

{var i = 100}
{while i--}
    ...
{end}

{var i = 100}
{repeat}
    ...
{until i--}


4) Статичный scope для proto
Как я уже писал выше: теперь при декларации proto блока, он наследует родительский scope.

5) Сахарок:
Для директивы data добавлена короткая форма записи: {{ ... }};
Теперь функцииям-шаблонам в JS ставится свойство name.
Внутри шаблона доступны локальные переменные TPL_NAME и PARENT_TPL_NAME.

В остальном исправления множества ошибок и т.д.

ЗЫ:
И смешно и грустно: первая версия шаблонки была ~400 строк, а эта уже почти 2.7к
__________________
kobezzza
code monkey

Последний раз редактировалось kobezzza, 25.06.2013 в 20:13.
Ответить с цитированием