npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@kson_org/monaco-editor

v0.3.0

Published

Monaco editor with KSON language support and LSP integration

Readme

@kson_org/monaco-editor

A Monaco editor with full KSON language support — completions, diagnostics, hover, go-to-definition, formatting, and semantic highlighting — powered by the same language server used by the VS Code extension.

This package is the ESM library distribution, for apps that already use Monaco and a bundler.

Install

npm install @kson_org/monaco-editor monaco-editor

API

Setup

Monaco needs a worker factory for its built-in features (tokenization, diff, and the json/typescript/css/html language services). This library does not auto-install one, so configure MonacoEnvironment.getWorker before creating any editor:

import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';

self.MonacoEnvironment = {
    getWorker(_workerId: string, label: string): Worker {
        // Add label-specific branches (json, typescript, ...) here as you need them.
        return new editorWorker();
    },
};

The label argument is 'editor' for the default worker that handles KSON tokenization; Monaco passes other labels ('json', 'typescript', …) when the corresponding language services are used.

The ?worker import above is Vite syntax. For webpack/Rspack, use new Worker(new URL('monaco-editor/esm/vs/editor/editor.worker.js', import.meta.url)). For Next.js, load the editor with dynamic(..., { ssr: false }) since Monaco is browser-only.

createKsonEditor(container, options?): Promise<KsonEditor>

Creates a KSON editor inside container. The first call starts a language server in a Web Worker.

KsonEditorOptions

| Option | Type | Description | |-----------------|-------------------------------------------------|-------------------------------------------------------------------| | value | string | Initial editor content. | | uri | string | Document URI for LSP identification. Default 'inmemory://kson/document.kson'. | | editorOptions | monaco.editor.IStandaloneEditorConstructionOptions | Forwarded to monaco.editor.create(). | | lspOptions | LspOptions (see below) | Options forwarded to the language server at initialization. Honored on the first editor; ignored on subsequent ones (they join the running server). |

LspOptions

| Option | Type | Description | |----------------------|----------------------------------------------------------|-----------------------------------------------| | bundledSchemas | Array<{ fileExtension: string; schemaContent: string }> | Maps file extensions to JSON Schema strings. | | bundledMetaSchemas | Array<{ schemaId: string; name: string; schemaContent: string }> | Custom meta-schemas. | | enableBundledSchemas | boolean | Master toggle. Defaults to true when bundledSchemas is non-empty, false otherwise. Set explicitly only to override. |

Each bundledSchemas entry maps a file extension to a JSON Schema (draft-07) string. Documents whose URI ends in .{fileExtension} get that schema's validation, completions, and hover. The most specific extension wins (e.g. special.kson beats kson for a .special.kson file).

KsonEditor (return value)

| Property | Type | Description | |----------------------|--------------------------------------|------------------------------------------------| | editor | monaco.editor.IStandaloneCodeEditor| The underlying Monaco editor instance. | | bridge | KsonLspBridge | The LSP bridge (shared with all editors on the page). | | worker | Worker | The language server Web Worker. | | serverCapabilities | ServerCapabilities | Capabilities reported by the language server. | | dispose() | () => void | Dispose this editor and release its share of the LSP worker (the worker is torn down when the last reference is released — see below). |

Only one language server runs per page. Additional editors join it automatically; the worker is torn down when the last editor is disposed.

Additional exports

| Export | Sub-path | Description | |------------------------|---------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | attachKsonLsp | @kson_org/monaco-editor | Attach the LSP to an editor you already created (e.g. via @monaco-editor/react). See the React demo for a worked example. | | useKsonLsp | @kson_org/monaco-editor/react | React hook over attachKsonLsp — handles the StrictMode-safe attach/detach lifecycle for you. | | registerKsonLanguage | @kson_org/monaco-editor | Register the KSON language with Monaco (called automatically by createKsonEditor). | | KSON_LANGUAGE_ID | @kson_org/monaco-editor | The language identifier string ('kson'). | | KsonLspBridge | @kson_org/monaco-editor | The LSP bridge class, for advanced use. | | TabBar | @kson_org/monaco-editor | The tab bar component used for multi-document navigation. |

React (@monaco-editor/react)

For apps that already render Monaco via @monaco-editor/react, the useKsonLsp hook from @kson_org/monaco-editor/react is a one-hook integration.

npm install @kson_org/monaco-editor @monaco-editor/react monaco-editor react react-dom

Three pieces are required:

import { useState } from 'react';
import * as monaco from 'monaco-editor';
import { Editor, loader } from '@monaco-editor/react';
import { useKsonLsp } from '@kson_org/monaco-editor/react';
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';

// 1. Reuse the bundled monaco — otherwise @monaco-editor/react fetches a
// second copy from a CDN and our LSP providers register against the wrong module.
loader.config({ monaco });

// 2. Wire the default-label worker — kson tokenization runs there.
self.MonacoEnvironment = {
    getWorker(_workerId: string, _label: string): Worker {
        return new editorWorker();
    },
};

function MyEditor() {
    const [editor, setEditor] = useState<monaco.editor.IStandaloneCodeEditor | null>(null);
    // 3. Attach the LSP — handles StrictMode and async attach/detach for you.
    useKsonLsp(editor, { lspOptions: { /* bundledSchemas, ... */ } });
    // defaultPath must end in .kson — the LSP keys schemas off the URI extension.
    return <Editor language="kson" defaultPath="config.kson" onMount={setEditor} />;
}

useKsonLsp calls attachKsonLsp under the hood, bakes in the cancelled-flag dance that guards the unmount-before-attach race, and disposes the LSP refcount on unmount. Options are read once when the editor first becomes non-null; re-mount the editor if you need to change schemas. See main.tsx for a runnable example.

Local development

Demos and dev commands for working in the source repo:

# Vanilla TS demo — imports createKsonEditor from source
./gradlew tooling:lsp-clients:npm_run_demoVanilla

# React demo — attachKsonLsp inside @monaco-editor/react
./gradlew tooling:lsp-clients:npm_run_demoReact

# Iframe demo
./gradlew tooling:lsp-clients:npm_run_demoIframe

# Build library
./gradlew tooling:lsp-clients:npm_run_buildMonaco

# Run tests
./gradlew tooling:lsp-clients:npm_run_test