@xihe-lab/tapd-core 2.0.0-rc.1 → 2.0.0-rc.3

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 (158) hide show
  1. package/README.md +23 -0
  2. package/dist/advisor/index.d.ts.map +1 -1
  3. package/dist/advisor/index.js +2 -0
  4. package/dist/advisor/index.js.map +1 -1
  5. package/dist/cache/read-cache.d.ts +136 -0
  6. package/dist/cache/read-cache.d.ts.map +1 -0
  7. package/dist/cache/read-cache.js +322 -0
  8. package/dist/cache/read-cache.js.map +1 -0
  9. package/dist/cache/read-cache.test.d.ts +2 -0
  10. package/dist/cache/read-cache.test.d.ts.map +1 -0
  11. package/dist/cache/read-cache.test.js +429 -0
  12. package/dist/cache/read-cache.test.js.map +1 -0
  13. package/dist/errors/index.d.ts +120 -0
  14. package/dist/errors/index.d.ts.map +1 -0
  15. package/dist/errors/index.js +429 -0
  16. package/dist/errors/index.js.map +1 -0
  17. package/dist/index.d.ts +3 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +2 -0
  20. package/dist/index.js.map +1 -1
  21. package/dist/registry/registry.d.ts +7 -0
  22. package/dist/registry/registry.d.ts.map +1 -1
  23. package/dist/registry/registry.js +9 -3
  24. package/dist/registry/registry.js.map +1 -1
  25. package/dist/registry/registry.test.js +293 -2
  26. package/dist/registry/registry.test.js.map +1 -1
  27. package/dist/registry/richtext-manifests.generated.d.ts +1 -1
  28. package/dist/registry/richtext-manifests.generated.d.ts.map +1 -1
  29. package/dist/registry/richtext-manifests.generated.js +1 -1
  30. package/dist/registry/richtext-manifests.generated.js.map +1 -1
  31. package/dist/registry/richtext.d.ts +9 -0
  32. package/dist/registry/richtext.d.ts.map +1 -1
  33. package/dist/registry/richtext.js +33 -15
  34. package/dist/registry/richtext.js.map +1 -1
  35. package/dist/registry/richtext.test.js +70 -7
  36. package/dist/registry/richtext.test.js.map +1 -1
  37. package/dist/richtext/attachment-anchor.d.ts +58 -0
  38. package/dist/richtext/attachment-anchor.d.ts.map +1 -0
  39. package/dist/richtext/attachment-anchor.js +221 -0
  40. package/dist/richtext/attachment-anchor.js.map +1 -0
  41. package/dist/richtext/attachment-anchor.test.d.ts +2 -0
  42. package/dist/richtext/attachment-anchor.test.d.ts.map +1 -0
  43. package/dist/richtext/attachment-anchor.test.js +149 -0
  44. package/dist/richtext/attachment-anchor.test.js.map +1 -0
  45. package/dist/richtext/escape.d.ts +7 -0
  46. package/dist/richtext/escape.d.ts.map +1 -0
  47. package/dist/richtext/escape.js +60 -0
  48. package/dist/richtext/escape.js.map +1 -0
  49. package/dist/richtext/index.d.ts +15 -0
  50. package/dist/richtext/index.d.ts.map +1 -0
  51. package/dist/richtext/index.js +35 -0
  52. package/dist/richtext/index.js.map +1 -0
  53. package/dist/richtext/mention.d.ts +49 -0
  54. package/dist/richtext/mention.d.ts.map +1 -0
  55. package/dist/richtext/mention.js +179 -0
  56. package/dist/richtext/mention.js.map +1 -0
  57. package/dist/richtext/mention.test.d.ts +2 -0
  58. package/dist/richtext/mention.test.d.ts.map +1 -0
  59. package/dist/richtext/mention.test.js +123 -0
  60. package/dist/richtext/mention.test.js.map +1 -0
  61. package/dist/richtext/pipeline.d.ts +5 -0
  62. package/dist/richtext/pipeline.d.ts.map +1 -0
  63. package/dist/richtext/pipeline.js +199 -0
  64. package/dist/richtext/pipeline.js.map +1 -0
  65. package/dist/richtext/round-trip.test.d.ts +2 -0
  66. package/dist/richtext/round-trip.test.d.ts.map +1 -0
  67. package/dist/richtext/round-trip.test.js +105 -0
  68. package/dist/richtext/round-trip.test.js.map +1 -0
  69. package/dist/sdk-routes.d.ts.map +1 -1
  70. package/dist/sdk-routes.js +4 -0
  71. package/dist/sdk-routes.js.map +1 -1
  72. package/dist/tapd-client.d.ts +79 -2
  73. package/dist/tapd-client.d.ts.map +1 -1
  74. package/dist/tapd-client.js +177 -24
  75. package/dist/tapd-client.js.map +1 -1
  76. package/dist/tools/attachment.d.ts +47 -0
  77. package/dist/tools/attachment.d.ts.map +1 -1
  78. package/dist/tools/attachment.js +278 -32
  79. package/dist/tools/attachment.js.map +1 -1
  80. package/dist/tools/attachment.test.d.ts +2 -0
  81. package/dist/tools/attachment.test.d.ts.map +1 -0
  82. package/dist/tools/attachment.test.js +432 -0
  83. package/dist/tools/attachment.test.js.map +1 -0
  84. package/dist/tools/board.js +22 -22
  85. package/dist/tools/board.js.map +1 -1
  86. package/dist/tools/bug.d.ts.map +1 -1
  87. package/dist/tools/bug.js +262 -259
  88. package/dist/tools/bug.js.map +1 -1
  89. package/dist/tools/changes.js +20 -20
  90. package/dist/tools/changes.js.map +1 -1
  91. package/dist/tools/comment.d.ts.map +1 -1
  92. package/dist/tools/comment.js +26 -23
  93. package/dist/tools/comment.js.map +1 -1
  94. package/dist/tools/custom-fields.js +16 -16
  95. package/dist/tools/custom-fields.js.map +1 -1
  96. package/dist/tools/image.js +2 -2
  97. package/dist/tools/image.js.map +1 -1
  98. package/dist/tools/index.d.ts.map +1 -1
  99. package/dist/tools/index.js +2 -0
  100. package/dist/tools/index.js.map +1 -1
  101. package/dist/tools/iteration.js +50 -50
  102. package/dist/tools/iteration.js.map +1 -1
  103. package/dist/tools/media.d.ts +9 -0
  104. package/dist/tools/media.d.ts.map +1 -0
  105. package/dist/tools/media.js +45 -0
  106. package/dist/tools/media.js.map +1 -0
  107. package/dist/tools/mini-comment.js +27 -27
  108. package/dist/tools/mini-comment.js.map +1 -1
  109. package/dist/tools/mini-item.js +83 -83
  110. package/dist/tools/mini-item.js.map +1 -1
  111. package/dist/tools/mini-workspace.js +5 -5
  112. package/dist/tools/mini-workspace.js.map +1 -1
  113. package/dist/tools/program.js +7 -7
  114. package/dist/tools/program.js.map +1 -1
  115. package/dist/tools/relations.js +14 -14
  116. package/dist/tools/relations.js.map +1 -1
  117. package/dist/tools/release.js +53 -53
  118. package/dist/tools/release.js.map +1 -1
  119. package/dist/tools/report.js +8 -8
  120. package/dist/tools/report.js.map +1 -1
  121. package/dist/tools/richtext-wiring.test.d.ts +2 -0
  122. package/dist/tools/richtext-wiring.test.d.ts.map +1 -0
  123. package/dist/tools/richtext-wiring.test.js +302 -0
  124. package/dist/tools/richtext-wiring.test.js.map +1 -0
  125. package/dist/tools/settings.js +77 -77
  126. package/dist/tools/settings.js.map +1 -1
  127. package/dist/tools/source.js +14 -14
  128. package/dist/tools/source.js.map +1 -1
  129. package/dist/tools/story.d.ts.map +1 -1
  130. package/dist/tools/story.js +123 -120
  131. package/dist/tools/story.js.map +1 -1
  132. package/dist/tools/task.d.ts.map +1 -1
  133. package/dist/tools/task.js +126 -123
  134. package/dist/tools/task.js.map +1 -1
  135. package/dist/tools/test.js +117 -117
  136. package/dist/tools/test.js.map +1 -1
  137. package/dist/tools/timesheet.js +23 -23
  138. package/dist/tools/timesheet.js.map +1 -1
  139. package/dist/tools/user.js +8 -8
  140. package/dist/tools/user.js.map +1 -1
  141. package/dist/tools/utility.d.ts +17 -0
  142. package/dist/tools/utility.d.ts.map +1 -1
  143. package/dist/tools/utility.js +204 -88
  144. package/dist/tools/utility.js.map +1 -1
  145. package/dist/tools/wiki.d.ts.map +1 -1
  146. package/dist/tools/wiki.js +71 -56
  147. package/dist/tools/wiki.js.map +1 -1
  148. package/dist/tools/workflow.js +26 -26
  149. package/dist/tools/workflow.js.map +1 -1
  150. package/dist/tools/workspace.js +16 -16
  151. package/dist/tools/workspace.js.map +1 -1
  152. package/dist/types.d.ts +5 -0
  153. package/dist/types.d.ts.map +1 -1
  154. package/package.json +15 -11
  155. package/dist/tools/zz-acceptance-echo.d.ts +0 -3
  156. package/dist/tools/zz-acceptance-echo.d.ts.map +0 -1
  157. package/dist/tools/zz-acceptance-echo.js +0 -9
  158. package/dist/tools/zz-acceptance-echo.js.map +0 -1
