Как добавить подсветку кода на сайт. 2 способа на примере ModX

На сайтах, посвященных веб-разработке нужна подсветка кода, чтобы материал лучше воспринимался читателем. В этой статье я расскажу о двух способах ее внедрения на примере CKEditor и ModX. Подсветка у нас появится не только на самом сайте, но и в админке.

Подсветка кода с помощью javascript

Наиболее простым вариантом является подключение javascript-библиотеки, которая делает все на стороне клиента. То есть прямо в браузере после загрузки страницы. Для этой цели я воспользуюсь библиотекой highlight.js, которая поддерживает 137 языков программирования, а также имеет 65 стилей подсветки на выбор.

Итак, качаем дистрибутив и, согласно документации, подключаем на страницу сайта скрипт и выбранный файл стилей:

html<link rel="stylesheet" href="/path/to/styles/default.css">
<script src="/path/to/highlight.pack.js"></script>
<script>hljs.initHighlightingOnLoad();</script>

Можно также подключить highlight.js ничего особо не качая, с cdn серверов:

html<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.9.1/styles/default.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.9.1/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>

Ну, и для оптимизации скорости загрузки сайта разносим места подключения по странице:

  • стиль в <head>
  • js-скрипты в конец <body>

С в фронтендом закончили, теперь перейдем к вопросу: как добавлять код в админке?

Это делается очень просто, если у вас используется CKEditor. В базовой конфигурации редактора код вставить проблематично, но среди обширного списка его дополнений есть замечательный плагин codesnippet. Его мы и используем.
Качаем плагин и находим папку, в которую установлен CKEditor для админки сайта. У ModX она находится здесь: manager/assets/components/ckeditor/
Находим внутри папку plugins и заливаем туда скачанный плагин. Для ModX путь должен получится такой:
manager/assets/components/ckeditor/ckeditor/plugins/codesnippet/

Осталось подключить его в конфиге CKEditor'а (здесь - ckeditor/ckeditor/config.js).
Для этого допишем в строку config.extraPlugins имя плагина через запятую.

javascriptconfig.extraPlugins = 'base64image,codesnippet';

Если такой строки в конфиге нет, ее нужно создать.

На панели инструментов редактора появится кнопка «Вставить сниппет»

На панели инструментов редактора появится кнопка Вставить сниппет

Нажав на нее попадем в окно вставки кода. Следует выбрать язык для подсветки и вставить или написать кусок кода.

Попадем в окно вставки кода

Сниппет из коробки интегрирован именно с highlight.js, так что код будет подсвечен даже у вас в редакторе:

Код подсвечен даже у вас в редакторе

Вот и все, посветка с помощью javascript реализована.

Серверная подсветка кода

В случае использования подсветки кода с помощью javascript, браузеру необходимо сначала загрузить всю страницу и скрипты (т.е. посетитель видит неподсвеченный код по мере загрузки), и только потом приступить к подсветке. Это порождает визуальный лаг, особенно заметный на медленных соединениях. К тому же, никто не застрахован от ошибки яваскрипта на каком-нибудь экзотическом (или не очень) устройстве, из-за чего код останется неподсвеченным вовсе. Добавьте сюда параноиков с отключенным яваскриптом и становится понятно, что мы не можем контролировать качество подсветки кода при использовании яваскрипта.

Чтобы этого избежать используют подсветку кода на стороне сервера (server-side). В этом случае на страницу необходимо включить только css-стили подсветки, остальное делается при формировании страницы. Этот способ мы здесь и реализуем.

Для серверной подсветки среди плагинов CKEditor тоже есть решение, но мы пойдем своим путем.

Для серверной обработки мы используем … тоже highlight.js, но портированный на php. Называется эта библиотека highlight.php, cкачать ее можно нажав на кнопку:

Скачать highlight.php c GitHub

Качаем архив с библиотекой, распаковываем и находим в нем папку Highlight, в ней содержится все что нам необходимо.
Заливаем содержимое найденной папки по следующему пути core/components/Highlight/

Теперь создаем новый сниппет-модификатор, назовем его highlight.

И наполняем его моим кодом:

php/**
* @name highlight (Code Highlight modifier)
* @author Optim1zer (http://optimizer.ru)
* @uses A port of highlight.js to PHP (https://github.com/scrivo/highlight.php)
* @uses PHP 5.3+
*
* Модификатор для подсветки кода в переданном тексте
* Ищет блоки, заключенные в <pre><code> и подсвечивает их как highlight.js
*/

// пропускаем обработку если нет тега <pre> 

if (stripos($input, '<pre>') === false) {
    return $input;
}

$path = $modx->getOption('core_path').'components/Highlight/';

require_once($path."Autoloader.php");
spl_autoload_register("Highlight\\Autoloader::load");

$hl = new Highlight\Highlighter();

// Если не переопределить выбрасывается исключение если анализируемый код содержит неподдерживаемый символ для одного из языков (например '<', для json и sql)

$hl->setAutodetectLanguages(array("xml", "javascript", "php"));

$output = preg_replace_callback('~<pre>\s*<code[^>]*?(?:class="language-(\w+)")?>(.*?)</code>\s*</pre>~is', function($p) use ($hl) {
    $lang = $p[1];
    $code = html_entity_decode($p[2], NULL, 'UTF-8');
    if (empty($lang)) {
        $r = $hl->highlightAuto($code);
    } else {
        $r = $hl->highlight($lang, $code);
    }
    return '<pre><code class="hljs '.$r->language.'">'.$r->value.'</code></pre>';
}, $input);

return $output;

Скачать код сниппета

После этого нам остается только подключить файл стилей от highlight.js. Например, этот:

html<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.9.1/styles/default.min.css">

И, конечно, использовать модификатор в шаблоне на контенте:

[[*content:highlight]]

Для CKEditor'a в админке мы используем тот же codesnippet, с нативной поддержкой highlight.js, подключение которого описано в предыдущем разделе. Таким образом, для админки ничего не меняется и подсветка кода у вас там тоже сохраняется.

Итог: Мы ушли от подсветки кода на стороне клиента и перешли к простому html-коду, подсвеченному с помощью правил css, что гарантированно дает нам верное отображение кода во всех браузерах, даже с отключенным javascript. Скептики скажут, что это повышает нагрузку на сервер, но ее можно свести к минимуму подключив полностраничное кеширование, что и делается на сайтах с большой посещаемостью.

15 ноября 2015