Javascript-форум (https://javascript.ru/forum/)
-   Ваши сайты и скрипты (https://javascript.ru/forum/project/)
-   -   Snakeskin (https://javascript.ru/forum/project/35057-snakeskin.html)

kobezzza 29.01.2013 17:03

Snakeskin
 
https://github.com/SnakeskinTpl/Snakeskin
http://snakeskintpl.github.io/docs/index-ru.html
http://codepen.io/kobezzza/pen/zrJNXx

kobezzza 04.02.2013 14:08

Обновил версию, исправил кучу багов и добавил пару новых фич, написал статью на хабр, где очень подробно описал всё, ссылку приложил к первому посту и в readme на гитхабе.

Tim 05.02.2013 01:41

Цитата:

ссылку приложил к первому посту и в readme на гитхабе
спс, люблю квесты

кст, инвайтом не поделишься? :p

Deff 05.02.2013 02:21

Цитата:

Сообщение от Tim
инвайтом не поделишься?

Если про хабр там имхо карма должна более 50, (про гит - не наю

kobezzza 05.02.2013 09:59

Цитата:

Сообщение от Tim (Сообщение 231650)
спс, люблю квесты

кст, инвайтом не поделишься? :p

Какие квесты, ты о чём? Мне просто напряжно поддерживать актуальной инфу сразу в куче источников, а в первом посте всего 2 ссылки и понятно, что и куда и ведёт.

Напиши статью, и тебе скорее всего дадут инвайт. Я на хабре редко сижу и кармы у меня там нема.

Цитата:

Сообщение от Deff (Сообщение 231665)
(про гит - не наю

У гитхаба только приватные репозитарии платные, я вот за 8-мь штук где то 12 баксов плачу в месяц, очень доволнен.

PS: я удивлён, что данный пост здесь не вызывал никакой реакции, даже не закидали какашками :) Ведь тема шаблонизации для ЖС больная и уже есть овер9000 велосипедов, но буду считать, что людям просто лень читать мой пост :)

Deff 05.02.2013 11:49

Цитата:

Сообщение от kobezzza
но буду считать, что людям просто лень читать мой пост

Там имхо с конца января пошла толпа заготовок забавных новостных топиков и переводов(по 4-10 новых страниц за сутки)... Народ на текущие местные разработки просто забил и они теряются в толпе. Ксать погоняй статью по разным Хабам(у тебя сейчас она только в разделе JavaScript*, (в Веб-разработке* - неплохое отношение к поделкам), карочь можно отображение присутствие в Хабах можно менять и, сразу, одновременно, можно показать присутствие статьи до в 3-х Хабах)
Добавка отражений в Хабах - клик по текущему JavaScript* (при редактировании

В апреле опять спад интереса... Карочь самое вдумчивое отношение на Хабре - осенью

Зы: я б диннотексты во второй части - "Синтаксис шаблонов Snakeskin", "Директивы" ,
- Т. е каждый подобный подраздел с кодами убрал под спойлер: имя на спойлере - имя данного подраздела,
тогда бы страх "многотекста" рассеялся

*Возможно вслед за скрытым спойлером с именем раздела(или до) - короткий резъюм в пару строк.

DjDiablo 05.02.2013 12:17

Цитата:

буду считать, что людям просто лень читать мой пост
Ну почему же, мы прочитали :)

* сомневаюсь в том что в наследовании есть смысл.

* Также я задумываюсь о более активном применении data-bind, а его у тебя нет.

* Сильно не нравиться то что шаблоны оказывают в глобальной области видимости. Думаю неймспейсы должны быть обязательными.

в остальном пока без эмоций.

kobezzza 05.02.2013 12:26

Цитата:

Сообщение от DjDiablo (Сообщение 231701)
* сомневаюсь в том что в наследовании есть смысл.

По опыту работы с огромными приложениями (десятки и сотни тысяч строк кода) могу сказать, что наследование в шаблонах это ну ппц как круто, а про остальное дело вкуса.

Если использовать ООП при построение UI, то наследование в шаблонах это просто волшебно, пример из реального проекта:
выпадающее меню -> стилизованный селект -> поле ввода с автокомплитом, логично что у этих UI идёт цепь наследования JavaScript, но также у них наследуются шаблоны и тем самым мы избавляемся от копипасты.

kobezzza 05.02.2013 13:16

Deff,
да я в общем, не гонюсь ни за кармой, ни за славой, но пасиб за советы:) Эта шаблонка, как наверно и всё остальное, что я делаю - делаю в первую очередь для себя и своих задач, а статью писал как размышления для самого себя и дока для моих наёмных работников, ну если кто захочет использовать в своих проектах, то мне безусловно будет приятно:)

Меня просто удивило, что такая холиварная тема осталась незамеченной:) Когда я работал в Яндексе, то мы каждый день спорили с другими отделами чей шаблонизатор лучше:)

