跳转到内容

模組:Loop/archive

维基百科,自由的百科全书

这是本页的一个历史版本,由SunAfterRain留言 | 贡献2025年2月22日 (六) 14:11编辑。这可能和当前版本存在着巨大的差异。

local p = {}
local mError = setmetatable({}, {
	__index = function (t, k)
		local _mError = require('Module:Error')
		mError = _mError
		return _mError[k]
	end
})
local mIfexist
local mTemplateParameters
local mYesno

local function inArray(item, arr)
	for i, v in ipairs(arr) do
		if item == v then
			return v
		end
	end
	return nil
end

local function titleExists(title, usePF)
	if not mIfexist then
		mIfexist = require('Module:Ifexist')
	end
	return mIfexist[usePF and '_parseFunctionExists' or '_luaExists'](title)
end

local function yesno(value)
	if not mYesno then
		mYesno = require('Module:Yesno')
	end
	return mYesno(value)
end

local function makeError(message)
	return mError.error({ '[[Module:Loop/archive]]錯誤:' .. message })
end

local function buildLink(titleText, display, checkExists, checkExistsPF)
	local success, title = pcall(mw.title.new, titleText)
	if not success or not title then
		return ''
	end
	if checkExists and not titleExists(title) then
		return string.format('<!--noexist:lua--><span style="color: var(--color-disabled, #a2a9b1);">%s</span>', display)
	end
	if checkExistsPF then
		if titleExists(title, true) then
			return string.format('[[%s|%s]]', title.prefixedText, display)
		else
			return string.format('<!--noexist:pf--><span style="color: var(--color-disabled, #a2a9b1);">%s</span>', display)
		end
	end
	return string.format('[[%s|%s]]', title.prefixedText, display)
end

local function formatTemplate(template, vars)
	local result = ""

	local i = 1
	while i <= mw.ustring.len(template) do
		local char = mw.ustring.sub(template, i, i)
		if char == "%" then
			local nextChar = mw.ustring.sub(template, i + 1, i + 1)
            local nextNextChar = mw.ustring.sub(template, i + 2, i + 2)
			if nextChar == "%" then
				result = result .. "%"
				i = i + 2
			elseif vars[nextChar .. nextNextChar] then
				result = result .. vars[nextChar .. nextNextChar]
				i = i + 3
			elseif vars[nextChar] then
				result = result .. vars[nextChar]
				i = i + 2
			else
				error("Invalid format sequence: %" .. (nextChar or ""))
			end
		else
			result = result .. char
			i = i + 1
		end
	end

	return result
end

local function escapePrefix(prefix)
	prefix = prefix:gsub('%%', '%%%%'):gsub('%/$', '')
	-- omit gsub 2nd return value
	return prefix
end

local currentYear = tonumber(os.date('%Y'))
local currentMonth = tonumber(os.date('%m'))

