简介:这是一款面向科研人员与文献管理用户的Zotero插件,基于TypeScript开发,用于将scite的Smart Citation数据接入个人文献库,帮助读者在阅读论文时快速判断引用属于支持、提及还是反驳,从而更高效地评估文献可信度。压缩包共31个文件,约1.24MB,包含7个ts源码文件、8个png界面截图、4个json配置、2个xul界面定义,以及manifest、properties、css、md说明等,覆盖插件核心逻辑、界面布局与本地化资源,目录结构清晰,便于二次开发与调试。已有1163人学习下载。安装后每篇论文条目会显示Supporting、Mentioning、Contrasting三类引用统计,并可一键跳转站点报告页,适合需要文献综述、引用核查或插件开发参考的研究者使用。
1. 装 scite-zotero-plugin 之前,先把 TypeScript 工具链对齐
上周帮一位做文献管理的朋友处理一个 Zotero 插件,项目叫 scite-zotero-plugin,仓库拉下来npm install跑完,npm run build直接报了一屏类型错误,tsc版本和@types/zotero对不上,折腾到半夜。这类插件本身不复杂,难的是 TypeScript 工具链和 Zotero 宿主版本之间的对齐——装错一个 Node 小版本,或者tsconfig里target写高了,编译产物在 Zotero 里就是加载不出来。这篇笔记按我实际装一遍的顺序写:先列环境、再装依赖、配构建、最后验证插件在 Zotero 里能正常注册。适合正在给 Zotero 写插件、或者想跑通 scite-zotero-plugin 这套 TypeScript 工程的开发者,新手照着能走通,熟手能对照看版本取舍。
2. 环境准备:Node、Zotero 与 TypeScript 版本怎么选
2.1 三个必须锁定的版本
scite-zotero-plugin 是 TypeScript 写的 Zotero 插件,构建链依赖 Node 和 npm,运行宿主是 Zotero 客户端。这三个东西的版本关系必须先理清,否则后面全是玄学报错。
| 组件 | 推荐版本 | 说明 |
|---|---|---|
| Node.js | 18.x LTS 或 20.x LTS | 低于 16 的 Node 跑不动现代构建工具链 |
| npm | 随 Node 自带,9.x 以上 | 锁文件格式要和团队一致 |
| TypeScript | 5.x(以仓库 package.json 为准) | 不要全局装,用项目内版本 |
| Zotero | 7.x | 插件 manifest 的strict_min_version要对上 |
我一般不会去追 Node 的最新奇数版,LTS 就够。TypeScript 这块有个血泪经验:很多人习惯npm install -g typescript,然后tsc用的是全局版本,和项目devDependencies里的版本不一致,编译行为就会飘。正确做法是永远走npx tsc或者npm run build,让项目自己决定用哪个编译器。
Zotero 版本这块要注意,Zotero 7 和 6 的插件 API 差异不小,manifest.json里的applications.zotero.strict_min_version写错,插件在客户端里会直接不显示。装之前先确认你本机 Zotero 是 7.x,再去看仓库 README 或package.json里声明的兼容范围。
2.2 拉代码与依赖安装
环境确认完,拉代码、装依赖。这一步看着简单,坑主要在 npm 源和锁文件上。
# 克隆仓库(地址以实际仓库为准) git clone <scite-zotero-plugin 仓库地址> cd scite-zotero-plugin # 确认 Node 版本,建议 18 或 20 node -v npm -v # 用锁文件安装,保证依赖树和作者一致 npm cinpm ci和npm install的区别值得说一句:ci严格按package-lock.json装,不会改动锁文件,适合复现环境;install可能会升级次要版本并重写锁文件。装插件这种要复现的场景,我一般强制用ci。如果仓库没提交锁文件,那就只能npm install,装完把锁文件提交上去,别让它漂。
如果npm ci卡在某个包下载上,先看是不是默认源慢,换一个可用的镜像源再试,但换完记得把package-lock.json里的resolved字段一致性检查一下,避免锁文件里混了不同源的地址导致后续安装报错。
依赖装完,目录里会出现node_modules,先别急着构建,下一步先把 TypeScript 配置和构建脚本看明白。
2.3 检查 tsconfig 与构建脚本
TypeScript 项目的构建行为几乎全由tsconfig.json决定。scite-zotero-plugin 这类插件通常会把源码编到build/或dist/目录,再打包成.xpi。打开tsconfig.json,重点看这几个字段:
{ "compilerOptions": { "target": "ES2020", "module": "ESNext", "moduleResolution": "bundler", "strict": true, "outDir": "build", "rootDir": "src", "types": ["zotero"] }, "include": ["src/**/*.ts"] }target决定输出语法级别,Zotero 7 基于较新的运行环境,ES2020 一般没问题,写太高(比如 ES2022)在旧宿主里可能不认。moduleResolution用bundler还是node要看构建工具,用打包器就bundler,纯tsc输出就node。types里声明zotero是为了让编辑器认识Zotero全局对象,这个类型包一般来自@types/zotero或仓库自带的类型声明,装依赖时应该已经进来了。
再看package.json的scripts:
{ "scripts": { "build": "tsc && node scripts/build.js", "watch": "tsc --watch", "lint": "eslint src --ext .ts" } }build通常是先tsc编译再跑打包脚本生成.xpi。如果tsc报类型错误,先别改代码,先确认@types/zotero的版本和 Zotero 客户端版本是否匹配——类型包太新或太旧都会报一堆“属性不存在”。这一步确认完,再进下一章实际构建。
3. 构建与打包:从 tsc 到可安装的 xpi
3.1 先跑通 tsc 编译
构建第一步是纯 TypeScript 编译,把src/下的.ts变成build/下的.js。直接跑:
# 只做类型检查和编译,不打包 npx tsc --noEmit--noEmit只检查类型不输出文件,适合先排类型错误。如果这一步就报错,问题基本集中在三处:类型包版本不匹配、tsconfig的include没覆盖到某些文件、或者代码里用了宿主不支持的 API。逐条看报错信息,别急着// @ts-ignore,那玩意儿攒多了后面全是黑匣子。
类型检查过了,再正式编译:
npm run build这条命令会先tsc输出到build/,再执行打包脚本。如果build脚本里带了rm -rf build之类的清理逻辑,注意别把源码目录误删——我见过outDir和rootDir配反导致编译产物覆盖源码的翻车现场,改之前先git status看一眼。
3.2 打包成 Zotero 能识别的 xpi
Zotero 插件本质是一个 zip 包,扩展名改成.xpi,里面必须有manifest.json和编译后的 JS。打包脚本一般做两件事:把build/产物和manifest.json、locale/、chrome/等资源拷到一个临时目录,再 zip 成.xpi。
# 手动打包的等价做法,便于理解脚本在干什么 mkdir -p dist cp -r build/* dist/ cp manifest.json dist/ cd dist && zip -r ../scite-zotero-plugin.xpi . && cd ..manifest.json是插件的身份证,重点字段:
{ "manifest_version": 2, "name": "scite-zotero-plugin", "version": "0.1.0", "applications": { "zotero": { "id": "scite-zotero-plugin@example.com", "strict_min_version": "7.0", "strict_max_version": "7.*" } } }id必须唯一且稳定,升级插件时靠它识别;strict_min_version和strict_max_version决定在哪些 Zotero 版本里能装。这两个版本号写错,插件在客户端里要么不显示,要么装了不生效。打包完检查一下.xpi里是不是真的包含manifest.json在根目录,层级错了 Zotero 直接拒绝安装。
3.3 开发模式下的热加载
每次改代码都手动打包再装,效率太低。Zotero 插件开发一般用两种方式提速:一是tsc --watch持续编译,二是用 Zotero 的调试模式加载未打包的插件目录。
# 终端一:持续编译 npx tsc --watch然后在 Zotero 里打开工具 → 开发者 → 运行脚本或通过调试桥加载build/目录。具体入口随 Zotero 版本略有差异,核心思路是让客户端直接读编译产物目录,改完代码tsc自动输出,重启插件即可看到效果。这一步配好,后面调 UI 和 API 会省大量时间。
4. 配置与调试:让插件在 Zotero 里真正跑起来
4.1 安装 xpi 与确认注册
打包出的.xpi安装方式:Zotero 里工具 → 插件 → 齿轮 → 从文件安装插件,选中.xpi。装完在插件列表里应该能看到 scite-zotero-plugin 的名字和版本。
如果列表里没有,按这个顺序排查:先看.xpi根目录有没有manifest.json;再看manifest.json的applications.zotero.id是否合法;最后看strict_min_version是否高于你本机 Zotero 版本。这三条中任何一条不满足,插件都会被静默忽略,不报错,特别容易让人怀疑人生。
装好后打开 Zotero 的错误控制台(工具 → 开发者 → 错误控制台),看有没有插件加载时的异常。TypeScript 编译产物如果target写太高,宿主解析不了,这里会直接抛语法错误。
4.2 调试 TypeScript 源码
调试插件最有效的方式是看 Zotero 的调试输出。开发阶段建议在代码里加日志,通过Zotero.debug()输出到错误控制台:
// 在插件初始化入口打日志,确认生命周期走到了哪一步 function onStartup() { Zotero.debug("[scite-zotero-plugin] startup begin"); try { // 初始化逻辑 Zotero.debug("[scite-zotero-plugin] startup done"); } catch (e) { Zotero.debug(`[scite-zotero-plugin] startup failed: ${e}`); } }Zotero.debug的输出会进错误控制台,比console.log更贴合宿主环境。try/catch包一层是为了让初始化异常有明确落点,不然插件静默失败,你连从哪查都不知道。
如果要用断点调试,Zotero 支持远程调试协议,在启动参数里开调试端口,然后用浏览器开发者工具连上去。这一步配置稍繁琐,日常改逻辑用日志基本够,遇到复杂状态再上断点。
4.3 常见配置项取舍
插件配置一般落在 Zotero 的偏好设置里,通过Zotero.Prefs读写。几个容易写错的点:
- 偏好键名要带插件前缀,比如
extensions.scite-zotero-plugin.enabled,不带前缀容易和别的插件冲突。 - 默认值要在
prefs.js或初始化代码里显式设置,别依赖“读不到就用 undefined”。 - 布尔值和字符串别混,
Zotero.Prefs.get返回类型和存入类型不一致时,判断逻辑会静默走错分支。
// 读取偏好时给默认值,避免 undefined 参与判断 const enabled = Zotero.Prefs.get( "extensions.scite-zotero-plugin.enabled", true ) as boolean;第二个参数是默认值,类型断言是为了让 TypeScript 知道返回类型。这种写法比先get再判空清晰,也少一层嵌套。
5. 避坑与排查:五条装插件时真踩过的坑
5.1 现象:npm ci 报锁文件不同步
原因:package.json和package-lock.json不一致,通常是有人改了依赖没提交锁文件。解决:本地先npm install生成新锁文件,确认依赖树合理后提交,再让其他人npm ci。别直接删锁文件了事,那等于放弃版本锁定。
5.2 现象:tsc 报大量 “Property does not exist on type Zotero”
原因:@types/zotero版本和 Zotero 客户端版本不匹配,类型包太旧缺新 API,太新则引用了宿主还没有的接口。解决:按 Zotero 主版本选类型包版本,装完npx tsc --noEmit复验。实在对不上,就在项目里维护一份精简的类型声明,只声明用到的 API。
5.3 现象:xpi 装上了但插件列表不显示
原因:manifest.json的strict_min_version高于本机 Zotero 版本,或id格式不合法。解决:把strict_min_version调到不高于本机版本,id用名称@域名形式。改完重新打包,注意别装了两个同 id 的旧版本。
5.4 现象:插件加载后功能不生效,控制台无报错
原因:初始化入口没被调用,或者偏好键名写错导致逻辑走了默认分支。解决:在onStartup里加Zotero.debug日志,确认生命周期;再逐项核对偏好键名和默认值。这类静默失败最耗时间,日志要打在最前面。
5.5 现象:改完代码重新打包,行为没变化
原因:Zotero 缓存了旧版插件,或者打包时build/没清理导致新旧文件混在一起。解决:打包前清空输出目录,装新包前先在插件列表里移除旧版并重启 Zotero。养成“清目录 → 重打包 → 卸旧装新”的顺序,能省掉大量“改了没反应”的自我怀疑。
6. 装完怎么验证:三步确认插件真的跑通
装完不等于跑通,我一般用三步验证,缺一步都不算完。
第一步,确认插件注册成功。打开 Zotero 插件列表,scite-zotero-plugin 在列且版本号与manifest.json一致;同时错误控制台里没有加载异常。这一步排除的是“装了但没生效”的情况。
第二步,确认初始化逻辑执行。在错误控制台过滤插件前缀日志,应该能看到startup begin和startup done成对出现。如果只有 begin 没有 done,说明初始化中途抛异常,回去看 catch 里打的错误信息。
第三步,确认核心功能可用。按插件实际功能触发一次操作,比如打开对应面板或执行一次命令,观察是否有预期输出、偏好设置是否被正确读写。可以用一段临时脚本验证偏好读写:
// 验证偏好读写是否闭环 Zotero.Prefs.set("extensions.scite-zotero-plugin.enabled", true); const v = Zotero.Prefs.get("extensions.scite-zotero-plugin.enabled"); Zotero.debug(`[verify] enabled = ${v}`); // 期望输出 true三步都过,这套环境才算真正装完。从那以后我每次装 Zotero 插件,都强制走一遍“注册 → 初始化日志 → 功能触发”的验证链,不再靠“看起来装上了”下结论。版本对齐和日志落点是这类 TypeScript 插件最省后悔药的两件事,希望帮到你。
本文还有配套的精品资源,点击获取