kobezzza 05.02.2013 15:42

Добавил в "Веб-разработку" :)

nerv_ 19.06.2013 00:59

глупый вопрос - в боевых проектах использовал или сделал и положил на полку? :)

UPD:
не знаю, как оно там с точки зрения парсинга, но смущает, что:
- циклы
{forEach a => el, i}
{end}

- ифы
{if a > 3}
{end}

- вичи :)
{with obj}
{end}

- темплейты
{template test(obj)}
{end}

- прото
{proto a}
{end}

- блок
{block a}Вася{end}

заканчиваются на {end} в то время, как
- cdata
{cdata}
{end cdata}

на {end cdata}. Не порядок, однако.

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

Привет бейсик, здравствуй наглядность:
{forEach a => el, i}
{next}

{if a > 3}
{end if}

{with obj}
{end with}

{template test(obj)}
{end template}

{proto a}
{end proto}

{block a}Вася{end block}

{cdata}
{end cdata}

kobezzza 19.06.2013 02:20

Цитата:

Сообщение от nerv_ (Сообщение 257106)
глупый вопрос - в боевых проектах использовал или сделал и положил на полку? :)

Конечно использую, этот как бы и писалось под проект (я вроде об этом говорил:) ), причём огромный, сейчас уже больше 300-шаблонов (пишу несколько лет, но последние пол года на фул тайме, т.к. уволился с работы, Бог даст к НГ сделаю релиз) и многие находятся в зависимостях наследования.

Я очень жирно использую ООП и мне крайне важно было максимально гибкая система наследования в шаблонах, а также одинаково удобная система использования на сервере (node.js) и клиенте.

Ошибки и новые фичи исправляю по мере необходимости. На этой недели собирался сделать большой фикс, так как всплыли некоторые оч противные баги (вроде невозможности декларировать константы внутри прототипа).

С cdata проблема в том, что содержимое вырезается по регулярке до анализа шаблона и построения дерева, поэтому возможна следующая проблема:

{cdata}
    {end}
{end}


Фактически содержимое внутри блока cdata никак не обрабатывается, поэтому я могу написать что угодно, но в данном случае нужно либо как то экранировать {end} теги внутри области (как например это делается в xml), тому кто пишет шаблон или ввести особый закрывающий тег, как сейчас сделано у меня.

А так я не вижу смысла делать для каждой директивы свой закрывающий тег - это имхо не круто, тем более с точки зрения парсинга это не даёт профита, т.к. по шаблону у меня строится дерево, в котором видна вся вложенность блоков. Ну а чтобы было видно человеку - нужно делать отступы :)

{template foo(params, type = 'static')}
    {if type === 'static'}
        муахахаха!
    {else}
        {block bar}
            ...
        {end}
    {end}
{end}

nerv_ 19.06.2013 11:11

kobezzza, спасибо за ответ.

По поводу {end} я категорически тебе предлагаю сделать так, как написал выше. Причина - удобство. Я вижу какой тег закрыт :) Пример
// начало кода
// много букв
    {end}
{end}

смысл примера в том, что я не вижу шапки кода, только подвал. Т.о. для того, чтобы отличить одно от другого, придется скроллить. Иными словами, на этом уровне все кошки серы (почти все).