--[=[
byYear 提供的變數:
年分
%Y 對應解析器函數的 Y
]=]
function p.byYear(frame)
	local args = frame.args
	local prefix = args.prefix -- 存檔母頁面
	local template = args.template -- 存檔頁面名模板 預設是套用 prefix/%Y年
	if not template and not prefix then
		return makeError('至少必須指定前綴 <code>prefix</code> 或 <code>template</code> 其中一個參數。')
	end
	local startYear = tonumber(args.start) -- 循環開始年分
	local endYear = tonumber(args['end']) or currentYear -- 循環終止年分
	local range = tonumber(args.range) or 1 -- 循環年分分組
	local offset = tonumber(args.offset) or 0 -- 正常會用 2001~2005 2006~2010 此方法分組 此參數指定後對範圍進行偏移偏移
	local checkExists = args.checkExists and yesno(args.checkExists) or false -- 檢查存檔目標是否存在
	local checkExistsPF = not checkExists and (args.checkExistsPF and yesno(args.checkExistsPF) or true) -- 檢查存檔目標是否存在(解析器函式版)
	local outputTableBox = args.outputTableBox and yesno(args.outputTableBox) or false -- 是否輸出表格的框 {| |}
	local tableProps = outputTableBox and (args.tableProps ~= nil and args.tableProps or 'style="width:100%;"') -- 表格屬性組
	local disableCurrentBold = args.disableCurrentBold and yesno(args.disableCurrentBold) or false -- 是否阻止對當前年分加粗

	template = template or '%prefix/%Y年'
	template = template:gsub('%%prefix', escapePrefix(prefix))

	local output = {}
	if outputTableBox then
		local tableBox = '{|'
		if tableProps then
			tableBox = tableBox .. ' ' .. mw.text.trim(tableProps)
		end
		output[#output + 1] = tableBox
	end
	local index = math.ceil((startYear - offset) / range) - 1
	while index * range + offset < endYear do
		output[#output + 1] = '|-'
		for i = 1, range, 1 do
			local curYear = index * range + offset + i
			local link = (curYear >= startYear and curYear <= endYear)
				and buildLink(
					formatTemplate(template, {
						Y = tostring(curYear)
					}),
					string.format(
						(curYear == currentYear and not disableCurrentBold)
							and '<span style="font-weight: bold;">%4d</span>'
							or '%4d',
						curYear
					),
					checkExists,
					checkExistsPF
				)
				or string.format('<!--%4d-->', curYear)
			output[#output + 1] = '|' .. link
		end
		output[#output + 1] = '|style="text-align: right;"|年'
		index = index + 1
	end
	if outputTableBox then
		output[#output + 1] = '|}'
	end
	return table.concat(output, '\n')
end

local function getMonthGroup(month, monthInGroup)
	return math.ceil(month / monthInGroup)
end

--[=[
byMonth 提供的變數:
年分
%Y 對應解析器函數的 Y

月份(monthInGroup = 1 時才有定義)
%m 對應解析器函數的 m,有補 0
%n 對應解析器函數的 n,沒補 0

該組開始月份
%Sm 對應解析器函數的 m,有補 0
%Sn 對應解析器函數的 n,沒補 0

該組結束月份
%Em 對應解析器函數的 m,有補 0
%En 對應解析器函數的 n,沒補 0

當前組是該年的第幾組(例如 monthInGroup = 3 時 %gi 就是第幾季)
%gI 有補 0
%gi 沒補 0
]=]
function p.byMonth(frame)
	local args = frame.args
	local prefix = args.prefix -- 存檔母頁面
	local template = args.template -- 存檔頁面名模板 預設是套用 prefix/%Y年/%n月(monthInGroup = 1) / prefix/%Y年/%Sn-%En月(monthInGroup > 1)
	if not template and not prefix then
		return makeError('至少必須指定前綴 <code>prefix</code> 或 <code>template</code> 其中一個參數。')
	end
	local startYear = tonumber(args.startYear) -- 循環開始年分
	local startMonth = tonumber(args.startMonth) -- 循環開始月份
	local endYear = tonumber(args.endYear) or currentYear -- 循環終止年分
	local endMonth = tonumber(args.endMonth) or currentMonth -- 循環終止月份
	local monthInGroup = tonumber(args.monthInGroup) or 1 -- 循環月份分組
	if monthInGroup == 12 then
		return makeError('byMonth 不接受僅把一年分成一組。')
	elseif 12 % monthInGroup ~= 0 then
		return makeError('無法用 ' .. range .. ' 整除月份總數 12。')
	end
	
	local startMonthGroup = getMonthGroup(startMonth, monthInGroup)
	local endMonthGroup = getMonthGroup(endMonth, monthInGroup)
	template = template or (monthInGroup > 1 and '%prefix/%Y年/%Sn-%En月' or '%prefix/%Y年/%n月')
	template = template:gsub('%%prefix', escapePrefix(prefix))

	local checkExists = args.checkExists and yesno(args.checkExists) or false -- 檢查存檔目標是否存在
	local checkExistsPF = not checkExists and (args.checkExistsPF and yesno(args.checkExistsPF) or true) -- 檢查存檔目標是否存在(解析器函式版)
	local outputTableBox = args.outputTableBox and yesno(args.outputTableBox) or false -- 是否輸出表格的框 {| |}
	local tableProps = outputTableBox and (args.tableProps ~= nil and args.tableProps or 'style="width: 100%;"') -- 表格屬性組
	local disableCurrentBold = args.disableCurrentBold and yesno(args.disableCurrentBold) or false -- 是否阻止對當前月份組加粗

	local output = {}
	if outputTableBox then
		local tableBox = '{|'
		if tableProps then
			tableBox = tableBox .. ' ' .. mw.text.trim(tableProps)
		end
		output[#output + 1] = tableBox
	end
	for year = startYear, endYear, 1 do
		output[#output + 1] = '|-'
		output[#output + 1] = string.format('!style="text-align: left;"|%4d年', year)
		for monthGroup = 1, 12 / monthInGroup, 1 do
			local shouldPrintLink = not ((year == startYear and monthGroup < startMonthGroup) or (year == endYear and monthGroup > endMonthGroup))
			local link
			if monthInGroup == 1 then
				link = shouldPrintLink
					and buildLink(
						formatTemplate(template, {
							Y = tostring(year),
							m = string.format('%2d', monthGroup),
							n = tostring(monthGroup),
							Sm = string.format('%2d', monthGroup),
							Sn = tostring(monthGroup),
							Em = string.format('%2d', monthGroup),
							En = tostring(monthGroup),
							gI = string.format('%2d', monthGroup),
							gi = tostring(monthGroup),
						}),
						string.format(
							(year == endYear and monthGroup == endMonthGroup and not disableCurrentBold)
								and '<span style="font-weight: bold;">%d</span>'
								or '%d',
							monthGroup
						),
						checkExists,
						checkExistsPF
					)
					or string.format('<!--%d-->', monthGroup)
			else
				local startMonth = (monthGroup - 1) * monthInGroup + 1
				local endMonth = monthGroup * monthInGroup
				link = shouldPrintLink
					and buildLink(
						formatTemplate(template, {
							Y = tostring(year),
							Sm = string.format('%2d', startMonth),
							Sn = tostring(startMonth),
							Em = string.format('%2d', endMonth),
							En = tostring(endMonth),
							gI = string.format('%2d', monthGroup),
							gi = tostring(monthGroup),
						}),
						string.format(
							(year == endYear and monthGroup == endMonthGroup and not disableCurrentBold)
								and '<span style="font-weight: bold;">%d-%d</span>'
								or '%d-%d',
							startMonth, endMonth
						),
						checkExists,
						checkExistsPF
					)
					or string.format('<!--%d-%d-->', startMonth, endMonth)
			end
			output[#output + 1] = string.format('|%s', link)
		end
		output[#output + 1] = '|style="text-align: right;"|月'
	end
	if outputTableBox then
		output[#output + 1] = '|}'
	end
	return table.concat(output, '\n')
end

return p