Changelog: Difference between revisions
From Project Rebearth
Created page with "-- 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 formatD..." |
No edit summary |
||
| (3 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
| Line 18: | Line 14: | ||
} | } | ||
local function formatDate(isoDate) | local function formatDate(isoDate) | ||
local y, m, d = isoDate:match("^(%d+)-(%d+)-(%d+)$") | local y, m, d = isoDate:match("^(%d+)-(%d+)-(%d+)$") | ||
| Line 27: | Line 22: | ||
end | end | ||
local function validateTag(tag) | local function validateTag(tag) | ||
if VALID_TAGS[tag] then | if VALID_TAGS[tag] then | ||
| Line 35: | Line 29: | ||
end | end | ||
local function getRelatedPages(entry) | local function getRelatedPages(entry) | ||
local aliases = mw.loadData("Module:Aliases/data") | local aliases = mw.loadData("Module:Aliases/data") | ||
| Line 44: | Line 35: | ||
local function addPage(name) | local function addPage(name) | ||
local canonical = aliases[name] or name | local canonical = aliases[name] or name | ||
if not seen[canonical] then | if not seen[canonical] then | ||
| Line 52: | Line 42: | ||
end | end | ||
for target in entry.text:gmatch("%[%[([^%]|]+)[^%]]*%]%]") do | for target in entry.text:gmatch("%[%[([^%]|]+)[^%]]*%]%]") do | ||
local trimmed = mw.text.trim(target) | local trimmed = mw.text.trim(target) | ||
| Line 60: | Line 49: | ||
end | end | ||
for resource in entry.text:gmatch("{{Icon|([^}]+)}}") do | for resource in entry.text:gmatch("{{Icon|([^}]+)}}") do | ||
local trimmed = mw.text.trim(resource) | local trimmed = mw.text.trim(resource) | ||
| Line 68: | Line 56: | ||
end | end | ||
if entry.pages then | if entry.pages then | ||
for _, name in ipairs(entry.pages) do | for _, name in ipairs(entry.pages) do | ||
| Line 75: | Line 62: | ||
end | end | ||
if entry.exclude then | if entry.exclude then | ||
local excludeSet = {} | local excludeSet = {} | ||
| Line 93: | Line 79: | ||
end | end | ||
local function groupByDate(entries) | local function groupByDate(entries) | ||
local groups = {} | local groups = {} | ||
| Line 115: | Line 100: | ||
end | end | ||
local function renderEntry(frame, entry) | |||
local function renderEntry(entry) | local line = "* " .. validateTag(entry.tag) .. " " .. entry.text | ||
return frame:preprocess(line) | |||
end | end | ||
function p.all(frame) | function p.all(frame) | ||
local | local _dataTitle = mw.title.new("Module:Changelog/data.json") | ||
local data = mw.text.jsonDecode(_dataTitle:getContent()) | |||
local groups = groupByDate(data) | local groups = groupByDate(data) | ||
local out = {} | local out = {} | ||
| Line 129: | Line 114: | ||
out[#out + 1] = "=== " .. formatDate(group.date) .. " ===" | out[#out + 1] = "=== " .. formatDate(group.date) .. " ===" | ||
for _, entry in ipairs(group.entries) do | for _, entry in ipairs(group.entries) do | ||
out[#out + 1] = renderEntry(entry) | out[#out + 1] = renderEntry(frame, entry) | ||
end | end | ||
end | end | ||
return | return "\n" .. table.concat(out, "\n") | ||
end | end | ||
function p.forPage(frame) | function p.forPage(frame) | ||
local args = frame.args | local args = frame.args | ||
| Line 146: | Line 130: | ||
local limit = tonumber(args.limit) or 5 | local limit = tonumber(args.limit) or 5 | ||
local | local _dataTitle = mw.title.new("Module:Changelog/data.json") | ||
local data = mw.text.jsonDecode(_dataTitle:getContent()) | |||
local matched = {} | local matched = {} | ||
for _, entry in ipairs(data) do | for _, entry in ipairs(data) do | ||
| Line 160: | Line 144: | ||
end | end | ||
if #matched == 0 then | if #matched == 0 then | ||
return '<div class="rb-changelog rb-changelog-empty">No changelog entries for this page yet.</div>' | return '<div class="rb-changelog rb-changelog-empty">No changelog entries for this page yet.</div>' | ||
end | end | ||
local limited = {} | local limited = {} | ||
for i = 1, math.min(limit, #matched) do | for i = 1, math.min(limit, #matched) do | ||
| Line 178: | Line 160: | ||
out[#out + 1] = "==== " .. formatDate(group.date) .. " ====" | out[#out + 1] = "==== " .. formatDate(group.date) .. " ====" | ||
for _, entry in ipairs(group.entries) do | for _, entry in ipairs(group.entries) do | ||
out[#out + 1] = renderEntry(entry) | out[#out + 1] = renderEntry(frame, entry) | ||
end | end | ||
end | end | ||
| Line 187: | Line 169: | ||
out[#out + 1] = "</div>" | out[#out + 1] = "</div>" | ||
return | return table.concat(out, "\n") | ||
end | end | ||
return p | return p | ||
Latest revision as of 14:24, 4 March 2026
Documentation for this module may be created at Module:Changelog/doc
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",
}
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
local function validateTag(tag)
if VALID_TAGS[tag] then
return "{{Tag|" .. tag .. "}}"
end
return '<span class="error">Unknown tag: "' .. tag .. '"</span>'
end
local function getRelatedPages(entry)
local aliases = mw.loadData("Module:Aliases/data")
local pages = {}
local seen = {}
local function addPage(name)
local canonical = aliases[name] or name
if not seen[canonical] then
seen[canonical] = true
pages[#pages + 1] = canonical
end
end
for target in entry.text:gmatch("%[%[([^%]|]+)[^%]]*%]%]") do
local trimmed = mw.text.trim(target)
if trimmed ~= "" then
addPage(trimmed)
end
end
for resource in entry.text:gmatch("{{Icon|([^}]+)}}") do
local trimmed = mw.text.trim(resource)
if trimmed ~= "" then
addPage(trimmed)
end
end
if entry.pages then
for _, name in ipairs(entry.pages) do
addPage(name)
end
end
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
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
local function renderEntry(frame, entry)
local line = "* " .. validateTag(entry.tag) .. " " .. entry.text
return frame:preprocess(line)
end
function p.all(frame)
local _dataTitle = mw.title.new("Module:Changelog/data.json")
local data = mw.text.jsonDecode(_dataTitle:getContent())
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
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 _dataTitle = mw.title.new("Module:Changelog/data.json")
local data = mw.text.jsonDecode(_dataTitle:getContent())
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
if #matched == 0 then
return '<div class="rb-changelog rb-changelog-empty">No changelog entries for this page yet.</div>'
end
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