eMy wordpress site has a custom post type called tool, which has three custom fields called html, css, and js.  This tool post type is displayed on my site with a custom template, and a shortcode that renders the contents of the html, css, and js fields in an iframe. This shortcode is created by a function in my functions.php file, and a simplified version of this function looks like this:
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.log("hello world");
         }
           </script>
  </body>
  </html>';
}
The problem with this code is that when i use the shortcode which runs this function, it only renders the css, and the html and js are rendered in plain text.
I chatted with openai's chatgpt about it and it recommended me to store the iframe contents in a seperate html file and then to set the iframe src to this html file as such:
$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>';
This soultion i already dislike because it just seems like it is complicating things even more. When i did try to use this code, the iframe instead rendered the page i was on and an equally broken iframe in it. iframeception.
Another thing i tried was passing the html that should be in the iframe inside a urlencode as such: (this is a snippet, this code would replace the iframe in my current approach)
<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>
This just rendered it as raw text into the correct html elements at least (view https://prnt.sc/4I24tFgxQ56m)
To clarify further, these get_field() functions are from a wordpress plugin called acf, view the documentation here: https://www.advancedcustomfields.com/resources/get_field/
From all of this information i concluded that the error must stem from the string literals not properly being escaped and therefore conflict with/ cause the rest of the values to be returned in string format. Yet i was hoping that the htmlspecialchars was gonna solve it, but it only helped with rendering CSS. In my current solution, I put all the code I want to render inside the iframe's source using a data URL, the iframe closing tag comes after the content of the iframe therefore.
So you can further visualize what i am trying to convey, here is the link to the page that is suffering this bug: https://tropical.team/tools/calculator. It is posible i still have some testing code on here so you will see something a bit diffrent than i described but i will try to change it to this when i get back.
I chatted with chatGPT for over 3 hours yesterday but concluded that when i realized that it started going in circles. I doubt there is a replacement for the get_field function, or an argument that would help with this, but if there is do tell me, i also have yet to integrate validation for those html, css, and js fields, so for now, just expect proper code being passed.