diff options
context:
space:
mode:
authorBryce Kwon <bryce@brycekwon.com>
committerBryce Kwon <bryce@brycekwon.com>
commit
parent
tree
download
Reorganize the tree into vendor/ and custom/
Diffstat (limited to 'extensions/link-commits.lua')
-rw-r--r--extensions/link-commits.lua153
1 file changed, 0 insertions, 153 deletions
diff --git a/extensions/link-commits.lua b/extensions/link-commits.lua
deleted file mode 100644
index e7b17cc..0000000
--- a/extensions/link-commits.lua
+++ /dev/null
@@ -1,153 +0,0 @@
--- cgit commit-filter that turns git object names and configurable text
--- references in commit messages into links. Use it with the commit-filter or
--- repo.commit-filter setting and the lua: prefix.
---
--- commit-filter=lua:/path/to/link-commits.lua
---
--- cgit hands the filter the message already HTML-escaped, so this only wraps
--- matches in anchors. No external dependencies. Runs on Lua 5.1 through 5.4
--- and LuaJIT.
---
--- Two kinds of thing are linked, object names (runs of hex that look like git
--- hashes) and any number of text-reference rules you define, each a pattern
--- and a URL. Both are configured in the block below. All matches are resolved
--- in a single left-to-right pass, so nothing is ever linked twice.
-
---
--- ===== CONFIGURATION =====
---
-
--- Object names (git hashes). Handled specially, because the length rule cannot
--- be written as a plain Lua pattern.
---
--- Recognition is by shape, since a commit-filter cannot ask the repository
--- whether a hash is real. Any hex run within the length bounds is linked,
--- whatever mix of digits and letters it has, so abbreviated and all-digit
--- hashes are both caught. The cost is that a long hex-looking number can now
--- and then link to an object that does not exist, which cgit renders as a
--- harmless "bad object name" page. Shape matching is inherently approximate,
--- the length bounds are the only filter.
-local objects = {
- -- Set false to stop linking bare hashes.
- enabled = true,
- -- A hex run within these lengths is linked. Git abbreviations run about 7
- -- to 12 characters, full names are 40 (sha1) or 64 (sha256).
- min_length = 7,
- max_length = 64,
- -- Link target, %s is replaced with the matched hash. "./?id=%s" is relative
- -- to the current page and works for the common virtual-root layout.
- url = "./?id=%s",
-}
-
--- Text-reference rules. Each rule is a Lua pattern with ONE capture and a URL
--- where %s is replaced by that capture, percent-encoded. The whole match is
--- shown, the capture is what goes in the URL. Rules are tried in order and the
--- leftmost match on the line wins, so put more specific patterns first. Leave
--- the list empty to link only object names.
---
--- Lua patterns are not regular expressions. There is no alternation and no
--- {n,m} repetition. %d is a digit, %a a letter, %w a letter or digit, %x a hex
--- digit, and a literal magic character is escaped with %, so a literal '-' is
--- '%-'. Reference: https://www.lua.org/manual/5.1/manual.html#5.4.1
-local rules = {
- { pattern = "#(%d+)", url = "https://bugs.example.com/?bug=%s" },
- -- { pattern = "CVE%-(%d%d%d%d%-%d+)", url = "https://www.cve.org/CVERecord?id=CVE-%s" },
- -- { pattern = "!(%d+)", url = "https://gitlab.example.com/group/repo/-/merge_requests/%s" },
- -- { pattern = "RFC%s?(%d+)", url = "https://www.rfc-editor.org/rfc/rfc%s" },
-}
-
---
--- =========================
---
-
-local chunks = {}
-
--- Percent-encode everything but the URL-unreserved characters, so a captured
--- value cannot break out of the href attribute or the URL.
-local function url_encode(s)
- return (string.gsub(s, "[^%w._~-]", function(c)
- return string.format("%%%02X", string.byte(c))
- end))
-end
-
--- Build one anchor. url_template has %s where the encoded capture goes, display
--- is the text shown. A function replacement is used so a '%' in the encoded
--- value is not treated as a gsub reference.
-local function make_link(url_template, capture, display)
- local encoded = url_encode(capture)
- local href = string.gsub(url_template, "%%s", function() return encoded end)
- return '<a href="' .. href .. '">' .. display .. '</a>'
-end
-
--- Collect every candidate match as {s, e, pri, link}. A lower pri wins a tie on
--- the same start position.
-local function collect(text)
- local cands = {}
- for pri, rule in ipairs(rules) do
- -- A malformed pattern is an operator error, skip that rule rather than
- -- failing the whole page.
- pcall(function()
- local init = 1
- while init <= #text do
- local s, e, cap = string.find(text, rule.pattern, init)
- if not s then break end
- if cap == nil then
- cap = string.sub(text, s, e)
- end
- cands[#cands + 1] = {
- s = s, e = e, pri = pri,
- link = make_link(rule.url, cap, string.sub(text, s, e)),
- }
- init = (e >= s) and e + 1 or s + 1
- end
- end)
- end
- if objects.enabled then
- local objpri = #rules + 1
- local init = 1
- while init <= #text do
- local s, e, run = string.find(text, "%f[%w](%x+)%f[%W]", init)
- if not s then break end
- if #run >= objects.min_length and #run <= objects.max_length then
- cands[#cands + 1] = {
- s = s, e = e, pri = objpri,
- link = make_link(objects.url, run, run),
- }
- end
- init = e + 1
- end
- end
- return cands
-end
-
-function filter_open(...)
- chunks = {}
-end
-
-function filter_write(str)
- chunks[#chunks + 1] = str
-end
-
-function filter_close()
- local text = table.concat(chunks)
- local cands = collect(text)
- table.sort(cands, function(a, b)
- if a.s ~= b.s then
- return a.s < b.s
- end
- return a.pri < b.pri
- end)
- local out = {}
- local i = 1
- for _, c in ipairs(cands) do
- -- Skip a candidate that overlaps one already emitted.
- if c.s >= i then
- out[#out + 1] = string.sub(text, i, c.s - 1)
- out[#out + 1] = c.link
- i = c.e + 1
- end
- end
- out[#out + 1] = string.sub(text, i)
- html(table.concat(out))
- return 0
-end