Можно замутить опрос, но на мой взгляд это скорее минус, чем плюс.

nerv_ 19.06.2013 11:16

еще можно пойти по пути html
{foreach} a => el, i}
{/foreach}

{if a > 3}
{/if}

{with obj}
{/with}

{template test(obj)}
{/template}

{proto a}
{/proto}

{block a}Вася{/block}

{cdata}
{/cdata}

т.е. я к тому, что должно быть видно, какой тег закрыт

Цитата:

Сообщение от kobezzza
Конечно использую, этот как бы и писалось под проект (я вроде об этом говорил )

значит я проглядел :)

Почему развел демагогию: присматриваюсь к твоему шаблонизатору :D

kobezzza 19.06.2013 11:23

Цитата:

Сообщение от nerv_ (Сообщение 257139)
kobezzza, спасибо за ответ.

По поводу {end} я категорически тебе предлагаю сделать так, как написал выше. Причина - удобство. Я вижу какой тег закрыт :)

Я могу добавить реализацию {/...} или {end ...}, это не проблема и даже ничего переделывать не придётся:) На этой недели или в начале следующей зарелизю новую версию с исправлениями.

Цитата:

Сообщение от nerv_ (Сообщение 257141)
Почему развел демагогию: присматриваюсь к твоему шаблонизатору

Ну если решишься, то пиши, что не так :)

UPD:
Я протупил, писать {end что то} можно уже сейчас, т.е.
{forEach data => el, i}
{end forEach}


Т.к. парсер обрабатывает директиву, как {названиеДирективы любые условия}, а в случае с end условий нет, т.е. можно писать что угодно и это ничего не сломает :)

{forEach data => el, i}
{end это конец моего блока}

kobezzza 19.06.2013 11:51

Добавил поддержку закрытия директив через / , как в xml. Новая версия доступна на гитхабе.

{template foo()}
{/template}


Раз уж зашла тема, скажу что в следующей версии добавлю:
1) Переменные. Я долго противился этому введению, пока пару раз сам не встал на грабли, когда константы не могут их заменить. В отличии от констант переменные нельзя будет явно переопределить в дочернем шаблоне, а только через переопределение родительского блока или прототипа или константы на которую переменная ссылается.

Т.е.
{template base()}
    {block foo}
        {var a = 1}
        ...
    {end}
{end}

{template child() extends base}
    /// Переопределяем блок и заодно переменную внутри него
    {block foo}
        {var a = 2}
    {end}
{end}


2) Циклы. Есть задачи, вроде: сгенерить для select-а номер года от 19.. до ныненшнего, а с итератором такое решение выглядит немного странно.

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


вместо
{forEach new Array(10) => el, i}
    ...
{end}


3) Также улучшу и задокументирую некоторые нестандартные фичи, о которых сейчас знаю только я :)

В остальном будет исправление известных ошибок и написание новых тестов.

nerv_ 19.06.2013 18:09

kobezzza, отлично, спасибо :)

kobezzza 23.06.2013 22:33

Почти закончил работу, над новой версией, скорее всего во вторник выложу, но возник вопрос, когда переписывал модуль обработки scope, а именно:

Мой шаблонизатор поддерживают директиву with (в JS with не используется), которая позволяет явно указывать контекст поиска свойств объекта, т.е. :

{template foo()}
    {my = {
        name: 'Koba',
        age: 23
    }}

    {with my}
        <p>Имя: {name}</p>
        <p>Возраст: {age}</p>
    {end}
{end}


Это очень удобно, особенно когда у нас ссылка вроде myObj.someProp1.someProp2.
А также в моём шаблонизаторе есть "волшебная" директива proto, которая позволяется создавать что-то вроде микрошаблонов.

{template foo()}
    {proto logo}
        <img src="..." alt="моё супер лого" />
    {end}

    <div class="header">
        ...
        {apply logo}
    </div>

    <div class="footer">
        ...
        {apply logo}
    </div>
{end}


