diff options
authorBryce Kwon <bryce@brycekwon.com>
committerBryce Kwon <bryce@brycekwon.com>
commit
parent
tree
download
Lead a readme's relative links into the tree
A browser resolved them against the about page, where nothing lives now that the page answers 404 below itself. They resolve the way GitHub resolves a readme's links instead, from the readme's directory and on the branch it was read from.
Diffstat (limited to 'tests/extensions')
-rw-r--r--tests/extensions/harness.lua11
-rw-r--r--tests/extensions/test-about-render.lua36
2 files changed, 44 insertions, 3 deletions
diff --git a/tests/extensions/harness.lua b/tests/extensions/harness.lua
index d9318ee..fc83a73 100644
--- a/tests/extensions/harness.lua
+++ b/tests/extensions/harness.lua
@@ -46,16 +46,23 @@ html_attr = sink(function(s)
return (s:gsub("[&<>'\"]", attr_map))
end)
+-- The bytes url_escape_table encodes, which are those a url path cannot
+-- carry plainly and those an attribute or a query would misread.
+html_url_path = sink(function(s)
+ return (s:gsub("[%c \"#%%&'+<=>?\\^`{|}\128-\255]", function(c)
+ return string.format("%%%02X", c:byte())
+ end))
+end)
+
-- No shipped extension calls the remaining sinks, so rather than risk an
-- unfaithful copy quietly passing a test, using one fails loudly until its
--- escaping is mirrored from source/html.c the way the three above are.
+-- escaping is mirrored from source/html.c the way the ones above are.
local function unmirrored(name)
return function()
error(name .. " is not mirrored by the test harness yet")
end
end
-html_url_path = unmirrored("html_url_path")
html_url_arg = unmirrored("html_url_arg")
html_include = unmirrored("html_include")
diff --git a/tests/extensions/test-about-render.lua b/tests/extensions/test-about-render.lua
index b0379b7..4f8b532 100644
--- a/tests/extensions/test-about-render.lua
+++ b/tests/extensions/test-about-render.lua
@@ -28,6 +28,11 @@ local function render(filename, text)
return h.run({ filename }, { text })
end
+-- A readme tracked in a repository comes with the url of its tree.
+local function render_tree(filename, query, text)
+ return h.run({ filename, "/r/tree/", query }, { text })
+end
+
-- Dispatch and the plain text rendering need nothing but the script itself,
-- so they run whatever became of lpeg.
@@ -107,7 +112,36 @@ out = render("README.md", "[docs](https://example.com/docs)")
h.contains("an https link renders as an anchor", out, "<a href='https://example.com/docs'>docs</a>")
out = render("README.md", "[docs](docs/page.html)")
-h.contains("a relative link renders as an anchor", out, "<a href='docs/page.html'>docs</a>")
+h.contains("with no tree a relative link stays as written", out, "<a href='docs/page.html'>docs</a>")
+
+out = render_tree("README.md", "", "[road](ROADMAP.md)")
+h.contains("a relative link leads into the tree", out, "<a href='/r/tree/ROADMAP.md'>road</a>")
+
+out = render_tree("docs/README.md", "", "[a](guide.md#setup) [b](../NEWS) [c](/src/x.c)")
+h.contains("a link resolves against the readme's directory", out, "href='/r/tree/docs/guide.md#setup'")
+h.contains("dot segments fold", out, "href='/r/tree/NEWS'")
+h.contains("a leading slash names the root", out, "href='/r/tree/src/x.c'")
+
+out = render_tree("docs/README.md", "", "[up](../../../etc/passwd)")
+h.contains("no link climbs above the root", out, "href='/r/tree/etc/passwd'")
+
+out = render_tree("README.md", "?h=next", "[a](NEWS#top)")
+h.contains("the ref's query comes before the fragment", out, "href='/r/tree/NEWS?h=next#top'")
+
+out = render_tree("README.md", "&h=next", "[a](NEWS)")
+h.contains("the query is escaped for the attribute", out, "href='/r/tree/NEWS&amp;h=next'")
+
+out = render_tree("README.md", "", "[a](my%20file.md) [b](a&b.md) [c](f.md?plain=1)")
+h.contains("an encoded path is encoded only once", out, "href='/r/tree/my%20file.md'")
+h.contains("a path is escaped for the url", out, "href='/r/tree/a%26b.md'")
+h.contains("a query in a link is dropped", out, "href='/r/tree/f.md'")
+
+out = render_tree("README.md", "", "[a](x%00y)")
+h.contains("an encoded nul stays encoded", out, "href='/r/tree/x%2500y'")
+
+out = render_tree("README.md", "", "[a](#usage) [b](https://example.com/x)")
+h.contains("a fragment stays on the page", out, "href='#usage'")
+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>")