Emmet как платформа
для инструментов
Сергей Чикуёнок | http://emmet.io
Что такое Emmet?
• Инструмент для ускорения работы с HTML и CSS
• Плагин для множества популярных редакторов кода
• Написан на чистом JavaScript, легко встраивается
Что такое Emmet?
Развитие инструментов для
фронт-энд разработчиков
1990-е: Microsoft FrontPage
2000-е: Ъ-кодеры пишут в «Блокноте»
2010-е: Sublime Text,WebIDE
Sublime Text WebIDE
• быстрый
• красивый
• классный API
• удобный автокомплит
• кроссплатформенный
• богатый функционал
• много хорошо интегрированных
инструментов
• удобная отладка
С точки зрения фронт-энд
разработчика:
Sublime Text WebIDE
• только раскрашивает HTML и CSS
• API работает с обычным текстом
• Java
• медленная
• API позволяет работать с AST, но
это очень сложно
• разработчики акцентируют
внимание на других вещах
Код по-прежнему долго писать
и тяжело редактировать
Выход?
Препроцессоры!
Преимущества:
• Короткая нотация, быстрее писать
• Читабельность
• Синтаксический сахар
• Шаблонизация, связь с внешними данными
Недостатки:
• Сложная отладка кода
• Не решают проблему редактирования существующего
кода
• Не всегда можно использовать на клиенте
Чего хочется:
• писать меньше кода
• работать в любимом редакторе
• разрабатывать инструменты на JavaScript
• работать с HTML и CSS как с DOM
Emmet – платформа для
инструментов
веб-разработчика
Emmet как платформа
• модульная архитектура
• написан на JavaScript
• поддержка большого количества редакторов
•поддержка расширений
Расширения Emmet
• Обычные .js и .json-файлы в специальной папке
• Загружаются автоматически
• Могут дополнять или переопределять основной
функционал
• Одинаково работают в разных редакторах
Основные модули
• разбор и преобразование аббревиатур
• поиск пар тэгов в коде
• работа с HTML-тэгами и CSS-правилами через DOM-
подобный интерфейс
Как из аббревиатур
получается HTML-код
Разбор аббревиатуры в дерево
Нормализация дерева
Формирование текстового результата
Готовый код
Как из аббревиатур
получается HTML-код
Разбор аббревиатуры в дерево
Нормализация дерева
Формирование текстового результата
Готовый код
препроцессоры
постпроцессоры
фильтры
emmet.exec(function(require, _) {
require('filters').add('my_filter', function process(tree, profile) {
_.each(tree.children, function(item) {
// пример для HTML
item.start = '<' + item.name() + '>';
item.end = '</' + item.name() + '>';
// пример для Jade
item.start = item.name() + 'n';
item.padding = 't';
// преобразуем уже существующий результат
item.start = item.start.replace(/</g, '&lt;').replace(/>/g, '&gt;');
// рекурсивное преобразование всего дерева
process(item, profile);
});
});
});
Пример фильтра
div>em|my_filter
var tag = emmet.require('htmlMatcher').tag(
'hello <em>world</em>', // текст, где искать тэг
12 // позиция, с которой начать поиск
);
tag.open = { // открывающий тэг
name: 'em',
selfClose: false, // является ли тэг самозакрывающимся
range: new Range() // {start: 6, end: 10}
};
tag.close = {...}; // закрывающий тэг
tag.innerRange = new Range(); // {start: 10, end: 15}
tag.innerContent = function(){}; // world
tag.outerRange = new Range(); // {start: 6, end: 20}
tag.outerContent = function(){}; // <em>world</em>
tag.range = innerRange || outerRange;
tag.content = innerContent || outerContent;
Получение HTML-тэга
emmet.exec(function(require, _) {
require('actions').add('rename_tag', function(editor) {
var tag = require('htmlMatcher').tag(editor.getContent(), editor.getCaretPos());
if (tag) {
var newName = editor.prompt('Введите новое имя тэга');
if (tag.close) {
editor.replaceContent(
'</' + newName + '>',
tag.close.range.start,
tag.close.range.end);
}
editor.replaceContent(
'<' + newName,
tag.open.range.start,
tag.open.range.start + tag.open.name.length + 1);
}
});
});
Пример: переименование тэга
Интерфейс для редактирования
HTML и CSS
(EditTree)
• Интерфейс для высокоуровнего редактирования HTML-
тэгов и CSS-правил
• Похож на DOM
• Предоставляет доступ ко всем атрибутам/свойствам
контейнера, а также их диапазонам
•Учитывает форматирование кода
var tree = emmet.require('xmlEditTree')
.parse('<tag attr1="val1" attr2="val2">');
tree.value('attr1'); // val1
tree.get('attr1').range(); // {start: 5, end: 17}
tree.value('attr1', 'Hello world');
tree.remove('attr2');
tree.add('a', 'b', 0);
tree.source; // <tag a="b" attr1="Hello world">
Редактирование HTML
(xmlEditTree)
var tree = emmet.require('cssEditTree').parse('div {color: red}');
// можно использовать метод parseFromPosition(content, pos)
// для получения правила из документа
tree.value('color', 'black');
tree.value('position', 'relative');
tree.source; // div {color: black;position: relative;}
Редактирование CSS
(cssEditTree)
Только вы сами можете
создавать лучшие
инструменты
Вопросы?
serge.che@gmail.com
http://emmet.io
@emmetio

