Module:ChapterList
Documentation for this module may be created at Module:ChapterList/doc
-- Module:ChapterList (enhanced)
-- Builds a sortable chapter table with volume headers, "Not yet in print",
-- and book‑exclusive chapters. All metadata is pulled from Module:ChapterNavbox.
local p = {}
---------------------------------------------------------------------
-- helpers
---------------------------------------------------------------------
local function formatDate(iso)
local y, m, d = iso:match("^(%d%d%d%d)%-(%d%d)%-(%d%d)$")
if not y then return iso or '' end
return tonumber(m) .. "/" .. tonumber(d) .. "/" .. y:sub(3, 4)
end
-- numeric value of a chapter number (handles decimals)
local function numVal(n)
return tonumber(n) or 0
end
---------------------------------------------------------------------
-- pull data
---------------------------------------------------------------------
local nav = require('Module:ChapterNavbox') -- expects .volumes and .bookExclusiveChapters
local volumes = nav.volumes or {}
local bookExclusive = nav.bookExclusiveChapters or {}
-- read the raw wikitext list (Template:ChapterList)
local tplTitle = mw.title.new('Template:ChapterList')
local raw = tplTitle and tplTitle:getContent() or ''
-- parse {{Chapter|number=…|title=…|date=…}}
local chapters = {}
for _, line in ipairs(mw.text.split(raw, "\n", true)) do
local trimmed = mw.text.trim(line)
if trimmed:find('^{{Chapter') then
local inner = trimmed:match('^{{Chapter%s*(.+)}}$')
if inner then
if inner:sub(1,1) == '|' then inner = inner:sub(2) end
local params = {}
for part in inner:gmatch('[^|]+') do
local k, v = part:match('^(%w+)%s*=%s*(.+)$')
if k and v then params[k] = v end
end
if params.number and params.title and params.date then
table.insert(chapters, params)
end
end
end
end
-- sort chapters by numeric number
table.sort(chapters, function(a,b) return numVal(a.number) < numVal(b.number) end)
---------------------------------------------------------------------
-- build table
---------------------------------------------------------------------
local function addHeaderRow(out, text, colspan)
table.insert(out, '|-')
table.insert(out, '! colspan="' .. (colspan or 3) .. '" | ' .. text)
end
function p.renderTable(frame)
local out = {
'{| class="wikitable sortable"',
'! #',
'! Title',
'! Published'
}
-- iterate volumes in declared order
local used = {} -- track chapters already emitted
for _, vol in ipairs(volumes) do
-- header with optional style
local header = vol.name
if vol.style and vol.style ~= '' then
table.insert(out, '|-')
table.insert(out, '! colspan="3" style="' .. vol.style .. '" | ' .. header)
else
addHeaderRow(out, header)
end
for _, ch in ipairs(chapters) do
if not used[ch] then
local n = numVal(ch.number)
if n >= vol.start and n <= vol.end_ then
used[ch] = true
local isInter = tostring(ch.number):find('%.')
local dispNum = isInter and '' or ch.number
local dispTitle = isInter and ('Intermission: [[' .. ch.title .. ']]')
or ('[[' .. ch.title .. ']]')
table.insert(out, '|-')
table.insert(out, '| ' .. dispNum .. ' || ' .. dispTitle .. ' || ' .. formatDate(ch.date))
end
end
end
end
-- Not yet in print header
addHeaderRow(out, 'Not yet in print')
for _, ch in ipairs(chapters) do
if not used[ch] then
local isInter = tostring(ch.number):find('%.')
local dispNum = isInter and '' or ch.number
local dispTitle = isInter and ('Intermission: [[' .. ch.title .. ']]')
or ('[[' .. ch.title .. ']]')
table.insert(out, '|-')
table.insert(out, '| ' .. dispNum .. ' || ' .. dispTitle .. ' || ' .. formatDate(ch.date))
used[ch] = true
end
end
-- Book‑exclusive header
if #bookExclusive > 0 then
addHeaderRow(out, 'Book‑exclusive')
for _, be in ipairs(bookExclusive) do
local link = be.link or be.title:gsub(' ', '_')
table.insert(out, '|-')
table.insert(out, '| || [[' .. link .. '|' .. be.title .. ']] || ')
end
end
table.insert(out, '|}')
return table.concat(out, '\n')
end
return p