
Security News
vlt Launches "reproduce": A New Tool Challenging the Limits of Package Provenance
vlt's new "reproduce" tool verifies npm packages against their source code, outperforming traditional provenance adoption in the JavaScript ecosystem.
@codingame/monaco-vscode-api
Advanced tools
NPM module that implements the VSCode api and redirects calls to Monaco editor.
npm install vscode@npm:@codingame/monaco-vscode-api
npm install -D @types/vscode
⚠️ And add in your package.json ⚠️:
{
"scripts": {
"postinstall": "monaco-treemending",
}
}
Monaco-editor is a library that is constructed using code from vscode and goes through an intense treeshaking process.
However, due to the inclusion of additional code from VSCode in this library that utilizes internal modules bundled in monaco, this treeshaking is a problem here.
To tree-mend (to untreeshake it) monaco-editor, this library provides a script that will apply a patch on the local installation of monaco-editor, restoring all the code that was treeshaken during the monaco-editor build process
This library uses a lot the new URL('asset.extension', import.meta.url)
syntax which is supported by vite
While it works great in build
mode (because rollup is used), there is some issues in `watch`` mode:
There are workarounds for both:
import.meta.url
by the original module path (you need the --experimental-import-meta-resolve note option):{
...
optimizeDeps: {
esbuildOptions: {
plugins: [{
name: 'import.meta.url',
setup ({ onLoad }) {
// Help vite that bundles/move files in dev mode without touching `import.meta.url` which breaks asset urls
onLoad({ filter: /.*\.js/, namespace: 'file' }, async args => {
const code = fs.readFileSync(args.path, 'utf8')
const assetImportMetaUrlRE = /\bnew\s+URL\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*,\s*import\.meta\.url\s*(?:,\s*)?\)/g
let i = 0
let newCode = ''
for (let match = assetImportMetaUrlRE.exec(code); match != null; match = assetImportMetaUrlRE.exec(code)) {
newCode += code.slice(i, match.index)
const path = match[1].slice(1, -1)
const resolved = await import.meta.resolve!(path, url.pathToFileURL(args.path))
newCode += `new URL(${JSON.stringify(url.fileURLToPath(resolved))}, import.meta.url)`
i = assetImportMetaUrlRE.lastIndex
}
newCode += code.slice(i)
return { contents: newCode }
})
}
}]
}
}
}
Not allowed to load local resource:
errorsThe short version: set up and use a custom webpack config file and add this under module
:
parser: {
javascript: {
url: true,
},
},
See this issue or this StackOverflow answer for more details, and this discussion for more context.
Also, monaco-editor use standalone
versions or the vscode services, which are much simpler.
You may want to provide your custom implementations of them. To do so, you can use the initialize
method from vscode/services
.
Also, monaco-editor doesn't provide good type for them, so this library does it.
Example:
import { INotificationService, initialize } from 'vscode/services'
class MyCustomNotificationService implements INotificationService { ... }
await initialize({
get [INotificationService.toString()] () {
return new MyCustomNotificationService(...)
}
})
Additionally, 25 packages that include the vscode version of some services (with some glue to make it work with monaco) are published:
Extensions (included by default): @codingame/monaco-vscode-extensions-service-override
Files (included by default): @codingame/monaco-vscode-files-service-override
file://
files, but also adds the support for lazy loaded extension files. It adds separate memory user files (e.g. config, keybindings), cache files and log files.QuickAccess (included by default): @codingame/monaco-vscode-quickaccess-service-override
Notifications: @codingame/monaco-vscode-notifications-service-override
Dialogs: @codingame/monaco-vscode-dialogs-service-override
Model: @codingame/monaco-vscode-model-service-override
Editor: @codingame/monaco-vscode-editor-service-override
Views: @codingame/monaco-vscode-views-service-override
editor
service. Do not use both services at the same time.Configuration: @codingame/monaco-vscode-configuration-service-override
Keybindings: @codingame/monaco-vscode-keybindings-service-override
Languages: @codingame/monaco-vscode-languages-service-override
onLanguage:${language}
event (to load vscode extension listening to those events)Textmate: @codingame/monaco-vscode-textmate-service-override
Themes: @codingame/monaco-vscode-theme-service-override
Snippets: @codingame/monaco-vscode-snippets-service-override
Audio cue: @codingame/monaco-vscode-audio-cue-service-override
Debug: @codingame/monaco-vscode-debug-service-override
Preferences: @codingame/monaco-vscode-preferences-service-override
Output: @codingame/monaco-vscode-output-service-override
Terminal: @codingame/monaco-vscode-terminal-service-override
Search: @codingame/monaco-vscode-search-service-override
Markers: @codingame/monaco-vscode-markers-service-override
SCM: @codingame/monaco-vscode-scm-service-override
Testing: @codingame/monaco-vscode-testing-service-override
Language detection worker: @codingame/monaco-vscode-language-detection-worker-service-override
Storage: @codingame/monaco-vscode-storage-service-override
LifeCycle: @codingame/monaco-vscode-lifecycle-service-override
Remote agent: @codingame/monaco-vscode-remote-agent-service-override
Another package @codingame/monaco-vscode-server
is published, which expose a vscode-ext-host-server
bin to start the remote agent
Accessibility: @codingame/monaco-vscode-accessibility-service-override
Workspace trust: @codingame/monaco-vscode-workspace-trust-service-override
Extension Gallery: @codingame/monaco-vscode-extension-gallery-service-override
import * as vscode from 'vscode'
import { initialize } from 'vscode/services'
import getEditorServiceOverride from '@codingame/monaco-vscode-editor-service-override'
import getConfigurationServiceOverride, { updateUserConfiguration, configurationRegistry } from '@codingame/monaco-vscode-configuration-service-override'
await initialize({
...getModelEditorServiceOverride((model, input, sideBySide) => {
// Open a new editor here and return it
// It will be called when for instance the user ctrl+click on an import
}),
...getConfigurationServiceOverride(vscode.Uri.file('/tmp/'))
})
updateUserConfiguration(`{
"editor.fontSize": 12,
"[java]": {
"editor.fontSize": 15,
}
}`)
initialize
can only be called once ( and it should be called BEFORE creating your first editor).
The editors created using monaco.editor.create
don't use the configuration from the configurationService.
This library exposes functions to create editors binded on the configuration service:
before:
import * as monaco from 'monaco-editor'
const model = monaco.editor.createModel(...)
const editor = monaco.editor.create({ model, ... })
...
model.dispose()
editor.dispose()
after:
import { createConfiguredEditor, createModelReference } from 'vscode/monaco'
const modelRef = await createModelReference(...)
const editor = createConfiguredEditor({ model: modelRef.object.textEditorModel })
...
await modelRef.object.save()
...
modelRef.dispose()
editor.dispose()
createConfiguredEditor
returns a subclass of what is returned by monaco.editor.create
, the updateOptions
method can still be used.
The only difference is that is will use the configurationService
as a default configuration
createModelReference
return a reference to a model. The value is fetched from the memory filesystem (which is written if you provide the second argument).
The reference can then be disposed, the model will only be disposed if there is no remaining references.
To be able to use the VSCode api directly from your code, you need to import vscode/localExtensionHost
and the services to be initialized.
You will then be able to import it as if you were in a VSCode extension:
import * as vscode from 'vscode'
import 'vscode/localExtensionHost'
const range = new vscode.Range(...)
vscode.languages.registerCompletionItemProvider(...)
The api will use the manifest of a default vscode extension, which can be overriden by providing it to the initialize
function.
You can also register a new extension from its manifest:
import { registerExtension, initialize, ExtensionHostKind } from 'vscode/extensions'
await initialize()
const extension = {
name: 'my-extension',
publisher: 'someone',
version: '1.0.0',
engines: {
vscode: '*'
},
contributes: {
}
}
const { registerFileUrl, getApi } = registerExtension(extension, ExtensionHostKind.LocalProcess)
registerFileUrl('/file-extension-path.json', new URL('./file-real-path.json', import.meta.url).toString())
const vscode = await getApi()
vscode.languages.registerCompletionItemProvider(...)
VSCode uses a bunch of default extensions. Most of them are used to load the default languages and grammars (see https://github.com/microsoft/vscode/tree/main/extensions).
This library bundles and publishes them and allows to import the ones you want:
import '@codingame/monaco-vscode-javascript-default-extension'
import '@codingame/monaco-vscode-json-default-extension'
...
VSCode extension are bundled as vsix files. This library publishes a rollup plugin (vite-compatible) that allows to load a vsix file.
import vsixPlugin from '@codingame/monaco-vscode-rollup-vsix-plugin'
...
plugins: [
...,
vsixPlugin()
]
import './extension.vsix'
This library also offers the possibility to localize vscode and the extensions in the supported languages. To do so, import one of the following packages before anything else:
@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
⚠️ The language pack should be imported and loaded BEFORE anything else from monaco-editor or this library is loaded. Otherwise, some translations would be missing. ⚠️
Try it out on https://codingame.github.io/monaco-vscode-api/
There is a demo that showcases the service-override features. It allows to register contributions with the same syntaxes as in VSCode. It includes:
From CLI run:
# build monaco-vscode-api (the demo use it as a local dependency)
npm ci
npm run build
# start demo
cd demo
npm ci
npm start
# OR: for vite debug output
npm run start:debug
For the debug feature, also run:
npm run start:debugServer
⚠️ Building monaco-vscode-api is only supported on Linux or Mac. It you use Windows, have a look at WSL ⚠️
To connect to a remote agent, run:
npm run start:extHostServer
Then go to http://localhost:5173/?remoteAuthority=localhost:8000
You can also go to http://localhost:5173/?remoteAuthority=localhost:8000&remotePath=/any/path/on/your/machine to open a directory on your machine as the current workspace
This project was mainly created to make the implementation of monaco-languageclient more robust and maintainable.
monaco-languageclient uses vscode-languageclient which was built to run inside a VSCode extension. VSCode extensions communicate with the editor via an API they can import into their code.
The VSCode api exports:
The first implementations of monaco-languageclient were using a fake VSCode api implementation. The vscode-languageclient was hacked so the VSCode<->protocol object converters were mainly bypassed, so the fake VSCode api was receiving Language Server Protocol objects. Then the objects were transformed using custom transformers into Monaco objects to communicate with the monaco api.
This approach has some disadvantages:
With this library, it would be possible to plug vscode-languageclient directly on top of monaco, monaco-languageclient still helps to do so by:
FAQs
VSCode public API plugged on the monaco editor
The npm package @codingame/monaco-vscode-api receives a total of 30,492 weekly downloads. As such, @codingame/monaco-vscode-api popularity was classified as popular.
We found that @codingame/monaco-vscode-api demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 6 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
vlt's new "reproduce" tool verifies npm packages against their source code, outperforming traditional provenance adoption in the JavaScript ecosystem.
Research
Security News
Socket researchers uncovered a malicious PyPI package exploiting Deezer’s API to enable coordinated music piracy through API abuse and C2 server control.
Research
The Socket Research Team discovered a malicious npm package, '@ton-wallet/create', stealing cryptocurrency wallet keys from developers and users in the TON ecosystem.