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

monolithed 28.06.2013 13:08

Цитата:

Сообщение от kobezzza
Вопрос же был про пых, а не про шелл

Хм. действительно.

Цитата:

Сообщение от kobezzza
Похоже на BEMHTML от Яндекса чем-то

Ага похоже, только гибче

Цитата:

Сообщение от kobezzza
div class="{PARENT_TPL_NAME ? PARENT_TPL_NAME + '__title' : ''} {TPL_NAME}__title"

А теперь представь что у тебя на сайте 100 тем (пример любой почтовой службы) и некоторые стили пересекаются.

В моем предствлении это будет так:
@set theme_1, theme_2, theme_3 < theme (data) {
    &.title: data.title
}

kobezzza 28.06.2013 13:39

Цитата:

Сообщение от monolithed (Сообщение 259006)
А теперь представь что у тебя на сайте 100 тем (пример любой почтовой службы) и некоторые стили пересекаются.

В моем предствлении это будет так:
@set theme_1, theme_2, theme_3 < theme (data) {
    &.title: data.title
}

Ну я же говорю, что у мя есть специальная прослоечка, которая делает нормальную реализацию БЭМ:) Только я не мешаю классы в html, а делаю @extend в Stylus, т.е.

<div class="b-me"> ... </div>


.b-me {
  @extend .b-about;
}


Т.е. у мя тоже всё гуд :) Единственное принципиальное отличие твоего подхода от моего, что ты полностью абстрагируешься от html, заменяя сущность тега, на сущность элемента, а у меня абстракция на уровне блоков, т.е. структура блока всё равно описывается старым добрым HTML:

{setBEM b-button, tag: 'span'}
{template bButton() extends iBlock}
	<button class="{this.blockName}__btn">
		...
	</button>
{end}


/// Пример вызова:
{bem b-button, name: '...', ...}Текст кнопки{end}


Но кстати, если у меня меняется именно тема, то я создаю не дочерний блок, а применяю модификатор: b-button_theme_dark и т.д.

monolithed 28.06.2013 14:55

Цитата:

Сообщение от kobezzza
Но кстати, если у меня меняется именно тема, то я создаю не дочерний блок, а применяю модификатор: b-button_theme_dark и т.д.

Согласен, мой пример не корректен )

kobezzza 05.07.2013 09:47

Небольшой апдейт: в скрипт трансляции добавлен сборщик файлов Jossy, т.е. если вы компилите шаблоны с помощью консольной команды snakeskin или с помощью фаел вотчера шторма, то вы можете использовать директивы вроде
//#include
для конкатенации файлов - это может быть очень удобным при разбиении шаблонов на разные файлы.

monolithed 06.07.2013 10:37

У меня тоже есть подобный препроцессор. Правда пока нельзя писать инструкции в виде комментариев )

А чем грант не подошел?

kobezzza 06.07.2013 11:13

Цитата:

Сообщение от monolithed (Сообщение 260514)
А чем грант не подошел?

Хз, я даже не пробовал, т.к. меня всем устраивает этот, да и простой как топор, юзаю его уже давно :)

ЗЫ: понравилась твоя либа для тестирования :)

monolithed 06.07.2013 11:39

Цитата:

Сообщение от kobezzza
ЗЫ: понравилась твоя либа для тестирования

У меня есть планы ее (пере|до)писать, есть некоторые баги + хочу сделать веб-интерфейс )

kobezzza 06.07.2013 11:45

Цитата:

Сообщение от monolithed (Сообщение 260518)
У меня есть планы ее (пере|до)писать, есть некоторые баги + хочу сделать веб-интерфейс )

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

monolithed 06.07.2013 11:52

Цитата:

Сообщение от kobezzza
Было бы оч круто реализовать прозрачную поддержку браузерной модели для тестирования в консольке, а ля phantomjs

Отладчик это все-таки отдельный иструмент

nerv_ 28.11.2013 15:59

