Jump to content

Module:Resolve category redirect

Permanently protected module
From Wikipedia, the free encyclopedia

local p = {}

local function cleanup( rtarget )
	rtarget = mw.text.trim( rtarget )
	rtarget = mw.ustring.gsub( rtarget, '^1%s*=%s*', '' )
	rtarget = string.gsub( rtarget, '^[Cc]ategory:', '' )
	return rtarget
end

local function escape( text )
	return string.gsub( text or '', '-', '%%-' ) --expand as needed
end

--Returns the target of {{Category redirect}}, if it exists, else returns the original cat.
function p.rtarget( cat, frame )
	cat = string.gsub( cat, '^[Cc]ategory:', '' ) --"!" in cat not recognized by mw.title.makeTitle() otherwise
	if string.match( cat, '[|]' ) then return cat end
	local cattitle = mw.title.makeTitle( 'Category', cat or '' ) --makeTitle() allows ':' in cat names
	if not cattitle then return cat end
	local catcontent = cattitle:getContent()
	if string.match( catcontent or '', '{{ *[Cc]at' ) then --regex common to all possible calls
		catcontent = mw.ustring.gsub( catcontent, '|%s*keep%s*=%s*[yY]?[eE]?[sS]?%s*', '' ) --remove other params
		local getRegex = require('Module:Template redirect regex').main
		local tregex = getRegex('Category redirect')
		for _, v in pairs (tregex) do
			local found = mw.ustring.match( catcontent, v..'%s*|' )
			if found then --refine
				local rtarget = mw.ustring.match( catcontent, v..'%s*|%s*([^{|}]+)}}' ) or --{{Category redirect|...}} (most common)
								mw.ustring.match( catcontent, v..'%s*|%s*([^{|}]+)|' )     --{{Category redirect|...|...}} (2nd most common)
				if rtarget then --normal, plain text target
					return cleanup(rtarget)
				else
					local ty_regex = '%s*|%s*([^{|}]*{{([^#][^{|}]+)}}[^{|}]*)' --$1 nests $2
					local rtarget_ty, ty = mw.ustring.match( catcontent, v..ty_regex )
					if rtarget_ty then --{{Category redirect|...{{Title year}}... (less common)
						local ty_eval = frame:expandTemplate{ title = ty, args = { page = cat } } --frame:newChild doesn't work, use 'page' param instead
						local rtarget_ty_eval = mw.ustring.gsub( rtarget_ty, '{{%s*'..escape(ty)..'%s*}}', ty_eval )
						return cleanup(rtarget_ty_eval)
					else --resolve basic parser functions: e.g. {{#time:j F Y}} on Proposed deletion as of today (very uncommon)
						local pf_regex = '%s*|%s*([^{|}]*{{%s*(#[^{|}#:]+):([^{|}#:]+)}}[^{|}]*)' --$1 nests $2 & $3
						local rtarget_pf, pf, pf_arg = mw.ustring.match( catcontent, v..pf_regex )
						if rtarget_pf then
							local pf_eval = frame:callParserFunction{ name = pf, args = { pf_arg } }
							local rtarget_pf_eval = mw.ustring.gsub( rtarget_pf, '{{%s*'..escape(pf)..'%s*:%s*'..escape(pf_arg)..'%s*}}', pf_eval )
							return cleanup(rtarget_pf_eval)
						else --resolve parser functions with sub-parameter: e.g. {{#time:F Y|now -1 year}} on Orphaned articles from last year
							local pfp_regex = '%s*|%s*([^{|}]*{{%s*(#[^{|}#:]+):([^{|}#:]+)|([^{|}#:]+)}}[^{|}]*)' --$1 nests $2, $3, $4
							local rtarget_pfp, pfp, pfp_arg1, pfp_arg2 = mw.ustring.match( catcontent, v..pfp_regex )
							if rtarget_pfp then
								local pfp_args_gsub = escape(pfp_arg1)..'%s*|%s*'..escape(pfp_arg2)
								local pfp_eval = frame:callParserFunction{ name = pfp, args = { pfp_arg1, pfp_arg2 } }
								local rtarget_pfp_eval = mw.ustring.gsub( rtarget_pfp, '{{%s*'..escape(pfp)..'%s*:%s*'..pfp_args_gsub..'%s*}}', pfp_eval )
								return cleanup(rtarget_pfp_eval)
							else --potential TODO: +loop for multiple templates/parameters
								return cat
							end
						end
	end	end	end	end	end
	return cat
end

function p.main( frame )
	local args = frame:getParent().args
	local cat  = mw.text.trim( args[1] or '' )
	if (cat == '') or (cat == nil) then
		return ''
	end
	return p.rtarget( cat, frame )
end

return p