// ZPWR-MODAL-EDITOR — ENGINEERING REPORT

Shared frontend submodule · monaco-vim + monaco-emacs engines vendored & owned · surface-adapter driven · esbuild IIFE bundle · build-on-each-consumer · one window.ZModal facade

Docs

>_EXECUTIVE SUMMARY

zpwr-modal-editor is the shared Vim / Emacs modal-editing editor of the MenkeTechnologies app stack — one TypeScript source of truth for the vim and emacs editing modes, vendored from monaco-vim and monaco-emacs and adapted so we own them outright. The source lives in src/ and each consuming app bundles it with its own monaco-editor dependency.

The design turns on a surface adapter: the vim engine talks only to a CodeMirror-shaped adapter, so the same ~7.1k-line engine can drive a Monaco editor today and a raw DOM surface later. The bundle is produced with esbuild (IIFE, ES2020, minified) and exposes a single window.ZModal facade — create (Monaco-backed mount) plus the Monaco-agnostic attachVim / attachEmacs primitives.

v0.1.0
Version
12
src .ts files
10,202
src lines
7,135
vim engine lines
1,314
monaco adapter lines
1,329
emacs engine lines
2
Modal engines
1
Surface adapters
3
Facade methods
0
External runtime deps
MIT
License

Counts derived from the repo: src/**/*.ts = 12 files / 10,202 lines; vim engine engine/vim/keymap_vim.ts = 7,135; adapters/monaco_adapter.ts = 1,314; engine/emacs/*.ts = 1,329; modal engines = vim + emacs; surface adapters = monaco (dom = next milestone); window.ZModal methods = create + attachVim + attachEmacs; runtime deps = 0 (lodash replaced by a local util).


~ARCHITECTURE

One engine source, built per consumer, behind a swappable surface adapter. The entry wires the Monaco theme + worker and the facade; the vim engine is bolted onto whichever adapter class it imports; the bundler runs inside each app to resolve its own Monaco dep and emit vendored IIFE artifacts.

LayerImplementation
Vim enginethe full CodeMirror vim keymap (motions, operators, registers, marks, ex commands, search, macros) vendored via monaco-vim; it references its host editor only through the adapter it imports as "CodeMirror"
Surface adaptermonaco_adapter.ts implements the CodeMirror API (cursor, selections, ranges, marks, operations, scrolling) over a Monaco editor; a dom_adapter implementing the same API would drive a textarea / contenteditable with no Monaco
Emacs enginemonaco-emacs' extension — keybindings, kill-ring, mark, incremental search — coupled directly to the Monaco editor API; rides the Monaco adapter only
No runtime depsthe two lodash helpers monaco-emacs used (throttle, kebabCase) are replaced by engine/emacs/localutil.ts, so the package carries zero external runtime deps
Facadewindow.ZModalcreate (Monaco-backed mount) + attachVim / attachEmacs (Monaco-agnostic primitives) + VimMode / EmacsExtension / StatusBar
Buildesbuild IIFE, ES2020, minified; codicon .ttf inlined as a data URL; runs inside the consumer, writes to its frontend/lib

&FACADE SURFACE

The bundle exposes one global, window.ZModal. create is the convenience mount (news up a Monaco editor and applies a mode); attachVim / attachEmacs are the primitives it is built on, for hosts that already own a Monaco editor and must not bundle a second one.

MethodRole
create(host, opts)create a Monaco editor + apply mode; returns a handle (getValue / setValue / focus / setMode / layout / destroy)
attachVim(editor, statusEl?)attach vim to an existing Monaco editor; mode / key-buffer / ex line render into statusEl; returns the vim adapter
attachEmacs(editor)attach emacs to an existing Monaco editor; returns the started extension
VimMode / EmacsExtension / StatusBarthe underlying classes, re-exported for advanced use

!INTEGRATION — ONE MONACO PER PAGE

The default build bundles its own Monaco. If a host page also loads another Monaco bundle (e.g. zpwr-hooks-editor), a WebKit / WKWebView content process can crash on the second full Monaco — the window renders fully blank (the content process is gone). Chromium tolerates two Monacos on one page; WebKit does not. This is an integration constraint, not a bug in the engine. Two supported patterns:

PatternHow
Share one Monacothe app creates its Monaco editor and calls attachVim(editor) / attachEmacs(editor); no second Monaco is bundled. A monaco-editor-external build variant (the clean way to ship this) is the next packaging task.
Be the only Monacouse create(...) (bundles Monaco) only in apps that don't already load one.
DOM adapterthe planned dom_adapter sidesteps the constraint entirely for vim — in-place modal editing on a page surface with no Monaco at all.

/BUNDLER & RESOLVE FIXES

scripts/build-modal-editor.mjs emits two bundles — modal-editor.bundle.js (+ .css) and modal-editor.worker.js — and carries esbuild resolve overrides so the vendored engines and Monaco resolve to ESM rather than AMD define() builds that throw in the WebView. Bare monaco-editor imports (the vendored monaco-emacs require()s it) are pinned to esm/vs/editor/edcore.main.js — the same lean ESM instance the entry uses — instead of the AMD min build. Deep monaco-editor/esm/* subpaths without a file extension get .js appended and resolve to the package dir directly (the package exports map only resolves extensioned paths). The build defaults its output to <cwd>/frontend/lib and honors MODAL_EDITOR_OUT. Because the vim/emacs engines are vendored, the consumer needs only esbuild + monaco-editor in devDependencies — no monaco-vim / monaco-emacs.


$CI GATES

This is a non-Rust (frontend / TypeScript) submodule, so it is exempt from the meta repo's cargo gates (fmt / clippy / doc / cargo test). The umbrella MenkeTechnologiesMeta repo enforces the documentation and brand gates on docs/:

GateRequirement
doctype / charset / lang<!DOCTYPE html> first line, <meta charset="utf-8">, <html lang="en">
meta tagsnon-empty <title>, viewport meta, description meta on both pages
structureat least one <h1>; every <img> has alt; no deprecated HTML4 tags
linksexternal href/src https-only; no placeholder hrefs; target="_blank" carries rel="noopener noreferrer"; index ↔ report cross-linked
behaviorno inline event handlers (all via hud-theme.js); referenced css/js exist in docs/
brand"zpwr-modal-editor" present in titles + headings

#PROJECT METADATA

ItemValue
Version0.1.0
Typemodule (ESM); TypeScript source
Pinned devDeps (consumer)esbuild ^0.28.1, monaco-editor 0.55.1 (the vim/emacs engines are vendored — no monaco-vim / monaco-emacs deps)
Bundle artifactsmodal-editor.bundle.js + modal-editor.bundle.css + modal-editor.worker.js
Vendored frommonaco-vim 0.4.4, monaco-emacs 0.3.0 (MIT; upstream licenses retained under src/engine/)
AuthorMenkeTechnologies
Repositorygithub.com/MenkeTechnologies/zpwr-modal-editor
Meta umbrellaMenkeTechnologiesMeta