Была у меня давняя отдаленная мечта — иметь подсветку синтаксиса кода в блоге. Причем мне категорически не нравится идея делать это так, как это обычно делается: с помощью некой отдельной тулзы, которая кушает код и выдает раскрашенный HTML (мне для этого, наверное, даже тулзы бы не понадобилось, потому что экспортировать рсцвеченный код умеет тот же SciTE). Как-то все это слишком много телодвижений отнимает. Кроме того, я пользуюсь Markdown'ом, который escape'ит код всякими <
и >
за меня, а я всегда смотрю и редактирую просто чистые блоки кода, поэтому заменять его кашей тегов мне нравится еще меньше.
Мой идеальный подсветчик представлялся мне javascript'овой библиотечкой, которая ищет на странице код в определенных тегах и меняет его на разбитый на части HTML, а цвета и шрифты задаются в CSS.
История
Писать мне (а видимо, и не только мне) его очень не хотелось, потому что я, во-первых, ненавижу парсинг, а во-вторых не люблю искать чужие решения (именно искать, пользоваться-то ими я люблю, если они хорошие). Но вот вчера вечером я, что называется, "психанул", и решил попробовать написать, причем поставил себе условие, что если сразу не получится, много дней мучиться не буду: и так забот хватает.
Сначала полез поискать, не есть ли уже чего-нибудь похожего в наличии. Может плохо искал, но все что нашел — это "Compiler Generator In Javascript", в котором написано в частности:
AFAIK, this is the first publically availible parser generator in javascript.
Что подсказало мне, что тема не разработана :-). Сам этот генератор крут и наворочен, и я подумал, что даже просто определять грамматики для него — целая история. И после этого стал писать свой.
За вечер и полночи я придумал простенький формат грамматики, написал лексер и отладил подсветку двух языков — Python и HTML — в Firefox'е и IE (про Оперу не знаю, но должно быть нормально все). И оно работает! Оно даже отличает имена функций и классов Питона от других идентификаторов и разбирается, что в HTML атрибуты могут задаваться очень по-разному (attr="value"
, attr=value
, attr
). О, как!
"Но и это еще не все!" Помимо прочего мне надо было, чтобы вся эта благодать работала для всего кода, уже написанного в блоге, а ползать по всем статьям, выискивать код и говорить, каким языком он написан, мне было лениво. Поэтому я придумал эвристику, по которой язык кода определяется автоматически. Конечно, как любая эвристика, она неточна, но поскольку Питон, HTML и CSS, который я собираюсь вскоре добавить, синтаксически сильно различаются, она работает на удивление хорошо. А чтобы различать близкие языки, есть еще идеи, как это улучшить.
Как это работает, можно видеть например на этой странице.
Download и инструкция
Если кого это заинтересовало, то библиотечку можно брать и пользоваться: highlight.js.
Как водится, замечу, что это первая версия, написанная за несколько часов, а поэтому в ней есть баги, и она еще не много умеет.
Подключается очень просто, один файл и один инициализирующий вызов, например так:
<script type="text/javascript" src="highlight.js"></script>
<script type="text/javascript">
window.onload = function() {initHighlighting();}
</script>
Кодом на странице считаются блоки <pre><code>...</code></pre>
. Код этот размечается <span>
ами с разными классами ("keyword", "comment", "string", "attribute" ...). Полный список их можно найти в самом файлике, где в начале идет описание грамматик. Параметры называются "className".
Непосредственно оформление задается в стилях примерно так:
.comment {
color: gray;
}
.keyword {
font-weight: bold;
}
.python .string {
color: blue;
}
.html .atribute .value {
color: green;
}
Грамматики, как видно из файла, довольно неподробные. Это намеренно, потому что я не большой любитель сильно цветастых кодов. Однако, формат их довольно простой (как мне кажется :-) ), поэтому кому нравится, может дорисовать себе как угодно подробно. А я потом, как руки дойдут, сделаю страничку, где все это собирать буду.
Вот. После этого запойного программного спурта ощущаю теперь удивительный подъем вкупе с некоторой сонливостью. Давно меня так не торкало :-).
Комментарии: 14
Респект.
Пока особо без надобности, но в перспективе - пригодится.
Только цвета не очень понятные imho.
Темно-красный от черного не сильно отличим беглым взглядом.
Но это моё имхо. :)
Писать свой парсер - это конечно решение правильное.
Но я бы наверное решал такую задачу через потрошение внутренностей "RSDN Authoring Pack". У него уже есть готовый раскрасочный механизм на js для кучи языков. Там, кстати, вообще забавное решение - шаблон для ворда который дергает wsc-компонент, который подключает js во внешнем файле. Впервые увидел wsc на практике.
Вот хороший скрипт для подсветки кода: . Он правда не умеет самостоятельно определять язык, но зато "знаком" с бОльшим их количеством.
упс.. ссылочку на скрипт забыл
Да, в опере всё нормально. И в восьмёрке, и в девятке.
Довольно элегантно получилось.
В Сафари пусто.
Шикарная вещь! Надо будет попробовать сделать подсветку синтаксиса для Ruby и прикрутить к своему блогу
Было бы очень неплохо! Там наверняка понадобятся с меня разъяснения, как все это устроено, пишите мылом, расскажу.
Вот, ещё нашёл.
http://jquery.com/demo/code/
Making dp.SyntaxHighlighter for Python Not Suck про улучшение поддержки Python в dp.SyntaxHighlighter (про него Tomaz говорил)
Как известно, Google ворует все свои фичи у Яндекса. Так, увидев, что какой-то мужик из Яндекса написал подсветку синтаксиса на JavaScript'е, они почти через год выпустили свою
Кстати, ты просил сообщать об инсталляциях — с недавних пор стоит на knotes.ru (там, правда, кода пока что мало)
Пост от августа 2006 года, в Яндексе я тогда не работал. Да и сейчас highlight.js к Яндексу никакого отношения не имеет.
А гуглокодовский prettifier сделан в октябре того же года.