@dvina/artifact-renderer

中文文档
0.0.59发布于 2026/11/13MITTypeScriptES Module近 30 天下载 4877

Framework-agnostic SDK for embedding the Dvina Artifact Renderer in an iframe.

原始使用文档
文档目录12 节
  1. Install
  2. Important
  3. Quick Start
  4. Private Files
  5. Main API
  6. Loading
  7. Theme Updates
  8. Safe Area
  9. Scroll progress
  10. Runtime Notes
  11. Related Packages
  12. Documentation

@dvina/artifact-renderer

@dvina/artifact-renderer is an iframe-first SDK for embedding the Dvina Artifact Renderer inside your application.

It is designed for products that need to preview user uploads, generated artifacts, and private documents without rendering untrusted content directly inside the host app DOM.

Install

npm install @dvina/artifact-renderer

Important

This package is the host-side SDK. You also need to deploy the self-hosted viewer image to a dedicated origin such as https://viewer.example.com/.

docker run --pull always -p 8080:8080 kantist/artifact-renderer-viewer:latest

Quick Start

import { createViewer, type ViewerDocument } from "@dvina/artifact-renderer";

const container = document.querySelector("#viewer-slot");

if (!(container instanceof HTMLElement)) {
  throw new Error("Viewer container not found.");
}

const documentToPreview: ViewerDocument = {
  id: "artifact-123",
  name: "analysis.pdf",
  format: "pdf",
  source: {
    kind: "url",
    url: "https://cdn.example.com/previews/analysis.pdf",
  },
};

createViewer({
  container,
  viewerUrl: "https://viewer.example.com/",
  allowedOrigin: "https://viewer.example.com",
  document: documentToPreview,
});

Private Files

For private files, use a session-backed document and provide getSession().

createViewer({
  container,
  viewerUrl: "https://viewer.example.com/",
  allowedOrigin: "https://viewer.example.com",
  document: {
    id: "private-doc-7",
    name: "board-packet.docx",
    format: "docx",
    source: {
      kind: "session",
      sessionId: "board-packet-session",
      url: "https://api.example.com/viewer/files/private-doc-7/preview",
    },
  },
  getSession: async () => {
    const response = await fetch("https://api.example.com/viewer/sessions", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        documentId: "private-doc-7",
        scope: "artifacts:read",
      }),
      credentials: "include",
    });

    if (!response.ok) {
      throw new Error("Failed to create viewer session.");
    }

    return response.json();
  },
});

Main API

  • createViewer(options)
  • controller.loadDocument(document, options?)
  • controller.setTheme(theme)
  • controller.setSafeArea(safeArea)
  • controller.goToPage(page)
  • controller.sendArtifactData(data, options?)
  • controller.destroy()
  • controller.getDiagnostics()

Loading

The viewer draws nothing of its own while a document loads. Keep your own loading UI over the iframe until the viewer.document-loaded event (or viewer.error / viewer.unsupported), so your app has one spinner everywhere.

Theme Updates

Pass theme to createViewer(...) for the initial render, then call setTheme(...) when your app theme changes.

const controller = createViewer({
  container,
  viewerUrl: "https://viewer.example.com/",
  allowedOrigin: "https://viewer.example.com",
  document: documentToPreview,
  theme: { mode: "light" },
});

controller.setTheme({
  mode: "dark",
  tokens: {
    surface: "#0f1115",
    text: "#f3f5f8",
  },
});

setTheme(...) updates the viewer appearance without reloading the current document.

Safe Area

Pass overlay and device insets through createViewer. Each edge is a finite, non-negative number in CSS pixels; omitted edges default to 0.

const controller = createViewer({
  container,
  viewerUrl: "https://viewer.example.com/",
  allowedOrigin: "https://viewer.example.com",
  document: documentToPreview,
  safeArea: { top: 64, right: 0, bottom: 34, left: 0 },
});

controller.setSafeArea({ top: 80, bottom: 24 });
controller.setSafeArea({}); // Reset all edges.

setSafeArea replaces all edges without reloading the document. The latest value is retained across document loads, HTML streams, and calls made before readiness. The consumer should measure overlays and resolve device safe-area values in its own window (including env(safe-area-inset-*) when needed); these are not read from the parent window or added automatically.

PDF, PPTX, DOCX, text, Markdown, code, media, and archive viewers apply insets to their scrolling surfaces, so content can scroll beneath an overlaid host header. Spreadsheet headings and the footer respect insets; EPUB reserves space around its navigation and chapter frame.

Bootstrapped HTML applies insets inside the document and exposes --viewer-safe-area-top/right/bottom/left, window.artifactRenderer.safeArea, and the dvina-artifact-renderer:safe-area window event. Custom fixed/sticky layouts or nested scrollers can use these values themselves. Direct-URL HTML, disabled bootstrap, and script-disabled sandboxes instead inset the iframe inside its wrapper, because document-level styling is unavailable there.

Scroll progress

const controller = createViewer({
  container,
  viewerUrl,
  allowedOrigin,
  document,
  scrollProgressDistance: 48, // optional; CSS pixels, default 48
  onScroll(progress) {
    header.style.setProperty("--title-scroll", String(progress));
  },
});

progress is how far the document has scrolled from its top, from 0 to 1 over the first scrollProgressDistance pixels, rounded to hundredths. The viewer follows whichever element scrolls vertically (the Markdown page, the PDF viewport, a sheet's table, DOCX, PPTX, code, archives, EPUB); sideways scrolls are ignored. Bootstrapped HTML reports its own document's scroll through the bridge. It is sent only when it changes, at most once a frame, so scrolling past the distance sends nothing more, and it resets to 0 when a new document loads. The same value arrives in onEvent as viewer.scroll; it is not recorded in diagnostics.

Runtime Notes

  • browser-only package
  • exact allowedOrigin is required
  • private files should use short-lived bearer-token sessions
  • @dvina/artifact-renderer-core
  • @dvina/artifact-renderer-protocol

Documentation

See the repository documentation for:

  • React integration
  • Angular 20+ integration
  • NestJS backend integration
  • viewer deployment
  • release checklist

版本与发布记录

@dvina/artifact-renderer 共发布 59 个版本,首次发布于 2026/04/09;过去 12 个月发布了 59 个版本。

版本发布日期距今
0.0.59latest2026/11/13今天
0.0.582026/11/13今天
0.0.572026/11/112 天前
0.0.562026/11/094 天前
0.0.552026/11/094 天前
0.0.542026/11/094 天前

关于 @dvina/artifact-renderer 的常见问题

@dvina/artifact-renderer 是什么?

Framework-agnostic SDK for embedding the Dvina Artifact Renderer in an iframe.

如何安装 @dvina/artifact-renderer?

在项目目录运行 npm install @dvina/artifact-renderer,或使用 pnpm add / yarn add / bun add。

@dvina/artifact-renderer 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@dvina/artifact-renderer 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@dvina/artifact-renderer 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@dvina/artifact-renderer 可以商用吗?

@dvina/artifact-renderer 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@dvina/artifact-renderer 的下载量有多少?

根据 npm 官方下载统计,@dvina/artifact-renderer 在 2026/10/13 – 2026/11/11 这 30 天内被下载 4,877 次,日均约 163 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@dvina/artifact-renderer 还在维护吗?

最新版本 0.0.59 发布于 2026/11/13(今天);至今共发布 59 个版本,其中过去 12 个月发布了 59 个;首次发布于 2026/04/09。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。