>_EXECUTIVE SUMMARY
zpwr-hooks-editor is the shared stryke Hooks code editor of the MenkeTechnologies app stack — one JavaScript source of truth for a Monaco editor wired with monaco-vim, monaco-emacs and a thin stryke-LSP adapter. It was extracted from the Audio-Haxor frontend so the editor is no longer duplicated across apps; the source lives in src/ and each consuming app bundles it with its own monaco-* dependencies.
The bundle is produced with esbuild (IIFE, ES2020, minified) and exposes a single window.HooksEditor facade. Language intelligence — completion, hover, diagnostics, definitions, references, rename, signature help, document symbols, code actions, semantic tokens — comes from the stryke language server (stryke --lsp) over a caller-supplied transport, mapped onto Monaco's provider/marker APIs by a thin LSP JSON-RPC client.
Two Monarch grammars ship in the one bundle, picked per editor with create({ language }): stryke (the default, Perl tokens plus the full language server) and latex (grammar, structural snippets, document-driven \ref/\cite completion and a sectioning outline, with no language server). An app that edits LaTeX — zlatex's equation pane — reuses this editor instead of forking a second one, so the theme, the vim/emacs keymaps and the Monaco instance stay shared.
Counts derived from the repo: src/*.mjs = 3 files / 1091 lines; with scripts/build-hooks-editor.mjs = 4 files / 1179 lines; register…Provider(LANG_ID call sites = 13 (plus 3 LATEX_ID providers, 16 registrations in all); monaco.languages.setMonarchTokensProvider call sites = 2; window.HooksEditor methods = 5; consumers Audio-Haxor + traderview + ztranslator + zpwr-daw = 4; devDependencies in package.json = 4.
~ARCHITECTURE
One editor source, built per consumer. The entry registers the stryke and latex languages, the cyberpunk theme, the vim/emacs keymaps and the LSP↔Monaco provider mappings; the bundler runs inside each app to resolve its own Monaco deps and emit vendored IIFE artifacts.
| Layer | Implementation |
|---|---|
| Editor core | Monaco edcore.main — all editor contributions (suggest, hover, find, folding, multi-cursor, minimap, command palette), no bundled languages |
| stryke language | stryke is a Perl-5 superset, so it reuses Monaco's Perl Monarch grammar + language config (basic-languages/perl) registered under the stryke language id; server semantic tokens overlay the Monarch highlighting |
| latex language | a second Monarch grammar in the same bundle, selected with create({ language: 'latex' }) — control words/symbols, math shifts, % comments, brace/bracket matching and $/brace auto-closing. Three LATEX_ID providers: snippet completion for the structural constructs (\frac, \sqrt, \left…\right, \sum, pmatrix, cases, …), cross-reference completion that offers the document's own \labels inside \ref{} and its \bibitem keys inside \cite{}, and a document-symbol provider that turns \part…\subparagraph into the outline. No language server is attached — the stryke server speaks stryke, so a LaTeX buffer is never opened against it |
| Modal editing | monaco-vim + monaco-emacs, switched at runtime via setMode('default'|'vim'|'emacs'); vim status/command line rendered into a caller element |
| LSP client | createLspCore — a thin JSON-RPC client (init/notify/request/receive/connected/isInitialized/onDiagnostics/ready) over a host-supplied transport; the entry maps it onto Monaco's 13 provider registrations + diagnostic markers |
| Facade | window.HooksEditor — initClient / receive / clientReady / whenReady / create |
| Editor handle | returned by create — getValue / setValue / focus / setMode / language / insert / selectRange / bindKey / onSelection / destroy. bindKey(spec, handler) takes a key back from Monaco for this editor's lifetime (Electron-style spec, e.g. "CmdOrCtrl+Shift+O", which is otherwise Monaco's Go to Symbol); returns false on an unparseable spec |
| Build | esbuild IIFE, ES2020, minified; codicon .ttf inlined as a data URL; runs inside the consumer, writes to its frontend/lib |
&LSP PROVIDER SURFACE
The entry registers 13 Monaco language providers against the stryke language id, each mapping a stryke-LSP method onto Monaco's provider API (LSP positions/ranges are 0-based, Monaco 1-based; kinds and severities are translated). Diagnostics arrive as server notifications and are applied as Monaco model markers. The latex id carries 3 further providers of its own (two completion, one document symbol) that are computed locally from the model and never touch the server.
| Monaco provider | Role |
|---|---|
registerCompletionItemProvider | completion popup (auto + trigger chars) |
registerHoverProvider | hover docs |
registerSignatureHelpProvider | signature help |
registerDefinitionProvider / registerDeclarationProvider | go-to definition / declaration |
registerReferenceProvider | find references |
registerDocumentHighlightProvider | occurrence highlight |
registerRenameProvider | rename symbol (workspace edit) |
registerDocumentSymbolProvider | outline / document symbols |
registerCodeActionProvider | code actions / quick fixes |
registerDocumentFormattingEditProvider | document formatting |
registerFoldingRangeProvider | folding ranges |
registerDocumentSemanticTokensProvider | semantic highlighting (server legend from the handshake) |
/BUNDLER & RESOLVE FIXES
scripts/build-hooks-editor.mjs emits two bundles — hooks-editor.bundle.js (+ .css) and hooks-editor.worker.js — and carries esbuild resolve overrides to avoid AMD define() builds that throw in the WebView and silently degrade the editor to a textarea. monaco-vim is forced to its ESM build (dist/index.mjs) because the browser condition's UMD bundle ships an embedded CodeMirror vim keymap with a bare define(). Bare monaco-editor imports are pinned to esm/vs/editor/edcore.main.js (the same lean ESM instance the entry uses) instead of the AMD min build monaco-emacs' require() would pull. Deep monaco-editor/esm/* subpaths without a file extension get .js appended and resolve to the package dir directly. The build defaults its output to <cwd>/frontend/lib and honors HOOKS_EDITOR_OUT.
$CI GATES
This is a non-Rust (frontend / JS) Tier-6 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/:
| Gate | Requirement |
|---|---|
| doctype / charset / lang | <!DOCTYPE html> first line, <meta charset="utf-8">, <html lang="en"> |
| meta tags | non-empty <title>, viewport meta, description meta on both pages |
| structure | at least one <h1>; every <img> has alt; no deprecated HTML4 tags |
| links | external href/src https-only; no placeholder hrefs; target="_blank" carries rel="noopener noreferrer"; index ↔ report cross-linked |
| behavior | no inline event handlers (all via hud-theme.js); referenced css/js exist in docs/ |
| brand | "zpwr-hooks-editor" present in titles + headings |
#PROJECT METADATA
| Item | Value |
|---|---|
| Version | 0.1.0 |
| Type | module (ESM); private npm package |
| Pinned devDeps | esbuild ^0.28.1, monaco-editor 0.55.1, monaco-vim 0.4.4, monaco-emacs 0.3.0 (canonical pins each consumer must match) |
| Bundle artifacts | hooks-editor.bundle.js + hooks-editor.bundle.css + hooks-editor.worker.js |
| Language server | stryke --lsp (strykelang), reached over a host-supplied transport |
| Consumers | Audio-Haxor, traderview, ztranslator (Tauri, crates/); zpwr-daw (JUCE, libs/) |
| Author | MenkeTechnologies |
| Repository | github.com/MenkeTechnologies/zpwr-hooks-editor |
| Meta umbrella | MenkeTechnologiesMeta |