Skip to content

一个强大的 OneBot12 消息段命令解析器,支持 TypeScript 和双格式(ESM/CJS)输出

Notifications You must be signed in to change notification settings

zhinjs/segment-matcher

Repository files navigation

Segment Matcher

npm version npm downloads License Test Coverage Node.js Version

消息段匹配器 - 高性能、类型安全的消息段模式匹配库,支持 ESM/CJS 双格式。

📖 文档

✨ 特性

  • 🎯 精确匹配: 支持复杂的消息段模式匹配,包括字面量、类型化字面量、参数等
  • 高性能:
    • 优化的匹配算法
    • 智能缓存系统(类型检查缓存、模式解析缓存)
    • 针对大小数组的优化策略
  • 🔧 灵活配置:
    • 支持自定义类型化字面量字段映射
    • 支持多字段优先级映射
    • 支持动态字段提取
  • 🛡️ 类型安全:
    • 完整的 TypeScript 类型定义
    • 运行时类型检查
    • 智能类型推导
  • 🔗 模块化设计:
    • 清晰的模块划分
    • 低耦合高内聚
    • 易于扩展
  • 📦 双格式支持:
    • ESM (ECMAScript Modules)
    • CommonJS
  • 🧪 测试完善:
    • 91%+ 测试覆盖率
    • 完整的单元测试
    • 边界情况测试
    • 性能测试
  • 🎨 丰富的类型系统:
    • 数字类型 (number) - 整数或浮点数
    • 整数类型 (integer) - 仅整数
    • 浮点数类型 (float) - 必须带小数点
    • 布尔类型 (boolean) - true/false
    • 单词类型 (word) - 非空格字符序列 ⭐ 新增
    • 文本类型 (text) - 支持引号包裹 ⭐ 增强
  • 📝 参数系统:
    • 必需参数 (<param:type>)
    • 可选参数 ([param:type])
    • 带默认值的可选参数 ([param:type=default])
    • 剩余参数 ([...rest:type])
  • 🔄 字段映射:
    • 单字段映射
    • 多字段优先级映射
    • 动态字段提取
  • 🚦 智能空格处理:
    • 参数间的单个空格自动处理 ⭐ 新增
    • 多个空格视为字面量精确匹配
    • 支持单个文本段自动提取多个参数 ⭐ 新增
  • 💬 引号支持:
    • 单引号和双引号 ⭐ 新增
    • 嵌套不同类型引号 ⭐ 新增
    • 多个 text 参数明确边界 ⭐ 新增

🚀 快速开始

安装

npm install segment-matcher

基础用法

import { SegmentMatcher } from 'segment-matcher';

// 创建消息段匹配器(注意空格敏感)
const matcher = new SegmentMatcher('hello <name:text>'); // "hello " 后面的空格

// 匹配消息段并处理结果
const segments = [
  { type: 'text', data: { text: 'hello Alice' } } // 注意 "hello " 后面的空格
];

const result = matcher.match(segments);
if (result) {
  console.log('匹配的消息段:', result.matched);
  console.log('提取的参数:', result.params);
  console.log('剩余的消息段:', result.remaining);
}

🎨 高级特性

1. 单个文本段多参数提取 ⭐ 新功能

// 支持从单个连续文本段中提取多个参数
const matcher = new SegmentMatcher('move [x:number=0] [y:number=0]');

// 单个文本段,匹配器会自动提取参数
const result = matcher.match([
  { type: 'text', data: { text: 'move 10 20' } }
]);

console.log(result.params); // { x: 10, y: 20 }

2. word 类型 - 非空格字符 ⭐ 新类型

// word 类型可以提取多个单词参数,不会像 text 那样贪婪匹配
const matcher = new SegmentMatcher('config [key:word=name] [value:word=default]');

const result = matcher.match([
  { type: 'text', data: { text: 'config database mysql' } }
]);

console.log(result.params); // { key: 'database', value: 'mysql' }

3. 引号支持 - 包含空格的文本 ⭐ 新功能

// 使用引号可以提取多个包含空格的 text 参数
const matcher = new SegmentMatcher('post [title:text=Untitled] [tags:text=none]');

// 使用双引号
const result1 = matcher.match([
  { type: 'text', data: { text: 'post "My Article Title" "tag1 tag2 tag3"' } }
]);
console.log(result1.params); 
// { title: 'My Article Title', tags: 'tag1 tag2 tag3' }

