суббота, 1 мая 2010 г.

Подсветка кода. Разного. В редакторах TinyMCE, FCKeditor и на blogspot.com

Подсветка программного кода при веб публикации, проблема не новая, но я с ней столкнулся первый раз и как то не задумывался, как это делает, например библиотека phpDocumentor или некоторые движки форумов. И вот понадобилось.
Собственно написать такой функционал для программиста средней руки  - не проблема, достаточно хорошо знать регулярные выражения, и я бы начал этот труд, но при нормальном современном процессе веб-разработки, сроки реализации обычно "вчера", и с этим трудно что либо поделать. Дополнительная сложность состояла в том, что 50% кода требущего подстветки являл собой HTML, отображать и редактировать который любой онлайновый HTML WISIWIG редактор по естественным причинам не может. Да и не хочется изобретать велосипед, если процесс его изобретения ничего интересного для  тебя не представляет.
Слава богу не все такие "ленивые и нелюбопытные" и инструменты для решения подобных задачь уже созданы.
Впрочем употребляя множественное число я наверное погорячился, аналогов известной JavaScript библиотеке SyntaxHighlighter я не нашёл.И не сильно этому огорчился - библиотека замечательная, а о возможных сложностях её применения я сейчас расскажу.

Сначала скачаем SyntaxHighlighter, с сайта разработчика  (http://alexgorbatchev.com/wiki/SyntaxHighlighter:Download  сайт канадский. но что то в его названии мне намекает...). Важно скачать именно последнею версиию, тапк как синтаксис применения ранних версий библиотеки здорово отличается.
Скачав, не будем спешить распаковывать полученный архив на територию нашего веб сайта. Сначала посмотрим, что мы добыли (Рис. 1).

 Рис. 1
Библиотека SyntaxHighlighter

как видете у нас три папки, в двух из которых находятся скрипты, которые и занимаются парсингом и подсветкой кода, разница состоит в том, что в папке scripts они находятся в сжатом виде, а в папке src - в первозданном ( в последних релизах там только миниум).  Для подключения библиотеке необходимо вклчить в код веб страницы два javascript файла - ядро библиотеки и интерпритатор нужного языка. Допустим, для PHP код будет следующим:

<script  type="text/javascript" src="js/shCore.js"></script>
<script  type="text/javascript" src="js/shBrushPhp.js"></script>


Теперь идём в папку styles и берём от туда файл shCore.css и css файл соответствующий какому нибудь либо стилю подсветки (Midnight Commander, Emac и др. Я выбрал Defoult):

<link href='css/shCore.css'  rel='stylesheet' type='text/css'/>
<link href='css/shThemeDefault.css'  rel='stylesheet' type='text/css'/>

И инициализируем библиотеку:
<script type='text/javascript'>
 SyntaxHighlighter.config.bloggerMode = true;
 SyntaxHighlighter.all();
</script>
Теперь оформляем публикуемый код следующим образом:

<pre class="brush: php">
$foo="test";
function bar($one, $second=1){
phpinfo();
}
</pre>


Если всё сдедано правильно результат должен выглчядеть вот так:

$foo="test";
function bar($one, $second=1){
phpinfo(); 
} 

Теперь попробуем подсвечивать HTML код. Добавляем соответствующею кисть:

<script  type="text/javascript" src="js/shCore.js"></script>
<script  type="text/javascript" src="js/shBrushPhp.js"></script>
<script  type="text/javascript" src="js/shBrushXml.js"></script>

Да да, именно xml (не будем забывать, что html, вернее xhtml яdляется подмножество xml). Нстоящая прроблема с html разметкой немного в другом. если она будет сохранена в первозданном виде, браузер не будет её отображать, он будет её интерпретировать. Это кстати относиться к символам <? или <% в php или asp коде соответственно. Выход из этой ситуации есть и я его исполюзлвал, в честности для пнаписания предыдущего предложения. Нужно использовать html сущности, и вместо < и > писать "&lt;" и "&gt;"

Смотрим пример:

<pre class="brush: html">
&lt;div id="test1" &gt;
Текст
&lt;/div &gt;
&lt;img src="logo.png"/&gt;
</pre>


Должно получиться следующее:

<div  id="test1" >
Текст
</div >
<img  src="logo.png"/>


Тут нужно обратить внимание на brush: html. В данном случае я использовал псевдоним для «кисти» Xml. Псевдонимы «кистей» и их названия есть в документации по SyntaxHighlighter , но для особо ленивых я приведу табличку нативно поддерживаемых языков:


Название Псевдоним Имя файла
ActionScript3 as3, actionscript3 shBrushAS3.js
Bash/shell bash, shell shBrushBash.js
ColdFusion cf, coldfusion shBrushColdFusion.js
C# c-sharp, csharp shBrushCSharp.js
C++ cpp, c shBrushCpp.js
CSS css shBrushCss.js
Delphi delphi, pas, pascal shBrushDelphi.js
Diff diff, patch shBrushDiff.js
Erlang erl, erlang shBrushErlang.js
Groovy groovy shBrushGroovy.js
JavaScript js, jscript, javascript shBrushJScript.js
Java java shBrushJava.js
JavaFX jfx, javafx shBrushJavaFX.js
Perl perl, pl shBrushPerl.js
PHP php shBrushPhp.js
Plain Text plain, text shBrushPlain.js
PowerShell ps, powershell shBrushPowerShell.js
Python py, python shBrushPython.js
Ruby rails, ror, ruby shBrushRuby.js
Scala scala shBrushScala.js
SQL sql shBrushSql.js
Visual Basic vb, vbnet shBrushVb.js
XML xml, xhtml, xslt, html, xhtml shBrushXml.js

Впрочем на этом список поддерживаемсых языков не заканчивается. Со списоко языков с которыми можно работать прямо сейчас и в ближайшем будущем представлен здесь:

http://www.undermyhat.org/blog/2009/09/list-of-brushes-syntaxhighligher/

Более того, если вы не обнаружили в смиске ваш любимый Algol 68 то отчаивается не следует. Библиотека расширяема, как с точки зрения архитектуры, так и лицензии. желающих принять участие в её расширении прошу вот сюда:
http://alexgorbatchev.com/wiki/SyntaxHighlighter:Brushes:Custom
и наверное сюда
http://alexgorbatchev.com/wiki/SyntaxHighlighter:API

Ну а нам, простым пользователям остаётся ознакомиться с базовыми функкциями.


Опции конфигурирования SyntaxHighlighter

При инициализации можно задать несколько параметров  подсветки. Их немного, поэтому перечислю все: 
tagName - название тега, которым обрамляется подсвечиваемый код. По умолчанию это разумеется "pre". устанавливается так:
SyntaxHighlighter.config.tagName = "div";

string - позволяет менять различные системные сообщения библи отеки, такие, как
"view source" или "Can't find brush for: " (это сообщение пояляется если вы используете кисть, которую забыли подключить. Использовать её следует так:
SyntaxHighlighter.config.strings.viewSource = "Посмотреть исходный код";

Опция stripBrs - предназначена для борьбы с некоторыми HTML и не только редакторами, которые автоматически добавляют тег
в концекаждой строки. По умолчанию false.
Опции toolbarItemWidth и toolbarItemHeight отвечают за размеры иконок панели инструментов (по умолчанию 16X16)
clipboardSwf - показывает расположение иконки "скопировать в буфер обмена". По умолчанию NULL, то есть иконка не показывается.
И наконец загадочная для меня опция bloggerMode. По дукоментации её надо включать (устанавливать значение в true), если библиотека используется на блоге blogger.com. По видимому это для какой то цели нужно автору и посему я её вклчил.

Следущий уровень настройки работы SyntaxHighlighter заключается в атрибутах, прописываемых для обрампляющего тега. Применяются они следующим образом:
<pre class="brush: php; first-line: 10; gutter: false;" &qt;...</pre&qt;

Тут параметров немного больше:
auto-links - отключае/включает гиперсылки в коде
class-name - позволяет задавать дополнительное имя класса, для создания пользовательских стилей.
collapse - при значении true показывает код в свёрнутом виде. Вот так:

function foo()
 {
  var bar="test";
  return 0;  
 } 
 
first-line - задаёт номер первой строки при нумерации строк
gutter - включает/выкключает нумерацию строк
highlight -используется для выделения одной или нескольких строк:

function foo()
 {
  var bar="test";
  document.write("Hello!");
  det=document.getElementById("det");
  return 0;  
 }

опция html-script очень пригодиться для илюсьрации вставки какпого лиюо кода в html разметку. При веб программировании это до сих пор довольно актуально. Применяется это так:


< class="brush: php; html-script: true">
<html>
<body>
<div style="font-weight: bold"><?= str_replace("\n", "<br/>", $var) ?></div>

<?php
/***********************************
** Multiline block comments
**********************************/

$stringWithUrl = "http://alexgorbatchev.com";
$stringWithUrl = 'http://alexgorbatchev.com';
ob_start("parseOutputBuffer"); // Start Code Buffering
session_start();
?>
</body>
</html>
</pre>

Результат:

<html>
<body>
<div style="font-weight: bold"><?= str_replace("\n", "<br/>", $var) ?></div>
          
<?php
 /***********************************
  ** Multiline block comments
  **********************************/
          
  $stringWithUrl = "http://alexgorbatchev.com";
  $stringWithUrl = 'http://alexgorbatchev.com';
  ob_start("parseOutputBuffer");      // Start Code Buffering
  session_start();
?>
</body>
</html>

ligh - моя любимая опция, отключающая панель инструментов и нумерацию строк.
smart-tabs - как видно из назвапния, при значении true пытается самомтоятельно упорядочить отступы в коде.
tab-size - устанавливает размер таб-отступа.
toolbar -включае/выключает панель инструментов
wrap-lines - включает/выключает перенос длинных строк, не впещающихся в стандарный размер страницы с кодом. при значении false (по умолчанию - true), строки не переносятся, и появляется горизонтальный скрол-бар.
Вроде всё. Теперь мы готовы для практического применения SyntaxHighlighter

WISIWIG HTML online редакторы

Публикация статей. новостей, прочего контента сейчас делается посредством этих программ. И не важно, что ты сам программист, ты не обязан знать HTML и уж точно не обязан возиться с вёрсткой, всякий раз, когда ты решил осчастливить мир новой публикацией. Как быть там с подсветкой кода?
Большинсво, если не все такого рода редакторов позволяют работать непосредственно с тегами HTML. Но приэтом теряется преимущество такого способы публикации и существует опастность интепретации редапрпрпрктором эти тегов так как ему а не вам нужно.
На счастье для наиболее распространённых online редакторов уже есть плагины, поддерживающие SyntaxHighlighter.
Для редактора  TinyMCE используется плагин SyntaxHL от RichGuk. Скачиваем архив и помещаем папку syntaxhl в директорию плагинов редактора (tiny_mce/plugins/). Привызове редактора на веб-странице, внесём этот плагин в список загружаемых, и добавим  иконку syntaxhl на панель интструментов:
tinyMCE.init({
// General options
  mode : "textareas",
  theme : "advanced",
  plugins :    "safari,syntaxhl,pagebreak,style,...",

// Theme options
 theme_advanced_buttons1 : "syntaxhl,|,italic,underline...",
 theme_advanced_buttons2 : "...",
 theme_advanced_buttons3 : "...",

remove_linebreaks : false,
extended_valid_elements : "textarea[cols|rows|disabled|name|readonly|class]",
 

 });

Теперь при запуске редактора, в верхней понеле инструментов появляется новая иконка (рис 2),

Рис 2
Иконка SyntaxHL

при нажатии на которую открывается окно ввода кода (рис 3).



Рис 3
 SyntaxHL в работе

Как видете, теперь библиотеку можно исполльзовать не вписывая каждый раз теги
<pre&qt; и т д.
Пробплемы возникают, когда мы пытаемся отредактировать уже сохранённый текст, содержащий html разметку. При инициализации редактора все сущности теги нашего кода преодразуются в теги и при повторном сохранении превращаются в обычную разметку. Выход простой - использовать php функцию htmlspecialchars, преобразующую теги в сущности, при выводе редактируемого текста в TinyMCE:
print '';

Если вы пишете на другом языке, используйте аналогичные функции из них ( Server.HTMLencode для ASP, escape в Perl).
Редактор  FCKeditor, или в более новой и не режущий нежный американский слух, CKeditor так-же имеет плагин, аналогичный по функциональности. Это Highlight Plugin. Устанавливается он схожим образом - папка (syntaxhighlight2) с плагином помещается в fckeditor/plugins/. Далее в конфигурационном файле редактора (fckconfig.js) пишем следующее:

FCKConfig.Plugins.Add( 'syntaxhighlight2', 'en');
 И там-же добавляем иконку:

FCKConfig.ToolbarSets["Basic"] = [
['SyntaxHighLight','-''Bold','Italic','-','OrderedList',...]
];
Далее можно установить язык по умолчанию:
FCKConfig.SyntaxHighlight2LangDefault = 'xhtml' ;
Псевдонимы языков следующие:
    • c++ - C++
    • csharp - C#
    • css - CSS
    • delphi - Delphi
    • java - Java
    • jscript - Java Script
    • php - PHP
    • python - Python
    • ruby - Ruby
    • sql - SQL
    • vb - VB.NET
    • xhtml - XML/HTML
В будущем планируется расширить список языков ввести предпросмотр и конфигурационные опции, а пока, то что есть мы можем видеть на рис. 4.

 Рис. 4
Highlight Plugin в работе

Осталось немного - подключить библиотеку к этому самому блогу. Как видите мне это удалось, но сразу скажу, что удобных плагинов для вставки кода тут пока не существует. А вот просто применить SyntaxHighlight мы можем. Дпля этого идём в настройки нашего блога, выбираем вкладку "Дизайн", там пункт "Изменить HTML". В открывшемся исходном коде шаблона ищем закрывающий тег и вставляем перед ним следующий код:

<link href='http://bitbucket.org/alexg/syntaxhighlighter/raw/8815b7f713eb/Styles/shCore.css' rel='stylesheet' type='text/css'/ &qt;
<link href='http://bitbucket.org/alexg/syntaxhighlighter/raw/8815b7f713eb/Styles/shThemeDefault.css' rel='stylesheet' type='text/css'/  &qt;


Разумеется вы можете его модифицировать исходя из своиз потребностей, руководствуясь описаными выше настройками. Ну а принаписании статей, пользуйтесь вкладкой "Изменить HTML", добавляя тег pre с соответствующими атрибутами к блокам кода.
 На этом всё. Осталось сказать спасибо Алексу Горбачеву за его замечательную библиотеку.

1 комментарий:

  1. А в самом TinyMCE (после добавления кода посредством SyntaxHL) можно увидеть подсвеченный код?
    Если да, то как?

    ОтветитьУдалить