Как сделать так, чтобы Fenom не ломал сайт?

Вопрос такой — есть ли способ сделать так, чтобы Fenom не ломался после того, как наткнется на «неожиданный символ», который тут поставлен не для него, а просто в коде JS/JSON/..? (Не {ignore})

Ситуация простая и понятная — на сайте стоит феном и активно используется везде. Но если вставить какой-нибудь JS код, или иной код с фигурной скобкой — все. Страница не открывается. Ошибка в логе.
Я знаю, что есть {ignore}, но это не решение, когда менеджер может вставить JS Код в редакторе.

Эмоциональное дополнение — И в принципе это мне кажется очень недружелюбным подходом, т.к. в любом месте сайта может появиться скобочка (например вставили счетчик в шаблон), и сайт ломается. Я уверен, что так быть не должно. Почему бы феному просто не проигнорировать тот набор символов, которые он не может прочитать? Почему он должен ломать всю страницу, если ему что-то не понравилось!? И для тестирования просто иметь иметь какую-то настройку — типа «строгий режим» для разработки, и мягкий — для рабочего сайта.

Я понимаю, что есть полу-решения, например — обернуть вызов [[*content]] в {ignore}. Но что если на какой-то странице шаблона мне все таки нужен синтаксис Fenom? То есть это не универсальное решение, а костыль.

Upd
С подачи Артема разместил вопрос на Гитхабе — github.com/fenom-template/fenom/issues/308
Сергей
11 ноября 2019, 13:49
modx.pro
1
2 349
+2

Комментарии: 32