Emmet - инструмент для веб-разработчика

  • 1.
    Emmet как платформа дляинструментов Сергей Чикуёнок | http://emmet.io
  • 2.
    Что такое Emmet? •Инструмент для ускорения работы с HTML и CSS • Плагин для множества популярных редакторов кода • Написан на чистом JavaScript, легко встраивается
  • 3.
  • 4.
  • 5.
  • 6.
    2000-е: Ъ-кодеры пишутв «Блокноте»
  • 7.
  • 8.
    Sublime Text WebIDE •быстрый • красивый • классный API • удобный автокомплит • кроссплатформенный • богатый функционал • много хорошо интегрированных инструментов • удобная отладка
  • 9.
    С точки зренияфронт-энд разработчика: Sublime Text WebIDE • только раскрашивает HTML и CSS • API работает с обычным текстом • Java • медленная • API позволяет работать с AST, но это очень сложно • разработчики акцентируют внимание на других вещах
  • 10.
    Код по-прежнему долгописать и тяжело редактировать
  • 11.
  • 12.
  • 13.
    Преимущества: • Короткая нотация,быстрее писать • Читабельность • Синтаксический сахар • Шаблонизация, связь с внешними данными
  • 14.
    Недостатки: • Сложная отладкакода • Не решают проблему редактирования существующего кода • Не всегда можно использовать на клиенте
  • 15.
    Чего хочется: • писатьменьше кода • работать в любимом редакторе • разрабатывать инструменты на JavaScript • работать с HTML и CSS как с DOM
  • 16.
    Emmet – платформадля инструментов веб-разработчика
  • 17.
    Emmet как платформа •модульная архитектура • написан на JavaScript • поддержка большого количества редакторов •поддержка расширений
  • 18.
    Расширения Emmet • Обычные.js и .json-файлы в специальной папке • Загружаются автоматически • Могут дополнять или переопределять основной функционал • Одинаково работают в разных редакторах
  • 19.
    Основные модули • разбори преобразование аббревиатур • поиск пар тэгов в коде • работа с HTML-тэгами и CSS-правилами через DOM- подобный интерфейс
  • 20.
    Как из аббревиатур получаетсяHTML-код Разбор аббревиатуры в дерево Нормализация дерева Формирование текстового результата Готовый код
  • 21.
    Как из аббревиатур получаетсяHTML-код Разбор аббревиатуры в дерево Нормализация дерева Формирование текстового результата Готовый код препроцессоры постпроцессоры фильтры
  • 22.
    emmet.exec(function(require, _) { require('filters').add('my_filter',function process(tree, profile) { _.each(tree.children, function(item) { // пример для HTML item.start = '<' + item.name() + '>'; item.end = '</' + item.name() + '>'; // пример для Jade item.start = item.name() + 'n'; item.padding = 't'; // преобразуем уже существующий результат item.start = item.start.replace(/</g, '&lt;').replace(/>/g, '&gt;'); // рекурсивное преобразование всего дерева process(item, profile); }); }); }); Пример фильтра div>em|my_filter
  • 23.
    var tag =emmet.require('htmlMatcher').tag( 'hello <em>world</em>', // текст, где искать тэг 12 // позиция, с которой начать поиск ); tag.open = { // открывающий тэг name: 'em', selfClose: false, // является ли тэг самозакрывающимся range: new Range() // {start: 6, end: 10} }; tag.close = {...}; // закрывающий тэг tag.innerRange = new Range(); // {start: 10, end: 15} tag.innerContent = function(){}; // world tag.outerRange = new Range(); // {start: 6, end: 20} tag.outerContent = function(){}; // <em>world</em> tag.range = innerRange || outerRange; tag.content = innerContent || outerContent; Получение HTML-тэга
  • 24.
    emmet.exec(function(require, _) { require('actions').add('rename_tag',function(editor) { var tag = require('htmlMatcher').tag(editor.getContent(), editor.getCaretPos()); if (tag) { var newName = editor.prompt('Введите новое имя тэга'); if (tag.close) { editor.replaceContent( '</' + newName + '>', tag.close.range.start, tag.close.range.end); } editor.replaceContent( '<' + newName, tag.open.range.start, tag.open.range.start + tag.open.name.length + 1); } }); }); Пример: переименование тэга
  • 25.
    Интерфейс для редактирования HTMLи CSS (EditTree) • Интерфейс для высокоуровнего редактирования HTML- тэгов и CSS-правил • Похож на DOM • Предоставляет доступ ко всем атрибутам/свойствам контейнера, а также их диапазонам •Учитывает форматирование кода
  • 26.
    var tree =emmet.require('xmlEditTree') .parse('<tag attr1="val1" attr2="val2">'); tree.value('attr1'); // val1 tree.get('attr1').range(); // {start: 5, end: 17} tree.value('attr1', 'Hello world'); tree.remove('attr2'); tree.add('a', 'b', 0); tree.source; // <tag a="b" attr1="Hello world"> Редактирование HTML (xmlEditTree)
  • 27.
    var tree =emmet.require('cssEditTree').parse('div {color: red}'); // можно использовать метод parseFromPosition(content, pos) // для получения правила из документа tree.value('color', 'black'); tree.value('position', 'relative'); tree.source; // div {color: black;position: relative;} Редактирование CSS (cssEditTree)
  • 28.
    Только вы самиможете создавать лучшие инструменты
  • 29.