sveltejs / kit

web development, streamlined
https://kit.svelte.dev
MIT License
18.44k stars 1.89k forks source link

Issue when content rendered with `{@html ...}` contains a script tag #9870

Closed renevanpelt closed 1 year ago

renevanpelt commented 1 year ago

Describe the bug

When I retreive html from the backend using fetch, I can use the { @html 'bar' } syntax.

However, whenever that html markup contains, for example, an embeddable widget. Like an embedded tweet or instagram post, the rendering becomes unreliable.

Basically, when I get the page directly from typing in the url in the browser, everything is rendered well. But when I navigate to such a page with an internal link, it doesn't.

When trying to replicate this in this REPL I run into another few problems:

  1. It doesn't work on the first request now
  2. When I try to get the "</script>" string into a variable, the compiler complains (see image).

image

Am I doing something wrong? Can't find any documentation on the subject.

Thanks.

Reproduction

REPL

Logs

No response

System Info

See the REPL, I guess?

Severity

blocking an upgrade

Additional Information

No response

fiorelorenzo commented 1 year ago

I don't think any of your issues are SvelteKit issues:

  1. looks like a CORS problem;
  2. is fixed by escaping the / with a \, like this: ... <\/script>";.
Rich-Harris commented 1 year ago

Yeah the </script> thing is expected. That sequence of characters in HTML will always close any currently open <script> element, even if it's inside a string or a comment, and Svelte inherits that behaviour. It looks like the REPL has since been updated and I'm not seeing the error overlay, is there still an issue here?

renevanpelt commented 1 year ago

Yeah the </script> thing is expected. That sequence of characters in HTML will always close any currently open <script> element, even if it's inside a string or a comment, and Svelte inherits that behaviour. It looks like the REPL has since been updated and I'm not seeing the error overlay, is there still an issue here?

Thanks, I understand the </script> thing now. In the REPL, I've done a little trick so that the string is split up and doesn't contain </script>

I have updated a REPL to show my situation.

I'm not sure how to reproduce my problem, since the embed has a CORS issue in the REPL.

The problem is pretty simple: When I retreive an embed script like that from our backend as part of the body for an article. It works perfectly when I navigate straight to the page by typing in the URL in the browser. However, navigating to it from another page on the same site gives the result as shown in the REPL (but maybe due to a different reason).

If I knew how to describe it better, I would! Thanks for bearing with me here.

Rich-Harris commented 1 year ago

I'm not sure how to reproduce my problem, since the embed has a CORS issue in the REPL.

Create a clonable repo! Since SvelteLab doesn't currently offer download (AFAICT) I recommend either publishing something to GitHub, or using StackBlitz as suggested in the issue template.

However, navigating to it from another page on the same site gives the result as shown in the REPL

That's because <script> executes synchronously when loading a page, but if you add it programmatically then it will execute whenever it happens to load, so it won't be ready by the time your component initializes. This isn't a Svelte/SvelteKit thing, it's just how browsers work.

If you want to wait until a script has loaded then you will need to add an onload handler e.g. in an onMount:

onMount(() => {
  const script = document.createElement('script');
  script.onload = () => {
    // ...
  };
  script.src = src;
});
paoloricciuti commented 1 year ago

I'm not sure how to reproduce my problem, since the embed has a CORS issue in the REPL.

Create a clonable repo! Since SvelteLab doesn't currently offer download (AFAICT) I recommend either publishing something to GitHub, or using StackBlitz as suggested in the issue template.

However, navigating to it from another page on the same site gives the result as shown in the REPL

That's because <script> executes synchronously when loading a page, but if you add it programmatically then it will execute whenever it happens to load, so it won't be ready by the time your component initializes. This isn't a Svelte/SvelteKit thing, it's just how browsers work.

If you want to wait until a script has loaded then you will need to add an onload handler e.g. in an onMount:

onMount(() => {
  const script = document.createElement('script');
  script.onload = () => {
    // ...
  };
  script.src = src;
});

Just hopping in to say that sveltelab does in fact provide downloadable code. You can search for download in the command palette 😉