Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support remark syntax plugins in @mdx-js/monaco #264

Closed
4 tasks done
remcohaszing opened this issue Jan 13, 2023 · 5 comments · Fixed by #304
Closed
4 tasks done

Support remark syntax plugins in @mdx-js/monaco #264

remcohaszing opened this issue Jan 13, 2023 · 5 comments · Fixed by #304

Comments

@remcohaszing
Copy link
Member

Initial checklist

Problem

The language service was written with support for remark/micromark syntax plugins in mind, but not the Monaco editor integration.

The language service is used in a web worker. Since unified plugins are functions, they can’t be passed from the main thread to the worker. This means the user will need to define a custom worker in order to use remark plugins.

Solution

Mimic https://github.com/remcohaszing/monaco-tailwindcss to allow users to define a custom worker and inject options.

Alternatives

🤷

@ChristianMurphy
Copy link
Member

It may be possible for the main thread and worker to talk via a proxy sending requests between the two.

Which is how https://partytown.builder.io/ works.
https://partytown.builder.io/how-does-partytown-work gives background on the approach.

@remcohaszing
Copy link
Member Author

Yes, that’s how Monaco editor works as well. The problem is we can’t pass functions (like unified plugins), because they aren’t supported by the structured clone algorithm.

It’s not a big deal. I dealt with it before in monaco-tailwindcss and monaco-unified, but it makes usage a bit quirky.

@ChristianMurphy
Copy link
Member

Partytown's approach may be able to help:

Data passed between the main thread and web worker must be serializable. Partytown automatically handles the serializing and deserializing of data passed between threads. This works for primitive values, such as a string, boolean or number, and also functions, which get unique IDs assigned that are passed to the opposite thread and can be called.

https://partytown.builder.io/how-does-partytown-work

@ChristianMurphy
Copy link
Member

The source implementing function serializing/proxy support https://github.com/BuilderIO/partytown/blob/main/src/lib/web-worker/worker-serialization.ts

@remcohaszing
Copy link
Member Author

It appears Partytown requires even more configuration of the build tool. In my experience maintaining various Monaco editor related projects, this is the part users struggle with. Partytown really looks like a cool project, but I don’t think having a library depend on it is a good choice.

The difference when using the approach by monaco-tailwindcss, is this (This works with Webpack and Vite. Exact usage depends on the build tool.):

  window.MonacoEnvironment = {
    getWorker(moduleId, label) {
      switch (label) {
        case 'editorWorkerService':
          return new Worker(new URL('monaco-editor/esm/vs/editor/editor.worker', import.meta.url))
        case 'css':
        case 'less':
        case 'scss':
          return new Worker(new URL('monaco-editor/esm/vs/language/css/css.worker', import.meta.url))
        case 'handlebars':
        case 'html':
        case 'razor':
          return new Worker(new URL('monaco-editor/esm/vs/language/html/html.worker', import.meta.url))
        case 'json':
          return new Worker(new URL('monaco-editor/esm/vs/language/json/json.worker', import.meta.url))
        case 'mdx':
-         return new Worker(new URL('@mdx-js/monaco/mdx.worker', import.meta.url))
+         return new Worker(new URL('./mdx.worker', import.meta.url))
        case 'javascript':
        case 'typescript':
          return new Worker(new URL('monaco-editor/esm/vs/language/typescript/ts.worker', import.meta.url))
        default:
          throw new Error(`Unknown label ${label}`)
      }
    }
  };

and the addition of this file:

import { initialize } from '@mdx-js/mdx.worker'
import remarkFrontmatter from 'remark-frontmatter'
import remarkGfm from 'remark-gfm'

initialize({
  plugins: [remarkFrontmatter, remarkGfm]
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

2 participants