Skip to content

前言 ​

本节内容

本节将介绍 JavaScript 脚本的编写的前置知识,更多内容请看 API 列表 和 常见用法示例,请善用侧边栏和搜索,按需阅读文档。

我们假定你熟悉 JavaScript / TypeScript,编程语言的教学超出了本文档的目的,如果你还不熟悉它们,可以从互联网上寻找到很多优秀的教程。如:

注意:你只需要学习 JavaScript 语言本身,不包括 WebAPI。

快速开始 ​

JavaScript(JS)虽然作为 Web 页面中的脚本语言被人所熟知,但是它也被用到了很多 非浏览器环境 中,例如 Node.js、Apache CouchDB、Adobe Acrobat 等。

—— 来自 MDN 文档

海豹的 JS 插件就是运行在一个非浏览器环境中—— goja 作为 JS 脚本引擎所提供的环境,该环境目前支持了 ES6 基本上全部的特性,包括 async/await、promise 和 generator 等异步编程友好的特性。

除了 JS 语言规范所提供的 内置对象,海豹额外在环境中提供了如下全局对象:

  • seal 用于自定义扩展、增加指令、管理黑白名单……几乎所有与海豹本体有关的 API 都挂载在这个内置对象上。
  • console 专门与海豹的日志模块进行交互。
  • setTimeout/setInterval 等与事件循环相关的函数。
  • fetch 用于网络请求。
  • atob/btoa 用于 base64 编解码。

警告

需要注意引擎的整型为 32 位,请小心溢出问题。

现在,让我们从最简单的扩展开始,这个扩展只会在日志中打印一条 Hello World!。

新建一个 JS 文件,写入如下内容,然后通过海豹的 WebUI 上传并重载 JS 环境(或是直接复制到海豹 WebUI 的调试控制台中运行)。

javascript
// ==UserScript==
// @name         示例:如何开始
// @author       木落
// @version      1.0.0
// @description  这是一个演示脚本,并没有任何实际作用。
// @timestamp    1671368035
// 2022-12-18
// @license      Apache-2
// @homepageURL  https://github.com/sealdice/javascript
// ==/UserScript==

console.log('Hello World!');

你应当能在控制台中观察到一条 Hello World 的日志。

提示:打印日志

console 打印出来的东西不仅会在控制台中出现,在日志中也会显示。

涉及网络请求或延迟执行的内容,有时候不会在控制台调试面板上显示出来,而在日志中能看到。

插件元数据 ​

每个 JS 扩展需要在开头以固定格式注释的形式留下信息,以便使用和分享,这些信息通常被称为「插件元数据」:

javascript
// ==UserScript==
// @name         脚本的名字
// @author       木落
// @version      1.0.0
// @description  这是一个演示脚本,并没有任何实际作用。
// @timestamp    1672066028
// @license      Apache-2
// @homepageURL  https://github.com/sealdice/javascript
// @depends      SzzRain:demo:1.0.0
// @sealVersion  1.4.5
// ==/UserScript==
属性含义
@name必填,JS 扩展的名称,会展示在插件列表页面
@author必填,作者名
@version必填,版本号,可以自己定义,但建议遵循 语义版本控制(Semantic Versioning)
@description可选,对扩展的功能的描述
@timestamp可选,最后更新时间,以秒为单位的 unix 时间戳,新版本支持了直接使用时间字符串,如 2023-10-30。
@license可选,开源协议,示例中的 Apache-2 是一个比较自由的协议,允许任意使用和分发(包括商用),当然你也可以使用其它协议(MIT GPL 等)
@homepageURL可选,你的扩展的主页链接,有 GitHub 仓库可以填仓库链接,没有则可以填海豹官方插件仓库
@depends v1.4.4可选,从 v1.4.4 加入,指定你的扩展依赖的其他扩展,可以不含此行或含有多行。详见 依赖其他扩展
@sealVersion v1.4.5可选,从 v1.4.5 加入,指定你的扩展的目标海豹版本。详见 目标海豹版本

插件编写 ​

单 JS 文件编写插件 ​

我们更推荐使用 TypeScript 来编写插件,编译到 ES6 后使用即可。不过先从 JavaScript 开始也是没有任何问题的。

编写插件时,可以下载海豹提供的 seal.d.ts 文件,将其保存在和你要编写的 JS 文件同级的目录下。

seal.d.ts 支持了在使用 vscode 等工具编写时,对海豹提供的 API 的代码补全。

海豹 API 代码补全

提示

seal.d.ts 文件随时可能会有更新,如果你需要的 API 没有提示,可以检查一下是否是最新版本。

插件的工程化编写 ​

如果你打算使用 TypeScript,或者需要编写大型插件,希望更加工程化以方便维护,见 插件的工程化编写。

插件的工程化编写

插件的工程化编写是 为有一定经验的开发者准备的。相关文档默认你了解如何使用前端工具链,你应当具备诸如命令行、Node.js、npm/pnpm 等工具的使用知识。

如果你对上面的内容感到陌生,请自行了解或放弃使用,手册不会介绍相关内容。

使用单 JS 文件编写插件与使用模板工程编写本质上是没有区别的,并不会出现某些功能无法使用的差异。

扩展依赖 ​

依赖其他扩展 v1.4.4 ​

有些时候,你的扩展依赖于另一个扩展提供的功能,希望在缺失对应扩展时不进行这个插件的加载。

例如,「SzzRain:每日新闻」依赖于「SzzRain:定时任务」,我们希望在骰主仅安装了「SzzRain:每日新闻」时,提示需要安装其依赖的「SzzRain:定时任务」扩展。

从 v1.4.4 开始,你可以在 插件元数据 中通过 @depends 来指定扩展依赖的其他扩展。

指定依赖的格式 ​

指定依赖的格式为 作者:插件名[:SemVer版本约束,可选],其中 : 是分隔符,注意必须是半角符号。

例如,使用 @depends SzzRain:定时任务,这意味着该插件需要同时安装一个名为 定时任务,作者名为 SzzRain 的插件才可正常工作。

javascript
// ==UserScript==
// @name         每日新闻
// @author       SzzRain
// @version      2.0.0
// ...
// @depends      SzzRain:定时任务:>=2.0.0

在上面的示例中,可以看见「SzzRain:每日新闻」通过 @depends 指明了其依赖 SzzRain:定时任务:>=2.0.0。

版本限制是可选的,比如上面示例中的 >=2.0.0,这表示 SzzRain:每日新闻 依赖于 SzzRain:定时任务,且后者的版本必须大于等于 2.0.0。这在你需要依赖高版本插件的情况下很有用。

插件名、作者、版本号

指定依赖插件涉及到对应的插件名、作者名和版本号,其为插件元数据中的 @name、@author 和 @version。

有更复杂的指定依赖版本需求?

除了上面提到的 >=2.0.0 之外,你还可以参阅海豹所使用的 go-semver 库的文档,来进行更复杂的限制。

比如 1.1.4-5.1.4 意味着指定的依赖版本需要在 1.1.4 和 5.1.4 之间。

但是,目标依赖的版本号需要符合 SemVer 才能更好的支持你进行版本限制。

依赖多个扩展 ​

依赖可以是多个,每一行指定一个 @depends,这意味着这个插件需要同时满足所有的依赖才能工作。

例如我们给上面的「SzzRain:每日新闻」增加一个新的依赖:

javascript
// ==UserScript==
// @name         每日新闻
// @author       SzzRain
// @version      2.0.0
// ...
// @depends      SzzRain:定时任务:>=2.0.0
// @depends      sealdice:强制依赖

此时,这个插件需要同时安装 SzzRain:定时任务(且版本大于等于 2.0.0)和 sealdice:强制依赖 这两个插件时,才能正常加载。

目标海豹版本 v1.4.5 ​

新版本的海豹有时会增加更多插件可以调用的 API,但会出现使用旧版本海豹的骰主,去尝试加载使用了新 API 的插件而出错的情况。

为了让插件作者无需反复说明,也更好地提示使用插件的骰主,从 v1.4.5 开始,你可以在 插件元数据 中通过 @sealVersion 来指定插件的目标海豹版本。

例如,当插件使用了新版本 LatestVersion 新增的 API,应将目标海豹版本填写为该 API 实际引入的核心版本。不满足兼容条件时,核心会向骰主提示版本不兼容并拒绝加载。

文档或示例尚未填入正式版本时会使用 vA.B.C 占位;写入插件元数据时应去掉 v 并替换为实际版本:

javascript
// A.B.C 应替换为所用 API 实际引入的核心版本。
// @sealVersion  A.B.C

兼容的海豹版本

@sealVersion 是 JS API 的核心版本兼容声明,当前没有另一个独立的 @apiVersion 字段。使用哪个版本新增的 API,就至少声明哪个核心版本;LatestVersion 新增接口应声明对应接口引入时的实际核心版本。

海豹会尝试在兼容的情况下尽可能地加载插件,这是由海豹核心自动处理的。

该字段支持 SemVer 约束。例如 @sealVersion >=1.4.6 会严格检查当前核心版本;不带比较符号的 @sealVersion 1.4.6 会使用核心维护的 JS API 兼容版本集合判断。除非插件确实要求所有后续核心版本,否则推荐填写引入所用 API 的最低目标版本。

一些有帮助的资源 ​

VS Code 可以安装 SealDice Snippets 插件,提供了一些常见代码片段,帮助快速生成模板代码。

其他问题 ​

我不会 JavaScript,海豹支持其他编程语言编写插件吗? ​

这个问题分为两个部分,如果你所说的其他编程语言为 Python、Lua 等与 JavaScript 无关的编程语言,那么目前是无法使用这些语言编写海豹插件的。如果你有一些其它骰系的插件(比如一些 Lua 插件),你只能通过按原逻辑重写为海豹 JavaScript 插件的方式来在海豹中使用。

但是有些编程语言是可以编译为 JavaScript 的,典型的像 TypeScript、CoffeeScript。这些语言在编写时使用它们自己,最后只要编译成 JavaScript 就可以在海豹中使用了。