@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.
- package/CHANGELOG.md +12 -0
- package/lib/adapter.d.ts +28 -1
- package/lib/adapter.d.ts.map +1 -1
- package/lib/adapter.js +100 -1
- package/lib/adapter.js.map +1 -1
- package/lib/built/adapter-process.d.ts +4 -0
- package/lib/built/adapter-process.d.ts.map +1 -1
- package/lib/built/adapter-process.js +94 -0
- package/lib/built/adapter-process.js.map +1 -1
- package/lib/built/ai-trigger.d.ts +89 -0
- package/lib/built/ai-trigger.d.ts.map +1 -0
- package/lib/built/ai-trigger.js +162 -0
- package/lib/built/ai-trigger.js.map +1 -0
- package/lib/built/database.d.ts.map +1 -1
- package/lib/built/database.js +2 -2
- package/lib/built/database.js.map +1 -1
- package/lib/built/tool.d.ts +281 -0
- package/lib/built/tool.d.ts.map +1 -0
- package/lib/built/tool.js +834 -0
- package/lib/built/tool.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -0
- package/lib/index.js.map +1 -1
- package/lib/plugin.d.ts +28 -1
- package/lib/plugin.d.ts.map +1 -1
- package/lib/plugin.js +124 -14
- package/lib/plugin.js.map +1 -1
- package/lib/types.d.ts +244 -0
- package/lib/types.d.ts.map +1 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +38 -12
- package/lib/utils.js.map +1 -1
- package/package.json +4 -4
- package/src/adapter.ts +107 -2
- package/src/built/adapter-process.ts +99 -0
- package/src/built/ai-trigger.ts +256 -0
- package/src/built/database.ts +2 -2
- package/src/built/tool.ts +1049 -0
- package/src/index.ts +4 -0
- package/src/plugin.ts +164 -39
- package/src/types.ts +300 -1
- package/src/utils.ts +37 -13
- 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
|
-
//
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
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 +
|
|
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
|
-
|
|
241
|
-
expect(
|
|
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
|
})
|