npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

stream-diffs

v0.0.2

Published

Lightweight, stream-native code and diff rendering for AI output, powered by @pierre/diffs and Shiki.

Readme

stream-diffs

面向 AI 输出的轻量、只读代码与 Diff 渲染库。底层使用 @pierre/diffs 与 Shiki;流式阶段不创建 Monaco model 和 worker,结束后可切换为可交互的 File、Diff 或 Git 冲突解决界面。

安装

pnpm add stream-diffs

Vue 组件入口需要 Vue 3:

pnpm add stream-diffs vue

流式代码

import { createCodeStream } from 'stream-diffs'

const output = createCodeStream({
  fileName: 'answer.ts',
  language: 'typescript',
  theme: { dark: 'github-dark', light: 'github-light' },
  maxHeight: 600,
  lineNumbers: true,
  autoScroll: 'near-bottom',
})

await output.mount(document.querySelector('#code')!)
output.append('export const ')
output.append('answer = 42\n')
await output.finalize({ view: 'file' })

实时高亮默认保护阈值为 10,000 行或 1,000,000 字符。超过任一阈值后会终止持续增长的高亮 DOM,继续累积文本并使用只追加纯文本显示;最终仍能生成准确的 File 或 Diff:

const output = createCodeStream({
  limits: {
    maxStreamingLines: 20_000,
    maxStreamingChars: 2_000_000,
    overflowBehavior: 'stop-highlighting',
  },
  onOverflow: stats => console.warn('已停止实时高亮', stats),
})

这些是 stream-diffs 的安全默认值,不是 Diffs 官方上限。宿主已限制输出长度时可传入 limits: false

append() 是性能最佳的增量路径。对于每次返回完整文本的 SDK,可以使用:

output.updateSnapshot('export')
output.updateSnapshot('export const')
output.updateSnapshot('export const answer = 42')

也可以直接消费 ReadableStream<string> 或异步迭代器:

await output.consume(response.body!)
await output.finalize({
  view: 'diff',
  original: previousSource,
  diffStyle: 'split',
})

单列与双列 Diff

import { createDiffSurface } from 'stream-diffs'

const review = createDiffSurface({
  kind: 'diff',
  oldFile: { name: 'src/app.ts', contents: before },
  newFile: { name: 'src/app.ts', contents: after },
  options: {
    diffStyle: 'unified', // 单列
    // diffStyle: 'split', // 双列
    diffIndicators: 'bars',
    lineDiffType: 'word-alt',
    enableLineSelection: true,
  },
})

await review.mount(document.querySelector('#diff')!)
review.setSelectedLines({ start: 8, end: 12, side: 'additions' })

kind: 'file' 渲染静态代码,kind: 'merge-conflict' 渲染 Git 冲突解决 UI。

原始 Git patch 与预解析 FileDiffMetadata 也可以直接渲染:

createDiffSurface({ kind: 'patch', patch: unifiedPatch, fileIndex: 0 })
createDiffSurface({ kind: 'diff', fileDiff: parsedMetadata })

在 markstream-vue 中自动使用

markstream-vue 会动态优先选择已安装的 stream-diffs,现有 CodeBlock 用法无需改变:

pnpm add markstream-vue stream-diffs
<MarkdownRender :content="markdown" :loading="streaming" />

高级配置继续通过已有的 codeBlockProps.monacoOptions 传入;保留这个属性名是为了兼容现有 API:

const codeBlockProps = {
  monacoOptions: {
    diffStyle: 'split',
    enableLineSelection: true,
    onLineSelected: range => console.log(range),
    onTokenEnter: ({ tokenText, tokenElement }) => {
      showHover(tokenText, tokenElement)
    },
    lineAnnotations: comments,
    renderAnnotation: renderComment,
    onController: controller => codeController = controller,
  },
}

流式阶段 markstream 保留自己的 <pre>。代码块完整且进入可视区域后,它只创建一次最终的静态 FileFileDiff,等待最新渲染稳定后再原子切换;完整冲突标记会进入冲突解决 UI。两种可选渲染器同时安装时优先 stream-diffs;移除它即可显式使用 stream-monaco

首次冷启动仍需异步初始化共享的 Shiki highlighter,因此 markstream 会保留 <pre>,直到 Diffs surface ready;它不创建 Monaco worker 或 model。实测 Chrome 中冷启动 fallback 中位数为 72.4 ms,stream-monaco 为 913.0 ms;1、12、24 threads 压测均未检测到容器高度回落。方法和复现命令见性能与包体积

兼容运行时提供 whenVisualReady()。只有它返回 true 时适配层才移除 <pre>;返回 false 表示创建已过期或被取消,必须继续保留 fallback。

交互能力

  • Custom headers:renderHeaderPrefixrenderHeaderMetadatarenderCustomHeader
  • Token Hover:onTokenEnteronTokenLeaveonTokenClick
  • 行选择:enableLineSelectiononLineSelectedsetSelectedLines()
  • Comments & Annotations:annotationsrenderAnnotationsetAnnotations()
  • Accept/Reject:acceptReject(hunkIndex, 'accept' | 'reject' | 'both'),也支持指定 changeIndex
  • Merge:mergeConflictActionsTypeonMergeConflictResolveresolveConflict()
  • 完整原生能力:getNativeInstance() 返回当前 FileFileDiffUnresolvedFilegetResolvedFile() 返回 Accept/Reject 后的完整文件。

示例:

review.acceptReject(0, 'accept')
review.setAnnotations([
  { side: 'additions', lineNumber: 14, metadata: { body: '这里需要校验输入' } },
])

const merge = createDiffSurface({
  kind: 'merge-conflict',
  file: { name: 'app.ts', contents: conflictedSource },
  options: {
    mergeConflictActionsType: 'default',
    onMergeConflictResolve(file) {
      save(file.contents)
    },
  },
})

当前底层 Diffs 版本把 UnresolvedFile、merge resolution 和 token hooks 标记为实验性能力,stream-diffs 会如实保留这个状态与原生类型。

Vue 组件

<script setup lang="ts">
import { StreamCode, StreamDiff, StreamMergeConflict } from 'stream-diffs/vue'
</script>

<template>
  <StreamCode :code="generated" language="typescript" :loading="streaming" />
  <StreamDiff :original="before" :modified="after" diff-style="split" />
  <StreamMergeConflict :code="conflictedSource" language="typescript" />
</template>

完整说明见 API 文档性能与包体积markstream-vue 接入文档

运行 pnpm example 可以打开真实浏览器能力实验页,同页覆盖 unified/split review、annotations、token hover、行选择、accept/reject、merge actions 和 streaming-to-file 转换。

同步的 Pierre 底层工具使用独立入口,避免根入口提前加载渲染依赖:

import { parseDiffFromFile, parsePatchFiles } from 'stream-diffs/pierre'

设计边界

  • 流式阶段只读、只追加。
  • delta append 的性能优于 cumulative snapshot。
  • 流式阶段使用 FileStream,最终 Diff 基于完整 snapshot 计算,保证准确性。
  • 超长输出会继续以只追加纯文本显示,并仍可最终生成准确 File 或 Diff。
  • 不包含 cursor editing、undo/redo、Monaco model、补全、LSP 与诊断运行时。
  • @pierre/diffs 在首次 mount 时动态加载,SSR import 安全。

License

MIT