kobezzza, у меня возник глупый вопрос: как ты навешиваешь обработчики событий для шаблонизируемых элементов? Через делегирование?

Хочется максимально простого и понятного кода. Допустим, когда я использую ангуляр, я пишу так:
<div ng-repeat="item in array"> <!-- повторить див столько раз, сколько элементов в массие -->
    <div ng-click="controller.click(item)"></div> <!-- навесить обработчик клика на каждый элемент -->
</div>

// упрощенный js
var controller = {
    click: function(item) {
        // item - элемент модели, по кот. кликнули
    }
};

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

kobezzza 28.11.2013 16:47

Цитата:

Сообщение от nerv_ (Сообщение 283310)
kobezzza, у меня возник глупый вопрос: как ты навешиваешь обработчики событий для шаблонизируемых элементов? Через делегирование?

Хочется максимально простого и понятного кода. Допустим, когда я использую ангуляр, я пишу так:
<div ng-repeat="item in array"> <!-- повторить див столько раз, сколько элементов в массие -->
    <div ng-click="controller.click(item)"></div> <!-- навесить обработчик клика на каждый элемент -->
</div>

// упрощенный js
var controller = {
    click: function(item) {
        // item - элемент модели, по кот. кликнули
    }
};

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

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

{template bButton.prototype.tpl()}
    <div class="{this|el 'cont'|elMod 'focus', 'true'}">
    </div>
{end}


Тут фильтры el и elMod и т.д. являются часть моего фреймворка который реализует паттерн БЭМ, т.е. это отдельная хреновина не имеющая отношения к шаблонизатору.

Сам Snakeskin - это просто транслятор и микролиба (фильтры + итераторы) и ничего больше.

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

{template page()}
    {block scripts}
        <script src="1"></script>
        <script src="2"></script>
    {end}
{end}

{template page2() extends page}
    {block scripts}
        {super} /// будет заменено на block scripts из page
        <script src="3"></script>
    {end}
{end}


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

{template page()}
    {proto scripts}
        <script src="1"></script>
        <script src="2"></script>
    {end}
    {block scripts}
        {apply scripts}
    {end}
{end}

{template page2() extends page}
    {proto page2_scripts}
        <script src="3"></script>
    {end}
    {block scripts}
        {apply scripts}
        {apply page2_scripts}
    {end}
{end}

nerv_ 28.11.2013 17:34

Цитата:

Сообщение от kobezzza
Сам шаблонизатор не знает ни про какие событие и прочее, но необходимую логику я задаю через вызовы фильтров или функций внутри шаблона

Цитата:

Сообщение от kobezzza
Сам Snakeskin - это просто транслятор и микролиба (фильтры + итераторы) и ничего больше.

я это понял, но поскольку у меня нет
Цитата:

Сообщение от kobezzza
фильтры el и elMod и т.д. являются часть моего фреймворка который реализует паттерн БЭМ

думаю, как мне лучше поступить :) И пока мой выбор склоняется в пользу DOM Level 0 - через атрибуты
<div onclick="fn(this)"></div>

kobezzza 28.11.2013 18:56

Цитата:

Сообщение от nerv_ (Сообщение 283339)
я это понял, но поскольку у меня нет

думаю, как мне лучше поступить :) И пока мой выбор склоняется в пользу DOM Level 0 - через атрибуты
<div onclick="fn(this)"></div>

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

nerv_ 28.11.2013 21:41

Цитата:

Сообщение от kobezzza
Как частное решение может подойти, но много подводных камней вроде не возможности установить таким образом событие на погружение и т.д.

Вот поэтому я и пытаюсь у тебя выпытать как лучше поступить, но пока не получается :)

kobezzza 28.11.2013 21:50

Цитата:

Сообщение от nerv_ (Сообщение 283381)
Вот поэтому я и пытаюсь у тебя выпытать как лучше поступить, но пока не получается :)

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

