Лучше поздно, чем никогда. Прошедшей ночью я наконец выложил очередную версию highlight.js, в которой появилось много приятных добавлений, некоторые из которых были готовы ещё полгода назад.
Новые языки
- Андрей Фёдоров описал язык Lua
- давний контрибьютор хайлайтера Пётр Леонов описал язык конфигурации Nginx
- Владимир Москва описал TeX
Таким образом, сейчас 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
, которая сама вешалась на событие загрузки страницы, после чего искала блоки кода и раскрашивала их. У этого подхода было несколько неудобств:
- постоянно возникал вопрос "как подсветить код, подтянутый потом через ajax"
- блоки кода узнавались только в виде
<pre><code>..</code></pre>
(хотя это, по правде говоря, фича, потому что это рекомендует HTML5) - момент инциализации был непредсказуем, если на странице делалась другая инициализация средствами какого-нибудь js-фреймворка
Теперь всё это можно контролировать. Например с использованием jQuery хайлайтинг может выглядеть так:
$(document).ready(function() {
$('div.pre').each(function(i, e) {hljs.highlightBlock(e, ' ')});
});
В функцию highlightBlock
передаётся DOM-элемент с текстом кода, а вторым опциональным параметром — замена для символов табуляции. Эту же функцию можно использовать в любой момент для раскраски кода в любой момент жизни страницы.
Плагин WordPress
В этой версии я отказался от поддержки плагина к WordPress, по той простой причине, что мой блог теперь работает на собственном движке, и этот плагин мне даже отладить не на чем. Будет очень хорошо, если кто-нибудь его поддержку подхватит, старый код плагина по прежнему доступен в Базаре, и по идее, должен работать прямо в таком виде.
Правда, про этот плагин мне писали, что он возможно страдает уязвимостью безопасности, так как не проверяет nonce'ы. У меня не хватило здоровья разобраться в том, что это, реально ли есть дыра, и как её починить.
Комментарии: 13
Отлично! Хотя у меня последнее время автодетект работать не хочет. Обновлюсь, посмотрю.
SQL отнюдь не обязан начинаться с оператора и заканчиваться точкой с запятой. Может стоять комментарий или прагма (которую тоже неплохо бы расцветить). Но главная бяка всех "умных" редакторов - невозможность понять совмещение языков в одном тексте. Например, связку PHP + HTML + SQL + JavaScript не может правильно разобрать ни один редактор. :(
Впрочем это мелкие придирки. Работа в целом хорошая. Только добавить бы примеров использования в разных ситуациях - просто на странице, в окне ввода автоматом, в окне ввода но только по требованию, особенности подключения к разным форумам и блогам...
Кстати, введение динамического "предпросмотра" написанного в этот блог - когда оно сделано? Ужас! Невозможно писать в броузере! Пришлось временно отключить скрипты на странице. Впрочем, подталкивание читателей к написанию заметок не в броузере, а в блокноте способствует предотвращению его пропажи при сбоях OpenID и других проблемах с блогом.
Это не только редактор, это человек распознать не сможет. Узнайте уже про MVC и никогда так не пишите.
Комментарии highlight.js понимает. А вот что такое "прагма" в SQL, я просто не знаю. Сделаете патчик? Это примерно вот здесь в sql.js. Надо добавить новый подрежим в contains и описать его по аналогии с другими или по документации.
highlight.js понимает js и css внутри HTML. До остального руки не доходили, да и сложность там растёт несоразмерно пользе.
человек распознает без проблем. В mvc не обязательно что одному языку один файл. Пример - ror models ruby+find_by_sql sql, routes ruby+regexps, erb+html и тд. Но больше 2 языков в mvc редкость.
пардон, тот что выше это я. ошибся полем
Не знаю как насчёт SQL, но вот связку из PHP+CSS+HTML+JS colorer (плагин к фару, и вообще движок раскраски) понимает легко.
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 finally released
when he'd refactored
let the new mode appear OR allow the new mode to appear
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. : )
Спасибо. По поводу 'публичности' highlightBlock. Хотелось бы ещё и findCode тоже сделать публичным.
А стоит ли? Функция довольно ограниченная, и вообще вся эта штука присутствут в хайлайтере только для того, чтобы он работал из коробки независимо от js-фреймворков. А если тебе нужно делать что-то над DOM'ом, то лучше взять любой фреймворк и делать это его средствами.
Nick Lutsiuk, thanks!
Fixed everything. Though the last one was not a genuine mistake but just an artifact left from reformulation.
32 языка это уже не шутки !) спасибо) а в каком направлении вы его дальше развивать хотите?) или это процесс стихийный? :)
На мой личный взгляд, больше всего хайлайтеру нужно отлаживать эвристику. Но на практике я живу контрибуциями: что люди присылают, тем и развивается.