diff options
| -rw-r--r-- | custom/extensions/about-render.lua | 19 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | tests/extensions/test-about-render.lua | 9 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2 files changed, 26 insertions, 2 deletions
diff --git a/custom/extensions/about-render.lua b/custom/extensions/about-render.lua index 3c92252..4e4b50b 100644 --- a/custom/extensions/about-render.lua +++ b/custom/extensions/about-render.lua @@ -157,7 +157,8 @@ end -- The page renders untrusted repository content. Every run of text goes out -- through cgit's html_txt, every attribute value through html_attr or, for a -- path in the tree, html_url_path, and every link target through safe_url --- first. html() only ever gets literal tag scaffolding. +-- first. html() only ever gets literal tag scaffolding and the character +-- references whose shape the markdown grammar checked. local emit_inline @@ -166,6 +167,8 @@ emit_inline = function(list) local kind = node.kind if kind == "text" then html_txt(node.text) + elseif kind == "reference" then + html(node.text) elseif kind == "break" then html("<br>") elseif kind == "code" then @@ -294,7 +297,7 @@ if has_lpeg then local whitespace = S(" \t\r\n\f\v") local eol = P(-1) - local marker = S("`![*_<\\") + local marker = S("`![*_<\\&") local punctuation = S("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~") local url_char = 1 - S(")") - whitespace -- Bound the link and image inner scans. Without a cap a readme of @@ -323,6 +326,9 @@ if has_lpeg then local function node_image() return { kind = "image" } end + local function node_reference(text) + return { kind = "reference", text = text } + end local function node_autolink(url) return { kind = "link", kids = { node_text(url) }, url = url } end @@ -339,6 +345,14 @@ if has_lpeg then local address = (alnum + S(".!#$%&'*+/=?^_`{|}~-")) ^ 1 * P("@") * alnum * (alnum + S(".-")) ^ 0 + -- A character reference passes through for the browser to decode, + -- within CommonMark's lengths. Its shape leaves no room for markup, and + -- a name the browser does not know shows as written. + local digit, hex = R("09"), R("09", "af", "AF") + local reference = P("&") * (R("az", "AZ") * alnum ^ -31 + + P("#") * digit * digit ^ -6 + + P("#") * S("xX") * hex * hex ^ -5) * P(";") + local label = P("[") * C((1 - P("]")) ^ (-max_scan)) * P("]") local target = P("(") * space ^ 0 * C(url_char * url_char ^ (-max_scan)) * (1 - P(")")) ^ (-max_scan) * P(")") @@ -349,6 +363,7 @@ if has_lpeg then local inline_grammar = Ct(( (P("`") * C((1 - P("`")) ^ 1) * P("`")) / node_code + (P("\\") * C(punctuation)) / node_text + + C(reference) / node_reference + (P("<") * C(uri) * P(">")) / node_autolink + (P("<") * C(address) * P(">")) / node_mail + (P("[!") * label * target * P("]") * target) / node_image diff --git a/tests/extensions/test-about-render.lua b/tests/extensions/test-about-render.lua index 236c61a..e84c854 100644 --- a/tests/extensions/test-about-render.lua +++ b/tests/extensions/test-about-render.lua @@ -117,6 +117,15 @@ h.contains("an escaped hash starts no heading", out, "<p># not a heading</p>") out = render("README.md", "`a\\*b`") h.contains("code keeps its backslashes", out, "<code>a\\*b</code>") +out = render("README.md", "© © © &") +h.contains("character references pass through", out, "<p>© © © &</p>") + +out = render("README.md", "AT&T & &#xZZ; �") +h.contains("a bare ampersand is escaped", out, "<p>AT&T & &#xZZ; &#12345678;</p>") + +out = render("README.md", "`&`") +h.contains("code shows a reference as written", out, "<code>&amp;</code>") + out = render("README.md", "run `x < y` here") h.contains("inline code is escaped", out, "<code>x < y</code>") |
