diff options
| -rw-r--r-- | custom/extensions/about-render.lua | 19 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | tests/extensions/test-about-render.lua | 8 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2 files changed, 26 insertions, 1 deletion
diff --git a/custom/extensions/about-render.lua b/custom/extensions/about-render.lua index cc0892f..1543795 100644 --- a/custom/extensions/about-render.lua +++ b/custom/extensions/about-render.lua @@ -294,7 +294,7 @@ if has_lpeg then local whitespace = S(" \t\r\n\f\v") local eol = P(-1) - local marker = S("`![*_") + local marker = S("`![*_<") local url_char = 1 - S(")") - whitespace -- Bound the link and image inner scans. Without a cap a readme of -- unclosed brackets ("[[[[...") makes every position scan to the @@ -322,6 +322,21 @@ if has_lpeg then local function node_image() return { kind = "image" } end + local function node_autolink(url) + return { kind = "link", kids = { node_text(url) }, url = url } + end + local function node_mail(address) + return { kind = "link", kids = { node_text(address) }, url = "mailto:" .. address } + end + + -- CommonMark's autolinks, an absolute url or an address between angle + -- brackets. Anything else in brackets stays escaped text. + local alnum = R("az", "AZ", "09") + local scheme_char = alnum + S("+.-") + local uri = R("az", "AZ") * scheme_char * scheme_char ^ -30 * P(":") + * (1 - S("<>") - R("\0 ") - P("\127")) ^ 0 + local address = (alnum + S(".!#$%&'*+/=?^_`{|}~-")) ^ 1 + * P("@") * alnum * (alnum + S(".-")) ^ 0 local label = P("[") * C((1 - P("]")) ^ (-max_scan)) * P("]") local target = P("(") * space ^ 0 * C(url_char * url_char ^ (-max_scan)) @@ -332,6 +347,8 @@ if has_lpeg then -- a remote one would have every visitor's browser call a third party. local inline_grammar = Ct(( (P("`") * C((1 - P("`")) ^ 1) * P("`")) / node_code + + (P("<") * C(uri) * P(">")) / node_autolink + + (P("<") * C(address) * P(">")) / node_mail + (P("[!") * label * target * P("]") * target) / node_image + (P("!") * label * target) / node_image + (label * target) / node_link diff --git a/tests/extensions/test-about-render.lua b/tests/extensions/test-about-render.lua index eb62a89..601d0dc 100644 --- a/tests/extensions/test-about-render.lua +++ b/tests/extensions/test-about-render.lua @@ -153,6 +153,14 @@ h.contains("an absolute link is left alone", out, "href='https://example.com/x'" out = render("README.md", "[mail](mailto:a@example.com)") h.contains("a mailto link renders as an anchor", out, "<a href='mailto:a@example.com'>mail</a>") +out = render("README.md", "see <https://example.com/a?b=1> or <me@example.com>") +h.contains("a url in angle brackets links", out, "<a href='https://example.com/a?b=1'>https://example.com/a?b=1</a>") +h.contains("an address in angle brackets links", out, "<a href='mailto:me@example.com'>me@example.com</a>") + +out = render("README.md", "<javascript:alert(1)> and <b>") +h.excludes("an unsafe autolink renders no anchor", out, "<a ") +h.contains("other angle brackets stay text", out, "<b>") + out = render("README.md", "[bad](javascript:alert(1))") h.excludes("a javascript link renders no anchor", out, "<a ") h.contains("its text still reaches the page", out, "bad") |
