import { getMarkdown, parseMarkdownToStructure } from 'stream-markdown-parser'
import { describe, expect, it } from 'vitest'
function expectDetailsContainer(markdown: string, name: string) {
for (const final of [false, true]) {
const md = getMarkdown(`${name}-${final}`)
const nodes = parseMarkdownToStructure(markdown, md, { final }) as any[]
expect(nodes).toHaveLength(1)
expect(nodes[0]?.type).toBe('html_block')
expect(nodes[0]?.tag).toBe('details')
expect(String(nodes[0]?.raw ?? '')).toBe(markdown)
}
}
describe('html block details regression', () => {
it('keeps details as one container node while rendering trailing blocks into html children content', () => {
const markdown = ` Thinking...
好的,我需要帮用户生成首次病程记录。首先得仔细阅读提供的入院记录内容,确保所有信息都被正确提取。这里是详情
首先。。。。
首先。。。。
') expect(details?.attrs).toEqual([ ['style', 'color:gray;background-color: #f8f8f8;padding: 8px;border-radius: 4px;'], ['open', ''], ]) expect(details?.children).toHaveLength(3) expect(summary?.type).toBe('html_block') expect(summary?.tag).toBe('summary') expect(summary?.attrs).toBeUndefined() expect(summary?.children?.[0]?.type).toBe('paragraph') expect(summary?.children?.[0]?.children?.[0]?.content).toContain('Thinking') expect(introParagraph?.type).toBe('paragraph') expect(introParagraph?.children?.[0]?.content).toContain('这里是详情') expect(details?.children?.[2]?.type).toBe('paragraph') expect(details?.children?.[2]?.children?.[0]?.content).toBe('首先。。。。') }) it('keeps the blank line paragraph inside details while streaming before the closing tag arrives', () => { const chunks = [ `首先。。。。
') expect(nodes[0]?.children?.[0]?.tag).toBe('summary') expect(nodes[0]?.children?.[1]?.type).toBe('paragraph') expect(nodes[0]?.children?.[2]?.type).toBe('paragraph') } else { expect(String(nodes[0]?.content ?? '')).not.toContain('首先。。。。
') expect(nodes[0]?.children?.[0]?.tag).toBe('summary') expect(nodes[0]?.children?.[1]?.type).toBe('paragraph') expect(nodes[0]?.children ?? []).toHaveLength(2) } } if (final) { expect(nodes[0]?.loading).toBe(false) expect(String(nodes[0]?.content ?? '')).toContain('首先。。。。
') expect(String(nodes[0]?.raw ?? '')).toBe(markdown) } } }) it('keeps nested details blocks grouped under the outer details container', () => { const markdown = `inner body
') expect(trailingParagraph?.children?.[0]?.content).toBe('after inner') }) it('keeps complex markdown children inside details and preserves the trailing closing newline', () => { const markdown = `') expect(String(details?.content ?? '')).toContain('data-lang="js"') expect(String(details?.content ?? '')).toContain('tail
') expect(details?.children?.map((child: any) => child?.type === 'html_block' ? `${child?.type}:${child?.tag}` : child?.type)) .toEqual(['html_block:summary', 'list', 'blockquote', 'code_block', 'paragraph']) }) it('parses markdown inside summary into summary children', () => { const markdown = `` const md = getMarkdown('html-block-details-summary-markdown') const nodes = parseMarkdownToStructure(markdown, md, { final: true }) as any[] const details = nodes[0] const summary = details?.children?.[0] const summaryParagraph = summary?.children?.[0] expect(nodes).toHaveLength(1) expect(details?.tag).toBe('details') expect(summary?.tag).toBe('summary') expect(details?.attrs).toEqual([['open', '']]) expect(summaryParagraph?.type).toBe('paragraph') expect(summaryParagraph?.children?.[0]?.type).toBe('strong') expect(summaryParagraph?.children?.[0]?.children?.[0]?.content).toBe('sum') expect(summaryParagraph?.children?.[2]?.type).toBe('emphasis') expect(summaryParagraph?.children?.[2]?.children?.[0]?.content).toBe('x') expect(details?.children?.[1]?.children?.[0]?.content).toBe('body') }) it('keeps opener content before and after summary as structured children', () => { const markdown = `**sum** _x_
bodylead` const md = getMarkdown('html-block-details-opener-mixed') const nodes = parseMarkdownToStructure(markdown, md, { final: true }) as any[] const details = nodes[0] expect(nodes).toHaveLength(1) expect(details?.tag).toBe('details') expect(details?.attrs).toEqual([['open', '']]) expect(details?.children?.map((child: any) => child?.type === 'html_block' ? `${child?.type}:${child?.tag}` : child?.type)) .toEqual(['paragraph', 'html_block:summary', 'paragraph', 'html_block:div', 'paragraph']) expect(details?.children?.[0]?.children?.[0]?.content).toBe('lead') expect(details?.children?.[1]?.children?.[0]?.children?.[0]?.content).toBe('sum') expect(details?.children?.[2]?.children?.[0]?.content).toBe('text') expect(details?.children?.[3]?.tag).toBe('div') expect(details?.children?.[4]?.children?.[0]?.content).toBe('para') }) })sum
textinnerpara