shikijs / twoslash

You take some Shiki, add a hint of TypeScript compiler, and 🎉 incredible static code samples
https://shikijs.github.io/twoslash/
MIT License
1.09k stars 53 forks source link

[Question] Can we use tsserver plugins with shiki-twoslash? #170

Open znck opened 2 years ago

orta commented 2 years ago

It doesn't seem massively outside of the scope for supporting it IMO, we do host a TSServer.

If the diff is reasonable and well tested, I'd be open to support.

znck commented 2 years ago

As far as I understand @typescript/vfs creates a language service using createLanguageService(), I don't see TSServer.

Where should I look to start a PR?

orta commented 2 years ago

I think we might need to emulate some the commands sent from the language service to look like the ones sent from the tsserver process - I think they might be pretty much pass throughs in the tsc codebase

znck commented 2 years ago

PluginModule.create() expects project and serverHost. I am not sure how to emulate project.

diff --git a/packages/typescript-vfs/src/index.ts b/packages/typescript-vfs/src/index.ts
index 453dcf9b..e7c99c39 100755
--- a/packages/typescript-vfs/src/index.ts
+++ b/packages/typescript-vfs/src/index.ts
@@ -5,6 +5,7 @@ type LanguageServiceHost = import("typescript").LanguageServiceHost
 type CompilerHost = import("typescript").CompilerHost
 type SourceFile = import("typescript").SourceFile
 type TS = typeof import("typescript")
+type PluginModuleFactory = import("typescript/lib/tsserverlibrary").server.PluginModuleFactory

 let hasLocalStorage = false
 try {
@@ -39,7 +40,8 @@ export function createVirtualTypeScriptEnvironment(
   rootFiles: string[],
   ts: TS,
   compilerOptions: CompilerOptions = {},
-  customTransformers?: CustomTransformers
+  customTransformers?: CustomTransformers,
+  plugins: PluginModuleFactory[] = []
 ): VirtualTypeScriptEnvironment {
   const mergedCompilerOpts = { ...defaultCompilerOptions(ts), ...compilerOptions }

@@ -50,7 +52,16 @@ export function createVirtualTypeScriptEnvironment(
     ts,
     customTransformers
   )
-  const languageService = ts.createLanguageService(languageServiceHost)
+  const languageService = plugins.reduce((languageService, plugin) => {
+    return plugin({ typescript: ts }).create({
+      languageService,
+      languageServiceHost,
+      project: null as any, // ??
+      config: {},
+      serverHost: {} as any, // create severHost
+    })
+  }, ts.createLanguageService(languageServiceHost))
+  // TODO: Enable plugins
   const diagnostics = languageService.getCompilerOptionsDiagnostics()

   if (diagnostics.length) {