You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is a current map of the vinary-viewer source tree — every ClojureScript
namespace (and the handful of Node-side .js / macro .clj helpers that sit
inside a layer) and its role. Architecture overview:
../architecture/01-overview.md.
The tree splits into two processes joined by the preload IPC seam, plus a set of
process-agnostic libraries (the common document IR, streaming, and the
terminal CLI/TUI renderers) that both the GUI renderer and the headless
tools build on:
Layer
Prefix
Process
Count
Main process
vinary.main.*
Electron main
24 cljs + 4 js
App / re-frame
vinary.app.*
renderer
10
Input / keybindings
vinary.input.*
renderer
7 cljs + 1 clj
Renderer services
vinary.renderer.*
renderer
20
UI components
vinary.ui.*
renderer
22
Common document IR
vinary.ir.*
shared
25
Document streaming
vinary.stream.*
shared
5
Terminal renderer
vinary.terminal.*
Node (vv-cli/vv-tui)
5
Terminal UI
vinary.tui.*
Node (vv-tui)
7
Headless CLI
vinary.cli.*
Node (vv-cli)
2
Top-level libraries
vinary.*
shared
2
1. Main process (vinary.main.*)
The Electron main process: all filesystem, child_process, network, and native
window/view work. Renderer code never imports these namespaces.
Namespace
Responsibility
vinary.main.core
Electron app/window lifecycle: creates the sandboxed renderer window + contextBridge preload, wires the menu, and opens the initial argv file.
Pure, electron/DOM-free routing helpers for the IO service (so the node :test build can assert routing without Electron).
vinary.main.content_service.js
(JS) Electron-free content engine: bounded paged reads for large logs / delimited tables, office (docx via mammoth, ODF) + workbook parsing, log sniffing, byte/line streaming sessions (streamOpen/Pull/Close), remote SFTP reads, and diff-source + remote-asset resolution. Reused verbatim by vv-cli/vv-tui.
vinary.main.file-kind
Pure file-kind classifier (extension → kind) shared by the service and tests; also remote-uri? / archive-uri? / pdf-sibling-path / source-sibling-paths.
vinary.main.config
keybindings.edn load/save/watch; pushes raw EDN text over vv:keymap (clj→js would flatten keyword command-ids).
recent.edn load/save/watch: the dir→last-child :trail, the :recent-files MRU (File ▸ Open Recent), and the :web-history URL MRU.
vinary.main.connections
Persisted non-secret SSH connection metadata (connections.edn): host entries for URI/host hints. Secrets never land here (see ssh.cljs).
vinary.main.window
Persisted main-window geometry (window.edn): position, size, maximized state, clamped to a visible display. Main-only.
vinary.main.grammars
Grammar registry (main side): decides which files are source (→ the read-only CodeMirror view) and pushes the user grammar + filetype registry.
vinary.main.shell
Menu-bar shell actions: the multi-file Open dialog, clipboard writes, reveal/open-path, open-external, app-info, quit, devtools, and app-window zoom.
vinary.main.startup
Pure, electron-free startup configuration (so the node :test build can assert it).
vinary.main.web
In-app HTTP browsing: a main-owned WebContentsView (http/https) with bounds, navigation relay, page zoom, snapshot cache, TOC bridge, and the page-key/scroll relay to the web preload.
vinary.main.pdf
RETIRED — the native PDF WebContentsView superseded by the in-renderer pdf.js view (ADR-0013). init! is commented out in core.cljs, so the vv:pdf-* channels have no live listener; the namespace is kept for recoverability.
Native password-manager bridge: provider CLIs run only in the trusted main process; the renderer sees sanitized metadata and the web preload receives fills directly. Secrets never enter renderer app-db (ADR-0016).
vinary.main.password-adapters
Provider adapters (e.g. CLI-backed vaults). All provider execution stays in main.
vinary.main.password-config
Main-side, non-secret bridge config: provider ordering and enablement.
vinary.main.password-util
Pure helpers for the password bridge (no IO, no secrets) — node-testable.
vinary.main.ssh
Electron/IPC wiring for the SSH/SFTP transport: injects the host-key trust prompt + the secret prompt + error/status sinks, and owns the vv:ssh-* channels. Secrets stay main-side (ADR-0027).
vinary.main.ssh_transport.js
(JS) SFTP transport over ssh2: a connection pool keyed by user@host:port, the auth chain (agent → identity files → password → keyboard-interactive/MFA), and host-key TOFU against known_hosts. Electron-free (prompts/sinks injected via configure()).
vinary.main.ssh_agent.js
(JS) ssh-agent client implementing SSH_AGENTC_ADD_IDENTITY (the AddKeysToAgent directive), which ssh2's agent classes do not expose.
vinary.main.ssh_config.js
(JS) Pure, dependency-light ~/.ssh/config + known_hosts parsing and host-key crypto helpers (no fs/net/electron) — node-testable in isolation.
Exposes window.vv via contextBridge; all renderer↔main IPC crosses here (89 vv:* channels).
resources/web-preload.js
Runs inside the HTTP web view (isolated): reports the heading outline + active heading, scrolls on TOC jumps and forwarded page keys, and runs the native password-form observer + self-contained link hints.
Normalize a DOM KeyboardEvent into a canonical chord token (modifiers folded cross-platform).
vinary.input.keymap
Keymap registry: the bundled presets (embedded at compile time via shadow.resource/inline), key normalization, and the active-keymap atom + user-delta merge.
vinary.input.keymaps-registry
app-db registry of keymap sets — the three read-only built-ins (Standard/Vim/Emacs) plus user sets — and the persistence envelope.
vinary.input.resolver
Modal/chord resolver (Interpreter): normalize → resolution context → step decision (:prefix/:dispatch/:consume/:pass/:retry); pending sequence + chord timer in resolver-local atoms; global keydown handling.
vinary.input.events
Input mode, pending sequence, command palette, keymap config/selection, and the keybinding-editor events.
vinary.input.fx
Input-related effects: active-keymap installation, debounced persistence, chord-timeout, and the smooth :dom/scroll / :dom/focus.
vinary.input.kbedit-history
Reversible editor commands (the Command pattern as data) for keybinding undo/redo.
vinary.input.presets
(macro .clj) SUPERSEDED — a compile-time preset-EDN slurp kept for reference; presets are now inlined by vinary.input.keymap via shadow.resource/inline (which tracks the EDN as a recompile dependency).
5. Renderer services (vinary.renderer.*)
Renderer-side, DOM-touching helpers behind the UI: parsing, rendering, layout,
find, scroll, and the pdf.js / CodeMirror engines.
Namespace
Responsibility
vinary.renderer.core
Renderer boot: re-frame loop, DataScript→re-frame reactivity bridge, IPC bridge (the on* handlers), keybinding-resolver install, React root mount, dev hooks.
vinary.renderer.markdown
Markdown → {html, toc, assets} via the common IR (render-ir), plus the office / org / latex IR render entry points.
vinary.renderer.markdown-pipeline
The DOM-free remark → rehype parse+transform pipeline (through metadata collection), extracted from markdown so streaming and the IR frontend share one spine.
vinary.renderer.math
MathJax TeX-to-SVG rendering and cached Markdown math postprocessing.
vinary.renderer.mathjax-version-shim
OBSOLETE after the MathJax 4 migration — retained (not deleted) as a record of why it existed.
vinary.renderer.mermaid
Mermaid source-to-SVG rendering for Markdown fences and direct Mermaid files; pre-DOM sizing + refit.
vinary.renderer.figures
Measure and size embedded local SVG/image figures (pre-DOM, no flash) + refit on font change.
vinary.renderer.latex
LaTeX → HTML string, the reusable front-end shared by standalone .tex documents and embedded-in-Org LaTeX (ADR-0025).
Per-navigation content-pane scroll restore (want!/apply!) and late-retry guard.
vinary.renderer.source-nav
Bidirectional source⇄preview jump helpers — content-agnostic (any format that stamps data-vv-source-*).
vinary.renderer.pdf
In-renderer pdf.js engine: worker bootstrap, canvas/text/link layers, virtualization, zoom, outline, and the :pdf/reflow effect (ADR-0013).
vinary.renderer.pdf-layout
Pure, DOM-free PDF geometry/zoom/outline helpers (unit-tested).
vinary.renderer.pdf-cache
PDF byte cache (keyed by :doc/path, not DataScript) + the in-page-find text-materialization hook; deliberately free of any pdfjs-dist require.
vinary.renderer.virtual-layout
Pure, DOM-free vertical-stack geometry shared by the in-renderer PDF view and the streaming preview body (pre-estimated sibling spacer).
vinary.renderer.find
CSS Custom Highlight API in-page search (search!/cycle!/clear!).
vinary.renderer.media
Local media URL cache-busting and source helpers for Markdown previews.
vinary.renderer.syntax
Read-only source view: a CodeMirror 6 editor highlighted by web-tree-sitter grammars; grammar registry, source selection, and source⇄line scroll helpers.
vinary.renderer.hints
Vimium-style link hints for the content pane: collect visible targets, assign labels, follow a chosen target.
vinary.renderer.history-input
Coalescing for browser-style history commands that can arrive through multiple native input channels.
6. UI layer (vinary.ui.*)
Reagent view components and their pure view-helpers.
Namespace
Responsibility
vinary.ui.views
Main shell, content strategy (per-kind view selection), Markdown body lifecycle, toolbar, status/modeline; hosts the in-pane directory browser (:doc/kind = "directory") and the Ctrl-hover breadcrumb URI bar.
vinary.ui.tabs
The tab strip + the shared tab-item used by the horizontal strip and the sidebar's vertical Tabs list.
vinary.ui.sidebar
The left sidebar shell: a tabbed pane hosting the multi-project Files tree and the Contents (TOC) outline.
vinary.ui.tree
The git file-tree (the sidebar's Files tab), one {:root :files} per project, filtering, and reveal-active.
vinary.ui.context-menu
The themed right-click context menu: targets and actions.
vinary.ui.menubar
The custom, theme-matched menu bar (File / View / Settings / Help), incl. the View ▸ Fit radio submenu.
vinary.ui.menu-focus
Pure helpers for keyboard focus inside custom menus (skipping separators/disabled rows).
vinary.ui.zoombar
The always-visible bottom zoom bar: − / editable % field / preset dropdown / +, dispatching the context-aware [:view/zoom …].
vinary.ui.palette
Command palette / fuzzy finder: one overlay, three sources (:command/:file/:theme).
vinary.ui.settings
The Preferences dialog: variable + fixed-width fonts, sizes, and view prefs (theme lives here too).
vinary.ui.extensions
Settings ▸ Extensions dialog: ad-blocking controls + the Chrome-extension manager.
vinary.ui.ext-toolbar
Browser-action toolbar (extension icons in the address-bar row; click → open popup).
vinary.ui.keybindings-editor
Visual keybinding editor (Settings ▸ Key Bindings ▸ Customize…): a two-pane modal with undoable edits.
vinary.ui.about
The Help ▸ About dialog: app name + version + repo link.
vinary.ui.modal
Shared modal-dialog shell: the scrim overlay + bordered/elevated panel with a title bar.
vinary.ui.icons
Font Awesome (Free Solid, self-hosted) icon set.
vinary.ui.access-keys
Shared helpers for desktop-style Alt access keys in custom renderer UI.
vinary.ui.platform
Tiny renderer-side OS detection (single-click-open?): single-click opens on Linux, double-click on Windows/macOS.
vinary.ui.preview-context
Pure helpers for Markdown preview context menus: term extraction and source-location formatting.
vinary.ui.preview-navigation
Navigation events for links activated from preview surfaces (classify link/target → the right open event).
vinary.ui.passwords
Renderer UI for the native password-manager bridge: provider status + login picker + save prompt — status/metadata only, never a secret.
vinary.ui.ssh
Renderer UI for SSH/SFTP remote files: the auth prompt (password / key passphrase / multi-prompt MFA) and the connection-error surface. The typed secret stays in the modal's local state.
7. Common document IR (vinary.ir.*)
One weighted-transducer intermediate representation that every format front-end
targets and every back-end lowers from (ADR-0017). The design lineage is the
lling-llang weighted-automata toolkit: front-ends parse a format into the
IR, layers/transducers transform it, back-ends lower it to HTML or ANSI,
and capabilities derive views (e.g. a TOC) from it. Markdown, office, org,
latex, diff, source, tables, logs, PDF-reflow, and archives all render through
this one tree.
7.1 Core algebra + parsing machinery
Namespace
Responsibility
vinary.ir.node
The common document IR node — one uniform tagged tree (constructors, children, walkers).
vinary.ir.meta
Per-node metadata accessors + stable anchor identity (metadata rides in the node).
vinary.ir.semiring
Semiring-generic weights: the algebra (K, ⊕, ⊗, 0̄, 1̄) that lets one parser/transducer work over many weight domains.
vinary.ir.transducer
Weighted top-down tree transducer over the IR (blueprint: lling-llang tree_transducers).
vinary.ir.lattice
A token lattice — a weighted DAG of alternative token hypotheses consumed by the Earley parser.
Earley recognizer over a token lattice (predict/scan/complete).
vinary.ir.forest
Packed parse-forest extraction from an Earley chart.
vinary.ir.layer
A composable IR→IR transform pipeline (blueprint: lling-llang LayerPipeline).
vinary.ir.flag
RETIRED (ADR-0017) — the :vv/ir migration flag that gated the common-IR render path during rollout.
7.2 Back-ends + capabilities
Namespace
Responsibility
vinary.ir.backend.html
IR → HTML: lower the IR to a HAST tree and serialize it through the shared sanitizer.
vinary.ir.backend.ansi
IR → terminal ANSI — the terminal analog of the HTML back-end (used by vv-cli/vv-tui).
vinary.ir.backend.sanitize
The single HTML sanitize schema (GitHub's allowlist) for the IR back-end and the Markdown pipeline.
vinary.ir.capability.toc
Table-of-contents capability over the IR: walk for heading-role nodes and emit the outline.
7.3 Front-ends (format → IR)
Namespace
Responsibility
vinary.ir.frontend.markdown
rehype HAST (from the app's unified pipeline) → IR.
vinary.ir.frontend.office
Office HTML (docx via mammoth, or the ODF block HTML) → IR.
vinary.ir.frontend.source
A web-tree-sitter parse tree → IR (the source-view code outline).
vinary.ir.frontend.pdf
pdf.js text-content items → IR (the hybrid, lossless PDF reflow).
vinary.ir.frontend.table
A content-service table envelope (workbook sheets, or one page of rows) → IR.
vinary.ir.frontend.log
A content-service log envelope (full text, or one page of lines) → IR.
vinary.ir.frontend.log-stream
Streaming log front-end: line batches → :record IR blocks, emitted incrementally with bounded memory.
vinary.ir.frontend.diff
.diff/.patch text (via vinary.diff) → IR for the unified colored view + per-file outline.
vinary.ir.frontend.archive
An archive/directory listing envelope → IR (directory-browser-compatible entries).
7.4 Grammar
Namespace
Responsibility
vinary.ir.grammar.log
WPDA for streaming log-record segmentation (the pushdown stack tracks brace nesting so a multi-line record is one block).
8. Document streaming (vinary.stream.*)
Bounded-memory incremental rendering (ADR-0019): trade total throughput for
latency + bounded memory on large documents. Default-on for the streamable kinds.
Namespace
Responsibility
vinary.stream.protocol
The StreamParser contract: a document that arrives as a sequence of batches → incremental IR blocks.
vinary.stream.scheduler
Drives a stream into the DOM: open a transport session, then on each idle tick pull one batch, parse it, and commit its blocks.
vinary.stream.sink
Append-mode render sink: lower IR blocks to HTML and append them to the stream body.
vinary.stream.transport
Renderer-side pull client for the main-process stream sessions (window.vv.stream{Open,Pull,Close}).
vinary.stream.flag
The document-streaming feature gate (which kinds stream, and the size threshold).
9. Terminal renderer (vinary.terminal.*)
The headless second renderer over the shared IR/streaming spine (ADR-0019): the
GUI is untouched; these lower the same IR to ANSI for vv-cli/vv-tui.
Headless terminal image graphics (the terminal analog of <img>): kitty/sixel raster + vector decode.
vinary.terminal.pdf
Headless PDF text extraction: the pdf.js legacy build (pure JS, no DOM/canvas) → reflowed text.
vinary.terminal.stream
The sink-agnostic, cancellable terminal streaming engine (line stream via content_service).
vinary.terminal.syntax
Headless tree-sitter → ANSI syntax highlighter (the terminal analog of the CodeMirror-coupled highlighter).
10. Terminal UI (vinary.tui.*)
vv-tui — the interactive full-screen terminal viewer. A pure core (state,
viewport, keys, find, toc) with one impure Node-coupled driver (term).
Namespace
Responsibility
vinary.tui.core
Wires the raw-terminal driver → key events → the pure reducer → the viewport paint (with a --drive test seam).
vinary.tui.term
The raw-terminal driver — the ONLY impure module: alternate screen, raw mode, cursor.
vinary.tui.keys
Raw-stdin bytes → key events (pure, incremental — unit-testable without a terminal).
vinary.tui.state
The pure key→command reducer (step) across three modes (:normal scroll, find, toc).
vinary.tui.viewport
A pure windowed line buffer: only a :h-row window is painted, so per-frame cost is bounded.
vinary.tui.find
Pure in-buffer search over rendered ANSI lines (matching on ANSI-stripped visible text).
vinary.tui.toc
The pure table-of-contents overlay (resolves the document's toc entries to a navigable list).
11. Headless CLI (vinary.cli.*)
Namespace
Responsibility
vinary.cli.core
vv-cli — a headless terminal document renderer; reads a file with the Electron-free content_service and prints.
vinary.cli.render
Turn a content_service payload into terminal ANSI, reusing the GUI's IR front-ends verbatim and lowering through ir.backend.ansi.
12. Top-level libraries (vinary.*)
Namespace
Responsibility
vinary.diff
Pure unified/git diff model + the side-by-side (split) renderer — DOM-free and fs-free, so it is fully unit-testable (ADR-0026).
vinary.grammar-catalog
Compile-time catalog of bundled tree-sitter grammars.
13. Dependency direction
Renderer code does not import vinary.main.*. Main code does not import renderer
UI namespaces. The preload IPC seam (resources/preload.js) is the process
boundary. The vinary.ir.*, vinary.stream.*, and vinary.diff libraries are
DOM-free and process-agnostic, so both the renderer and the headless
vinary.cli.* / vinary.tui.* tools depend on them — never the reverse.