Шаблон же это простая яваскриптовая функция, которая выплёвывает текст, который затем в innerHTML пихается, т.е. можно делегировать как угодно :)

У меня "свои" обработчики пишутся не в шаблоне, а в коде блока. А обработчики для связи 2-х разных блоков в шаблоне как декларативные схемы.

PS: а если тебе нужен дата-биндинг почему бы не взять один из уже имеющихся популярных фреймворков, или у тебя спортивный интерес/узкозаточенная задача ?

nerv_ 28.11.2013 21:56

kobezzza, спасибо за ответы и терпение :) Форум, как обычно, не плюсует.

kobezzza 28.11.2013 21:58

Цитата:

Сообщение от nerv_ (Сообщение 283385)
kobezzza, спасибо за ответы и терпение :) Форум, как обычно, не плюсует.

Нез, мне не сложно:)

nerv_ 30.11.2013 00:00

А это должно работать? http://jsfiddle.net/NAPWB/5/

kobezzza 30.11.2013 10:13

Цитата:

Сообщение от nerv_ (Сообщение 283620)
А это должно работать? http://jsfiddle.net/NAPWB/5/

Не:) Вложенные шаблоны не допускаются, тебе надо было сделать что-то вроде:

{template foo.tpl(name)}
    <h1 onclick="bar.click(this)">Hello {name}!</h1>
    {call this.header.tpl(name, 'ещё параметр')}
{/template}

/// Можно смело использовать неймспейсы любой длины, т.к. Snakeskin создаст их если что
{template foo.header.tpl(name, header)}
     <h2>{header}</h2>
     <h3>{name}</h3>
{/template}


НО

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

{template base(name)}
    {proto foo}
         121
    {/proto}

    {apply foo}
    {apply foo}
{/template}


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

{proto foo}
      {apply foo}
{/proto}


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

http://habrahabr.ru/post/168093/ здесь довольно исчерпывающее описание прототипов, хотя сама статья уже местами устарела, т.к. писалась для версии 1 почти год назад, а ща уже 2.4

nerv_ 30.11.2013 16:07

Цитата:

Сообщение от kobezzza
Вложенные шаблоны не допускаются

я так и понял :) За пример спасибо. Мне как раз нужно включение шаблонов друг в друга.

kobezzza 30.11.2013 16:15

На самом деле, для вызова любой функции (а шаблон - это простая функция) можно использовать простой вывод, аля:
{this.header.tpl(name, 'ещё параметр')}


Но дело в том, что на все такие выводы по умолчанию ставится фильтр html, который экранирует всякие вредные сущности:)

По сути
{this.header.tpl(name, 'ещё параметр')|!html}

и
{call this.header.tpl(name, 'ещё параметр')}


эквивалентны, т.к. фильтр !html отменяет действие html, но с call как то получше выглядит

nerv_ 15.12.2013 13:54

Оказывается, так нельзя:
<script type="text/x-snakeskin-template" id="templates">
    <!-- msg -->
    {template app.templates.test(data)}
        <div></div>
    {/template}
</script>

на комменты ругается, если я правильно понял

kobezzza 15.12.2013 14:18

Цитата:

Сообщение от nerv_ (Сообщение 286698)
Оказывается, так нельзя:
<script type="text/x-snakeskin-template" id="templates">
    <!-- msg -->
    {template app.templates.test(data)}
        <div></div>
    {/template}
</script>

на комменты ругается, если я правильно понял

