Skip to content

Conversation

@feugy
Copy link

@feugy feugy commented May 4, 2025

Work in progress.

This PR allows to parse and compile module files (*.svelte.ts) written in TypeScript.

More context to come.

Before submitting the PR, please make sure you do the following

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • Prefix your PR title with feat:, fix:, chore:, or docs:.
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.
  • If this PR changes code within packages/svelte/src, add a changeset (npx changeset).

Tests and linting

  • Run the tests with pnpm test and lint the project with pnpm lint

@changeset-bot
Copy link

changeset-bot bot commented May 4, 2025

⚠️ No Changeset found

Latest commit: 58ac644

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@svelte-docs-bot
Copy link

@paoloricciuti
Copy link
Member

Before you go too far: I don't think this is a good idea...there's already a tool to do this and it's the typescript compiler. Inside svelte files it's a different story because the typescript compiler can't operate there but for .ts files there's really no reason to add the maintenance burden in svelte. Furthermore acorn typescript can only compile deletable TS which, while arguably a better default, it's not the same.

@feugy
Copy link
Author

feugy commented May 4, 2025

Hello @paoloricciuti, thanks for the heads up!

Indeed, this looks like a dead end. I'm running more experiment before closing this draft.
Context: I'm trying to test .svelte.ts files with bun's test runner.

Like for .svelte files, I had to write a bun plugin to transpile the tested code in JS.
However, the bun plugin gets the original source code, in TS, and the not the compile JS it should.

@paoloricciuti
Copy link
Member

Hello @paoloricciuti, thanks for the heads up!

Indeed, this looks like a dead end. I'm running more experiment before closing this draft. Context: I'm trying to test .svelte.ts files with bun's test runner.

Like for .svelte files, I had to write a bun plugin to transpile the tested code in JS. However, the bun plugin gets the original source code, in TS, and the not the compile JS it should.

This feels a job for another bun plugin rather than the svelte compiler...however, shouldn't bun understand ts natively?

@feugy feugy closed this May 4, 2025
@feugy
Copy link
Author

feugy commented May 4, 2025

shouldn't bun understand ts natively?

It absolutely does. However, since the runes inside .svelte.ts were not compiled, I'm getting:

Svelte error: rune_outside_svelte
The `$state` rune is only available inside `.svelte` and `.svelte.js/ts` files

when trying to run it.

@paoloricciuti
Copy link
Member

Oh gotcha...yeah that's an annoying problem 🤔

@feugy
Copy link
Author

feugy commented May 4, 2025

I couldn't find a viable workaround with Typescript svelte modules.

The way I could test svelte modules with Bun tester:

  1. write svelte module in JavaScript (with JSDoc for minimal type support)
  2. use the following Bun plugin to compile them when they are required in test files:
    // file src/tests/bun-svelte-module.ts
    import { file, plugin } from 'bun'
    import { compileModule } from 'svelte/compiler'
    
    plugin({
      name: 'bun-svelte-module',
      async setup(build) {
        build.onLoad({ filter: /\.svelte\.js$/ }, async ({ path }) => {
          const text = await file(path).text()
          return {
            contents: compileModule(text, { filename: path, generate: 'server' }).js.code,
            loader: 'js'
          }
        })
      }
    })
    # file bunfig.toml
    [test]
    preload = ["./src/tests/bun-svelte-module.ts"]

@dummdidumm
Copy link
Member

I know nothing about Bun bundler plugins but the way it works for Vite/Rollup/Webpack is that the typescript transpiled plug-in runs first and then the Svelte plugin can be called with the transpiled JavaScript to transpiled runes.
But since Bun supports TS natively I guess there's not such thing as a TS->JS plugin? Maybe it's enough to use transpileModule from typescript in your custom plugin and pass its output to the Svelte parser.

@feugy feugy deleted the compile-module-ts branch May 4, 2025 19:04
@feugy
Copy link
Author

feugy commented May 4, 2025

I guess there's not such thing as a TS->JS plugin

Indeed, or at least I couldn't find anything like this.

Maybe it's enough to use transpileModule from typescript

I'll git this a try!

Thanks for all the ideas

@paoloricciuti
Copy link
Member

You can also do what we are doing in the repl and use ts-blank-space to remove all the deletable TS

@feugy
Copy link
Author

feugy commented May 5, 2025

What a brilliant idea @paoloricciuti! ts-blank-space did perfect job.

import { file, plugin } from 'bun'
import { compileModule } from 'svelte/compiler'
import removeTS from 'ts-blank-space'

plugin({
  name: 'bun-svelte-module',

  async setup(build) {
    build.onLoad({ filter: /\.svelte\.[j|t]s$/ }, async ({ path }) => {
      const text = await file(path).text()
      const isTS = path.endsWith('.ts')
      return {
        contents: compileModule(isTS ? removeTS(text) : text, {
          filename: path,
          generate: 'client'
        }).js.code,
        loader: 'js'
      }
    })
  }
})

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

Successfully merging this pull request may close these issues.

3 participants