Trevixal API
    Preparing search index...
    interface SplitViewOptions {
        container: HTMLElement;
        debounceMs?: number;
        mode?: SplitMode;
        onMirror?: (mirror: Editor) => void | (() => void);
        orientation?: SplitOrientation;
        renderNode?: () => ((node: EditorNode) => string | null) | undefined;
        script?: () => string | undefined;
        styles?: string;
        syncScroll?: boolean;
        theme?: () => HTMLDocumentTheme | undefined;
    }
    Index
    container: HTMLElement

    Where the pane is appended; the host lays it out beside the editor.

    debounceMs?: number

    Quiet time after an edit before the preview re-renders (default 150).

    mode?: SplitMode

    preview (default) renders HTML in an iframe; mirror opens a second editor.

    onMirror?: (mirror: Editor) => void | (() => void)

    Install extensions on the mirrored editor as it is created, and return a disposer.

    The mirror is a second, independent editor. It shares the document, and nothing else: highlighting, diagram rendering and the click handlers behind tabs and accordions are all attached per editor, so a mirror left bare shows plain grey code, no diagrams, and tab titles that do not respond. Give it the same extensions the primary has and the two panes behave alike, which is the only reason to have a second one.

    createSplitView(editor, {
    container,
    mode: 'mirror',
    onMirror: (pane) => {
    const offHighlight = codeHighlight(pane, highlighter)
    const offBindings = blockBindings(pane)
    const diagrams = diagram(pane, { render })
    return () => {
    offHighlight()
    offBindings()
    diagrams.destroy()
    }
    },
    })
    orientation?: SplitOrientation

    Side-by-side (horizontal, default) or stacked (vertical).

    renderNode?: () => ((node: EditorNode) => string | null) | undefined

    Per-node HTML for the preview, read on every re-render.

    Syntax colours and a drawn diagram are not in the document, the first is a decoration, the second an element the view appends beside the block, so serializing the document alone produces neither. This is the hook that puts them back: @trevixal/ui exports captureRenderedBlocks to read them off the live editor and renderedNodeHTML to turn them into the markup a standalone page needs.

    script?: () => string | undefined

    JavaScript inlined into the preview page, read on every re-render.

    The preview is a page, not an editor: nothing in it is connected to anything, so without this a tab strip in there is a picture of one. The titles are drawn and clicking them does nothing.

    The frame runs it itself, which is why the sandbox names scripts and not allow-same-origin. The two together are the pair that lets a frame reach out and rewrite the page embedding it; scripts alone leave the preview on an opaque origin, able to run this and nothing else. It cannot read this page's DOM, its cookies or its storage.

    It is the same script the downloaded file carries, so the two behave alike. @trevixal/ui exports documentBehaviourScript for exactly this.

    The embedder cannot reach in either, which is the point and also the constraint: whatever the pane needs from the frame it has to ask for by postMessage, which is how the scroll link below works.

    styles?: string

    CSS inlined into the preview document.

    syncScroll?: boolean

    Keep both panes showing the same part of the document (default true).

    Scrolling either one moves the other to the same block, so a reader comparing them is looking at the same paragraph twice rather than hunting for it. Turn it off for a preview meant to be scrolled on its own.

    theme?: () => HTMLDocumentTheme | undefined

    The palette to render the preview in, read on every re-render so the pane follows a theme change rather than keeping the one it opened with. @trevixal/ui exports editorTheme for this.