@@ -2,7 +2,7 @@ import assert from 'node:assert/strict';
2
2
  import { allTools } from '../tools/index.js';
3
3
  import { resolveWrite } from './write-policy.js';
4
4
  import { ToolRegistry } from './registry.js';
5
- import { SERVER_MD_TOOLS, WRITE_RICHTEXT_FIELDS_BY_TOOL, } from './richtext-manifests.generated.js';
5
+ import { DUAL_WRITE_TOOLS, WRITE_RICHTEXT_FIELDS_BY_TOOL, } from './richtext-manifests.generated.js';
6
6
  import { isRichtextAutoEnabled, looksLikeHtml, transformWriteArgs, transformReadData, READ_RICHTEXT_FIELDS, } from './richtext.js';
7
7
  const RICHTEXT_PARAM_FIELDS = ['description', 'markdown_description'];
8
8
  function withAutoOff(fn) {
@@ -40,13 +40,15 @@ const checks = [
40
40
  const args = transformWriteArgs('tapd_create_story', { description: html });
41
41
  assert.equal(args.description, html);
42
42
  }],
43
- ['write: wiki markdown routed to server markdown_description', () => {
43
+ ['write: wiki dual-write renders html description and keeps md original', () => {
44
+ const md = '# wiki md\n\n- a\n- b';
44
45
  const args = transformWriteArgs('tapd_create_wiki', {
45
46
  name: 'w',
46
- description: '# wiki md',
47
+ description: md,
47
48
  });
48
- assert.equal(args.description, undefined);
49
- assert.equal(args.markdown_description, '# wiki md');
49
+ assert.match(args.description, /<h1>wiki md<\/h1>/);
50
+ assert.match(args.description, /<li>a<\/li>/);
51
+ assert.equal(args.markdown_description, md);
50
52
  }],
51
53
  ['write: wiki html passthrough keeps description', () => {
52
54
  const html = '<p>wiki html</p>';
@@ -61,7 +63,7 @@ const checks = [
61
63
  markdown_description: '# explicit md',
62
64
  });
63
65
  assert.equal(args.markdown_description, '# explicit md');
64
- assert.equal(args.description, undefined);
66
+ assert.match(args.description, /<h1>md from description<\/h1>/);
65
67
  }],
66
68
  ['write: switch off leaves args untouched', () => {
67
69
  const md = '# 原样';
@@ -103,6 +105,26 @@ const checks = [
103
105
  assert.equal(result.note, '<p>note 不在富文本清单</p>');
104
106
  assert.equal(result.nested.description, '');
105
107
  }],
108
+ ['read: legacy wiki falls back to markdown_description when description empty', () => {
109
+ const data = {
110
+ id: '1',
111
+ title: 'legacy',
112
+ description: '',
113
+ markdown_description: '# 存量 md\n\n**加粗**',
114
+ };
115
+ const result = transformReadData(data);
116
+ assert.equal(result.description, '# 存量 md\n\n**加粗**');
117
+ assert.equal(result.markdown_description, '# 存量 md\n\n**加粗**');
118
+ }],
119
+ ['read: fallback skips when description already has content', () => {
120
+ const html = '<p>已有正文</p>';
121
+ const data = {
122
+ description: html,
123
+ markdown_description: '**存量 md**',
124
+ };
125
+ const result = transformReadData(data);
126
+ assert.match(result.description, /已有正文/);
127
+ }],
106
128
  ['read: switch off returns raw html', () => {
107
129
  const data = { description: '<p>raw</p>' };
108
130
  const result = withAutoOff(() => transformReadData(data));
@@ -128,6 +150,47 @@ const checks = [
128
150
  assert.equal(result.ok, true);
129
151
  assert.match(captured?.description, /<h1>hi<\/h1>/);
130
152
  }],
153
+ ['exec: wiki create two-phase writes html then md original', async () => {
154
+ delete process.env.TAPD_RICHTEXT_AUTO;
155
+ const posts = [];
156
+ const registry = new ToolRegistry();
157
+ registry.register([allTools.find(t => t.name === 'tapd_create_wiki')]);
158
+ const result = await registry.exec('tapd_create_wiki', { name: 'zzz-delete-me-d8fix', workspace_id: 39814312, creator: 'x', description: '# 标题\n\n**加粗** 文本\n\n- 项' }, { entry: 'mcp' }, () => ({
159
+ post: (_path, body) => {
160
+ posts.push(body);
161
+ return Promise.resolve({ Wiki: { id: '123' } });
162
+ },
163
+ }));
164
+ assert.equal(result.ok, true);
165
+ assert.equal(posts.length, 2);
166
+ assert.match(posts[0].description, /<h1>标题<\/h1>/);
167
+ assert.match(posts[0].description, /<strong>加粗<\/strong>/);
168
+ assert.equal(posts[0].markdown_description, undefined);
169
+ assert.equal(posts[1].id, '123');
170
+ assert.match(posts[1].description, /<h1>标题<\/h1>/);
171
+ assert.match(posts[1].markdown_description, /\*\*加粗\*\*/);
172
+ }],
173
+ ['exec: wiki create auto-off sends single raw request', async () => {
174
+ process.env.TAPD_RICHTEXT_AUTO = '0';
175
+ try {
176
+ const posts = [];
177
+ const registry = new ToolRegistry();
178
+ registry.register([allTools.find(t => t.name === 'tapd_create_wiki')]);
179
+ const result = await registry.exec('tapd_create_wiki', { name: 'zzz-delete-me-d8fix', workspace_id: 39814312, creator: 'x', description: '# 原样' }, { entry: 'cli' }, () => ({
180
+ post: (_path, body) => {
181
+ posts.push(body);
182
+ return Promise.resolve({ Wiki: { id: '123' } });
183
+ },
184
+ }));
185
+ assert.equal(result.ok, true);
186
+ assert.equal(posts.length, 1);
187
+ assert.equal(posts[0].description, '# 原样');
188
+ assert.equal(posts[0].markdown_description, undefined);
189
+ }
190
+ finally {
191
+ delete process.env.TAPD_RICHTEXT_AUTO;
192
+ }
193
+ }],
131
194
  ['exec: read tool returns markdown description', async () => {
132
195
  delete process.env.TAPD_RICHTEXT_AUTO;
133
196
  const registry = new ToolRegistry();
@@ -179,7 +242,7 @@ const checks = [
179
242
  }
180
243
  assert.deepEqual(WRITE_RICHTEXT_FIELDS_BY_TOOL, scanned);
181
244
  assert.equal(Object.keys(scanned).length >= 25, true);
182
- for (const name of SERVER_MD_TOOLS) {
245
+ for (const name of DUAL_WRITE_TOOLS) {
183
246
  assert.ok(scanned[name]?.includes('description'), name);
184
247
  assert.ok(scanned[name]?.includes('markdown_description'), name);
185
248
  }
@@ -1 +1 @@
1
- {"version":3,"file":"richtext.test.js","sourceRoot":"","sources":["../../src/registry/richtext.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"richtext.test.js","sourceRoot":"","sources":["../../src/registry/richtext.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EACL,gBAAgB,EAChB,6BAA6B,GAC9B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,eAAe,CAAC;AAEvB,MAAM,qBAAqB,GAAG,CAAC,aAAa,EAAE,sBAAsB,CAAC,CAAC;AAEtE,SAAS,WAAW,CAAI,EAAW;IACjC,OAAO,CAAC,GAAG,CAAC,kBAAkB,GAAG,GAAG,CAAC;IACrC,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;YAAS,CAAC;QACT,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IACxC,CAAC;AACH,CAAC;AAED,MAAM,MAAM,GAA2C;IACrD,CAAC,+DAA+D,EAAE,GAAG,EAAE;YACrE,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;YACtC,MAAM,CAAC,KAAK,CAAC,qBAAqB,EAAE,EAAE,IAAI,CAAC,CAAC;YAC5C,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,qBAAqB,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QAClE,CAAC,CAAC;IAEF,CAAC,wDAAwD,EAAE,GAAG,EAAE;YAC9D,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC,CAAC;YAC/C,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,CAAC;YAC9C,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,CAAC;YACnD,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,aAAa,CAAC,EAAE,KAAK,CAAC,CAAC;QACpD,CAAC,CAAC;IAEF,CAAC,yDAAyD,EAAE,GAAG,EAAE;YAC/D,MAAM,IAAI,GAAG,kBAAkB,CAAC,mBAAmB,EAAE;gBACnD,IAAI,EAAE,GAAG;gBACT,WAAW,EAAE,kBAAkB;aAChC,CAAC,CAAC;YACH,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAC7B,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,WAAqB,EAAE,cAAc,CAAC,CAAC;YACzD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,WAAqB,EAAE,aAAa,CAAC,CAAC;QAC1D,CAAC,CAAC;IAEF,CAAC,iDAAiD,EAAE,GAAG,EAAE;YACvD,MAAM,IAAI,GAAG,iCAAiC,CAAC;YAC/C,MAAM,IAAI,GAAG,kBAAkB,CAAC,mBAAmB,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5E,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACvC,CAAC,CAAC;IAEF,CAAC,uEAAuE,EAAE,GAAG,EAAE;YAC7E,MAAM,EAAE,GAAG,uBAAuB,CAAC;YACnC,MAAM,IAAI,GAAG,kBAAkB,CAAC,kBAAkB,EAAE;gBAClD,IAAI,EAAE,GAAG;gBACT,WAAW,EAAE,EAAE;aAChB,CAAC,CAAC;YACH,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,WAAqB,EAAE,mBAAmB,CAAC,CAAC;YAC9D,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,WAAqB,EAAE,aAAa,CAAC,CAAC;YACxD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC;QAC9C,CAAC,CAAC;IAEF,CAAC,gDAAgD,EAAE,GAAG,EAAE;YACtD,MAAM,IAAI,GAAG,kBAAkB,CAAC;YAChC,MAAM,IAAI,GAAG,kBAAkB,CAAC,kBAAkB,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;YACpF,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;YACrC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,CAAC;QACrD,CAAC,CAAC;IAEF,CAAC,sEAAsE,EAAE,GAAG,EAAE;YAC5E,MAAM,IAAI,GAAG,kBAAkB,CAAC,kBAAkB,EAAE;gBAClD,IAAI,EAAE,GAAG;gBACT,WAAW,EAAE,uBAAuB;gBACpC,oBAAoB,EAAE,eAAe;aACtC,CAAC,CAAC;YACH,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,EAAE,eAAe,CAAC,CAAC;YACzD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,WAAqB,EAAE,+BAA+B,CAAC,CAAC;QAC5E,CAAC,CAAC;IAEF,CAAC,yCAAyC,EAAE,GAAG,EAAE;YAC/C,MAAM,EAAE,GAAG,MAAM,CAAC;YAClB,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,mBAAmB,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;YAC5F,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;YAClC,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,kBAAkB,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;YAC5F,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;YACnC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,CAAC;QACrD,CAAC,CAAC;IAEF,CAAC,gDAAgD,EAAE,GAAG,EAAE;YACtD,MAAM,IAAI,GAAG,kBAAkB,CAAC,kBAAkB,EAAE,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAC,CAAC;YAC3F,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,oBAAoB,CAAC,CAAC;QACvD,CAAC,CAAC;IAEF,CAAC,8DAA8D,EAAE,GAAG,EAAE;YACpE,MAAM,IAAI,GAAG;gBACX,IAAI,EAAE;oBACJ,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,uCAAuC,EAAE;oBACxE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,qBAAqB,EAAE,CAAC;oBACvD,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,2BAA2B,EAAE,CAAC,EAAE;iBAC5E;aACF,CAAC;YACF,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAgB,CAAC;YACtD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YACxC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;YACpD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YAC1D,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,CAAC;YAC1D,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,SAAS,CAAC,CAAC;QACtE,CAAC,CAAC;IAEF,CAAC,oDAAoD,EAAE,GAAG,EAAE;YAC1D,MAAM,IAAI,GAAG;gBACX,WAAW,EAAE,SAAS;gBACtB,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,qBAAqB;gBAC3B,MAAM,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE;aAC5B,CAAC;YACF,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAgB,CAAC;YACtD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;YAC5C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACrC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;YACjD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAC9C,CAAC,CAAC;IAEF,CAAC,6EAA6E,EAAE,GAAG,EAAE;YACnF,MAAM,IAAI,GAAG;gBACX,EAAE,EAAE,GAAG;gBACP,KAAK,EAAE,QAAQ;gBACf,WAAW,EAAE,EAAE;gBACf,oBAAoB,EAAE,mBAAmB;aAC1C,CAAC;YACF,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAgB,CAAC;YACtD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;YACtD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,CAAC;QACjE,CAAC,CAAC;IAEF,CAAC,2DAA2D,EAAE,GAAG,EAAE;YACjE,MAAM,IAAI,GAAG,aAAa,CAAC;YAC3B,MAAM,IAAI,GAAG;gBACX,WAAW,EAAE,IAAI;gBACjB,oBAAoB,EAAE,WAAW;aAClC,CAAC;YACF,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAA0D,CAAC;YAChG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAC3C,CAAC,CAAC;IAEF,CAAC,mCAAmC,EAAE,GAAG,EAAE;YACzC,MAAM,IAAI,GAAG,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC;YAC3C,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC;YAC1D,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC7B,CAAC,CAAC;IAEF,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAChD,MAAM,IAAI,GAAG,oHAAoH,CAAC;YAClI,MAAM,EAAE,GAAG,iBAAiB,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAA4B,CAAC;YAC/E,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;YAC5C,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;QACpD,CAAC,CAAC;IAEF,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;YAChE,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;YACtC,IAAI,QAA6C,CAAC;YAClD,MAAM,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAC;YACpC,QAAQ,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,mBAAmB,CAAE,CAAC,CAAC,CAAC;YACzE,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAChC,mBAAmB,EACnB,EAAE,IAAI,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,EAC3H,EAAE,KAAK,EAAE,KAAK,EAAE,EAChB,GAAG,EAAE,CAAC,CAAC;gBACL,IAAI,EAAE,CAAC,KAAa,EAAE,IAA6B,EAAE,EAAE;oBACrD,QAAQ,GAAG,IAAI,CAAC;oBAChB,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;gBAClD,CAAC;aACF,CAA0B,CAC5B,CAAC;YACF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YAC9B,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,WAAqB,EAAE,cAAc,CAAC,CAAC;QAChE,CAAC,CAAC;IAEF,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;YACtE,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;YACtC,MAAM,KAAK,GAA8B,EAAE,CAAC;YAC5C,MAAM,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAC;YACpC,QAAQ,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,kBAAkB,CAAE,CAAC,CAAC,CAAC;YACxE,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAChC,kBAAkB,EAClB,EAAE,IAAI,EAAE,qBAAqB,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,0BAA0B,EAAE,EAC9G,EAAE,KAAK,EAAE,KAAK,EAAE,EAChB,GAAG,EAAE,CAAC,CAAC;gBACL,IAAI,EAAE,CAAC,KAAa,EAAE,IAA6B,EAAE,EAAE;oBACrD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACjB,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;gBAClD,CAAC;aACF,CAA0B,CAC5B,CAAC;YACF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YAC9B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC9B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAqB,EAAE,cAAc,CAAC,CAAC;YAC7D,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAqB,EAAE,sBAAsB,CAAC,CAAC;YACrE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,oBAAoB,EAAE,SAAS,CAAC,CAAC;YACvD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YACjC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAqB,EAAE,cAAc,CAAC,CAAC;YAC7D,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,oBAA8B,EAAE,YAAY,CAAC,CAAC;QACtE,CAAC,CAAC;IAEF,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;YACjE,OAAO,CAAC,GAAG,CAAC,kBAAkB,GAAG,GAAG,CAAC;YACrC,IAAI,CAAC;gBACH,MAAM,KAAK,GAA8B,EAAE,CAAC;gBAC5C,MAAM,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAC;gBACpC,QAAQ,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,kBAAkB,CAAE,CAAC,CAAC,CAAC;gBACxE,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAChC,kBAAkB,EAClB,EAAE,IAAI,EAAE,qBAAqB,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,EAC1F,EAAE,KAAK,EAAE,KAAK,EAAE,EAChB,GAAG,EAAE,CAAC,CAAC;oBACL,IAAI,EAAE,CAAC,KAAa,EAAE,IAA6B,EAAE,EAAE;wBACrD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;wBACjB,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;oBAClD,CAAC;iBACF,CAA0B,CAC5B,CAAC;gBACF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;gBAC9B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;gBAC9B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;gBAC3C,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,oBAAoB,EAAE,SAAS,CAAC,CAAC;YACzD,CAAC;oBAAS,CAAC;gBACT,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;YACxC,CAAC;QACH,CAAC,CAAC;IAEF,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;YAC1D,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;YACtC,MAAM,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAC;YACpC,QAAQ,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,kBAAkB,CAAE,CAAC,CAAC,CAAC;YACxE,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAChC,kBAAkB,EAClB,EAAE,YAAY,EAAE,QAAQ,EAAE,EAC1B,EAAE,KAAK,EAAE,KAAK,EAAE,EAChB,GAAG,EAAE,CAAC,CAAC;gBACL,GAAG,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,gCAAgC,EAAE,CAAC,EAAE,CAAC;aAC9G,CAA0B,CAC5B,CAAC;YACF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YAC9B,MAAM,IAAI,GAAG,MAAM,CAAC,IAA2C,CAAC;YAChE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;QAC3D,CAAC,CAAC;IAEF,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;YAC3D,OAAO,CAAC,GAAG,CAAC,kBAAkB,GAAG,GAAG,CAAC;YACrC,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAC;gBACpC,QAAQ,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,mBAAmB,CAAE,CAAC,CAAC,CAAC;gBACzE,IAAI,QAA6C,CAAC;gBAClD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAChC,mBAAmB,EACnB,EAAE,IAAI,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,EAC3H,EAAE,KAAK,EAAE,KAAK,EAAE,EAChB,GAAG,EAAE,CAAC,CAAC;oBACL,IAAI,EAAE,CAAC,KAAa,EAAE,IAA6B,EAAE,EAAE;wBACrD,QAAQ,GAAG,IAAI,CAAC;wBAChB,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;oBAClD,CAAC;iBACF,CAA0B,CAC5B,CAAC;gBACF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;gBAC9B,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;YAC9C,CAAC;oBAAS,CAAC;gBACT,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;YACxC,CAAC;QACH,CAAC,CAAC;IAEF,CAAC,+DAA+D,EAAE,GAAG,EAAE;YACrE,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;YACtC,MAAM,QAAQ,GAAG,wEAAwE,CAAC;YAC1F,MAAM,OAAO,GAAG,kBAAkB,CAAC,mBAAmB,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,CAAC;YACnF,MAAM,KAAK,GAAG,OAAO,CAAC,WAAqB,CAAC;YAC5C,MAAM,QAAQ,GAAG,iBAAiB,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAA4B,CAAC;YACtF,MAAM,QAAQ,GAAG,kBAAkB,CAAC,mBAAmB,EAAE,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;YAChG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;QAC5C,CAAC,CAAC;IAEF,CAAC,gEAAgE,EAAE,GAAG,EAAE;YACtE,MAAM,OAAO,GAA6B,EAAE,CAAC;YAC7C,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;gBAC5B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;oBAAE,SAAS;gBAClC,MAAM,KAAK,GAAI,IAAI,CAAC,WAAmD,CAAC,KAAK,IAAI,EAAE,CAAC;gBACpF,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC;gBAC7D,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;oBAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;YACrD,CAAC;YACD,MAAM,CAAC,SAAS,CAAC,6BAA6B,EAAE,OAAO,CAAC,CAAC;YACzD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;YACtD,KAAK,MAAM,IAAI,IAAI,gBAAgB,EAAE,CAAC;gBACpC,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,IAAI,CAAC,CAAC;gBACxD,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,sBAAsB,CAAC,EAAE,IAAI,CAAC,CAAC;YACnE,CAAC;QACH,CAAC,CAAC;IAEF,CAAC,8DAA8D,EAAE,GAAG,EAAE;YACpE,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,oBAAoB,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;QACtE,CAAC,CAAC;CACH,CAAC;AAEF,IAAI,MAAM,GAAG,CAAC,CAAC;AACf,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;IACnC,IAAI,CAAC;QACH,MAAM,KAAK,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,EAAE,CAAC;QACT,OAAO,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;QAC9B,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC/E,CAAC;AACH,CAAC;AAED,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;IACf,OAAO,CAAC,KAAK,CAAC,KAAK,MAAM,IAAI,MAAM,CAAC,MAAM,SAAS,CAAC,CAAC;IACrD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC;KAAM,CAAC;IACN,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,SAAS,CAAC,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,58 @@
1
+ import type { HtmlNodeLike } from './mention.js';
2
+ /** TAPD 前端附件组件的 file-type 图标分类。 */
3
+ export type FileType = 'text' | 'image' | 'pdf' | 'other';
4
+ /** 扩展名 → file-type 映射表(键为小写扩展名;导出供 Wave 2 上传工具复用)。 */
5
+ export declare const FILE_TYPE_BY_EXTENSION: Readonly<Record<string, FileType>>;
6
+ /** 由文件名(任意大小写扩展名)映射 file-type;无扩展名或未收录 → other。 */
7
+ export declare function fileTypeFor(filename: string): FileType;
8
+ export declare const ATTACH_SCHEME = "attach:";
9
+ export declare const DEFAULT_ATTACHMENT_SLUG = "story_description_attachment";
10
+ /** 附件引用。size/fileType 可省略:省略 fileType 时按 name 扩展名映射。 */
11
+ export interface AttachmentRef {
12
+ workspaceId: string;
13
+ id: string;
14
+ name: string;
15
+ size?: number;
16
+ fileType?: FileType;
17
+ }
18
+ export interface AttachmentAnchorHtmlOptions {
19
+ /** href 末段 slug(随实体类型变化的场景可覆盖;默认评论/需求描述通用值)。 */
20
+ slug?: string;
21
+ /** data-can-preview,默认 true(R6 五件套定稿值)。 */
22
+ canPreview?: boolean;
23
+ }
24
+ /**
25
+ * 生成附件引用 md:`[📎 <文件名>](attach:<ws>/<id>)`。
26
+ * 文件名中的 `[` `]` `\` 按 md 规则转义(parseAttachmentAnchorMd 可逆)。
27
+ */
28
+ export declare function attachmentAnchorMd(ref: Pick<AttachmentRef, 'workspaceId' | 'id' | 'name'>): string;
29
+ /**
30
+ * 解析单个附件引用 md 片段(非附件链接 / scheme 不符 → null,调用方原样保留)。
31
+ * 返回的 ref 不含 size/fileType(md 形态不承载,html 侧按文件名重新映射)。
32
+ */
33
+ export declare function parseAttachmentAnchorMd(md: string): AttachmentRef | null;
34
+ /** 生成 R6 定稿最小锚点(data 五件套 + 零 spans)。size 省略时不输出 data-size。 */
35
+ export declare function attachmentAnchorHtml(ref: AttachmentRef, options?: AttachmentAnchorHtmlOptions): string;
36
+ /**
37
+ * 解析单个锚点标签串。识别条件(缺一即 null,调用方原样保留该锚点):
38
+ * data-is-tapd-attachment="true" + data-name + href 形如
39
+ * `/<ws>/attachments/preview_attachments/<id>/<slug>`。兼容完整编辑器模板(含 inner spans / type / class)。
40
+ */
41
+ export declare function parseAttachmentAnchorHtml(anchorHtml: string): AttachmentRef | null;
42
+ /** 扫描 html 片段中全部可识别的附件锚点。 */
43
+ export declare function findAttachmentAnchors(html: string): AttachmentRef[];
44
+ /**
45
+ * html 片段 → md 语义片段:可识别锚点 → `[📎 name](attach:ws/id)`;
46
+ * 不认识的锚点与其余内容原样透传(交给基础转换器 turndown 处理)。
47
+ */
48
+ export declare function attachmentHtmlToMd(html: string): string;
49
+ /**
50
+ * md 片段 → html 语义片段:附件引用 → R6 锚点;
51
+ * 非 `attach:` scheme 的链接与其余内容原样透传(交给基础转换器 markdown-it 处理)。
52
+ */
53
+ export declare function attachmentMdToHtml(md: string): string;
54
+ /** turndown 规则 filter 用:节点是否为可识别附件锚点。 */
55
+ export declare function isAttachmentAnchorNode(node: HtmlNodeLike): boolean;
56
+ /** turndown 规则 replacement 用:锚点节点 → 附件引用 md;不满足识别条件返回 null(调用方保留原样)。 */
57
+ export declare function attachmentAnchorNodeToMd(node: HtmlNodeLike): string | null;
58
+ //# sourceMappingURL=attachment-anchor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment-anchor.d.ts","sourceRoot":"","sources":["../../src/richtext/attachment-anchor.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,mCAAmC;AACnC,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC;AAE1D,sDAAsD;AACtD,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAMrE,CAAC;AAEF,mDAAmD;AACnD,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAItD;AAED,eAAO,MAAM,aAAa,YAAY,CAAC;AACvC,eAAO,MAAM,uBAAuB,iCAAiC,CAAC;AAEtE,wDAAwD;AACxD,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED,MAAM,WAAW,2BAA2B;IAC1C,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAiBD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,IAAI,CAAC,aAAa,EAAE,aAAa,GAAG,IAAI,GAAG,MAAM,CAAC,GAAG,MAAM,CAKlG;AAOD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAQxE;AAED,8DAA8D;AAC9D,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,GAAE,2BAAgC,GAAG,MAAM,CAoB1G;AAoCD;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAGlF;AAED,6BAA6B;AAC7B,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CASnE;AAID;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAavD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAWrD;AAED,yCAAyC;AACzC,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAGlE;AAED,wEAAwE;AACxE,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CAc1E"}
@@ -0,0 +1,221 @@
1
+ // TAPD 2.0 rc.2 P1/P3(需求 1139814312001001548)—— 附件引用 md 扩展 ↔ data 五件套锚点 HTML
2
+ // 双向语义(纯函数层)。设计依据:FSD §3.1(embed_md/embed_html)、R6 定稿模板;
3
+ // 实证:rc2-painpoints-research.md(评论 367/368/369 严格作用域)+ e2e 金样 poc-rc2-file-embed.mjs。
4
+ //
5
+ // md 扩展语法(BNF):
6
+ // attachment-md ::= "[📎 " link-text "](attach:" ws "/" id ")"
7
+ // link-text ::= ( md-escape | 非 "\" "]" 换行 字符 )*
8
+ // md-escape ::= "\" 任一非换行字符 (仅 \[ \] \\ 被 unescape 语义消费)
9
+ // ws / id ::= 1*( 排除空白、")(" 、"/" 的字符 )(实际为 TAPD 数字 ID)
10
+ //
11
+ // HTML 定稿最小模板(前端重建组件只读 data 五件套,inner spans 全可省——评论 369 实证完美渲染):
12
+ // <a data-is-tapd-attachment="true" data-can-preview="true" data-file-type="text"
13
+ // data-name="<文件名>" data-size="<字节数>" target="_blank" rel="noopener"
14
+ // href="/<ws>/attachments/preview_attachments/<附件ID>/story_description_attachment"><文件名></a>
15
+ //
16
+ // 语义约定:
17
+ // - data-file-type 由文件扩展名映射(fileTypeFor / FILE_TYPE_BY_EXTENSION,导出供 Wave 2 上传工具复用)。
18
+ // - html→md 方向丢 size/slug/type 细节:md 形态是纯引用(by design,round-trip 允许该损)。
19
+ // - 不认识的锚点(缺 data 五件套关键属性、裸 <a href> 等)原样保留,绝不猜测改写。
20
+ // - 与 mention.ts 相同的分层约定:fragment 级函数只做语义 token 替换 + 其余原样透传,
21
+ // Wave 2 在 markdown-it/turndown token 级接线(本文件提供节点级 duck-typing 辅助)。
22
+ import { decodeHtmlEntities, escapeHtmlAttr, escapeHtmlText } from './escape.js';
23
+ /** 扩展名 → file-type 映射表(键为小写扩展名;导出供 Wave 2 上传工具复用)。 */
24
+ export const FILE_TYPE_BY_EXTENSION = {
25
+ txt: 'text',
26
+ png: 'image',
27
+ jpg: 'image',
28
+ jpeg: 'image',
29
+ pdf: 'pdf',
30
+ };
31
+ /** 由文件名(任意大小写扩展名)映射 file-type;无扩展名或未收录 → other。 */
32
+ export function fileTypeFor(filename) {
33
+ const match = /\.([A-Za-z0-9]+)$/.exec(filename.trim());
34
+ if (!match)
35
+ return 'other';
36
+ return FILE_TYPE_BY_EXTENSION[match[1].toLowerCase()] ?? 'other';
37
+ }
38
+ export const ATTACH_SCHEME = 'attach:';
39
+ export const DEFAULT_ATTACHMENT_SLUG = 'story_description_attachment';
40
+ function assertRefToken(value, field) {
41
+ if (!value)
42
+ throw new TypeError(`attachment ${field} must be a non-empty string`);
43
+ if (/[\s()/]/.test(value)) {
44
+ throw new TypeError(`attachment ${field} must not contain whitespace, "/", "(" or ")": ${JSON.stringify(value)}`);
45
+ }
46
+ }
47
+ function escapeMdLinkText(name) {
48
+ return name.replace(/[\\\][]/g, (ch) => `\\${ch}`);
49
+ }
50
+ function unescapeMdLinkText(text) {
51
+ return text.replace(/\\([\\\][])/g, '$1');
52
+ }
53
+ /**
54
+ * 生成附件引用 md:`[📎 <文件名>](attach:<ws>/<id>)`。
55
+ * 文件名中的 `[` `]` `\` 按 md 规则转义(parseAttachmentAnchorMd 可逆)。
56
+ */
57
+ export function attachmentAnchorMd(ref) {
58
+ assertRefToken(ref.workspaceId, 'workspaceId');
59
+ assertRefToken(ref.id, 'id');
60
+ if (!ref.name)
61
+ throw new TypeError('attachment name must be a non-empty string');
62
+ return `[📎 ${escapeMdLinkText(ref.name)}](${ATTACH_SCHEME}${ref.workspaceId}/${ref.id})`;
63
+ }
64
+ // `\\.` 允许任意转义字符;其余字符排除 `\`、`]`、换行(`[` 无需排除但转义统一处理)。
65
+ const ATTACH_MD_PATTERN = '\\[📎 ((?:\\\\.|[^\\\\\\]\\n])*)\\]\\(attach:([^()\\s]+)/([^()\\s]+)\\)';
66
+ const ATTACH_MD_RE = new RegExp(ATTACH_MD_PATTERN, 'g');
67
+ const ATTACH_MD_RE_ONE = new RegExp(ATTACH_MD_PATTERN);
68
+ /**
69
+ * 解析单个附件引用 md 片段(非附件链接 / scheme 不符 → null,调用方原样保留)。
70
+ * 返回的 ref 不含 size/fileType(md 形态不承载,html 侧按文件名重新映射)。
71
+ */
72
+ export function parseAttachmentAnchorMd(md) {
73
+ const match = ATTACH_MD_RE_ONE.exec(md);
74
+ if (!match)
75
+ return null;
76
+ return {
77
+ workspaceId: match[2],
78
+ id: match[3],
79
+ name: unescapeMdLinkText(match[1]),
80
+ };
81
+ }
82
+ /** 生成 R6 定稿最小锚点(data 五件套 + 零 spans)。size 省略时不输出 data-size。 */
83
+ export function attachmentAnchorHtml(ref, options = {}) {
84
+ assertRefToken(ref.workspaceId, 'workspaceId');
85
+ assertRefToken(ref.id, 'id');
86
+ if (!ref.name)
87
+ throw new TypeError('attachment name must be a non-empty string');
88
+ const slug = options.slug ?? DEFAULT_ATTACHMENT_SLUG;
89
+ const canPreview = options.canPreview ?? true;
90
+ const fileType = ref.fileType ?? fileTypeFor(ref.name);
91
+ const attrs = [
92
+ 'data-is-tapd-attachment="true"',
93
+ `data-can-preview="${canPreview}"`,
94
+ `data-file-type="${fileType}"`,
95
+ `data-name="${escapeHtmlAttr(ref.name)}"`,
96
+ ];
97
+ if (ref.size !== undefined)
98
+ attrs.push(`data-size="${ref.size}"`);
99
+ attrs.push('target="_blank"', 'rel="noopener"', `href="/${ref.workspaceId}/attachments/preview_attachments/${ref.id}/${slug}"`);
100
+ return `<a ${attrs.join(' ')}>${escapeHtmlText(ref.name)}</a>`;
101
+ }
102
+ const A_OPEN_RE = /<a\b[^>]*>/gi;
103
+ const FLAG_ATTR_RE = /\bdata-is-tapd-attachment\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/i;
104
+ const NAME_ATTR_RE = /\bdata-name\s*=\s*(?:"([^"]*)"|'([^']*)')/i;
105
+ const SIZE_ATTR_RE = /\bdata-size\s*=\s*(?:"(\d+)"|'(\d+)')/i;
106
+ const FILE_TYPE_ATTR_RE = /\bdata-file-type\s*=\s*(?:"([^"]*)"|'([^']*)')/i;
107
+ const HREF_ATTR_RE = /\bhref\s*=\s*(?:"([^"]*)"|'([^']*)')/i;
108
+ const PREVIEW_HREF_RE = /^\/([^/\s]+)\/attachments\/preview_attachments\/([^/\s]+)\/([^/\s]*)$/i;
109
+ const FILE_TYPES = new Set(['text', 'image', 'pdf', 'other']);
110
+ function attrValue(match) {
111
+ if (!match)
112
+ return null;
113
+ return decodeHtmlEntities(match[1] ?? match[2] ?? match[3] ?? '');
114
+ }
115
+ function refFromOpenTag(openTag) {
116
+ const flag = attrValue(FLAG_ATTR_RE.exec(openTag));
117
+ if (flag?.toLowerCase() !== 'true')
118
+ return null;
119
+ const name = attrValue(NAME_ATTR_RE.exec(openTag));
120
+ const href = attrValue(HREF_ATTR_RE.exec(openTag));
121
+ if (!name || !href)
122
+ return null;
123
+ const hrefMatch = PREVIEW_HREF_RE.exec(href);
124
+ if (!hrefMatch)
125
+ return null;
126
+ const ref = { workspaceId: hrefMatch[1], id: hrefMatch[2], name };
127
+ const size = attrValue(SIZE_ATTR_RE.exec(openTag));
128
+ if (size !== null) {
129
+ const parsed = Number.parseInt(size, 10);
130
+ if (Number.isFinite(parsed))
131
+ ref.size = parsed;
132
+ }
133
+ const fileType = attrValue(FILE_TYPE_ATTR_RE.exec(openTag));
134
+ if (fileType !== null && FILE_TYPES.has(fileType))
135
+ ref.fileType = fileType;
136
+ return ref;
137
+ }
138
+ /**
139
+ * 解析单个锚点标签串。识别条件(缺一即 null,调用方原样保留该锚点):
140
+ * data-is-tapd-attachment="true" + data-name + href 形如
141
+ * `/<ws>/attachments/preview_attachments/<id>/<slug>`。兼容完整编辑器模板(含 inner spans / type / class)。
142
+ */
143
+ export function parseAttachmentAnchorHtml(anchorHtml) {
144
+ const openMatch = /^<a\b[^>]*>/i.exec(anchorHtml);
145
+ return openMatch ? refFromOpenTag(openMatch[0]) : null;
146
+ }
147
+ /** 扫描 html 片段中全部可识别的附件锚点。 */
148
+ export function findAttachmentAnchors(html) {
149
+ const refs = [];
150
+ A_OPEN_RE.lastIndex = 0;
151
+ let match;
152
+ while ((match = A_OPEN_RE.exec(html)) !== null) {
153
+ const ref = refFromOpenTag(match[0]);
154
+ if (ref)
155
+ refs.push(ref);
156
+ }
157
+ return refs;
158
+ }
159
+ const A_TAG_RE = /<a\b[^>]*>[\s\S]*?<\/a\s*>|<a\b[^>]*\/?>/gi;
160
+ /**
161
+ * html 片段 → md 语义片段:可识别锚点 → `[📎 name](attach:ws/id)`;
162
+ * 不认识的锚点与其余内容原样透传(交给基础转换器 turndown 处理)。
163
+ */
164
+ export function attachmentHtmlToMd(html) {
165
+ let out = '';
166
+ let pos = 0;
167
+ let match;
168
+ A_TAG_RE.lastIndex = 0;
169
+ while ((match = A_TAG_RE.exec(html)) !== null) {
170
+ const openMatch = /^<a\b[^>]*>/i.exec(match[0]);
171
+ const ref = openMatch ? refFromOpenTag(openMatch[0]) : null;
172
+ out += html.slice(pos, match.index);
173
+ out += ref ? attachmentAnchorMd(ref) : match[0];
174
+ pos = match.index + match[0].length;
175
+ }
176
+ return out + html.slice(pos);
177
+ }
178
+ /**
179
+ * md 片段 → html 语义片段:附件引用 → R6 锚点;
180
+ * 非 `attach:` scheme 的链接与其余内容原样透传(交给基础转换器 markdown-it 处理)。
181
+ */
182
+ export function attachmentMdToHtml(md) {
183
+ let out = '';
184
+ let pos = 0;
185
+ let match;
186
+ ATTACH_MD_RE.lastIndex = 0;
187
+ while ((match = ATTACH_MD_RE.exec(md)) !== null) {
188
+ out += md.slice(pos, match.index);
189
+ out += attachmentAnchorHtml({ workspaceId: match[2], id: match[3], name: unescapeMdLinkText(match[1]) });
190
+ pos = match.index + match[0].length;
191
+ }
192
+ return out + md.slice(pos);
193
+ }
194
+ /** turndown 规则 filter 用:节点是否为可识别附件锚点。 */
195
+ export function isAttachmentAnchorNode(node) {
196
+ if (node.nodeName.toUpperCase() !== 'A')
197
+ return false;
198
+ return (node.getAttribute('data-is-tapd-attachment') ?? '').toLowerCase() === 'true';
199
+ }
200
+ /** turndown 规则 replacement 用:锚点节点 → 附件引用 md;不满足识别条件返回 null(调用方保留原样)。 */
201
+ export function attachmentAnchorNodeToMd(node) {
202
+ if (!isAttachmentAnchorNode(node))
203
+ return null;
204
+ const name = node.getAttribute('data-name');
205
+ const href = node.getAttribute('href');
206
+ if (!name || !href)
207
+ return null;
208
+ const hrefMatch = PREVIEW_HREF_RE.exec(decodeHtmlEntities(href));
209
+ if (!hrefMatch)
210
+ return null;
211
+ const ref = { workspaceId: hrefMatch[1], id: hrefMatch[2], name: decodeHtmlEntities(name) };
212
+ const size = node.getAttribute('data-size');
213
+ const parsedSize = size === null ? Number.NaN : Number.parseInt(size, 10);
214
+ if (Number.isFinite(parsedSize))
215
+ ref.size = parsedSize;
216
+ const fileType = node.getAttribute('data-file-type');
217
+ if (fileType !== null && FILE_TYPES.has(fileType))
218
+ ref.fileType = fileType;
219
+ return attachmentAnchorMd(ref);
220
+ }
221
+ //# sourceMappingURL=attachment-anchor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment-anchor.js","sourceRoot":"","sources":["../../src/richtext/attachment-anchor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=attachment-anchor.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment-anchor.test.d.ts","sourceRoot":"","sources":["../../src/richtext/attachment-anchor.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,149 @@
1
+ // attachment-anchor 语义单测:fileTypeFor 映射 / md 扩展语法 / R6 五件套模板 / 解析容错 / 不认识锚点原样保留。
2
+ import assert from 'node:assert/strict';
3
+ import { ATTACH_SCHEME, DEFAULT_ATTACHMENT_SLUG, FILE_TYPE_BY_EXTENSION, attachmentAnchorHtml, attachmentAnchorMd, attachmentHtmlToMd, attachmentMdToHtml, fileTypeFor, findAttachmentAnchors, isAttachmentAnchorNode, attachmentAnchorNodeToMd, parseAttachmentAnchorHtml, parseAttachmentAnchorMd, } from './attachment-anchor.js';
4
+ const WS = '39814312';
5
+ const ID = '1139814312001000001';
6
+ // 完整编辑器模板(含 inner spans / type / class,e2e 金样 poc-rc2-file-embed.mjs 同构)
7
+ const EDITOR_STYLE_ANCHOR = `<a data-is-tapd-attachment="true" contenteditable="false" target="_blank" rel="noopener" ` +
8
+ `data-can-preview="true" data-file-type="text" type="text" data-name="comment-embed.txt" data-size="54" ` +
9
+ `href="/${WS}/attachments/preview_attachments/1139814312001000004/story_description_attachment" ` +
10
+ `class="tapd-editor__attachment-item"><span class="tapd-editor__attachment-item__left">` +
11
+ `<span class="tapd-editor__attachment-item__text-wrapper">` +
12
+ `<span class="tapd-editor__attachment-item__title">comment-embed.txt</span>` +
13
+ `<span class="tapd-editor__attachment-item__size">0.00MB</span></span></span></a>`;
14
+ const checks = [
15
+ ['fileTypeFor: txt→text、png/jpg/jpeg→image、pdf→pdf、其他→other(大小写不敏感)', () => {
16
+ assert.equal(fileTypeFor('说明.txt'), 'text');
17
+ assert.equal(fileTypeFor('pic.PNG'), 'image');
18
+ assert.equal(fileTypeFor('a.jpg'), 'image');
19
+ assert.equal(fileTypeFor('a.jpeg'), 'image');
20
+ assert.equal(fileTypeFor('doc.pdf'), 'pdf');
21
+ assert.equal(fileTypeFor('app.log'), 'other');
22
+ assert.equal(fileTypeFor('noext'), 'other');
23
+ assert.equal(fileTypeFor('报表@v2.pdf'), 'pdf');
24
+ }],
25
+ ['FILE_TYPE_BY_EXTENSION: 映射表导出供 Wave 2 复用', () => {
26
+ assert.equal(FILE_TYPE_BY_EXTENSION.txt, 'text');
27
+ assert.equal(FILE_TYPE_BY_EXTENSION.png, 'image');
28
+ assert.equal(FILE_TYPE_BY_EXTENSION.pdf, 'pdf');
29
+ assert.equal(ATTACH_SCHEME, 'attach:');
30
+ assert.equal(DEFAULT_ATTACHMENT_SLUG, 'story_description_attachment');
31
+ }],
32
+ ['attachmentAnchorMd: md 扩展语法生成', () => {
33
+ assert.equal(attachmentAnchorMd({ workspaceId: WS, id: ID, name: '需求说明.txt' }), `[📎 需求说明.txt](attach:${WS}/${ID})`);
34
+ }],
35
+ ['attachmentAnchorMd: 文件名中 []\\ 转义可逆;非法 ws/id 抛错', () => {
36
+ const md = attachmentAnchorMd({ workspaceId: WS, id: ID, name: 'a]b[ c\\d.txt' });
37
+ assert.equal(md, `[📎 a\\]b\\[ c\\\\d.txt](attach:${WS}/${ID})`);
38
+ const parsed = parseAttachmentAnchorMd(md);
39
+ assert.equal(parsed?.name, 'a]b[ c\\d.txt');
40
+ assert.throws(() => attachmentAnchorMd({ workspaceId: 'ws x', id: ID, name: 'f' }), TypeError);
41
+ assert.throws(() => attachmentAnchorMd({ workspaceId: WS, id: '', name: 'f' }), TypeError);
42
+ }],
43
+ ['parseAttachmentAnchorMd: 非 attach: 链接与普通链接 → null', () => {
44
+ assert.equal(parseAttachmentAnchorMd('[标题](https://www.tapd.cn/x)'), null);
45
+ assert.equal(parseAttachmentAnchorMd('[📎 x](https://a/b)'), null);
46
+ assert.equal(parseAttachmentAnchorMd('plain text'), null);
47
+ }],
48
+ ['parseAttachmentAnchorMd: 完整解析 ws/id/name', () => {
49
+ const ref = parseAttachmentAnchorMd(`前缀 [📎 需求说明.txt](attach:${WS}/${ID}) 后缀`);
50
+ assert.deepEqual(ref, { workspaceId: WS, id: ID, name: '需求说明.txt' });
51
+ }],
52
+ ['attachmentAnchorHtml: R6 定稿最小模板逐字段(含 size)', () => {
53
+ assert.equal(attachmentAnchorHtml({ workspaceId: WS, id: ID, name: '接口设计.pdf', size: 2048 }), `<a data-is-tapd-attachment="true" data-can-preview="true" data-file-type="pdf" ` +
54
+ `data-name="接口设计.pdf" data-size="2048" target="_blank" rel="noopener" ` +
55
+ `href="/${WS}/attachments/preview_attachments/${ID}/story_description_attachment">接口设计.pdf</a>`);
56
+ }],
57
+ ['attachmentAnchorHtml: size 省略不输出 data-size;fileType 按扩展名默认映射;slug 可覆盖', () => {
58
+ const html = attachmentAnchorHtml({ workspaceId: WS, id: ID, name: 'app.log' });
59
+ assert.ok(html.includes('data-file-type="other"'));
60
+ assert.ok(!html.includes('data-size'));
61
+ assert.ok(html.includes(`href="/${WS}/attachments/preview_attachments/${ID}/story_description_attachment"`));
62
+ const custom = attachmentAnchorHtml({ workspaceId: WS, id: ID, name: 'a.txt', fileType: 'text' }, { slug: 'bug_description_attachment' });
63
+ assert.ok(custom.includes('/bug_description_attachment">'));
64
+ assert.ok(custom.endsWith('>a.txt</a>'));
65
+ }],
66
+ ['attachmentAnchorHtml: 文件名 HTML 特殊字符转义', () => {
67
+ const html = attachmentAnchorHtml({ workspaceId: WS, id: ID, name: 'a"b&c.txt' });
68
+ assert.ok(html.includes('data-name="a&quot;b&amp;c.txt"'));
69
+ assert.ok(html.endsWith('>a&quot;b&amp;c.txt</a>') === false);
70
+ assert.ok(html.endsWith('>a"b&amp;c.txt</a>'));
71
+ }],
72
+ ['parseAttachmentAnchorHtml: 生成结果可逆解析', () => {
73
+ const html = attachmentAnchorHtml({ workspaceId: WS, id: ID, name: '接口设计.pdf', size: 2048 });
74
+ assert.deepEqual(parseAttachmentAnchorHtml(html), {
75
+ workspaceId: WS, id: ID, name: '接口设计.pdf', size: 2048, fileType: 'pdf',
76
+ });
77
+ }],
78
+ ['parseAttachmentAnchorHtml: 完整编辑器模板(inner spans/type/class)可识别', () => {
79
+ assert.deepEqual(parseAttachmentAnchorHtml(EDITOR_STYLE_ANCHOR), {
80
+ workspaceId: WS, id: '1139814312001000004', name: 'comment-embed.txt', size: 54, fileType: 'text',
81
+ });
82
+ assert.deepEqual(findAttachmentAnchors(`<p>前</p>${EDITOR_STYLE_ANCHOR}<p>后</p>`).length, 1);
83
+ }],
84
+ ['parseAttachmentAnchorHtml: 不认识的锚点 → null(裸 <a>/缺 data-name/缺 flag)', () => {
85
+ assert.equal(parseAttachmentAnchorHtml(`<a href="/${WS}/attachments/preview_attachments/${ID}/story_description_attachment">x.txt</a>`), null);
86
+ assert.equal(parseAttachmentAnchorHtml(`<a data-is-tapd-attachment="true" href="/${WS}/attachments/preview_attachments/${ID}/story_description_attachment">残缺</a>`), null);
87
+ assert.equal(parseAttachmentAnchorHtml(`<a data-can-preview="true" data-name="x.txt" href="/${WS}/attachments/preview_attachments/${ID}/story_description_attachment">无flag</a>`), null);
88
+ assert.equal(parseAttachmentAnchorHtml(`<a data-is-tapd-attachment="true" data-name="x.txt" href="https://elsewhere/x">外部链接</a>`), null);
89
+ }],
90
+ ['attachmentHtmlToMd: 锚点 → md 扩展语法;不认识锚点原样保留', () => {
91
+ const md = attachmentHtmlToMd(`<p>材料</p>${EDITOR_STYLE_ANCHOR}`);
92
+ assert.equal(md, `<p>材料</p>[📎 comment-embed.txt](attach:${WS}/1139814312001000004)`);
93
+ const bare = `<a href="/${WS}/attachments/preview_attachments/${ID}/story_description_attachment">残缺</a>`;
94
+ assert.equal(attachmentHtmlToMd(`<p>x</p>${bare}`), `<p>x</p>${bare}`);
95
+ const plain = '<p>普通 <a href="https://e.com">链接</a></p>';
96
+ assert.equal(attachmentHtmlToMd(plain), plain);
97
+ }],
98
+ ['attachmentMdToHtml: md → 锚点;非 attach 链接透传', () => {
99
+ const html = attachmentMdToHtml(`见 [📎 需求说明.txt](attach:${WS}/${ID})`);
100
+ assert.ok(html.startsWith('见 <a data-is-tapd-attachment="true"'));
101
+ assert.ok(html.includes('data-name="需求说明.txt"'));
102
+ assert.ok(html.endsWith(`>需求说明.txt</a>`));
103
+ const link = '参考 [标题](https://e.com/a)';
104
+ assert.equal(attachmentMdToHtml(link), link);
105
+ }],
106
+ ['attachmentMdToHtml: 多锚点与转义名可逆', () => {
107
+ const md = `[📎 a.txt](attach:${WS}/1139814312001000002) 中间 [📎 b.pdf](attach:${WS}/${ID})`;
108
+ const html = attachmentMdToHtml(md);
109
+ assert.equal(findAttachmentAnchors(html).length, 2);
110
+ assert.equal(attachmentHtmlToMd(html), md);
111
+ }],
112
+ ['节点辅助: isAttachmentAnchorNode / attachmentAnchorNodeToMd', () => {
113
+ const node = {
114
+ nodeName: 'A',
115
+ getAttribute: (name) => ({
116
+ 'data-is-tapd-attachment': 'true',
117
+ 'data-name': 'comment-embed.txt',
118
+ 'data-size': '54',
119
+ 'data-file-type': 'text',
120
+ href: `/${WS}/attachments/preview_attachments/1139814312001000004/story_description_attachment`,
121
+ })[name] ?? null,
122
+ };
123
+ assert.equal(isAttachmentAnchorNode(node), true);
124
+ assert.equal(attachmentAnchorNodeToMd(node), `[📎 comment-embed.txt](attach:${WS}/1139814312001000004)`);
125
+ const bare = { nodeName: 'A', getAttribute: () => null };
126
+ assert.equal(isAttachmentAnchorNode(bare), false);
127
+ assert.equal(attachmentAnchorNodeToMd(bare), null);
128
+ }],
129
+ ];
130
+ let failed = 0;
131
+ for (const [name, check] of checks) {
132
+ try {
133
+ check();
134
+ console.log(`PASS ${name}`);
135
+ }
136
+ catch (error) {
137
+ failed += 1;
138
+ console.error(`FAIL ${name}`);
139
+ console.error(` ${error instanceof Error ? error.message : String(error)}`);
140
+ }
141
+ }
142
+ if (failed > 0) {
143
+ console.error(`\n${failed}/${checks.length} failed`);
144
+ process.exitCode = 1;
145
+ }
146
+ else {
147
+ console.log(`\n${checks.length}/${checks.length} passed`);
148
+ }
149
+ //# sourceMappingURL=attachment-anchor.test.js.map