prettier-plugin-svelte icon indicating copy to clipboard operation
prettier-plugin-svelte copied to clipboard

Script & style contents lost when invoked with range option

Open tomblachut opened this issue 3 years ago • 7 comments

Hello 👋

There are some cases when users would like to reformat only parts of file, unfortunately it's not working right now.

Reproduction: Use following file

<script>
  console.
  log('hello')
</script>
<article>
              <section>
</section>
</article>
{#if
  true}
        <div></div>
{/if}
<style>
    .css.is.best{ align-content:
            baseline}
</style>

and run

prettier index.svelte --range-start 0 --range-end 10

Output:

<script ✂prettier:content✂="CiAgY29uc29sZS4KICBsb2coJ2hlbGxvJykK">{}</script>
<article>
              <section>
</section>
</article>
{#if
  true}
        <div></div>
{/if}
<style ✂prettier:content✂="CiAgICAuY3NzLmlzLmJlc3R7IGFsaWduLWNvbnRlbnQ6CiAgICAgICAgICAgIGJhc2VsaW5lfQo="></style>

Apart from nothing being really formatted (different issue, I've noticed it also does not work in official html), we get those base64 encoded placeholders.

During my investigation I've noticed that parser.preprocess encodes content, and printer.embed decodes it, but printer.embed is not called with custom range used.

I'd like to ask, what is the technical reasoning behind those placeholders? This package uses svelte parser under the hood, and it returns deep AST with embedded JS already parsed (and TS types stripped, right?). Would it be possible to get rid of parse.preprocess if svelte parser had shallow option that would leave text of Script and Style nodes as text? I believe it could be then passed to textToDoc in embed

tomblachut avatar Jun 16 '21 14:06 tomblachut

Unfortunately getting rid of some kind of snipping is not possible given the way the Svelte compiler is written. From what I understand, the compiler expects vanilla JS/CSS in the script/style tags, and is greedy, meaning the moment it encounters a script or style tag it switches to a JS/CSS parser and parses until it finds a closing tag. If those JS/CSS parsers find anything that's not valid JS/CSS syntax, they throw. So we have to find another way to handle embeds, by somehow unsnipping everything even when ranges are given.

dummdidumm avatar Jun 16 '21 14:06 dummdidumm

Hmm you're right it would be really complex. Shallow parser would open Pandora box of brace nesting and quoting issues...

Snipping unfortunately also messes up offset inside file, length of base64 encode is different than that of original.

tomblachut avatar Jun 17 '21 08:06 tomblachut

I'm not that familar with how formatting a specific range works in prettier. Possible solutions without knowing more:

  • Check if we can do snipping differently, preserving the offsets
  • Check if we can recalculate the offsets after snipping to adjust for the new lengths

dummdidumm avatar Jun 17 '21 14:06 dummdidumm

I dug into this today and found out that right now it's impossible to support range formatting, because we can't hook into Prettier at the required position: https://github.com/prettier/prettier/issues/11404

dummdidumm avatar Aug 27 '21 07:08 dummdidumm

any update on this? it still doesen't work.

KraXen72 avatar Sep 02 '23 14:09 KraXen72

+1

sjunepark avatar Sep 29 '23 06:09 sjunepark

This is not solved these days , and it was reported first time 3 years ago. :( :(

eriknyk avatar Jan 25 '24 19:01 eriknyk