Юзерскрипт: кроссбраузерно, кроссдоменно

в 9:38, , рубрики: add-on, greasemonkey, HabrAjax, Scriptish, userscript, метки: , , , ,

Юзерскрипт: кроссбраузерно, кроссдоменноРазработка юзерскрипта HabrAjax преодолела свои очередные проблемы с кроссбраузерной поддержкой новых функций и создала плеяду статей (7 штук, ещё не опубликованных) по разным вопросам, связанным в основном с юзерскриптами и их кроссдоменным доступом. Все эти статьи нетривиальны, в интернете их темы освещаются частично, а некоторые не освещаются даже в описаниях багов браузеров (или автору неизвестны иноязычные решения). Статьи придётся выкладывать в произвольном порядке, потому что нет оснований как-либо их упорядочивать — каждая связана с другой лишь по тематике. Сейчас я приведу анонсы статей, без ссылок, чтобы сложить представление, о чём пойдёт речь в дальнейшем. Реализация — в HabrAjax, но там довольно много прикладного кода, не слишком хороший пример для демонстрации. Поэтому для каждой статьи будут коды с более адаптированными примерами, насколько возможно.

Фикс-идея кроссбраузерности

Разработчики для пользователей хотят обеспечить максимальную простоту инсталляции, чтобы работать с юзерскриптами (или аддонами) было просто — взять файл и инсталлировать одним кликом; ещё лучше, чтобы все кроссбраузерные различия были учтены внутри единого общего файла. Аддоны (некроссбраузерные) так и делают — пользователю достаточно сказать «Установить» — и далее он получает желаемое без особых сложностей. Поэтому так популярны аддоны, хотя для их генерации из общего юзерскрипта приходится писать довольно сложный компоновщик.

Для юзерскриптов приходится часто писать браузерозависимые коды — как для преодоления различий в вёрстке, так и для учёта особенностей инсталляции. Тем не менее, идея делать проще зовёт к тому, чтобы сделать юзерскрипт, автоматически учитывающий разницу в особенностях инсталляции. Первое, с чем приходится сталкиваться — особенности браузерной инсталляции скриптов и понимание ими метаданных. Немало забот прибавляют кроссдоменные взаимодействия. При работе с юзерскриптами в разных браузерах появляется пара браузерных багов при межсайтовом обмене данными.

Требования к обмену данными у нас будут вовсе не такие ограниченные, как обычно принято. Обычно (для Оперы) считают, что мы можем написать функцию в скрипте на другом домене, и вся задача состоит в её выполнении во внедрённом скрипте. Часто мы не можем менять данные на чужом домене, а получить их — наша задача. Данные нужно извлекать:
1) произвольные текстовые, которые допускается обрамлять скриптом JS и передавать как файл JS (чтобы их упаковать в юзерскрипт);
2) вообще произвольные текстовые данные из другого файла без возможности обрамить чем-либо;
3) любые хеши JSON — в другой домен.

Первый случай возникает, когда нужно прочитать метаданные юзерскрипта в самом скрипте или при желании записать стили CSS без кодирования в строки JS. Кроссдоменности пока нет, но задача не совсем тривиальна, если хотим получить единый кроссбраузерный вид (в общем случае не решается — в Firefox недостаёт функций, а введённый в GreaseMonkey тип «xml» синтаксически несовместим с языком JS — другими словами, чуждый тип никак нельзя сделать кроссбраузерным). Получаем полурешения — кроссбраузерный вид для случая метаданных и Scriptish вместо GreaseMonkey, или необходимость чуть-чуть подправить файл на 2 символа для браузера Firefox сверх возможностей JS — тогда обеспечивается чтение не только метаданных, но и произвольных данных в файле *.user.js. Это, конечно, плохо, но таковы реалии совместимости юзерскриптов. Подробно проблема и возможные решения изложены в статье "Чтение многострочных данных в JS". Она выходит за рамки юзерскриптов, но именно в них имеет реальные шансы на решение.

