На сайтах, посвященных веб-разработке нужна подсветка кода, чтобы материал лучше воспринимался читателем. В этой статье я расскажу о двух способах ее внедрения на примере CKEditor и ModX. Подсветка у нас появится не только на самом сайте, но и в админке.
Наиболее простым вариантом является подключение 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>
Ну, и для оптимизации скорости загрузки сайта разносим места подключения по странице:
С в фронтендом закончили, теперь перейдем к вопросу: как добавлять код в админке?
Это делается очень просто, если у вас используется 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. Скептики скажут, что это повышает нагрузку на сервер, но ее можно свести к минимуму подключив полностраничное кеширование, что и делается на сайтах с большой посещаемостью.