Skip to content
QuireKit MSFE
Developer docs
v0.0.0 · Experimental
API referenceView Markdown ↗

Rendering and host API

Projection layers, component mounting, languages, search and preview controls.

Signatures come from public package exports. Descriptions are checked against current JSDoc; identifiers retain their original names.

Source reveal

readSourcePresentation(state) returns mode, selection, reveal, composing and selecting. The presentation selection stays stable during a pointer gesture and can differ from live state.selection. reveal is selection (the ordinary MSFE default) or hidden, which keeps recognized syntax projected while editing. Built-in ProjectionContext.active already accounts for this policy. Prefer active in extensions instead of revealing syntax from the live caret. Source mode always displays the original text.

sourceRevealSetting is a public PresentationSetting<SourceRevealPolicy>. Install sourceRevealSetting.extension(() => 'hidden') through addCodeMirrorExtensions(), then call sourceRevealSetting.set(editor, 'selection'). read(state) returns the applied value and requested(state) returns the latest request; both return undefined when uninstalled. The setter returns MsfeResult: not-installed for a missing setting, invalid-change for an invalid value, and rejection for destroyed or unmounted instances. Requests do not change source or permission and defer during pointer selection and composition. Product consumers should use MD Editor's view.

Replacement ranges participate in atomic navigation under hidden, preventing caret stops inside invisible syntax. Unknown or incomplete input must remain source text; do not hide unsupported text with CSS.

sourceRevealResolver.of(resolveOwner) installs an optional CodeMirror facet for the host. resolveOwner(state, range) returns the canonical source range containing the original fragment, so inline syntax can share a paragraph, list-item or cell owner. Bounds must be integer document positions; invalid ownership throws invalid-source-reveal-owner. Without a resolver, each node retains its own reveal range. Query only local syntax ancestry; do not serialize the document, change selection or dispatch. MD Editor installs this policy for custom nodes, normalized replacements and measured component geometry alike.

Built-in projections keep using ProjectionContext.active. Independent CodeMirror plugins can call isSourceRevealed(state, { from, to }) to apply the same mode, hidden preference and stable pointer selection. isSourceActive(selection, from, to) only tests intersection. A replacement's revealRange identifies its complete fragment before host ownership is resolved; interaction: 'atomic' retains its explicit atomic behavior.

Optional input proxy

sourceInputProxy({ mediaQuery, modes?, revealMargin?, onSelectionTap? }) returns an installable CodeMirror extension, enabled by default only in live mode when the owner-window media condition matches. MD Editor already installs it for narrow touch devices; hosts must not install a second copy. It reuses @quirekit/ime and mounts a textarea in the current Document/ShadowRoot input layer, outside rendered content. The document, logical selection, source rules and history remain in the original CM state. Cancellation preserves the selected source; confirmation commits once. Permission loss, document replacement and disposal release the native host. Optional onSelectionTap(view, point) returns true when the host handled a tap in an existing selection; the proxy neither moves the caret nor focuses again. Touch end and its compatibility click are accepted once. MD Editor uses this to toggle selection actions. Native Selection may not own noneditable source while the proxy is active; independent embedded controls retain their ranges. revealMargin reserves additional client CSS space when revealing the caret, defaulting to 8px. MD Editor uses 32px for the painted grip and its touch target. It changes neither source position nor document layout.

editor.focus() selects the current input owner. Custom CM controls should use focusSourceView(view), sourceInputHasFocus(view) and sourceInputElement(view) rather than assuming view.hasFocus or contentDOM represents mobile keyboard focus. sourceInputFocusChanged(update) reports native and proxy logical focus changes. During measurement, sourceInputCaret(view) returns a preedit tail rectangle in client CSS coordinates, or null without preedit, when callers can use coordsAtPos. Do not focus or clear input every frame.

sourceInputPosition(view, { x, y }) accepts a client CSS hit, skips atomic interiors and zero-height source rows, and snaps a gap to one of its nearest visible source boundaries. It returns null when no mounted caret can be proven; retain the previous endpoint instead of accepting a hidden posAtCoords hit. sourceCaretRect(view, pos, side?) returns only a mounted caret with a real line box. It tries the other association when the preferred fence/heading boundary is invisible, with one ordinary read or at most two boundary reads, returning null when geometry cannot be proven.

During measurement, sourceViewport(view) intersects VisualViewport offsets, clipping ancestors and CM scrollMargins without counting the keyboard and dock twice. sourceScrollStep(view, delta) measures one vertical step in the nearest scrollable ancestor, handing off to the page at its limit; applySourceScrollStep(step) performs that measured write without changing source or selection. Consumers own a single drag frame and re-hit the latest endpoint, stopping on release, cancellation, permission/mode changes and disposal. Accepted proxy taps, actual input and viewport resize reveal the caret through the same bounds; manual scrolling and programmatic focus restoration retain no navigation anchor. Mounted nearest-caret scroll delegates to the same reveal owner to avoid competing writes; visible input performs no scroll write. Keyboard changes can await pending document-tail layout for at most eight measurements, stopping as soon as the endpoint is visible. New user scroll intent still cancels immediately.

