Module:ProjectCounts: Difference between revisions
Created page with "-- Counts data rows in the wikitable(s) inside one named section of a page. -- Usage: {{#invoke:ProjectCounts|count|Active BOINC Projects|page=BOINC projects}} local p = {} local function esc(s) return (s:gsub('(%W)', '%%%1')) end function p.count(frame) local section = mw.text.trim(frame.args[1] or '') local title = mw.title.new(frame.args.page or 'BOINC projects') if not title then return 0 end local content = title:getContent() if not content the..." |
No edit summary |
||
| Line 1: | Line 1: | ||
-- | -- Module:ProjectCounts | ||
local p = {} | local p = {} | ||
local function esc(s) return (s:gsub('(%W)', '%%%1')) end | local function esc(s) return (s:gsub('(%W)', '%%%1')) end | ||
local function getContent(page) | |||
local t = mw.title.new(page) | |||
if not t then return nil end | |||
return t:getContent() | |||
end | |||
-- Extract the wikitext of one section: from its heading (any level) | |||
-- to the next heading of the same or higher level. | |||
local function getSection(content, section) | |||
local hStart, hEnd, marks = content:find('\n(=+)%s*' .. esc(section) .. '%s*=*') | |||
if not hStart then return nil end | |||
local depth = #marks | |||
local secEnd = #content + 1 | |||
local pos = hEnd | |||
while true do | |||
local nStart, nEnd, nMarks = content:find('\n(=+)', pos) | |||
if not nStart then break end | |||
if #nMarks <= depth then secEnd = nStart break end | |||
pos = nEnd | |||
end | |||
return '\n' .. content:sub(hEnd + 1, secEnd - 1) | |||
end | |||
-- Data rows = row separators minus one header separator per table. | |||
local function countRows(body) | |||
local _, tables = body:gsub('\n{|', '') | |||
local _, seps = body:gsub('\n|%-', '') | |||
return math.max(seps - tables, 0) | |||
end | |||
local function countSection(page, section) | |||
local content = getContent(page) | |||
if not content then return 0 end | |||
local body = getSection(content, mw.text.trim(section)) | |||
if not body then return 0 end | |||
return countRows(body) | |||
end | |||
-- {{#invoke:ProjectCounts|count|Section name|page=Page title}} | |||
function p.count(frame) | function p.count(frame) | ||
return countSection(frame.args.page or 'BOINC projects', frame.args[1] or '') | |||
end | |||
-- {{#invoke:ProjectCounts|total|Section A|Section B|...|page=Page title}} | |||
function p.total(frame) | |||
local page = frame.args.page or 'BOINC projects' | |||
local content = getContent(page) | |||
if not content then return 0 end | |||
local sum = 0 | |||
for _, s in ipairs(frame.args) do | |||
local body = getSection(content, mw.text.trim(s)) | |||
if body then sum = sum + countRows(body) end | |||
end | |||
return sum | |||
end | |||
-- {{#invoke:ProjectCounts|documented|Local BOINC project wiki pages|page=Main Page}} | |||
-- Counts distinct mainspace article links in a section, skipping redlinks. | |||
function p.documented(frame) | |||
local page = frame.args.page or 'Main Page' | |||
local section = mw.text.trim(frame.args[1] or 'Local BOINC project wiki pages') | |||
local content = getContent(page) | |||
if not content then return 0 end | |||
local body = getSection(content, section) | |||
if not body then return 0 end | |||
local seen, n = {}, 0 | |||
for link in body:gmatch('%[%[([^|%]%[#:]+)') do | |||
link = mw.text.trim(link) | |||
if link ~= '' and not seen[link] then | |||
seen[link] = true | |||
local t = mw.title.new(link) | |||
if t and t.namespace == 0 and t.exists then | |||
n = n + 1 | |||
end | |||
end | |||
end | |||
return n | |||
end | end | ||
return p | return p | ||