Думаю смысл кода выше всем понятен, но всё же поясню: внутри директивы proto мы декларируем часть шаблона, которая не будет выведена сразу после декларации, а только после того, как мы её вызовем, с помощью директивы apply.

А теперь собственно суть проблемы: сейчас директива proto всегда использует глобальный scope шаблона, т.е.

{template foo()}
    {my = {
        name: 'Koba',
        age: 23
    }}

    {with my}
         {proto gen}
            <p>Имя: {name}</p>
            <p>Возраст: {age}</p>
         {end}
         /// Будет ошибка, т.к. прототип всегда использует глобальный контекст шаблона
         {apply gen}
    {end}
{end}


Проблема решается в общем то довольно тривиально: нужно просто поместить директиву with внутрь прототипа, но я подумал, а что если прототипы будут при декларации получать родительский scope, т.е. пример выше сможет корректно работать, т.к. директива proto находится в контексте with и будет его наследовать. Как вам такое предложение?

melky 24.06.2013 00:17

Цитата:

Сообщение от kobezzza
Как вам такое предложение?

а вот так можно будет делать?
{template foo()}

    {my = {
        name: 'Koba',
        age: 23
    }}

     {proto gen}
        <p>Имя: {name}</p>
        <p>Возраст: {age}</p>
     {end}

    {with my}
         {apply gen}
    {end}

{end}

kobezzza 24.06.2013 09:06

Цитата:

Сообщение от melky (Сообщение 258063)
а вот так можно будет делать?
{template foo()}

    {my = {
        name: 'Koba',
        age: 23
    }}

     {proto gen}
        <p>Имя: {name}</p>
        <p>Возраст: {age}</p>
     {end}

    {with my}
         {apply gen}
    {end}

{end}

Не, я же делаю статический scope, т.е. определяется в момент декларации, а не в момент вызова. Но, я думаю о возможности указывать scope явно при вызове прототипа.

nerv_ 24.06.2013 21:48

Цитата:

Сообщение от kobezzza
Мой шаблонизатор поддерживают директиву with (в JS with не используется), которая позволяет явно указывать контекст поиска свойств объекта, т.е. :

к слову, в бэйсике (vbscript) директива with работает следующим образом:
with obj1
    .prop = 2; // магическая точка очень кстати
end with


Цитата:

Сообщение от kobezzza
Но, я думаю о возможности указывать scope явно при вызове прототипа.

звучит неплохо. Только, если прототип не указан явно, надо что-нибудь подставить по умолчанию :)

kobezzza 25.06.2013 11:51

Цитата:

Сообщение от nerv_ (Сообщение 258262)
к слову, в бэйсике (vbscript) директива with работает следующим образом:
with obj1
    .prop = 2; // магическая точка очень кстати
end with

В новой версии, которая наверно сегодня выйдет я сделал похожее решение, но более гибкое. Как зарелизю, так опишу)

Цитата:

Сообщение от nerv_ (Сообщение 258262)
звучит неплохо. Только, если прототип не указан явно, надо что-нибудь подставить по умолчанию :)

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

По умолчанию раньше у всех прототипов где бы они не были объявлены всегда был был глобальный контекст (относительно шаблона). В новой же версии контекст по умолчанию привязан к родительскому (как я описывал постами выше).

Ща пью кофе, делаю финальные тесты, рефакторинг и обновляю доку:) К вечеру всё буит наверно

animhotep 25.06.2013 12:51

интересно глянуть. сейчас демо с гитхаба ругается
Snakeskin Error: Missing closing or opening tag in the template, node: (class: undefined, id: templates)")!


теги все там закрыты, так что хз чего он хочет

kobezzza 25.06.2013 13:08

Цитата:

Сообщение от animhotep (Сообщение 258343)
интересно глянуть. сейчас демо с гитхаба ругается
Snakeskin Error: Missing closing or opening tag in the template, node: (class: undefined, id: templates)")!


теги все там закрыты, так что хз чего он хочет

Гм, разберусь.

UPD: не были закомитены собранные файлы, теперь всё работает

kobezzza 25.06.2013 19:08

