import { describe, expect, it } from 'vitest'
import { getMarkdown, parseMarkdownToStructure } from '../src'
describe('thinking custom tag after inline html prefix', () => {
const thinkingContent = String.raw`勾股定理是数学中一个非常重要的定理,尤其在几何学中有着广泛的应用。它描述了直角三角形三边之间的关系。
### 勾股定理的定义:
在**直角三角形**中,斜边(即与直角相对的边)的平方等于另外两条直角边的平方和。
用公式表示为:
$$
a^2 + b^2 = c^2
$$
其中:
- $ a $ 和 $ b $ 是直角三角形的两条直角边;
- $ c $ 是斜边(即最长的一条边)。
---
### 举例说明:
比如一个直角三角形,两条直角边分别是3和4,那么斜边 $ c $ 可以通过勾股定理计算得出:
$$
c = \sqrt{3^2 + 4^2} = \sqrt{9 + 16} = \sqrt{25} = 5
$$
所以这个三角形的三边是3、4、5,是一个经典的勾股数(毕达哥拉斯三元组)。
如果你有兴趣,我还可以为你提供勾股定理的几种不同证明方式,或者讲解一些有趣的勾股数例子!`
it('keeps the full thinking markdown inside the thinking node and does not leak trailing block nodes', () => {
const markdown = `
介绍下勾股定理
${thinkingContent}`
const tags = ['usrhead', 'aihead', 'thinking']
const md = getMarkdown('thinking-inline-prefix-regression', { customHtmlTags: tags })
const nodes = parseMarkdownToStructure(markdown, md, { customHtmlTags: tags, final: true }) as any[]
expect(nodes.map(node => node?.type)).toEqual(['paragraph', 'thinking'])
const prefix = nodes[0]
expect(prefix?.type).toBe('paragraph')
expect(prefix?.children?.map((node: any) => node?.type)).toEqual([
'usrhead',
'hardbreak',
'text',
'hardbreak',
'hardbreak',
'hardbreak',
'hardbreak',
'aihead',
])
expect(prefix?.children?.[2]?.content).toBe('介绍下勾股定理')
const thinking = nodes[1]
expect(thinking?.type).toBe('thinking')
expect(thinking?.content).toBe(thinkingContent)
expect(String(thinking?.raw ?? '')).toContain('')
expect(String(thinking?.raw ?? '')).toContain('')
expect(nodes.at(-1)?.type).toBe('thinking')
})
it('keeps streaming block markers inside thinking before arrives', () => {
const markdown = `
介绍下勾股定理
${thinkingContent}`
const tags = ['usrhead', 'aihead', 'thinking']
const md = getMarkdown('thinking-inline-prefix-streaming-regression', { customHtmlTags: tags })
const nodes = parseMarkdownToStructure(markdown, md, { customHtmlTags: tags, final: false }) as any[]
expect(nodes.map(node => node?.type)).toEqual(['paragraph', 'thinking'])
const thinking = nodes[1]
expect(thinking?.type).toBe('thinking')
expect(thinking?.loading).toBe(true)
expect(String(thinking?.content ?? '')).toContain('### 勾股定理的定义:')
expect(String(thinking?.content ?? '')).toContain('---')
expect(String(thinking?.content ?? '')).toContain('$$\nc = \\sqrt{3^2 + 4^2} = \\sqrt{9 + 16} = \\sqrt{25} = 5\n$$')
expect(nodes.at(-1)?.type).toBe('thinking')
const innerNodes = parseMarkdownToStructure(String(thinking?.content ?? ''), getMarkdown('thinking-inline-prefix-streaming-inner'))
expect(innerNodes.some(node => node?.type === 'heading')).toBe(true)
expect(innerNodes.some(node => node?.type === 'thematic_break')).toBe(true)
expect(innerNodes.some(node => node?.type === 'math_block')).toBe(true)
})
it('keeps a stable top-level thinking node from the first streaming chunk when the prefix contains
', () => {
const tags = ['usrhead', 'aihead', 'thinking']
const md = getMarkdown('thinking-inline-prefix-streaming-stability', { customHtmlTags: tags })
const chunks = [
'
介绍下勾股定理
第',
'
介绍下勾股定理
第一段',
'
介绍下勾股定理
第一段\n\n### 标题',
]
for (const chunk of chunks) {
const nodes = parseMarkdownToStructure(chunk, md, { customHtmlTags: tags, final: false }) as any[]
expect(nodes.map(node => node?.type)).toEqual(['paragraph', 'thinking'])
expect(nodes[0]?.children?.some((node: any) => node?.type === 'thinking')).toBe(false)
expect(nodes[1]?.type).toBe('thinking')
expect(nodes[1]?.loading).toBe(true)
}
})
it('keeps a stable top-level thinking node when the prefix is only
and the close arrives on the same line', () => {
const md = getMarkdown('thinking-br-prefix-same-line-stability', { customHtmlTags: ['thinking'] })
const openNodes = parseMarkdownToStructure('
hi', md, { customHtmlTags: ['thinking'], final: false }) as any[]
expect(openNodes.map(node => node?.type)).toEqual(['paragraph', 'thinking'])
expect(openNodes[0]?.children?.map((node: any) => node?.type)).toEqual(['hardbreak'])
expect(openNodes[1]?.type).toBe('thinking')
expect(openNodes[1]?.loading).toBe(true)
const closedNodes = parseMarkdownToStructure('
hi', md, { customHtmlTags: ['thinking'], final: true }) as any[]
expect(closedNodes.map(node => node?.type)).toEqual(['paragraph', 'thinking'])
expect(closedNodes[0]?.children?.map((node: any) => node?.type)).toEqual(['hardbreak'])
expect(closedNodes[1]?.type).toBe('thinking')
expect(closedNodes[1]?.loading).toBe(false)
})
})