diff options
| -rw-r--r-- | custom/extensions/about-render.lua | 43 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | tests/extensions/test-about-render.lua | 13 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2 files changed, 43 insertions, 13 deletions
diff --git a/custom/extensions/about-render.lua b/custom/extensions/about-render.lua index 9d5f72d..af18d1b 100644 --- a/custom/extensions/about-render.lua +++ b/custom/extensions/about-render.lua @@ -166,6 +166,8 @@ emit_inline = function(list) local kind = node.kind if kind == "text" then html_txt(node.text) + elseif kind == "break" then + html("<br>") elseif kind == "code" then html("<code>"); html_txt(node.text); html("</code>") elseif kind == "strong" then @@ -255,7 +257,7 @@ emit_blocks = function(blocks) html("<p>") for i, line in ipairs(block.lines) do if i > 1 then - html("<br>") + html("\n") end emit_inline(line) end @@ -274,7 +276,7 @@ end -- Markdown is a deliberate subset rather than CommonMark, leaving out -- reference links, raw HTML passthrough, nested lists and setext headings, --- and emphasis does not span a hard line break. Man rendering covers the +-- and inline markup does not span the end of a line. Man rendering covers the -- common macros and drops the rest. Both parse into a node tree before -- anything is emitted, so a failed parse falls back to plain text without -- leaving half a page behind. @@ -375,6 +377,28 @@ if has_lpeg then local function ordered(mark) return mark:match("%d") ~= nil end + -- A paragraph's lines run together the way GitHub shows them, unless one + -- ends in two spaces or a backslash, which breaks the line there. The + -- last line of a paragraph has nothing to break before. + local function paragraph_lines(raw) + local lines = {} + for i, line in ipairs(raw) do + local hard = false + if i < #raw then + if line:sub(-1) == "\\" then + line, hard = line:sub(1, -2), true + else + hard = line:sub(-2) == " " + end + end + lines[i] = parse_inline(trim(line)) + if hard then + lines[i][#lines[i] + 1] = { kind = "break" } + end + end + return lines + end + local parse_blocks parse_blocks = function(lines, depth) @@ -426,13 +450,9 @@ if has_lpeg then blocks = parse_blocks(inner, depth + 1), } else - local paragraph = {} - for _, quoted in ipairs(inner) do - paragraph[#paragraph + 1] = parse_inline(quoted) - end blocks[#blocks + 1] = { kind = "para", - lines = paragraph, + lines = paragraph_lines(inner), } end elseif i + 1 <= n and line:find("|", 1, true) and table_delimiter:match(lines[i + 1]) then @@ -472,13 +492,16 @@ if has_lpeg then items = items, } else - local paragraph = { parse_inline(line) } + local paragraph = { line } i = i + 1 while i <= n and not lines[i]:match("^%s*$") and not block_start:match(lines[i]) do - paragraph[#paragraph + 1] = parse_inline(lines[i]) + paragraph[#paragraph + 1] = lines[i] i = i + 1 end - blocks[#blocks + 1] = { kind = "para", lines = paragraph } + blocks[#blocks + 1] = { + kind = "para", + lines = paragraph_lines(paragraph), + } end end return blocks diff --git a/tests/extensions/test-about-render.lua b/tests/extensions/test-about-render.lua index 801cc45..b7d12c7 100644 --- a/tests/extensions/test-about-render.lua +++ b/tests/extensions/test-about-render.lua @@ -88,10 +88,17 @@ out = render("readme.markdown", "# Long") h.contains("the long markdown extension dispatches too", out, "<h1>Long</h1>") out = render("README.md", "line one\nline two") -h.contains("a paragraph keeps its line break", out, "<p>line one<br>line two</p>") +h.contains("the lines of a paragraph run together", out, "<p>line one\nline two</p>") out = render("README.md", "first para\r\nsecond line") -h.contains("crlf line endings are normalised", out, "<p>first para<br>second line</p>") +h.contains("crlf line endings are normalised", out, "<p>first para\nsecond line</p>") + +out = render("README.md", "one \ntwo\\\nthree") +h.contains("two trailing spaces break the line", out, "<p>one<br>\ntwo") +h.contains("a trailing backslash breaks the line", out, "two<br>\nthree</p>") + +out = render("README.md", "spaces \n\nslash\\") +h.contains("the last line takes no break", out, "<p>spaces</p><p>slash\\</p>") out = render("README.md", "a **bold** and *leaning* word") h.contains("double stars embolden", out, "<strong>bold</strong>") @@ -239,7 +246,7 @@ out = render("page.3", ".SS Details") h.contains("a subsection renders one level down", out, "<h3>Details</h3>") out = render("page.1", ".B bold words\nplain after") -h.contains("the bold macro renders strong", out, "<p><strong>bold words</strong><br>plain after</p>") +h.contains("the bold macro renders strong", out, "<p><strong>bold words</strong>\nplain after</p>") out = render("page.1", "a \\fBbold\\fR c") h.contains("font escapes carry across a run", out, "<p>a <strong>bold</strong> c</p>") |