Вне декларации шаблона можно юзать лишь некоторые директивы: cut, save, объявление супер-глобальный переменных и комментарии snakeskin (/* ... */ и ///), т.е.

<script type="text/x-snakeskin-template" id="templates">
    /*
     * Мой супер шаблон
     */
    {template app.templates.test(data)}
        <div></div>
    {/template}
</script>


Однако в след версии я планирую добавить возможность комментов, которые не вырезаются парсером, а вставляются в JS, для того чтобы делать анотации для GCC.

А зачем тебе понадобилось вне шаблона что-то делать и как ты это планировал потом использовать?

nerv_ 15.12.2013 14:31

Цитата:

Сообщение от kobezzza
А зачем тебе понадобилось вне шаблона что-то делать и как ты это планировал потом использовать?

Планирую внутри одного
<script type="text/x-snakeskin-template" id="templates">
   ...
</script>

использовать много шаблонов. Хотел добавить комментарии к каждому из них. Воспользуюсь таким синтаксисом:
Цитата:

Сообщение от kobezzza (Сообщение 286705)
<script type="text/x-snakeskin-template" id="templates">
    /*
     * Мой супер шаблон
     */
    {template app.templates.test(data)}
        <div></div>
    {/template}
</script>

спасибо :) Жаль, только, что IDE его не подсвечивает, в отличии от html комментариев.

kobezzza 15.12.2013 14:35

Цитата:

Сообщение от nerv_ (Сообщение 286709)
Планирую внутри одного
<script type="text/x-snakeskin-template" id="templates">
   ...
</script>

использовать много шаблонов. Хотел добавить комментарии к каждому из них. Воспользуюсь таким синтаксисом:

спасибо :) Жаль, только, что IDE его не подсвечивает, в отличии от html комментариев.

Лучше создавай отдельные файлики, компиль (или настрой автокомпиляцию с файл вотчером - это очень просто) и подключай как простые скрипты, но дело твоё:)
http://screencast.com/t/iU7AgM6jvjaj

***

А по поводу подсветки, в WebStorm можно создать новый формат данных и задать ему подсветку, я так и сделал (но тут надо выносить шаблоны в отдельный файлики).

ЗЫ: Если очень нужно, я могу добавит в парсер лексему XML комментариев, как комментарий ВНЕ декларации шаблона, это будет не сложно.

nerv_ 15.12.2013 14:59

Цитата:

Сообщение от kobezzza
Лучше создавай отдельные файлики, компиль (или настрой автокомпиляцию с файл вотчером - это очень просто) и подключай как простые скрипты

Так и планировал, но пока в процессе разработки все лежит в куче, дабы быстро править. Компилит в браузере.

За видео спасибо :)

Цитата:

Сообщение от kobezzza
или настрой автокомпиляцию с файл вотчером - это очень просто

можно ссылку?

Цитата:

Сообщение от kobezzza
А по поводу подсветки, в WebStorm можно создать новый формат данных и задать ему подсветку, я так и сделал (но тут надо выносить шаблоны в отдельный файлики).

не знал

Цитата:

Сообщение от kobezzza
ЗЫ: Если очень нужно, я могу добавит в парсер лексему XML комментариев, как комментарий ВНЕ декларации шаблона, это будет не сложно.

обойдусь )

kobezzza 15.12.2013 15:15

Цитата:

Сообщение от nerv_ (Сообщение 286724)
можно ссылку?

Ну разумеется если ты юзаешь вебшторм. А так:

1) npm i -g snakeskin
2) Затем создаёшь новый тип данных в шторме (FileTypes)
3) Потом создаёшь новый вотчер (File Watchers) и настраиваешь его

У меня параметры такие:
Program: C:\Users\kobez_000\AppData\Roaming\npm\snakeskin.c md
Arguments: -s $FileName$ -o $FileNameWithoutExtension$.ss.js
Working Directory: $FileDir$
Output Path: $FileNameWithoutExtension$.ss.js

Если компилишь шаблоны под ноду, то также нужно поставить флаг -n

PS: Вместе со след версией выпущу плагин для grunt

nerv_ 18.12.2013 21:33

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

kobezzza 22.12.2013 21:15

Сегодня потратил день, на сортировку скопившихся "хотелок" от новой версии Snakeskin и утвердил следующее:

1) Директива
{super}
- для безопасной подстановки тела родительского блока или прототипа в указанное место в дочернем.

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

