sveltejs / prettier-plugin-svelte

Format your svelte components using prettier.
MIT License
735 stars 95 forks source link

cannot define on:load on script element and please both prettier and svelte check #347

Closed opensas closed 1 year ago

opensas commented 1 year ago

Describe the bug

If I create a script element with an on:load handler like this:

<svelte:head>
    <script src="http://localhost:5173/dummy.js" on:load={() => console.log('script:load')} />
</svelte:head>

pnpm check runs ok but pnpm lint (the prettier part) complains

$ pnpm check
> svelte-kit sync && svelte-check --tsconfig ./tsconfig.json
[...]
svelte-check found 0 errors and 0 warnings
sas@xps ~/devel/apps/glas-it/apps/wingback/tmp/script-onload-error 
$ pnpm lint
[...]
[warn] Code style issues found in the above file. Forgot to run Prettier?
 ELIFECYCLE  Command failed with exit code 1.

   If I run pnpm format it gets rewritten like this (couldn't find a way to tell prettier to leave that as is  

 <svelte:head>
    <script src="http://localhost:5173/dummy.js" on:load={() => console.log('script:load')}></script>
</svelte:head>

but then pnpm check complains

$ pnpm check
> svelte-kit sync && svelte-check --tsconfig ./tsconfig.json

Error: Unexpected token (js)
<svelte:head>
        <script src="http://localhost:5173/dummy.js" on:load={() => console.log('script:load')}></script>
</svelte:head>

Also, running pnpm format once more, against what prettier already formatted, throws a similar error:

$ pnpm format
> prettier --plugin-search-dir . --write .
[error]   1 | <svelte:head>
[error] > 2 |   <script src="http://localhost:5173/dummy.js" on:load={() = ✂prettier:content✂="IGNvbnNvbGUubG9nKCdzY3JpcHQ6bG9hZCcpfT4=">{}</script>
[error]     |                                                         ^
[error]   3 | </svelte:head> (2:56)
[error] 1: <svelte:head>
[error] 2:   <script src="http://localhost:5173/dummy.js" on:load={() = ✂prettier:content✂="IGNvbnNvbGUubG9nKCdzY3JpcHQ6bG9hZCcpfT4=">{}</script>
[error]                                                             ^
[error] 3: </svelte:head>

I couldn't find a way to configure prettier to leave those cases untouched, and neither could find a way for svelte-check to understand that it's a valid statement

Reproduction

create a new sveltekit project

create-svelte version 2.3.4

Welcome to SvelteKit!

✔ Which Svelte app template? › Skeleton project
✔ Add type checking with TypeScript? › Yes, using TypeScript syntax
✔ Add ESLint for code linting? … Yes
✔ Add Prettier for code formatting? … Yes
✔ Add Playwright for browser testing? … No
✔ Add Vitest for unit testing? … No

run pnpm install

replace routes/+page.svelte` with:

<svelte:head>
    <script src="http://localhost:5173/dummy.js" on:load={() => console.log('script:load')} />
</svelte:head>

run pnpm check (ok) run pnpm lint (complains about prettier) run pnpm format (prettier rewrites the code adding a </script> run pnpm format again -> error! run pnpm check again -> error!

Expected behavior

Either pnpm format formats the closing script without adding a </script> or both prettier and svelte-check accept the <script ... on:load={...}></script> as valid

System Info

Which package is the issue about?

prettier-plugin-svelte (also related with svelte-check)

Additional Information, eg. Screenshots

Issue first reported at svelte-check repo

I created this repo with the error

You can open it in gitpod clicking here

then run

npm install -g pnpm
pnpm check
pnpm lint
pnpm format
# and then again
pnpm format
pnpm check
opensas commented 1 year ago

possible duplicate of: https://github.com/sveltejs/language-tools/issues/748

dummdidumm commented 1 year ago
<!-- prettier-ignore -->
<svelte:head>
    <script src="http://localhost:5173/dummy.js" on:load={() => console.log('script:load')} />
</svelte:head>

prevents Prettier from formatting this - this should solve your "am stuck between two things" problem.

opensas commented 1 year ago

thanks a lot for keeping an eye on this issue, I followed your advise and ended up with something like this:

[...]
    const onload = () => (ready = true);
</script>

<svelte:head>
    <script on:load={onload} {src} {defer}></script>
</svelte:head>

but the prettier-ignore thing could also work

opensas commented 1 year ago

@dummdidumm just to confirm that the <!-- prettier-ignore --> workaround didn't work

image

the best alternative so far is to declare a function and call it from the script tag

image