add an script tag in iframe whose content is getting set by srcdoc

1.9k views Asked by At

So What I want to do is something like this - lets say I have an htmlString like this --

let htmlString = `<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
            <img src="https://images.unsplash.com/photo-1593642532744-d377ab507dc8?ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80"/>
    <div id="root"></div>
    <script type="text/jsx">
      ReactDOM.render(
        <h1>Hello, React!</h1>,
        document.getElementById('root')
      );
    </script>
  </body>
</html>`

I want to modify this strings and add an -- another script tag as -- first script tag -- to get the output string as --

let htmlString = `<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
    <script src="">console.log("Script Added at top")</script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
            <img src="https://images.unsplash.com/photo-1593642532744-d377ab507dc8?ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80"/>
    <div id="root"></div>
    <script type="text/jsx">
      ReactDOM.render(
        <h1>Hello, React!</h1>,
        document.getElementById('root')
      );
    </script>
  </body>
</html>`

I don't know how many other tags will be there inside the head tag, so can't do a simple find and replace

1

There are 1 answers

6
mplungjan On

DOME manipulation could work but you would never be able to insert your script as the first script to execute:

NOTE: This will not work in a stacksnippet - try it on your own server

const html = `<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"><\/script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"><\/script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"><\/script>
  </head>
  <body>
            <img src="https://images.unsplash.com/photo-1593642532744-d377ab507dc8?ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80"/>
    <div id="root"></div>
    <script type="text/jsx">
      ReactDOM.render(
        <h1>Hello, React!</h1>,
        document.getElementById('root')
      );
    <\/script>
  </body>
</html>`
const script = document.createElement("script");
script.textContent = `console.log("Script Added at top")`;
const iframe = document.createElement("iframe");
iframe.src = 'data:text/html;charset=utf-8,' + encodeURI(html);
document.body.appendChild(iframe);
const doc = iframe.contentWindow;
doc.querySelector("head").appendChild(script);

You can remove the \ from /script if the script is external

let html = `<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"><\/script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"><\/script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"><\/script>
  </head>
  <body>
            <img src="https://images.unsplash.com/photo-1593642532744-d377ab507dc8?ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80"/>
    <div id="root"></div>
    <script type="text/jsx">
      ReactDOM.render(
        <h1>Hello, React!</h1>,
        document.getElementById('root')
      );
    <\/script>
  </body>
</html>`.split("\n")
html.splice(4,0,`    <script src="">console.log("Script Added at top")<\/script>`)
const htmlString = html.join("\n")
console.log(htmlString)

Insert before any script:

let htmlString = `<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"><\/script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"><\/script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"><\/script>
  </head>
  <body>
            <img src="https://images.unsplash.com/photo-1593642532744-d377ab507dc8?ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80"/>
    <div id="root"></div>
    <script type="text/jsx">
      ReactDOM.render(
        <h1>Hello, React!</h1>,
        document.getElementById('root')
      );
    <\/script>
  </body>
</html>`
parts = htmlString.split("<script")
parts[0] += `    <script src="">console.log("Script Added at top")<\/script>\n     `;
htmlString = parts.join("<script")
console.log(htmlString)