HTML Tidy терпит неудачу в теге скрипта в строковой литературе JavaScript

Я использую 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 – мой любимый)