{template foo(param)}
	{proto icon(%iconName)}
		{param} - {%iconName}
	{end}
	
	{apply icon('foo')}
{end}


Разумеется, старый синтаксис прототипов (без указания параметров) останется рабочим.

3) Поддержка рекурсий в прототипах. Хотя прототип напоминает простые функции JS, но на самом деле это не так, поэтому использование рекурсии изначально было запрещено, ввиду некорректной работы транслятора (он уходил в бесконечный цикл), но любую рекурсию можно представить в виде простого цикла, собственно что я и планирую сделать для рекурсивных прототипов.

4) Директива для конструкции switch-case-default
5) Директивы {return} {break} и {continue} для прерывания в теле директив циклов и прерывания общего шаблона (return)

6) Директива-хэлпер для безопасной работы с атрибутами узлов:

<input {attr 'type', 'text'} />


7) Декларация прототипов вне тела шаблона:

/// Прототип getIcon добавится в конец шаблона foo
{proto foo->getIcon}
      ...
{end}


8) Поддержка JSDoc комментариев: комментарии вида /** ... */ не будут вырезаться из шаблона и будут вставлены в конечный JS, чтобы можно было использовать их при дальнейшем сжатии с помощью GCC.

В остальном будут исправления ошибок и различные доработки.
Завтра приступаю к реализации.

nerv_ 26.12.2013 00:49

Здорово, но большинство опций я вряд ли буду использовать. Это уже для продвинутых "юзеров" :)

kobezzza 26.12.2013 11:31

Цитата:

Сообщение от nerv_ (Сообщение 289305)
Здорово, но большинство опций я вряд ли буду использовать. Это уже для продвинутых "юзеров" :)

Ну в первую очередь это нужно мне:)

monolithed 27.12.2013 00:59

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

Кстати вот очень клевая штука:
http://www.ractivejs.org/

kobezzza 07.01.2014 18:31

Фух, почти закончил работу над новой версией, вышло дольше чем думал. На этой недели закончу, но уже предлагаю поиграться с бетой и заодно потестить : http://jsfiddle.net/NAPWB/6/.

С функциональной стороны сделано всё, что хотел, и даже больше, однако ещё нужно написать новые тесты, обновить доку и т.д.

Ну а теперь по порядку. Изначально данный апдейт планировался как эволюционное развитие ветки 2.x, однако в ходе разработки, стало ясно, что необходимы некоторые принципиальные изменения, которые повлекут за собой несовместимость с предыдущей версией, поэтому новая версия выйдет как 3.0.0.

Что изменилось по сравнению с 2.x:

1) Реализована блочная область видимости переменных вместо единой шаблонной, т.е.

{template foo()}
    {if 1}
        {var a = 1}
        {a} /// 1
    {/}

    {a} /// error, a is not defined
{/}


Отмечу, что данное нововведение распространяется именно на переменные, т.е. константы работают также, как и раньше.

2) Переосмыслена и переделана работа с пробельными символами: теперь любой пробельный символ (будь то табуляция или переход строки) трактуются как пробел, однако смежные пробельные символы схлопываются в один, т.е.

{template foo()}
/// перевод строки даст пробел
<div
class="foo">
{/}


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

{template foo()}
   Привет{&}                 Мир! /// получится ПриветМир!
{/}


3) Директивы cut и save были убраны, а их функционал частично заменила новая директива placeholder. Эта директива имеет одинаковый синтаксис с директивой template, однако, в отличии от template, placeholder существует только на этапе трансляции, т.е.

{placeholder foo()}
   foobar
{/}


foo(); // error


Директива может участвовать в цепи наследований также, как и template.

4) Добавлен новый возможный аргумент для директив forEach и forIn (forIn отличается от forEach тем, что всегда итерирует объект, как for (key in data), причём без проверки на hasOwnProperty). Теперь порядок аргументов для forEach такой:

