模組:PJ:VG/PORTAL/TODAY
外观
require("strict")
local getArgs = require("Module:Arguments").getArgs
local p = {}
local DEFAULT_SOURCE_PAGE = "Portal:电子游戏/内容展示/今日条目/data"
local EXCERPT_TEMPLATE = "Transclude lead excerpt"
local cache = {}
local function makeInvokeFunc(funcName)
return function(frame)
local args = getArgs(frame)
return p[funcName](args)
end
end
local function trim(value)
return mw.text.trim(value or "")
end
local function getSourcePage(args)
local sourcePage = trim(args.source)
if sourcePage ~= "" then
return sourcePage
end
return DEFAULT_SOURCE_PAGE
end
local function setArg(target, key, value)
if trim(value) ~= "" then
target[key] = value
end
end
local function normalizeDateKey(value)
value = trim(value)
if value == "" then
return nil
end
if value:match("^%d%d%d%d$") then
return value
end
if value:match("^%d+月%d+日$") then
local month, day = value:match("^(%d+)月(%d+)日$")
return string.format("%02d%02d", tonumber(month), tonumber(day))
end
local month, day = value:match("^(%d+)%s*[-/.]%s*(%d+)$")
if month and day then
return string.format("%02d%02d", tonumber(month), tonumber(day))
end
return nil
end
local function getDateKey(args)
if trim(args.date) ~= "" then
return normalizeDateKey(args.date) or trim(args.date)
end
local month = trim(args.month or args.m)
local day = trim(args.day or args.d)
if month ~= "" and day ~= "" then
return string.format("%02d%02d", tonumber(month), tonumber(day))
end
return mw.getContentLanguage():formatDate("md", nil, true)
end
local function extractPageName(line)
line = trim(line)
if line == "" then
return nil
end
local linkTarget = line:match("%[%[([^%]]+)%]%]")
if linkTarget then
line = linkTarget
end
line = line:gsub("|.*$", "")
line = line:gsub("#.*$", "")
line = trim(line)
if line == "" then
return nil
end
return line
end
local function parseSource(sourcePage)
if cache[sourcePage] then
return cache[sourcePage]
end
local title = mw.title.new(sourcePage)
if not title then
return nil, "Cannot open source page: " .. sourcePage
end
local content = title:getContent()
if not content or content == "" then
return nil, "Source page is empty: " .. sourcePage
end
local byDate = {}
local allPages = {}
local currentDateKey = nil
for line in mw.text.gsplit(content, "\n", true) do
local caseKey = trim(line:match("^|%s*(%d%d%d%d)%s*=") or "")
if caseKey ~= "" then
currentDateKey = caseKey
if not byDate[currentDateKey] then
byDate[currentDateKey] = {}
end
else
local bullet = trim(line:match("^%*+%s*(.-)%s*$") or "")
if currentDateKey and bullet ~= "" then
local pageName = extractPageName(bullet)
if pageName then
table.insert(byDate[currentDateKey], pageName)
table.insert(allPages, pageName)
end
end
end
end
cache[sourcePage] = {
byDate = byDate,
allPages = allPages
}
return cache[sourcePage]
end
local function uniquePages(pages)
local seen = {}
local result = {}
for _, pageName in ipairs(pages) do
if not seen[pageName] then
seen[pageName] = true
table.insert(result, pageName)
end
end
return result
end
local function sortDateKeys(byDate)
local keys = {}
for dateKey in pairs(byDate) do
table.insert(keys, dateKey)
end
table.sort(keys, function(a, b)
return tonumber(a) < tonumber(b)
end)
return keys
end
local function renderError(message)
return '<span class="error">' .. message .. "</span>"
end
local function renderExcerpt(args, pageName)
local templateArgs = {
[1] = pageName
}
setArg(templateArgs, "paragraphs", args.paragraphs)
setArg(templateArgs, "files", args.files)
setArg(templateArgs, "fileargs", args.fileargs)
setArg(templateArgs, "errors", args.errors)
return mw.getCurrentFrame():expandTemplate {
title = EXCERPT_TEMPLATE,
args = templateArgs
}
end
local function pickStablePage(pages, seedText)
if not pages or #pages == 0 then
return nil
end
local seed = tostring(seedText or "")
local hashValue = 0
for i = 1, #seed do
hashValue = hashValue + seed:byte(i) * i
end
local index = (hashValue % #pages) + 1
return pages[index]
end
p.main = makeInvokeFunc("_main")
p.listAll = makeInvokeFunc("_listAll")
p.listAllByDates = makeInvokeFunc("_listAllByDates")
p.forDate = makeInvokeFunc("_forDate")
p.randomForDate = makeInvokeFunc("_randomForDate")
p.showDate = makeInvokeFunc("_showDate")
function p._main(args)
return p._randomForDate(args)
end
function p._listAll(args)
local sourcePage = getSourcePage(args)
local data, errorMessage = parseSource(sourcePage)
if not data then
return renderError(errorMessage)
end
local pages = data.allPages
if trim(args.unique) ~= "no" then
pages = uniquePages(pages)
end
if #pages == 0 then
return renderError("No pages found")
end
local separator = args.sep or "、"
local output = {}
for _, pageName in ipairs(pages) do
table.insert(output, "[[" .. pageName .. "]]")
end
return table.concat(output, separator)
end
function p._listAllByDates(args)
local sourcePage = getSourcePage(args)
local data, errorMessage = parseSource(sourcePage)
if not data then
return renderError(errorMessage)
end
local dateKeys = sortDateKeys(data.byDate)
local months = {}
for _, dateKey in ipairs(dateKeys) do
local month = tonumber(dateKey:sub(1, 2))
local day = tonumber(dateKey:sub(3, 4))
if not months[month] then
months[month] = {
[1] = {},
[2] = {},
[3] = {}
}
end
local columnIndex = 1
if day >= 21 then
columnIndex = 3
elseif day >= 11 then
columnIndex = 2
end
local block = {}
table.insert(block, "<h3>" .. tostring(month) .. "月" .. tostring(day) .. "日</h3>")
table.insert(block, "<ul>")
for _, pageName in ipairs(data.byDate[dateKey]) do
table.insert(block, "<li>[[" .. pageName .. "]]</li>")
end
table.insert(block, "</ul>")
table.insert(months[month][columnIndex], table.concat(block, "\n"))
end
local output = {}
for month = 1, 12 do
if months[month] then
table.insert(output, "<h2>" .. tostring(month) .. "月</h2>")
table.insert(output, '<div style="display:flex; gap:1em; align-items:flex-start;">')
for columnIndex = 1, 3 do
table.insert(output, '<div style="flex:1; min-width:0;">')
if #months[month][columnIndex] > 0 then
table.insert(output, table.concat(months[month][columnIndex], "\n"))
end
table.insert(output, "</div>")
end
table.insert(output, "</div>")
end
end
return table.concat(output, "\n")
end
function p._forDate(args)
local sourcePage = getSourcePage(args)
local dateKey = getDateKey(args)
local data, errorMessage = parseSource(sourcePage)
if not data then
return renderError(errorMessage)
end
local pages = data.byDate[dateKey]
if not pages or #pages == 0 then
return renderError('No pages found for "' .. dateKey .. '" in [[' .. sourcePage .. "]]")
end
local output = {}
for _, pageName in ipairs(pages) do
table.insert(output, renderExcerpt(args, pageName))
end
return table.concat(output, "\n\n----\n\n")
end
function p._randomForDate(args)
local sourcePage = getSourcePage(args)
local dateKey = getDateKey(args)
local data, errorMessage = parseSource(sourcePage)
if not data then
return renderError(errorMessage)
end
local pages = data.byDate[dateKey]
if not pages or #pages == 0 then
return renderError('No pages found for "' .. dateKey .. '" in [[' .. sourcePage .. "]]")
end
local pageName = pickStablePage(pages, args.seed or dateKey)
if not pageName then
return renderError("No page could be selected")
end
return renderExcerpt(args, pageName)
end
function p._showDate(args)
local sourcePage = getSourcePage(args)
local dateKey = getDateKey(args)
local data, errorMessage = parseSource(sourcePage)
if not data then
return renderError(errorMessage)
end
local pages = data.byDate[dateKey]
if not pages or #pages == 0 then
return renderError('No pages found for "' .. dateKey .. '" in [[' .. sourcePage .. "]]")
end
local month = tonumber(dateKey:sub(1, 2))
local day = tonumber(dateKey:sub(3, 4))
local output = {}
table.insert(output, "<h2>當日展示(" .. tostring(month) .. "月" .. tostring(day) .. "日)</h2>")
for _, pageName in ipairs(pages) do
table.insert(output, "<h3>" .. pageName .. "</h3>")
table.insert(output, renderExcerpt(args, pageName))
end
return table.concat(output, "\n")
end
return p