diff options
Diffstat (limited to 'pkgs/simple')
| -rw-r--r-- | pkgs/simple/cgit-about-filter/cgit-about-filter.lua | 90 |
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 |