// 使用单引号
const result2 = matcher.match([
  { type: 'text', data: { text: "post 'Quick Tips' 'tutorial'" } }
]);
console.log(result2.params); 
// { title: 'Quick Tips', tags: 'tutorial' }

// 嵌套不同类型引号
const result3 = matcher.match([
  { type: 'text', data: { text: `post "It's great" 'He said "hello"'` } }
]);
console.log(result3.params); 
// { title: "It's great", tags: 'He said "hello"' }

4. 类型化字面量

// 匹配特定类型的消息段
const matcher = new SegmentMatcher('{text:hello}{at:123456}');

// 匹配结果包含完整的消息段信息
const result = matcher.match([
  { type: 'text', data: { text: 'hello' } },
  { type: 'at', data: { user_id: 123456 } }
]);

5. 剩余参数匹配

// 收集所有剩余的图片
const matcher = new SegmentMatcher('图片[...images:image]');

const result = matcher.match([
  { type: 'text', data: { text: '图片' } },
  { type: 'image', data: { file: '1.jpg' } },
  { type: 'image', data: { file: '2.jpg' } }
]);

// result.params.images 将包含所有图片的 URL

6. 自定义字段映射

// 自定义字段映射规则
const matcher = new SegmentMatcher('图片<img:image>', {
  image: ['url', 'file', 'src']  // 按优先级尝试这些字段
});

// 匹配时会按照指定的字段优先级提取值
const result = matcher.match([
  { type: 'text', data: { text: '图片' } },
  { type: 'image', data: { url: 'https://example.com/image.jpg' } }
]);

7. 智能空格处理 ⭐ 新功能

// 参数间的单个空格会被自动处理(可选)
const matcher = new SegmentMatcher('cmd [a:number] [b:number]');

// 以下两种输入都可以匹配
matcher.match([{ type: 'text', data: { text: 'cmd 10 20' } }]);   // 有空格 ✅
matcher.match([{ type: 'text', data: { text: 'cmd 1020' } }]);     // 紧贴也可以 ✅

// 但多个空格会被视为字面量
const strictMatcher = new SegmentMatcher('cmd  [a:number]'); // 两个空格
strictMatcher.match([{ type: 'text', data: { text: 'cmd  10' } }]);  // 必须两个空格 ✅
strictMatcher.match([{ type: 'text', data: { text: 'cmd 10' } }]);   // 一个空格 ❌

📚 类型对比指南

场景 推荐类型 示例 说明
单个单词 word [name:word] 不包含空格的字符串
包含空格的文本 text + 引号 [msg:text] 输入 "hello world" 明确边界
最后一个参数 text [msg:text] 贪婪匹配剩余内容
数字 number [count:number] 整数或浮点数
整数 integer [age:integer] 只接受整数
浮点数 float [price:float] 必须带小数点
布尔值 boolean [flag:boolean] true/false

⚠️ 注意事项

  1. 智能空格处理 ⭐ 更新

    • 参数间的单个空格自动处理(可选匹配)
    • 多个连续空格视为字面量(必须精确匹配)
    • 支持单个文本段自动提取多个参数
  2. 引号使用建议 ⭐ 新增

    • 使用引号包裹包含空格的 text 参数
    • 双引号内可以使用单引号,反之亦然
    • 相同类型的引号不能嵌套(如 "a"b" 会在第二个 " 处结束)
  3. 类型选择 ⭐ 新增

    • 多个单词参数优先使用 word 类型
    • 需要包含空格时使用 text + 引号
    • text 类型放在参数列表末尾可以省略引号
  4. 类型安全

    • 建议启用 TypeScript 的严格模式
    • 使用类型断言时要小心
  5. 性能优化

    • 对于频繁使用的模式,重用 SegmentMatcher 实例
    • 合理使用字段映射来避免不必要的字段访问

🧪 测试

# 运行测试
npm test

# 运行测试并生成覆盖率报告
npm run test:coverage

📦 构建

# 构建项目
npm run build

# 清理构建产物
npm run clean

📄 许可证

MIT License - 查看 LICENSE 文件了解详情。

🔗 相关链接

About

一个强大的 OneBot12 消息段命令解析器,支持 TypeScript 和双格式(ESM/CJS)输出

Topics

Resources

Security policy

Stars

Watchers

Forks

Sponsor this project

Packages

No packages published