Projection declarations

Use block layers for multiline previews; see Diagrams.

@quirekit/msfe-core

Composable layer; block output is provided before CM computes the viewport.

ProjectionLayerts

Canonical inputs

Query bounded semantics; never dispatch while building.

@quirekit/msfe-core

Bounded projection inputs, with semantic queries and typed state access.

ProjectionInputts

View descriptions

Stable renderers and immutable props form retained view descriptions.

@quirekit/msfe-core

@param renderer - Typed renderer. @param props - Typed immutable inputs. @param map - Pure relocation of source-coordinate props for incremental layers; no resource acquisition or source writes. @returns Installable view description.

componentViewts

Mount context

Scope belongs to the current view; request measurement after geometry changes.

@quirekit/msfe-core

Generic component inputs, independent of source-node persistence.

ComponentViewMountts

Update and teardown

Update the retained entry and release host-owned resources during teardown.

@quirekit/msfe-core

Generic retained component lifecycle.

ComponentViewHandlets

Code languages

See Code blocks for a complete lazy registry.

@quirekit/msfe-core

Host-owned lazy language; parsed by the canonical Markdown mixed parser.

CodeLanguagets

Search panel

Components use view; replacement respects permission and composition.

@quirekit/msfe-core

Host renderer contract for the existing search panel lifecycle.

SearchPanelPropsts

Preview configuration

Math, Mermaid and TextDiagrams expose host action controls through this option.

@quirekit/msfe-markdown-extras

Optional host UI; feature packages do not prescribe a product button skin.

PreviewOptionsts

edit delegates preview editing to host UI such as the shared formula panel. The request has passed target and permission validation. For an asynchronous draft, independently call captureAnchor(range), check anchor.target() on confirmation and release it on close. Return true after taking ownership; omitting the callback retains source reveal. See MD Editor.

@quirekit/msfe-markdown-extras

An explicit editing request after the preview's mapped source has been validated.

PreviewEditRequestts

Preview actions

Install TextDiagrams for PlantUML/DOT with the same PreviewOptions, edit callback and cancellation lifecycle. The neutral renderTextDiagram(language, source, options) API from @quirekit/text-diagram/browser returns a sanitized SVG snapshot tied to the exact language and source. rasterizeTextDiagram(snapshot, ownerDocument, signal) produces PNG from that snapshot. MD Editor previews, the shared source workspace and Word image export use this path for all three languages.

renderMermaidSvg() renders sanitized static SVG from source in a browser, sharing the preview's serialized Mermaid queue and security configuration. Pass a cancellation signal and typography; hosts can rasterize the result for file export. It does not read editor DOM, register SVG events, or permit external image/style resources.

@quirekit/msfe-markdown-extras

@param text - Exact Mermaid source. @param signal - Explicit lifetime. @param typography - Effective host font role. @returns Sanitized SVG from the shared text-diagram owner.

renderMermaidSvgts
@quirekit/msfe-markdown-extras

Host typography resolved only when acquiring a new preview, without a UI package dependency.

PreviewTypographyts

Handle loading, errors, retry and source reveal.

@quirekit/msfe-markdown-extras

Semantic preview actions passed to a host's existing component library.

PreviewControlPropsts

Image resources

Source destinations pass field validation before host resolution.

@quirekit/msfe-image

Resolves Markdown image destinations and stores pasted or dropped images, without storing host credentials in the document.

ImageOptionsts

Block controls

The core owns native hit testing, pointer lifecycle and guarded transactions; hosts own component rendering. Child flows are opt-in. Pointer updates inspect only local ancestor paths, and commands run only on release or explicit menu actions.

@quirekit/msfe-core

@param state - Accepted source. @param node - Candidate container. @returns Editable child flow, null for unhandled syntax, or false to exclude an incomplete/position-sensitive block.

SourceBlockScopeResolverts
@quirekit/msfe-core

Optional nested child-flow declarations; document-level blocks work without configuration.

sourceBlockScopests
@quirekit/msfe-core

@param options - Host-owned UI observers. @returns Source-native block hit testing, drag/drop and menu intent lifecycle.

createSourceBlockControlsts
@quirekit/msfe-core

Framework-neutral observers; UI remains in the consumer's component/provider tree.

SourceBlockControlsOptionsts
@quirekit/msfe-core

Small transient snapshot for a host-rendered block handle and menu.

SourceBlockControlsts
@quirekit/msfe-core

Host insertion entry for empty source, sharing the block observer without drag semantics.

SourceInsertionControlsts
@quirekit/msfe-core

Client-space geometry read from the canonical view, never a layout authority.

SourceBlockRectts
@quirekit/msfe-core

Current validated insertion boundary during a pointer gesture.

SourceBlockDropts
MSFE · QuireKitYour Markdown source stays yours.