From 2996ee9afd5c5680165f725a107074abba8ffa56 Mon Sep 17 00:00:00 2001 From: Bryce Kwon Date: Fri, 16 Oct 2026 17:59:29 -1000 Subject: Run a paragraph's lines together like GitHub GitHub shows a single newline in a markdown file as a space, and roff fills the lines of a man page the same way, so text wrapped in the source came out ragged on the about page. --- custom/extensions/about-render.lua | 43 +++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 10 deletions(-) (limited to 'custom') 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("
") elseif kind == "code" then html(""); html_txt(node.text); html("") elseif kind == "strong" then @@ -255,7 +257,7 @@ emit_blocks = function(blocks) html("

") for i, line in ipairs(block.lines) do if i > 1 then - html("
") + 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 -- cgit