Как добавить подсветку синтаксиса в коде, используя Prism.js

Опубликовано: 01.09.2018

Подсветка синтаксиса стала своего рода стандартным вопросом для обсуждения и написания практических руководств на целом ряде сайтов. Доступно множество способов для включения подсветки синтаксиса в зависимости от того, какие языки вы используете и как хотите отображать свой код.

Долгое время автор этого руководства использовал для данной цели , поскольку он прост в настройке. Единственный недостаток в его применении кроется в том, что он не всегда создает выделение цветом для всех используемых вами элементов кода. Попытки переработать его на свой лад не увенчались успехом, поскольку с данным инструментом не так-то просто разобраться самостоятельно в плане внесения авторских правок в исходный его код.

Скачать исходники | Демонстрация

К счастью, не так давно был найден другой инструмент для подсветки синтаксиса под названием Prism.js , позволяющий расширять возможности подсветки синтаксиса и выделения блоков разметки кода в HTML и CSS силами достаточно простого плагина.

Взяв за основу данный инструмент и добавив в него поддержку нумерации строк и подсветку кода PHP , а также изменив несколько паттернов по работе с различными элементами разных языков, автор смог получить плагин, речь о создании и использовании которого и пойдет в этой статье.

Собираем плагин

Нам надо всего лишь добавить функцию и шорт-код в WordPress, чтобы мы могли легко включать подсветку кода в своих сниппетах, используя для этой цели слегка модифицированный скрипт Prism.js . Самый простой способ решить все задачи — это сделать отдельный плагин. В итоговом виде выглядеть это будет как-то вот так:

Начнем писать наш плагин с обязательных полей:

/* Plugin Name: Syntax Highlighter Plugin URI: http://wp.tutsplus.com/tutorials/plugins/adding-a-syntax-highlighter-shortcode-using-prism-js Description: Highlight your code snippets with an easy to use shortcode based on Lea Verou's Prism.js. Version: 1.0.0 Author: c.bavota Author URI: http://bavotasan.com */

Далее добавим наш шорт-код и обработаем этот код, чтобы быть уверенными в том, что он сработает в точно нужное нам время:

