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 🙏

© 2025 – Pkg Stats / Ryan Hefner

paste-tool

v0.0.4-beta.2

Published

Tiny browser paste helper — extract rich text or merge multiple pasted images into a single, layout-preserving Blob.

Downloads

27

Readme

中文说明

Read this in: English · 中文

npm version license

paste-tool 是一个轻量、无运行时依赖的浏览器剪贴板辅助库:在粘贴时提取富文本(HTML/RTF/纯文本),或将多张粘贴的图片按原始布局合并为一张可预览/上传的图片 Blob。适用于从 Excel/Word/远程桌面或截图粘贴内容并需要稳定上游负载的场景。

目录

  • 安装
  • 快速开始
  • API
  • 示例
    • 文本粘贴
    • 图片粘贴
    • 图片回退
  • Playground
  • 功能亮点
  • 常见问题
  • 贡献
  • 开发
  • 许可
  • README (English)

安装

pnpm add paste-tool
# 或
npm install paste-tool
# 或
yarn add paste-tool

快速开始

库暴露单一函数 onPaste(isImage, event),根据 isImage 返回图片 Blob 或文本对象 ClipboardTextPayload

interface HtmlSnapshotOptions { log?: (message: string, error: unknown) => void mimeType?: string // 默认为 image/png;可指定 image/jpeg 或 image/svg+xml(直接返回 SVG) }

处理文本粘贴

import { onPaste } from 'paste-tool'

window.addEventListener('paste', async (event) => {
  try {
    const payload = await onPaste(false, event)
    console.log('首选内容:', payload.preferred)
    console.log('HTML:', payload.html)
    console.log('纯文本:', payload.plain)
  }
  catch (err) {
    console.error('剪贴板没有文本数据', err)
  }
})

特点:

  • 优先级:HTML > RTF > 纯文本。
  • 支持合并来自多片段(例如从表格复制)的内容,保留布局和换行方向(横向/纵向)。
  • 当同步事件数据不足时,会回退使用异步剪贴板 API(navigator.clipboard)。

处理图片粘贴

import { onPaste } from 'paste-tool'

window.addEventListener('paste', async (event) => {
  try {
    const blob = await onPaste(true, event)
    const url = URL.createObjectURL(blob)
    document.querySelector<HTMLImageElement>('#preview')!.src = url
  }
  catch (err) {
    console.error('剪贴板没有图片数据', err)
  }
})

当检测到多张图片时,库会根据剪贴板中携带的布局提示(HTML 片段、换行或表格结构)推断排列顺序并在画布上合成一张图片。输出优先使用 image/pngimage/webp,否则降级为 PNG。

如果未找到图片但存在富文本(某些源把图片以 HTML/text 暴露),onPaste(true, ...) 会返回 ClipboardTextPayload,你可以根据该结果回退到文本处理逻辑。

如果担心 HTML 渲染带来的性能开销,可以传入第三个参数进行控制:

const blob = await onPaste(true, event, {
  enableHtmlSnapshot: false, // 关闭 HTML → 图片 的自动回退
})

图片粘贴回退(示例)

import type { ClipboardTextPayload } from 'paste-tool'
import { onPaste } from 'paste-tool'

function isTextPayload(v: unknown): v is ClipboardTextPayload {
  return typeof v === 'object' && v !== null && 'plain' in v
}

window.addEventListener('paste', async (event) => {
  event.preventDefault()
  const result = await onPaste(true, event)
  if (result instanceof Blob) {
    // 使用图片
  }
  else if (isTextPayload(result)) {
    // 回退使用文本(例如 HTML 包含 <table>)
  }
})

API

onPaste(isImage: boolean, event?: ClipboardEvent | null, options?: PasteOptions): Promise<Blob | ClipboardTextPayload>

类型:

interface PasteOptions {
  enableHtmlSnapshot?: boolean // 默认 true;无图像 Blob 时是否尝试把 HTML 光栅化成图片
  htmlSnapshotOptions?: HtmlSnapshotOptions // 透传给 renderHtmlToImage
}

interface ClipboardTextPayload {
  html: string | null
  rtf: string | null
  plain: string | null
  preferred: string | null // HTML > RTF > plain
}

失败时 Promise 会以错误信息拒绝(说明没有可用数据)。

另提供 renderHtmlToImage(html: string, options?: HtmlSnapshotOptions): Promise<Blob>,用于手动将任意 HTML 片段渲染成图片;可通过 options.log 自定义错误日志,或设置 options.mimeType(如 image/jpeg / image/svg+xml)控制输出格式。

Playground

仓库内提供一个 Vue playground(playground/vue),用于手工测试。启动:

pnpm install
pnpm --filter paste-tool-playground dev
# 打开 http://localhost:5173 进行粘贴测试

常见问题

  • 可以不传事件直接调用吗? 可以,函数会尝试使用 navigator.clipboard.read() / readText() 做异步读取(浏览器支持及权限要求视环境而定)。

  • 支持多张图片合成吗? 支持,库会尽量按原始复制的布局合并(表格/行列/块状排列),无法完全确定时按合理默认堆叠。

  • 生成的图片为何出现透明/背景差异? 有些源(或截图)会包含透明区域。库在合成时有选项填充白底以保证在深色 UI 中显示一致。若你希望自定义背景色,请在合成前对返回的 Blob 再次处理或打开对应选项(可在代码中调整)。

进阶与性能建议

  • 采用 Promise.allSettled 并优先解码体积小的 Blob,可以更快获得预览。
  • 使用 OffscreenCanvas + Worker 将合成放到工作线程可避免主线程阻塞。
  • 对重复粘贴的相同图片维护缓存(key = type+size+lastModified)可减少解码成本。

贡献

欢迎提交 PR 或 Issue。请在 Issue 中说明浏览器、操作系统、粘贴来源与复现步骤(最好附上截图或最小复现)。

开发

pnpm install
pnpm run typecheck
pnpm run lint
pnpm test

许可

MIT

赞助

buy me a cup of coffee