Підсвітка синтаксису за допомогою javascript
Як Ви могли помітити в моєму блозі всі блоки програмного коду мають підсвітку синтаксису, що значно спрощує його перегляд. Чесно кажучи не вигадав іншого використання, як для якихось сайтів та блогів з програмування, однак сама концепція може стати в нагоді не тільки для таких проектів.
Теорія
Яким чином можна надати будь-якому елементу html сторінки певного кольору чи інші характеристики? Звичайно ж за допомогою css. Найпростіший варіант, який здається вірним і з точки зору валідності та семантики - використання html-тега span.
Тепер залишається автоматично огорнути елементи. Саме тут стане корисним javascript та його регулярні вирази. За допомогою функції replace будемо "огортати" всі входження ключових слів та спеціальних символів в span з відповідним стилем
Залишається єдина деталь: мусимо замінювати ключові слова тільки там, де це необхідно. Для цього скористаємось контейнером div задавши йому клас code. Для того, щоб отримати всі елементи з даним класом я користуюсь однією з функцій перелічених мною раніше.
Перейдемо до практики
Спершу опишу всі стилі css якими я скористався. Це файл highlight.css:
.code {
background: #eee;
border: #333 1px dashed;
padding: 10px;
margin-top: 5px;
}
.str { color: red }
.func { color: blue }
.comm { color: orange }
.kwrd { font-weight:bold }
.str span { color: red; font-weight: normal }
.comm span { color: orange; font-weight: normal }
</div>
Ну тепер настав час для javascript:
<div class="code">function highlight(code) {
var keywords = /(([^a-z0-9$_])(var|function|default|typeof|new|return|if|for|in|while|break|do|continue|switch|case)([^a-z0-9$_]))/gi,
brackets = /({|}|]|[||)/gi,
strings = /((".*?")|('.*?'))/g,
functions = /([a-z\_$][a-z0-9_]*)(/gi,
comments = /(//.*(
|
|$))/g;
return code.trim().replace(strings, '<span class="str">$1</span>').replace(keywords, '<span class="kwrd">$1</span>').replace(brackets, '<span class="kwrd">$1</span>').replace(comments, '<span class="comm">$1</span>').replace(functions, '<span class="func">$1</span>(').replace(/ /g, ' ');
}
window.onload = function() {
var code = getElementsByClass("code");
for (var e = 0; e < code.length; e++)
code[e].innerHTML = highlight(code[e].innerHTML);
}
Код є доволі прозорим, однак дам декілька коментарів.
В функції highlight спочатку я описую п'ять типів елементів через регулярні вирази: ключові слова (keywords), дужки (brackets), рядки (strings), функції користувача (functions) та коментарі (coments). Далі, користуючись функцією replace огортаю елементи що відповідають описаним регулярним виразам в відповідні span'и.
Далі в коді я описую функцію, що буде виконана при завантаженні документу. Ця анонімна функція вибирає всі елементи з класом code за замінює їх вміст (innerHTML) результатом роботи функції highlight.
Як ви бачите все доволі просто. Залишається підключити всі необхідні файли, а саме white-utils.js (в якому зібрані утилітарні функції, хоча використовується з них зараз лише одна) та highlight.js.
Інші шляхи
Було б нечесно назвати себе першопрохідцем такої справи. Взагалі то моє рішення базується на одному записі з блога на хабрі. На жаль, скрипти наведені за тим посиланням відмовились коректно працювати з двигунцем мого блога. Тому довелось його вдосконалювати.
Є вже готові бібліотеки, наприклад highlight.js чи Codepress. Однак їх розмір значно перевищує розмір мого коду, разом з усіма утилітарними функціями (враховуючи те, що взагалі то з 2 Кб підключений функцій я використовую лише одну єдину, то можна розмір ще більше скоротити і вийде приблизно 1 Кб). Мене такі результати влаштовують. Думаю, що в подальшому буду розвивати цей модуль для надання йому більшого функціоналу. Приєднуйтесь якщо бажаєте. Пишіть в коментарях чи мені на пошту (grandse(at)ukr.net) про виявлені помилки та додатки. Буду вдячний за будь-які відгуки.
Сподіваюсь матеріал стане в нагоді.
P.S.: Приношу свої вибачення за паузу в публікаціях, оскільки прийшов майже тиждень з часу останньої замітки і за можливі подальші прогалини. Зараз я доволі сильно захворів тому не практично не можу працювати. Як тільки моє здоров'я покращиться буду писати більше: ідей у мене для публікацій є ще багато, так що кому цікаво читати не забувайте про підписку через rss та поштову розсилку.
Коментарі:
Ей.. девелопер...
Всі лінки - переходи з РСС на тебе ведуть лише на одну сторінку.. і це не сторінка статті, на яку є бажання перейти...
Крім того - форма коментування в 3 файрфоксі глючить
Лінки виправив. Вірніше виправив їх розбір. Справ то було в одному рядку. А от не можу зрозуміти, що за глюки в формі коментування не знаю - сам користуюсь третім вогнелисом.
Легка версія скрипта для підсвітки коду під руками звичайно не зашкодить. Правда, мені подобається highlight.js від Івана Сагалаєва. Зараз вже є 5.0 версія. Хочу поставити собі на блозі. Дуже потужна штука:
* при завантаженні "highlight.js" вам не обов'язково брати код з підтримкою усіх мов програмування, можна брати лише файл з вибраними мовами (що зменшить загальний розмір).
* скрипт розуміє багато мов програмування;
* може автоматично визначати поточну мову коду;
* на сайті є хороша російськомовна документація, яка дозволить програмісту відносно легко додати мову програмування чи розмітки, якої не достає;
* є купа стильових тем на різні смаки для зображення підсвітки коду: Default, Dark, FAR, IDEA, Sunburst, Zenburn, Visual Studio, Ascetic;
* і на останок є плагін до WordPress'у.
Дякую за розгорнутий коментар.
Варіант з highlight.js я також розглядав. Однак пакунок з замовленими мною мовами програмуваннями важить 30+ Кб. Все ж таки порівнювати 2 та 30+. Різниця в 15 разів мене не влаштовує.
Самостійній вибір мови програмування? Здавалося б чудово, проте наскільки мені відомо комюніті продовжує боротьбу за точність розпізнавання деяких мов.
Ну і останнє те, що в мене блог не на wordpress :)
Однак російськомовна документація та широкий набір мов роблять його досить гарним рішенням в багатьох випадках.
Та й взагалі цікаво було самому спробувати вирішити проблему. :) just for fun ;)
Тут на кону стоять можливості проти розміру. Тому вибір звичайно ж в кожного буде свій.
Щоб прискорити процес при використанні highlight.js, можна перерахувати у виклику функції initHighlightingOnLoad лише ті мови (чи мову), які використовуються в тексті:
type="text/javascript">
hljs.initHighlightingOnLoad('html', 'css');
Таким чином highlight.js динамічно підвантажує відповідні мовні файли і важить менше, ніж з набором за умовчанням.
> Самостійній вибір мови програмування? Здавалося б чудово, проте наскільки мені відомо комюніті продовжує боротьбу за точність розпізнавання деяких мов.
Це, imho, лише як можливість для лінивих ;). Сам розробник радить прописувати мову вручну. Але й без цього я б так і робив. Це не проблема.
Можливості проти розміру. Я розумію, що моя реалізація значно поступається тому ж highlight.js, проте мені її цілком вистачає, хоча й хочу трошки розширити свою бібліотечку. Подивимось що з цього вийде.
> Подивимось що з цього вийде.
Вийде потужний скрипт, який за байтами буде на рівні з highlight.js :)))))



