Это достаточно частый вопрос. И даже мне из-за этого приходилось переделывать вёрстку. Ответ в понимании механизма парсинга. В предыдущей статье я уже описывал последовательность подготовки ответа пользователю. Давайте её вспомним. Сначала MODX получает контент шаблона и передаёт его парсеру (мы говорим о pdoParser). Если шаблона нет, то берётся контент ресурса. Далее:

  1. Парсер обрабатывает кэшируемые элементы в контенте, если ресурс не из кэша. На этом этапе Fenom не работает.
  2. Парсятся некэшируемые элементы. Нераспарсенные не удаляются. Здесь Fenom уже запускается, причём обрабатывает контент до парсера MODX. Т.е. сначала обработаются теги Fenom, а только потом теги MODX. При условии, что включена настройка обработки тегов Fenom на страницах.
  3. Парсятся некэшируемые элементы. Нераспарсенные удаляются. Fenom работает как на предыдущем шаге.

На каждом этапе MODX парсит контент на глубину до 10-го уровня. Т.е. распарсил тег, и если результат содержит ещё теги MODX, то запускается новый цикл парсинга. И так 10 раз.

Теперь давайте возьмём пример из первой ссылки. В шаблоне пишем теги Fenom:

# Блок кода №1
<!doctype html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    {$_modx->resource.content}
    {ignore}
    <input pattern="\+7\s\(\d{3}\)\s\d{3}-\d{2}-\d{2}"/>
    {/ignore}
</body>
</html>

И в ресурсе тоже вызываем сниппет через Fenom:

# Блок код №2
{$_modx->runSnippet('!pdoMenu', [
	'parents'    => $_modx->resource.id
	,'level'     => 1
	,'showHidden'=> 1
])}

Теперь посмотрим как это будет парсится по шагам.

Шаг 1. Обработка кэшируемых элементов

На этом шаге в парсер попадет контент шаблона (см. код выше). Теги Fenom на этом этапе не парсятся. MODX ищет кэшируемые теги. Таких, как мы видим, нет. Обработка закончена.

Шаг 2. Обработка некэшируемых элементов без удаления нераспарсенных тегов

На этом этапе Fenom уже запускается (только если есть теги Fenom). Он получает первоначальный контент и парсит его. Результат будет такой:

# Блок кода №3
<!doctype html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    {$_modx->runSnippet('!pdoMenu', [
        'parents'    => $_modx->resource.id
        ,'level'     => 1
        ,'showHidden'=> 1
    ])}
    <input pattern="\+7\s\(\d{3}\)\s\d{3}-\d{2}-\d{2}"/>
</body>
</html>

Тег {$_modx->resource.content} заменён на контент ресурса, а тег {ignore} исчез. Но он исчез не по ошибке, он отработал согласно указанной ему задаче — вернул завёрнутый в него код без обработки. Дальше запускается парсер MODX и ищет стандартные некэшируемые теги со знаком !. Их в контенте нет, поэтому обработка завершается.

Шаг 3. Обработка некэшируемых элементов с удалением нераспарсенных тегов

Вот теперь самое интересное. На этом шаге в контенте всё ещё присутствуют теги Fenom. Поэтому он, имея полное право, парсит их. А своими тегами Fenom считает всё, что обернуто фигурными скобками, но за одним исключением (и это исключение добавил Василий) — теги должны начинаться с $, ', (, строки с пробела (вот тут я об этом писал). А так как тега {ignore} уже нет, то Fenom обрабатывает все фигурные скобки и в том числе {3}.

Примечание

Если в контенте есть только теги типа {3}, Fenom их пропускает, так как они не подходят под регулярку (если только вы не правили её, удалив, например, \s). Он просто не запустится. Но если на странице есть правильные теги, то он обработает все фигурные скобки без исключений. Т.е. вместе с «правильными» тегами Fenom обработает и те, которые изначально игнорирует.

Надеюсь, теперь понятно, почему «не работает» тег {ignore}. Теперь давайте рассмотрим вариант решения.

Вариант 1

Самый просто вариант — указать в шаблоне кэшируемый тег [[*content]] вместо {$_modx->resource.content}:

# Блок кода №4
<!doctype html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    [[*content]]
    {ignore}
    <input pattern="\+7\s\(\d{3}\)\s\d{3}-\d{2}-\d{2}"/>
    {/ignore}
</body>
</html>

Тогда MODX уже на первом шаге подготовит для Fenom такой контент:

# Блок кода №5
<!doctype html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    {$_modx->runSnippet('!pdoMenu', [
        'parents'    => $_modx->resource.id
        ,'level'     => 1
        ,'showHidden'=> 1
    ])}
    {ignore}
    <input pattern="\+7\s\(\d{3}\)\s\d{3}-\d{2}-\d{2}"/>
    {/ignore}
</body>
</html>

Здесь уже и контент ресурса и тег {ignore}. Fenom его учтёт и вернёт уже такой результат (это второй шаг):

# Блок кода №6
<!doctype html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    ... Результат работы сниппета ...
    <input pattern="\+7\s\(\d{3}\)\s\d{3}-\d{2}-\d{2}"/>
</body>
</html>

На третьем шаге Fenom пропустит этот контент, так как теги {цифра} не соответствуют регулярному выражению (если вы его не правили).

В итоге вы получите ожидаемый результат.

Вариант 2

Перенести блок с тегом {ignore} в ресурс. Тогда Fenom только на третьем (последнем) шаге получит контент из блока кода №5 и Fenom пропустит всё что указанно в {ignore}.

Заключение

В общем идея должна быть понятна — тег {ignore} должен присутствовать в итерации, после которой больше не будет тегов Fenom. К сожалению, добиться этого не всегда получается. Специфика MODX.

Update 07.12.2017

В новой версии pdoTools эта проблема устранена. Решение простое — содержимое тега {ignore} перед запуском парсера вырезается и возвращается обратно перед выводом ответа пользователю. Правда, как выяснилось, не работает если код шаблона или чанка находится в файле.

06 октября 2017, 18:05   929     4

Комментарии ()

  1. shock 15 февраля 2018, 19:20 # 0
    Добрый день!
    Спасибо за ваш труд, Сергей!
    Подскажите как вы экранируете тег
    {/ignore}
    в подсветке кода?
    Дело в том, что если код помещать в
    {ignore}{/ignore}
    , наличие второго
    {/ignore}
    приводит к ошибке.
    Буду очень признателен за подсказку.
    1. Сергей Шлоков 15 февраля 2018, 20:48 # 0
      Здравствуйте!
      Просто я использую Tickets. Он сам всё экранирует. Для самостоятельного экранирования используйте мнемоники. Коды 123 и 125 соответственно вместо скобок.
      1. shock 15 февраля 2018, 21:14 # 0
        Спасибо, понял.
        В Tickets случайно не jevix этим занимается?
        1. Сергей Шлоков 15 февраля 2018, 21:17 # 0
          Он самый.

    Вы должны авторизоваться, чтобы оставлять комментарии.

    Выделите опечатку и нажмите Ctrl + Enter, чтобы отправить сообщение об ошибке.