From 15e4fbf593339dda1a17c873cd0e5dafe9bfedab Mon Sep 17 00:00:00 2001 From: Terrance Chen Date: Sat, 13 Jun 2026 13:29:12 -0700 Subject: [PATCH] fix(markdown-core): treat infinity chunk limit as unbounded Fix render-aware markdown chunking so `Number.POSITIVE_INFINITY` is treated as an explicit unbounded chunk limit instead of falling back to `1`. This preserves full Signal media captions and disabled Signal text chunking while keeping invalid non-finite limits on the existing fallback path. Fixes #92734. Thanks @yhterrance for the report and fix. --- extensions/signal/src/format.chunking.test.ts | 10 ++++++++++ .../src/render-aware-chunking.test.ts | 14 ++++++++++++++ .../markdown-core/src/render-aware-chunking.ts | 7 +++++++ 3 files changed, 31 insertions(+) diff --git a/extensions/signal/src/format.chunking.test.ts b/extensions/signal/src/format.chunking.test.ts index 0b7e3123405d..cf729de5371f 100644 --- a/extensions/signal/src/format.chunking.test.ts +++ b/extensions/signal/src/format.chunking.test.ts @@ -296,6 +296,16 @@ describe("splitSignalFormattedText", () => { }); describe("markdownToSignalTextChunks", () => { + it("treats Infinity as unbounded for media captions", () => { + const markdown = "Here's **another** photo from today's walk."; + + const chunks = markdownToSignalTextChunks(markdown, Number.POSITIVE_INFINITY); + + expect(chunks).toHaveLength(1); + expect(chunks[0]?.text).toBe("Here's another photo from today's walk."); + expect(chunks[0]?.styles.map((style) => style.style)).toContain("BOLD"); + }); + describe("link expansion chunk limit", () => { it("does not exceed chunk limit after link expansion", () => { // Create text that is close to limit, with a link that will expand diff --git a/packages/markdown-core/src/render-aware-chunking.test.ts b/packages/markdown-core/src/render-aware-chunking.test.ts index 8913168a79e3..7bd4213e2770 100644 --- a/packages/markdown-core/src/render-aware-chunking.test.ts +++ b/packages/markdown-core/src/render-aware-chunking.test.ts @@ -84,4 +84,18 @@ describe("renderMarkdownIRChunksWithinLimit", () => { expect(chunks.map((chunk) => chunk.source.text)).toEqual(["a", "b", "c"]); expect(chunks.every((chunk) => chunk.rendered.length <= 1)).toBe(true); }); + + it("treats Infinity as no size cap and returns a single chunk", () => { + const text = "one two three four five six seven eight nine ten"; + const ir = markdownToIR(text); + const chunks = renderMarkdownIRChunksWithinLimit({ + ir, + limit: Number.POSITIVE_INFINITY, + renderChunk: renderEscapedHtml, + measureRendered: (rendered) => rendered.length, + }); + + expect(chunks).toHaveLength(1); + expect(chunks[0]?.source.text).toBe(text); + }); }); diff --git a/packages/markdown-core/src/render-aware-chunking.ts b/packages/markdown-core/src/render-aware-chunking.ts index db596671c19a..de045152e3ca 100644 --- a/packages/markdown-core/src/render-aware-chunking.ts +++ b/packages/markdown-core/src/render-aware-chunking.ts @@ -47,6 +47,13 @@ export function renderMarkdownIRChunksWithinLimit( return []; } + // Callers pass Infinity to mean "no size cap" (e.g. a media caption that must not be + // split). resolveIntegerOption rejects non-finite values and would fall back to 1, + // shattering the text into one chunk per character; emit the whole IR as one chunk. + if (options.limit === Number.POSITIVE_INFINITY) { + return [{ source: options.ir, rendered: options.renderChunk(options.ir) }]; + } + const normalizedLimit = resolveIntegerOption(options.limit, 1, { min: 1 }); const pending = chunkMarkdownIR(options.ir, normalizedLimit); const finalized: MarkdownIR[] = [];