bem-xjst
Шаблонизатор для тех, кто ведёт веб-разработку в рамках БЭМ-методологии. В основе шаблонизатора лежат декларативные принципы из XSLT (eXtensible Stylesheet Language Transformations)
Написать шаблон
Data friendly design
Шаблонизатор позволяет формировать интерфейс на основе данных и гибко его настраивать.
transform
Итеративность
Пошаговое улучшение
timeline
Гибкость
Отзывчиваость инрефейса
tonality
Вариативность
Проверка условий
photo_size_select_small
Расширяемость
Доопределение шаблонов
Пошаговый процесс шаблонизации
Пишем шаблон на примере блока карточки пользователя, рассматривая основные возможности шаблонизатора.
1
К элементу photo добавляем тег img
+6
• 1 comment
Посмотреть изменения
John Johnson
Johnson & Johnson
http://johnson.co
add
2
К элементу photo добавляем атрибут url
+6
• 1 comment
Посмотреть изменения
John Johnson
Johnson & Johnson
http://johnson.co
add
3
Оборачиваем элемент photo в блок avatar
+7
• 1 comment
Посмотреть изменения
John Johnson
Johnson & Johnson
http://johnson.co
add
4
К элементу company добавляем ковычки
+5
• 1 comment
Посмотреть изменения
John Johnson
"Johnson & Johnson"
http://johnson.co
add
5
К элементу website миксуем блок link из библиотеки
+6
• 1 comment
Посмотреть изменения
John Johnson
"Johnson & Johnson"
add
6
Заменяем элемент add на блок add
+4
• 1 comment
Посмотреть изменения
John Johnson
"Johnson & Johnson"
7
Добавляем в еще одну ссылку
+13
• 1 comment
Посмотреть изменения
John Johnson
"Johnson & Johnson"
play_arrow
Скринкаст
Запись всего процесса верстки карточки пользователя на основе данных и Sketch файла.
view_quilt
Пример шаблона
http://bit.ly/xjst-template
code
Исходники Github
http://bem.github.io/bem-xjst
supervisor_account
Задать вопросы
bemxjst@bem.info
Манифест
Как видите, достаточну большую часть работы шаблонизатор делает  без вашего участия. Это позволяет вам больше экспериметировать при реализации интерфейса.
BEMHTML
HTML
К элементу photo добавляем тег
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad vel dolore recusandae eum quia id laudantium est officia excepturi, obcaecati eaque, quibusdam, iste fugiat quo nemo ut. Architecto, cumque, inventore.
Предыдущий шаг
block('user')( content()(function(n, ctx) { return { elem : 'photo', url: ctx.url, title: 'john-photo' } }), content()(function(n, ctx) { return [ applyNext(), { elem : 'add', content : 'add' } ] }), content()(function(n, ctx) { return [ applyNext(), { elem : 'info', content : [ { elem : 'name', content : ctx.name }, { elem : 'company', content : 'Johnson & Johnson' }, { elem : 'website', content : 'http://johnson.co', url : 'http://johnson.co' } ] } ] }) );
Текущий шаг
block('user')( content()(function(n, ctx) { return { elem : 'photo', url: ctx.url, title: 'john-photo' } }), content()(function(n, ctx) { return [ applyNext(), { elem : 'add', content : 'add' } ] }), content()(function(n, ctx) { return [ applyNext(), { elem : 'info', content : [ { elem : 'name', content : ctx.name }, { elem : 'company', content : 'Johnson & Johnson' }, { elem : 'website', content : 'http://johnson.co', url : 'http://johnson.co' } ] } ] }), elem('photo')( match(function (context, json) { return json.url; })( tag()('img') ) ) );
Предыдущий шаг
<div class="user user_type_active"> <div class="user__photo"></div> <div class="user__info"> <div class="user__name">John Johnson</div> <div class="user__company">Johnson &amp; Johnson</div> <div class="user__website">http://johnson.co</div> </div> <div class="user__add">add</div> </div>
Текущий шаг
<div class="user user_type_active"> <img class="user__photo"> <div class="user__info"> <div class="user__name">John Johnson</div> <div class="user__company">Johnson &amp; Johnson</div> <div class="user__website">http://johnson.co</div> </div> <div class="user__add">add</div> </div>
BEMHTML
HTML
К элементу photo добавляем атрибут url
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad vel dolore recusandae eum quia id laudantium est officia excepturi, obcaecati eaque, quibusdam, iste fugiat quo nemo ut. Architecto, cumque, inventore.
Предыдущий шаг
block('user')( content()(function(n, ctx) { return { elem : 'photo', url: ctx.url, title: 'john-photo' } }), content()(function(n, ctx) { return [ applyNext(), { elem : 'add', content : 'add' } ] }), content()(function(n, ctx) { return [ applyNext(), { elem : 'info', content : [ { elem : 'name', content : ctx.name }, { elem : 'company', content : 'Johnson & Johnson' }, { elem : 'website', content : 'http://johnson.co', url : 'http://johnson.co' } ] } ] }), elem('photo')( match(function (context, json) { return json.url; })( tag()('img') ) ) );
Текущий шаг
block('user')( content()(function(n, ctx) { return { elem : 'photo', url: ctx.url, title: 'john-photo' } }), content()(function(n, ctx) { return [ applyNext(), { elem : 'add', content : 'add' } ] }), content()(function(n, ctx) { return [ applyNext(), { elem : 'info', content : [ { elem : 'name', content : ctx.name }, { elem : 'company', content : 'Johnson & Johnson' }, { elem : 'website', content : 'http://johnson.co', url : 'http://johnson.co' } ] } ] }), elem('photo')( match(function (context, json) { return json.url; })( tag()('img') ) ), elem('photo')( match(function (context, json) { return json.url; })( addAttrs()((context, json) => ({ href: json.url })) ) ) );
Предыдущий шаг
<div class="user user_type_active"> <img class="user__photo"> <div class="user__info"> <div class="user__name">John Johnson</div> <div class="user__company">Johnson &amp; Johnson</div> <div class="user__website">http://johnson.co</div> </div> <div class="user__add">add</div> </div>
Текущий шаг
<div class="user user_type_active"> <img class="user__photo" href="john.png" > <div class="user__info"> <div class="user__name">John Johnson</div> <div class="user__company">Johnson &amp; Johnson</div> <div class="user__website">http://johnson.co</div> </div> <div class="user__add">add</div> </div>
BEMHTML
HTML
К элементу photo добавляем тег
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad vel dolore recusandae eum quia id laudantium est officia excepturi, obcaecati eaque, quibusdam, iste fugiat quo nemo ut. Architecto, cumque, inventore.
Предыдущий шаг
block('user')( content()(function(n, ctx) { return { elem : 'photo', url: ctx.url, title: 'john-photo' } }), content()(function(n, ctx) { return [ applyNext(), { elem : 'add', content : 'add' } ] }), content()(function(n, ctx) { return [ applyNext(), { elem : 'info', content : [ { elem : 'name', content : ctx.name }, { elem : 'company', content : 'Johnson & Johnson' }, { elem : 'website', content : 'http://johnson.co', url : 'http://johnson.co' } ] } ] }), elem('photo')( match(function (context, json) { return json.url; })( tag()('img') ) ), elem('photo')( match(function (context, json) { return json.url; })( addAttrs()((context, json) => ({ href: json.url })) ) ) );
Текущий шаг
block('user')( content()(function(n, ctx) { return { elem : 'photo', url: ctx.url, title: 'john-photo' } }), content()(function(n, ctx) { return [ applyNext(), { elem : 'add', content : 'add' } ] }), content()(function(n, ctx) { return [ applyNext(), { elem : 'info', content : [ { elem : 'name', content : ctx.name }, { elem : 'company', content : 'Johnson & Johnson' }, { elem : 'website', content : 'http://johnson.co', url : 'http://johnson.co' } ] } ] }), elem('photo')( match(function (context, json) { return json.url; })( tag()('img') ) ), elem('photo')( match(function (context, json) { return json.url; })( addAttrs()((context, json) => ({ href: json.url })) ) ), elem('photo').wrap()(function() { return { block: 'avatar', content: this.ctx } }) );
Предыдущий шаг
<div class="user user_type_active"> <img class="user__photo" href="john.png" > <div class="user__info"> <div class="user__name">John Johnson</div> <div class="user__company">Johnson &amp; Johnson</div> <div class="user__website">http://johnson.co</div> </div> <div class="user__add">add</div> </div>
Текущий шаг
<div class="user user_type_active"> <div class="avatar"> <img class="avatar__photo" href="john.png" > </div> <div class="user__info"> <div class="user__name">John Johnson</div> <div class="user__company">Johnson &amp; Johnson</div> <div class="user__website">http://johnson.co</div> </div> <div class="user__add">add</div> </div>
BEMHTML
HTML
К элементу photo добавляем тег
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad vel dolore recusandae eum quia id laudantium est officia excepturi, obcaecati eaque, quibusdam, iste fugiat quo nemo ut. Architecto, cumque, inventore.
Предыдущий шаг
block('user')( content()(function(n, ctx) { return { elem : 'photo', url: ctx.url, title: 'john-photo' } }), content()(function(n, ctx) { return [ applyNext(), { elem : 'add', content : 'add' } ] }), content()(function(n, ctx) { return [ applyNext(), { elem : 'info', content : [ { elem : 'name', content : ctx.name }, { elem : 'company', content : 'Johnson & Johnson' }, { elem : 'website', content : 'http://johnson.co', url : 'http://johnson.co' } ] } ] }), elem('photo')( match(function (context, json) { return json.url; })( tag()('img') ) ), elem('photo')( match(function (context, json) { return json.url; })( addAttrs()((context, json) => ({ href: json.url })) ) ), elem('photo').wrap()(function() { return { block: 'avatar', content: this.ctx } }) );
Текущий шаг
block('user')( content()(function(n, ctx) { return { elem : 'photo', url: ctx.url, title: 'john-photo' } }), content()(function(n, ctx) { return [ applyNext(), { elem : 'add', content : 'add' } ] }), content()(function(n, ctx) { return [ applyNext(), { elem : 'info', content : [ { elem : 'name', content : ctx.name }, { elem : 'company', content : 'Johnson & Johnson' }, { elem : 'website', content : 'http://johnson.co', url : 'http://johnson.co' } ] } ] }), elem('photo')( match(function (context, json) { return json.url; })( tag()('img') ) ), elem('photo')( match(function (context, json) { return json.url; })( addAttrs()((context, json) => ({ href: json.url })) ) ), elem('photo').wrap()(function() { return { block: 'avatar', content: this.ctx } }), elem('company')( prependContent()('«'), appendContent()('»') ) );
Предыдущий шаг
<div class="user user_type_active"> <div class="avatar"> <img class="avatar__photo" href="john.png" > </div> <div class="user__info"> <div class="user__name">John Johnson</div> <div class="user__company">Johnson &amp; Johnson</div> <div class="user__website">http://johnson.co</div> </div> <div class="user__add">add</div> </div>
Текущий шаг
<div class="user user_type_active"> <div class="avatar"> <img class="avatar__photo" href="john.png" > </div> <div class="user__info"> <div class="user__name">John Johnson</div> <div class="user__company">"Johnson &amp; Johnson"</div> <div class="user__website">http://johnson.co</div> </div> <div class="user__add">add</div> </div>
BEMHTML
HTML
К элементу photo добавляем тег
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad vel dolore recusandae eum quia id laudantium est officia excepturi, obcaecati eaque, quibusdam, iste fugiat quo nemo ut. Architecto, cumque, inventore.
Предыдущий шаг
block('user')( content()(function(n, ctx) { return { elem : 'photo', url: ctx.url, title: 'john-photo' } }), content()(function(n, ctx) { return [ applyNext(), { elem : 'add', content : 'add' } ] }), content()(function(n, ctx) { return [ applyNext(), { elem : 'info', content : [ { elem : 'name', content : ctx.name }, { elem : 'company', content : 'Johnson & Johnson' }, { elem : 'website', content : 'http://johnson.co', url : 'http://johnson.co' } ] } ] }), elem('photo')( match(function (context, json) { return json.url; })( tag()('img') ) ), elem('photo')( match(function (context, json) { return json.url; })( addAttrs()((context, json) => ({ href: json.url })) ) ), elem('photo').wrap()(function() { return { block: 'avatar', content: this.ctx } }), elem('company')( prependContent()('«'), appendContent()('»') ) );
Текущий шаг
block('user')( content()(function(n, ctx) { return { elem : 'photo', url: ctx.url, title: 'john-photo' } }), content()(function(n, ctx) { return [ applyNext(), { elem : 'add', content : 'add' } ] }), content()(function(n, ctx) { return [ applyNext(), { elem : 'info', content : [ { elem : 'name', content : ctx.name }, { elem : 'company', content : 'Johnson & Johnson' }, { elem : 'website', content : 'http://johnson.co', url : 'http://johnson.co' } ] } ] }), elem('photo')( match(function (context, json) { return json.url; })( tag()('img') ) ), elem('photo')( match(function (context, json) { return json.url; })( addAttrs()((context, json) => ({ href: json.url })) ) ), elem('photo').wrap()(function() { return { block: 'avatar', content: this.ctx } }), elem('company')( prependContent()('«'), appendContent()('»') ), elem('website')( tag()('a'), mix()({ block: 'link' }), addAttrs()((context, json) => ({ href: json.url }) ) );
Предыдущий шаг
<div class="user user_type_active"> <div class="avatar"> <img class="avatar__photo" href="john.png" > </div> <div class="user__info"> <div class="user__name">John Johnson</div> <div class="user__company">"Johnson &amp; Johnson"</div> <div class="user__website">http://johnson.co</div> </div> <div class="user__add">add</div> </div>
Текущий шаг
<div class="user user_type_active"> <div class="avatar"> <img class="avatar__photo" href="john.png" > </div> <div class="user__info"> <div class="user__name">John Johnson</div> <div class="user__company">"Johnson &amp; Johnson"</div> <a class="user__website link" href="http://johnson.co">http://johnson.co</a> </div> <div class="user__add">add</div> </div>
BEMHTML
HTML
Заменяем элемент add на блок add
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad vel dolore recusandae eum quia id laudantium est officia excepturi, obcaecati eaque, quibusdam, iste fugiat quo nemo ut. Architecto, cumque, inventore.
Предыдущий шаг
block('user')( content()(function(n, ctx) { return { elem : 'photo', url: ctx.url, title: 'john-photo' } }), content()(function(n, ctx) { return [ applyNext(), { elem : 'add', content : 'add' } ] }), content()(function(n, ctx) { return [ applyNext(), { elem : 'info', content : [ { elem : 'name', content : ctx.name }, { elem : 'company', content : 'Johnson & Johnson' }, { elem : 'website', content : 'http://johnson.co', url : 'http://johnson.co' } ] } ] }), elem('photo')( match(function (context, json) { return json.url; })( tag()('img') ) ), elem('photo')( match(function (context, json) { return json.url; })( addAttrs()((context, json) => ({ href: json.url })) ) ), elem('photo').wrap()(function() { return { block: 'avatar', content: this.ctx } }), elem('company')( prependContent()('«'), appendContent()('»') ), elem('website')( tag()('a'), mix()({ block: 'link' }), addAttrs()((context, json) => ({ href: json.url }) ) );
Текущий шаг
block('user')( content()(function(n, ctx) { return { elem : 'photo', url: ctx.url, title: 'john-photo' } }), content()(function(n, ctx) { return [ applyNext(), { elem : 'add', content : 'add' } ] }), content()(function(n, ctx) { return [ applyNext(), { elem : 'info', content : [ { elem : 'name', content : ctx.name }, { elem : 'company', content : 'Johnson & Johnson' }, { elem : 'website', content : 'http://johnson.co', url : 'http://johnson.co' } ] } ] }), elem('photo')( match(function (context, json) { return json.url; })( tag()('img') ) ), elem('photo')( match(function (context, json) { return json.url; })( addAttrs()((context, json) => ({ href: json.url })) ) ), elem('photo').wrap()(function() { return { block: 'avatar', content: this.ctx } }), elem('company')( prependContent()('«'), appendContent()('»') ), elem('website')( tag()('a'), mix()({ block: 'link' }), addAttrs()((context, json) => ({ href: json.url }) ), elem('add').replace()({ block: 'add-to-friend' }) );
Предыдущий шаг
<div class="user user_type_active"> <div class="avatar"> <img class="avatar__photo" href="john.png" > </div> <div class="user__info"> <div class="user__name">John Johnson</div> <div class="user__company">"Johnson &amp; Johnson"</div> <a class="user__website link" href="http://johnson.co">http://johnson.co</a> </div> <div class="user__add">add</div> </div>
Текущий шаг
<div class="user user_type_active"> <div class="avatar"> <img class="avatar__photo" href="john.png" > </div> <div class="user__info"> <div class="user__name">John Johnson</div> <div class="user__company">"Johnson &amp; Johnson"</div> <a class="user__website link" href="http://johnson.co">http://johnson.co</a> </div> <div class="add-to-friend"></div> </div>
BEMHTML
HTML
Добавляем еще одну ссылку
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad vel dolore recusandae eum quia id laudantium est officia excepturi, obcaecati eaque, quibusdam, iste fugiat quo nemo ut. Architecto, cumque, inventore.
Предыдущий шаг
block('user')( content()(function(n, ctx) { return { elem : 'photo', url: ctx.url, title: 'john-photo' } }), content()(function(n, ctx) { return [ applyNext(), { elem : 'add', content : 'add' } ] }), content()(function(n, ctx) { return [ applyNext(), { elem : 'info', content : [ { elem : 'name', content : ctx.name }, { elem : 'company', content : 'Johnson & Johnson' }, { elem : 'website', content : 'http://johnson.co', url : 'http://johnson.co' } ] } ] }), elem('photo')( match(function (context, json) { return json.url; })( tag()('img') ) ), elem('photo')( match(function (context, json) { return json.url; })( addAttrs()((context, json) => ({ href: json.url })) ) ), elem('photo').wrap()(function() { return { block: 'avatar', content: this.ctx } }), elem('company')( prependContent()('«'), appendContent()('»') ), elem('website')( tag()('a'), mix()({ block: 'link' }), addAttrs()((context, json) => ({ href: json.url }) ) );
Текущий шаг
block('user')( content()(function(n, ctx) { return { elem : 'photo', url: ctx.url, title: 'john-photo' } }), content()(function(n, ctx) { return [ applyNext(), { elem : 'add', content : 'add' } ] }), content()(function(n, ctx) { return [ applyNext(), { elem : 'info', content : [ { elem : 'name', content : ctx.name }, { elem : 'company', content : 'Johnson & Johnson' }, { elem : 'website', content : 'http://johnson.co', url : 'http://johnson.co' } ] } ] }), elem('photo')( match(function (context, json) { return json.url; })( tag()('img') ) ), elem('photo')( match(function (context, json) { return json.url; })( addAttrs()((context, json) => ({ href: json.url })) ) ), elem('photo').wrap()(function() { return { block: 'avatar', content: this.ctx } }), elem('company')( prependContent()('«'), appendContent()('»') ), elem('website')( tag()('a'), mix()({ block: 'link' }), addAttrs()((context, json) => ({ href: json.url }) ), elem('info')( content()(function(n, ctx) { return [ applyNext(), { elem : 'website', content : 'http://bem.info', url : 'http://bem.info' } ] }) ) );
Предыдущий шаг
<div class="user user_type_active"> <div class="avatar"> <img class="avatar__photo" href="john.png" > </div> <div class="user__info"> <div class="user__name">John Johnson</div> <div class="user__company">"Johnson &amp; Johnson"</div> <a class="user__website link" href="http://johnson.co">http://johnson.co</a> </div> <div class="add-to-friend"></div> </div>
Текущий шаг
<div class="user user_type_active"> <div class="avatar"> <img class="avatar__photo" href="john.png" > </div> <div class="user__info"> <div class="user__name">John Johnson</div> <div class="user__company">"Johnson &amp; Johnson"</div> <a class="user__website link" href="http://johnson.co">http://johnson.co</a> <a class="user__website link" href="http://bem.info">http://bem.info</a> </div> <div class="add-to-friend"></div> </div>