@zhin.js/core 1.0.24 → 1.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/lib/adapter.d.ts +28 -1
  3. package/lib/adapter.d.ts.map +1 -1
  4. package/lib/adapter.js +100 -1
  5. package/lib/adapter.js.map +1 -1
  6. package/lib/built/adapter-process.d.ts +4 -0
  7. package/lib/built/adapter-process.d.ts.map +1 -1
  8. package/lib/built/adapter-process.js +94 -0
  9. package/lib/built/adapter-process.js.map +1 -1
  10. package/lib/built/ai-trigger.d.ts +89 -0
  11. package/lib/built/ai-trigger.d.ts.map +1 -0
  12. package/lib/built/ai-trigger.js +162 -0
  13. package/lib/built/ai-trigger.js.map +1 -0
  14. package/lib/built/database.d.ts.map +1 -1
  15. package/lib/built/database.js +2 -2
  16. package/lib/built/database.js.map +1 -1
  17. package/lib/built/tool.d.ts +281 -0
  18. package/lib/built/tool.d.ts.map +1 -0
  19. package/lib/built/tool.js +834 -0
  20. package/lib/built/tool.js.map +1 -0
  21. package/lib/index.d.ts +2 -0
  22. package/lib/index.d.ts.map +1 -1
  23. package/lib/index.js +4 -0
  24. package/lib/index.js.map +1 -1
  25. package/lib/plugin.d.ts +28 -1
  26. package/lib/plugin.d.ts.map +1 -1
  27. package/lib/plugin.js +124 -14
  28. package/lib/plugin.js.map +1 -1
  29. package/lib/types.d.ts +244 -0
  30. package/lib/types.d.ts.map +1 -1
  31. package/lib/utils.d.ts.map +1 -1
  32. package/lib/utils.js +38 -12
  33. package/lib/utils.js.map +1 -1
  34. package/package.json +4 -4
  35. package/src/adapter.ts +107 -2
  36. package/src/built/adapter-process.ts +99 -0
  37. package/src/built/ai-trigger.ts +256 -0
  38. package/src/built/database.ts +2 -2
  39. package/src/built/tool.ts +1049 -0
  40. package/src/index.ts +4 -0
  41. package/src/plugin.ts +164 -39
  42. package/src/types.ts +300 -1
  43. package/src/utils.ts +37 -13
  44. package/tests/component-new.test.ts +17 -6
package/src/utils.ts CHANGED
@@ -197,23 +197,46 @@ export namespace segment {
197
197
  template = unescape(template);
198
198
  const result: MessageElement[] = [];
199
199
  // 修复 ReDoS 漏洞:使用更安全的正则表达式
200
- // 原: /<(\S+)(\s[^>]+)?\/>/ 可能导致回溯
201
- const closingReg = /<(\w+)(?:\s+[^>]*?)?\/>/;
202
- // 原: /<(\S+)(\s[^>]+)?>([\s\S]*?)<\/\1>/ 可能导致回溯
203
- const twinningReg = /<(\w+)(?:\s+[^>]*?)?>([^]*?)<\/\1>/;
200
+ // 注意:需要使用捕获组来获取属性字符串,否则无法正确重建原始标签
201
+ // closingReg: 自闭合标签 <type attr="val"/>
202
+ const closingReg = /<(\w+)(\s+[^>]*?)?\/>/;
203
+ // twinningReg: 成对标签 <type attr="val">child</type>
204
+ const twinningReg = /<(\w+)(\s+[^>]*?)?>([^]*?)<\/\1>/;
204
205
 
205
206
  let iterations = 0;
206
207
  const MAX_ITERATIONS = 1000; // 防止无限循环
207
208
 
208
209
  while (template.length && iterations++ < MAX_ITERATIONS) {
209
- const [_, type, attrStr = "", child = ""] =
210
- template.match(twinningReg) || template.match(closingReg) || [];
211
- if (!type) break;
212
- const isClosing = closingReg.test(template);
213
- const matched = isClosing
214
- ? `<${type}${attrStr}/>`
215
- : `<${type}${attrStr}>${child}</${type}>`;
216
- const index = template.indexOf(matched);
210
+ const twinMatch = template.match(twinningReg);
211
+ const closeMatch = template.match(closingReg);
212
+
213
+ // 选择位置更靠前的匹配
214
+ let match: RegExpMatchArray | null = null;
215
+ let isClosing = false;
216
+
217
+ if (twinMatch && closeMatch) {
218
+ const twinIndex = template.indexOf(twinMatch[0]);
219
+ const closeIndex = template.indexOf(closeMatch[0]);
220
+ if (closeIndex <= twinIndex) {
221
+ match = closeMatch;
222
+ isClosing = true;
223
+ } else {
224
+ match = twinMatch;
225
+ }
226
+ } else if (closeMatch) {
227
+ match = closeMatch;
228
+ isClosing = true;
229
+ } else if (twinMatch) {
230
+ match = twinMatch;
231
+ }
232
+
233
+ if (!match) break;
234
+
235
+ const [fullMatch, type, attrStr = "", child = ""] = isClosing
236
+ ? [match[0], match[1], match[2] || ""]
237
+ : [match[0], match[1], match[2] || "", match[3] || ""];
238
+ const index = template.indexOf(fullMatch);
239
+ if (index === -1) break; // 安全检查
217
240
  const prevText = template.slice(0, index);
218
241
  if (prevText)
219
242
  result.push({
@@ -222,7 +245,7 @@ export namespace segment {
222
245
  text: unescape(prevText),
223
246
  },
224
247
  });
225
- template = template.slice(index + matched.length);
248
+ template = template.slice(index + fullMatch.length);
226
249
  // 修复 ReDoS 漏洞:使用更简单的正则表达式
227
250
  // 原: /\s([^=]+)(?=(?=="([^"]+)")|(?=='([^']+)'))/g 嵌套前瞻断言
228
251
  const attrArr = [
@@ -271,6 +294,7 @@ export namespace segment {
271
294
  if (typeof item === "string") return item;
272
295
  const { type, data } = item;
273
296
  if (type === "text") return data.text;
297
+ if (type === "at") return `@${data.user_id||data.qq}`;
274
298
  return data.text ? `{${type}}(${data.text})` : `{${type}}`;
275
299
  })
276
300
  .join("");
@@ -10,7 +10,17 @@ import {
10
10
  Fetch
11
11
  } from '../src/component'
12
12
  import { Message } from '../src/message'
13
- import { SendOptions } from '../src/types'
13
+ import { SendOptions, SendContent } from '../src/types'
14
+ import { segment } from '../src/utils'
15
+
16
+ // Helper to convert content to string for assertions
17
+ function contentToString(content: SendContent): string {
18
+ if (typeof content === 'string') return content
19
+ if (Array.isArray(content)) {
20
+ return content.map(c => typeof c === 'string' ? c : segment.toString(c)).join('')
21
+ }
22
+ return segment.toString(content)
23
+ }
14
24
 
15
25
  // Mock utils functions
16
26
  vi.mock('../src/utils', () => ({
@@ -212,7 +222,7 @@ describe('函数式组件系统测试', () => {
212
222
  }
213
223
 
214
224
  const result = await renderComponents(componentMap, options)
215
- expect(result.content).toContain('Hello John')
225
+ expect(contentToString(result.content)).toContain('Hello John')
216
226
  })
217
227
 
218
228
  it('应该正确渲染多个组件', async () => {
@@ -237,8 +247,9 @@ describe('函数式组件系统测试', () => {
237
247
  }
238
248
 
239
249
  const result = await renderComponents(componentMap, options)
240
- expect(result.content).toContain('[Hello]')
241
- expect(result.content).toContain('{42}')
250
+ const contentStr = contentToString(result.content)
251
+ expect(contentStr).toContain('[Hello]')
252
+ expect(contentStr).toContain('{42}')
242
253
  })
243
254
 
244
255
  it('应该正确处理嵌套组件', async () => {
@@ -264,7 +275,7 @@ describe('函数式组件系统测试', () => {
264
275
 
265
276
  const result = await renderComponents(componentMap, options)
266
277
  // 现在嵌套组件渲染应该工作了
267
- expect(result.content).toContain('标题: Test')
278
+ expect(contentToString(result.content)).toContain('标题: Test')
268
279
  })
269
280
  })
270
281
 
@@ -344,7 +355,7 @@ describe('函数式组件系统测试', () => {
344
355
 
345
356
  const result = await renderComponents(componentMap, options)
346
357
  // 错误会被捕获并转换为错误消息
347
- expect(result.content).toMatch(/\[error Error: Test error\]/)
358
+ expect(contentToString(result.content)).toMatch(/\[error Error: Test error\]/)
348
359
  })
349
360
  })
350
361
  })