


























@@ -160,75 +160,88 @@ describe("toSanitizedMarkdownHtml", () => {
160160161161it("keeps adjacent trailing CJK text outside www auto-links", () => {
162162const html = toSanitizedMarkdownHtml("www.example.com重新解读");
163-expect(html).toContain('<a href="http://www.example.com"');
164-expect(html).toContain("重新解读");
165-expect(html).not.toContain("重新解读</a>");
163+expect(html).toBe(
164+ '<p><a href="http://www.example.com" rel="noreferrer noopener" target="_blank">www.example.com</a>重新解读</p>\n',
165+);
166166});
167167168168it("keeps Japanese text outside www auto-links", () => {
169169const html = toSanitizedMarkdownHtml("www.example.comテスト");
170-expect(html).toContain('<a href="http://www.example.com"');
171-expect(html).toContain("テスト");
170+expect(html).toBe(
171+'<p><a href="http://www.example.com" rel="noreferrer noopener" target="_blank">www.example.com</a>テスト</p>\n',
172+);
172173});
173174});
174175175176describe("explicit protocol links", () => {
176177it("links https:// URLs", () => {
177178const html = toSanitizedMarkdownHtml("Visit https://example.com");
178-expect(html).toContain('<a href="https://example.com"');
179+expect(html).toBe(
180+'<p>Visit <a href="https://example.com" rel="noreferrer noopener" target="_blank">https://example.com</a></p>\n',
181+);
179182});
180183181184it("links http:// URLs", () => {
182185const html = toSanitizedMarkdownHtml("Visit http://github.com/openclaw");
183-expect(html).toContain('<a href="http://github.com/openclaw"');
186+expect(html).toBe(
187+'<p>Visit <a href="http://github.com/openclaw" rel="noreferrer noopener" target="_blank">http://github.com/openclaw</a></p>\n',
188+);
184189});
185190186191it("links email addresses", () => {
187192const html = toSanitizedMarkdownHtml("Email me at test@example.com");
188-expect(html).toContain('<a href="mailto:test@example.com"');
193+expect(html).toBe(
194+'<p>Email me at <a href="mailto:test@example.com" rel="noreferrer noopener" target="_blank">test@example.com</a></p>\n',
195+);
189196});
190197191198it("keeps adjacent trailing CJK text outside https:// auto-links", () => {
192199const html = toSanitizedMarkdownHtml("https://example.com重新解读");
193-expect(html).toContain('<a href="https://example.com"');
194-expect(html).toContain(">https://example.com</a>");
195-expect(html).toContain("重新解读");
200+expect(html).toBe(
201+ '<p><a href="https://example.com" rel="noreferrer noopener" target="_blank">https://example.com</a>重新解读</p>\n',
202+);
196203});
197204198205it("keeps CJK text outside https:// links with path", () => {
199206const html = toSanitizedMarkdownHtml("https://example.com/path重新解读");
200-expect(html).toContain('<a href="https://example.com/path"');
201-expect(html).toContain("重新解读");
207+expect(html).toBe(
208+'<p><a href="https://example.com/path" rel="noreferrer noopener" target="_blank">https://example.com/path</a>重新解读</p>\n',
209+);
202210});
203211204212it("preserves mid-URL CJK in https:// links", () => {
205213// CJK in the middle of a URL path (not trailing) must not be trimmed
206214const html = toSanitizedMarkdownHtml("https://example.com/你/test");
207-expect(html).toContain("你/test</a>");
208-expect(html).not.toContain("你/test</a>你");
215+expect(html).toBe(
216+'<p><a href="https://example.com/%E4%BD%A0/test" rel="noreferrer noopener" target="_blank">https://example.com/你/test</a></p>\n',
217+);
209218});
210219211220it("preserves percent-encoded CJK inside URLs when no raw CJK present", () => {
212221// Percent-encoded paths without raw CJK are preserved as-is
213222const html = toSanitizedMarkdownHtml("https://example.com/path/%E4%BD%A0%E5%A5%BD");
214-expect(html).toContain("<a href=");
223+expect(html).toBe(
224+'<p><a href="https://example.com/path/" rel="noreferrer noopener" target="_blank">https://example.com/path/</a>你好</p>\n',
225+);
215226// markdown-it linkify decodes percent-encoded CJK for display, then our
216227// CJK trim rule splits at the first raw CJK char. This is acceptable
217228// because raw percent-encoded CJK in chat is extremely rare.
218229});
219230220231it("does NOT rewrite explicit markdown links with CJK display text", () => {
221232const html = toSanitizedMarkdownHtml("[OpenClaw中文](https://docs.openclaw.ai)");
222-expect(html).toContain('href="https://docs.openclaw.ai"');
223-expect(html).toContain("OpenClaw中文</a>");
233+expect(html).toBe(
234+'<p><a href="https://docs.openclaw.ai" rel="noreferrer noopener" target="_blank">OpenClaw中文</a></p>\n',
235+);
224236});
225237226238it("preserves mailto: scheme when trimming CJK from email links", () => {
227239// Email followed by space+CJK — linkify recognizes the email,
228240// then CJK trim should preserve the mailto: prefix.
229241const html = toSanitizedMarkdownHtml("Contact test@example.com 中文说明");
230-expect(html).toContain('href="mailto:test@example.com"');
231-expect(html).toContain("test@example.com</a>");
242+expect(html).toBe(
243+'<p>Contact <a href="mailto:test@example.com" rel="noreferrer noopener" target="_blank">test@example.com</a> 中文说明</p>\n',
244+);
232245});
233246});
234247此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。