Skip to content

Compiling inline HTML to createRawSnippet #16987

@HighFunctioningSociopathSH

Description

Describe the problem

One of the things that empowers Svelte is its compiler, which gives it superpowers, and I was wondering why, when Svelte is a compiler, we can't have support for JSX-like syntax. Snippets are one of the best features of Svelte 5, and I was wondering if Svelte's compiler can turn HTML written inside the script tag to createRawSnippet functions, which could help the compiler shine.

Describe the proposed solution

Let's say we have an object with a bunch of properties that are all Snippets. Right now, we should either manually create the Snippets using createRawSnippet or create them inside the template using #snippet block. Let's say we have similar-looking snippets that we want to pass to this object, so we would do something like =>

<script lang="ts">
  const someObj = $state({
    firstItem: redLi,
    secondItem: blueLi,
  });
</script>

{#snippet redLi()}
  <li style="background: red;">red list item</li>
{/snippet}

{#snippet blueLi()}
  <li style="background: blue;">blue list item</li>
{/snippet}

Now, you might immediately say, make a single snippet and use parameters for dynamic parts. Let's do that =>

<script lang="ts">
  const someObj = $state({
    firstItem: listItem,
    secondItem: listItem,
  });
</script>

{#snippet listItem(color: string)}
  <li style="background: {color};">{color} list item</li>
{/snippet}

But now the issue is, we are leaving it to the renderer of the snippet to decide on the color, but we don't want that, so we try doing something like =>

<script lang="ts">
  const someObj = $state({
    firstItem: () => listItem("red"),
    secondItem: () => listItem("blue"),
  });
</script>

{#snippet listItem(color: string)}
  <li style="background: {color};">{color} list item</li>
{/snippet}

{@render someObj.firstItem()}

But as we all know, you can't do this or any similar way, such as func.bind
Now you are left with using createRawSnippet which results in something like =>

<script lang="ts">
  import { createRawSnippet } from "svelte";

  function getListItemSnippet(color: string) {
    return createRawSnippet(() => ({
      render: () => `<li style="background: ${color};">${color} list item</li>`,
      setup(element) {
        $effect(() => {
          (element as HTMLElement).style.setProperty("background", color);
        });
        $effect(() => {
          element.innerHTML = `${color} list item`;
        });
      },
    }));
  }
  const someObj = $state({
    firstItem: getListItemSnippet("red"),
    secondItem: getListItemSnippet("blue"),
  });
</script>

{@render someObj.firstItem()}
{@render someObj.secondItem()}

Now don't you think it would be really nice if the Svelte compiler could turn the following code =>

<script lang="ts">
  const someObj = $state({
    firstItem: <li style="background: red;">red list item</li>,
    secondItem: <li style="background: blue;">blue list item</li>,
  });
</script>

Into =>

<script lang="ts">
  import { createRawSnippet } from "svelte";

  const someObj = $state({
    firstItem: createRawSnippet(() => ({ render: () => `<li style="background: red;">red list item</li>` })),
    secondItem: createRawSnippet(() => ({ render: () => `<li style="background: blue;">blue list item</li>` })),
  });
</script>

Under the hood.
It would be nice to have this. The compiler can be put to great use in a scenario like this, and I believe this would make working with loops a lot easier, just like JSX. It is kind of like what Svelte already does for the template, but in the script section.

Of course, the example above is pretty simple, but in real applications, you would need to generate stuff like AST, server and client codes, hydration code and other things like that. That's why I was hoping the Svelte's compiler could actually do the creation of the raw snippet for me since it's already doing it for the HTML section.

Importance

nice to have

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions