Лучше поздно, чем никогда. Прошедшей ночью я наконец выложил очередную версию 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'ы. У меня не хватило здоровья разобраться в том, что это, реально ли есть дыра, и как её починить.

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

  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. Nick Lutsiuk

    Your English is fine, you don't have to put too much effort to improve on that. But here's my bit of nitpicking:

    Last night I've finally released

    Last night I finally released

    when he's refactored

    when he'd refactored

    let the new mode to appear

    let the new mode appear OR allow the new mode to appear

    all languages contains only of

    all the language consists only of OR all the language contains only

    Anyway, a couple more blog posts like this and you're going to have to put away that apologetic paragraph at the bottom. : )

  9. Āudioslave ᵝ « ... »

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

  10. Ivan Sagalaev

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

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

  11. Ivan Sagalaev

    Nick Lutsiuk, thanks!

    Fixed everything. Though the last one was not a genuine mistake but just an artifact left from reformulation.

  12. Рома

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

  13. Ivan Sagalaev

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

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