Обратим внимание, что эти неразрешимые проблемы возникают, когда пытаемся данные и скрипт упаковать в одном-единственном файле скрипта (юзерскрипта или простого скрипта). Если использовать 2 файла — проблемы уже нет, потому что данные из 2-го файла можем прочитать как текст или HTML (в комментарии HTML держать почти произвольный текст), а в первом держать только скрипты. Однако, однофайловое решение — это хороший тон работы с пользователем: ему предоставляется один файл, который надо просто «инсталлировать». Правда, несколько забываем о такой мелочи, что только Хром может инсталлировать юзерскрипт нативно; для Firefox нужен аддон GreaseMonkey или Scriptish, для Оперы — прописывание настроек для сайта в настройках браузера (значит, если новый компьютер — то новые заботы с чередой действий, а не просто «инсталлировать файл). У неё аддон, подобный GreaseMonkey, находится в очень примитивном состоянии — требуется копировать скрипты в поле ввода аддона, не учитываются метаданные, поэтому его не упоминаем. Наконец, Safari тоже требует аддона (NinjaKit) и копирования тела файла юзерскрипта в редактор аддона. То есть, однофайловость + кроссбраузерность оказывается и без того сильно натянутой.

Второй и третий случаи обмена данными — решаются внедрением юзерскрипта в недоступную разработчику область чужого домена. Здесь решение усложняется багами в 2 браузерах из 4. В статьях „Обход бага Хромиума по кроссдоменному обмену в юзерскриптах“, „Кроссдоменный обмен данными в юзерскрипте в Опере“ показано, что их можно преодолеть.

Аддон вместо юзерскрипта для Оперы

Мы их предупреждали, что не остановимся ни перед чем, лишь бы пользователю было хорошо? Предупреждали. А они что сделали? Массу настроек без возможности автоматизации. Теперь мы имеем моральное право удариться во все тяжкие — придумать алгоритм генерации аддона для Оперы, заменяющего юзерскрипт. Потому что автоматизировать создание аддона можно, а создание встроенного в Оперу юзерскрипта — нет. Получим вожделенное решение в виде одной кнопки „Инсталлировать“ и даже место на сайте Оперы. Как сделать — в статье „Аддон для Opera из юзерскрипта“.

То же самое, кстати, и для Safari. Имеется NinjaKit — более близкий к возможностям GreaseMonkey аддон, но в него зачем-то вручную нужно копировать текст скрипта, и он не умеет полноценно поддерживать кроссдоменный запрос GM_XMLHTTPRequest. Всё это как-то несерьёзно; неизвестно, будет ли это поддержано. Проще тоже удариться в аддоны, решив заодно вопрос с иконками юзерскриптов, нормально решённый в Firefox и больше нигде не решённый (не считая аддонов): директива метаданных @icon поддерживается, а иконы в списке скриптов — работают только в Firefox. Там требуется маленький квест по получению звания разработчика в глазах верховного держателя всех правил, поэтому всё вместе описано в статье „Аддон для Safari из юзерскрипта“.

Кроссбраузерные аддоны

Раз мы с Оперой и Safari выкинуты в необходимость писать собственные аддоны, сильно отличающиеся по коду от юзерскрипта (не в том плане, что трудно собрать, а сильное различие в байтах), появляется очередная шальная мысль: ведь все аддоны всех браузеров построены по общим принципам — zip-архив, отличающийся своим расширением и ряд файлов с очень похожими функциями. А не сделать ли нам общий кроссбраузерный архив, в котором достаточно только переписать расширение? Если не будет конфликтов в именах файлов, то дело выполнимо — 4 витиеватых дорожки снова сольются в одну, а особенности реализации стерпит единый архив, включив избыточные браузерозависимые настройки. Сборщик архива снова упростится, заключаясь в ручной операции переименования расширения.

Пробраться в чужой огород со своими юзерскриптами

