Подсветка исходного кода в вики

После анонса проекта университетской вики пора рассказать о некоторых расширениях, упрощающих использование вики в качестве платформы для написания лекций.

Начнем с такой популярной задачи для мехмата и физфака как программирование. А именно подсветки синтаксиса.

highlight-example.png


Возможные варианты подсветки[править]

Существует несколько способов подсветить синтаксис в вебе. Но так или иначе они делятся на два принципиальных решения:

  • Подсветка на стороне сервера.
  • Подсветка на стороне браузера силами javascript.

Подсветка в MediaWiki[править]

Для MediaWiki первый вариант работает в случае использования GeSHi. Подсветить же с помощью javascript можно разными скриптами.

Большинство из возможных решений требует указания конкретного языка, для которого будет осуществляться подсветка, но некоторые умеют автоматически определять язык (иногда ошибаясь и чем больше фрагмент кода, тем точнее определение языка).

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

highlight.js[править]

Из оставшихся вариантов наиболее функциональным является highlight.js, который и будем использовать.

Но есть одна проблема, которая касается вообще всех вариантов подсветки кода для MediaWiki: все они требуют заключение кода в два вложенных контейнера, типа <pre><code>...</code></pre>.

Почему так, а не <pre>...</pre>? Очевидно, тег <pre> зарезервирован для своего стандартного применения в рамках HTML: вставки предформатированного текста.

После некоторых размышлений я решил считать исходным кодом и подсвечивать с помощью highlight.js все что находится в тегах <code>...</code>.

Это нестандартное для MediaWiki решение и оно не переносимо в википедию т.к. тег <code> является inline-тегом и по W3C должен использоваться для написания исходного кода в строке, а не в виде блока. В этом смысле <code> похож на тег <span> для случая форматирования исходного кода.

Работает подсветка так: мой фильтр в MediaWiki находит тег <code>...</code> и заменяет его на <pre><code>...</code></pre>, который уже с удовольствием подсвечивается highlight.js, а браузер получает в себя HTML-код без нарушения семантики.

Но и это еще не все. Скрипту highlight.js можно сказать какой именно язык используется при помощи указания класса <pre><code class="php">...</code></pre>.

Этот момент я тоже упростил в плане написания, раз уж все равно потеряли совместимость с википедией. Нужный язык из списка поддерживаемых можно указать так: <code php>...</code>.

Ограничения[править]

В исходном коде нельзя использовать тег <code>. На практике это можно встретить при использовании XML.

В Кампусе в блогах подсветка работать не будет т.к. я туда не стал подключать highlight.js, но тег <code> в <pre> обернут все равно будет:

        $items['infopanel/userpages/%'] = array(
                'title' => 'Материалы пользователя',
                'description' => 'Материалы, опубликованные пользователем',
                'page callback' => 'show_userpages_infopanel',
                'page arguments' => array(2),
                'access arguments' => array('show any user pages'),
                'type' => MENU_CALLBACK,
        );

        return $items;
}

// hook_cron implementation
function infopanel_cron() {
  $query = db_query("SELECT * FROM {field_data_field_date_unpublish} AS u INNER JOIN {node} AS n WHERE n.nid = u.entity_id AND n.vid = u.revision_id AND n.status='1' AND u.field_date_unpublish_value < NOW()");
  foreach ($query as $res) {
    if (isset($res->nid)) {
      db_update("node")->condition('nid',$res->nid)->fields(array('status'=>'0'))->execute();
      watchdog("infopanel","Срок публикации ноды ':nid' истек и она снята с публикации",array(':nid'=>$res->nid),WATCHDOG_INFO);
    }
  }
}

Для включения подсветки, тогда, окажется достаточным подключения скрипта highlight.js и, поэтому, именно тег <code> я рекомендую использовать в блогах при написании какого-либо кода вместо привычного в таких случаях <pre>.