Sergey
11 ноября 2019, 15:50
+1
Сергей, полностью разделяю ваше негодование. Кроме того, совсем недавно я узнал, что даже тег {ignore} не всегда может спасти, в комментарии было написано, что при использовании этого специального тега, нужно после всех фигурных скобок ставить пробел. Когда я его прочитал, был в шоке, в коде вообще какой-то огород получается. После этого у меня в голове поломались все принципы программирования. До сих пор задаюсь вопросом, почему разработчик решил использовать именно фигурную скобку для своего парсера, ведь она очень часто используется при верстке сайтов, как он мог это не учесть? Если кто-то знает ответ, поделитесь пожалуйста, чтобы я наконец перестал ломать свою голову )))
Сергей, я полностью Вас поддерживаю в вашем вопросе, мое мнение, что действительно необходимо что-то с этим делать, так быть не должно.
Теперь готов выслушать критику. )))
    Павел Бигель
    14 ноября 2019, 16:34
    0
    Фигурная скобка используется почти любым шаблонизатором. Де-факто это стандарт.

    По поводу поста — я в целом согласен.
      Sergey
      15 ноября 2019, 13:16
      0
      Павел, спасибо Вам за ответ, теперь более или менее стало понятно. ?
    Вася
    11 ноября 2019, 16:23
    0
    ну а пройтись автозаменой по js коду? И поставить пробел после открывающейся скобки тяжело?
      Sergey
      11 ноября 2019, 17:59
      0
      Василий, а если она встречается не только в JS, а и в других местах, например, на сайте используется математика, там таких фигурных скобок предостаточно используется, как в этом случае быть? Запаришься пробелы ставить. Да и не удобно это, забыл пробел поставить, и все приплыли. )))
      И еще, Сергей пишет о том, что менеджер может в любой момент вставить фигурную скобку в редакторе, и что постоянно за ним следить? Тут конечно единственный вариант, использовать тег {ignore}, других вариантов не вижу.
        Николай Савин
        11 ноября 2019, 18:10
        0
        В случае с менеджером, можно написать плагин, который при сохранении страницы заменяет все фигурные скобки на мнемонику или аналог или вообще вырезает их, если это не уместно.
          Сергей
          11 ноября 2019, 18:39
          +1
          Ну ведь это же костыль… А что если менеджер ± программист и может поправить шаблон. И в принципе вопрос не в том «как замотивировать себя уделять больше времени сайту», а в том «как облегчить себе жизнь» и сделать так, чтобы было невозможно выстрелить себе в ногу.

          Или, допустим у меня есть большой сайт без фенома, и я делаю рефакторинг, внедряю феном. Тут уже программист, а не менеджер может что-то упустить.

          Или текстовый редактор может быть не только у контента. Или — текстовый редактор может впоследствии появится у какого-то поля, в которое менеджер скопирует некий невалидный код.
          Сценариев масса, и писать плагин на обработку каждого ТВ поля — это очень грустный сценарий.
            Вася
            11 ноября 2019, 18:40
            0
            Вообще js выносят в файлы обычно из HTML, а там нет разницы
              Sergey
              11 ноября 2019, 18:53
              0
              Василий, поверьте, не всегда получается полностью вынести JS из тела страницы. Иногда он там просто необходим.
              Артем
              11 ноября 2019, 23:03
              0
              Писать плагины для решения конкретных задач — это теперь костыль?
              Собственно, нравится Fenom — извольте учитывать его особенности и решать их при необходимости.
              Если вы хотите, чтобы проблему решили в ядре, то вы явно не по адресу, вам сюда: github.com/fenom-template/fenom/issues
              Если не нравится особенность Fenom'а, то всегда можно отказаться от него в пользу доисторических фильтров MODX.
                Сергей
                11 ноября 2019, 23:15
                0
                Да, я держу в голове вариант «не нравится — дверь вон там», но данным вопросом я просто хочу узнать, есть ли у кого-то решение подобной проблемы, т.к. предполагаю, что с этой болью сталкивались (почти) все. И да, я ищу такое решение, которое бы гарантировало бы отсутствие ошибки. На мой взгляд плагин в предложенном виде этого не гарантирует.

                Я ищу вариант плагина, который не давал бы феному положить сайт. Но как именно его написать я не представляю. Но теоретически мне кажется можно, т.к. феном ведь генерирует ошибку, и указывает на строку. Но вот вместо ошибки переключить бы парсер в режим «ignore» для этой части кода. Может быть у кого-то есть подобное решение?
                  Артем
                  12 ноября 2019, 01:39
                  0
                  т.к. предполагаю, что с этой болью сталкивались (почти) все
                  так и есть, все и решают ее традиционными способами: либо вы выставляете ручками везде дополнительные пробелы, либо вы погружаетесь в эту статью и вникаете в принцип работы {ignore}, чтобы понимать, где он сработает, а где нет, а затем комбинируете это с первым вариантом, либо вы пишете свой плагин, который обрабатывает нужный вам контент, ищет вхождения регуляркой и заменяет их, добавляя дополнительный пробел. Собственно, это просто автоматизированный первый вариант.
                    Николай
                    14 ноября 2019, 18:47
                    +1
                    Простой плагин на событие OnLoadWebDocument

                    <?php
                    
                    $pagetitle = $modx->resource->pagetitle;
                    
                    $pagetitle = str_replace('{', '&# 123;', $pagetitle);
                    $pagetitle = str_replace('}', '&# 125;', $pagetitle);
                    
                    $modx->resource->set('pagetitle', $pagetitle);

                    Срабатывает до парсинга тегов. Получаем любое поле ресурса, и заменяем скобки на спецсимволы. Пробел после &# добавил, иначе они преобразуются в скобку здесь на сайте. Так можно прогнать все поля, которые заполняет контент-менеджер. Причём плагин заменяет скобки только в момент открытия страницы. Исходники по факту остаются не тронутыми.
                Sergey
                11 ноября 2019, 18:42
                0
                Соглашусь, с плагином может сработать, но все зависит от того, что там менеджер добавляет, возможно ли будет все нюансы предусмотреть, я о том, как понять, нужна в данном случае фигурная скобка или нет, или ее нужно заменить на мнемонику? Нужно смотреть. И опять же получается, что необходимо еще доп плагины писать, то есть постоянно нужно искать какие-то дополнительные решения, к тому, что имеется. Мое мнение, все должно работать без лишних наворотов. Может я конечно и ошибаюсь.
                  iWatchYouFromAfar
                  11 ноября 2019, 18:49
                  +3
                  Вы абсолютно правы, да должно! Вы можете взять и сделать так, чтобы все работало без лишних наворотов, все скажут вам спасибо!
                    Александр Туниеков
                    13 ноября 2019, 16:48
                    0
                    можете взять и сделать так, чтобы все работало без лишних наворотов, все скажут вам спасибо!
                    Вроде предложил решение, чтоб все работало без наворотов, а спасибо не от кого не слышно :-).
                      iWatchYouFromAfar
                      14 ноября 2019, 12:41
                      0
                      Предложить и сделать — это разные вещи.
                        Александр Туниеков
                        14 ноября 2019, 13:12
                        0
                        Конечно разные. Однако прежде чем сделать всегда есть идея что сделать. Без нее делать то нечего :-). Так вот, идея есть и она предложена на рассмотрение, а сделать в процессе и зависит, в общем-то, от итогов рассмотрения.
                        И поддержка от заинтересованных лиц не помешала бы. А вот заинтересованные лица «жуют попкорн» :-).
                          iWatchYouFromAfar
                          14 ноября 2019, 13:18
                          0
                          Это лучше обсуждать в репозитории Фенома, создав либо issue, либо PR.
          Александр Туниеков
          12 ноября 2019, 00:11
          +1
          Вопрос актуальный. Тоже на этой скобке проблемы вылазят. Взглянул на исходники fenom. По идее фигурная скобка прошита только в этой функции github.com/fenom-template/fenom/blob/fc188a582229c7735df1bb584eb268548a957f46/src/Fenom/Template.php#L212
          В принципе, ее там можно заменить чем-то другим, но спецсимволов на клаве не так много, и все где-то используются. А двойным символом заменять не красиво и не удобно :-(.
          Думаю лучше чтоб на этой строке github.com/fenom-template/fenom/blob/fc188a582229c7735df1bb584eb268548a957f46/src/Fenom/Template.php#L276
          не создавалось исключение с обрывом компиляции, а чтоб ошибка кидалась в лог и компиляция продолжалась.
          Лог прикрутить довольно сложно.
          $result = $fenom->fetch("template/name.tpl", $vars);
          Возвращает уже откомпилированную страницу. Не массив. И чтоб метод вернул массив много изменений надо.
          Можно сделать костыль. Вместо исключения
          throw new CompileException("Unexpected token '" . $tokens->current() . "' in {$this} line {$this->_line}, near '{" . $tokens->getSnippetAsString(0, 0) . "' <- there", 0, E_ERROR, $this->_name, $this->_line);
          Запихать ошибку в текст страницы
          $error_text = "Unexpected token '" . $tokens->current() . "' in {$this} line {$this->_line}, near '{" . $tokens->getSnippetAsString(0, 0) . "' <- there";
          $this->_appendText("<!--log ".$error_text." end_log-->");
          И уже в MODX в pdoParser вылавливать ошибку в тексте и писать ее в лог MODX.
          Ну вот так по идее можно решить проблему :-)
            Фарит
            Фарит
            12 ноября 2019, 10:16
            0
            Сейчас как только возникает ошибка, сразу же её видно, можно за несколько секунд заяндексить и исправить.
            По-вашему рецепту эта ошибка вылезет намного позже и с наслоениями, вероятно у других людей, возможно у менеджеров.
              Александр Туниеков
              12 ноября 2019, 14:12
              0
              Сейчас ошибка возникает фиг знает где. Вот последний случай. Мне понадобилось включить fenom на страницах готового сайта. И сайт стал показывать пустые страницы. В логах
              pdotools.class.php : 989) Unexpected token ':' in 65502631cb124d85a4b77cf0b9656e40 line 71, near '{"active":' <- there
              То есть, не понятно в каком шаблоне или чанке или контенте или tv. Ищи где хочешь.
              Оказалось в шаблоне нашел и поправил быстро. Но пришлось поволноваться. Ошибку вызывает вызов типа
              [[!pdoResource?
              &parents=`1`
              &where=``{"active":1}`
              ]]
              Сейчас я воспроизвел ее на тестовом сайте. yadi.sk/i/fPFVkXKf9M8oIQ
              Вчера я наметил идею. То есть, не окончательный вариант. Счас попробуем реализовать.
              Реализовал. Вот изменения:
              Файл core/components/pdotools/vendor/fenom/fenom/src/Fenom/Template.php со строки 273
              } else {
                                          try{
                                              $code = $this->parseTag($tokens);
                                              if ($tokens->key()) { // if tokenizer have tokens - throws exceptions
                                                  throw new CompileException("Unexpected token '" . $tokens->current() . "' in {$this} line {$this->_line}, near '{" . $tokens->getSnippetAsString(0, 0) . "' <- there", 0, E_ERROR, $this->_name, $this->_line);
                                              }
                                              $this->_appendCode($code, '{' . $tag . '}'); // start the tag lexer
                                          }catch (\Exception $e){
                                              $this->_appendText('{' . $tag . '}');
                                              $this->_appendText('<pre class="fenomLog">'.$e->getMessage().'</pre>');
                                          }
                                      }
              Файл core/components/pdotools/model/pdotools/pdotools.class.php со строки 580
              $content = $tpl->fetch($properties);
                                  //$this->modx->log(modX::LOG_LEVEL_ERROR, $tpl);
                                  //$this->modx->log(modX::LOG_LEVEL_ERROR, $content);
                                  if(preg_match("#<pre class=\"fenomLog\">(.*?)</pre>#is", $content, $matches)){
                                      $content = preg_replace("#<pre class=\"fenomLog\">(.*?)</pre>#is", "", $content);
                                      $this->modx->log(modX::LOG_LEVEL_ERROR, print_r($matches,1));
                                  }
              Журнал ошибок
              [2019-11-12 14:03:20] (ERROR @ D:\OpenServer\domains\modx.loc\core\components\pdotools\model\pdotools\pdotools.class.php : 585) Array
              (
                  [0] => <pre class="fenomLog">Unexpected token ':' in 57d5300dc6213bb54abc3938f719d063 line 72, near '{"active":' <- there</pre>
                  [1] => Unexpected token ':' in 57d5300dc6213bb54abc3938f719d063 line 72, near '{"active":' <- there
              )
              
              [2019-11-12 14:03:20] (ERROR @ D:\OpenServer\domains\modx.loc\core\components\pdotools\model\pdotools\pdofetch.class.php : 172) [pdoTools] Error 42S22: Unknown column 'modResource.active' in 'where clause'
              Страница нормально грузиться yadi.sk/i/yTdJ1mWadBz_nQ и если бы у меня на тестовом сайте было бы поле modResource.active то и сниппет бы нормально отработал. То есть, все JS/JSON отработали бы без ошибок.
                Александр Туниеков
                12 ноября 2019, 14:26
                0
                В сниппете ошибка. В коде страницы поправил, а здесь забыл.
                [[!pdoResources?
                &parents=`1`
                &where=`{"active":1}`
                ]]
                  Фарит
                  Фарит
                  12 ноября 2019, 15:01
                  0
                  Оказалось в шаблоне нашел и поправил быстро. Но пришлось поволноваться.
                  Вот именно про это я написал. В процессе написания сайта вы всегда помните свои последние действия, в крайнем случае можно просто их отменить.

                  А теперь представьте, что сайт уже ушел менеджеру, и он случайно в меню нашел кнопку «Обновить», по привычке с Гмаркетом или Апстором нажал её не сделав бэкапы…
                  Александр Туниеков
                  12 ноября 2019, 15:02
                  0
                  По-вашему рецепту эта ошибка вылезет намного позже и с наслоениями, вероятно у других людей, возможно у менеджеров.
                  Если не правильно написан тег фенома, то на странице он просто выведется и в логе MODX будет описание. То есть ошибку сразу видно и плюс видно сам не правильный тег. А если на феном переводиться готовый сайт, то все JS/JSON будут работать как и работали. Без проблем. И если менеджер введет проставит фигурные скобочки в контент, то они так же отобразятся.

                  Единственное если менеджер поставит открывающую скобку без закрывающей, то сайт сломается на строке github.com/fenom-template/fenom/blob/fc188a582229c7735df1bb584eb268548a957f46/src/Fenom/Template.php#L248 Но я даже не знаю как это обойти :-(. Можно, конечно, так же, вместо исключения, запихать ошибку в лог и тег проигнорировать, но скорее всего fenom поймает закрывающую скобку хорошего тега и сайт снова сломается. В смысле поломается порядок тегов. Вместо {'asd' | snippet} в обработку попадет {текст {'asd' | snippet}
                Александр Туниеков
                13 ноября 2019, 17:18
                0
                Так, кто хочет решить проблему, помогайте разрабам объяснить, что проблема есть и ее нужно решать :-).
                А то чувствую в отказ уйдут.
                github.com/fenom-template/fenom/issues/308
                  Александр Туниеков
                  13 ноября 2019, 17:45
                  0
                  Еще бы Василия привлечь к обсуждению, но у него issues закрыт github.com/bezumkin/pdoTools и где искать его контакты не понятно.
                    Александр Туниеков
                    14 ноября 2019, 22:50
                    0
                    Сделал PR на fenom и на pdoTools.
                    This option, when compiling a Fenom tag error, enables the output of this tag as is and output error in pdoTools for MODX log. To inverse JS / JSON code on MODX template.
                    Изменения вносятся одновременно в 2 компонента. Сюда в pdoTools и в исходники Fenom. Чтоб опция работала, нужно, либо загрузить fenom с форка github.com/touol/fenom, либо дождаться примут PR и обновить исходники.
                    Опция pdotools_fenom_soft_mode включается системных настройках pdoTools. При ее включении, fenom феном, не распознанные теги, добавляет в текст шаблона(чанка) как есть и продолжает компилировать шаблон. При включении pdotools_fenom_save_on_errors, ошибки сохраняются в лог MODX.
                    Изменено поведение только самой критичной части компилятора fenom здесь. То есть, ошибки на валидном JS / JSON коде. В остальных случаях, феном так же выбрасывает исключения (На не закрытых {if ..},{block},{ignore} и т.д.).
                    Транспортный пакет с правками pdoTools и fenom file.modx.pro/files/7/5/8/758e797e15b740fd58e7993054996bc3.zip (переименовать в pdotools-2.13.0-pl.transport.zip)
                    Есть желающие протестировать? Вдруг что-то еще поправить надо.
                      Александр Туниеков
                      14 ноября 2019, 23:12
                      0
                      Мне кажется, сейчас сайт сломаешь, если только специально ломать.
                      Вставляю
                      {
                      {$_modx->user.fullname}
                      <script>
                          x = {"active":1};
                          console.info(x);
                      </script>
                      на сайте { Администратор по умолчанию
                      {if 
                      {$_modx->user.fullname}
                      {if {$_modx->user.fullname}
                      {if}
                      {$_modx->user.fullname}
                      {if} Администратор по умолчанию
                      {if true}
                      {$_modx->user.fullname}
                      Сломался. Так как не закрытый блок. Только, что-то сомнительно, чтоб менеджеры {if или {if true} нечаянно написали.
                      {a
                      {$_modx->user.fullname}
                      на сайте: {a {$_modx->user.fullname}
                      А вот это могут :-(.
                      Ну меня, пока, устраивает, что не ломается по каждому чиху. Посмотрим что дальше будет.
                      Александр Туниеков
                      14 ноября 2019, 23:36
                      0
                      В файле core/components/pdotools/model/pdotools/_fenom.php
                      Можно дописать модификатор
                      $this->_modifiers['ignore'] = function ($string) {
                                  return "{ignore}".$string."{/ignore}";
                      };
                      И затем выводить контент так
                      {$_modx->resource.content | ignore}
                      В следующий PR включу :-).
                        Максим
                        26 ноября 2019, 08:28
                        +1
                        Приведите конкретный пример.
                        Какой именно js-код нельзя вынести в отельный файл?
                          Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                          32