Цитата:
Jade - это LESS, т.е. примитивная шаблонка SS - это Stylus, т.е. полноценный язык для генерации шаблонов Какое то подробное сравнение - тема отдельной статьи, которую я наверное и напишу, но сейчас у меня другие приоритеты. Цитата:
contents.ss - namespace [%fileName%] - include 'posts/*' - template main() - forEach posts => post /// A тут уже делаем всё, что нам нужно |
...и кстати, не холивара ради, а потому что коль уж здесь любители шаблонов собрались...
> вдохновился от Django Templates для Python У меня есть четкое мнение (это всего лишь одно из всех мнений), что Django Templates - это полная хрень. С одной стороны, он делает из пользователя идиота. Не позволяет даже объявить переменную в шаблоне например, в общем там куча ограничений. Типа это философия такая - типа верстала не должен иметь возможности накосячить. Типа верстала не сильно шарит в шаблонном движке. Но эта философия уже давно протухла и воняет. Современный верстала должен не просто шарить в шаблонном движке, а обязан быть гуру шаблонного движка, иначе - *вон из професси*. При всем при этом если нужен шаг в сторону - лезь либо в templatetags, либо во view. А верстала туда лазить не должен! Но самое мать его веселое - это доступ к ORM. {% for post in posts %} <h1>{{ post.name </h1> <p>{{ post.date }}</p> {% endfor %} пока все хорошо. А теперь нужно добавить user.reg_date {% for post in posts %} <h1>{{ post.name </h1> <p>{{ post.date }}</p> <span>{{ post.user.reg_date }}</span> {% endfor %} Опа, и вот у нас уже 50 лишних запросов к базе. Это сделал верстала. (И это вообще лайтовый пример.) А должно быть вот как: (Верстала): программер, мне в постах еще юзеры теперь нужны (Программер): понял, добавлю (и уже там select_related и все дела) Конечно проблема с доступом к ORM - это скорее проблема уровнем повыше, чем особенность шаблонодвижка, но наглядно демонстрирует всю ущербность подхода. Сейчас Django нативно поддерживает Jinja2, и оно лучше. Jade было бы еще лучше (к сожалению с сабжем пока не знаком), но увы. ...Это все просто мысли. 2all: Как, согласны? |
Цитата:
|
> Если коротко - всем
Браво :D *Скромность украшает мужчину, но настоящий мужчина не нуждается в приукрашивании!* > Какое то подробное сравнение - тема отдельной статьи, которую я наверное и напишу, но сейчас у меня другие приоритеты. Интересно, буду ждать. > contents.ss А вот это уже интересно. Реально куль. Но проблема в другом - как данные ИЗ_ШАБЛОНА вытащить В_УПРАВЛЯЮЩИЙ_СКРИПТ? Так как в примере - проблема сильно ближе к решению. А можно на выходе JSON получить? SS - это вообще чисто html-движок (как Jade), или движок общего назначения (как Django Templates)? |
> То, что я вдохновлялся больше 3-х лет назад чем то, не значит, что оно сейчас так и т.д.
ну я это не с целью наезда, а скорее обсудить проблему. Типа > потому что коль уж здесь любители шаблонов собрались... |
Цитата:
Цитата:
Допустим у нас есть папка posts, там мы будем хранить наши посты, и для группировки засуним их в один родительский немспейс posts. posts/ posts/foo.ss - namespace posts[%fileName%] /// тоже самое, что и написать явно posts.foo /// Главный шаблон назовём main, он содержит основной пост - template main() < .hello Hello world! /// А это шаблон с превью статьи - template preview() Hello! Теперь создадим файл с содержанием, который будет выводить тексты превью contents.ss - namespace contents - include 'posts/*' /// Подключаем по маске все файлы из папки posts - template main() /// Т.к. все посты у нас лежат в неймспейсе posts, то просто делаем обход этого объекта - forEach posts => post += post.preview() /// Вызываем шаблон превею и выводим его текст Цитата:
Цитата:
- namespace myMd /// Здесь будем использовать вариант синтаксиса без управляющих пробелов, для более удобной генерации /// И также включим режим "терпимости к пробелам", чтобы сохранить структуру пробелов, т.к. мы генерируем md {template index(data) @= tolerateWhitespaces true} # Hello world {forEach data => el} * {el} {/} {/template} |
> В SS нет такой проблемы, потому что здесь иная философия.
у меня конкретный юзкейс > += post.preview() /// Вызываем шаблон превею и выводим его текст Мне оно так не надо, мне надо конкретно - 1) галпом разобрать шаблоны постов, получить структуриированные данные из них 2) засунуть все как мне надо в json, сжать его и положить куда надо в папке билда Между п. 1 и 2 должен стоять контроллер, которому вообще по барабану, какой там шаблонодвижок. Он должен получить данные из п. 1 и с ними уже делать что угодно. |
Цитата:
- namespace contents - include 'posts/*' - template main() - var contents = [] - forEach posts => post ? contents.push({preview: post.preview(), content: post.main()}) /// Т.к. у нас результатом шаблона будет JSON, то убираем html экранирование {contents|json|!html} |
> В Jade шаблоном является сам файл, а в SS для декларации шаблонов используется специальная директива template (по духу близкая к class в JS), т.е. в одном файле может быть много шаблонов, у шаблонов могут быть методы, шаблоны могут наследоваться от других шаблонов и т.д. В этом главное отличии SS от большинства других шаблонов
А вот это богато, базара нет. То есть мы получаем дополнительную степень свободы, потому что мы больше не привязаны к семантике файловой системы, и можем строить собственную семантику отношений шаблонов, при этом используя ФС как нам удобно, так чтоли? |
Цитата:
var foo = 1; function bar(a) { return a + foo; } - var foo = 1 - template bar(a) {a + foo} Кстати результатом работы шаблонов SS может быть не только строка, а что угодно, например можно сказать СС собрать DocumentFragment из шаблона. /// Вернёт <div class="hello"></div> - template foo() < .hello /// Вернёт DocumentFragment - template bar() @= renderMode 'dom' < .hello |
> /// Т.к. у нас результатом шаблона будет JSON
Вот это уже почти в цель. В целом мой конкретный юзкейс это решит неплохо, пусть и совсем не так как я хотел. Если же рассматривать проблему более широко (формулировка): Можно ли передать произвольные структурированные данные из шаблона в контроллер - то ответ будет - да, можно - создай шаблон-коллектор данных, там все разбери в JSON как надо и этот JSON можешь уже юзать в контроллере. Так? Я правильно все понял? |
Цитата:
Цитата:
|
> /// Вернёт <div class="hello"></div>
А что значит "вернет"? Вернет вызвавший шаблон, или в контроллер? (я так понял что первый вариант) Вообще, что возвращается в контроллер? Две сущности как обычно 1) результат компиляции (какой-то внутренний пофигу какой формат) 2) результат конечного рендера - строка Так чтоли? |
Я же говорю, SS это язык, который транслируется в JS, как CoffeScript или TypeScript.
Непосредственным результатом работы транслятора является JS файл, грубо говоря - namespace foo - template bar() < .foo Скомпилится в if (typeof foo === undefined) { var foo = {}; } module.exports = foo; foo.bar = function bar() { return '<div class="foo"></div>'; } И дальше мы этот файл подключаем уже в своём JS и работаем с ним как с JS функциями. А вот сами функции в зависимости режима компиляции могут возвращать разные результаты. |
http://codepen.io/kobezzza/pen/zrJNXx
Вот тут для понимания важны 2 строчки: // Компилируем шаблоны Snakeskin.compile(document.getElementById('templates')); // Вызываем наш скомпилированный шаблон, как простую JS функцию document.getElementById('test').innerHTML = demo.helloWorld(); http://codepen.io/kobezzza/pen/GoPNZx А вот тут я продекларировал шаблон, который возвращает не строку, а DocumentFragment. |
> Да. Но разумеется можно генерить что угодно, а не только JSON.
Но на самом деле у нас вот здесь > {contents|json|!html} contents - это объект JS. И в контроллере в моем случае нужен объект JS. Но в текущей реализации понадобится этот объект перегнать в строку (JSON), а потом эту строку перегнать обратно в объект. Внутри шаблона мы вольны оперировать как угодно объектами JS и собрать что угодно из чего угодно. Вот бы это "что угодно" можно было бы в контроллер вытаскивать - это стало бы киллер-фичей, *я гарантирую это* Например: шаблон: .... connector myData ~ // do something with data ~ ~ var myVar = <get something from outer template scope>.someMethod() + something // ..etc ~ ... ~ var bar = <get something from outer template scope>.someMethod() + something // ..etc ~ myVar.foo = bar. ~ ... ~ // do something with data share bar, myVar .... я не знаю синтаксис SS, тильду (~) использовал для того чтобы ничего не делать с тем что за ней - так какие-то манипуляции с данными, которые видеть ни откуда не нужно. Если ничего делать с данными не нужно - можно сразу - share bar, myVar в контроллере: var tpl = ss('my_tpl.ss'); // не знаю как там, но суть ясна var bar = tpl.connectors.myData.bar; var myVar = tpl.connectors.myData.myVar; Коннекторы - это "обратный билет" для данных в контроллер. Конкретно мой юзкейс - я бы сдалал так: 1) Создал бы родительский шаблон для всех постов, в нем бы создал коннектор. 2) В галпфайле в процессе рендера html-файлов всех постов параллельно бы получил данные из всех коннекторов. 3) Профит, нужные данные контроллер получил, дальше как угодно, это же объекты JS. Ну как идея? |
Я думал тебе JSON нужен :)
- namespace contents - include 'posts/*' - template main() - var contents = [] - forEach posts => post ? contents.push({preview: post.preview(), content: post.main()}) /// Явно указываем return, /// чтобы результатом был исходный массив - return contents Цитата:
Цитата:
|
> codepen.io/kobezzza/pen/zrJNXx
> codepen.io/kobezzza/pen/GoPNZx Щикааарно! |
kobezzza, пара вопросов, если не сложно,
по работе с http://codepen.io/ что там нужно нажать чтоб посмотреть результат на полный экран full? и Snakeskin для ie не предназначен? |
Цитата:
Цитата:
|
> return contents
от блин, да с этого и надо было начинать. :lol: то есть var tpl = ss.compile(someGlobalVars); var всеЧтоМнеНужноИзШаблона = tpl.main(); var html = tpl.render(someLocalVars); И делов то? |
kobezzza,
спасибо |
Ну не совсем так. compile транслирует шаблоны, а если мы делаем это в браузере, то он их сразу и скомпилит.
Для использование в ноде есть более удобное АПИ + плагины для галпа, гранта и вебпака. Например, в ноде (чистый SS без плагинов) это будет выглядеть так: var ss = require('snakeskin'); ss.compileFile('myFile.ss') // Функция вернёт объект с функциями (которые были шаблонами) В браузере компиляция делается просто с помощью метода compile, как в примерах, что я кидал. |
> Ну не совсем так.
да, я не так сформулировал, надо было так var ss = require('snakeskin'); var tpl = ss.compileFile('myFile.ss', someGlobalVars); // Функция вернёт объект с функциями (которые были шаблонами) var всеЧтоМнеНужноИзШаблона = tpl.main(someLocalVars); var html = tpl.render(someLocalVars); // render - не знаю как там эта функция называется, ну в общем вроде понятно Так? |
Да, только для передачи глобальных переменных ключ vars :)
var tpl = ss.compileFile('myFile.ss', {vars: someGlobalVars}); Цитата:
|
> Да
Круто. Я в общем проникся. Вот Jade догрызу до победного, и надо будет изучить SS поближе. В проекте кстати со страшной силой надо перевести доки и трекер на английский. Эта проблема всем проблемам проблема. 0 форков - это пичалька конкретная. Рускоговорящих нодеров по пальцам перечесть. |
Цитата:
Цитата:
Цитата:
Цитата:
|
> Странный показатель, ладно ещё там лайки, хотя тоже всё это писькомерство, но форки то что показывают?)
Форки - это сколько людей активно копается в исходниках. Проект же написан на JS для JS-программистов (грубо говоря), для таких проектов как раз форки решают, а не лайки. upd: ну и еще показатель насколько вероятны pull-requests, естественно если 0 - невероятно не вероятны |
Цитата:
Цитата:
|
уж то жто делать, как душе угодно я как то сразу ещё год назад понял, лиш бы работало и некого не трогать, не суваться в редакторры любого типа. Читаю ВАС второй год пользы 0, пониммания дай бог 50%. Но интересно, может прозрею?
|
А почему, сообщения не все проходят?
|
Цитата:
*** Выпустил очередной патч - beta13. |
Выпустил beta18 с исправлением 4-х критических багов.
|
Выпустил beta23 (думаю скоро уже будет стейбл релиз), к сожалению документацию ещё не готова и наверное будет делать еще где то месяц, т.к. в этом месяце ушло слишком много времени и сил на стабилизацию релиза, тесты и т.д.
|
Цитата:
|
Цитата:
|
О, привет! Вчера как раз наткнулся на вас на гите. Долго вспоминал, где же я уже видел такое.
Вы мне помогали запустить loader. Спасибо, кстати. Писал на гите на инглише, сначала по привычке, а потом когда понял, кто авторы - может, когда будете раскручивать SS - чтобы люди не пугались русского языка :) Теперь, если разрешите, к сути. Думаю вы и без меня это знаете, но очень не хватает документации. Сейчас начинаю новый достаточно крупный проект. И система темплеитов в неимспеисе мне очень нравится. Т.е в одном файле можно описать шаблоном весь модуль. И функциями дергать нужную часть. Замечательно же! Но вот не могу ничего стоящего сделать. Все-время натыкаюсь на проблемы. Лезу в тесты, чтобы посмотреть хотя бы примеры кода. Но выручают слабо( Первый же пример. Создал тестовый темплеит import { testModule } from './template.ss'; console.log( testModule.markup({ buttonText: 'Кнопка' }), testModule.mainCode({ toggleClass: 'active' }) ); - namespace testModule - template markup(@params) < button { @buttonText } - template mainCode() # op $('.button').on('click', function() { $(this).toggleClass('activsssse'); }); Все работает. Но если темплеит mainCode будет большой, то очень неудобен отступ слева в два таба. Я пошел дальше. Обнаружил такое Темплеит можно обьявить так { template mainCode() } {/ template } Но тут возникла другая проблема. Фигурные скобки вырезает из шаблона. А вот эту вот опцию "op" я не придумал куда ставить :).. В общем, спасибо за интересный инструмент. Ждем доки. А пока что-то другое придется использовать. |
Цитата:
Цитата:
Цитата:
Цитата:
{template foo()} /// Допустим нам нужно объявить какой то JS: /// просто декларируем директиву в синтаксисе #{ ... } /// и все вложенные директивы будут работать с таким же синтаксисом #{script} var a = {a: 1, b: #{1 + 2}}; #{/} {/} Также можно использовать универсальный символ экранирования - \. Но в данном кейзе он не оч удобен. {template foo()} {script} var a = \{a: 1, b: {1 + 2}}; {/} {/} Цитата:
|
Цитата:
Цитата:
Получить через темплеит в некоторых случаях html разметку. В других JS код. К примеру вот руки просятся написать что-то типа такого - namespace testModule { template markup(@params) } <button>{ @buttonText }</button> // Обычная разметка {/ template } { template mainCode() @= tolerateWhitespaces true @= renderMode 'raw' } // отображать как есть. Правда я не понимаю, как тогда здесь ставить переменные :) var a = { 1: 2 }; {/ template } |
Цитата:
Цитата:
- namespace demo - template myButton(@params) < .button {@value} #{template myJS(foo)} var a = { foo: 'bar' bla: #{1 + 2}, baz: '#{foo ? "baz" : "bla"}' }; #{/} Цитата:
Цитата:
stringConcat - по умолчанию, строки получаются через конкатенацию; stringBuffer - также строка, но строки создаёются через класс Snakeskin.StringBuffer; dom - шаблон возвращает DocumentFragment. |
Часовой пояс GMT +3, время: 21:21. |