Для массивов:
*) Ссылка на элемент массива;
*) Индекс массива;
*) Ссылка на итерируемый массив;
*) Является ли первым;
*) Является ли последним;
*) Длина массива.

Для объектов:
*) Ссылка на свойство;
*) Ключ свойства;
*) Ссылка на итерируемый объект;
*) Номер итерации;
*) Является ли первым;
*) Является ли последним;
*) Длина объекта.

Для forIn аргументы такие же, как и у forEach для объектов. Кстати, теперь директивы forEach и forIn разворачиваются в циклы на этапе трансляции, что позволило увеличить скорость скомпилированных шаблонов, а также возможность использования новых директив break и continue.

5) Для директивы data изменено сокращение, теперь это =, т.е.
{template foo()}
   {= foo, bar}
{/}


Старое сокращение {{}} теперь используется новой директивой decl, которая вставляет текст, так как он был написан вместе со скобками директивы, т.е.:
{template foo()}
   {{foo}} /// даст {{foo}}
{/}


Также, как и в data, в decl можно прокидывать переменные из шаблона, с помощью синтаксиса ${}. Новая директива decl создана для удобного использования библиотек, которые осуществляют data binding (вроде http://www.ractivejs.org/).

6)
Костыль для console был удалён, теперь нужно использовать директиву void
{template foo()}
   {void console.log(1)}
   /// или так
   {?console.log(1)}
{/}



На этом ломающие изменения заканчиваются. Основные нововведения:


1)
Добавлена директива super, которая осуществляет вставку тела родительского блока или прототипа:

{template base()}
   <head>
       {block scripts}
           <script src="../1.js"></script>
       {/}
   </head/>
{/}

{template child() extends base}
   {block scripts}
       {super}
       <script src="../2.js"></script>
   {/}
{/}


2) Прототипы теперь поддерживают параметры и рекурсию, а также новую директиву return:
{template foo()}
   {proto bar(i)}
      {i}

      {if i === 2}
           {return}
      {/}

      {if i}
          {apply bar(--i)}
      {/}
   {/}

   {apply bar(4)} /// 4 3 2
{/}


3) Прототипы теперь можно выносить за пределы шаблона, перед декларацией
{proto foo->bar}
    1
{/}

{template foo()}
   {apply bar}
{/}


4)
Добавлена поддержка jsDoc
/**
 * Данный комментарий будет в скомпилированном JS
 * @return {string}
 */
{template foo()}
   1
{/}


5) Директива var теперь имеет сокращение : и поддерживает множественную декларацию
{template foo()}
   {:a = 1}
   {var b = 2, e = 3}
{/}


6) Новые директивы switch case (имеет сокращение >) default

{template foo()}
   {switch 1}
      {case 1} foo {/}
      {> 2} foo2 {/}
      {default} foo3 {/}
   {/}
{/}


7) Новые директивы try catch finally

{template foo()}
   {try}
       {void dddd()}
   {catch err}
        {err}
   {finally}
        bar!!!
   {/}
{/}


8) Новые директивы break и continue. Могут использоваться внутри forEach, forIn, for, while, do, repeat.
9) Для цикла repeat-until добавлен псевдоним do-while
10) Новая директива return. Может использоваться внутри прототипов или шаблона (в случае шаблона может принимать значение)

11) Новая директива attr для удобного задания атрибутов узлам в xml разметке:
{template foo()}
   <div {attr 'class', 'foo'} {attr -'bind', 'bar'}></div> /// class="foo" data-bind="bar"
{/}


12) Частично переписано АПИ добавления директив, в релизе будет иметь документацию, пример:

Snakeskin.addDirective(
	'if',

	{
		placement: 'template',
		notEmpty: true
	},

	function (command) {
		this.startDir();
		if (this.isSimpleOutput()) {
			this.save('if (' + this.prepareOutput(command, true) + ') {');
		}
	}
);

