跳转到内容

模組:Selected recent additions

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

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

local randomModule = require('Module:Random')

-- Helper function to clean table arguments (remove whitespace, empty strings)
function cleanupArgs(argsTable)
	local cleanArgs = {}
	for key, val in pairs(argsTable) do
		if type(val) == 'string' then
			val = val:match('^%s*(.-)%s*$') -- Trim whitespace
			if val ~= '' then
				cleanArgs[key] = val
			end
		else
			cleanArgs[key] = val -- Keep non-string values as is
		end
	end
	return cleanArgs
end

-- Helper function to check for affirmative values (yes, true, etc.)
function isAffirmed(val)
	if not val then return false end
	-- Simplified list, add more if needed for Chinese context, though 'yes'/'true' are common in params
	local affirmedWords = ' add added affirm affirmed include included on true yes y ' 
	return string.find(affirmedWords, ' ' .. string.lower(tostring(val)) .. ' ', 1, true) and true or false
end

-- Helper function to generate output string from items
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 -- Added newline before 'more' for better formatting
	end
	return mw.text.trim(output)
end

-- Helper function to clean wikitext for pattern matching
function cleanForPatternMatching(wikitext)
	-- Remove wikilink brackets, keeping the link text (or display text if piped)
	local cleaned = mw.ustring.gsub(wikitext, "%[%[([^%]|]-)%]%]", "%1") -- [[Link]] -> Link
	cleaned = mw.ustring.gsub(cleaned, "%[%[.-%|(.-)%]%]", "%1")     -- [[Article|Display]] -> Display
	-- Remove external links, keeping the display text if available, otherwise remove all
	cleaned = mw.ustring.gsub(cleaned, "%[%S+%s+(.-)%]", "%1")      -- [http://example.com Text] -> Text
	cleaned = mw.ustring.gsub(cleaned, "%[%S+%]"," ")               -- [http://example.com] -> " " (space to avoid merging words)
	-- Remove any remaining pipes that might affect matching (e.g. from templates not fully substituted)
	cleaned = mw.ustring.gsub(cleaned, "%|"," ")
	-- Remove bold/italic markup
	cleaned = mw.ustring.gsub(cleaned, "'''", "")
	cleaned = mw.ustring.gsub(cleaned, "''", "")
	return cleaned
end

-- Helper function to create a collapsible section
function makeCollapsed(outerText, innerText)
	-- Using standard Chinese Wikipedia hidden templates if names differ, adjust as needed.
	-- Assuming {{Hidden begin}} and {{Hidden end}} are standard.
	return "{{Hidden begin | titlestyle = font-weight:normal | title = " .. outerText .. "}}" .. innerText .. "{{Hidden end}}"
end

-- Get recent additions for a specific subpage (archive month)
function getRecentAdditions(subpagePath, keepPatterns, skipPatterns, showWikitext, contentLang)
	local title = mw.title.new(subpagePath)
	if not title or not title.exists then
		return {} -- Page doesn't exist or invalid title
	end
	local raw = title:getContent()
	if not raw then
		return {} -- No content
	end

	local converter = contentLang:getConverter()
	
	-- Chinese DYK entries are typically list items starting with '*'
	-- Each item is usually on its own line.
	local itemPattern = '\n%*%s?.*' -- Match lines starting with '*'
	local items = {}

	for itemLine in mw.ustring.gmatch('\n' .. raw, itemPattern) do -- Prepend newline to match first item
		local originalItem = mw.ustring.gsub(itemLine, '^\n%*%s*', '%* ') -- Normalize: ensure it starts with "* "
		
		-- Apply word conversion for matching and for the final display item
		local convertedItemForMatching = converter:convert(originalItem)
		local textToSearch = cleanForPatternMatching(convertedItemForMatching)
		
		local keep = false
		local skip = false
		
		-- Check keep patterns
		if #keepPatterns == 0 then -- If no keepPatterns, keep all by default (original module implies this for empty patterns list but it's better to be explicit or error)
			keep = true -- Or handle as an error: "Search pattern not set" is handled in main. If patterns is empty, this path shouldn't be hit.
		else
			for _, keepPatt in ipairs(keepPatterns) do
				if mw.ustring.find(textToSearch, keepPatt, 1, false) then -- Plain string find
					keep = true
					break
				end
			end
		end

		-- Check skip patterns if we intend to keep it
		if keep and #skipPatterns > 0 then
			for _, skipPatt in ipairs(skipPatterns) do
				if mw.ustring.find(textToSearch, skipPatt, 1, false) then -- Plain string find
					skip = true
					break
				end
			end
		end

		if keep and not skip then
			local displayItem = converter:convert(originalItem) -- Convert the original item again for display to ensure consistency

			-- Remove HTML comments from the display item
			displayItem = mw.ustring.gsub(displayItem, "%<%!%-%-(.-)%-%-%>", "")
			
			if showWikitext then
				-- For 'showWikitext', we show the wikitext of the *converted* item
				local itemWikitext = "<pre>" .. mw.text.nowiki(displayItem) .. "</pre>"
				displayItem = makeCollapsed(displayItem, itemWikitext)
			end
			table.insert(items, mw.text.trim(displayItem))
		end
	end
	return items
end

-- Get items from archives over a span of months
function getItems(maxMonths, patterns, skipPatterns, showWikitext)
	local allItems = {}
	local zhLang = mw.language.new('zh') -- For date formatting specifically for archive paths
	local contentLang = mw.language.getContentLanguage() -- For -{}- conversion

	local currentYear  = tonumber(zhLang:formatDate('Y', 'now'))
	local currentMonth = tonumber(zhLang:formatDate('n', 'now'))

	for monthsAgo = 0, maxMonths - 1 do
		local targetMonth = currentMonth - monthsAgo
		local targetYear = currentYear
		
		-- Adjust year and month if targetMonth goes into previous years
		while targetMonth <= 0 do
			targetMonth = targetMonth + 12
			targetYear = targetYear - 1
		end
		
		-- Format: Wikipedia:新条目推荐/存档/YYYY年M月
		local subpageName = targetYear .. '年' .. targetMonth .. '月'
		local pagePath = 'Wikipedia:新条目推荐/存档/' .. subpageName
		
		local monthlyItems = getRecentAdditions(pagePath, patterns, skipPatterns, showWikitext, contentLang)
		for _, item in ipairs(monthlyItems) do
			table.insert(allItems, item)
		end
	end
	return allItems
end

-- Get patterns from arguments (e.g., 1, 2, 3 or not1, not2, not3)
function getPatterns(args, prefix)
	local patterns = {}
	local i = 1
	local key
	while true do
		key = prefix and (prefix .. i) or tostring(i)
		if args[key] then
			table.insert(patterns, args[key])
		else
			break
		end
		i = i + 1
	end
	return patterns
end

local p = {}

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

	-- Allow 'not' as an alias for 'not1' if 'not1' isn't set
	if args['not'] and not args['not1'] then
		args['not1'] = args['not']
	end
	
	local patterns = getPatterns(args)
	if #patterns < 1 then
		return frame:expandTemplate{ title = 'Error', args = { '未设置搜索样式(参数1、2等)。' } } -- Using {{Error}} template for better visibility
	end

	local skipPatterns = getPatterns(args, 'not')

	local months = tonumber(args.months) or 6 -- Default to 6 months, 30 seemed a bit much for DYK
	
	local showWikitext = isAffirmed(args.wikitext)

	local allItems = getItems(months, patterns, skipPatterns, showWikitext)
	
	if #allItems < 1 then
		return args.header and '' or args.none or '没有找到符合条件的项目。' -- Localized "none" message
	end

	local maxItems = tonumber(args.max) or 6

	local moreLinkText = args.more
	if isAffirmed(args.more) or (type(args.more) == 'string' and args.more == '') then -- if 'more=yes' or 'more='
		-- Default "more" link for Chinese Wikipedia
		moreLinkText = "'''[[Wikipedia:新条目推荐|更多新条目推荐...]]'''"
	elseif type(args.more) == 'string' and args.more ~= '' then
		-- User provided custom text for 'more'
		moreLinkText = args.more 
	else
		moreLinkText = nil -- No 'more' link if not specified or affirmed
	end

	local nonRandom = isAffirmed(args.latest) -- 'latest' implies not random, show newest first from collected

	local output = makeOutput(allItems, maxItems, moreLinkText, nonRandom)
	
	if args.header then
		output = args.header .. '\n' .. output
		if args.footer then -- Only add footer if header is present and footer is specified
			output = output .. '\n' .. args.footer
		elseif args.header then -- Default footer if header is present but no custom footer
			output = output .. '\n' .. '{{Box-footer}}'
		end
	end
	
	-- Preprocess the output if it contains templates (e.g., from header, footer, or makeCollapsed)
	-- Check for '{', which might indicate a template or other complex wikitext
	if mw.ustring.find(output, '{', 1, true) then
		return frame:preprocess(output)
	else 
		return output
	end
end

return p