Меня, почему-то, очень воодушевляет возможность писать расширения для хрома. Это не значит, что я этим воодушевлением как-то пользуюсь, но тем не менее. Задачи я получаю через Chrome, в нем же их потом тестирую, в нем же читаю (не)довольные письма от заказчиков после коммита, и на каждой стадии хватает мелочей, которые можно улучшить.
А расширение — оно простое. Манифест + какой-нибудь js файл с логикой — и всё.
Самое простое расширение, которое я когда-либо делал для себя — content script. Это обычный JavaScript файл, который подгружается для страниц, которые требуется надругать. У него полный доступ к DOM, что можно очень эффектно эксплуатировать. С моём случае скрипт подгружался для баг трэкера, пробегался по содержимому баг репорта и подсвечивал потенциально проблемные места красным, затенял менее приоритетные, форматировал историю навигации, stack trace, и т. п.. Читать такие кейсы было намного проще, да и времени экономилась уйма.
Hello world мира контентных скриптов обычно состоит из двух файлов: manifest.json и, например, helloWorld.js.
1 2 3 4 5 6 7 8 9 10 |
{ "name": "Hello world", "description": "Do you really need a description for that?", "version": "0.1", "manifest_version": 2, "content_scripts": [{ "matches": [ "http://www.html5rocks.com/*" ], "js": ["helloWorld.js"] }] } |
Поля вполне понятны, кроме, возможно, версий. Их две — одна на экстеншн, одна для манифеста (всегда двойка). В секцию content_scripts я иногда добавлял «css».
helloWorld.js вообще эстетически прекрасен:
1 |
console.log("hello world"); |
Если добавить этот экстеншн в хром, то при заходе на хабру он будет писать вселенское приветствие прямо в консоль.
Добавить расширение в хром тоже элементарно:
- открываем хром
- заходим на chrome://extensions
- убеждаемся, что чекбокс Developer mode включен
- жмем кнопку Load unpacked extension
- натравливаем диалог на папку с манифестом.
Всё. Хром настолько вежлив, что если в манифесте были какие-то ошибки (например, JSON ключи не в кавычках), то он выскажет недоумение сразу же.
Однако во всех hello world приложениях есть один существенный недостаток — их вопиющая бесполезность. Посмотрим, можно ли сделать мир действительно немного лучше.
В одной из стран-членов ООН есть портал onliner.by, который во время сеанса прокрастинации сильно выручает новостями о мире, технике и дорожно-транспортных происшествиях. Есть только одна проблема — любое упоминание Apple, android или продукции, которая с ними связана, открывает портал в филиал ада сразу за первым комментариям.
Особенно плохо то, что моя ранимая психика подвисает на этих комментариях, и пока я на каждый коммент мысленно не отвечу автору, в чем именно он неправ, нормально работать не получится.
Можно сделать экстеншн, который детектит в заголовке статьи ключевые слова, и в случае чего заменяет комменты на котиков, плейсхолдеры — на что угодно. За базу легко сойдет предыдущий hello world.
Итак, манифест. Тут всё гуд, только поменяем html5rocks на онлайнер:
1 |
"matches": ["http://tech.onliner.by/*"], |
Как определить, что заголовок грозит бедой? Легко. Судя по всему, заголовки к статьям всегда лежат в h3 где-то внутри тэга article. Искать заголовок по имени класса рисково, так как он выглядит неочевидным.
В код пустим это так:
1 |
var titleNode = document.querySelector("article h3"), |
Комментарии делятся на 2 группы: лучший и все остальные. Судя по именам классов, это всегда b-best-comment либо commentListItem:
1 |
var comments = document.querySelectorAll(".b-best-comment, .commentListItem"); |
На что менять? Хватает сервисов, которые по урлу дают картинку-плейсхолдер заданного размера. Есть просто прямоугольники, есть с котятами, есть с сиськами. В общем, на любой вкус. На случай, если пост будут читать дети, остановимся на серых прямоугольниках:
1 2 3 |
commentNode.innerHTML = "<img src='http://placehold.it/{0}x{1}'>" .replace("{0}", width) .replace("{1}", height); |
Всё! Берем заголовок, ищем ключевые слова, если находим — берем всё комменто-образное и превращаем в тлен. Вот так выглядит весь код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
var titleNode = document.querySelector("article h3"), title = titleNode && titleNode.textContent.trim().toLowerCase(), bannedWords = ["Apple", "iPad", "iOS", "Android", "Samsung"], mentionedInTheTitle = function (bannedWord) { return title.indexOf(bannedWord.toLowerCase()) !== -1; }; if (title && bannedWords.some(mentionedInTheTitle)) { var comments = document.querySelectorAll(".b-best-comment, .commentListItem"); Array.prototype.forEach.call(comments, function (commentNode) { var width = commentNode.offsetWidth, height = commentNode.offsetHeight; commentNode.style.width = width + "px"; commentNode.style.height = height + "px"; commentNode.style.paddingLeft = "0"; //http://placehold.it/{0}x{1} //http://placekitten.com/g/{0}/{1} //http://worksafe.placeboobs.com/{0}/{1} //http://placeboobs.com/{0}/{1} commentNode.innerHTML = "<img src='http://placehold.it/{0}x{1}'>" .replace("{0}", width) .replace("{1}", height); }); } else { console.log("The page is safe. So far."); } |
Просто же!
Со включенным расширением комментарии выглядят теперь так:
С котами будет симпатичнее.
Дебагить такие экстеншены очень просто: ставим debugger; и он подхватится дев тулами. Для не content script расширений в общем случае это не так.
Во время разработки экстеншена, чтобы увидеть сделанные в нем изменения на странице, нужно проделать дополнительную манипуляцию: прежде чем перегружать саму страницу, на которой загружен экстеншн, нужно зайти на chrome://extensions и перегрузить её через ctrl+R либо cmd+R(либо кнопка update extensions now).
Все.
P.S.: Когда-то я давал презентацию по расширениям, в которой упоминался пример с content script и препроцессингом баг репортов. Посмотреть её можно тут:
Само выступление тут: