@xihe-lab/tapd-core 2.0.0-rc.4 → 2.0.0-rc.6
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/LICENSE +16 -4
- package/README.md +6 -1
- package/dist/registry/mention-guard.d.ts +10 -0
- package/dist/registry/mention-guard.d.ts.map +1 -0
- package/dist/registry/mention-guard.js +66 -0
- package/dist/registry/mention-guard.js.map +1 -0
- package/dist/registry/registry.d.ts.map +1 -1
- package/dist/registry/registry.js +4 -1
- package/dist/registry/registry.js.map +1 -1
- package/dist/registry/richtext.d.ts +2 -1
- package/dist/registry/richtext.d.ts.map +1 -1
- package/dist/registry/richtext.js +4 -3
- package/dist/registry/richtext.js.map +1 -1
- package/dist/richtext/field-guidance.d.ts +21 -0
- package/dist/richtext/field-guidance.d.ts.map +1 -0
- package/dist/richtext/field-guidance.js +24 -0
- package/dist/richtext/field-guidance.js.map +1 -0
- package/dist/richtext/index.d.ts +1 -0
- package/dist/richtext/index.d.ts.map +1 -1
- package/dist/richtext/index.js +1 -0
- package/dist/richtext/index.js.map +1 -1
- package/dist/tools/bug.d.ts.map +1 -1
- package/dist/tools/bug.js +3 -2
- package/dist/tools/bug.js.map +1 -1
- package/dist/tools/comment.js +1 -1
- package/dist/tools/comment.js.map +1 -1
- package/dist/tools/iteration.js +3 -3
- package/dist/tools/iteration.js.map +1 -1
- package/dist/tools/release.js +3 -3
- package/dist/tools/release.js.map +1 -1
- package/dist/tools/story.js +3 -3
- package/dist/tools/story.js.map +1 -1
- package/dist/tools/task.js +5 -5
- package/dist/tools/task.js.map +1 -1
- package/dist/tools/test.d.ts.map +1 -1
- package/dist/tools/test.js +23 -10
- package/dist/tools/test.js.map +1 -1
- package/dist/tools/utility.d.ts.map +1 -1
- package/dist/tools/utility.js +13 -22
- package/dist/tools/utility.js.map +1 -1
- package/package.json +8 -5
- package/dist/advisor/advisor.test.d.ts +0 -2
- package/dist/advisor/advisor.test.d.ts.map +0 -1
- package/dist/advisor/advisor.test.js +0 -102
- package/dist/advisor/advisor.test.js.map +0 -1
- package/dist/cache/read-cache.test.d.ts +0 -2
- package/dist/cache/read-cache.test.d.ts.map +0 -1
- package/dist/cache/read-cache.test.js +0 -429
- package/dist/cache/read-cache.test.js.map +0 -1
- package/dist/config/config.test.d.ts +0 -2
- package/dist/config/config.test.d.ts.map +0 -1
- package/dist/config/config.test.js +0 -229
- package/dist/config/config.test.js.map +0 -1
- package/dist/registry/long-id-guard.test.d.ts +0 -2
- package/dist/registry/long-id-guard.test.d.ts.map +0 -1
- package/dist/registry/long-id-guard.test.js +0 -224
- package/dist/registry/long-id-guard.test.js.map +0 -1
- package/dist/registry/registry.test.d.ts +0 -2
- package/dist/registry/registry.test.d.ts.map +0 -1
- package/dist/registry/registry.test.js +0 -511
- package/dist/registry/registry.test.js.map +0 -1
- package/dist/registry/richtext.test.d.ts +0 -2
- package/dist/registry/richtext.test.d.ts.map +0 -1
- package/dist/registry/richtext.test.js +0 -273
- package/dist/registry/richtext.test.js.map +0 -1
- package/dist/schema/export.test.d.ts +0 -2
- package/dist/schema/export.test.d.ts.map +0 -1
- package/dist/schema/export.test.js +0 -68
- package/dist/schema/export.test.js.map +0 -1
- package/dist/tools/attachment.test.d.ts +0 -2
- package/dist/tools/attachment.test.d.ts.map +0 -1
- package/dist/tools/attachment.test.js +0 -432
- package/dist/tools/attachment.test.js.map +0 -1
- package/dist/tools/md-to-html.test.d.ts +0 -2
- package/dist/tools/md-to-html.test.d.ts.map +0 -1
- package/dist/tools/md-to-html.test.js +0 -125
- package/dist/tools/md-to-html.test.js.map +0 -1
- package/dist/tools/richtext-wiring.test.d.ts +0 -2
- package/dist/tools/richtext-wiring.test.d.ts.map +0 -1
- package/dist/tools/richtext-wiring.test.js +0 -302
- package/dist/tools/richtext-wiring.test.js.map +0 -1
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* rc.2 P3 接线测试(需求 1139814312001001548 P3 + 1139814312001001547 P2 md 闭环)。
|
|
3
|
-
*
|
|
4
|
-
* 覆盖(FSD §3.4-3.6 / §3.7 / §8):
|
|
5
|
-
* 1. tapd_md_to_html upload_images:本地图上传替换(mock 上传)、失败清单、远端路径不动、去重单次上传
|
|
6
|
-
* 2. tapd_md_to_html workspace_id:@昵称成员校验 warnings + /users 不可用降级跳过
|
|
7
|
-
* 3. @ 语义 token 级转换:code_span / 链接 URL / 裸 URL / 邮箱 / 工单号内 @ 不误伤
|
|
8
|
-
* 4. raw_html 透传对比:写工具 md 管道 vs raw_html 直发(registry 实链路 + D8 双写不破坏)
|
|
9
|
-
* 5. turndown 规则顺序:保真规则(at-who/附件锚点)先于 GFM/内建规则匹配
|
|
10
|
-
*
|
|
11
|
-
* Run directly: npx tsx src/tools/richtext-wiring.test.ts (from packages/core)
|
|
12
|
-
* Mock client pattern follows attachment.test.ts — no real credentials.
|
|
13
|
-
*/
|
|
14
|
-
import assert from 'node:assert/strict';
|
|
15
|
-
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
16
|
-
import { tmpdir } from 'node:os';
|
|
17
|
-
import path from 'node:path';
|
|
18
|
-
import { ReadStream } from 'node:fs';
|
|
19
|
-
import { ToolRegistry } from '../registry/registry.js';
|
|
20
|
-
import { transformWriteArgs } from '../registry/richtext.js';
|
|
21
|
-
import { utilityTools } from './utility.js';
|
|
22
|
-
import { allTools } from './index.js';
|
|
23
|
-
// ---------------------------------------------------------------------------
|
|
24
|
-
// Recording mock client
|
|
25
|
-
// ---------------------------------------------------------------------------
|
|
26
|
-
class RecordingClient {
|
|
27
|
-
postFileCalls = [];
|
|
28
|
-
getCalls = [];
|
|
29
|
-
postCalls = [];
|
|
30
|
-
postFileResponse = { image_src: '/tfl/pictures/202609/uploaded.png' };
|
|
31
|
-
getResponse = [];
|
|
32
|
-
postResponse = { Comment: { id: '9001' } };
|
|
33
|
-
postFile(p, params) {
|
|
34
|
-
this.postFileCalls.push({ path: p, params });
|
|
35
|
-
return Promise.resolve(this.postFileResponse);
|
|
36
|
-
}
|
|
37
|
-
get(p, params) {
|
|
38
|
-
this.getCalls.push({ path: p, params });
|
|
39
|
-
return Promise.resolve(this.getResponse);
|
|
40
|
-
}
|
|
41
|
-
post(p, params) {
|
|
42
|
-
this.postCalls.push({ path: p, params });
|
|
43
|
-
return Promise.resolve(this.postResponse);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
const WS = 39814312;
|
|
47
|
-
const registry = new ToolRegistry();
|
|
48
|
-
registry.register(allTools);
|
|
49
|
-
const mdToHtmlTool = utilityTools.find(t => t.name === 'tapd_md_to_html');
|
|
50
|
-
const htmlToMdTool = utilityTools.find(t => t.name === 'tapd_html_to_md');
|
|
51
|
-
const createCommentTool = registry.get('tapd_create_comment');
|
|
52
|
-
async function mdRender(params, client = new RecordingClient()) {
|
|
53
|
-
return mdToHtmlTool.handler(client, params);
|
|
54
|
-
}
|
|
55
|
-
async function mdFromHtml(html) {
|
|
56
|
-
const result = await htmlToMdTool.handler({}, { html });
|
|
57
|
-
return result.markdown;
|
|
58
|
-
}
|
|
59
|
-
const AT = (name) => `<b class="at-who" contenteditable="false" data-userid="${name}" data-type="user">@${name}</b>`;
|
|
60
|
-
const tmpRoot = await mkdtemp(path.join(tmpdir(), 'tapd-rc2-wiring-'));
|
|
61
|
-
async function tempFile(name, content) {
|
|
62
|
-
const p = path.join(tmpRoot, name);
|
|
63
|
-
await writeFile(p, content);
|
|
64
|
-
return p;
|
|
65
|
-
}
|
|
66
|
-
const checks = [
|
|
67
|
-
// -------------------------------------------------- 1. upload_images (P2 闭环)
|
|
68
|
-
['upload_images: 本地图上传并替换为 /tfl/(返回 uploaded_images 清单 + ReadStream 进 multipart)', async () => {
|
|
69
|
-
const img = await tempFile('shot.png', Buffer.from('89504e47', 'hex'));
|
|
70
|
-
const dotted = `${tmpRoot}/./shot.png`; // 同一文件的另一种写法(resolve 后同路径)
|
|
71
|
-
const rec = new RecordingClient();
|
|
72
|
-
const result = await mdRender({ content: `看截图  与 `, upload_images: true, workspace_id: WS }, rec);
|
|
73
|
-
// 同一文件去重:单次上传(绝对路径归一)
|
|
74
|
-
assert.equal(rec.postFileCalls.length, 1);
|
|
75
|
-
assert.equal(rec.postFileCalls[0].path, '/files/upload_image');
|
|
76
|
-
assert.ok(rec.postFileCalls[0].params.image instanceof ReadStream);
|
|
77
|
-
const html = result.html;
|
|
78
|
-
assert.ok(html.includes('<img src="/tfl/pictures/202609/uploaded.png" alt="首页">'), html);
|
|
79
|
-
assert.ok(!html.includes('shot.png'));
|
|
80
|
-
// 两种写法都替换为同一 /tfl/ 路径;上传清单只记真实发生的 1 次上传
|
|
81
|
-
assert.equal((html.match(/\/tfl\/pictures\/202609\/uploaded\.png/g) ?? []).length, 2);
|
|
82
|
-
assert.deepEqual(result.uploaded_images, [
|
|
83
|
-
{ local_path: dotted, image_src: '/tfl/pictures/202609/uploaded.png' },
|
|
84
|
-
]);
|
|
85
|
-
assert.equal(result.failed_images, undefined);
|
|
86
|
-
}],
|
|
87
|
-
['upload_images: 缺失文件列入 failed_images 不中断;远端 /tfl/ 与 http(s) 路径原样保留', async () => {
|
|
88
|
-
const rec = new RecordingClient();
|
|
89
|
-
const result = await mdRender({
|
|
90
|
-
content: '  ',
|
|
91
|
-
upload_images: true,
|
|
92
|
-
workspace_id: WS,
|
|
93
|
-
}, rec);
|
|
94
|
-
assert.equal(rec.postFileCalls.length, 0, '远端路径绝不触发上传');
|
|
95
|
-
const html = result.html;
|
|
96
|
-
assert.ok(html.includes('src="/tfl/a.png"'));
|
|
97
|
-
assert.ok(html.includes('src="https://cdn.example/x.png"'));
|
|
98
|
-
assert.ok(html.includes('src="./nope-missing.png"'));
|
|
99
|
-
assert.deepEqual(result.failed_images, [{ local_path: './nope-missing.png', reason: 'file not found: ./nope-missing.png (resolved: ' + path.resolve('./nope-missing.png') + ')' }]);
|
|
100
|
-
}],
|
|
101
|
-
['upload_images: 无 workspace 且无默认配置 → 明确报错;默认 false 零副作用', async () => {
|
|
102
|
-
const rec = new RecordingClient();
|
|
103
|
-
await assert.rejects(mdToHtmlTool.handler(rec, { content: '', upload_images: true }), /workspace_id is required/);
|
|
104
|
-
const result = await mdRender({ content: '' }, rec);
|
|
105
|
-
assert.equal(rec.postFileCalls.length, 0, '默认关闭时不触达上传通道');
|
|
106
|
-
assert.ok(result.html.includes('src="./x.png"'));
|
|
107
|
-
}],
|
|
108
|
-
['upload_images 语义:md_to_html 保持读闸门外(write=false),side_effect=upload 供审计(FSD §3.4)', () => {
|
|
109
|
-
const def = registry.get('tapd_md_to_html');
|
|
110
|
-
assert.equal(def.write ?? false, false, '不计入实体写闸门');
|
|
111
|
-
assert.equal(def.side_effect, 'upload');
|
|
112
|
-
}],
|
|
113
|
-
// -------------------------------------------------- 2. @昵称成员校验 (§3.6)
|
|
114
|
-
['workspace_id 提供时:未命中昵称进 warnings,命中不提示', async () => {
|
|
115
|
-
const rec = new RecordingClient();
|
|
116
|
-
rec.getResponse = [{ User: { user: '徐昭' } }, { User: { user: 'bob' } }];
|
|
117
|
-
const result = await mdRender({ content: '请 @徐昭 与 @ghost 与 @bob 处理', workspace_id: WS }, rec);
|
|
118
|
-
assert.equal(rec.getCalls[0].path, '/users');
|
|
119
|
-
assert.equal((rec.getCalls[0].params).workspace_id, WS);
|
|
120
|
-
assert.ok(result.html.includes(AT('徐昭')));
|
|
121
|
-
assert.deepEqual(result.warnings, ['@ghost 未命中项目成员昵称(请核对昵称拼写;关键通知场景建议同时填 cc)']);
|
|
122
|
-
}],
|
|
123
|
-
['workspace_id 校验降级:/users 403/失败 → 跳过校验并提示,转换不受影响', async () => {
|
|
124
|
-
const rec = new RecordingClient();
|
|
125
|
-
rec.get = () => Promise.reject(new Error('403 Forbidden: users::_get required'));
|
|
126
|
-
const result = await mdRender({ content: '请 @徐昭 处理', workspace_id: WS }, rec);
|
|
127
|
-
assert.ok(result.html.includes(AT('徐昭')));
|
|
128
|
-
const warnings = result.warnings;
|
|
129
|
-
assert.equal(warnings.length, 1);
|
|
130
|
-
assert.match(warnings[0], /成员校验已跳过.*403/);
|
|
131
|
-
assert.match(warnings[0], /服务端智能识别/);
|
|
132
|
-
}],
|
|
133
|
-
['未提供 workspace_id:零额外请求(校验不触发),纯转换', async () => {
|
|
134
|
-
const rec = new RecordingClient();
|
|
135
|
-
const result = await mdRender({ content: '请 @徐昭 处理' }, rec);
|
|
136
|
-
assert.equal(rec.getCalls.length, 0);
|
|
137
|
-
assert.equal(result.warnings, undefined);
|
|
138
|
-
assert.ok(result.html.includes(AT('徐昭')));
|
|
139
|
-
}],
|
|
140
|
-
// -------------------------------------------------- 3. @ token 级不误伤 (§8)
|
|
141
|
-
['@ token 级:code_span / 链接 URL / 裸 URL / 邮箱 / 工单号 内 @ 不误伤', async () => {
|
|
142
|
-
const result = await mdRender({ content: '联系 user@example.com;工单 T-100@QA;代码 `@code_x`;链接 [标题](https://e.com/@li);裸地址 https://e.com/@wang;真提及 @徐昭' });
|
|
143
|
-
const html = result.html;
|
|
144
|
-
assert.ok(html.includes('user@example.com'));
|
|
145
|
-
assert.ok(html.includes('T-100@QA'));
|
|
146
|
-
assert.ok(html.includes('<code>@code_x</code>'));
|
|
147
|
-
assert.ok(html.includes('href="https://e.com/@li"'));
|
|
148
|
-
assert.ok(html.includes('https://e.com/@wang'));
|
|
149
|
-
assert.equal(html.match(/at-who/g)?.length, 1, '仅真提及生成一个 at-who');
|
|
150
|
-
assert.ok(html.includes(AT('徐昭')));
|
|
151
|
-
}],
|
|
152
|
-
['@ 转义 @@ 与列表/引用上下文:@@ → 字面 @,块内提及照常', async () => {
|
|
153
|
-
const result = await mdRender({ content: '- 字面 @@support\n> 引用里 @李四' });
|
|
154
|
-
const html = result.html;
|
|
155
|
-
assert.ok(html.includes('字面 @support'));
|
|
156
|
-
assert.ok(!html.includes('@@'));
|
|
157
|
-
assert.ok(html.includes(AT('李四')));
|
|
158
|
-
}],
|
|
159
|
-
['attach: 链接 token 级转换:→ R6 五件套锚点;链接文本/URL 内 @ 不二次处理', async () => {
|
|
160
|
-
const result = await mdRender({ content: `材料 [📎 报表@v2.txt](attach:${WS}/1139814312001000001),普通 [链接](https://e.com)。` });
|
|
161
|
-
const html = result.html;
|
|
162
|
-
assert.ok(html.includes('data-is-tapd-attachment="true"'));
|
|
163
|
-
assert.ok(html.includes('data-file-type="text"'));
|
|
164
|
-
assert.ok(html.includes('data-name="报表@v2.txt"'));
|
|
165
|
-
assert.ok(html.includes(`href="/${WS}/attachments/preview_attachments/1139814312001000001/story_description_attachment"`));
|
|
166
|
-
assert.ok(html.includes('href="https://e.com"'));
|
|
167
|
-
assert.ok(!html.includes('attach:'), 'attach: scheme 已被锚点替换');
|
|
168
|
-
}],
|
|
169
|
-
// -------------------------------------------------- 4. raw_html 透传对比 (§3.5)
|
|
170
|
-
['raw_html=false(默认):写管道 md→html + @/附件语义自动转换', async () => {
|
|
171
|
-
const rec = new RecordingClient();
|
|
172
|
-
await registry.exec('tapd_create_comment', { workspace_id: WS, entry_type: 'stories', entry_id: '1139814312001001533', description: '变更通知:@徐昭 请确认,材料 [📎 说明.txt](attach:39814312/1)' }, { entry: 'cli' }, () => rec);
|
|
173
|
-
const params = rec.postCalls[0].params;
|
|
174
|
-
assert.equal(params.description, `<p>变更通知:${AT('徐昭')} 请确认,材料 <a data-is-tapd-attachment="true" data-can-preview="true" data-file-type="text" data-name="说明.txt" target="_blank" rel="noopener" href="/39814312/attachments/preview_attachments/1/story_description_attachment">说明.txt</a></p>\n`);
|
|
175
|
-
assert.equal(params.raw_html, undefined, 'raw_html 参数消费后不透传 TAPD API');
|
|
176
|
-
}],
|
|
177
|
-
['raw_html=true:description 原样透传(绕过 md→html),参数摘除', async () => {
|
|
178
|
-
const rec = new RecordingClient();
|
|
179
|
-
const raw = '<p>原文 <b>HTML</b>:@徐昭 不转换、[📎 a.txt](attach:1/2) 不转换</p>';
|
|
180
|
-
await registry.exec('tapd_create_comment', { workspace_id: WS, entry_type: 'stories', entry_id: '1139814312001001533', description: raw, raw_html: true }, { entry: 'cli' }, () => rec);
|
|
181
|
-
const params = rec.postCalls[0].params;
|
|
182
|
-
assert.equal(params.description, raw, '一字不改直发(R7 服务端保真)');
|
|
183
|
-
assert.equal(params.raw_html, undefined);
|
|
184
|
-
}],
|
|
185
|
-
['raw_html 对比 registry.exec:md 管道 vs raw_html 同文异果', async () => {
|
|
186
|
-
const mdPath = await registry.exec('tapd_create_comment', { workspace_id: WS, entry_type: 'stories', entry_id: '1', description: 'hello @徐昭 **加粗**' }, { entry: 'cli' }, () => ({ post: () => Promise.resolve({}) }));
|
|
187
|
-
assert.equal(mdPath.ok, true);
|
|
188
|
-
const rawRec = new RecordingClient();
|
|
189
|
-
await registry.exec('tapd_create_comment', { workspace_id: WS, entry_type: 'stories', entry_id: '1', description: 'hello @徐昭 **加粗**', raw_html: true }, { entry: 'cli' }, () => rawRec);
|
|
190
|
-
assert.equal((rawRec.postCalls[0].params).description, 'hello @徐昭 **加粗**');
|
|
191
|
-
}],
|
|
192
|
-
['raw_html=true:D8 双写不破坏(wiki markdown_description 维持既有策略——永不自动改写、无 md 源时不回填)', () => {
|
|
193
|
-
const raw = '<p>HTML 正文 @徐昭</p>';
|
|
194
|
-
// wiki:raw_html 时 description 透传,markdown_description 不被自动回填为 HTML
|
|
195
|
-
const wikiRaw = transformWriteArgs('tapd_create_wiki', { description: raw, raw_html: true });
|
|
196
|
-
assert.equal(wikiRaw.description, raw);
|
|
197
|
-
assert.equal(wikiRaw.markdown_description, undefined);
|
|
198
|
-
assert.equal(wikiRaw.raw_html, undefined);
|
|
199
|
-
// 对照组(raw_html=false):双写生效——description 渲染、markdown_description 保留 md 源
|
|
200
|
-
const wikiMd = transformWriteArgs('tapd_create_wiki', { description: '# 标题 @徐昭' });
|
|
201
|
-
assert.ok(wikiMd.description.includes('<h1>标题 '));
|
|
202
|
-
assert.ok(wikiMd.description.includes(AT('徐昭')));
|
|
203
|
-
assert.equal(wikiMd.markdown_description, '# 标题 @徐昭');
|
|
204
|
-
// 用户显式提供的 markdown_description 始终原样(raw_html 与否一致)
|
|
205
|
-
const wikiExplicit = transformWriteArgs('tapd_create_wiki', { description: raw, markdown_description: '自有 md', raw_html: true });
|
|
206
|
-
assert.equal(wikiExplicit.markdown_description, '自有 md');
|
|
207
|
-
// story(非双写):raw_html 透传;对照走管道
|
|
208
|
-
const storyRaw = transformWriteArgs('tapd_create_story', { description: raw, raw_html: true });
|
|
209
|
-
assert.equal(storyRaw.description, raw);
|
|
210
|
-
const storyMd = transformWriteArgs('tapd_create_story', { description: '正文 @徐昭' });
|
|
211
|
-
assert.ok(storyMd.description.includes(AT('徐昭')));
|
|
212
|
-
// raw_html 仅是语义开关:TAPD_RICHTEXT_AUTO=0 时同样摘除、全原样
|
|
213
|
-
const prev = process.env.TAPD_RICHTEXT_AUTO;
|
|
214
|
-
process.env.TAPD_RICHTEXT_AUTO = '0';
|
|
215
|
-
try {
|
|
216
|
-
const off = transformWriteArgs('tapd_create_comment', { description: '正文 @徐昭', raw_html: true });
|
|
217
|
-
assert.equal(off.description, '正文 @徐昭');
|
|
218
|
-
assert.equal(off.raw_html, undefined);
|
|
219
|
-
}
|
|
220
|
-
finally {
|
|
221
|
-
if (prev === undefined)
|
|
222
|
-
delete process.env.TAPD_RICHTEXT_AUTO;
|
|
223
|
-
else
|
|
224
|
-
process.env.TAPD_RICHTEXT_AUTO = prev;
|
|
225
|
-
}
|
|
226
|
-
}],
|
|
227
|
-
// -------------------------------------------------- 5. turndown 规则顺序 (§8)
|
|
228
|
-
['turndown 保真规则先于 GFM/内建规则:at-who 不降级 **粗体**,附件锚点不被当普通链接', async () => {
|
|
229
|
-
const md = await mdFromHtml(`<p>负责人 ${AT('徐昭')},材料 <a data-is-tapd-attachment="true" data-can-preview="true" data-file-type="pdf" data-name="设计.pdf" data-size="9" target="_blank" rel="noopener" href="/39814312/attachments/preview_attachments/2/story_description_attachment">设计.pdf</a></p>`);
|
|
230
|
-
assert.ok(md.includes('@徐昭'));
|
|
231
|
-
assert.ok(!md.includes('**'), `at-who 禁止降级为粗体: ${md}`);
|
|
232
|
-
assert.ok(md.includes('[📎 设计.pdf](attach:39814312/2)'));
|
|
233
|
-
assert.ok(!md.includes('href='), '附件锚点不得残留为普通链接');
|
|
234
|
-
}],
|
|
235
|
-
['turndown 规则优先级:保真规则 unshift 后先于 GFM 表格/删除线与内建 strong/inlineLink 匹配', async () => {
|
|
236
|
-
// 表格单元格 + 删除线 + 粗体 + 链接混排:保真语义优先,GFM 其余能力不受影响
|
|
237
|
-
const html = '<table><thead><tr><th>负责人</th><th>材料</th></tr></thead><tbody><tr><td>' + AT('徐昭') + '</td><td>' +
|
|
238
|
-
'<a data-is-tapd-attachment="true" data-can-preview="true" data-file-type="other" data-name="a.bin" href="/39814312/attachments/preview_attachments/3/story_description_attachment">a.bin</a>' +
|
|
239
|
-
'</td></tr></tbody></table><p><b>普通粗体</b> <a href="https://e.com">普通链接</a></p>';
|
|
240
|
-
const md = await mdFromHtml(html);
|
|
241
|
-
assert.ok(md.includes('@徐昭'));
|
|
242
|
-
assert.ok(md.includes('[📎 a.bin](attach:39814312/3)'));
|
|
243
|
-
assert.ok(md.includes('**普通粗体**'));
|
|
244
|
-
assert.ok(md.includes('[普通链接](https://e.com)'));
|
|
245
|
-
assert.match(md, /\|\s*负责人\s*\|\s*材料\s*\|/);
|
|
246
|
-
}],
|
|
247
|
-
['html→md:字面 @ 加倍保 round-trip,CODE 内 @ 不加倍', async () => {
|
|
248
|
-
const md = await mdFromHtml('<p>找 @徐昭 或字面 @support,代码 <code>@code_x</code></p>');
|
|
249
|
-
assert.ok(md.includes('@@徐昭'), 'html→md 方向 mention 加倍为 @@(round-trip 稳定)');
|
|
250
|
-
assert.ok(md.includes('@@support'));
|
|
251
|
-
assert.ok(md.includes('`@code_x`'), 'code_span 内 @ 原样');
|
|
252
|
-
// round-trip 稳定
|
|
253
|
-
const once = await mdRender({ content: md });
|
|
254
|
-
const again = await mdFromHtml(once.html);
|
|
255
|
-
assert.equal(again, md);
|
|
256
|
-
}],
|
|
257
|
-
['registry 全量注册:10 个富文本写工具均带 raw_html 通道(comment/story/task/bug/wiki create+update)', () => {
|
|
258
|
-
const expected = [
|
|
259
|
-
'tapd_create_comment', 'tapd_update_comment',
|
|
260
|
-
'tapd_create_story', 'tapd_update_story',
|
|
261
|
-
'tapd_create_task', 'tapd_update_task',
|
|
262
|
-
'tapd_create_bug', 'tapd_update_bug',
|
|
263
|
-
'tapd_create_wiki', 'tapd_update_wiki',
|
|
264
|
-
];
|
|
265
|
-
for (const name of expected) {
|
|
266
|
-
const tool = registry.get(name);
|
|
267
|
-
// 从 zod schema shape 中确认 raw_html 字段存在且默认 false
|
|
268
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
269
|
-
const shape = tool.inputSchema.shape;
|
|
270
|
-
assert.ok(shape.raw_html, `${name} 缺 raw_html 参数`);
|
|
271
|
-
}
|
|
272
|
-
// 基线不回归:工具总数保持 216 + tapd_md_to_html/html_to_md 增参不新增工具
|
|
273
|
-
assert.equal(registry.list().length, 216);
|
|
274
|
-
}],
|
|
275
|
-
['cli meta:md-to-html 增参不影响派生命令;tapd_html_to_md 纯读不受写闸门影响', async () => {
|
|
276
|
-
assert.equal(createCommentTool.name, 'tapd_create_comment');
|
|
277
|
-
const back = await registry.exec('tapd_html_to_md', { html: `<p>${AT('徐昭')}</p>` }, { entry: 'cli', readOnly: true }, () => ({}));
|
|
278
|
-
assert.equal(back.ok, true);
|
|
279
|
-
assert.equal(back.data.markdown, '@徐昭');
|
|
280
|
-
}],
|
|
281
|
-
];
|
|
282
|
-
let failed = 0;
|
|
283
|
-
for (const [name, check] of checks) {
|
|
284
|
-
try {
|
|
285
|
-
await check();
|
|
286
|
-
console.log(`PASS ${name}`);
|
|
287
|
-
}
|
|
288
|
-
catch (error) {
|
|
289
|
-
failed++;
|
|
290
|
-
console.error(`FAIL ${name}`);
|
|
291
|
-
console.error(` ${error instanceof Error ? error.stack ?? error.message : String(error)}`);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
await rm(tmpRoot, { recursive: true, force: true });
|
|
295
|
-
if (failed > 0) {
|
|
296
|
-
console.error(`\n${failed}/${checks.length} failed`);
|
|
297
|
-
process.exitCode = 1;
|
|
298
|
-
}
|
|
299
|
-
else {
|
|
300
|
-
console.log(`\n${checks.length}/${checks.length} passed`);
|
|
301
|
-
}
|
|
302
|
-
//# sourceMappingURL=richtext-wiring.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"richtext-wiring.test.js","sourceRoot":"","sources":["../../src/tools/richtext-wiring.test.ts"],"names":[],"mappings":"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"}
|