@evilflowers/evilflowersviewer

中文文档
0.7.9发布于 2026/11/13TypeScriptES Module构建来源已验证近 30 天下载 2172

邪恶的花鸟Viewer

浏览器的焦点可扩展的 PDF 工作空间

阅读、搜索、注释、引用和分享文档而不离开页面.

中文使用文档
文档目录13 节
  1. 特征
  2. 智能浏览器
  3. 样式隔离( S)
  4. 无障碍
  5. 开始
  6. 智能浏览器
  7. 坐标和页
  8. 聊天 - options.chatPackage
  9. 区域 - options.regionPackage
  10. 大赦国际强调: options.agentAnnotationPackage
  11. 试试看
  12. 捐款
  13. 承认

邪恶的花鸟Viewer

浏览器的焦点可扩展的 PDF 工作空间

阅读、搜索、注释、引用和分享文档而不离开页面.

Latest release npm package License

EvilFlowersViewer displaying a PDF with annotations, search tools and page thumbnails

EvilFlowersViewer是一个基于pdf.js库的PDF查看器,它让用户查看并与PDF文档交互 直接在浏览器中。 它由一个大学团队开发,是可靠、高效和易于定制的.

特征

  • PDF 文档在浏览器中直接渲染
  • 缩小文档的大小
  • 通过页面缩略图视图进行页面导航
  • 文档中的文本搜索
  • 可选语义 / AI 搜索与关键词结果一起显示
  • 共享整个文档或与所选页面共享
  • BibTeX、BibLaTeX、RIS和文献目录中的引用导出
  • 打印整个文档或带有所选页面
  • 下载文档
  • 浅/ 暗主题( 荣耀主机提供的主题, 否则是读者保存的选择, 否则是系统偏好)
  • 全屏模式
  • 从已停靠的绘图铁路上编辑文档( 自由手、 形状、 突出显示器、 清除器、 撤销/ 重写) 页面旁边,所以它从来没有覆盖文档
  • 在页面角和缩略图上显示的页面书签
  • 方便键盘和屏幕阅读器(参见 无障碍(中文(简体) )

智能浏览器

每个都仅在主机通过它所需要的回调时出现(参见: 智能浏览器:

  • 解释 在可拖动弹出中选定段落、数字、表格或方程式,并手 解释到聊天
  • 阅读聊天 关于公开出版物,停靠在页面旁:流出答案 链接回到书中,推荐出版物作为卡片,以及附件(选定 可移动芯片
  • 聊天历史: 重新打开先前的对话; 对其他出版物的聊天只读
  • 图、表和方程徘徊概述目录从页面中提取的内容, 带有显示裁剪、标题、表格或 LaTeX 的卡片以及聊天和解释动作
  • 大赦国际的要点: 标出一个提示的助手的句子,从文字上划出,带有 每个亮点的注释徽章, 一个边栏列表 步过它们,并显示/隐藏每个 注释
  • 建议: 开放页或a的类似、先决条件和高级出版物 选择

样式隔离( S)

所有取景器样式都标注在单个下 .efv-viewer 根类和尾风 全球飞行前禁用,所以 导入此库后, 将不再重写主机 应用程序 (单位:千美元)*, (中文(简体) ), body,按钮、输入和滚动条不受影响。 有用吗 其它方式: 每个工具都作为 .efv-viewer .x (台风) important: '.efv-viewer'以自己的宿主盟誓 .text-primary 或者说 .bg-secondary 无法 复为观相. Inter字体是自行托管的(没有外部Google字体请求). 消费者只需导入样式表——不需要人工范围界定/包装:

import '@evilflowers/evilflowersviewer/dist/style.css';

无障碍

使用键盘和辅助技术来使用:

  • 键盘: 所有控件都可以通过 标签; 页面缩略图、工具 颜色表对 输入编号 :空间快捷键 : ←编号 :→ 页 次, + 键编号 :- 说吧 缩放, 法语 搜索, T级 目录, 一、导 言 资料, 页:1 份额, C级 引用, 英格兰 步骤后退(解释出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出 (中文(简体) ). 在任何文本字段中打入,包含主机,从不触发这些快捷键.
  • 屏幕阅读器: 每个仅图标按钮都有一个可访问的名称(本地化),切换 曝光 aria-pressed编号 :aria-expanded左边的铁路是 role="toolbar",对话框是 role="dialog" + 键 aria-modal 装入者通过 role="status"。光彩化的页布是 aria-hidden; 可选择的 pdf.js 文本 层中包含可读内容,当前搜索匹配在其上被标记 (单位:千美元)role="mark", (中文(简体) ), aria-current="true") (中文(简体) ).
  • 焦点运动( M): 一个可见 :focus-visible 为键盘用户显示环并全部 动画尊重 prefers-reduced-motion。 。 。 .
  • 观众的根带有一个 lang 属性匹配 options.lang 所以发音是 没错 所有A11y CSS都标注在下面 .efv-viewer 永远不要碰主页.

开始

所需经费: 节点 ≥ 22.13 (由pdfjs-dist 6要求).

要从"邪恶花朵"开始 跟着这些步骤:

  1. 安装 EvilFlowersViewer 包 :
npm install @evilflowers/evilflowersviewer
  1. 导入默认值 renderPDFViewer 函数和样式表:
import renderPDFViewer from '@evilflowers/evilflowersviewer';
import '@evilflowers/evilflowersviewer/dist/style.css';
  1. 用单个选项对象称呼它 。 它还原了Vue App 举个例子 可以在拆卸时卸载 :
const app = renderPDFViewer({
  rootId: '#my-viewer',      // CSS selector of the mount element
  data: uint8ArrayOfPdf,      // TypedArray of the PDF bytes
  options: { theme: 'light', lang: 'en' /* … */ },
  config: { download: true, share: true, print: true, edit: false },
});

// later, e.g. on route change:
app.unmount();

查看器选项和属性文档

投入说明
根编号您使用的组件标识 renderViewer 函数.
数据键入箭头( 如 . Uint8Array)与 PDF 字节. 也通过 data 或者说 url。 。 。 .
url 密码PDF 的 URL (中文(简体) ). pdf.js 获取它并显示进度栏;当服务器回答 HTTP 范围请求时(Accept-Ranges: bytes, (中文(简体) ), 206),第1页在文件全部下载之前制作. 没有 Range 支持, 文件将全部流出 .
http页眉可选 Record<string, string> 随同发送 url 请求,例如:. Authorization。 。 。 .
证书可选布尔。 以交叉原产地发送 cookie url 请求.
范围可选号码。 每个Range请求的字节(pdf.js默认为65536).
选项可选对象由主题,语言,引用Bib,homeFunction等组成.
选项。 主题"黑暗"或"光"。 强迫观众主题. 没有它,观看者使用读者最后选择的日/月切换(保存在 localStorage 作为 efv-theme),否则系统偏好,随之而来的是活体.
选项。lang"请"或"恩". 指定查看器的语言.
选项字符串或无效。 载有文件的引用(例如, @article{name, ...}) (中文(简体) ).
选项。家庭功能函数( 类型 : () => void)或无. 回向出家观相.
选项。关闭功能函数( 类型 : () => void)或无. 闭取相者.
选项函数( 类型 : “ (页数: 字符串)
共享功能。页面与所选页面字符串( 如“ 1, 3-6, 10 ”) 或无效( 表示没有页面) .
共享功能. expaireDateISO 字符串指定共享文档的寿命 .
函数 QQ 返回返回含有共享文档链接的字符串.
选项。打印功能函数( 类型 : “ (页数: 字符串)
选项.语义搜索功能函数( 类型 : (query: string) => Promise<ISemanticSearchResult[]>)或无. 可选语义/AI搜索. 提供时,搜索面板显示第二列AI结果({ page, text, score? })关键词相匹配;省略面板时仅保留关键词.
选项.edit 包管理编辑功能的可选对象,包含以下功能:
编辑 Package.saveGroupFunc函数( 类型 : (name: string) => Promise<{ response: { id: string } }>) (中文(简体) ). 保存新组并返回其ID.
编辑软件包。 getGroupsFunc函数( 类型 : () => Promise<{ id: string; name: string }[]>) (中文(简体) ). 收回所有可用的组.
编辑 Package.saveLayerFunc函数( 类型 : `( svg: string, groupId: string, page: number) @ 许诺 < ILayer
编辑 Package.update LayerFunc函数( 类型 : (id: string, svg: string, groupId: string, page: number) => Promise<void>) (中文(简体) ). 更新特定页面上组合中的现有层.
编辑软件包。 getLayerFunc函数( 类型 : “ (页: 数字, 组ID: 字符串) ) @% 承诺<ILayer>
编辑软件包。 getLayersFunc可选函数( 类型 : (groupId: string) => Promise<IPageLayer[]>, (中文(简体) ), IPageLayer =: { id, svg, page }) (中文(简体) ). 在一个请求中返回组的每层;查看器在进入编辑模式时会加载一次,结果中缺失的页面没有分层,页面翻转不再取取. 失败后,观众会回到 getLayerFunc。与目录: GET /api/v1/annotation-items?annotation_id=<groupId>&paginate=false。 。 。 .
选项.page 书签包可选 { getBookmarksFunc, addBookmarkFunc, removeBookmarkFunc } 持续页印。 没有它,书签仍然有效 但只能持续到观众.
选项函数( 类型 : (entry: ISuggestedEntry) => void) (中文(简体) ). 为被点击的出版物卡打开主机的详细视图(建议,聊天).
选项。bookmark 切换功能函数( 类型 : (entry: ISuggestedEntry) => Promise<{ isOnShelf, shelfRecordId? }>) (中文(简体) ). 从读者的书架上添加或去掉一张卡片的出版物.
选项函数( 类型 : (kind: SUGGESTION_KIND, context?: { selectedText?, page? }) => Promise<ISuggestedEntry[]>),启用建议和选择菜单的"类似".
选项。解释功能函数( 类型 : (text: string, context?: IExplainContext) => Promise<IExplainResult>)启用“解释”; context 携带 page 关于数字/表/方程式, regionId。 。 。 .
选项。聊天包可选 IChatPackage。启用读取聊天-见 智能浏览器。 。 。 .
选项可选 IRegionPackage。允许图/表/方程式徘徊.
选项. 代理说明包可选 IAgentAnnotationPackage。启用 AI 突出显示层及其侧边栏.
配置可选配置对象控制查看器特性 .
配置. 下載布尔. 启用或禁用下载特性.
相会. 份额布尔. 启用或禁用共享特性 .
配置. print布尔. 启用或禁用打印特性.
配置编辑布尔. 启用或禁用编辑功能.

智能浏览器

观众从不跟后端说话 每个智能特性都是主机回调 一个特性在召回未通过时完全隐藏 - 没有按钮,没有菜单项,没有 层。 所有类型都从包中导出.

坐标和页

  • 页面编号总是 读者 页面号码 (基于 1, 如查看器所示) 。 A 类 服务剪切或重排的复制件的主机在回答前转换它们.
  • 职位(IPageBox)是分数 0..1 页面宽度和高度 左上边 来源数字 : { x0, y0, x1, y1 }在任何缩放时都保持正确.

聊天 - options.chatPackage

chatPackage: {
  // Required. Stream the answer through the handlers; resolve when done.
  // chatId is the conversation to continue, or null to start one — return the id used.
  sendMessageFunc: async (message, contexts, { onChunk, onMessage, onEntries, onError }, { page, chatId }) => {
    // ...
    return { chatId };
  },
  resetFunc: () => {},                 // optional: forget the current conversation
  suggestions: ['Summarize this chapter'], // optional: prompt shortcuts in an empty chat
  getChatsFunc: async () => [...],     // optional, with getChatFunc: enables chat history
  getChatFunc: async (chatId) => [...],
  deleteChatFunc: async (chatId) => {}, // optional: delete buttons in history
}
  • 公开出版物始终是聊天的主题,并非作为上下文发送. contexts 带读者随附的: selection, (中文(简体) ), explain, (中文(简体) ), region 或者说 highlight (单位:千美元)IChatContext) (中文(简体) ).
  • 答文为平. [[page:12]] 财务报告和审定财务报表 [[region:<id>]] 转换为跳入 书. onEntries 将出版物显示为卡片(助理推荐工具).
  • 历史列表 IChatSummary 物项; aboutThisBook: false 聊天只开放读取.

区域 - options.regionPackage

regionPackage: {
  // Called once per page and cached.
  getRegionsFunc: async (page) => [
    { id, kind: 'figure' | 'table' | 'equation', page, bbox, caption, category, markdown, latex, imageUrl },
  ],
}

无 imageUrl 将卡片从页面中切入到区域中.

大赦国际强调: options.agentAnnotationPackage

agentAnnotationPackage: {
  getAnnotationsFunc: async () => [
    { id, title, prompt, summary, status: 'pending' | 'done' | 'failed', unresolvedCount,
      highlights: [{ id, seq, page, quads: [IPageBox, ...], text, note }] },
  ],
  requestAnnotationFunc: async (prompt) => annotation, // optional: "ask to highlight" box
  deleteHighlightFunc: async (annotationId, highlightId) => {}, // optional
  deleteAnnotationFunc: async (annotationId) => {},             // optional
}

每个亮点都是按读取顺序排列的一句话(seq),每个文本行为一四.

试试看

npm run dev 挂载样本应用程序( m)src/App.vue每一个功能被接通 嘲笑英寸 src/assets/examples/params/examples.ts。AI 突出显示模拟读取 PDF 样本的真实文本 线条,因此在实际文本上突出显示地块;区域框每页固定.

捐款

我们欢迎社区捐款,帮助让邪恶斗士Viewer变得更好。 捐款,请跟随 这些步骤:

  1. 叉子恶花Viewer 仓库
  2. 为您的更改创建新分支
  3. 做你的改变,并用一个明确的承诺信息
  4. 将您的更改推进到您的防御库
  5. 创建拉动请求, 将您的更改合并到主 EvilFlowersViewer 主库

承认

这一开放源码项目由学生和博士生负责 信息学和信息技术学院 斯洛伐克大学 技术。 该软件供大学使用,配合其教育和研究活动。 我们 感谢教职员工对我们工作的支持和他们对开放源码社区的贡献.

版本与发布记录

@evilflowers/evilflowersviewer 共发布 72 个版本,首次发布于 2023/03/17;过去 12 个月发布了 18 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.7.9latest2026/11/131 天前
0.7.72026/11/095 天前
0.7.62026/11/059 天前
0.7.52026/11/059 天前
0.7.42026/11/059 天前
0.7.32026/10/3015 天前

关于 @evilflowers/evilflowersviewer 的常见问题

@evilflowers/evilflowersviewer 是什么?

邪恶的花鸟Viewer 浏览器的焦点可扩展的 PDF 工作空间 阅读、搜索、注释、引用和分享文档而不离开页面.

如何安装 @evilflowers/evilflowersviewer?

在项目目录运行 npm install @evilflowers/evilflowersviewer,或使用 pnpm add / yarn add / bun add。

@evilflowers/evilflowersviewer 支持 TypeScript 吗?

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

@evilflowers/evilflowersviewer 支持 ESM 还是 CommonJS?

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

@evilflowers/evilflowersviewer 需要什么版本的 Node.js?

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

@evilflowers/evilflowersviewer 可以商用吗?

@evilflowers/evilflowersviewer 使用 未声明 许可。package.json 没有声明许可证。没有许可证的代码默认保留全部权利,商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括,不构成法律意见,请以许可原文为准。

@evilflowers/evilflowersviewer 的下载量有多少?

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

@evilflowers/evilflowersviewer 还在维护吗?

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