На сайте eMy wordpress есть настраиваемый тип записи под названием tool, который имеет три настраиваемых поля с именами html, css и js. Этот тип сообщения инструмента отображается на моем сайте с помощью пользовательского шаблона и шорткода, который отображает содержимое полей html, css и js в iframe. Этот шорткод создается функцией в моем файле functions.php, и упрощенная версия этой функции выглядит так:
function renderTool() {
return '
<html>
<head>
<script
src = "https://kit.fontawesome.com/c48c422dea.js"
crossorigin = "anonymous"
></script>
<style>
.container {background:blue;}
</style>
</head>
<body>
<div id = "container" class = "container">
<div id = "tool" class = "tool cssreset">
<iframe src = "data:text/html;charset=utf-8,' .
'<html>
<head>
<style>' . htmlspecialchars(get_field("css")) . '</style>
<script>' . htmlspecialchars(get_field("js")) . '</script>
</head>
<body>' . htmlspecialchars(get_field("html")) . '</body>
</html>'
. '"></iframe>
</div>
<div class = "bar" id = "bar">
<i class = "toggle fa fa-solid fa-expand"></i>
</div>
</div>
<script>
function myfunction() {
console.info("hello world");
}
</script>
</body>
</html>';
}
Проблема с этим кодом заключается в том, что когда я использую шорткод, который запускает эту функцию, он отображает только css, а html и js отображаются в виде простого текста.
Я поговорил об этом с чатом openai, и он порекомендовал мне сохранить содержимое iframe в отдельном html-файле, а затем установить iframe src в этот html-файл как таковой:
$css = htmlspecialchars(get_field("css"));
$js = htmlspecialchars(get_field("js"));
$html = htmlspecialchars(get_field("html"));
// Create the inner document and save it to a separate file
$inner_document = '
<html>
<head>
<style>
'. $css .'
</style>
<script>
'. $js .'
</script>
</head>
<body>
'. $html .'
</body>
</html>
';
file_put_contents('inner-document.html', $inner_document);
// Use the inner document as the src for the iframe
return '<iframe src = "inner-document.html"></iframe>';
Эта идея мне уже не нравится, потому что кажется, что она еще больше все усложняет. Когда я пытался использовать этот код, iframe вместо этого отображал страницу, на которой я был, и в ней такой же сломанный iframe. iframeception.
Еще одна вещь, которую я пробовал, заключалась в передаче html, который должен быть в iframe внутри urlencode как таковой: (это фрагмент, этот код заменит iframe в моем текущем подходе)
<iframe src = "data:text/html;charset=utf-8,' . urlencode(
'<html>
<head>
<style>' . htmlspecialchars(get_field("css")) . '</style>
<script>' . htmlspecialchars(get_field("js")) . '</script>
</head>
<body>' . htmlspecialchars(get_field("html")) . '</body>
</html>'
) . '"></iframe>
Это просто отобразило его как необработанный текст, по крайней мере, в правильные элементы html (посмотрите https://prnt.sc/4I24tFgxQ56m)
Чтобы уточнить, эти get_field() функции взяты из плагина WordPress под названием acf, см. документацию здесь: https://www.advancedcustomfields.com/resources/get_field/
Из всей этой информации я пришел к выводу, что ошибка должна быть связана с тем, что строковые литералы не экранированы должным образом и, следовательно, конфликтуют с/вызывают возврат остальных значений в строковом формате. Тем не менее, я надеялся, что htmlspecialchars решит эту проблему, но это помогло только с рендерингом CSS. В моем текущем решении я помещаю весь код, который хочу отобразить, в источник iframe, используя URL-адрес данных, поэтому закрывающий тег iframe идет после содержимого iframe.
Чтобы вы могли лучше представить, что я пытаюсь донести, вот ссылка на страницу, которая страдает этой ошибкой: https://tropical.team/tools/calculator. Возможно, у меня все еще есть тестовый код, поэтому вы увидите что-то немного отличающееся от того, что я описал, но я попытаюсь изменить его на это, когда вернусь.
Вчера я болтал с
@FiddlingAway это были просто опечатки, поскольку этот код является переделанной копией фактического кода, они не вызывают проблемы, поскольку этих ошибок не существует в фактическом коде, я исправил это сейчас
Так проблема решена? Я перешел по вашей ссылке, и калькулятор отображается правильно (хотя в консоли есть ошибка JS, но я предполагаю, что вы работаете над ней в это время).
HTML отображается, а css и js - нет, проверьте элемент инструмента и просмотрите его содержимое, вы можете увидеть, что некоторый код отображается как текст, вычисленный считается правильно обработанным, когда он имеет желтый фон и работает, так что теперь его только 1/3
Ваш открывающий тег iframe все еще не закрыт. Вам не хватает > после объявления кодировки. Кроме того, вместо этого htmlspecialchars(...) используйте это htmlspecialchars_decode(...), если HTML-контент, хранящийся в вашей БД, прошел htmlspecialchars перед вставкой в БД.
Он закрыт, посмотрите еще раз, но на самом деле я не помещаю весь код в iframe, я помещаю его в значение src в качестве URL-адреса данных, потому что размещение его внутри iframe (между начальным и закрывающим тегами) не делает что-либо.
Да, я пропустил ту часть о том, что HTML находится внутри src, извините за это. В таком случае, как насчет использования urlencode(...)? Вам это нужно, потому что вы устанавливаете его как содержимое файла src. Пожалуйста, посмотрите это изображение , чтобы понять, что я имею в виду. urlencoded версия HTML также используется в этом ответе SO.
Я пробовал это, но потом он тоже сломался: prnt.sc/4I24tFgxQ56m
Не уверен, почему это происходит. Давайте пока откажемся от этого маршрута, попробуем еще кое-что, а потом я сдамся. Глядя на ваш сгенерированный код, я заметил, что элемент script внутри iframe использует кавычки для своего атрибута src. Я думаю, что это может нарушить ваш код — пожалуйста, посмотрите это изображение, если это звучит так, как будто я не имею никакого смысла. Решение этого было бы только временным решением, так как оно сработает только в этом случае - urlencode должно было сработать изначально, и я, честно говоря, не знаю, почему это не сработало.
Я исправил эту часть jsut, потому что мой плагин кэширования, как обычно, превращал мою жизнь в ад, я исключил модификации js-файлов для этих страниц, и теперь javascript правильно добавлен в заголовок. Калькулятор по-прежнему не работает, и в настоящее время я пытаюсь выяснить, является ли это ошибкой с PHP или просто фактическим кодом калькулятора.
Хорошо, рад, что вы решили эту часть. После публикации моего предыдущего комментария я понял, в чем проблема с urlencode — пробелы закодированы как +, и поэтому вы видели их повсюду. Я должен был порекомендовать rawurlencode - это будет кодировать пробелы как %20. Что касается выполнения скрипта - пожалуйста, ознакомьтесь с этим ТАКИМ вопросом и соответствующими ответами.
Я только что попытался использовать rawurlencode, и он лучше, но все еще не работает, просмотрите tropical.team/tool/calculator-2-0 и prnt.sc/tynlQTNv9JAh
Визуализированное тело вашего iframe, кажется, содержит HTML-документ внутри с содержимым, которое выглядит так, как будто оно было просмотрено htmlcharacters(). Можете ли вы проверить свой фоновый код, в частности этот: get_field("html"), и убедиться, что он не содержит ничего похожего на <html><head>...</head><body>....</body></html>?
это так, каждый раз, когда это будет, я думаю, использование srcdoc было бы более подходящим
@FiddlingAway есть идеи, как я могу справиться с тем фактом, что js не работает, я предполагаю, что это потому, что ссылки document.somrthing не применяются к фреймам, но относится ли это и к srcdoc?
Потому что это внедрение скрипта - попробуйте.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вместо того, чтобы передавать html в качестве URL-адреса данных, лучше использовать атрибут srcdoc для iframe. Это позволяет вам передать ему строку (html) и отобразить ее правильно. Вам придется сохранить функцию htmlspecialchars, потому что в противном случае двойные кавычки, которые могут быть возвращены get_field в том виде, в каком он отправлен пользователем, завершат строку значения srcdoc.
В вашем исходном коде внутри возвращаемой строки есть
echo. Кроме того, открывающий тег вашегоiframeустановлен неправильно — он находится за пределами строки, которую вы возвращаете.