Skip to content

String doesn’t accept the close tag for

I am building a code-editor, and below is my code:

<template>
  <div>
    <textarea
      id="html"
      placeholder="HTML"
    ></textarea>
    <textarea
      id="css"
      placeholder="CSS"
    ></textarea>
    <textarea
      id="js"
      placeholder="JavaScript"
    ></textarea>
    <iframe id="code"></iframe>
  </div>
</template>

<script>
export default {
  name: 'code-editor',
  mounted () {
    this.compile();
  },
  methods: {
    compile () {
      var html = document.getElementById("html");
      var css = document.getElementById("css");
      var js = document.getElementById("js");
      var code = document.getElementById("code").contentWindow.document;

      document.body.onkeyup = function () {
        code.open();
        code.writeln(
          `${html.value} <style> ${css.value} </style> <script> ${js.value} <script> `
        );
        code.close();
      };
    }
  }
}
</script>

<style>
textarea {
  width: 32%;
  /* float: top; */
  min-height: 250px;
  overflow: scroll;
  margin: auto;
  display: inline-block;
  background: #f4f4f9;
  outline: none;
  font-family: Courier, sans-serif;
  font-size: 14px;
}

iframe {
  bottom: 0;
  position: relative;
  width: 100%;
  height: 35em;
}
</style>

Inside my onkeyup function in the writeln command, with the above string I get this error:

 error  in ./src/components/CodeEditor.vue?vue&type=script&lang=js&

Syntax Error: Unterminated template (35:75)

  33 |         code.open();
  34 |         code.writeln(
> 35 |           `${html.value} <style> ${css.value} </style> <script> ${js.value} 
     |                                                                            ^

But then if I remove the </script> tag from the string it works. I don’t know why it doesn’t accept the close tag.

Can anyone explain this to me? Is there any way to make it accept the </script> tag?

Answer

You need it to break the </script> into "<" + "/script>" so that the HTML parser doesn’t interpret it as the closing tag. You can also do </script>.

An example of how it works:

<script>
  console.log("hello </script>");
  console.log("hello <" + "/script>");
</script>

And an example of how it wouldn’t work (with plain </script> which would be interpreted as the closing tag):

<script>
  console.log("hello </script>");
</script>

And if you want to use it inside back quotes, still the same (adding this per OP’s comment):

<script>
  let foo = "foo";
  console.log(`hello ${foo} </script>`);
</script>