Using extensions
Adding views, commands, panels, language support and filesystems to a workbench through the extensions option
An extension is an object you pass to extensions on the workbench. Some are values you import
directly; some are functions you call to set options. Pass a few together:
import { Workbench } from "codelet/workbench";
import { search } from "codelet/extensions/search";
import { logs } from "codelet/extensions/logs";
import { media } from "codelet/extensions/media";
const workbench = new Workbench({
parent: document.getElementById("app")!,
extensions: [search, logs(), media],
});search and media are extension objects. logs() is a function that returns one — that's how
an extension takes options.
#Everything is opt-in
A workbench passed no extensions has no Search icon, no panel, no language support — none of it
is built into the workbench itself. Each built-in lives at its own package entry
(codelet/extensions/search, codelet/extensions/logs, and so on), so a page that never imports
one never bundles it. What you add is the only cost past the workbench itself.
#Where extensions show up
- Activity bar — an icon down the side that opens a sidebar view.
- Panel — a tab along the foot of the editor, beside Problems. Logs and Terminal both add one.
- Secondary side bar — a pane beside the editor rather than instead of the tree. Chat uses this.
- Editor tab bar — a button at the right of the strip, over the file showing. The markdown preview button is one.
- Context menus — the explorer's, a tab's, a view's own rows, and the document itself.
- Command palette — every command an extension registered a handler for, under
Mod-KorMod-Shift-P.
How a manifest declares each of these, and what a command or a view can do once it's there:
#Manifest and activation
Every extension has two halves. Its manifest — what it contributes to the activity bar, the
panel, the palette, the tab bar — is plain data, read without running any of the extension's
code. Its activate function is where the real work happens: workers start, sockets open,
packages get fetched from a CDN.
That split is what lets the server render the shell around an extension without running it: the
icon and the title come from the manifest, and activate only runs once the workbench mounts in
a browser.
Warning
extensions is markup. Pass the exact same array, in the same order, to both renderWorkbench()
on the server and Workbench on the client — or hydration has nothing to match and the shell
rebuilds instead of taking over.
import { renderWorkbench } from "codelet/workbench/server";
import { EXTENSIONS } from "./extensions.ts";
const html = renderWorkbench({ extensions: EXTENSIONS });#Starting and stopping an extension
codelet/extensions/extensions draws a card for every extension the workbench was given, what
each one contributes, and a button that stops it and starts it again — without a reload.
import { extensions } from "codelet/extensions/extensions";
import { search } from "codelet/extensions/search";
import { logs } from "codelet/extensions/logs";
new Workbench({ parent, extensions: [extensions, search, logs()] });#Every built-in
Search
A sidebar view over the tree, and where a reference search lands too.
Terminal
xterm in the panel, over a shell another extension provides.
Source control
What has changed, in a pane of its own.
Language servers
TypeScript, CSS, HTML, JSON and Markdown, each its own entry.