kit icon indicating copy to clipboard operation
kit copied to clipboard

enhanced-img is no longer a Svelte preprocessor, breaking compatibility with mdsvex

Open GauBen opened this issue 6 months ago • 6 comments

Describe the bug

Hi!

In 0.4, @sveltejs/enhanced-img was built as a Svelte preprocessor, allowing it to run after mdsvex transformations.

Starting in 0.5, this is no longer the case, it's a generic Vite plugin.

This is an issue as @sveltejs/enhanced-img now parses all Svelte code, including .svx files, by itself through svelte-parse-markup, which does not have preprocessing built-in.

Reproduction

<!-- ./article.svx -->
I love `<enhanced:img>` tags
<!-- ./+page.svelte -->
<script>
import Article from './article.svx'
</script>
<Article />

This .svx file is not a valid Svelte file, but as it contains <enhanced:img, it will be parsed as if

(If you want a full blown repository, you can clone https://github.com/GauBen/gautier.dev/tree/repro, run yarn vite-node src/index.js to trigger the error)

Logs

This will fail with this error:

[InternalCompileError: `<enhanced:img>` was left open
https://svelte.dev/e/element_unclosed] {
  code: 'element_unclosed',
  filename: '/.../src/article.md',
  position: [ 8, 9 ],
  start: { line: 1, column: 8, character: 8 },
  end: { line: 1, column: 9, character: 9 },
  frame: '1: I love `<enhanced:img>` tags\n            ^\n2: ',
  plugin: 'vite-plugin-enhanced-img-markup',
  id: '/.../src/article.md',
  pluginCode: 'I love `<enhanced:img>` tags\n',
  loc: {
    '0': 8,
    '1': 9,
    file: '/.../src/article.md'
  }
}

System Info

enhanced-img 0.5+

Severity

blocking an upgrade

Additional Information

No response

GauBen avatar May 29 '25 21:05 GauBen

Would it work to change it to this?

<!-- ./article.svx -->
I love `&lt;enhanced:img>` tags

The other fix might be to make mdsvex a vite plugin. That probably wouldn't happen in the short-term, but if the preprocessor API got removed in favor of bundler plugins it could happen one day. Then we could have the order be mdsvex -> enhanced-img -> svelte. (The image plugin expects to operate on a Svelte file so it must come before the Svelte plugin because the Svelte compiler converts the Svelte file to a JS file)

benmccann avatar May 29 '25 21:05 benmccann

Thanks for the quick answer!

I oversimplified the reproduction a bit. On real markdown files, it fails on various occasions:

It will fail on CSS:

```css
.foo {
  display: none
}
```

On JSON too:

```json
{
  "foo": "bar"
}
```

On LaTeX:

$$
\text{score} = 5 \cdot \frac{\displaystyle \sum_{\text{article}} \text{weight}}{\cosh\left(\text{\# matches} - 1.5\right)}
$$

It will fail on unclosed tags: `<button>`.

GauBen avatar May 30 '25 07:05 GauBen

The issue here is that vite plugin svelte runs preprocess and compile within the same transform so other plugins cannot get the preprocessed output to further change that before compile. So either enhanced-img has to execute preprocess itself and pass the processed output, leaving vite-plugin-svelte to execute it again (should be a noop then) OR vite-plugin-svelte changes internally to split preprocess and compile into 2 vite plugins where enhanced-img can be inserted in the middle.

This can be inserted in the middle is a bit tricky though, have to think about it.

dominikg avatar May 30 '25 07:05 dominikg

Splitting them in two would be really nice and have other benefits for debugging: https://github.com/sveltejs/vite-plugin-svelte/issues/729

benmccann avatar May 30 '25 07:05 benmccann

so regarding ordering, vite-plugin-svelte currently still uses "enforce":"pre", to allow other plugins to inject themselves in between the preprocess and compile plugins we would have to change that, eg keep the preprocess plugin in pre but move compile to the regular group, so that adding vite-plugin-svelte-something in the vite config before vite-plugin-svelte would give something the preprocessed output in its transform which is then passed on to vite-plugin-sveltes own transform.

Another way would be with hook level ordering hints, but that would require the plugin authors to deal with it.

dominikg avatar May 30 '25 08:05 dominikg

@pngwn has said he will convert mdsvex to be a Vite plugin (it might be nice to use https://unplugin.unjs.io/ in order to keep support for webpack, etc.). Feel free to put together a PR if you'd like to expedite the process

benmccann avatar May 30 '25 14:05 benmccann

I'm going to close this since it was determined the fix will be made elsewhere

benmccann avatar Oct 04 '25 16:10 benmccann