Наноблог Артёма Сапегина

Создание файлов и структуры проекта по шаблонам с помощью Grunt

Grunt — это набор инструментов командной строки, облегчающих разработку на JavaScript. Он умеет склеивать и минифицировать JS-файлы, запускать тесты и JSHint, запускать задачи при изменении файлов и даже содержит простейший веб-сервер. Но самое интересное для меня — команда init, создающая файлы (или структуру папок) по шаблону.

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

Например, набрав grunt init:readme, я получаю в текущей папке файлы Readme.md и License.md, в которых уже стоят текущий год, моё имя и т. п.

Шаблон состоит из:

1. Файла templatename.js. В нём можно описать, что должен ввести пользователь; как эти параметры будут преобразованы и т. п. Тут доступны любые возможности JavaScript и Node.js.

2. Папки templatename/root со всеми файлами, которые будут скопированы при выполнении шаблона.

3. Файла templatename/rename.json с описанием правил переименования файлов.

Сами шаблоны должны лежать в ~/.grunt/tasks/init или %USERPROFILE%\.grunt\tasks\init\.

Например, шаблон простейшего HTML-файла может выглядеть так. Файл html.js:

// Описание шаблона, которое можно увидеть выполнив grunt init (список доступных шаблонов)
exports.description = 'Create a simple HTML5 file.';

exports.template = function(grunt, init, done) {

	grunt.helper('prompt', {}, [
		// Пользовательские параметры
		// Имя файла (такой запрос уже есть в Гранте, поэтому нужно вызывать его с помощью grunt.helper)
		// index -- значение по умолчанию
		grunt.helper('prompt_for', 'name', 'index'),
		// Язык (такого запроса в Гранте нет, поэтому нам нужно описать все параметры)
		{
			name: 'lang',
			message: 'Document language',
			default: 'en'
		},
	], function(err, props) {
		// Достаём параметры по умолчанию (находятся в файле defaults.json)
		grunt.utils._.defaults(props, init.defaults);

		// Список файлов для копирования
		var files = init.filesToCopy(props);

		// Список файлов для копирования
		init.copyAndProcess(files, props);

		/// Готово :)
		done();
	});

};

В папке html/root лежит один файл name.html. (Шаблон вымышленный, чтобы показать возможности Гранта. Настоящий есть в репозитории.)

<!DOCTYPE html>
<html lang="{%= lang %}">
<head>
	<meta charset="utf-8">
	<title></title>
	<meta name="copyright" content="© {%= grunt.template.today('yyyy') %} {%= author_name %}">
</head><body>
</body></html>

Остаётся задать правила переименования. Файл html/rename.json:

{
	"name.html": "{%= name %}.html"
}

Всё, шаблоном можно пользоваться:

Что ещё посмотреть про Грант:

— Репозиторий на Гитхабе (стандартные шаблоны, описание команды init).

— Набор моих шаблонов.

— Статья автора Гранта Introducing Grunt.

— Статья Meet Grunt: The Build Tool for JavaScript на Nettuts+.

Комментарии 0

Запуск TortoiseGit из командной строки

Обычно я работаю с Гитом из командной строки, но выбирать файлы для коммита и смотреть логи/диффы удобнее через TortoiseGit. Чтобы не открывать его каждый раз из Проводника, я положил в папку C:\Program Files\TortoiseGit\bin файл tgit.bat с таким содержимым:

@TortoiseProc /command:%1 /path:.

И tgit для запуска из Git Bash:

#!/usr/bin/env sh
TortoiseProc /command:$1 /path:.

Теперь я могу просто писать в консоли tgit commit или tgit log. (На самом деле я сделал ещё одну пару файлов: tgitc.bat/tgitc для ещё более быстрого запуска окна коммита TortoiseGit.)

P. S. Ну а на сервере удобно использовать tig.

Комментарии 0

Хранение данных в CSS-файлах

Иногда бывает нужно хранить какие-то данные в непосредственно CSS-файле, и иметь к ним доступ из JavaScript. Самый простой и кроссбраузерный способ — использование свойств content и font-family с одинаковым значением (font-family нужен для ИЕ).

Где-нибудь на странице нужно создать служебный элемент:

<div id="pony"></div>​

И применить к нему CSS:

#pony {
	display: none;
	content: 'Pink';
	font-family: 'Pink';
	}​

Теперь мы можем легко достать нашу строку:

function getCssString(elem) {
	var value = elem.css('content') || elem.css('font-family');
	return value && value.replace(/"/g, '');
}

alert(getCssString($('#pony')));

Можно посмотреть живой пример.

P. S. Спасибо коллеге Егору Дыдыкину за указание подсказку этого метода.

Комментарии 11

Создание удобных демостраниц на Гитхабе с помощью сабмодулей

Если вы используете гитхаб-страницы для демонстрации своих проектов, и вам надоело копировать исходные файлы из основной ветки в ветку gh-pages, то есть простой способ этого избежать.

Можно добавить ветку master как сабмодуль в ветку gh-pages (адрес репозитория должен быть именно в таком формате, иначе страница перестанет обновляться):

git submodule add git://github.com/sapegin/social-likes.git src
git submodule init

Теперь можно подключать к страницам любые файлы проекта из папки src. Не забывайте только обновлять сабмодуль после изменений в основной ветке:

cd src
git pull origin master
cd ..
git commit -a -m "Update source."
git push origin gh-pages

P. S. А вот результат.

Комментарии 0

Долой версии программ!

Недавно я смотрел статистику по браузерам на Мэйл.ру и обратил внимание, как хорошо работает автообновление в браузерах. Хром, Опера — у примерно 90% пользователей последняя версия. Файрфокс пока не успел: последние две версии распространены одинаково, да ещё и 3.6 торчит, который не умеет нормально обновляться. Обратный пример — ИЕ: 9-я версия вышла год назад, но так и не обогнала 8-ю.

Добавим к этому частые релизы (новые версии Хрома и Файрфокса выходят раз в три месяца) и «молчаливое» обновление: то есть без дурацких окон во весь экран и прерывания работы (в Хроме так уже давно, скоро точно так же будет в Файрфоксе).

Теперь возникает вопрос: нужно ли вообще пользователю знать о версиях установленных у него программ, и как-то участвовать в их обновлении? Ведь если я устанавливаю Хром, логично, что я хочу иметь свежайший и лучший Хром, а не какой-нибудь протухший. (Оставим ретроградов и параноиков в стороне.)

Что действительно интересно — так это новые фичи. О них нужно рассказывать прямо в приложении, показывая где они и рассказывая, как ими пользоваться. Но для этого совсем не обязательно ждать два года следующего мажорного релиза — можно выкатывать фичи по мере их готовности. Пользователю тоже проще осваивать их по чуть-чуть.

Именно такая модель давно применяется в веб-приложениях и отлично работает. Я понятия не имею, какая у Гугл Доков (где я набираю сейчас этот пост) последняя версия, но если там появится что-то интересное, мне это покажут и научат пользоваться.

Комментарии 14

Что важнее: код или продукт, и нужно ли скрывать свой код

Илья Бирман хорошо рассказывает, что важнее: сам продукт или его код. Во всём согласен, кроме сокрытия исходников и предположения, что туда никто не смотрит.

Смотрите, что является вашим продуктом? Код или полезное действие, который он обеспечивает? Я не даю исходники Эгеи, потому что продуктом является сам движок, а не его код. Бывает, конечно, наоборот: если вы делаете какую-то опенсорсную библиотеку, то сам код и является продуктом. В этом случае, несомненно, важно, как он устроен внутри. Но в большинстве случае пользователи не взаимодействуют с кодом вообще никак и никогда, и поэтому его внутреннее устройство не имеет значения.

Возможно, для Эгеи такой подход оправдан, но я довольно часто смотрю в чужой код. Из-за невнятной документации, странных ошибок (которые обычно приводят к ошибке в моём коде, но сначала нужно понять, что от меня ждёт чужой код), просто из любопытства и в качестве обучения. Поэтому я считаю наличие кода весьма полезным.

В последнее время я вижу всё меньше причин скрывать свой код. В этом есть немало плюсов, а минусов я пока не нашёл. Например, лучше получается выделять куски, пригодные для последующего использования; можно пользоваться прекрасным Гитхабом бесплатно. Есть и другие причины, но они уже зависят от популярности автора и проекта. (Хорошая заметка по теме — Open Source (Almost) Everything.)

Комментарии 6

Не надо больше социальных сетей

Социальных сетей становится всё больше и больше, но никто пока не сделал инструмент, который позволил бы иметь все информационные потоки в одном месте. С возможностью подписаться на человека (а не отдельно на его блог, твиттер, обновления сайта и т. п.), с крутыми фильтрами (чтобы не было в ленте постов про футбол и политику, чтобы одни и те же тупые шутки не мелькали в ленте по 10 раз, и можно было полностью исключать упоминания какого-либо явления или события).

Сейчас я читаю две RSS-ленты (все ЖЖ, естественно, тоже в них), Твиттер и Фейсбук. Плюс на несколько сайтов захожу раз в неделю поглядеть (500px, Dribbble…). В каждой ленте по несколько сотен потоков. По многим причинам это ужасно неудобно.

1. Первая лента — Яндекс Подписки. Её я читаю по будням. Тут в основном про веб-разработку и прочее занудство. Сюда же попадают фотографы, к кому я редко заглядываю под кат (Подписки показывают его только по клику, это удобно). У Подписок есть некоторые недостатки (огромная нескрываемая панель слева и неработающая j/k-навигация, например), но в целом он довольно удобный.

2. Вторая лента — Гугл Ридер. Этой штукой нельзя пользоваться без напильника (в виде плагина minimalist для Хрома) — разработчики налепили столько горизонтальных панелей, что на сообщения просто не остаётся места. Здесь у меня в основном фотографы и фотосайты. Её я читаю раз в неделю.

3. Твиттер. Тут есть одно спасение — Slipstream, который убирает из ленты немало мусора: форскверы, ютубы, трекеры похудания и пробежек, ретвиты отдельных пользователей и всё то, что нормальный человек никогда не опубликует). В Слипстриме у меня уже несколько десятков правил.

4. Фейсбук. До недавнего изменения дизайна ленты читать её было совершенно невозможно. Сейчас уже кое-как можно, правда приходится отписываться от ненужных событий (например, какое мне дело, кто с кем подружился) отдельно для каждого пользователя.

Ещё одна полезная штука — Instapaper. Раньше длинные статьи месяцами висели у меня в браузере, после чего я закрывал их, так и не прочитав. Сейчас я отправляю их в Инстапейпер (плагином для Хрома — это один клик), а раз в неделю мне на Киндл приходит «газета» с подборкой непрочитанных статей.

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

Комментарии 6

Стиль HTML-кода: HTML, XHTML и снова HTML

Лет 10 назад, когда я только-только начал заниматься веб-разработкой, то считал, что чем короче код, тем он круче (мы же в интернете, фигли). Да и вообще любил всякое ковбойство. Код я писал примерно такой:

<html><head>
<title>general protection fault group</title>
<meta http-equiv="Content-Type" content="text/html;charset=windows-1251" />
<link rel=STYLESHEET type=text/css href=styles/styles.css>
</head>
<body bgcolor=#666666 text=#333333 leftmargin=0 topmargin=0 rightmargin=0 bottommargin=0 marginheight=0 marginwidth=0>

Яваскрипт не отставал: односимвольные имена переменных, никаких комментариев и всё такое.

Потом я немного поумнел и понял, что так нельзя. Как раз тогда в моду вошёл XHTML с его строгим XML-синтаксисом, и я полностью перешёл на него. Закрывающий слэш, конечно, раздражал, но надо так надо.

А потом внезапно пришёл HTML5, и я в один день отказался от XML-синтаксиса. Как-то неожиданно пришло понимание, что суть не в следовании навязанным кем-то правилам (вспомним бессмысленные кнопки XHTML 1.0 и CSS 2.0, которые не так давно ставили на свои сайты все уважающие себя веб-разработчики), а в понимании того, что делаешь. Нет ничего хорошего в несемантичной вёрстке, даже если она проходит любую мыслимую валидацию. Но и нет смысла писать лишние закорючки, если есть более простой стандарт. При этом никто не запрещает закрывать теги и писать атрибуты в кавычках, хоть стандарт этого и не требует, просто потому, что это удобно.

Комментарии 0

О простых и сложных инструментах

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

С одной стороны нет смысла ставить/изучать Фотошоп, если задачи ограничиваются кадрированием и уменьшение для веба (сам до недавнего времени пользовался на работе сначала Пейнтом.Нет, а потом Фотошопом Элементс). Но с другой стороны, опытный фотограф в сто раз быстрее сделает это в Фотошопе, потому что Фотошоп он отлично знает. Ему нет смысла изучать ещё одну программу, которая позволит ему делать то же, что и Фотошоп, но будет запускаться на сотую секунды быстрее.

Пример из другой области. Я долго не желал изучать Гит. Он казался слишком красноглазым сложным и запутанным по сравнению с более простым Меркуриалом. Но сейчас я каждый день использую Гит на работе и немного использую Гитхаб; то есть Гит стал неизбежным и привычным, и теперь мне нет смысла изучать два похожих инструмента. Лучше хорошо изучить один и научиться эффективно применять его везде.

Получается, нет смысла изучать новый инструмент для какой-то задачи, если её можно решить достаточно хорошо, используя привычный и хорошо изученный инструмент.

Комментарии 16

Чем отличается разработка собственного кода от использования чужой библиотеки?

