TinyMCE vs XML теги и Code Sample плагин

TinyMCE - отличный WYSIWYG редактор, который позволяет легко и удобно редактировать материал перед его публикацией. Иногда появляется необходимость опубликовать и html/xml код.

В версии TinyMCE 4.3 появился замечательный инструмент Code Sample Plugin, который, как это всегда и бывает, направлен на то, чтобы упростить нам жизнь, позволив удобно вставлять блоки кода с подсветкой синтаксиса некоторых языков программирования и разметки, в частности как раз для XML/HTML.


Допустим, вы пишете статью и хотите вставить фрагмент XML-кода:

<?xml version="1.0" encoding="UTF-8"?>
<note>
	<to>Tove</to>
	<from>Jani</from>
	<heading>Reminder</heading>
	<body>Don't forget me this weekend!</body>
</note>

Чтобы воспользоваться новым Code Sample плагином, он должен быть указан при инициализации tinymce:

tinymce.init({
  selector: "#your-textarea-id",
  plugins: "codesample",
  toolbar: "codesample"
});

После этого на панели инструментов появится новая кнопка, после нажатия на которую вы увидите перед собой диалоговое окно, в котором можно вставить (желательно) валидный код, который будет автоматически преобразован в красиво оформленный фрагмент кода в редактируемой области WYSIWYG'а.

При этом в исходном коде это будет выглядеть вот так:

Всё это дело вы успешно сохраняете где-то в недрах базы данных, проверяете на сайте, там всё отображается корректно (прямо как в этой статье).

А теперь самое интересное

В какой-то момент вы вновь открываете эту статью в WYSIWYG редакторе и понимаете, что редактор «съел» все xml-теги! Если открыть окно просмотра исходного кода, то там будет только текст и ни единого xml-тега.

Т.е. получается, что TinyMCE позволил нам удобным способом вставить XML-код, а потом сам же его же не может отобразить :)

Вся соль кроется в том, что ему «не нравятся» ваши &amp;lt;note&amp;gt; и т.п. сущности (специальные группы символов). Чтобы он правильно их отобразил, следует использовать следующий вид: &amp;lt;note&amp;gt; Но ведь при сохранении всё равно на сервер передаётся именно &amp;lt;note&amp;gt;!

Простое решение:

1. сохранять ровно в том виде, в каком данные приходят на сервер (тогда и при выводе на сайте ничего не нужно будет менять, всё отобразится корректно)

2. при редактировании контента скармливать TinyMCE данные, предварительно заменяя & на &amp;

Пример кода на php:

if (!empty($content) and preg_match_all('/<code>.*?<\/code>/si',$content,$matches)) {
    foreach ($matches as $match) {
        $content = str_replace($match,str_replace('&','&amp;',$match),$content);
    }
    unset($match);
}
unset($matches);

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