fix: strengthen type guard in countMarkdownHeadings to prevent TypeError on non-string input

Fixes #11605. The existing guard `if (!text)` only catches falsy values.
When a truthy non-string value (e.g. number or object from an API response)
is passed through OpenMarkdownPreviewButton, it passes the guard and
text.replace() throws "TypeError: n.replace is not a function".

Changed the guard to `typeof text !== "string"` so any non-string value
returns 0 early. Added test cases for non-string inputs.
This commit is contained in:
Roo Code 2026-02-19 14:57:54 +00:00
parent aff46b14e2
commit 0600b3f62a
2 changed files with 11 additions and 1 deletions

View file

@ -8,6 +8,16 @@ describe("markdown heading helpers", () => {
expect(countMarkdownHeadings("")).toBe(0)
})
it("returns 0 for non-string values", () => {
// These simulate runtime scenarios where a non-string truthy value
// is passed due to unexpected API data (see issue #11605)
expect(countMarkdownHeadings(42 as unknown as string)).toBe(0)
expect(countMarkdownHeadings({ key: "value" } as unknown as string)).toBe(0)
expect(countMarkdownHeadings(["# heading"] as unknown as string)).toBe(0)
expect(countMarkdownHeadings(true as unknown as string)).toBe(0)
expect(countMarkdownHeadings(null as unknown as string)).toBe(0)
})
it("counts single and multiple headings", () => {
expect(countMarkdownHeadings("# One")).toBe(1)
expect(countMarkdownHeadings("# One\nContent")).toBe(1)

View file

@ -4,7 +4,7 @@
* Code fences are stripped before matching to avoid false positives.
*/
export function countMarkdownHeadings(text: string | undefined): number {
if (!text) return 0
if (typeof text !== "string" || !text) return 0
// Remove fenced code blocks to avoid counting headings inside code
const withoutCodeBlocks = text.replace(/```[\s\S]*?```/g, "")