Фух, вроде закончил работу на версией 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 26.06.2013 16:02

Зарелизил версию 2.3.4 с исправлением некоторых ошибок.
Также теперь проект добавлен в репозитарий npm, следовательно для простой установки можно сделать:

npm install -g snakeskin


Обновилось консольное АПИ. Подробности в доке на гитхабе или в консольке -h.
Обновилась документация на гитхабе.

Тем кто юзает продукты JetBrains теперь можно оч просто настроить file watcher для шаблона.
Поиграться с шаблоном можно здесь: http://jsfiddle.net/NAPWB

рони 26.06.2013 16:26

Цитата:

Сообщение от kobezzza
Поиграться с шаблоном можно здесь

ие не будет грузить скрипт с гитхаба в нём непосмотреть.

kobezzza 26.06.2013 16:28

Цитата:

Сообщение от рони (Сообщение 258629)
ие не будет грузить скрипт с гитхаба в нём непосмотреть.

Угу, уже пофиксил:)

nerv_ 26.06.2013 18:20

правильно понимаю, что это http://jsfiddle.net/NAPWB/3/ должно работать?

kobezzza 26.06.2013 18:31

Цитата:

Сообщение от nerv_ (Сообщение 258651)
правильно понимаю, что это http://jsfiddle.net/NAPWB/3/ должно работать?

Должно, это баг. Сейчас разберусь.

UPD: поправил, бага наитупейшия была, а воспроизводилось только на пробельных отступах :) Спс за репорт!

рони 26.06.2013 18:47

kobezzza,
ие нехочет {template helloWorld(name)}
up - заработало

kobezzza 26.06.2013 18:50

Цитата:

Сообщение от рони (Сообщение 258655)
kobezzza,
ие нехочет {template helloWorld(name)}
up - заработало

Это я случайно не тот файл залил:)

nerv_ 26.06.2013 19:15

Цитата:

Сообщение от kobezzza
поправил

спасибо :)

В целом, на мой взгляд, перспективный шаблонизатор.

upd: кстати, что насчет производительности? http://jsperf.com/javascript-templat...off-extended/2

kobezzza 26.06.2013 19:54

Цитата:

Сообщение от nerv_ (Сообщение 258658)
кстати, что насчет производительности? http://jsperf.com/javascript-templat...off-extended/2

Я честно не вижу смысла сравнивать скорость трансляции. Я знаю как ускорить трансляцию раза в полтора у себя, но это ухудшит читабельность кода, а смысла в этом особо нет.

Скорее всего всякие микро-темплейтинги делают трансляцию быстрее, т.к. весь их алгоритм - это сплит по разделителю и new Function.

У меня в проекте ~300 шаблонов и их трансляция это примерно 5-10% от общей сборки проекта и на моей машинке делается где то 0.7 секунд, а для сравнения Google Closure Templates делает это секунд за 20 (хз, почему так долго, особенно учитывая, что он написан на яве).

Но это всё лирическое отступление:)

Если у тебя 10-ок шаблонов и ты компилишь их на клиенте, то это в любом случае сделается очень быстро даже в ИЕ6 и даже на телефоне:) А если у тебя целая куча шаблонов и ты компилишь их не на сборке проекта, то стоит задуматься, а всё ли ты делаешь правильно:)

Да и вообще прекомпиляция это даже удобнее:
1) Скомпиленые шаблоны можно пропустить через минификатор вместе с остальным JS и это лишит головной боли с экспортом свойств, если сжатие идёт например через GCC.
2) Скомпилиный шаблон работает "мгновенно", т.к. его не нужно предварительно парсить и т.д.
3) Шаблоны можно и нужно разбивать на разные файлы, а не лепить всё в кучу, и тут всё оч просто с таким подходом.
4) В JS я просто вызываю функцию, а не думаю: "ой, это шаблон, его нужно скомпилить"
5) Не нужно тащить транслятор на клиент: а в моём случае это почти 3к строк.

В общем Snakeskin задумывался как шаблонизатор с прекомпиляцией, но а поддержка live-исполнения сделана исключительно для отладки:)
Оптимизация ради оптимизации - это пустая трата времени.

