Цапля

Вывод мнемоник и html-кодов спецсимволов

Стандартный тэг <code>
не позволяет показывать на страницах сайта мнемоники или коды спецсимволов, поэтому можно либо устанавливать плагины, либо попытаться самостоятельно организовать правильный вывод. Здесь на помощь придут регулярные выражения.

Узнать коды некоторых наиболее популярных символов можно в статье «Типографика. Символы первой необходимости», в ней же указано, как узнать код любого нужного символа.

Как работает htmlentities()?

Довольное простое решение есть в некоторых учебниках:
$content=preg_replace ("@<code.*?>(.*?)code>@", htmlentities('$1'), $content);
Здесь $content хранит строку внутри которой в тэгах <code> (или с добавлением класса или идентификатора, например <code class="show-html">) встречаются мнемоники (например, &copy;) и html-коды (например, &#169;) спецсимволов. И содержимое тэгов <code> мы бы хотели показать таким, какое оно введено, без преобразования в соответствующий символ (в нашем случае ©). Функция preg_replace() здесь отлично подходит. Если мы передали знак ©, то функция его так и выведет. Если мы передали код мнемоники, то функция выведет код мнемоники. Можно посмотреть таблицу преобразований, которую использует функция htmlentities(), воспользовавшись функцией get_html_translation_table(). Итак, данное решение не подходит. Результат его работы можно посмотреть на странице ex.zaplokee.net/htmlentities.php.

Как работает htmlentities()
Исходное выражение Какой получается код после обработки функцией htmlentities() Что видим в исходном коде страницы Что видим на странице сайта
& &amp;
& &
<
&lt;
<
<
>
&gt;
>
>
&nbsp;
&amp;nbsp;
&nbsp;

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

Поиски решения

Поскольку тэг <code> может применяться, чтобы показать php-код, где совершенно не нужен вывод мнемоник, то html-код будем помещать в тэг <code html>. Без создания класса, чтобы не утонуть в кавычках.

Значит задача имеет несколько этапов решения:
  1. найти упоминание тэга <codhtml>,
  2. взять то, что находится внутри тэга и поместить строку в переменную,
  3. применить к этой переменной htmlentities() при выводе на страницу,
  4. если <code html> встречается еще раз, то повторить шаги 1-3.

Комментарии к решению

Чтобы посчитать число повторений тэга <code html> в строке, воспользуемся функцией substr(). Пример ее работы можно также посмотреть на ex.zaplokee.net/htmlentities.php.

Чтобы избежать проблемы, когда в $1 лежит спецсимвол и htmlentities('$1') выводит сам спецсимвол, а не его код, воспользуемся функцией preg_match() и проверим наличие совпадений.

preg_match("@<code html>(.*?)code>@", $incoming, $matches)>0

То есть мы найдем первое в строке упоминание <code html>, возьмем то, что лежит внутри <code html> и </code> и положим в массив $matches, где нулевой элемент будет хранить целиком найденную подстроку, а первый элемент будет хранить ту часть подстроки, которую мы захватим в подмаску. Массив $matches в случае использования функции preg_match() будет одномерным.

В preg_replace() указываем, что замену надо выполнить единожды:
preg_replace("@<code html>(.*?)</code>@", "<htmlcode>".$change."</htmlcode>", $incoming, 1)

Здесь $change=htmlentities($matches[1],ENT_QUOTES,'utf-8');

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