add_filter( 'the_content', 'sh_pre_process_shortcode', 7 ); /** * Functionality to set up highlighter shortcode correctly. * * This function is attached to the 'the_content' filter hook. * * @since 1.0.0 */ function sh_pre_process_shortcode( $content ) { global $shortcode_tags; $orig_shortcode_tags = $shortcode_tags; $shortcode_tags = array(); // New shortcodes add_shortcode( 'code', 'sh_syntax_highlighter' ); $content = do_shortcode( $content ); $shortcode_tags = $orig_shortcode_tags; return $content; } /** * Code shortcode function * * This function is attached to the 'code' shortcode hook. * * @since 1.0.0 */ function sh_syntax_highlighter( $atts, $content = null ) { extract( shortcode_atts( array( 'type' => 'markup', 'title' => '', 'linenums' => '', ), $atts ) ); $title = ( $title ) ? ' rel="' . $title . '"' : ''; $linenums = ( $linenums ) ? ' data-linenums="' . $linenums . '"' : ''; $find_array = array( '[', ']' ); $replace_array = array( '[', ']' ); return '</pre> <div class="syntax-highlighter" title=""> <pre><code class="language-' . $type . '">' . preg_replace_callback( '|(.*)|isU', 'sh_pre_entities', trim( str_replace( $find_array, $replace_array, $content ) ) ) . '</code></pre> </div> <pre> '; } /** * Helper function for 'sh_syntax_highlighter' * * @since 1.0.0 */ function sh_pre_entities( $matches ) { return str_replace( $matches[1], htmlentities( $matches[1]), $matches[0] ); }

Функция sh_pre_process_shortcode() нужная для того, чтобы синтаксис нашего шорт-кода был обработан до того, как все фильтры контента уберут текст, предложенный в WordPress по умолчанию. Вспомогательная функция отфильтрует наш код и заменит значения HTML -кода нашими соответственными значениями и параметрами.

Делаем запросы к скриптам и стилям

Чтобы наш плагин работал как следует, нам надо добавить парочку функций в наши файлы CSS и JS :

add_action( 'wp_enqueue_scripts', 'sh_add_js' ); /** * Load all JavaScript to header * * This function is attached to the 'wp_enqueue_scripts' action hook. * * @uses is_admin() * @uses is_singular() * @uses wp_enqueue_script() * @uses plugins_url() * * @since 1.0.0 */ function sh_add_js() { if ( sh_has_shortcode( 'code' ) ) { wp_enqueue_script( 'sh_js', plugins_url( 'js/sh.js', __FILE__ ), '', '', true ); wp_enqueue_style( 'sh_css', plugins_url( 'css/sh.css', __FILE__ ) ); } } /** * Check posts to see if shortcode has been used * * @since 1.0.0 */function sh_has_shortcode( $shortcode = '' ) { global $wp_query; foreach( $wp_query->posts as $post ) { if ( ! empty( $shortcode ) && stripos($post->post_content, '[' . $shortcode) !== false ) { return true; } } return false; }

К ним также надо сделать запросы, но только в том случае, если наш шорт-код используется в структуре контента конкретного поста. Поэтому нам надо ввести дополнительную функцию, которая будет проверять, есть ли в посте требуемый шорт-код.

Быстрая разметка тегами

Добавляем быстрый тег к нашему шорт-коду, это достаточно просто:

add_action( 'admin_enqueue_scripts', 'sh_add_quicktags' ); /** * Adds a syntax highlighter quicktag to the post editor * * This function is attached to the 'admin_print_footer_scripts' action hook. * * @since 1.0.0 */ function sh_add_quicktags( $hook ) { if( 'post.php' == $hook || 'post-new.php' == $hook ) wp_enqueue_script( 'sh_quicktag_js', plugins_url( 'js/quicktag.js', __FILE__ ), array( 'quicktags' ), '', true ); }

Вот что нам понадобится в файле quicktag.js :

QTags.SyntaxButton = function() { QTags.TagButton.call( this, 'syntax_highlighter', 'syntax highlighter', '', '[/code]' ); }; QTags.SyntaxButton.prototype = new QTags.TagButton(); QTags.SyntaxButton.prototype.callback = function( e, c, ed ) { var type, linenums, title, t = this; if ( t.isOpen( ed ) === false ) { type = prompt( 'Type (markup, php, css, javascript)', 'markup' ), title = prompt( 'Title (optional)' ), linenums = prompt( 'Line number (optional)' ); type = ( type ) ? ' type="' + type + '"' : ''; title = ( title ) ? ' title="' + title + '"' : ''; linenums = ( linenums ) ? ' linenums="' + linenums + '"' : ''; if ( type ) { t.tagStart = '1'; QTags.TagButton.prototype.callback.call( t, e, c, ed ); } } else { QTags.TagButton.prototype.callback.call( t, e, c, ed ); } }; edButtons[150] = new QTags.SyntaxButton();

Оформление CSS

Для выделения синтаксиса я предпочитаю темную тему, поэтому использую следующие параметры для CSS :

code[class*="language-"], pre[class*="language-"] { color: #fff; text-shadow: 0 1px 1px #000; font-family: Menlo, Monaco, "Courier New", monospace; direction: ltr; text-align: left; word-spacing: normal; white-space: pre; word-wrap: normal; line-height: 1.4; background: none; border: 0; -moz-tab-size: 4; -o-tab-size: 4; tab-size: 4; -webkit-hyphens: none; -moz-hyphens: none; -ms-hyphens: none; hyphens: none; } pre[class*="language-"] code { float: left; padding: 0 15px 0 0; } pre[class*="language-"], :not(pre) > code[class*="language-"] { background: #222; } .syntax-highlighter[rel] { position: relative; } .syntax-highlighter[rel] pre[class*="language-"] { padding-top: 44px; } .syntax-highlighter[rel]:before { content: attr(rel); text-align: center; text-shadow: 1px 1px 2px rgba(0,0,0,0.6); position: absolute; top: -1px; background: #3A87AD; padding: 5px 10px; left: 0; right: 0; font: bold 16px/20px "myriad-pro-1","myriad-pro-2","Lucida Grande",Sans-Serif; color: #fff; -moz-border-radius: 7px 7px 0 0; -webkit-border-radius: 7px 7px 0 0; border-radius: 7px 7px 0 0; } /* Code blocks */ pre[class*="language-"] { padding: 15px; margin: 1em 0; overflow: auto; -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; } /* Inline code */ :not(pre) > code[class*="language-"] { padding: 5px 10px; line-height: 1; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } .token.comment, .token.line-comment, .token.prolog, .token.doctype, .token.cdata { color: #797979; } .token.selector, .token.operator, .token.punctuation { color: #fff; } .namespace { opacity: .7; } .token.tag, .token.boolean { color: #ffd893; } .token.atrule, .token.attr-value, .token.hex, .token.string { color: #B0C975; } .token.property, .token.entity, .token.url, .token.attr-name, .token.keyword { color: #c27628; } .token.regex { color: #9B71C6; } .token.entity { cursor: help; } .token.function, .token.constant { color: #e5a638; } .token.variable { color: #fdfba8; } .token.number { color: #8799B0; } .token.important, .token.deliminator { color: #E45734; } pre[data-line] { position: relative; padding: 1em 0 1em 3em; } .line-highlight { position: absolute; left: 0; right: 0; padding: inherit 0; margin-top: 1em; /* Same as .prism’s padding-top */ background: rgba(255,255,255,.2); pointer-events: none; line-height: inherit; white-space: pre; } .line-highlight:before, .line-highlight[data-end]:after { content: attr(data-start); position: absolute; top: .3em; left: .6em; min-width: 1em; padding: 0 .5em; background-color: rgba(255,255,255,.3); color: #fff; font: bold 65%/1.5 sans-serif; text-align: center; -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; text-shadow: none; } .line-highlight[data-end]:after { content: attr(data-end); top: auto; bottom: .4em; } /* for line numbers */ ol.linenums { margin: 0; padding: 0 0 0 35px; } .linenums li { padding-left: 10px; border-left: 3px #d9d336 solid; }

Использование шорт-кода

Код нашего "разметчика" содержит три атрибута: type , title и linenums . Расшифруем, что же они означают:

type : 4 типа языка, которые работают с нашим "разметчиком": markup , css , php , javascript . title : необязательный заголовок, который можно включить при запуске подсветки синтаксиса. linenums : добавляет номера строк к вашему коду, начиная с любого заданного вами числа (тоже необязательно).

Единственный обязательный атрибут — это " type ", по умолчанию его значение выставлено как " markup ".

Заключение

Сборка плагина для визуальной "подсветки" кода — дело всего нескольких кликов и последовательных шагов; но благодаря этому у вас появится плагин, который всегда можно скачать и установить на новый сайт без необходимости разбираться, как он работает, и как все это было собрано воедино. Хотя порой довольно занимательно разбираться в том, как все устроено в работе WordPress и как изменить те или иные настройки. Если темная тема оформления и выделения вам не по вкусу, то можете внести собственные настройки в CSS для внедрения новых стилей "подсветки", которая больше подойдет дизайну вашего сайта.

Источник:
rss