monaco-vscode-api

repository·main·Indexed 19 days ago

https://github.com/codingame/monaco-vscode-api

A bridge to integrate full VSCode functionality—including services, extensions, settings, and filesystem—into the Monaco Editor. It allows developers to replace standalone Monaco services with fully-functional VSCode services, support .vsix extension loading, and use VSCode JSON settings in the browser.

Tokens
14.5K
Snippets
45
Records
57
Agent score
67%

What's inside @codingame/monaco-vscode-api

  1. Create models using createModelReference

    main

    While standard monaco.editor.createModel works, it creates standalone models that are invisible to VSCode services.

    Instead, use monaco.editor.createModelReference(fileUri). This returns a model reference that:

    • Allows VSCode services to follow links (e.g., Ctrl+Click).
    • Binds the model to a virtual filesystem.
    • Provides lifecycle control (saving, dirty state).
    • Automatically disposes the model when all references are disposed.

    To use this, the file must exist on the virtual filesystem, which you can set up using registerFileSystemOverlay from the files service override.

    import * as monaco from 'monaco-editor'
    import { 
      RegisteredFileSystemProvider, 
      RegisteredMemoryFile, 
      registerFileSystemOverlay 
    } from '@codingame/monaco-vscode-files-service-override'
    
    const fileUri = monaco.Uri.file('file:///path/to/file.ts')
    
    // 1. Setup virtual filesystem overlay
    const fileSystemProvider = new RegisteredFileSystemProvider(false)
    fileSystemProvider.registerFile(new RegisteredMemoryFile(fileUri, 'const x = 1;'))
    const overlayDisposable = registerFileSystemOverlay(1, fileSystemProvider)
    
    // 2. Create the model reference
    const modelRef = await monaco.editor.createModelReference(fileUri)
    
    // 3. Use the model in an editor
    const editor = monaco.editor.create({
      model: modelRef.object.textEditorModel
    })
    
    // 4. Cleanup
    await modelRef.object.save()
    modelRef.dispose()
    editor.dispose()
    overlayDisposable.dispose()
  2. How Sandbox Mode works (beta)

    main

    Since VSCode is designed to initialize once, it is difficult to 'unload' services or reload configuration. Sandbox mode solves this by running the VSCode code inside an iframe while allowing it to interact with the main page DOM.

    Implementation Steps:

    1. Create a secondary HTML entrypoint to initialize services.
    2. Load that HTML in an iframe.
    3. Crucial: Set window.vscodeWindow to the parent window BEFORE any VSCode code is loaded.
    4. Initialize the service with a container mounted in the parent window.
    5. Do not import monaco-vscode-library in the top-level window; instead, expose functions on the iframe window to communicate with the top window.

    To 'unload' the workbench:

    • Remove the iframe element from the top frame.
    • Remove or empty the workbench container.
    • Clean up injected elements: document.querySelectorAll('[data-vscode]').forEach((el) => el.remove()).
  3. How Monaco service overrides work

    main

    Monaco uses simplified standalone services for features like themes and languages. This library allows you to replace these with fully-functional VSCode services or add new ones using the initialize function.

    Important: initialize can only be called once and must be called BEFORE creating your first editor instance.

    To use a service, you import a get<service-name>ServiceOverride function and pass its result to initialize.

    import { initialize } from '@codingame/monaco-vscode-api'
    import getThemeServiceOverride from '@codingame/monaco-vscode-theme-service-override'
    
    // Must be called before creating any editor
    await initialize({
      ...getThemeServiceOverride()
    })
  4. Handle production concerns for remote servers

    main

    When deploying in production, ensure the commit and product quality match between the client and the server.

    If you are running a cluster where clients are upgraded progressively, the server must support multiple versions. Because all calls to the server are prefixed by <quality>-<commit>, you can run multiple server versions on different ports and use a reverse proxy to route requests based on the path prefix.

  5. Configure Shadow DOM support

    main

    The library supports Shadow DOM to prevent style pollution between the VSCode workbench and your application.

    Prerequisites: Your bundler must be configured to load CSS files as strings or CSSStyleSheet objects instead of injecting them into the document <head>. This ensures styles are injected into the shadow root.

    Webpack Configuration

    Add a rule to handle CSS from @codingame/monaco-vscode, vscode, or monaco-editor:

    {
      test: /node_modules\/(@codingame\/monaco-vscode|vscode|monaco-editor).*\.css$/,
      use: [
        {
          loader: 'css-loader',
          options: {
            esModule: false,
            exportType: 'css-style-sheet', // or 'string'
            url: true,
            import: true
          }
        }
      ]
    }

    Vite Configuration

    Add this plugin to intercept and inline the CSS files:

    {
      name: 'load-vscode-css-as-string',
      enforce: 'pre',
      async resolveId(source, importer, options) {
        const resolved = (await this.resolve(source, importer, options))!
        if (
          resolved.id.match(
            /node_modules\/(@codingame\/monaco-vscode|vscode|monaco-editor).*\.css$/
          )
        ) {
          return {
            ...resolved,
            id: resolved.id + '?inline'
          }
        }
        return undefined
      }
    }
  6. Localize VSCode and extensions

    main

    To localize the interface, import a language pack.

    CRITICAL: The language pack must be imported and loaded BEFORE any other part of the @codingame/monaco-vscode-api library is loaded to ensure all translations are available.

    ```typescript
    // Must be first!
    import '@codingame/monaco-vscode-language-pack-fr'
    
    // Then import other api components
    import { initialize } from '@codingame/monaco-vscode-api'

    Supported language packs:

    • @codingame/monaco-vscode-language-pack-cs
    • @codingame/monaco-vscode-language-pack-de
    • @codingame/monaco-vscode-language-pack-es
    • @codingame/monaco-vscode-language-pack-fr
    • @codingame/monaco-vscode-language-pack-it
    • @codingame/monaco-vscode-language-pack-ja
    • @codingame/monaco-vscode-language-pack-ko
    • @codingame/monaco-vscode-language-pack-pl
    • @codingame/monaco-vscode-language-pack-pt-br
    • @codingame/monaco-vscode-language-pack-qps-ploc
    • @codingame/monaco-vscode-language-pack-ru
    • @codingame/monaco-vscode-language-pack-tr
    • @codingame/monaco-vscode-language-pack-zh-hans
    • @codingame/monaco-vscode-language-pack-zh-hant
  7. Run the VSCode or VSCodium server

    main

    Start the server from its installation directory.

    Warning: The command below starts the service on all interfaces without a security token for simplicity. Do not use this configuration in production.

    • For VSCode: ./bin/code-server
    • For VSCodium: ./bin/codium-server
    # Run VSCode server
    ./bin/code-server --port 8080 --without-connection-token --accept-server-license-terms --host 0.0.0.0
    
    # Or for VSCodium
    ./bin/codium-server --port 8080 --without-connection-token --accept-server-license-terms --host 0.0.0.0
  8. Upgrade to next VSCode and monaco-editor versions

    main

    Upgrading the underlying VSCode and monaco-editor versions requires a coordinated process across the vscode repository, the monaco-vscode-api repository, and the monaco-vscode-api-demo. This process assumes both monaco-vscode-api and vscode repositories are cloned locally at the same directory level.

    1. Update the VSCode repository

    1. Identify the target VSCode tag from the VSCode GitHub tags.
    2. In the VSCode repo, reset to the previous VSCode tag (found in config.vscode.ref of the monaco-vscode-api package.json).
    3. Apply the existing patch: git am ../monaco-vscode-api/vscode-patches/*.patch.
    4. Fetch the new tag: git fetch origin <tag>.
    5. Rebase on the new tag: git rebase <tag>.
    6. Resolve conflicts and update code (e.g., fix broken imports).
    7. Generate a new patch directory: rm -rf ../monaco-vscode-api/vscode-patches && git format-patch --zero-commit --no-numbered --no-signature <tag>.. -o '../monaco-vscode-api/vscode-patches'.

    2. Update the monaco-vscode-api repository

    1. Update package.json: set config.vscode.ref to the new VSCode tag and config.monaco.ref to the new monaco-editor version.
    2. Run npm install to trigger the VSCode installation script. Wait for the download and build to complete.
    3. Run npm run update-vscode-dependencies to align internal dependencies with the new VSCode version.
    4. Run npm install again (you may need to update/add an npm override for xterm in package.json to resolve invalid peer dependencies).
    5. Fix errors, adapt code, and build. Ensure you:
      • Use oxlint autofix to resolve most errors.
      • Implement any missing services (observable via the demo or by running git diff <previousTag> <newTag> -G'registerSingleton\(' in the VSCode repo).
      • Update duplicated files in src/assets to match VSCode.
    6. Update the demo (see below).
    7. Commit the changes as a breaking change by using ! before the : in the commit message (e.g., feat!: update vscode version).

    3. Update the monaco-vscode-api demo

    1. In the demo directory, run npm run update-local-dependencies.
    2. Reinstall dependencies: rm -rf node_modules package-lock.json && npm install.
    3. Verify functionality by checking the Window output in the OUTPUT panel for errors.
    4. Test various configurations: Full workbench mode, Shadow DOM mode, VSCode server, HTML file system provider, and Sandbox mode.
  9. Install @codingame/monaco-vscode-api

    main

    Install the core package via npm. You can also optionally install specialized API packages to provide full VSCode and Monaco compatibility.

    • @codingame/monaco-vscode-extension-api is installed as an alias to vscode so you can use import * as vscode from 'vscode' in your code.
    • @codingame/monaco-vscode-editor-api is installed as an alias to monaco-editor to provide the same API as the official editor.
    npm install @codingame/monaco-vscode-api
    # Optionally install the extension api and the editor api
    npm install vscode@npm:@codingame/monaco-vscode-extension-api
    npm install monaco-editor@npm:@codingame/monaco-vscode-editor-api
  10. Use a remote server with monaco-vscode-api

    main

    To connect your monaco-vscode-api client to a remote server, follow these steps:

    1. Add the service override: Include @codingame/monaco-vscode-remote-agent-service-override in your project.
    2. Configure the remote authority: In the service initialization function, provide a remoteAuthority string. This should contain only the authority (domain/IP and port, e.g., localhost:8080). You may also provide a connectionToken if required by the server.
    3. Access remote files: Use the vscode-remote scheme to open directories on the remote machine.
      • Format: vscode-remote://<authority>/<path/to/directory>
      • Example: vscode-remote://localhost:8080/my/project/directory
  11. Load VSCode extensions (.vsix files)

    main

    You can load standard VSCode .vsix files using a Rollup/Vite compatible plugin.

    1. Add vsixPlugin() to your rollup or vite configuration.
    2. Import the .vsix file directly in your code.
    // vite.config.ts / rollup.config.ts
    import vsixPlugin from '@codingame/monaco-vscode-rollup-vsix-plugin'
    
    export default {
      plugins: [
        vsixPlugin()
      ]
    }
    
    // main.ts
    import './extension.vsix'
  12. Install VSCode or VSCodium server

    main

    To use remote capabilities with monaco-vscode-api, you must install a VSCode or VSCodium server.

    1. Find the required commit SHA: Use the monaco-vscode-api version to find the compatible VSCode commit.
    2. Download the server:
      • VSCode: Download from https://update.code.visualstudio.com/commit:${commit_sha}/server-<platform>-<arch>/stable. Replace <platform> with win32, linux, or darwin, and <arch> with arm64, x64, or armhf.
      • VSCodium: Download the reh release from the VSCodium releases page.
    3. Extract the archive: Untar the downloaded file into your desired installation directory.
    # 1. Get the commit SHA
    curl https://raw.githubusercontent.com/CodinGame/monaco-vscode-api/v<monaco_vscode_api_version>/package.json | jq -r '.["config"]["vscode"]["commit"]'
    
    # 2. Extract the archive (example for Linux x64)
    mkdir -p <install_directory> && tar --no-same-owner -xzv --strip-components=1 -C <install_directory> -f <archive>