Skip to content
大纲

NPP 元数据

本文档详细介绍 NPP 插件系统中每个 MetaData 项的说明、格式以及需要注意的事项,以帮助开发者能够正确配置插件。

1. 必填元数据

1.1 @time - 加载时机

说明

@time 用于指定插件的加载时机,控制插件在页面加载过程中的执行时机。

格式

  • 类型: 字符串
  • 可选值: headbody
  • 默认值: body

示例

javascript
// ==Npplication==
// @time head
// @time body
// ==/Npplication==

说明

  • head: 在页面 <head>部分加载,适用于需要尽早执行的插件
  • body: 在页面 <body>部分加载,适用于大多数插件

注意事项

  • 插件应尽量使用 body 加载
  • head 适用于需要修改页面初始状态的插件
  • 需要考虑插件对页面加载性能的影响,选择错误的加载时机可能导致功能异常

1.2 @id - 插件唯一标识符

说明

@id 是插件的唯一标识符,用于系统内部识别和管理插件,是插件存储、更新和卸载的关键标识。

格式

  • 类型: 字符串
  • 格式: 13位时间戳 + UUIDv4

nitaiPage 通过以下两步完成验证:

BASE
// 时间戳
D{13} > 1749401460000
// UUIDv4
/^([0-9]{13})_[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/

注意事项

  • ID 必须全局唯一,不能与其他插件冲突
  • 一旦设置,不建议更改 (会影响安装、更新、卸载和存储)
  • 建议仅使用小写字母,避免大小写混淆

1.3 @version - 插件版本

说明

@version 用于定义插件的版本号,用于版本管理、更新检查和依赖关系验证。

格式

  • 类型: 字符串
  • 格式: MAJOR.MINOR.PATCH (纯数字)

示例

javascript
// ==Npplication==
// @version 1.0.0
// @version 2.1.3
// ==/Npplication==

注意事项

  • MAJOR: 主版本号,不兼容的API修改
  • MINOR: 次版本号,向下兼容的功能性新增
  • PATCH: 修订号,向下兼容的问题修正
  • 纯数字: 禁止使用连字符和标识符(如-beta.1)

2. 可选元数据

2.1 @description - 插件描述

说明

@description 用于提供插件的详细描述信息,帮助用户了解插件的特点。

格式

  • 类型: 字符串
  • 长度: 无限制,建议10-500个字符

示例

javascript
// ==Npplication==
// @description 一个简单实用的计算器插件
// @description Weather Widget - 显示实时天气信息的小工具
// ==/Npplication==

注意事项

  • 描述应简洁明了,突出插件核心功能
  • 虽不必要,但强烈建议填写

2.2 @author - 插件作者

说明

@author 用于标识插件的作者。

格式

  • 类型: 字符串
  • 长度: 无限制,建议5-20个字符

示例

javascript
// ==Npplication==
// @author 张三
// @author John Doe
// @author NitaiDev Team
// @author example@email.com
// ==/Npplication==

注意事项

  • 支持包含邮箱地址等联系方式
  • 不建议使用他人的作者标识
  • 建议使用一致的作者标识
  • 虽不必要,但强烈建议填写

2.3 @updateUrl - 更新地址

说明

@updateUrl 用于指定插件更新检查的 URL 地址,nitaiPage 会定期访问此地址检查插件更新。

格式要求

  • 类型: 字符串 (URL)
  • 协议: 必须使用 http 或 https 协议
  • 格式: 完整的 URL 地址

示例

javascript
// ==Npplication==
// @updateUrl https://example.com/store/myNpp.js
// @updateUrl http://example.com/store/myNpp.js
// ==/Npplication==

注意事项

  • URL 必须指向可公开访问的插件文件
  • 需要注意跨域 (CORS) 问题
  • 确保 URL 长期有效,避免频繁变更

2.4 @name - 名称

说明

@name 用于定义插件的显示名称,这个名称将展示给用户

格式

  • 类型: 字符串
  • 长度: 建议不要超出 16 字符
  • 字符集: 支持中文、英文、数字和符号

示例

javascript
// ==Npplication==
// @name 我的插件
// @name My_Npp
// ==/Npplication==

注意事项

  • 名称应简短
  • 尽量避免使用特殊字符和表情符号
  • 不建议与其他插件名称重复
  • 虽不必要,但强烈建议填写

2.5 @icon - 插件图标

说明

@icon 用于指定插件的图标URL,用于在用户界面中显示插件图标。

格式

  • 类型: 字符串 (URL)
  • 协议: http 或 https
  • 格式: 图片 URL 或 Base64

示例

javascript
// ==Npplication==
// @icon https://example.com/icon.png
// @icon https://cdn.jsdelivr.net/gh/user/repo/icon.svg
// @icon data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==
// ==/Npplication==

使用注意事项

  • 建议使用正方形图标 (如 48x48 或 96x96)
  • 支持 PNG、JPG、SVG 等常见格式
  • 图标 URL 应稳定可靠,避免失效

2.6 @dependencies - 依赖项

说明

@dependencies 用于声明插件所依赖的其他插件,在插件安装时需要满足对应条件才可安装。

格式

  • 类型: 字符串
  • 格式: 插件ID@版本号,多个依赖用逗号分隔

示例代码

javascript
// ==Npplication==
// @dependencies id@1.0.0
// @dependencies id@2.1.0,id2@1.5.0
// ==/Npplication==

注意事项

  • 谨慎指定依赖版本,确保兼容性
  • 考虑依赖项的加载顺序 (可能需要通知用户手动更改加载顺序)

2.7 @type - 插件类型

说明

@type 用于指定插件的类型

  • normal: 普通插件,默认类型,系统普通功能插件
  • coreNpp: 核心插件,系统核心功能插件,不允许卸载和新安装,只能更新

格式要求

  • 类型: 字符串
  • 可选值: coreNpp
  • 默认值: normal

示例

javascript
// ==Npplication==
// @type nomal
// @type [none]
// @type core
// ==/Npplication==

注意事项

  • 建议不填

2.8 @setting - 是否注册设置界面

说明

@setting 用于告诉 nitaiPage 插件是否需要设置界面。

格式要求

  • 类型: 布尔值
  • 可选值: truefalse
  • 默认值: false

示例

javascript
// ==Npplication==
// @setting true
// @setting false
// ==/Npplication==

具体设置及调用方法,请参考NPP 设置页面内容添加指南

3. Metadata 验证和处理机制

3.1 Metadata 处理流程

必需字段验证

javascript
// 验证必需字段
async function extractMetadata(url) {
    try {
        // 提取元数据块
        const urlMetadata = scriptText.match(
            /\/\/\s*==Npplication==\s*\n([\s\S]*?)\n\/\/\s*==\/Npplication==/
        );

        if (!urlMetadata || !urlMetadata[1]) {
           console.error('未找到元数据');
            return;
        }

        // 解析元数据
        const metadataLines = urlMetadata[1].split('\n');
        const metadata = {};

        // 验证 名字/id/版本
        if (!metadata.name
            || !metadata.id
            || !metadata.version
            || !metadata.time
        ) {
            console.error('缺少必要元数据字段');
            return;
        }
    }
}

格式验证

javascript
// 验证 id 格式
if (metadata.type !== 'coreNpp') {
    // UUID v4 格式
    const idPattern = /^([0-9]{13})_[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/;
    const idMatch = metadata.id.match(idPattern);
    if (!idMatch) {
        console.error('错误的 ID 格式');
        return;
    }

    // 验证 id 有效性
    const timestamp = parseInt(match[1]);
    if (timestamp < 1749401460000) {
        console.error('ID 无效');
        return;
    }
}

// 验证 加载时机
if (!metadata.time || !['head', 'body'].includes(metadata.time.toLowerCase())) {
    metadata.time = 'body'; // 默认
}

其它部分

javascript
return {
    name: metadata.name,
    id: metadata.id,
    version: metadata.version,
    time: metadata.time.toLowerCase(),
    updateUrl: metadata.updateUrl || url,
    description: metadata.description || '未提供',
    author: metadata.author || '未知',
    type: metadata.type || '',
    icon: metadata.icon || 'https://nitai-images.pages.dev/nitaiPage/defeatNpp.svg',
    screen: metadata.screen || '',
    forceUpdate: metadata.forced || 'false',
    setting: metadata.setting || 'false',
    dependencies: metadata.dependencies || '',
};

3.2 Metadata 存储和管理

存储结构

javascript
const pluginMetadata = {
    author: "Nitai"
    dependencies: ""
    description: "主题扩展插件"
    forceUpdate: "false"
    icon: "https://nitai-images.pages.dev/nitaiPage/themeColor.svg"
    id: "themeColor"
    ignoreUpdatePrompt: false
    installTime: 1754415490324
    name: "主题色"
    screen: "[`https://nitai-images.pages.dev/nitaiPage/store/themeColor_screen.webp`]"
    setting: "true"
    time: "head"
    type: "coreNpp"
    updateUrl: "https://nfdb.nitai.us.kg/themeColor.js"
    version: "0.2.1"
};

存储

javascript
// 保存插件 metadata
async function savePluginMetadata(pluginId, metadata) {
    return new Promise((resolve, reject) => {
        const request = indexedDB.open('NpplicationDB', 1);
      
        request.onsuccess = (event) => {
            const db = event.target.result;
            const transaction = db.transaction('plugins', 'readwrite');
            const store = transaction.objectStore('plugins');
          
            const putRequest = store.put({
                id: pluginId,
                ...metadata,
                lastUpdateTime: Date.now()
            });
          
            putRequest.onsuccess = () => resolve(true);
            putRequest.onerror = () => reject(putRequest.error);
        };
      
        request.onerror = () => reject(request.error);
    });
}

// 获取插件 metadata
async function getPluginMetadata(pluginId) {
    return new Promise((resolve, reject) => {
        const request = indexedDB.open('NpplicationDB', 1);
      
        request.onsuccess = (event) => {
            const db = event.target.result;
            const transaction = db.transaction('plugins', 'readonly');
            const store = transaction.objectStore('plugins');
            const getRequest = store.get(pluginId);
          
            getRequest.onsuccess = () => resolve(getRequest.result);
            getRequest.onerror = () => reject(getRequest.error);
        };
      
        request.onerror = () => reject(request.error);
    });
}

Released under the Apache-2.0 License.