Skip to Content

CSS / JS API

Manage custom CSS and JavaScript plugins.

dmn.css

Global custom CSS state is { path: string | null, content: string }.

dmn.css.get(): Promise<CustomCss>

Returns the current custom CSS (source file path and content).

const { path, content } = await dmn.css.get();

dmn.css.getUse(): Promise<boolean>

Returns whether custom CSS is enabled.

dmn.css.toggle(enabled: boolean): Promise<{ enabled: boolean }>

Enables or disables custom CSS.

dmn.css.load(): Promise<CssLoadResult>

Opens a file dialog and imports the selected CSS file. The file must be a regular .css file, UTF-8 encoded, and at most 1 MiB. Successfully imported files are added to the history (up to 10 entries).

type CssLoadResult = { success: boolean; error?: string; // error code on failure (see table below) content?: string; path?: string; };

If the user cancels the dialog, success is false and error is omitted.

dmn.css.setContent(content: string): Promise<CssSetContentResult>

Replaces the CSS content directly (the source path is unchanged). Content is limited to 1 MiB.

dmn.css.reset(): Promise<void>

Disables custom CSS and clears the content. The history is preserved.

dmn.css.onUse(callback): Unsubscribe

Subscribes to enable/disable changes. The callback receives { enabled: boolean }.

dmn.css.onContent(callback): Unsubscribe

Subscribes to content changes (imports, hot reload, direct edits). The callback receives CustomCss.

const unsub = dmn.css.onContent(({ path, content }) => { console.log("CSS updated:", path); });

dmn.css history

The app keeps up to 10 previously imported CSS files. Only paths in this history can be re-activated; arbitrary paths are rejected with PATH_NOT_AUTHORIZED.

dmn.css.historyGet(): Promise<CustomCssHistoryItem[]>

type CustomCssHistoryItem = { path: string; lastUsedAt: number; // unix millis status: "available" | "missing" | "invalid" | "tooLarge"; };

status is advisory: it reflects a quick file check at query time, and the authoritative validation happens on activation.

dmn.css.historyActivate(path: string): Promise<CssActivateResult>

Switches the global custom CSS to a history entry without a file dialog.

type CssActivateResult = { success: boolean; code?: CssHistoryErrorCode; // on failure content?: string; path?: string; };

dmn.css.historyRemove(path: string): Promise<CustomCssHistoryItem[]>

Removes an entry from the history (the file itself is not touched) and returns the updated list.

Error codes

CodeMeaning
PATH_NOT_AUTHORIZEDThe path is not in the history
NOT_FOUNDFile does not exist
NOT_REGULAR_FILENot a regular file
INVALID_EXTENSIONNot a .css file
TOO_LARGEOver 1 MiB
INVALID_UTF8Not valid UTF-8
IO_ERROROther I/O failure

dmn.css.tab

Per-tab CSS overrides the global CSS for a single key tab. A tab override is { path: string | null, content: string, enabled: boolean }. Tab CSS is rendered only while the global custom CSS toggle is on.

dmn.css.tab.getAll(): Promise<TabCssOverrides>

Returns all overrides as a Record<tabId, TabCss>.

dmn.css.tab.get(tabId: string): Promise<TabCssResponse>

Returns { tabId, css: TabCss | null }.

dmn.css.tab.load(tabId: string): Promise<TabCssLoadResult>

Opens a file dialog and imports a CSS file for the tab. The same constraints as dmn.css.load() apply; on failure error carries an error code string.

dmn.css.tab.activateHistory(tabId: string, path: string): Promise<TabCssActivateResult>

Applies a global history entry to the tab. The path must be in the history (PATH_NOT_AUTHORIZED otherwise).

type TabCssActivateResult = { success: boolean; code?: CssHistoryErrorCode; tabId: string; css?: TabCss; };

dmn.css.tab.export(tabId: string): Promise<TabCssExportResult>

Opens a save dialog and writes the tab’s registered CSS content to a .css file.

type TabCssExportResult = { success: boolean; code?: "NO_TAB_CSS" | "IO_ERROR"; error?: string; // details for IO_ERROR path?: string; // saved location on success };

If the user cancels the dialog, success is false and code is omitted.

dmn.css.tab.set(tabId: string, css: TabCss | null): Promise<TabCssSetResult>

Sets or removes (with null) the tab override directly. Only paths previously authorized through a file dialog or history activation are accepted: an unauthorized path is dropped and the override is stored as content-only (path: null in the stored state and response).

dmn.css.tab.toggle(tabId: string, enabled: boolean): Promise<TabCssToggleResult>

Enables or disables the tab override without removing it.

dmn.css.tab.clear(tabId: string): Promise<TabCssClearResult>

Removes the tab override, falling back to the global CSS.

dmn.css.tab.onChanged(callback): Unsubscribe

Subscribes to tab override changes. The callback receives { tabId, css: TabCss | null }.

dmn.js

JavaScript plugin state is { plugins: JsPlugin[] } where each plugin is { id, name, path, content, enabled }.

dmn.js.get(): Promise<CustomJs>

Returns the current plugin list.

dmn.js.getUse(): Promise<boolean>

Returns whether JS plugins are enabled.

dmn.js.toggle(enabled: boolean): Promise<{ enabled: boolean }>

Enables or disables JS plugins globally.

dmn.js.load(): Promise<JsLoadResult>

Opens a file dialog and adds the selected plugin files.

type JsLoadResult = { success: boolean; added: JsPlugin[]; errors?: { path: string; error: string }[]; };

dmn.js.reload(): Promise<JsReloadResult>

Re-reads all plugin files from disk and returns { updated, errors? }. Plugins are always torn down and re-run, even if the file contents are unchanged, so an explicit reload can be used to reset plugin state.

dmn.js.remove(id: string): Promise<JsRemoveResult>

Removes a plugin by id.

dmn.js.setPluginEnabled(id: string, enabled: boolean): Promise<JsPluginUpdateResult>

Enables or disables a single plugin.

dmn.js.setContent(content: string): Promise<JsSetContentResult>

Replaces the inline JS content.

dmn.js.reset(): Promise<void>

Disables JS plugins and clears the plugin list.

dmn.js.onUse(callback): Unsubscribe

Subscribes to enable/disable changes ({ enabled: boolean }).

dmn.js.onState(callback): Unsubscribe

Subscribes to plugin list changes. The callback receives CustomJs.

const unsub = dmn.js.onState(({ plugins }) => { console.log( "plugins:", plugins.map((p) => `${p.name}(${p.enabled ? "on" : "off"})`), ); });