diff options
authorBryce Kwon <bryce@brycekwon.com>
committerBryce Kwon <bryce@brycekwon.com>
commit
parent
tree
download
Link the urls and addresses in angle brackets
-rw-r--r--custom/extensions/about-render.lua19
-rw-r--r--tests/extensions/test-about-render.lua8
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, "&lt;b&gt;")
+
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")