Как сделать так, чтобы Fenom не ломал сайт?
Вопрос такой — есть ли способ сделать так, чтобы Fenom не ломался после того, как наткнется на «неожиданный символ», который тут поставлен не для него, а просто в коде JS/JSON/..? (Не {ignore})
Ситуация простая и понятная — на сайте стоит феном и активно используется везде. Но если вставить какой-нибудь JS код, или иной код с фигурной скобкой — все. Страница не открывается. Ошибка в логе.
Я знаю, что есть {ignore}, но это не решение, когда менеджер может вставить JS Код в редакторе.
Эмоциональное дополнение — И в принципе это мне кажется очень недружелюбным подходом, т.к. в любом месте сайта может появиться скобочка (например вставили счетчик в шаблон), и сайт ломается. Я уверен, что так быть не должно. Почему бы феному просто не проигнорировать тот набор символов, которые он не может прочитать? Почему он должен ломать всю страницу, если ему что-то не понравилось!? И для тестирования просто иметь иметь какую-то настройку — типа «строгий режим» для разработки, и мягкий — для рабочего сайта.
Я понимаю, что есть полу-решения, например — обернуть вызов [[*content]] в {ignore}. Но что если на какой-то странице шаблона мне все таки нужен синтаксис Fenom? То есть это не универсальное решение, а костыль.
Upd
С подачи Артема разместил вопрос на Гитхабе — github.com/fenom-template/fenom/issues/308
Я знаю, что есть {ignore}, но это не решение, когда менеджер может вставить JS Код в редакторе.
Эмоциональное дополнение — И в принципе это мне кажется очень недружелюбным подходом, т.к. в любом месте сайта может появиться скобочка (например вставили счетчик в шаблон), и сайт ломается. Я уверен, что так быть не должно. Почему бы феному просто не проигнорировать тот набор символов, которые он не может прочитать? Почему он должен ломать всю страницу, если ему что-то не понравилось!? И для тестирования просто иметь иметь какую-то настройку — типа «строгий режим» для разработки, и мягкий — для рабочего сайта.
Я понимаю, что есть полу-решения, например — обернуть вызов [[*content]] в {ignore}. Но что если на какой-то странице шаблона мне все таки нужен синтаксис Fenom? То есть это не универсальное решение, а костыль.
Upd
С подачи Артема разместил вопрос на Гитхабе — github.com/fenom-template/fenom/issues/308
Комментарии: 32
Сергей, полностью разделяю ваше негодование. Кроме того, совсем недавно я узнал, что даже тег {ignore} не всегда может спасти, в комментарии было написано, что при использовании этого специального тега, нужно после всех фигурных скобок ставить пробел. Когда я его прочитал, был в шоке, в коде вообще какой-то огород получается. После этого у меня в голове поломались все принципы программирования. До сих пор задаюсь вопросом, почему разработчик решил использовать именно фигурную скобку для своего парсера, ведь она очень часто используется при верстке сайтов, как он мог это не учесть? Если кто-то знает ответ, поделитесь пожалуйста, чтобы я наконец перестал ломать свою голову )))
Сергей, я полностью Вас поддерживаю в вашем вопросе, мое мнение, что действительно необходимо что-то с этим делать, так быть не должно.
Теперь готов выслушать критику. )))
Сергей, я полностью Вас поддерживаю в вашем вопросе, мое мнение, что действительно необходимо что-то с этим делать, так быть не должно.
Теперь готов выслушать критику. )))
Фигурная скобка используется почти любым шаблонизатором. Де-факто это стандарт.
По поводу поста — я в целом согласен.
По поводу поста — я в целом согласен.
Павел, спасибо Вам за ответ, теперь более или менее стало понятно. ?
ну а пройтись автозаменой по js коду? И поставить пробел после открывающейся скобки тяжело?
Василий, а если она встречается не только в JS, а и в других местах, например, на сайте используется математика, там таких фигурных скобок предостаточно используется, как в этом случае быть? Запаришься пробелы ставить. Да и не удобно это, забыл пробел поставить, и все приплыли. )))
И еще, Сергей пишет о том, что менеджер может в любой момент вставить фигурную скобку в редакторе, и что постоянно за ним следить? Тут конечно единственный вариант, использовать тег {ignore}, других вариантов не вижу.
И еще, Сергей пишет о том, что менеджер может в любой момент вставить фигурную скобку в редакторе, и что постоянно за ним следить? Тут конечно единственный вариант, использовать тег {ignore}, других вариантов не вижу.
В случае с менеджером, можно написать плагин, который при сохранении страницы заменяет все фигурные скобки на мнемонику или аналог или вообще вырезает их, если это не уместно.
Ну ведь это же костыль… А что если менеджер ± программист и может поправить шаблон. И в принципе вопрос не в том «как замотивировать себя уделять больше времени сайту», а в том «как облегчить себе жизнь» и сделать так, чтобы было невозможно выстрелить себе в ногу.
Или, допустим у меня есть большой сайт без фенома, и я делаю рефакторинг, внедряю феном. Тут уже программист, а не менеджер может что-то упустить.
Или текстовый редактор может быть не только у контента. Или — текстовый редактор может впоследствии появится у какого-то поля, в которое менеджер скопирует некий невалидный код.
Сценариев масса, и писать плагин на обработку каждого ТВ поля — это очень грустный сценарий.
Или, допустим у меня есть большой сайт без фенома, и я делаю рефакторинг, внедряю феном. Тут уже программист, а не менеджер может что-то упустить.
Или текстовый редактор может быть не только у контента. Или — текстовый редактор может впоследствии появится у какого-то поля, в которое менеджер скопирует некий невалидный код.
Сценариев масса, и писать плагин на обработку каждого ТВ поля — это очень грустный сценарий.
Вообще js выносят в файлы обычно из HTML, а там нет разницы
Василий, поверьте, не всегда получается полностью вынести JS из тела страницы. Иногда он там просто необходим.
Писать плагины для решения конкретных задач — это теперь костыль?
Собственно, нравится Fenom — извольте учитывать его особенности и решать их при необходимости.
Если вы хотите, чтобы проблему решили в ядре, то вы явно не по адресу, вам сюда: github.com/fenom-template/fenom/issues
Если не нравится особенность Fenom'а, то всегда можно отказаться от него в пользу доисторических фильтров MODX.
Собственно, нравится Fenom — извольте учитывать его особенности и решать их при необходимости.
Если вы хотите, чтобы проблему решили в ядре, то вы явно не по адресу, вам сюда: github.com/fenom-template/fenom/issues
Если не нравится особенность Fenom'а, то всегда можно отказаться от него в пользу доисторических фильтров MODX.
Да, я держу в голове вариант «не нравится — дверь вон там», но данным вопросом я просто хочу узнать, есть ли у кого-то решение подобной проблемы, т.к. предполагаю, что с этой болью сталкивались (почти) все. И да, я ищу такое решение, которое бы гарантировало бы отсутствие ошибки. На мой взгляд плагин в предложенном виде этого не гарантирует.
Я ищу вариант плагина, который не давал бы феному положить сайт. Но как именно его написать я не представляю. Но теоретически мне кажется можно, т.к. феном ведь генерирует ошибку, и указывает на строку. Но вот вместо ошибки переключить бы парсер в режим «ignore» для этой части кода. Может быть у кого-то есть подобное решение?
Я ищу вариант плагина, который не давал бы феному положить сайт. Но как именно его написать я не представляю. Но теоретически мне кажется можно, т.к. феном ведь генерирует ошибку, и указывает на строку. Но вот вместо ошибки переключить бы парсер в режим «ignore» для этой части кода. Может быть у кого-то есть подобное решение?
т.к. предполагаю, что с этой болью сталкивались (почти) всетак и есть, все и решают ее традиционными способами: либо вы выставляете ручками везде дополнительные пробелы, либо вы погружаетесь в эту статью и вникаете в принцип работы {ignore}, чтобы понимать, где он сработает, а где нет, а затем комбинируете это с первым вариантом, либо вы пишете свой плагин, который обрабатывает нужный вам контент, ищет вхождения регуляркой и заменяет их, добавляя дополнительный пробел. Собственно, это просто автоматизированный первый вариант.
Простой плагин на событие OnLoadWebDocument
Срабатывает до парсинга тегов. Получаем любое поле ресурса, и заменяем скобки на спецсимволы. Пробел после добавил, иначе они преобразуются в скобку здесь на сайте. Так можно прогнать все поля, которые заполняет контент-менеджер. Причём плагин заменяет скобки только в момент открытия страницы. Исходники по факту остаются не тронутыми.
<?php
$pagetitle = $modx->resource->pagetitle;
$pagetitle = str_replace('{', ' 123;', $pagetitle);
$pagetitle = str_replace('}', ' 125;', $pagetitle);
$modx->resource->set('pagetitle', $pagetitle);
Срабатывает до парсинга тегов. Получаем любое поле ресурса, и заменяем скобки на спецсимволы. Пробел после добавил, иначе они преобразуются в скобку здесь на сайте. Так можно прогнать все поля, которые заполняет контент-менеджер. Причём плагин заменяет скобки только в момент открытия страницы. Исходники по факту остаются не тронутыми.
Соглашусь, с плагином может сработать, но все зависит от того, что там менеджер добавляет, возможно ли будет все нюансы предусмотреть, я о том, как понять, нужна в данном случае фигурная скобка или нет, или ее нужно заменить на мнемонику? Нужно смотреть. И опять же получается, что необходимо еще доп плагины писать, то есть постоянно нужно искать какие-то дополнительные решения, к тому, что имеется. Мое мнение, все должно работать без лишних наворотов. Может я конечно и ошибаюсь.
Вы абсолютно правы, да должно! Вы можете взять и сделать так, чтобы все работало без лишних наворотов, все скажут вам спасибо!
можете взять и сделать так, чтобы все работало без лишних наворотов, все скажут вам спасибо!Вроде предложил решение, чтоб все работало без наворотов, а спасибо не от кого не слышно :-).
Предложить и сделать — это разные вещи.
Конечно разные. Однако прежде чем сделать всегда есть идея что сделать. Без нее делать то нечего :-). Так вот, идея есть и она предложена на рассмотрение, а сделать в процессе и зависит, в общем-то, от итогов рассмотрения.
И поддержка от заинтересованных лиц не помешала бы. А вот заинтересованные лица «жуют попкорн» :-).
И поддержка от заинтересованных лиц не помешала бы. А вот заинтересованные лица «жуют попкорн» :-).
Это лучше обсуждать в репозитории Фенома, создав либо issue, либо PR.
Так обсуждается уже :-). В теме ссылка.
Вопрос актуальный. Тоже на этой скобке проблемы вылазят. Взглянул на исходники 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
не создавалось исключение с обрывом компиляции, а чтоб ошибка кидалась в лог и компиляция продолжалась.
Лог прикрутить довольно сложно.
Можно сделать костыль. Вместо исключения
Ну вот так по идее можно решить проблему :-)
В принципе, ее там можно заменить чем-то другим, но спецсимволов на клаве не так много, и все где-то используются. А двойным символом заменять не красиво и не удобно :-(.
Думаю лучше чтоб на этой строке 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. Ну вот так по идее можно решить проблему :-)
Сейчас как только возникает ошибка, сразу же её видно, можно за несколько секунд заяндексить и исправить.
По-вашему рецепту эта ошибка вылезет намного позже и с наслоениями, вероятно у других людей, возможно у менеджеров.
По-вашему рецепту эта ошибка вылезет намного позже и с наслоениями, вероятно у других людей, возможно у менеджеров.
Сейчас ошибка возникает фиг знает где. Вот последний случай. Мне понадобилось включить fenom на страницах готового сайта. И сайт стал показывать пустые страницы. В логах
Оказалось в шаблоне нашел и поправил быстро. Но пришлось поволноваться. Ошибку вызывает вызов типа
Вчера я наметил идею. То есть, не окончательный вариант. Счас попробуем реализовать.
Реализовал. Вот изменения:
Файл core/components/pdotools/vendor/fenom/fenom/src/Fenom/Template.php со строки 273
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 отработали бы без ошибок.
В сниппете ошибка. В коде страницы поправил, а здесь забыл.
[[!pdoResources?
&parents=`1`
&where=`{"active":1}`
]]
Оказалось в шаблоне нашел и поправил быстро. Но пришлось поволноваться.Вот именно про это я написал. В процессе написания сайта вы всегда помните свои последние действия, в крайнем случае можно просто их отменить.
А теперь представьте, что сайт уже ушел менеджеру, и он случайно в меню нашел кнопку «Обновить», по привычке с Гмаркетом или Апстором нажал её не сделав бэкапы…
По-вашему рецепту эта ошибка вылезет намного позже и с наслоениями, вероятно у других людей, возможно у менеджеров.Если не правильно написан тег фенома, то на странице он просто выведется и в логе MODX будет описание. То есть ошибку сразу видно и плюс видно сам не правильный тег. А если на феном переводиться готовый сайт, то все JS/JSON будут работать как и работали. Без проблем. И если менеджер введет проставит фигурные скобочки в контент, то они так же отобразятся.
Единственное если менеджер поставит открывающую скобку без закрывающей, то сайт сломается на строке github.com/fenom-template/fenom/blob/fc188a582229c7735df1bb584eb268548a957f46/src/Fenom/Template.php#L248 Но я даже не знаю как это обойти :-(. Можно, конечно, так же, вместо исключения, запихать ошибку в лог и тег проигнорировать, но скорее всего fenom поймает закрывающую скобку хорошего тега и сайт снова сломается. В смысле поломается порядок тегов. Вместо {'asd' | snippet} в обработку попадет {текст {'asd' | snippet}
Так, кто хочет решить проблему, помогайте разрабам объяснить, что проблема есть и ее нужно решать :-).
А то чувствую в отказ уйдут.
github.com/fenom-template/fenom/issues/308
А то чувствую в отказ уйдут.
github.com/fenom-template/fenom/issues/308
Еще бы Василия привлечь к обсуждению, но у него issues закрыт github.com/bezumkin/pdoTools и где искать его контакты не понятно.
Сделал 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.Транспортный пакет с правками pdoTools и fenom file.modx.pro/files/7/5/8/758e797e15b740fd58e7993054996bc3.zip (переименовать в pdotools-2.13.0-pl.transport.zip)
Изменения вносятся одновременно в 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} и т.д.).
Есть желающие протестировать? Вдруг что-то еще поправить надо.
Мне кажется, сейчас сайт сломаешь, если только специально ломать.
Вставляю
А вот это могут :-(.
Ну меня, пока, устраивает, что не ломается по каждому чиху. Посмотрим что дальше будет.
Вставляю
{
{$_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}А вот это могут :-(.
Ну меня, пока, устраивает, что не ломается по каждому чиху. Посмотрим что дальше будет.
В файле core/components/pdotools/model/pdotools/_fenom.php
Можно дописать модификатор
Можно дописать модификатор
$this->_modifiers['ignore'] = function ($string) {
return "{ignore}".$string."{/ignore}";
};
И затем выводить контент так{$_modx->resource.content | ignore}
В следующий PR включу :-).
Приведите конкретный пример.
Какой именно js-код нельзя вынести в отельный файл?
Какой именно js-код нельзя вынести в отельный файл?
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.