Я использую HTML Tidy в PHP, и он создает неожиданные результаты из-за <script>
в строковом литерале JavaScript. Вот пример ввода:
<html> <script> var t='<script><'+'/script>'; </script> </html>
Вывод HTML Tidy:
<html> <script> //<![CDATA[ var t='<script><'+'/script>'; <\/script> <\/html> //]]> </script> </html>
Он интерпретирует </script></html>
как часть скрипта. Затем он добавляет еще один </script></html>
чтобы закрыть открытые теги. Я пробовал это в онлайн-версии HTML Tidy ( http://www.dirtymarkup.com/ ), и это приводит к той же ошибке.
Как предотвратить эту ошибку в PHP?
Немного поиграв с ним, я обнаружил, что можно использовать комментарий //'<\/script>'
чтобы запутать алгоритм таким образом, чтобы эта ошибка не возникала:
<html> <script> var t='<script><'+'/script>'; //'<\/script>' </script> </html>
После очистки:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN"> <html> <head> <script> var t='<script><'+'/script>'; //'<\/script>' </script> <title></title> </head> <body> </body> </html>
Я предполагаю, что, поскольку алгоритм очистки просматривает коды и дважды обнаруживает строку <script>
, он ищет </script>
сразу. И разделение <
with /script>
делает второй </script>
неотвеченным, поэтому он решил добавить еще один </script>
в конце кода и как-то также закрыл его с помощью antoher </html>
. (Бедный дизайн!)
Поэтому я сделал второе предположение, что в алгоритме нет инструкции if, чтобы определить, есть ли </scirpt>
в комментарии, и я был прав! Наличие другой строки <\/script>
в качестве комментария javascript действительно заставляет алгоритм думать, что есть всего два </script>
.
Нет необходимости в конкатенации строк, чтобы избежать закрытия </script>
. Просто избежать символа /
достаточно, чтобы «обмануть» синтаксические анализаторы в браузерах и, кажется, также анализатор HTML Tidy:
<html> <script> var t='<script><\/script>'; </script> </html>
Попробуйте сделать тег сценария не полным, а конкатенацией строк
<html> <script> var t='<scr'+'ipt><'+'/script>'; </script> </html>
Полученный очищенный код
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN"> <html> <head> <script> var t='<scr'+'ipt><'+'/script>'; </script> <title></title> </head> <body> </body> </html>
Вероятно, это лучшая практика создания тега сценария, подобного этому: (это также должно решить ваши аккуратные проблемы)
<script> script = document.createElement('script'); script.type = 'text/javascript'; script.src = 'http://myserver.com/file.js'; document.getElementsByTagName('head')[0].appendChild(script); </script>
Один из способов сделать так, чтобы он был аккуратным, не обнаруживает тег сценария. «Самый чистый» способ, с помощью которого я мог придумать, – избегать символа в теге.
<html> <script> var t='<\script><'+'/script>'; </script> </html>
так что вы могли бы даже сделать это, не нарушая строчку, как указано выше:
var t='<\script></\script>';
Это работает так, как ожидалось
<html> <script> var t='<'+'script><'+'/script>'; </script> </html>
Кстати, конкатенация строк – не лучший способ создать динамически HTML для вставки на страницу, искать механизмы document.createElement или даже шаблоны (handlebars.js – мой любимый)