Підсвітка синтаксису за допомогою javascript

Опубліковано: 2008-11-27   08:14:38

BlogЯк Ви могли помітити в моєму блозі всі блоки програмного коду мають підсвітку синтаксису, що значно спрощує його перегляд. Чесно кажучи не вигадав іншого використання, як для якихось сайтів та блогів з програмування, однак сама концепція може стати в нагоді не тільки для таких проектів.

Теорія

Яким чином можна надати будь-якому елементу 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 та поштову розсилку.

Теги: javascript
Коментарі: 9
 

Коментарі:

podarok2008-11-28 10:23:10 :

Ей.. девелопер...

Всі лінки - переходи з РСС на тебе ведуть лише на одну сторінку.. і це не сторінка статті, на яку є бажання перейти...

Крім того - форма коментування в 3 файрфоксі глючить

 
GrAndSE2008-11-28 21:48:31 :

Лінки виправив. Вірніше виправив їх розбір. Справ то було в одному рядку. А от не можу зрозуміти, що за глюки в формі коментування не знаю - сам користуюсь третім вогнелисом.

 
virua2008-12-24 00:18:12 :

Легка версія скрипта для підсвітки коду під руками звичайно не зашкодить. Правда, мені подобається highlight.js від Івана Сагалаєва. Зараз вже є 5.0 версія. Хочу поставити собі на блозі. Дуже потужна штука:

* при завантаженні "highlight.js" вам не обов'язково брати код з підтримкою усіх мов програмування, можна брати лише файл з вибраними мовами (що зменшить загальний розмір).

* скрипт розуміє багато мов програмування;

* може автоматично визначати поточну мову коду;

* на сайті є хороша російськомовна документація, яка дозволить програмісту відносно легко додати мову програмування чи розмітки, якої не достає;

* є купа стильових тем на різні смаки для зображення підсвітки коду: Default, Dark, FAR, IDEA, Sunburst, Zenburn, Visual Studio, Ascetic;

* і на останок є плагін до WordPress'у.

 
GrAndSE2008-12-24 09:46:21 :

Дякую за розгорнутий коментар.

Варіант з highlight.js я також розглядав. Однак пакунок з замовленими мною мовами програмуваннями важить 30+ Кб. Все ж таки порівнювати 2 та 30+. Різниця в 15 разів мене не влаштовує.

Самостійній вибір мови програмування? Здавалося б чудово, проте наскільки мені відомо комюніті продовжує боротьбу за точність розпізнавання деяких мов.

Ну і останнє те, що в мене блог не на wordpress :)

Однак російськомовна документація та широкий набір мов роблять його досить гарним рішенням в багатьох випадках.

 
GrAndSE2008-12-24 09:47:50 :

Та й взагалі цікаво було самому спробувати вирішити проблему. :) just for fun ;)

 
virua2008-12-24 12:13:37 :

Тут на кону стоять можливості проти розміру. Тому вибір звичайно ж в кожного буде свій.

Щоб прискорити процес при використанні highlight.js, можна перерахувати у виклику функції initHighlightingOnLoad лише ті мови (чи мову), які використовуються в тексті:

type="text/javascript">

hljs.initHighlightingOnLoad('html', 'css');

Таким чином highlight.js динамічно підвантажує відповідні мовні файли і важить менше, ніж з набором за умовчанням.

> Самостійній вибір мови програмування? Здавалося б чудово, проте наскільки мені відомо комюніті продовжує боротьбу за точність розпізнавання деяких мов.

Це, imho, лише як можливість для лінивих ;). Сам розробник радить прописувати мову вручну. Але й без цього я б так і робив. Це не проблема.

 
GrAndSE2008-12-24 15:09:56 :

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

 
virua2008-12-24 15:40:52 :

> Подивимось що з цього вийде.

Вийде потужний скрипт, який за байтами буде на рівні з highlight.js :)))))

 
GrAndSE2008-12-24 18:33:54 :

Ні-ні-ні, Девід Блейн, все так просто :)

 

Додати коментар

user

email

url

text

Повідомляти про новікоментарі