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

@sv-print/plugin-api-pdf-vector

v0.1.0

Published

add vector pdf api to print template

Readme

@sv-print/plugin-api-pdf-vector

给 sv-print 提供导出矢量 PDF 的 API 插件。

基于 html2realpdf(Zig + WebAssembly 实现),导出的 PDF:

  • 文字可选中、可搜索、可复制(含 Unicode 映射,LLM/工具可直接读取文本,无需 OCR)
  • 字体子集嵌入(内置 Noto Sans 拉丁字体 + 阿拉伯/希伯来回退,支持注册自定义 TTF 中文字体)
  • 原生矢量图形: 边框、背景、渐变、阴影、表格、支持范围内的 SVG 均为矢量绘制
  • 链接保留: http/https/mailto/tel/ftp 链接转成 PDF 注释

与 plugin-api-pdf(snapdom 截图 + jsPDF 拼图方案) 相比,不存在像素化、放大模糊的问题,文字密集型文档体积通常更小。

与 plugin-api-pdf 的对比

| | plugin-api-pdf | plugin-api-pdf-vector | | -------- | ------------------------------- | -------------------------------------- | | 渲染方式 | 每页 DOM 截图为 JPEG 再嵌入 PDF | 浏览器快照 → WASM 矢量排版 | | 文字 | 不可选中(图片) | 可选中/可搜索/可复制 | | 体积 | 较大(整页 JPEG) | 较小(矢量 + 字体子集) | | 清晰度 | 受 pixelRatio/quality 限制 | 无限放大不失真 | | 图片资源 | 需同源/可跨域加载 | 需同源/可跨域加载(或 resourceResolver) | | 兼容性 | 纯 JS | 需支持 WebAssembly 的浏览器 |

参数命名与 plugin-api-pdf 保持一致(name/isDownload/type/onProgress 等),调用方法为 toVectorPdf(printData, options)。

安装

npm install @sv-print/plugin-api-pdf-vector @imggion/html2realpdf
import pluginApiPdfVector from "@sv-print/plugin-api-pdf-vector";

const plugins = [pluginApiPdfVector({})];

注意: 底层依赖 @imggion/html2realpdf 需一并安装(peerDependency)。 其 Worker 与 WASM 资源通过包内相对路径加载,使用 Vite/Webpack 等现代打包器时通常零配置可用。

Vite 开发服务器(dev)注意事项

Vite 的依赖预构建(esbuild)会丢失包内 new URL('./worker.js', import.meta.url) 等资源引用,导致 dev 模式下报 PDF Worker initialization failed。解决办法(二选一):

// vite.config.ts
export default defineConfig({
  optimizeDeps: {
    // 方案一(推荐): 排除预构建, 让 Vite 按源码处理并正确重写资源路径
    exclude: ["@imggion/html2realpdf"],
  },
});
// 方案二: 插件已内置降级 —— Worker 初始化失败时自动回退 main 线程渲染(控制台会有 warn 提示)
// 也可显式指定:
hiprintTemplate.toVectorPdf(printData, { execution: "main" });

生产构建(vite build)不受影响,Rollup 会正确处理资源引用。

示例

let hiprintTemplate = new hiprint.PrintTemplate(options);
// 其中 "text" 是一个元素的 "字段名(field)"
let printData = { text: "这是打印时显示的文本" };

// 1. 直接下载
await hiprintTemplate.toVectorPdf(printData, { name: "pdf名称" });

// 2. 获取 blob 自行处理
const res = await hiprintTemplate.toVectorPdf(printData, {
  name: "pdf名称",
  isDownload: false, // 不自动下载
  type: "blob", // 默认 blob; 支持: blob、arraybuffer、bloburl、datauristring
  onProgress: (cur, total, phase) => {
    // phase: "snapshot" | "wasm" | "complete" 三阶段
    console.log("toVectorPdf 进度", phase, cur, total);
  },
});
console.log("toVectorPdf", res); // Blob

注册中文字体(含中文内容时必需)

html2realpdf 内置字体仅覆盖拉丁(Noto Sans)+ 阿拉伯/希伯来文,中文等 CJK 字符必须注册 TTF 字体,否则导出报 MissingGlyph 错误:

const fontData = await (await fetch("/fonts/SourceHanSansCN-Regular.ttf")).arrayBuffer();

const res = await hiprintTemplate.toVectorPdf(printData, {
  name: "中文名称.pdf",
  fonts: [{ family: "SourceHanSansCN", data: fontData }],
});
  • 注册字体会自动追加为整个模板的 font-family 兜底:元素自身字体优先,未覆盖的字符(如中文)回落到注册字体,无需修改模板
  • 可同时注册多个字体(如宋体 + 黑体);同一 family 注册不同 weight/style 可实现粗体/斜体
  • 字体文件需为可嵌入的 TrueType(.ttf),otf/woff 不支持
  • data 支持直接传 ArrayBuffer,也支持 async () => ArrayBuffer 异步函数(首次导出时自动加载,适合按需拉取字体文件)

也可在插件初始化时全局注册: pluginApiPdfVector({ fonts: [...] })。

toVectorPdf 参数

hiprintTemplate.toVectorPdf(printData, options?)
  • printData: 打印数据(对象或数组)
  • options: 参数对象 ToPdfVectorOptions(name/isDownload/type/...)

常用参数(与 plugin-api-pdf 兼容)

| 参数 | 类型 | 默认 | 说明 | | ---------------------------- | ---------- | ----------------------- | ----------------------------------------------------------- | | name | string | "sv-print-时间戳.pdf" | 文件名(自动补 .pdf) | | isDownload | boolean | true | 是否自动下载 | | type | string | "blob" | 输出类型: blob、arraybuffer、bloburl、datauristring | | onProgress | function | - | 进度回调 (cur, total, phase) | | paperWidth / paperHeight | number | 面板尺寸 | 纸张尺寸覆盖(mm) | | orientation | string | 自动 | "portrait" / "landscape"(传入 paperWidth/Height 时无效) |

