Пример использования syntaxhighlighter в yii2

03.11.2015

Частенько в блогах может понадобиться возможность подключить подсветку вставляемого кода. И как правило базовая комплектация тега "pre" или "code" начинает не устраивать.

Как один из вариантов можно поставить себе интересный плагин syntaxhighlighter для редактора TinyMCE. В принципе использование syntaxhighlighter отдельно от TinyMCE так же возможно, просто Вам нужно будет вручную обернуть код в тег "pre" и написать нужный brush (кисть) для подсветки.

И так, допустим мы пользуемся редактором TinyMCE, тогда поставим для него плагин вставки кода (если вы пользутетесь другим редактором или вовсе без него, пропускаем этот шаг):

  1. Идем СЮДА и скачиваем сам плагин.
  2. Распаковываем содержимое архива в папку plugins редактора TinyMCE. (у меня например это vendor\....\yii2-tinymce\vendors\tinymce\js\tinymce\plugins\). В результате будет структура: vendor\....\yii2-tinymce\vendors\tinymce\js\tinymce\plugins\sh4tinymce\...
  3. Если у Вас редактор TinyMCE на русском, тогда нужно зайти в папку с языками плагина vendor\....\yii2-tinymce\vendors\tinymce\js\tinymce\plugins\sh4tinymce\langs\ и дублировать файл en.js после чего переименовать его в ru.js (можно перевести, а можно и оставить содержимое)
  4. Добавляем sh4tinymce плагин при инициализации TinyMCE (в секцию plugins и для удобства в toolbar).  Пример для js (аналогично делается и для extension TinyMCE для yii2):
    Подключение плагина sh4tinymce в TinyMCE
  5. Если требуется обновляем кэш (можно почистить в папке asset кэш для TinyMCE).

И так плагин для TinyMCE установили. Как он выглядит и работает, можно посмотреть здесь.

Чтобы подсветка работала на frontend части сайта, при просмотре статьи, нам нужно:

  1. Скачиваем SyntaxHighlighter.
  2. Открываем архив и переходим в папку scripts. Откуда копируем: shCore.js, shAutoloader.js и все необходимые brushes (кисти). Можно скопировать только те кисти которые Вы используете. Все это дело копируем в свой проект (например папку js)
  3. Переходим в архиве в папку styles и копируем желаемую тему. Например для темы Midnight копируем: shCoreMidnight.css и shThemeMidnight.css (принцип одинаков для всех тем). Стили помещаем в наш проект например в папку css.
  4. Далее создаем AssetBundle, с помощью которого мы сможет подключать подсветку кода только там, где она используется. И так, создаем класс frontend\assets\AssetHG.php с содержимым:

    <?php
    
    namespace frontend\assets;
    
    use yii\web\AssetBundle;
    
    class AssetHG extends AssetBundle
    {
        public $basePath = '@webroot';
        public $baseUrl = '@web';
    
        public $css = [
            'css/hg/shCoreRDark.css',
            'css/hg/shThemeRDark.css',
        ];
        public $js = [
            'js/hg/shCore.js',
            'js/hg/shAutoloader.js',
        ];
        public $depends = [
            'yii\web\YiiAsset',
            'yii\bootstrap\BootstrapAsset',
        ];
    
        private $brushes = [
            [ ['php'],  '/js/hg/brushes/shBrushPhp.js'],
            [ ['css'],  '/js/hg/brushes/shBrushCss.js'],
            [ ['js'],   '/js/hg/brushes/shBrushJScript.js'],
            [ ['bash'], '/js/hg/brushes/shBrushBash.js'],
            [ ['sql'],  '/js/hg/brushes/shBrushSql.js'],
            [ ['xml', 'html'], '/js/hg/brushes/shBrushXml.js'],
        ];
    
        public static function register($view, $content = null) {
    
            if($content) {
                $AssetHG = new AssetHG();
                if(!empty($AssetHG->brushes)) {
                    $brushes = array();
                    foreach ($AssetHG->brushes as $key => $brush) {
                        foreach ($brush[0] as $b) {
                            if (preg_match('/<pre.*?class=".*?brush:.*?'.$b.'.*?"/i', $content)) {
                                $brushes[] = "'". implode(' ', $brush[0]) ." $brush[1]'";
                                break;
                            }
                        }
                    }
                    if (!empty($brushes)) {
                        $brushes = implode(',', $brushes);
                        parent::register($view);
                        $view->registerJs("SyntaxHighlighter.autoloader($brushes);SyntaxHighlighter.all();");
                    }
                }
            } else {
                parent::register($view);
            }
        }
    }
    

    После чего изменяем пути к brushes, js и css на свои. (js/hg/, css/hg/,  /js/hg/brushes/ нужно свои подставить)

  5. Далее заходим в view статьи и добавляем в начало:

    use frontend\assets\AssetHG;
    
    AssetHG::register($this, $item->text);
    Где $item->text это текст статьи, в котором наш AssetBundle будет искать наличие использования подсветки кода.

Принцип работы очень прост: Мы перегружаем метод register чтобы добавить проверку использования в тексте статьи подсветки кода. Если мы не используем в статье подсветку, зачем тогда грузить весь javascript код и выполнять его? Далее метод находит используемые кисти в статье и именно их подгружает для подсветки. Ведь зачем грузить все 20 кистей, если мы используем в статье только одну кисть (например только для php). Если не передать второй параметр $item->text, тогда AssetBundle подключится в любом случае.

Вот и все. Проверяем.

comments powered by HyperComments