В первом случае вы полдня пишете код без остановки; а во втором — полдня ищете, какие нужно написать две строчки, что всё заработало (если библиотека хорошая, вы их находите).

Комментарии 3

Тестирование моделей с FileField/ImageField в Django

Оказалось, что тестирование моделей с файлом (поле FileField) или картинкой (поле ImageField) в Django не так уж очевидно. Допустим, у нас есть модель:

class MagicPony(models.Model):
	photo = models.ImageField(_('Photo'), upload_to='uploads/ponies')

При загрузке файла через HTML-форму проблем не возникает, но, чтобы загрузить изображение с диска, нужно дополнительно обернуть наш файл в объект File:

from django.core.files import File

class PonyTest(TestCase):
	def test_magic_power(self):
		file = open('pony.jpg', 'rb')
		file = File(file)
		pony = MagicPony.objects.create(photo=file)

		# Теперь можно писать любые проверки (наличие магической силы,
		# количество копыт и т. п.)

Комментарии 0

Курс по подготовке идиотов (цитаты из книги «Искусство оформления сайта»)

Искусство оформления сайтаМне всегда было интересно, где люди учатся делать те самые безвозвратно ужасные сайты, которыми полнятся интернеты. И кажется я нашёл ответ. Это книга С. Н. Бердышева «Искусство оформления сайта», изданная издательством Дашков и Ко в 2010 году. Не судите об этой книге по обложке — она совершенно не даёт представления о том, насколько она ужасна. Больше всего в книге удивляют пересказы умных книг о веб-дизайне и юзабилити с последующим созданием страницек-уродцев, полностью им не соответствующим. Судя по содержанию, книге уже лет 10, хотя все скриншоты сделаны в Висте, а список литературы составлен из книг 2008 года издания. Кстати, у автора почти два десятка книг о различных аспектах рекламы, маркетинга, бизнеса и других предметов. (Кстати, меня тоже пытались учить плохому, но я удержался.)

Далее идут цитаты из книги без каких-либо комментариев, чтобы не портить вам удовольствие.

(После того, как ссылка на пост появилась на Хабре, какой-то шутник заново зарегистрировал сайт, на который ссылается автор книги, и разместил там всё правду о ней.)

Читать дальше…

Комментарии 76

Анимация цвета с помощью плагина jQuery.Color()

Недавно команда jQuery выпустила бета-версию обновлённого плагина для анимации цвета jQuery.Color(). Плагин позволяет работать с цветовыми моделями RGBA и HSLA; читать и изменять (как на абсолютные значения, так и относительно текущего) отдельные компоненты цветов; анимировать цвет фона, текста и рамки.

Например, можно плавно изменять оттенок (hue) от 0 до 359 (т. е. от красного до красного со всеми остальными цветами между ними). (Первый пример по ссылке.)

(function animate() {
	var block = $('#c1');
	block.animate({backgroundColor: $.Color(block.css('backgroundColor')).hue('+=179')}, 3000, animate);
})();

А вот более полезное применение: обратная связь при клике. Блок как бы зажигается на мгновение. Это достигается плавным увеличением яркости (lightness) на 40%. При этом скрипту не нужно задавать никакие цвета: он сам определяет и начальный цвет, и конечный. Я недавно использовал такой эффект в пятизвёздочном рейтинге — смотрится хорошо. (Второй пример по той же ссылке.)

$('#c2').click(function(e) {
	var block = $(e.target);
	var color = $.Color(block.css('backgroundColor'));
	block.animate({backgroundColor: color.lightness('+=0.4')}, 300, function() {
		block.animate({backgroundColor: color}, 300);
	});
});

Комментарии 0

Подсветка кода в WordPress с помощью highlight.js

Решил заменить в блоге серверную подсветку кода (плагин wp-syntax) на клиентскую (highlight.js). Знаю, что для последнего уже есть несколько плагинов для Вордпресса, но мне показалось, что проще самому написать 10 строк кода.

Читать дальше…

Комментарии 4

CSS3 transition фона: кое-какие детали

Читая книгу «Stunning CSS3» обратил внимание, что стандарт CSS3 запрещает делать transition свойства background. Можно использовать только background-color, background-image (почему-то только для градиентов) и background-position. Однако, как было написано в книге, большинство браузеров должны понимать и просто background.

Я решил проверить, так ли это на самом деле, и сделал небольшой тест. На данный момент все браузеры, кроме Оперы, делают переход цвета фона, даже если написать просто background.

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

Проверку переходов background-position оставляю читателю в качестве домашнего задания.

Комментарии 0