import { describe, expect, it } from 'vitest'
import { clampHtmlNestingDepth } from './markdown-html-depth'
// The clamp exists to keep parse5 / hast-util-from-parse5 recursion off the
// call stack. Its contract is about DEPTH of unclosed elements, so the tests
// assert that relationship rather than any particular output string.
describe('clampHtmlNestingDepth', () => {
it('returns text without tags unchanged, by identity', () => {
const text = 'C:\\Windows\\System32 is 12 GB, and 5 < 7 is true'
expect(clampHtmlNestingDepth(text)).toBe(text)
})
it('leaves ordinary markup untouched, by identity', () => {
const text = '
'
expect(clampHtmlNestingDepth(text)).toBe(text)
})
it('leaves a wide but shallow tag run untouched — count is not the risk', () => {
const text = 'x'.repeat(20_000)
expect(clampHtmlNestingDepth(text)).toBe(text)
})
it('leaves void elements untouched — they never add depth', () => {
const text = '
'.repeat(20_000)
expect(clampHtmlNestingDepth(text)).toBe(text)
})
it('leaves self-closing tags untouched — they never add depth', () => {
const text = ''.repeat(20_000)
expect(clampHtmlNestingDepth(text)).toBe(text)
})
it('escapes an unbounded run of unclosed unknown tags', () => {
const clamped = clampHtmlNestingDepth('Let' + ''.repeat(16_383))
// Nothing is dropped: the text is still all there, just literal. Only the
// opening `<` needs escaping — that alone stops parse5 opening an element.
expect(clamped).toContain('<unk>')
expect(clamped.startsWith('Let')).toBe(true)
})
it('escapes an unbounded run of unclosed known tags', () => {
const clamped = clampHtmlNestingDepth(''.repeat(5_000))
expect(clamped).toContain('<div>')
})
it('keeps the prefix below the cap parseable and only escapes past it', () => {
const clamped = clampHtmlNestingDepth('
'.repeat(5_000))
const parseable = clamped.slice(0, clamped.indexOf('<'))
// Everything before the overflow point is untouched real markup...
expect(parseable).toBe(''.repeat(parseable.length / ''.length))
// ...and it is bounded, which is the entire point.
expect(parseable.length).toBeLessThan(''.repeat(5_000).length)
})
it('does not accumulate depth when tags close, however many there are', () => {
const text = 'x
'.repeat(10_000)
expect(clampHtmlNestingDepth(text)).toBe(text)
})
})