nerv_ 27.06.2013 00:53

Цитата:

Сообщение от kobezzza
5) Не нужно тащить транслятор на клиент: а в моём случае это почти 3к строк.

если есть сервер на node.js ) А как быть с php?

Цитата:

Сообщение от kobezzza
Скорее всего всякие микро-темплейтинги делают трансляцию быстрее, т.к. весь их алгоритм - это сплит по разделителю и new Function.

в целом так )

Цитата:

Сообщение от kobezzza
В общем Snakeskin задумывался как шаблонизатор с прекомпиляцией

да я так, побурчать :D тоже надо )))

kobezzza 27.06.2013 01:14

Цитата:

Сообщение от nerv_ (Сообщение 258694)
если есть сервер на node.js ) А как быть с php?

Зачем сервер? Я имел ввиду, что ты вовремя разработки написал шаблоны допустим, затем их скомпилил и просто включил на страничку как простой JS файл, где лежат нужные тебе функции, ну и дополнительно для работы нужно ещё подключить live модуль (snakeskin.live.js 800 байт). Если юзаешь вебшторм, то можно настроить фаел вотчер и он будет автоматом компилить шаблоны.

Если ты хочешь автоматизировать процесс компиляции на PHP, то просто нужно на сервак поставить любую VM яваскрипта и из пыхи запустить процесс (по моему команда exec, не помню уже).

Или ты имел ввиду использование в качестве серверного шаблонизатора? То тогда на пыхе не оч удобно будет, а на той же ноде, то ещё проще :)

ЗЫ: http://screencast.com/t/iU7AgM6jvjaj что может быть проще?)

monolithed 28.06.2013 01:03

Цитата:

Сообщение от kobezzza
Если ты хочешь автоматизировать процесс компиляции на PHP

Чем shell не угодил? ;)

monolithed 28.06.2013 01:39

Как тебе такой подход:

// about.tpl
@set about (data, value = 0) {
    &.title: data.title,
    &.text:  value
}

// me.tpl
@set me < about (data) {
    &.title: data.title
}

// index.tpl
@include about, me

@get about {
   title: title 1
}

@get me ({
   title: title 2
}, 1)


Будет транслированно в:

<div class="about">
     <div class="about__title">
           title 1
      </div>
      <div class="about__text"> 0 </div>
</div>

<div class="about me">
     <div class="about__title me__title">
           title 2
      </div>
      <div class="about__text me__text"> 1 </div>
</div>



Как это будет выглядеть в твоем случае? :)

PS:
1. div по-умолчанию, хотя можно определить любой тег, используя селекторную нотацию h1.header
2. & означает конкатенацию (автодополнение для bem)
3. + планирется полная абстракция от тегов (web components), ну и data-binding

kobezzza 28.06.2013 12:04

monolithed,
Похоже на BEMHTML от Яндекса чем-то :) Хорошее решение. У меня будет как то так:

{template about(data, value = 0)}
	<div class="{PARENT_TPL_NAME} {TPL_NAME}">
		<div class="{PARENT_TPL_NAME ? PARENT_TPL_NAME + '__title' : ''} {TPL_NAME}__title">
			{data.title}
		</div>
		
		<div class="{PARENT_TPL_NAME ? PARENT_TPL_NAME + '__text' : ''} {TPL_NAME}__text">
			{value}
		</div>
	</div>
{end}

{template me(data, value = 0) extends about}
{end}


Замечания:
Пример у меня выглядит немного неуклюже, т.к. для нормального BEM подхода у меня написана либа, работающая вместе с шаблонизатором. Т.е. сам шаблонизатор изначально не привязан к конкретной технологии, но его гибкость позволяет легко написать любой над-сахар.

kobezzza 28.06.2013 12:06

Цитата:

Сообщение от monolithed (Сообщение 258910)
Чем shell не угодил? ;)

Почему не угодил?) Вопрос же был про пых, а не про шелл:)


Часовой пояс GMT +3, время: 05:28.