summaryrefslogtreecommitdiffstats
path: root/pkgs/simple/cgit-about-filter
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-12 18:06:27 +0000
committertv <tv@krebsco.de>2026-11-12 19:18:57 +0100
commit6b7956fe6b916362eceb014ef6e092c6fae015c6 (patch)
tree949b2bc0eb634de81cc88922fd9ff128a687b88e /pkgs/simple/cgit-about-filter
parent56d0fbca73150eebf5c7b34facfbb8e93e592ee2 (diff)
cgit-about-filter: share column widths between tablesHEADmaster
Diffstat (limited to 'pkgs/simple/cgit-about-filter')
-rw-r--r--pkgs/simple/cgit-about-filter/cgit-about-filter.lua90
1 files changed, 90 insertions, 0 deletions
diff --git a/pkgs/simple/cgit-about-filter/cgit-about-filter.lua b/pkgs/simple/cgit-about-filter/cgit-about-filter.lua
index d4f441a..cd20d54 100644
--- a/pkgs/simple/cgit-about-filter/cgit-about-filter.lua
+++ b/pkgs/simple/cgit-about-filter/cgit-about-filter.lua
@@ -96,6 +96,95 @@ div#cgit div#summary td + td {
</style>
]]
+-- Column widths, shared by all tables with the same header. A column's
+-- weight is the larger of its longest word and its average cell length, in
+-- characters; code counts more, as monospace is wider. Narrow columns get a
+-- fixed width, the others a share of what's left.
+local code_weight = 1.25
+local narrow = 12
+
+local function length(s)
+ s = s:gsub("&#?%w+;", "x")
+ return select(2, s:gsub("[^\128-\191]", ""))
+end
+
+local function cell_weights(cell)
+ local longest, total = 0, 0
+ local function add(text, factor)
+ for word in text:gmatch("%S+") do
+ local n = length(word) * factor
+ longest = math.max(longest, n)
+ total = total + n + 1
+ end
+ end
+ for code in cell:gmatch("<code>(.-)</code>") do
+ add((code:gsub("<[^>]+>", "")), code_weight)
+ end
+ add((cell:gsub("<code>.-</code>", " "):gsub("<[^>]+>", " ")), 1)
+ return longest, math.max(total - 1, 0)
+end
+
+local function cells(row)
+ local result = {}
+ for cell in row:gmatch("<t[hd][^>]*>(.-)</t[hd]>") do
+ table.insert(result, cell)
+ end
+ return result
+end
+
+local function header(tbl)
+ return table.concat(cells(tbl:match("<tr>(.-)</tr>") or ""), "\0")
+end
+
+local function column_widths(output)
+ local stats = {}
+ for tbl in output:gmatch("<table>.-</table>") do
+ local key = header(tbl)
+ stats[key] = stats[key] or { rows = 0, longest = {}, total = {} }
+ local s = stats[key]
+ for row in tbl:gmatch("<tr>(.-)</tr>") do
+ s.rows = s.rows + 1
+ for i, cell in ipairs(cells(row)) do
+ local longest, total = cell_weights(cell)
+ s.longest[i] = math.max(s.longest[i] or 0, longest)
+ s.total[i] = (s.total[i] or 0) + total
+ end
+ end
+ end
+ local widths = {}
+ for key, s in pairs(stats) do
+ local weights, wide = {}, 0
+ for i = 1, #s.longest do
+ weights[i] = math.max(s.longest[i], s.total[i] / s.rows)
+ if weights[i] > narrow then
+ wide = wide + weights[i]
+ end
+ end
+ local cols = {}
+ for i, weight in ipairs(weights) do
+ if weight > narrow then
+ cols[i] = string.format('<col style="width:%.1f%%">', 100 * weight / wide)
+ else
+ cols[i] = string.format('<col style="width:calc(%dch + 1.2em)">', math.ceil(weight) + 1)
+ end
+ end
+ widths[key] = "<colgroup>" .. table.concat(cols) .. "</colgroup>"
+ end
+ return widths
+end
+
+-- Add the column widths, and let code break after underscores.
+local function layout_tables(output)
+ local widths = column_widths(output)
+ return (output:gsub("<table>.-</table>", function(tbl)
+ local key = header(tbl)
+ tbl = tbl:gsub("<code>(.-)</code>", function(code)
+ return "<code>" .. code:gsub("_", "_<wbr>") .. "</code>"
+ end)
+ return "<table>" .. widths[key] .. tbl:sub(#"<table>" + 1)
+ end))
+end
+
local buffer = ""
local should_render = true
local current_dir = "" -- Stores the directory prefix of the file being processed
@@ -169,6 +258,7 @@ function filter_close()
if output then
if output:find("<table>", 1, true) then
emit(table_style)
+ output = layout_tables(output)
end
emit(output)
else