模块:生日分类
可在模块:生日分类/doc创建此模块的帮助文档
--[=[
供[[模板:生日]]使用,亦可以在其他模块中调用`from_text`、`from_month_day`两个函数
测试例:
{{生日|1年2月3日}} -> 1年[[:分类:2月3日|2月3日]][[分类:2月3日]]
{{生日|2月3日}} / {{生日|2|3}} -> [[:分类:2月3日|2月3日]][[分类:2月3日]]
{{生日|1年<ref>……</ref>2月3日}} -> 1年<ref>……</ref>[[:分类:2月3日|2月3日]][[分类:2月3日]]
{{生日|2月3日<ref>……</ref>}} -> [[:分类:2月3日|2月3日]]<ref>……</ref>[[分类:2月3日]]
{{生日|2月30日}} -> 2月30日[[分类:错误生日]]
{{生日|2月3.0日}} -> 2月3.0日[[分类:错误生日]]
{{生日|2}} -> 2[[分类:错误生日]]
{{生日|阿巴阿巴}} -> 阿巴阿巴[[分类:错误生日]]
]=]
local p = {}
local MAX_DAY_OF_MONTH = {
-- 1 2 3 4 5 6 7 8 9 10 11 12
31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
}
local REF_MARKER_PATTERN = '\127\'"`UNIQ%-%-[rR][eE][fF]%-%x%x%x%x%x%x%x%x%-QINU`"\'\127'
local function ns0_category(category)
return (mw.title.getCurrentTitle().namespace == 0) and ('[[分类:'..category..']]') or ''
end
local function for_hacking_template(date)
return mw.getCurrentFrame():callParserFunction('#vardefine', '生日日期', date)
end
---@param month string | integer
---@param day string | integer
---@return string? # 错误日期返回nil,正确日期返回分类链接和分类
local function month_day_to_wikitext(month, day)
month, day = tonumber(month), tonumber(day)
local max_day = MAX_DAY_OF_MONTH[month]
if not (max_day and day and day >= 1 and day <= max_day) then
return nil
end
local month_day = month..'月'..day..'日'
return '[[:分类:'..month_day..'|'..month_day..']]'..ns0_category(month_day)
end
---@param text string
---@param ignore_error boolean? # 错误时不添加“错误生日”分类
---@return string
function p.from_text(text, ignore_error)
local var = ''
repeat -- 仅执行一次,当出现错误时跳出
local prefix, month, day, suffix = text:match('^(.-)(%d+)月(%d+)日(.-)$')
if not prefix then -- string库比mw.ustring更快,也因此不能写“[日号]”
prefix, month, day, suffix = text:match('^(.-)(%d+)月(%d+)号(.-)$')
end
if not prefix then break end
var = for_hacking_template(month..'月'..day..'日')
if prefix ~= '' and prefix:gsub('^..-年', '', 1):gsub(REF_MARKER_PATTERN, '') ~= '' then
-- “X月X日”前面的不是“X年”+任意数量的“<ref>……</ref>”
break
end
if suffix ~= '' and suffix:gsub(REF_MARKER_PATTERN, '') ~= '' then
-- “X月X日”后面的不是任意数量的“<ref>……</ref>”
break
end
local wikitext = month_day_to_wikitext(month, day)
if not wikitext then break end -- 月份或日期不合法
return var..prefix..wikitext..suffix
until true
if ignore_error then return var..text end
return var..text..ns0_category('错误生日')
end
---@param month string
---@param day string
---@param ignore_error boolean? # 错误时不添加“错误生日”分类
---@return string
function p.from_month_day(month, day, ignore_error)
local result = month_day_to_wikitext(month, day)
if result then return result end
result = month..'月'..day..'日'
if ignore_error then return result end
return result..ns0_category('错误生日')
end
function p.main(frame)
local args = frame.args
local arg1, arg2 = args[1], args[2]
arg1 = arg1 and mw.text.trim(arg1)
if not arg1 or arg1 == '' then
return ''
end
local ignore_error = args.ft and args.ft ~= ''
arg2 = arg2 and mw.text.trim(arg2)
if arg2 and arg2 ~= '' then
return p.from_month_day(arg1, arg2, ignore_error)
end
return p.from_text(arg1, ignore_error)
end
function p.from_parent(frame)
return p.main(frame:getParent())
end
return p