Changelog: Difference between revisions
From Project Rebearth
No edit summary |
No edit summary |
||
| Line 134: | Line 134: | ||
end | end | ||
return table.concat(out, "\n") | return "\n" .. table.concat(out, "\n") | ||
end | end | ||
Latest revision as of 19:27, 26 February 2026
Documentation for this module may be created at Module:Changelog/doc
-- Module:Changelog
-- Renders changelog entries from Module:Changelog/data.
-- Public: p.all(frame), p.forPage(frame)
local p = {}
local VALID_TAGS = {
New = true,
Balance = true,
Fix = true,
QoL = true,
Performance = true,
}
local MONTH_NAMES = {
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December",
}
--- Format "YYYY-MM-DD" → "February 14, 2026"
local function formatDate(isoDate)
local y, m, d = isoDate:match("^(%d+)-(%d+)-(%d+)$")
if not y then return isoDate end
local month = MONTH_NAMES[tonumber(m)]
if not month then return isoDate end
return month .. " " .. tonumber(d) .. ", " .. y
end
--- Validate tag; return tag name or error span.
local function validateTag(tag)
if VALID_TAGS[tag] then
return "{{Tag|" .. tag .. "}}"
end
return '<span class="error">Unknown tag: "' .. tag .. '"</span>'
end
--- Extract page names that an entry relates to.
--- Scans wikilinks [[Page]] / [[Page|display]], Icon templates {{Icon|Res}},
--- resolves aliases, merges manual pages, and removes excludes.
local function getRelatedPages(entry)
local aliases = mw.loadData("Module:Aliases/data")
local pages = {}
local seen = {}
local function addPage(name)
-- Resolve alias
local canonical = aliases[name] or name
if not seen[canonical] then
seen[canonical] = true
pages[#pages + 1] = canonical
end
end
-- Scan [[PageName]] and [[PageName|display]]
for target in entry.text:gmatch("%[%[([^%]|]+)[^%]]*%]%]") do
local trimmed = mw.text.trim(target)
if trimmed ~= "" then
addPage(trimmed)
end
end
-- Scan {{Icon|ResourceName}}
for resource in entry.text:gmatch("{{Icon|([^}]+)}}") do
local trimmed = mw.text.trim(resource)
if trimmed ~= "" then
addPage(trimmed)
end
end
-- Merge manual pages
if entry.pages then
for _, name in ipairs(entry.pages) do
addPage(name)
end
end
-- Remove excludes
if entry.exclude then
local excludeSet = {}
for _, name in ipairs(entry.exclude) do
excludeSet[name] = true
end
local filtered = {}
for _, name in ipairs(pages) do
if not excludeSet[name] then
filtered[#filtered + 1] = name
end
end
pages = filtered
end
return pages
end
--- Group entries by date, preserving input order.
local function groupByDate(entries)
local groups = {}
local dateOrder = {}
local dateMap = {}
for _, entry in ipairs(entries) do
if not dateMap[entry.date] then
dateMap[entry.date] = {}
dateOrder[#dateOrder + 1] = entry.date
end
local group = dateMap[entry.date]
group[#group + 1] = entry
end
for _, date in ipairs(dateOrder) do
groups[#groups + 1] = { date = date, entries = dateMap[date] }
end
return groups
end
--- Render a single entry as a wikitext bullet, preprocessing to expand templates.
local function renderEntry(frame, entry)
local line = "* " .. validateTag(entry.tag) .. " " .. entry.text
return frame:preprocess(line)
end
--- p.all — Full changelog for the main page.
function p.all(frame)
local data = mw.loadData("Module:Changelog/data")
local groups = groupByDate(data)
local out = {}
for _, group in ipairs(groups) do
out[#out + 1] = "=== " .. formatDate(group.date) .. " ==="
for _, entry in ipairs(group.entries) do
out[#out + 1] = renderEntry(frame, entry)
end
end
return "\n" .. table.concat(out, "\n")
end
--- p.forPage — Per-page filtered changelog.
function p.forPage(frame)
local args = frame.args
local targetPage = args.page or args[1]
if not targetPage or targetPage == "" then
targetPage = mw.title.getCurrentTitle().text
end
local limit = tonumber(args.limit) or 5
local data = mw.loadData("Module:Changelog/data")
-- Filter entries relevant to targetPage
local matched = {}
for _, entry in ipairs(data) do
local relatedPages = getRelatedPages(entry)
for _, pageName in ipairs(relatedPages) do
if pageName == targetPage then
matched[#matched + 1] = entry
break
end
end
end
-- Empty state
if #matched == 0 then
return '<div class="rb-changelog rb-changelog-empty">No changelog entries for this page yet.</div>'
end
-- Limit entries
local limited = {}
for i = 1, math.min(limit, #matched) do
limited[#limited + 1] = matched[i]
end
local groups = groupByDate(limited)
local out = {}
out[#out + 1] = '<div class="rb-changelog">'
for _, group in ipairs(groups) do
out[#out + 1] = "==== " .. formatDate(group.date) .. " ===="
for _, entry in ipairs(group.entries) do
out[#out + 1] = renderEntry(frame, entry)
end
end
out[#out + 1] = '<div class="rb-changelog-more">'
out[#out + 1] = "''[[Project Rebearth#Changelogs|See full changelog →]]''"
out[#out + 1] = "</div>"
out[#out + 1] = "</div>"
return table.concat(out, "\n")
end
return p