-- SPDX-FileCopyrightText: © 2026 Vladimir Zorin -- SPDX-License-Identifier: OWL-1.0 or later -- Licensed under the Open Weights License v1.0. See LICENSE for details. local testimony = require("testimony") local from_html = require("markdown.from_html") local testify = testimony.new("== markdown.from_html ==") testify:that("bare (HTML4 void) does not swallow following content", function() -- The netmeister.org bug: a void with no closing slash -- caused strip_block to drop everything from to EOF. local html = [[

Header

Article Title

This paragraph must survive the void input element above it.

And so must this one — there is enough body content to clear the MIN_ARTICLE_BYTES threshold so the body fallback is exercised.

]] local out = from_html.extract(html) testimony.assert_match("Article Title", out) testimony.assert_match("must survive", out) testimony.assert_match("MIN_ARTICLE_BYTES threshold", out) end) testify:that("bare (void) does not swallow following content", function() local html = [[

Before the embed tag, with enough text to push the document past the article-root minimum byte threshold so the body fallback kicks in and we exercise strip_block on the void element.

After Embed

This text comes after the void embed and must not be lost.

]] local out = from_html.extract(html) testimony.assert_match("After Embed", out) testimony.assert_match("must not be lost", out) end) testify:that("XHTML self-closing still works (regression)", function() local html = [[

Lead paragraph long enough to push past the minimum article body threshold so strip_block runs over the body content as expected.

Trailing Heading

Trailing prose that must survive across the self-closing input.

]] local out = from_html.extract(html) testimony.assert_match("Trailing Heading", out) testimony.assert_match("must survive", out) end) testify:that("unclosed
still drops to EOF (conservative behavior preserved)", function() -- For non-void STRIP_TAGS entries, an unclosed opener is treated as -- malformed and we discard everything from the opener to EOF — this -- prevents a stray sidebar/widget wrapper from leaking into the -- article. This test pins that behavior so the void-element fix -- doesn't accidentally relax it. local html = [[

Article text that should be preserved, with enough length to clear the article-root body threshold so we can observe the strip_block behavior on the form element below.

This should be discarded along with the unclosed form wrapper.

]] local out = from_html.extract(html) testimony.assert_match("should be preserved", out) -- The leaked form contents must NOT survive. testimony.assert_equal(nil, out:find("should be discarded", 1, true)) end) testify:that("netmeister-style HTML 4.01 page renders article body", function() -- Trimmed reproduction of the netmeister.org dns-tcpdump.html -- structure: uppercase HTML 4.01 tags, void before the -- article heading, article body wrapped in
. local html = [[ DNS tcpdump by example

Signs of Triviality

Opinions, mostly my own, on the importance of being and other things.
[homepage]

DNS tcpdump by example

April 6th, 2018

For my class on System Administration, I often use a homework assignment requiring students to capture and analyze tcpdump output to help them understand how the DNS works in detail.

# tcpdump -w /tmp/dns.pcap -i xennet0 port not 22

This is the closing paragraph.

]] local out = from_html.extract(html) -- The article-specific heading must appear (it sits AFTER the ). testimony.assert_match("DNS tcpdump by example", out) -- Body prose from inside
must appear. testimony.assert_match("System Administration", out) testimony.assert_match("closing paragraph", out) -- The
 command example must be preserved as a fenced code block.
	testimony.assert_match("tcpdump %-w /tmp/dns.pcap", out)
end)

testify:conclude()