Кроссдоменные запросы метаданных — это полбеды. Она элементарно решается в 2 браузерах, трудно — в Опере. Но решение в Опере покажется лёгким, если познакомиться с полной бедой — обеспечением кроссдоменного обмена данными из фреймов сторонних сайтов. Чтение метаданных будет просто частным случаем и детской забавой с использованием той же техники обмена для Оперы (к сожалению, с BeforeScript у них, видимо, какой-то баг в юзерскриптах, не всегда работает). Как решена „полная беда“ — описано в статье „Обход бага Хромиума по кроссдоменному обмену в юзерскриптах“, а как воспользоваться решением для получения вкусных плодов из чужого огорода, хозяева которых не спешат через API ими делиться — в статье „Компактный размер кнопок Google Plus“. И в самом деле, зачем тратить 70 пикселей по горизонтали, мучиться с отсутствием данных о количестве „лайков“, когда чаще всего достаточно 24 пикселей на 1-2-3 цифры числа „лайков“? Зачем нам в дизайне своих страниц „говорящие“ кнопки „+1“? Юзерскрипт решит все эти проблемы — дело за пользователем установить его. Опять восстаёт призрак Оперы и страшит тонной инструкций по настройкам — ура, не зря мы научились упаковывать скрипты в аддоны в прежних статьях.

Это наиболее зрелищное дополнение юзерскрипта из сделанных в последней версии стоит проиллюстрировать. Кнопки Google+ необычно компактны благодаря юзерскрипту.
Юзерскрипт: кроссбраузерно, кроссдоменно

Статьи, в общем, готовы; не проработаны тестовые примеры, если не считать самого скрипта HabrAjax, на базе которого все эти проблемы всплыли. Поэтому они будут публиковаться в ближайшую неделю-две по мере осознания готовности всех вспомогательных материалов. Например, хочется к описанию обхода бага Хромиума (существует 2.5 года; некоторые считают его „фичей безопасности“) приложить наиболее компактный и чистый юзерскрипт, готовый для использования.

А что же HabrAjax и где искать реализацию кроссдоменности?

Если кратко, то в версии 0.81 он приобрёл такие возможности:
* Прямые ссылки на личные страницы, чтобы добираться к ним не в 2-3 клика, а в один.

Юзерскрипт: кроссбраузерно, кроссдоменно

* Проверка обновлений скрипта — периодически, не чаще раза в день (период настраивается) проверяет скрипт. Не беспокоит, если версия — минорная. (кроссдоменные технологии)

Юзерскрипт: кроссбраузерно, кроссдоменно

* показ фич из метаданных — подсказывает, что в нём появилось нового, а также, новое на сервере при проверке. (кроссдоменные технологии)

Юзерскрипт: кроссбраузерно, кроссдоменно

* стильную иконку в метаданных (ваще круть) (вон она там, вверху справа).
* эти рамочки вокруг чекбоксов — напоминают о последних изменённых фичах.
* настраиваемая макс. высота рисунков при принудительном кате (по умолчанию 120 с ZenComment). Высота аннотации (максимальная) — вдвое больше.
* написать письмо, выделив цитату или имя автора — не нужно копировать их вручную (включается настройкой „цитатник-корректор“).
* кнопка предпросмотра в почте.
* компактные кнопки Google Plus (кроссдоменные технологии)
* Небольшие изменения в стилях ZenComment — их версия (2.16) встроена и в HabrAjax. Его удобно использовать вместе со скриптами, но сделано всё для того, чтобы стили и скрипты были независимы. Необходимые (позарез необходимый минимум) стили прописаны в скриптах и занимают уйму (250) строк.

Да, и насчёт скрипта — к тем, кто им уже пользуется — просьба поучаствовать в опросе — »В каком браузере вы используете скрипт HabrAjax?". Он поможет увидеть картину того, в каких браузерах и ОС работает скрипт. Если есть 2 разных компьютера — пишите 2 голоса в опросе (из разных мест). Имеет значение и аддон для Firefox — ведь оказалось, что более гибкий аддон — Scriptish, потому что он позволяет написать кроссбраузерный многострочный текст директив метаданных (это будет освещено в статье «Чтение многострочных данных в JS»).

Автор: spmbt

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js