跳转到内容

模組:Selected recent additions

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

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

local randomModule = require('Module:Random')

function cleanupArgs(argsTable)
	local cleanArgs = {}
	for key, val in pairs(argsTable) do
		if type(val) == 'string' then
			val = val:match('^%s*(.-)%s*$')
			if val ~= '' then
				cleanArgs[key] = val
			end
		else
			cleanArgs[key] = val
		end
	end
	return cleanArgs
end

function isAffirmed(val)
	if not(val) then return false end
	local affirmedWords = ' add added affirm affirmed include included on true yes y '
	return string.find(affirmedWords, ' '..string.lower(val)..' ', 1, true ) and true or false
end

function makeOutput(allItems, maxItems, more, notRandom)
	local output
	if notRandom then
		output = ''
		local itemIndex = 1
		local maxCount = math.min(#allItems, maxItems)
		while itemIndex <= maxCount do
			output = output .. allItems[itemIndex] .. '\n'
			itemIndex = itemIndex + 1
		end
	else
		local randomiseArgs = {
			['t'] = allItems,
			['limit'] = maxItems
		}
		local randomisedItems = randomModule.main('array', randomiseArgs )
		output = table.concat(randomisedItems, '\n')
	end
	if more then
		output = output .. '\n' .. more
	end
	return mw.text.trim(output)
end

-- 清理wikitext以便进行模式匹配
-- @param wikitext string: 原始wikitext行
-- @param frame table: Scribunto frame对象,用于preprocessString
function cleanForPatternMatching(wikitext, frame)
	local cleaned = wikitext
	-- 移除 wikilink 的方括号, 保留显示文本或链接目标
	-- [[链接目标|显示文本]] -> 显示文本
	-- [[链接目标]] -> 链接目标
	cleaned = mw.ustring.gsub(cleaned, "%[%[([^%]|]+)%|([^%]]+)%]%]", "%2")
	cleaned = mw.ustring.gsub(cleaned, "%[%[([^%]]+)%]%]", "%1")
	
	-- 处理字词转换标记 -{...}- 或 -{R|...}-
	-- 使用 frame:preprocessString 将标记转换为当前页面语言环境下的实际显示文本
	-- 模式 %-%{R?[^%}]*%}%- 匹配 -{...}-, -{R...}-, -{R|...}- 等形式
	if frame then -- 确保 frame 对象存在
		cleaned = mw.ustring.gsub(cleaned, "%-%{R?[^%}]*%}%-", function(match)
			return frame:preprocessString(match)
		end)
	else
		-- 如果没有 frame 对象 (例如在测试环境中直接调用此函数),
		-- 则采取降级策略,例如移除标记或保留原始标记。
		-- 这里选择简单移除,但在实际模块调用中 frame 应该总是可用的。
		cleaned = mw.ustring.gsub(cleaned, "%-%{R?[^%}]*%}%-", "")
	end

	-- 移除加粗/斜体标记 ('', ''', ''''')
	cleaned = mw.ustring.gsub(cleaned, "['']+", "")

	-- 移除HTML注释
	cleaned = mw.ustring.gsub(cleaned, "%<%!%-%-(.-)%-%-%>", "")
	
	return cleaned
end

function makeCollapsed(outerText, innerText)
	return "{{Hidden begin | titlestyle = font-weight:normal | title = " .. outerText .. "}}" .. innerText .. "{{Hidden end}}"
end

-- 从指定存档子页面获取新条目推荐项目
-- @param frame table: Scribunto frame对象
function getRecentAdditions(archivePagePath, keepPatterns, skipPatterns, showWikitext, frame)
	local title = mw.title.new(archivePagePath)
	if not title or not title.exists then
		return {}
	end
	local raw = title:getContent()
	if not raw then
		return {}
	end

	local items = {}
	local lines = mw.text.split(raw, '\n')

	for _, line in ipairs(lines) do
		line = line:match('^%s*(.-)%s*$') 
		if line and mw.ustring.match(line, '^%*%s*') then -- 中文维基DYK以 "* " 开头
			local originalItemText = line
			-- 传递 frame 对象给 cleanForPatternMatching
			local textForMatching = cleanForPatternMatching(originalItemText, frame)

			local keep = false
			if #keepPatterns == 0 then -- 如果没有指定 keepPatterns,则默认保留 (仍需通过 skipPatterns 检查)
				keep = true
			else
				for _, keepPatt in pairs(keepPatterns) do
					if mw.ustring.find(textForMatching, keepPatt, 1, false) then
						keep = true
						break
					end
				end
			end

			local skip = false
			if #skipPatterns > 0 then
				for _, skipPatt in pairs(skipPatterns) do
					if mw.ustring.find(textForMatching, skipPatt, 1, false) then
						skip = true
						break
					end
				end
			end

			if keep and not skip then
				local cleanItem = originalItemText
				cleanItem = mw.ustring.gsub(cleanItem, "%<%!%-%-(.-)%-%-%>", "")

				if showWikitext then
					local itemWikitext = "<pre>" .. mw.text.nowiki(cleanItem) .. "</pre>"
					cleanItem = makeCollapsed(cleanItem, itemWikitext)
				end
				table.insert(items, cleanItem)
			end
		end
	end
	return items
end

-- 获取过去数月的新条目推荐项目
-- @param frame table: Scribunto frame对象
function getItems(maxMonths, patterns, skipPatterns, showWikitext, frame)
	local allItems = {}
	local currentDateTime = os.date('*t')
	local currentYear  = tonumber(currentDateTime.year)
	local currentMonth = tonumber(currentDateTime.month)

	local monthsAgo = 0
	while monthsAgo < maxMonths do
		local targetYear = currentYear
		local targetMonth = currentMonth - monthsAgo
		
		while targetMonth <= 0 do
			targetMonth = targetMonth + 12
			targetYear = targetYear - 1
		end
		
		local archiveSubpage = string.format("%d年%d月", targetYear, targetMonth)
		local archivePagePath = 'Wikipedia:新条目推荐/存档/' .. archiveSubpage
		
		-- 传递 frame 对象给 getRecentAdditions
		local monthlyItems = getRecentAdditions(archivePagePath, patterns, skipPatterns, showWikitext, frame)
		for i, item in ipairs(monthlyItems) do
			table.insert(allItems, item)
		end
		monthsAgo = monthsAgo + 1
	end
	return allItems
end

function getPatterns(args, prefix)
	local patterns = {}
	local ii = 1
	while args[prefix and prefix..ii or ii] do
		patterns[ii] = args[prefix and prefix..ii or ii]
		ii = ii + 1
	end
	return patterns
end

local p = {}

p.main = function(frame)
	local parent = frame.getParent(frame)
	local parentArgs = parent.args
	local args = cleanupArgs(parentArgs)

	if args['not'] and not args['not1'] then
		args['not1'] = args['not']
	end
	
	local patterns = getPatterns(args)
	if #patterns < 1 and not isAffirmed(args.showall) then
		-- 使用 frame:expandTemplate 来显示标准错误消息模板 (如果适用)
		return frame:expandTemplate{ title = 'Error', args = { '未设置搜索关键词 (参数 1, 2, ...),或者设置 <code>showall=yes</code> 来显示所有条目。' } }
	end

	local skipPatterns = getPatterns(args, 'not')
	local months = tonumber(args.months) or 12 -- 默认搜索过去12个月
	local showWikitext = isAffirmed(args.wikitext)

	-- 传递 frame 对象给 getItems
	local allItems = getItems(months, patterns, skipPatterns, showWikitext, frame)
	if #allItems < 1 then
		return args.header and '' or (args.none or '未找到符合条件的新条目推荐。')
	end

	local maxItems = tonumber(args.max) or 5 -- 默认最多显示5条
	local moreLinkText = args.more
	if isAffirmed(args.more) then
		moreLinkText = "'''[[Wikipedia:新条目推荐/存档|更多新条目推荐...]]'''"
	elseif type(moreLinkText) == 'string' and moreLinkText == '' then -- 如果 more="" (空字符串), 则不显示
		moreLinkText = nil
	end

	local nonRandom = isAffirmed(args.latest)
	local output = makeOutput(allItems, maxItems, moreLinkText, nonRandom)

	if args.header then
		local footer = args.footer or '{{Box-footer}}' 
		-- 此处逻辑调整:如果allItems为空,在getItems之后已经返回了,所以这里不需要再次检查 #allItems < 1 来插入 'none' 消息
		output = args.header .. '\n' .. output .. '\n' .. footer
	end

	local needsExpansion = mw.ustring.find(output, '{{', 1, true)	
	if needsExpansion then
		return frame:preprocess(output)
	else 
		return output
	end
end

return p