Module:Resolve category redirect

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

--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 catcontent = mw.title.makeTitle( 'Category', cat or '' ):getContent() --makeTitle() allows ':' in cat names
	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_orig, ty = mw.ustring.match( catcontent, v..ty_regex )
					if rtarget_orig then --{{Category redirect|...{{Title year}}... (least common)
						local ty_eval = frame:expandTemplate{ title = ty, args = { page = cat } } --frame:newChild doesn't work, use 'page' param instead
						local rtarget_eval = mw.ustring.gsub( rtarget_orig, '{{%s*'..ty..'%s*}}', ty_eval )
						return cleanup(rtarget_eval)
					else --potential TODO: 1) +loop for multiple templates, 2) allow sub-parameters
						return cat
	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