矢量渲染相关参数

| 参数 | 类型 | 默认 | 说明 | | ------------------ | -------------------- | --------------------- | ----------------------------------------------------------------------------------------------------------------- | | fonts | FontRegistration[] | - | 注册嵌入 TTF 字体(含中文内容时必需, 见上文) | | metadata | object | - | PDF 元数据 { title, author, subject, keywords, creator } | | enableLinks | boolean | true | 是否保留链接注释 | | canvasToSvg | function | - | canvas 图表转矢量回调(见下文) | | fallback | string | "rasterize-subtree" | 不支持的 SVG(如 <use> 引用)策略; 设 "error" 则默认不做 SVG 转图片, 严格保留矢量并按错误中断导出(特殊需求) | | svgToImage | function | - | SVG 转图片回调(见下文) | | resourcePolicy | string | "error" | 图片加载失败策略: "omit" 忽略并继续 | | resourceResolver | function | - | 跨域/受保护资源解析器 | | baseUrl | string | 页面 URL | 相对资源解析基准 | | execution | string | "worker" | WASM 执行位置: "worker" / "main" | | wasmUrl | string | 包内路径 | wasm 资源地址覆盖(CDN 部署时使用) | | signal | AbortSignal | - | 中断渲染 | | debug | boolean | true | 控制台输出渲染诊断信息 | | data | any | - | 打印数据(与第一参数等效) |

echarts 图表保持矢量

echarts 元素默认以 SVG renderer 输出(plugin-ele-echarts 使用 renderer: "svg"),天然矢量。若使用 canvas renderer,可通过 canvasToSvg 让图表库导出 SVG:

const res = await hiprintTemplate.toVectorPdf(printData, {
  name: "图表.pdf",
  canvasToSvg: (canvas) => {
    const chart = echarts.getInstanceByDom(canvas);
    return chart ? chart.renderToSVGString() : null;
  },
});

SVG 默认转图片 / svgToImage 回调

导出时模板内的所有内联 <svg> 默认会转为图片(canvas 栅格化为 PNG), 彻底避开底层 WASM 解析器不支持的特性(<use> 引用、渐变 stroke、非法 preserveAspectRatio 等)导致的 InvalidSvg 中断。

如需自定义处理(服务端渲染、图表库导出、替换品牌图、高清位图等), 通过 svgToImage 回调自行接管:

const res = await hiprintTemplate.toVectorPdf(printData, {
  name: "条码.pdf",
  // 每个 <svg> 调用一次; 返回图片源, 返回 null 回落默认栅格化
  svgToImage: async (svg, { width, height, viewBox }) => {
    // 示例: 交给服务端渲染成 PNG
    const png = await serverRender(svg.outerHTML);
    return png; // 支持 data URL / URL / Blob / <canvas> / <img>
  },
});
  • svgToImage 返回 null → 走默认 canvas 栅格化
  • svgToImage 抛错 → 错误原样透传给 toVectorPdf(Promise reject)
  • 传 fallback: "error" 时默认不做 SVG 转图片与栅格化兜底, 完全保留矢量并严格报错(特殊需求)
  • 除 svgToImage 外, canvasToSvg 仅用于 canvas 元素(echarts canvas renderer 等), 二者互不影响

插件初始化配置

pluginApiPdfVector({
  execution: "worker", // 默认; Worker 不可用环境可设为 "main"
  wasmUrl: "https://cdn.example.com/libhtml2realpdf.wasm", // CDN 部署时覆盖
  fonts: [{ family: "SourceHanSansCN", data: fontBuffer }], // 全局注册字体
});

注意事项

  1. 中文字体: 内置字体不含 CJK 字形,未注册中文字体时导出直接报 MissingGlyph 错误,请务必通过 fonts 注册(见上文)
  2. 跨域图片: 图片资源需允许跨域(CORS),否则渲染报错;可用 resourcePolicy: "omit" 跳过失败图片或 resourceResolver 自行解析
  3. CSS 兼容: 底层渲染引擎有自己的 CSS 支持矩阵(见 css-support.md),自定义 expandCss 中使用不支持的属性时会产生诊断信息(debug: true 输出)
  4. SVG 兼容: 模板内的内联 <svg> 默认转为图片(canvas 栅格化为 PNG),因此 <use> 引用、渐变 stroke、非法 preserveAspectRatio 等不支持特性不再中断导出。需要矢量/自定义处理时用 svgToImage 回调;<img src="*.svg">、CSS 背景 SVG 等仍交由底层处理(不支持的子树自动栅格化)。默认全自动处理,特殊需求才需自行传参(如 fallback: "error" 严格全矢量、canvasToSvg 处理 echarts canvas)
  5. 水印: watermarkOptions 由面板 CSS 绘制时可正常矢量渲染
  6. 旧浏览器: 需要浏览器支持 WebAssembly 与 module Worker(所有现代浏览器均支持)
  7. Vite dev: 需排除 @imggion/html2realpdf 的依赖预构建(见上文),否则 Worker 404;插件也会自动降级 execution: "main"

License

LGPL

开源使用须知

1.请自觉遵守开源协议,其他用途可联系作者;

2.允许用于个人学习、毕业设计、教学案例、公益事业、商业使用;

3.如果商用必须保留版权信息,请自觉遵守;

4.禁止将本开源的代码和资源进行任何形式任何名义的出售,否则产生的一切任何后果责任由侵权者自负;

5.商用请仔细审查代码和漏洞,不得用于任一国家许可范围之外的商业应用,产生的一切任何后果责任自负;