惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
DataBreaches.Net
N
Netflix TechBlog - Medium
F
Fortinet All Blogs
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
宝玉的分享
宝玉的分享
Y
Y Combinator Blog
博客园 - 聂微东
WordPress大学
WordPress大学
酷 壳 – CoolShell
酷 壳 – CoolShell
B
Blog RSS Feed
小众软件
小众软件
The GitHub Blog
The GitHub Blog
S
SegmentFault 最新的问题
Hugging Face - Blog
Hugging Face - Blog
Jina AI
Jina AI
Microsoft Azure Blog
Microsoft Azure Blog
V
V2EX
B
Blog
H
Help Net Security
D
Docker
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
罗磊的独立博客
月光博客
月光博客
博客园 - 司徒正美

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
test: drop duplicate markdown cases · openclaw/openclaw@f...
steipete · 2026-04-18 · via Recent Commits to openclaw:main

@@ -3,11 +3,6 @@ import { md, toSanitizedMarkdownHtml } from "./markdown.ts";

3344

describe("toSanitizedMarkdownHtml", () => {

55

// ── Original tests from before markdown-it migration ──

6-

it("renders basic markdown", () => {

7-

const html = toSanitizedMarkdownHtml("Hello **world**");

8-

expect(html).toContain("<strong>world</strong>");

9-

});

10-116

it("strips scripts and unsafe links", () => {

127

const html = toSanitizedMarkdownHtml(

138

[

@@ -23,146 +18,6 @@ describe("toSanitizedMarkdownHtml", () => {

2318

expect(html).toContain("https://example.com");

2419

});

252026-

it("renders fenced code blocks", () => {

27-

const html = toSanitizedMarkdownHtml(["```ts", "console.log(1)", "```"].join("\n"));

28-

expect(html).toContain("<pre>");

29-

expect(html).toContain("<code");

30-

expect(html).toContain("console.log(1)");

31-

});

32-33-

it("flattens remote markdown images into alt text", () => {

34-

const html = toSanitizedMarkdownHtml("![Alt text](https://example.com/image.png)");

35-

expect(html).not.toContain("<img");

36-

expect(html).toContain("Alt text");

37-

});

38-39-

it("preserves base64 data URI images (#15437)", () => {

40-

const html = toSanitizedMarkdownHtml("![Chart](data:image/png;base64,iVBORw0KGgo=)");

41-

expect(html).toContain("<img");

42-

expect(html).toContain('class="markdown-inline-image"');

43-

expect(html).toContain("data:image/png;base64,");

44-

});

45-46-

it("flattens non-data markdown image urls", () => {

47-

const html = toSanitizedMarkdownHtml("![X](javascript:alert(1))");

48-

expect(html).not.toContain("<img");

49-

expect(html).not.toContain("javascript:");

50-

expect(html).toContain("X");

51-

});

52-53-

it("uses a plain fallback label for unlabeled markdown images", () => {

54-

const html = toSanitizedMarkdownHtml("![](https://example.com/image.png)");

55-

expect(html).not.toContain("<img");

56-

expect(html).toContain("image");

57-

});

58-59-

it("renders GFM markdown tables (#20410)", () => {

60-

const md = [

61-

"| Feature | Status |",

62-

"|---------|--------|",

63-

"| Tables | ✅ |",

64-

"| Borders | ✅ |",

65-

].join("\n");

66-

const html = toSanitizedMarkdownHtml(md);

67-

expect(html).toContain("<table");

68-

expect(html).toContain("<thead");

69-

expect(html).toContain("<th>");

70-

expect(html).toContain("Feature");

71-

expect(html).toContain("Tables");

72-

expect(html).not.toContain("|---------|");

73-

});

74-75-

it("renders GFM tables surrounded by text (#20410)", () => {

76-

const md = [

77-

"Text before.",

78-

"",

79-

"| Col1 | Col2 |",

80-

"|------|------|",

81-

"| A | B |",

82-

"",

83-

"Text after.",

84-

].join("\n");

85-

const html = toSanitizedMarkdownHtml(md);

86-

expect(html).toContain("<table");

87-

expect(html).toContain("Col1");

88-

expect(html).toContain("Col2");

89-

// Pipes from table delimiters must not appear as raw text

90-

expect(html).not.toContain("|------|");

91-

});

92-93-

it("does not throw on deeply nested emphasis markers (#36213)", () => {

94-

// Pathological patterns that can trigger catastrophic backtracking / recursion

95-

const nested = "*".repeat(500) + "text" + "*".repeat(500);

96-

expect(() => toSanitizedMarkdownHtml(nested)).not.toThrow();

97-

const html = toSanitizedMarkdownHtml(nested);

98-

expect(html).toContain("text");

99-

});

100-101-

it("does not throw on deeply nested brackets (#36213)", () => {

102-

const nested = "[".repeat(200) + "link" + "]".repeat(200) + "(" + "x".repeat(200) + ")";

103-

expect(() => toSanitizedMarkdownHtml(nested)).not.toThrow();

104-

const html = toSanitizedMarkdownHtml(nested);

105-

expect(html).toContain("link");

106-

});

107-108-

it("keeps oversized plain-text replies readable instead of forcing code-block chrome", () => {

109-

const input =

110-

Array.from(

111-

{ length: 320 },

112-

(_, i) => `Paragraph ${i + 1}: ${"Long plain-text reply. ".repeat(8)}`,

113-

).join("\n\n") + "\n";

114-115-

const html = toSanitizedMarkdownHtml(input);

116-117-

expect(html).not.toContain('<pre class="code-block">');

118-

expect(html).toContain('class="markdown-plain-text-fallback"');

119-

expect(html).toContain("Paragraph 1:");

120-

expect(html).toContain("Paragraph 320:");

121-

});

122-123-

it("preserves indentation in oversized plain-text replies", () => {

124-

const input = `${"Header line\n".repeat(5000)}\n indented log line\n deeper indent`;

125-

const html = toSanitizedMarkdownHtml(input);

126-127-

expect(html).toContain('class="markdown-plain-text-fallback"');

128-

expect(html).toContain(" indented log line");

129-

expect(html).toContain(" deeper indent");

130-

});

131-132-

it("exercises the cached oversized fallback branch", () => {

133-

const input =

134-

Array.from(

135-

{ length: 240 },

136-

(_, i) => `Paragraph ${i + 1}: ${"Cacheable long reply. ".repeat(8)}`,

137-

).join("\n\n") + "\n";

138-139-

expect(input.length).toBeGreaterThan(40_000);

140-

expect(input.length).toBeLessThan(50_000);

141-142-

const first = toSanitizedMarkdownHtml(input);

143-

const second = toSanitizedMarkdownHtml(input);

144-145-

expect(first).toContain('class="markdown-plain-text-fallback"');

146-

expect(second).toBe(first);

147-

});

148-149-

it("falls back to escaped plain text if md.render throws (#36213)", () => {

150-

const renderSpy = vi.spyOn(md, "render").mockImplementation(() => {

151-

throw new Error("forced render failure");

152-

});

153-

const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});

154-

const input = `Fallback **probe** ${Date.now()}`;

155-

try {

156-

const html = toSanitizedMarkdownHtml(input);

157-

expect(html).toContain('<pre class="code-block">');

158-

expect(html).toContain("Fallback **probe**");

159-

expect(warnSpy).toHaveBeenCalledOnce();

160-

} finally {

161-

renderSpy.mockRestore();

162-

warnSpy.mockRestore();

163-

}

164-

});

165-16621

// ── Additional tests for markdown-it migration ──

16722

describe("www autolinks", () => {

16823

it("links www.example.com", () => {

@@ -474,11 +329,22 @@ describe("toSanitizedMarkdownHtml", () => {

474329

expect(html).toContain("<s>deleted</s>");

475330

});

476331477-

it("renders tables", () => {

478-

const md = "| A | B |\n|---|---|\n| 1 | 2 |";

332+

it("renders tables surrounded by text", () => {

333+

const md = [

334+

"Text before.",

335+

"",

336+

"| A | B |",

337+

"|---|---|",

338+

"| 1 | 2 |",

339+

"",

340+

"Text after.",

341+

].join("\n");

479342

const html = toSanitizedMarkdownHtml(md);

480343

expect(html).toContain("<table");

481344

expect(html).toContain("<th>");

345+

expect(html).toContain("Text before.");

346+

expect(html).toContain("Text after.");

347+

expect(html).not.toContain("|---|");

482348

});

483349484350

it("renders basic markdown", () => {

@@ -617,9 +483,12 @@ describe("toSanitizedMarkdownHtml", () => {

617483

});

618484619485

it("caches oversized fallback results", () => {

620-

const input = Array.from({ length: 240 }, (_, i) => `P${i}`).join("\n\n") + "x".repeat(35000);

486+

const input =

487+

Array.from({ length: 240 }, (_, i) => `P${i}`).join("\n\n") + "x".repeat(45_000);

621488

const first = toSanitizedMarkdownHtml(input);

622489

const second = toSanitizedMarkdownHtml(input);

490+

expect(input.length).toBeGreaterThan(40_000);

491+

expect(first).toContain('class="markdown-plain-text-fallback"');

623492

expect(second).toBe(first);

624493

});

625494