Цитата:
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, время: 22:54. |