Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possibility of writing snippets in .svelte.ts files #12713

Open
webJose opened this issue Aug 2, 2024 · 18 comments
Open

Possibility of writing snippets in .svelte.ts files #12713

webJose opened this issue Aug 2, 2024 · 18 comments

Comments

@webJose
Copy link
Contributor

webJose commented Aug 2, 2024

Describe the problem

AFAIK, writing snippets outside of Svelte component files is not possible. However, unit testing would greatly benefit from being able to define snippets in .svelte.ts files. Right now, we either create a helper component for the test, or use createRawSnippet API.

Describe the proposed solution

Be capable of writing snippets in codefiles anywhere (top level, inside function bodies, etc.), as if they were functions or similar.

Importance

nice to have

@paoloricciuti
Copy link
Member

Isn't createRawSnippet exactly this?

@Conduitry
Copy link
Member

createRawSnippet is the API for this, yes. I don't know what we would want to do differently in a .svelte.js file. If you want to write something that looks like a component, use a .svelte file. If you want to programmatically create a snippet, use createRawSnippet.

@Rich-Harris
Copy link
Member

In the medium term it would be nice to be able to export snippets from Svelte components, perhaps like this:

<script context="module">
  export { foo };
</script>

{#snippet foo()}...{/snippet}

There's no intention to create a way to define snippets declaratively outside .svelte files though. Creating them programmatically with createRawSnippet is the way to go.

@webJose
Copy link
Contributor Author

webJose commented Aug 2, 2024

I understand. It is just that the {#snippet} construct is easier than the raw API. Also, a question (or maybe a point in favor of allowing this): How does one create a snippet with createRawSnippet that includes a component, not just HTML elements? How would that look like?

And finally, the one other ask I have in my mind is the ability to unit-test the effects of bind:. I think libraries like @testing-library/svelte would require a public API that would allow this. I know, different topic, but since I got your attention, I figured I should ask.

@webJose
Copy link
Contributor Author

webJose commented Aug 2, 2024

Rich's medium term solution would be very good: One could then create .test.svelte component files that define and export the snippets for testing. Then it is a matter of importing them in the .ts/.svelte.ts test file.

@rChaoz
Copy link
Contributor

rChaoz commented Aug 2, 2024

Also, I believe this is a duplicate of #11261, which I opened a long time ago, and got downvoted into oblivion. I personally really like the idea but from the community's response it's really not good

@Antonio-Bennett
Copy link

@rChaoz I think ppl disliked the syntax maybe not so much the idea

@rChaoz
Copy link
Contributor

rChaoz commented Aug 2, 2024

I understand, but the issue has the syntax as a suggestion. The issue itself was to add some way to create snippets in *.svelte.js files. Anyhow, what would a good syntax be, that's better that the current API?

@webJose
Copy link
Contributor Author

webJose commented Aug 2, 2024

As Rich is proposing is good enough for me. No need for new fancy syntax, IMHO. Adding the ability to export snippets is an excellent midpoint since component files are not required to have templates or script tags. One can create, today, a snippet-only component file. All we need is the export part.

@rChaoz
Copy link
Contributor

rChaoz commented Aug 2, 2024

But can't snippets depend on component props? How to handle that case?

@Antonio-Bennett
Copy link

@rChaoz Since snippets are pretty much functions in my head you just have to ensure where you are using that exported snippet just pass the required params

@webJose
Copy link
Contributor Author

webJose commented Aug 2, 2024

I'm with Antonio: Regular snippets are not for exporting. Exported snippets are exported for a reason. Let it be part of the requirements that they need to be self-contained. Any dependencies, via the parameters.

@rChaoz
Copy link
Contributor

rChaoz commented Aug 2, 2024

@Antonio-Bennett
Copy link

My perspective is that context module is for the purpose of having shared state so therefore create a shared state to be used. Not sure if then you can use the new $state.link rune that’s coming to keep shared state in sync with a parent value passed into the component?

@webJose
Copy link
Contributor Author

webJose commented Aug 2, 2024

Why would you want to export that snippet? What would be the use case for that? I can only imagine exporting for reuse, if at all. After all, components are superior. I just want exported snippets for unit testing because one consume them in TS/JS files. For application development, I consume from .svelte files, so why would I go the route of snippets when I can go the route of components?

@7nik
Copy link

7nik commented Aug 3, 2024

I understand, my question is: should the following be prohibited? It feels like it would be a huge loss to me. Or, how should svelte figure out whether it can be exported?

https://svelte-5-preview.vercel.app/#H4sIAAAAAAAAA0WOzQrCMBCEXyVEDy0V6rm2RY_evVkPNd1iMN2EZCNIyLub_oC3meGbYQIfpQLHq3vg2E_AK34xhh84fc1s3AcUQfJOeyvmpHbCSkNthx0pICa0R2IN2zvqCbJjfuqwLv8Qhp1DaUxCXZbHDhm7vWCrScfColIeyo2LS-tsAQewWyltPj2RRqZRKCneTchy1rTrTlHE5c8VhYUJkOYLK9-m75Me5Chh4BVZD_ERfwu31dD2AAAA

It's evident that the snippet references a variable defined in the script, so it cannot be hoisted to the context script and exported. The compiler can easily see it.


For curious ones, a close to the proposed solution workaround.
Plus, the solution is already proposed in #10350.

@paoloricciuti
Copy link
Member

Btw i started fiddling around with the changes to allow exporting snippets from the module and i think there's a decent blocker for it: the module is parsed by acorn that errors out if you are trying to export something that is not there. This is also true for the normal script.

So either one limitation is that you can only export a getter for the snippets in the form of function or we should find a way around this error (which seems pretty annoying because you want acorn to error out if you are exporting something that is not there and at the parsing phase we still don't know if the snippet could be hoisted or not).

@KevsRepos
Copy link

Wild idea:

{#snippet export foo()}
{/snippet}

Or

{@export foo}

{#snippet foo()}
{/snippet}

Besides the fact that even I dont like the syntax, could the language server even recognize foo being exported?
Another idea:

<script>
export let snippets = $snippets(foo); // exports object containing passed snippets
</script>

{#snippet foo()}
{/snippet}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants