Caliber.js Framework Library

一个旨在帮助开发者快速构建功能强大、可维护的现代油猴脚本的框架。它提供模块化架构、自动化的UI设置面板、响应式生命周期管理、高性能DOM调度器与网络请求拦截器等核心功能,让您专注于实现创意,而非繁琐的底层细节。

이 스크립트는 직접 설치하는 용도가 아닙니다. 다른 스크립트에서 메타 지시문 // @require https://update.greasyfork.org/scripts/545792/1908492/Caliberjs%20Framework%20Library.js을(를) 사용하여 포함하는 라이브러리입니다.

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

작성자
You Boy
버전
1.2.0
생성일
2025-08-14
갱신일
2026-08-21
크기
151KB
라이선스
MIT

Caliber.js 框架开发者手册 (v1.2.0)

Caliber.js 是一个专为现代油猴(Userscript)脚本打造的高性能、模块化、响应式开发框架。它将复杂的底层细节(异步生命周期流转、并发排他队列、DOM分帧调度、双 Hub 管道式网络请求拦截、配置自愈、防不法篡改与防删防护、CSP/Trusted-Types 兼容、SPA路由感知等)进行了高度工程化封装,让开发者只需专注于业务逻辑实现。


目录

  1. 快速上手
  2. 应用初始化 (createApp)
  3. 模块化开发 (Module Base Class)
  4. 核心 API 服务详解
  5. 声明式 UI 守护与自愈 (UI Guardian)
  6. 路由匹配与 SPA 页面感知
  7. 质量防护与内存泄漏审计 (Module Auditor)
  8. 内核生命周期与优雅注销 (Kernel Destruction)
  9. 完整开发示例

1. 快速上手

在油猴脚本头部引入 Caliber.js(或通过 @require 引入),定义继承自 Caliber.Module 的模块类并调用 Caliber.createApp 启动:

// ==UserScript==
// @name         My Advanced Script
// @namespace    https://example.com/
// @version      1.0.0
// @match        https://example.com/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @grant        unsafeWindow
// @require      https://path/to/Caliber.js
// ==/UserScript==

// 1. 定义功能模块
class MyFeatureModule extends Caliber.Module {
  id = "myFeature";
  name = "核心增强功能";
  description = "自动修改特定节点样式并显示状态。";

  defaultConfig = {
    enabled: true,
    highlightColor: {
      type: "color",
      value: "#ff0000",
      label: "高亮颜色",
      description: "设置被修饰元素的背景颜色"
    },
    customRules: {
      type: "textarea",
      value: "rule1\nrule2",
      label: "自定义匹配规则",
      inputProps: { rows: 3, placeholder: "每行一条规则..." }
    }
  };

  async onEnable(context) {
    this._logger.log("模块已开启,当前 URL 参数:", context.query);
  }

  async onDisable() {
    this._logger.log("模块已关闭,异步资源清理完成。");
  }
}

// 2. 启动框架内核
(async () => {
  await Caliber.createApp({
    appName: "我的增强脚本",
    isDebug: true, // 开启调试模式与内存泄露 Auditor 监控
    modules: [MyFeatureModule],
    services: {
      storage: {
        get: async () => JSON.parse((await GM_getValue("app_config", "{}"))),
        set: async (val) => GM_setValue("app_config", JSON.stringify(val))
      },
      command: {
        register: (name, cb) => GM_registerMenuCommand(name, cb)
      }
    },
    settingsPanel: {
      bottom: 50,
      right: 0 // 贴在屏幕右边缘
    }
  });
})();

2. 应用初始化 (createApp)

Caliber.createApp(options) 是脚本唯一的应用入口,内置了防重复启动预检(Preflight)与沙箱环境自适应机制。

完整启动参数表

参数名 类型 必填 默认值 说明
appName string - 应用唯一名称,用于生成命名空间、日志前缀、设置面板标题及菜单项
modules Array<typeof Module> - 注册的模块类数组(传类本身,而非实例)
services object - 宿主环境适配器服务集合
services.storage StorageAdapter localStorage 包含 get(): Promise<object>set(val): Promise<void>
services.command CommandAdapter 空实现 包含 register(name, callback): void
services.hostWindow Window 自动识别 默认自动识别 unsafeWindow,无油猴环境回退至标准 window
services.hostDocument Document document 宿主 document 对象
services.style StyleAdapter 自动安全注入 样式注入适配器,提供 add(css, id)remove(id)
isDebug boolean false 是否开启 Debug 模式(打印详细日志、激活 Auditor 泄漏审计)
settingsPanelEnabled boolean true 首次启动时设置面板触发按钮是否默认开启
settingsPanel object {} 设置面板外观及触发按钮定位配置,详见下方
framework.domProcessorBatchSize number 20 DOM 调度器每一渲染帧(rAF)允许处理的最大节点数

悬浮按钮与面板位置定制

settingsPanel: {
  enabled: true,  // 是否启用按钮
  bottom: 80,     // 距离屏幕底部像素值 (px)
  right: 0        // 距离屏幕右侧像素值 (px)
}

💡 智能动态贴边圆角: 框架会根据 rightbottom 坐标自动计算最佳形态:

  • right: 0, bottom: 50 ➔ 右侧无圆角、平贴边缘(经典胶囊半圆);
  • right: 20, bottom: 0 ➔ 底部无圆角、平贴下沿;
  • right: 0, bottom: 0 ➔ 右侧与底部皆为平角,完美卡在屏幕右下死角;
  • right: 25, bottom: 25 ➔ 自动转化为四角圆润的独立悬浮按钮。

3. 模块化开发 (Module Base Class)

所有功能模块必须继承 Caliber.Module 类。

模块基础属性

class DemoModule extends Caliber.Module {
  id = "demo-module";            // 唯一标识符 (必填,不可使用 "base-module")
  name = "示范模块";             // UI 中显示的模块名称 (必填)
  description = "这是一个示范模块"; // UI 中显示的描述文本
  match = "/user/:id";           // (可选) 页面匹配规则,不匹配时不激活
  uiGuard = null;                // (可选) 声明式 UI 守护配置,详见第 5 节
}

声明式配置项 (defaultConfig Schema)

defaultConfig 支持简单的基本类型值,也支持丰富的 Schema 配置(框架根据 Schema 自动生成 Shadow DOM 设置面板)。

控件类型与配置语法

defaultConfig = {
  enabled: true, // 框架保留字段:控制模块启停(必须包含或默认赋予)

  // 1. 文本输入框 (string)
  apiKey: {
    type: "string",
    value: "default_token",
    label: "API 密钥",
    description: "用户访问鉴权 Token",
    inputProps: { placeholder: "请输入密钥..." }
  },

  // 2. 多行文本域 (textarea) - v1.2.0 新增
  blockKeywords: {
    type: "textarea",
    value: "关键词A\n关键词B",
    label: "屏蔽列表",
    description: "每行输入一个过滤关键词",
    inputProps: { rows: 4, placeholder: "一行一条..." },
    divider: "bottom" // 底部添加分割线
  },

  // 3. 数字输入框 (number)
  limitCount: {
    type: "number",
    value: 20,
    label: "单页显示数量",
    inputProps: { min: 1, max: 100, step: 5 }
  },

  // 4. 开关切换器 (boolean)
  autoRefresh: {
    type: "boolean",
    value: false,
    label: "自动刷新开关"
  },

  // 5. 下拉选择器 (select)
  displayMode: {
    type: "select",
    value: "compact",
    label: "排版布局",
    options: [
      { label: "紧凑视图", value: "compact" },
      { label: "松散视图", value: "comfortable" }
    ]
  },

  // 6. 颜色选择器 (color)
  themeColor: {
    type: "color",
    value: "#007aff",
    label: "高亮主题色"
  }
};

高级排版属性(所有控件通用):

  • indentLevel (1 | 2 | 3): 树状层级缩进,自动生成等宽代码字体 └─ 连接线。
  • divider ("top" | "bottom" | "both"): 在配置项周围添加视觉分割线。
  • inputProps (object): 标签属性透传,可设置 min, max, step, placeholder, rows, maxLength 等原生 HTML 属性。

全流程异步生命周期 (Async Lifecycle)

Caliber v1.2.0 全面支持 Promise 异步返回。所有生命周期流转均受内部 排他异步串行队列 (#runExclusive) 保护,杜绝并发竞态。

生命周期方法 支持异步 触发时机 传入参数
onEnable(context) 模块被启用(且页面规则匹配通过)时调用 context: { params: {}, query: {} }
onDisable() 模块被禁用、或页面切换至不匹配页面时调用。
必须在此清理所有事件监听器和定时器
onConfigChange(key, newVal, oldVal) 用户在设置面板中修改该模块配置时实时触发 key, newVal, oldVal
onNavigate(context) SPA 页面专用。模块处于激活状态且页面发生前端路由导航时触发 context: { params: {}, query: {} }
onRender(targetElement) UI Guardian 专用。DOM 修复注入 UI 时触发 targetElement: 目标挂载父容器
onCleanup() UI Guardian 专用。组件被卸载时触发

模块快捷服务句柄

在模块内部通过 this.xxx 可直接调用核心能力:

this._logger      // 日志服务实例 (带有模块 ID 样式化彩色前缀)
this._eventBus     // 全局事件总线 (on, off, emit)
this._hostWindow   // 宿主 window 对象 (unsafeWindow)
this._hostDocument // 宿主 document 对象
this._scheduler    // 高性能 DOM 分帧批量处理调度器
this._interceptor  // 宿主网络请求拦截器
this._sanitizer    // DOM 净化与安全注入服务
this._executor     // 页面作用域代码执行器 (带10秒熔断保护)
this._utils        // 实用工具集合 (如 checkMatch 路由分词)
this._module       // 模块自控门面 (如请求热重启 this._module.requestReset())

4. 核心 API 服务详解

1. DOM 批量调度器 (_scheduler)

比传统 MutationObserver 性能更优。采用分帧批量调度(默认每帧处理 20 个节点),具备零订阅自动休眠机制

注册任务 (register)

const taskId = this._scheduler.register(selector, callback, options);
  • selector (string): 目标 CSS 选择器。
  • callback ((node: HTMLElement) => void): 匹配节点时的回调。
  • options (DomProcessorOptions, 可选):
    • add: boolean (默认 true) 是否监听节点新增。
    • attributes: boolean (默认 false) 是否监听属性变更。
    • attributeFilter: string[] 指定关注的属性名列表(如 ["data-status", "class"])。
    • root: HTMLElement | string 限制只监听特定父容器内部。
    • processExisting: boolean (默认 false) 是否在注册时立即处理 DOM 中已存在的匹配节点

注销任务 (unregister)

this._scheduler.unregister(taskId);

2. 双 Hub 管道式网络拦截器 (_interceptor)

依托宿主全局单例 Hub(__CALIBER_PAGE_NETWORK_HUB_V1__),同时支持 FetchXMLHttpRequest (XHR),具备管道式 FIFO 链式调度与跨模块多回调响应:

this._interceptor
  .target({
    url: "https://api.example.com/v1/user/info", // 目标 URL (Origin + Pathname)
    method: "GET",                              // HTTP 方法 (GET/POST 等)
    match: "/user/*"                            // 生效页面限制规则
  })
  .onRequest(`
    // 运行在宿主页面真实上下文中 (无闭包纯字符串)
    // 可用上下文: url, config, urlObject
    urlObject.searchParams.set('injected_by', 'caliber');
    config.headers = { ...config.headers, 'X-Caliber-Token': 'Verified' };
    return { url: urlObject.toString(), config };
  `)
  .onResponse((responseData) => {
    // 运行在油猴沙箱上下文中,安全接收并解析返回的数据 (JSON 或 text)
    console.log("沙箱成功捕获响应数据:", responseData);
  })
  .register(this.id);

解除拦截:

this._interceptor.removeHook(this.id);

3. 带熔断防护的页面作用域执行器 (_executor)

突破油猴沙箱(Sandbox)限制,在宿主真实 window 环境中执行 JS 代码,基于 crypto.randomUUID() 双向通信并异步返回可序列化的结果,内置 10秒超时熔断防护

async getHostState() {
  try {
    const data = await this._executor.execute(`
      (() => {
        // 直接访问网页挂载在 window 上的全局变量
        return window.__INITIAL_STATE__ ? window.__INITIAL_STATE__.user : null;
      })()
    `);
    this._logger.log("获取宿主数据成功:", data);
  } catch (err) {
    this._logger.error("页面执行失败或超时:", err.message);
  }
}

4. DOM 净化与安全注入 (_sanitizer)

专为对抗严格的 CSP (Content Security Policy) 与 Trusted Types 策略而设计:

// 1. 安全设置 innerHTML
this._sanitizer.setInnerHTML(targetElement, "<div class='card'>Content</div>");

// 2. 创建 TrustedHTML 对象
const trustedHtml = this._sanitizer.createTrustedHTML("<span>Text</span>");

// 3. 安全向页面注入 Script
this._sanitizer.injectScript(this._hostDocument, "console.log('Script Injected')");

// 4. 安全向页面注入 Style 样式 (自动追加应用专属命名空间)
this._sanitizer.injectStyle(this._hostDocument, ".my-btn { color: red; }", "custom-btn-style");

5. 无竞态模块重置门面 (_module)

当模块遇到需要完全推倒重建的配置变更时,可调用 requestReset() 触发无竞态热重置。框架会自动 await onDisable()、防抖拉取最新配置并即时执行 onEnable()

async onConfigChange(key, newVal, oldVal) {
  if (key === "engineType") {
    // 核心引擎改变,请求完整生命周期热重启
    await this._module.requestReset();
  }
}

5. 声明式 UI 守护与自愈 (UI Guardian)

在现代单页应用 (React/Vue) 中,DOM 经常被框架的 Virtual DOM 重新渲染抹除。uiGuard 能利用 requestIdleCallback 在低开销空闲帧中自动监控并毫秒级自愈恢复 UI 组件

class UIComponentModule extends Caliber.Module {
  id = "ui-enhancer";
  name = "界面增强器";

  // 声明 UI 守护契约
  uiGuard = {
    target: ".main-header",       // UI 组件应挂载的目标父节点选择器
    component: ".my-custom-badge" // 组件自身的 CSS 选择器(用于检测是否存在)
  };

  // 当 target 存在但 component 被删除/丢失时,框架自动触发 onRender 重新恢复
  onRender(targetElement) {
    const badge = this._hostDocument.createElement("span");
    badge.className = "my-custom-badge";
    badge.textContent = "VIP 标志";
    targetElement.appendChild(badge);
  }

  // 模块停用或清理时触发
  onCleanup() {
    this._hostDocument.querySelector(this.uiGuard.component)?.remove();
  }
}

6. 路由匹配与 SPA 页面感知

match 属性支持强大的内置分词引擎,自动解析路径与 Query 参数:

// 1. 动态 RESTful 命名参数 (自动提取到 context.params)
match = "/user/:userId/post/:postId";

// 2. 可选命名参数
match = "/list/:category?";

// 3. 全局通配符路径 (提取为 context.params._)
match = "/docs/*";

// 4. 正则表达式匹配
match = /^\/goods\/(?<goodsId>\d+)\.html$/;

// 5. 规则组合 (数组)
match = ["/dashboard", "/settings", "/*"];

SPA 路由无刷新切换感知

框架自动通过全局协调中心监听 pushStatereplaceStatepopstate

  • 新页面不符合规则 ➔ 触发 await onDisable()
  • 新页面符合规则且此前未激活 ➔ 触发 await onEnable(context)
  • 新页面符合规则且已处于激活状态 ➔ 自动触发 await onNavigate(context)

7. 质量防护与内存泄漏审计 (Module Auditor)

createApp 设置 isDebug: true 时,框架会自动激活 ModuleAuditor

在模块调用 onDisable() 结束并完全完成异步卸载后,审计员会自动比对追踪表,精准标红报告资源泄漏:

  1. 未移除的事件监听器:采用 (Target, Type, Listener, useCapture) 四元组精准追踪;
  2. 未清除的定时器:追踪 setInterval
  3. 未注销的 DOM 调度器任务:追踪 _scheduler.register

审计报告示例:

❌ [Auditor] LEAK DETECTED in module 'myFeature': Event listener(s) for type(s) [click] were NOT removed from element: <button id="btn">
❌ [Auditor] LEAK DETECTED in module 'myFeature': A setInterval (ID: 15) was NOT cleared.
❌ [Auditor] LEAK DETECTED in module 'myFeature': A scheduler task (ID: Symbol(.avatar)) was NOT unregistered.

8. 内核生命周期与优雅注销 (Kernel Destruction)

当需要动态卸载整个脚本时,可以调用 kernel.destroy() 实现零内存残留的无痕卸载

// 获取内核实例 (挂载在 hostWindow 上)
const kernelKey = Object.keys(window).find(k => k.startsWith("CALIBER_INSTANCE_"));
const kernel = window[kernelKey];

// 触发异步全量注销
await kernel.destroy();
  • 依次 await onDisable() 卸载所有已激活模块;
  • 批量注销宿主全局网络 Hub 中属于该 App 的所有 Hooks;
  • 移除 Web Component 设置面板;
  • 断开 MutationObserver 进入零功耗休眠模式
  • 彻底从全局作用域中 delete 内核单例键。

9. 完整开发示例

以下是一个集成了多行文本域配置、DOM 调度器分帧处理、网络请求拦截、UI 守护自愈与异步生命周期的综合实用模块:

class VideoDownloadEnhancer extends Caliber.Module {
  id = "video-enhancer";
  name = "高清视频下载助手";
  description = "自动捕获视频直链,添加快捷下载按钮与多行关键词过滤";
  match = "/video/:videoId";

  defaultConfig = {
    enabled: true,
    filterKeywords: {
      type: "textarea",
      value: "广告\n赞助商\n推广",
      label: "屏蔽过滤词",
      description: "包含这些关键词的视频将自动跳过",
      inputProps: { rows: 3, placeholder: "每行一个关键词..." },
      divider: "bottom"
    },
    btnColor: {
      type: "color",
      value: "#007aff",
      label: "下载按钮主题色"
    }
  };

  uiGuard = {
    target: ".video-toolbar",
    component: ".custom-download-btn"
  };

  #videoRealUrl = null;
  #schedulerTaskId = null;

  // 1. 模块激活 (支持 async)
  async onEnable(context) {
    this._logger.log(`当前视频 ID: ${context.params.videoId}`);

    // (1) 注册网络请求拦截器,捕获接口返回的真实直链
    this._interceptor
      .target({
        url: window.location.origin + "/api/video/detail",
        method: "GET"
      })
      .onResponse((data) => {
        if (data?.downloadUrl) {
          this.#videoRealUrl = data.downloadUrl;
          this._logger.log("已成功解析到视频直链:", this.#videoRealUrl);
        }
      })
      .register(this.id);

    // (2) 使用 DOM 调度器分帧给视频标题着色
    this.#schedulerTaskId = this._scheduler.register(".video-title", (el) => {
      el.style.borderLeft = `4px solid ${this._config.btnColor}`;
    }, { processExisting: true });
  }

  // 2. 声明式 UI 守护与自愈
  onRender(targetElement) {
    const btn = this._hostDocument.createElement("button");
    btn.className = "custom-download-btn";
    btn.textContent = "📥 极速下载";
    btn.style.cssText = `
      padding: 6px 14px; color: white; border: none; border-radius: 4px;
      cursor: pointer; background-color: ${this._config.btnColor};
    `;

    btn.onclick = () => {
      if (this.#videoRealUrl) {
        window.open(this.#videoRealUrl, "_blank");
      } else {
        alert("直链解析中,请稍候点击...");
      }
    };

    targetElement.appendChild(btn);
  }

  onCleanup() {
    this._hostDocument.querySelector(this.uiGuard.component)?.remove();
  }

  // 3. 配置实时双向同步
  onConfigChange(key, newValue) {
    if (key === "btnColor") {
      const btn = this._hostDocument.querySelector(this.uiGuard.component);
      if (btn) btn.style.backgroundColor = newValue;
    }
  }

  // 4. 模块异步优雅卸载
  async onDisable() {
    this._interceptor.removeHook(this.id);
    if (this.#schedulerTaskId) {
      this._scheduler.unregister(this.#schedulerTaskId);
      this.#schedulerTaskId = null;
    }
    this.onCleanup();
    this.#videoRealUrl = null;
    this._logger.log("模块已完全卸载释放。");
  }
}

// 启动框架
(async () => {
  await Caliber.createApp({
    appName: "VideoHelperApp",
    isDebug: true,
    modules: [VideoDownloadEnhancer],
    settingsPanel: {
      bottom: 60,
      right: 0 // 智能贴边平角
    }
  });
})();