Snakeskin.addDirective(
	'else',

	{
		placement: 'template'
	},

	function () {
		if (this.structure.name !== 'if') {
			throw this.error('Directive "' + this.name + '" can only be used with a "if"');
		}

		if (this.isSimpleOutput()) {
			this.save('} else {');
		}
	}
);


13) Увеличена скорость работы транслятора и исправлено множество ошибок
14) Сильно увеличена скорость работы в "живом" режиме в браузере
15) Очень сильно доработана обработка ошибок
16) 100% code review и рефакторинг + теперь исходный код переписан на ECMAScript 6 :)

Вроде всё :)

kobezzza 07.01.2014 22:15

Ради интереса сравнил скорость рендеринга с другими шаблонными движками... и каково было моё удивление, что Snakeskin занял первое место, обойдя даже самые примитивные шаблонки http://jsperf.com/templates/2 я почему то был уверен, что результат должен быть другим

monolithed 07.01.2014 22:41

Цитата:

Сообщение от kobezzza
Реализована блочная область видимости переменных вместо единой шаблонной, т.е.

Хм. разве не для этого придумали let?
Цитата:

Сообщение от kobezzza
Также введена новая директива &, которая декларирует, что все пробельные символы после этой директивы до любого не пробельного символа будут вырезаться, т.е.

Очень сомнительная фича ;)

Цитата:

Сообщение от kobezzza
6) Костыль для console был удалён, теперь нужно использовать директиву void

А почему просто не дать писать console.log?
Цитата:

Сообщение от kobezzza
Директива var теперь имеет сокращение : и поддерживает множественную декларацию

Цитата:

Сообщение от kobezzza
8) Новые директивы break и continue. Могут использоваться внутри forEach

Цитата:

Сообщение от kobezzza
9) Для цикла repeat-until добавлен псевдоним do-while

Цитата:

Сообщение от kobezzza
Новые директивы switch case (имеет сокращение >) default

Цитата:

Сообщение от kobezzza
7) Новые директивы try catch finally

Почему просто не писать так:

{template}
<script>
  ....
</script>
{/template}
?

Зачем усложнять то?

Цитата:

Сообщение от kobezzza
Новые директивы switch case (имеет сокращение >) default

Не знаю насчет такого синтаксиса, но во многих нормальных языках типа Haskell можно писать так:

switch text
      | "one"        => 1
      | "two"        => 2
      |              => 0


Ну или как LiveScript:

switch text
      case "one"  
            then 1
      case "two" 
             then 2
      case "three", "four"  
             then "3-4"
      default  
             then 0

monolithed 07.01.2014 22:45

Цитата:

Сообщение от kobezzza
самые примитивные шаблонк

HandlebarsJS забыл :)

Цитата:

Сообщение от kobezzza
необходимы некоторые принципиальные изменения

Планируешь будет data-binding?
Просто в современной разботке single-page приложений перерисовывать весть блок не очень гуд, особенно если в этом блоке сотни и тысячи элементов.

kobezzza 07.01.2014 22:49

Цитата:

Сообщение от monolithed (Сообщение 290926)
HandlebarsJS забыл :)

Он чёто не завёлся, потом сделаю более полный и нормальный тест, сёня уже сил нет.

Цитата:

Сообщение от monolithed (Сообщение 290926)
Планируешь будет data-binding?

Нет, Snakeskin - это шаблонный движок а не блендер из ХЗ чего, я просто сделал для него удобную синтаксическую основу. Т.е. дата-биндинг должен делаться отдельной либой.

kobezzza 07.01.2014 22:54

Цитата:

Сообщение от monolithed (Сообщение 290924)
Хм. разве не для этого придумали let?

Я бы с радостью юзал let-ы если бы они везде работали.

Цитата:

Сообщение от monolithed (Сообщение 290924)
Очень сомнительная фича ;)

/// Срежет не нужный пробел
<p>{&}
   1
   2
</p>


Цитата:

Сообщение от monolithed (Сообщение 290924)
А почему просто не дать писать console.log?

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


Цитата:

Сообщение от monolithed (Сообщение 290924)
Почему просто не писать так:

{template}
<script>
  ....
</script>
{/template}
?

Зачем усложнять то?

Тут можно долго спорить.


Цитата:

Сообщение от monolithed (Сообщение 290924)
Не знаю насчет такого синтаксиса, но во многих нормальных языках типа Haskell можно писать так:

switch text
      | "one"        => 1
      | "two"        => 2
      |                 => 0


Ну или как LiveScript:

switch text
      case "one"  
            then 1
      case "two" 
             then 2
      case "three", "four"  
             then "3-4"
      default  
             then 0

Ну у меня не язык программирования, а препроцессор шаблонов.

monolithed 07.01.2014 23:04

Цитата:

Сообщение от kobezzza
Ну у меня не язык программирования, а препроцессор шаблонов.

Тем не менее, ты вводишь новый синтаксис :)

Если уж вводить синтаксический сахар, то лично мне кажется нужно отталкиваться от существующих решений.
Вот пример из того же Haskell:
f x = 
    case x of
        0 -> "one"
        1 -> "two"
        _ -> 0 - x


Цитата:

Сообщение от kobezzza
Я бы с радостью юзал let-ы еслибы они везде работали.

А так ты вносишь неясность в голову JS-программистов.

Цитата:

Сообщение от kobezzza
/// Срежет не нужный пробел

Ни разу не требовалось.

Цитата:

Сообщение от kobezzza
Тут можно долго спорить

А в чем спор будет заключаться?
Вот к примеру в fest нет ничего лишнего, только основные инструкции и возможность писать произвольный JS код:

<fest:script>
var obj = {"foo": "bar"};
</fest:script>

<fest:each iterate="obj" index="i">
     <fest:value>obj[i]</fest:value>
</fest:each>


Пока я вижу в этом только плюсы, т.к. не нужно придумывать новые инструкции и усложнять парсинг.

Цитата:

Сообщение от kobezzza
Нет, Snakeskin - это шаблонный движок а не блендер из ХЗ чего, я просто сделал для него удобную синтаксическую основу.

Ну как сказать,
Цитата:

Сообщение от monolithed
Просто в современной разботке single-page приложений перерисовывать весть блок не очень гуд, особенно если в этом блоке сотни и тысячи элементов.


kobezzza 07.01.2014 23:15

Цитата:

Сообщение от monolithed (Сообщение 290933)
Тем не менее, ты вводишь новый синтаксис :)

За основу я взял синтаксис из Google Closure Templates и Django Templates.

Цитата:

Сообщение от monolithed (Сообщение 290933)
Если уж вводить синтаксический сахар, то лично мне кажется нужно отталкиваться от существующих решений.
Вот пример из того же Haskell:
f x = 
    case x of
        0 -> "one"
        1 -> "two"
        _ -> 0 - x

Я отталкиваюсь от грамматики, которая была изначально задана.

Цитата:

Сообщение от monolithed (Сообщение 290933)
А так ты вносишь неясность в голову JS-программистов.

Не думаю.

Цитата:

Сообщение от monolithed (Сообщение 290933)
Ни разу не требовалось.

А мне требовалось, а т.к. пишу я для себя в первую очередь - вот и добавил.

Цитата:

Сообщение от monolithed (Сообщение 290933)
А в чем спор будет заключаться?
Вот к примеру в fest нет ничего лишнего, только основные инструкции и возможность писать произвольный JS код:

Мне нравится синтаксис Closure Templates, Dust и т.д.

Цитата:

Сообщение от monolithed (Сообщение 290933)
Просто в современной разботке single-page приложений перерисовывать весть блок не очень гуд, особенно если в этом блоке сотни и тысячи элементов.

Ещё раз: дата-биндинг - это задача отдельный либы, которая использует шаблонизатор.


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