libs/markdown-test.lua
1-- markdown-test.lua
2-- Unit tests for libs/markdown.lua (Issue 10-055). Pure string-in/string-out, so
3-- this runs standalone with no project setup and never touches output/. Run:
4-- luajit libs/markdown-test.lua
5-- Each case asserts that a Markdown snippet renders to HTML containing the
6-- expected fragment(s); failures print the actual HTML so the gap is obvious.
7
8-- {{{ setup_dir_path()
9local function setup_dir_path(provided)
10 if provided then return provided end
11 return "/mnt/mtwo/programming/ai-stuff/neocities-modernization"
12end
13-- }}}
14
15local DIR = setup_dir_path(arg and arg[1])
16package.path = DIR .. "/libs/?.lua;" .. package.path
17local md = require("markdown")
18
19local passed, failed = 0, 0
20
21-- {{{ local function check()
22-- Render `src` and assert every fragment in `wants` appears in the output.
23local function check(name, src, wants)
24 local html = md.render(src)
25 local missing = {}
26 for _, want in ipairs(wants) do
27 if not html:find(want, 1, true) then missing[#missing + 1] = want end
28 end
29 if #missing == 0 then
30 passed = passed + 1
31 print(" ok " .. name)
32 else
33 failed = failed + 1
34 print("FAIL " .. name)
35 for _, m in ipairs(missing) do print(" missing: " .. m) end
36 print(" got: " .. html)
37 end
38end
39-- }}}
40
41-- {{{ local function check_absent()
42-- Render `src` and assert none of the fragments in `nots` appear (used to prove
43-- markup inside code is NOT re-interpreted).
44local function check_absent(name, src, nots)
45 local html = md.render(src)
46 local present = {}
47 for _, no in ipairs(nots) do
48 if html:find(no, 1, true) then present[#present + 1] = no end
49 end
50 if #present == 0 then
51 passed = passed + 1
52 print(" ok " .. name)
53 else
54 failed = failed + 1
55 print("FAIL " .. name)
56 for _, p in ipairs(present) do print(" should be absent: " .. p) end
57 print(" got: " .. html)
58 end
59end
60-- }}}
61
62print("markdown renderer tests")
63
64check("h1", "# Title", { "<h1>Title</h1>" })
65check("h3", "### Three", { "<h3>Three</h3>" })
66check("bold", "a **bold** word", { "<strong>bold</strong>" })
67check("italic star", "a *slanted* word", { "<em>slanted</em>" })
68check("italic underscore", "an _emphatic_ word", { "<em>emphatic</em>" })
69check("snake_case survives", "a snake_case_name here", { "snake_case_name" })
70check("inline code", "use `luajit -b` here", { "<code>luajit -b</code>" })
71check("link", "see [the docs](https://example.com/x)", {
72 '<a href="https://example.com/x">the docs</a>' })
73check("image", "", { '<img src="cat.png" alt="a cat">' })
74check("unordered list", "- one\n- two", { "<ul>", "<li>one</li>", "<li>two</li>", "</ul>" })
75check("ordered list", "1. first\n2. second", { "<ol>", "<li>first</li>", "<li>second</li>" })
76check("blockquote", "> quoted line", { "<blockquote>", "quoted line", "</blockquote>" })
77check("hr", "above\n\n---\n\nbelow", { "<hr>" })
78check("paragraph", "just a sentence.", { "<p>just a sentence.</p>" })
79check("fenced code", "```lua\nlocal x = 1\n```", {
80 '<pre><code class="lang-lua">', "local x = 1", "</code></pre>" })
81check("table", "| A | B |\n|---|---|\n| 1 | 2 |", {
82 "<table>", "<th>A</th>", "<th>B</th>", "<td>1</td>", "<td>2</td>", "</table>" })
83check("escaping", "a < b & c > d", { "a < b & c > d" })
84check("table alignment colons", "| L | R |\n|:--|--:|\n| a | b |", { "<th>L</th>", "<td>a</td>" })
85
86-- Markup inside code/fences must NOT be reinterpreted.
87check_absent("no emphasis in inline code", "`a*b*c`", { "<em>" })
88check_absent("no emphasis in fence", "```\nx = a*b*c\n```", { "<em>" })
89check_absent("html in code escaped", "`<script>`", { "<script>" })
90
91print(string.format("\n%d passed, %d failed", passed, failed))
92os.exit(failed == 0 and 0 or 1)
93