>_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.
Counts derived from the repo: src/*.mjs = 3 files / 810 lines; with scripts/build-hooks-editor.mjs = 4 files / 898 lines; register…Provider call sites = 13; 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 language, 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 |
| 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 |
| 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, 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.
| 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 |