Module:SongPeak
Appearance
Documentation for this module may be created at Module:SongPeak/doc
-- Module:SongPeak
-- Pulls the last PK value from the first table under "== Chart History ==" on the same page (or an optional page).
-- Returns the value (e.g., "1²⁰") so it can be used as |peak= in the infobox.
local p = {}
local function getPageText(titleArg)
-- If a title is passed (args.title), read that page; else read the current page
local titleObj
if titleArg and titleArg ~= "" then
titleObj = mw.title.new(titleArg)
else
titleObj = mw.title.getCurrentTitle()
end
if not titleObj then return "" end
return titleObj:getContent() or ""
end
-- Extract the wikitext for the first table following the "== Chart History ==" section header.
local function getChartHistoryTableText(pageText)
if not pageText or pageText == "" then return nil end
-- Find the "== Chart History ==" header
local secStart, secEnd = pageText:find("==%s*Chart%s+History%s*==")
if not secEnd then
-- Some editors might write "== Chart history ==" (lowercase) – handle case-insensitively
secStart, secEnd = pageText:lower():find("==%s*chart%s+history%s*==")
if not secEnd then return nil end
-- map back to original positions is not needed since we only slice *after* secEnd
end
-- Everything after that header
local after = pageText:sub(secEnd + 1)
-- Find the first table start
local tStart = after:find("{|")
if not tStart then return nil end
local rest = after:sub(tStart)
-- Grab until the matching table close. The first occurrence of "\n|}" should end this table.
local tClose = rest:find("\n|}%s*")
local tableText = tClose and rest:sub(1, tClose) or rest
return tableText
end
-- From a table’s wikitext, grab the last data row, then return the last cell (the PK column).
local function getLastPkFromTable(tableText)
if not tableText or tableText == "" then return nil end
-- Find the last row separator "|-" within this table
local lastRowPos
local searchFrom = 1
while true do
local pos = tableText:find("\n|%-", searchFrom)
if not pos then break end
lastRowPos = pos
searchFrom = pos + 3
end
if not lastRowPos then return nil end
-- Slice from the start of the last row to the next row (or end of table)
local rowsTail = tableText:sub(lastRowPos + 3)
local nextRowPos = rowsTail:find("\n|%-")
if nextRowPos then
rowsTail = rowsTail:sub(1, nextRowPos - 1)
end
-- The last row will have a first cell that starts with "|" then "||" separating subsequent cells.
-- Normalize newlines to spaces for simpler splitting.
rowsTail = rowsTail:gsub("^%s*|%s*", "") -- remove leading "|"
rowsTail = rowsTail:gsub("\n", " ")
-- Split by "||" into cells
local cells = {}
for part in mw.text.gsplit(rowsTail, "||", true) do
table.insert(cells, mw.text.trim(part))
end
if #cells == 0 then return nil end
-- The last cell should be the PK value (e.g., "1", "1²⁰", "5", etc.)
local lastCell = mw.text.trim(cells[#cells] or "")
-- Defensive cleanup: if there’s any trailing table syntax left, drop it.
-- (e.g., some editors might put a stray "|" at the end)
lastCell = lastCell:gsub("%s*|%s*$", "")
return lastCell ~= "" and lastCell or nil
end
function p.inferPeak(frame)
local args = frame.args or {}
local titleArg = args.title -- optional: {{#invoke:SongPeak|inferPeak|title=Some Page}}
local pageText = getPageText(titleArg)
if pageText == "" then return "" end
local tableText = getChartHistoryTableText(pageText)
if not tableText then return "" end
local pk = getLastPkFromTable(tableText)
-- Return the exact value (including superscripts) so color/type modules keep working.
return pk or ""
end
return p