markstream-vue integration

July 17, 2026 ยท View on GitHub

Integration status

The root stream-diffs entry and stream-diffs/markstream both export useMonaco, detectLanguage, and preloadMonacoWorkers. Existing markstream adapters can keep selecting the root entry without importing Monaco.

Resolution order

The CodeBlock loader attempts:

  1. import('stream-diffs')
  2. import('stream-monaco')
  3. the built-in basic <pre> fallback

This keeps both enhanced runtimes optional and makes stream-diffs the automatic lightweight choice when installed.

Runtime mapping

markstream operationstream-diffs behavior
streaming or offscreen blockmarkstream-owned <pre>; runtime not mounted
completed visible single fileone static interactive File
completed visible side-by-side diffone static split FileDiff
completed visible inline diffone static unified FileDiff
complete Git conflict markersUnresolvedFile
theme updatesetThemeType or rerender with the requested Shiki theme
cleanupdispose the current Diffs instance and cancel pending readiness

When loading changes to false and the block is visible, markstream creates a runtime with stream: false in the hidden editor layer. The <pre> stays visible until creation and whenVisualReady() finish. Markstream then switches the two layers in one component update. A stale creation cannot replace the fallback after unmount, collapse, or code-block identity change.

The existing monacoOptions property is retained because changing it would break markstream users. Diffs-native options can be placed in that object because CodeBlockMonacoOptions has an extension index.

The compatibility runtime removes only markstream/Monaco host fields such as MAX_HEIGHT, wordWrap, and renderSideBySide; every other option is forwarded to Pierre. This avoids a fixed allowlist that would drop current or future native APIs.

Advanced options

const codeBlockProps = {
  monacoOptions: {
    diffStyle: 'split',
    diffIndicators: 'bars',
    lineDiffType: 'word-alt',
    enableLineSelection: true,
    lineHoverHighlight: 'both',
    onLineSelected(range) {},
    onTokenEnter(token, event) {},
    onTokenLeave(token, event) {},
    lineAnnotations: comments,
    renderAnnotation(annotation) {},
    renderCustomHeader(fileOrDiff) {},
    mergeConflictActionsType: 'default',
    onMergeConflictResolve(file, payload) {},
    onController(controller) {},
  },
}

Use onController when an application needs imperative actions:

let controller

const options = {
  onController(value) {
    controller = value
  },
}

controller.setSelectedLines({ start: 10, end: 16, side: 'additions' })
controller.acceptReject(0, 'accept')
controller.resolveConflict(0, 'both')

Behavioral notes

  • During token streaming, the hot path stays in markstream's <pre>; line selection and token hooks become available on the final File/FileDiff surface.
  • Final diffs are recomputed from the complete original and modified contents. The library does not claim token-level incremental diff correctness.
  • If both enhanced packages are installed, stream-diffs wins. Remove it to explicitly use stream-monaco.
  • mergeConflict: false disables automatic conflict marker detection.
  • stream: false forces the static file surface.

Playground selection and benchmark

The markstream-vue playground's main Test page can switch between Stream Diffs, Monaco, Shiki, and the plain pre renderer. The selection resets the optional-runtime cache, so Stream Diffs and Monaco can be compared in the same session without changing installed dependencies.

/code-renderer-benchmark provides the repeatable streaming and multi-thread benchmark. Run pnpm test:e2e:code-renderer-streaming in markstream-vue for the asserted Chrome test, or use the page controls to change renderer, thread count, line count, chunk size, and delay. See Performance and package size for the recorded medians and resource-readiness conclusions.