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

Новые языки

Таким образом, сейчас highlight.js поддерживает ни много, ни мало, 32 языка!

Фиксы к существующим языкам

Существующие языки тоже получили некоторое количество багфиксов и улучшений. Подробно про них можно прочитать в базарном логе, но про два языка стоит сказать отдельно.

Лорен Сегал довольно глубоко переработал описание Руби и добавил туда раскраску инлайновой документации YARD (собственного изобретения). По его совету у режимов языка появился новый атрибут — displayClassName, который подставляется в генерируемую разметку вместо className. Необходимость в этом возникла, когда он вынес определение заголовков функций в отдельный режим, который пришлось назвать по-другому — "ftitle" вместо "title". Чтобы не сломать наложение стилей, можно было поступить двояко: либо во всех стилевых файлах рутинно добавлять ко всем селекторам .title ещё и .ftitle, либо сделать так, чтобы новый режим остался в раскладке как "title". Так и порешили.

Вторая переделка коснулась описания SQL, из-за чего я как раз и засиделся ночью допоздна :-). SQL всегда был очень "жадным" языком с точки зрения автоопределения. Например вот такой невинный фрагмент на Питоне определялся как SQL:

from django.utils import translation
translation.activate(language)

Здесь нужен небольшой экскурс в архитектуру хайлайтера.

Поскольку хайлайтеру не нужно исполнять программу на языке, а только его расцвечивать, синтаксис языков не описывается полностью. С точки зрения хайлайтера язык — это некая большая масса текста с вкраплениями в него специальных конструкций вроде строк и комментариев, которые в хайлайтере называются "режимами". Режимы определяют, какие ключевые слова в них могут встречаться. У большинства языков все ключевые слова определены в самом базовом режиме, обозначающем ту самую большую массу текста за пределами строк, комментариев и прочих специальных вещей.

SQL — как раз такой. Проблема с ним в том, что у него ключевых слов много — 217 штук (у Питона, например, всего 37). Это приводит к такому эффекту, что ключевые слова SQL легко встретить в других программах, где эти слова используются как имена переменных. В приведённом выше фрагменте к ключевым словам SQL относятся например "from", "translation" и "language". В то время, как от Питона там только "from" и "import". 4 вхождения против 2 — вот вам и SQL.

Чтобы это побеждать, я применяю всё время один и тот же способ. Представление языка меняется с "кучи свободного текста с вкраплениями режимов" на "весь язык состоит только из конкретных режимов". Надо только придумать, как это сделать малой кровью. Поразмыслив, я подумал, что SQL состоит по-крупному только из двух вещей: комментариев и SQL-операторов, и уже операторы содержат различные ключевые слова. Операторы же начинаются с небольшого количества зарезервированных слов ("select", "insert", "alter" и т.д. — всего 22 штуки), а заканчиваются точкой с запятой или концом файла.

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

Библиотечность

Я немного порефакторил код инициализации хайлайтера, и теперь его стало удобней использовать как библиотеку, а не только как самостоятельное приложение. Раньше он настаивал на том, чтобы быть проинициализированным вызовом initHighlightingOnLoad, которая сама вешалась на событие загрузки страницы, после чего искала блоки кода и раскрашивала их. У этого подхода было несколько неудобств:

Теперь всё это можно контролировать. Например с использованием jQuery хайлайтинг может выглядеть так:

$(document).ready(function() {
  $('div.pre').each(function(i, e) {hljs.highlightBlock(e, '    ')});
});

В функцию highlightBlock передаётся DOM-элемент с текстом кода, а вторым опциональным параметром — замена для символов табуляции. Эту же функцию можно использовать в любой момент для раскраски кода в любой момент жизни страницы.

Плагин WordPress

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

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

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

  1. Vooon

    Отлично! Хотя у меня последнее время автодетект работать не хочет. Обновлюсь, посмотрю.

  2. grey3.livejournal.com

    SQL отнюдь не обязан начинаться с оператора и заканчиваться точкой с запятой. Может стоять комментарий или прагма (которую тоже неплохо бы расцветить). Но главная бяка всех "умных" редакторов - невозможность понять совмещение языков в одном тексте. Например, связку PHP + HTML + SQL + JavaScript не может правильно разобрать ни один редактор. :(

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

    Кстати, введение динамического "предпросмотра" написанного в этот блог - когда оно сделано? Ужас! Невозможно писать в броузере! Пришлось временно отключить скрипты на странице. Впрочем, подталкивание читателей к написанию заметок не в броузере, а в блокноте способствует предотвращению его пропажи при сбоях OpenID и других проблемах с блогом.

  3. anonymous

    Например, связку PHP + HTML + SQL + JavaScript не может правильно разобрать ни один редактор.

    Это не только редактор, это человек распознать не сможет. Узнайте уже про MVC и никогда так не пишите.

  4. Ivan Sagalaev

    SQL отнюдь не обязан начинаться с оператора и заканчиваться точкой с запятой. Может стоять комментарий или прагма (которую тоже неплохо бы расцветить).

    Комментарии highlight.js понимает. А вот что такое "прагма" в SQL, я просто не знаю. Сделаете патчик? Это примерно вот здесь в sql.js. Надо добавить новый подрежим в contains и описать его по аналогии с другими или по документации.

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

    highlight.js понимает js и css внутри HTML. До остального руки не доходили, да и сложность там растёт несоразмерно пользе.

  5. anonymouse

    Это не только редактор, это человек распознать не сможет. Узнайте уже про MVC и никогда так не пишите.

    человек распознает без проблем. В mvc не обязательно что одному языку один файл. Пример - ror models ruby+find_by_sql sql, routes ruby+regexps, erb+html и тд. Но больше 2 языков в mvc редкость.

  6. homakov

    пардон, тот что выше это я. ошибся полем

  7. Kildor

    Не знаю как насчёт SQL, но вот связку из PHP+CSS+HTML+JS colorer (плагин к фару, и вообще движок раскраски) понимает легко.

  8. Āudioslave ᵝ « ... »

    Спасибо. По поводу 'публичности' highlightBlock. Хотелось бы ещё и findCode тоже сделать публичным.

  9. Ivan Sagalaev

    Хотелось бы ещё и findCode тоже сделать публичным.

    А стоит ли? Функция довольно ограниченная, и вообще вся эта штука присутствут в хайлайтере только для того, чтобы он работал из коробки независимо от js-фреймворков. А если тебе нужно делать что-то над DOM'ом, то лучше взять любой фреймворк и делать это его средствами.

  10. Рома

    32 языка это уже не шутки !) спасибо) а в каком направлении вы его дальше развивать хотите?) или это процесс стихийный? :)

  11. Ivan Sagalaev

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

Добавить комментарий