<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.cultopedia.org/index.php?action=history&amp;feed=atom&amp;title=Module%3AFootballer_positions</id>
	<title>Module:Footballer positions - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://www.cultopedia.org/index.php?action=history&amp;feed=atom&amp;title=Module%3AFootballer_positions"/>
	<link rel="alternate" type="text/html" href="https://www.cultopedia.org/index.php?title=Module:Footballer_positions&amp;action=history"/>
	<updated>2026-04-06T01:52:34Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.44.5</generator>
	<entry>
		<id>https://www.cultopedia.org/index.php?title=Module:Footballer_positions&amp;diff=2260&amp;oldid=prev</id>
		<title>imported&gt;S.A. Julio: add alias</title>
		<link rel="alternate" type="text/html" href="https://www.cultopedia.org/index.php?title=Module:Footballer_positions&amp;diff=2260&amp;oldid=prev"/>
		<updated>2025-12-26T21:46:02Z</updated>

		<summary type="html">&lt;p&gt;add alias&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local p = {}&lt;br /&gt;
&lt;br /&gt;
local mHList = require(&amp;#039;Module:List&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
-- Position definitions: {names/abbrevs}, link, display&lt;br /&gt;
-- Use %D for dash placeholder, %C for centre/center placeholder&lt;br /&gt;
local positionDefs = {&lt;br /&gt;
	-- Goalkeepers&lt;br /&gt;
	{{&amp;quot;goalkeeper&amp;quot;, &amp;quot;goalie&amp;quot;, &amp;quot;keeper&amp;quot;, &amp;quot;gk&amp;quot;}, &amp;quot;Goalkeeper (association football)&amp;quot;, &amp;quot;goalkeeper&amp;quot;},&lt;br /&gt;
	-- Defenders&lt;br /&gt;
	{{&amp;quot;defender&amp;quot;, &amp;quot;defence&amp;quot;, &amp;quot;defense&amp;quot;, &amp;quot;back&amp;quot;, &amp;quot;df&amp;quot;}, &amp;quot;Defender (association football)&amp;quot;, &amp;quot;defender&amp;quot;},&lt;br /&gt;
	{{&amp;quot;centreback&amp;quot;, &amp;quot;centralback&amp;quot;, &amp;quot;cb&amp;quot;}, &amp;quot;Defender (association football)#Centre-back&amp;quot;, &amp;quot;%Ccentre%Dback&amp;quot;},&lt;br /&gt;
	{{&amp;quot;centredefender&amp;quot;}, &amp;quot;Defender (association football)#Centre-back&amp;quot;, &amp;quot;%Ccentre-back&amp;quot;},&lt;br /&gt;
	{{&amp;quot;centraldefender&amp;quot;, &amp;quot;centraldefence&amp;quot;, &amp;quot;centraldefense&amp;quot;, &amp;quot;cd&amp;quot;}, &amp;quot;Defender (association football)#Centre-back&amp;quot;, &amp;quot;central defender&amp;quot;},&lt;br /&gt;
	{{&amp;quot;centrehalf&amp;quot;}, &amp;quot;Defender (association football)#Centre-back&amp;quot;, &amp;quot;%Ccentre%Dhalf&amp;quot;},&lt;br /&gt;
	{{&amp;quot;fullback&amp;quot;, &amp;quot;outsideback&amp;quot;, &amp;quot;fb&amp;quot;}, &amp;quot;Defender (association football)#Full-back&amp;quot;, &amp;quot;full%Dback&amp;quot;},&lt;br /&gt;
	{{&amp;quot;wingback&amp;quot;, &amp;quot;wb&amp;quot;}, &amp;quot;Defender (association football)#Wing-back&amp;quot;, &amp;quot;wing%Dback&amp;quot;},&lt;br /&gt;
	{{&amp;quot;sweeper&amp;quot;, &amp;quot;sw&amp;quot;}, &amp;quot;Defender (association football)#Sweeper&amp;quot;, &amp;quot;sweeper&amp;quot;},&lt;br /&gt;
	{{&amp;quot;libero&amp;quot;}, &amp;quot;Defender (association football)#Sweeper&amp;quot;, &amp;quot;libero&amp;quot;},&lt;br /&gt;
	{{&amp;quot;rightback&amp;quot;, &amp;quot;rightdefender&amp;quot;, &amp;quot;rb&amp;quot;}, &amp;quot;Defender (association football)#Full-back&amp;quot;, &amp;quot;right%Dback&amp;quot;},&lt;br /&gt;
	{{&amp;quot;rightfullback&amp;quot;}, &amp;quot;Defender (association football)#Full-back&amp;quot;, &amp;quot;right full%Dback&amp;quot;},&lt;br /&gt;
	{{&amp;quot;leftback&amp;quot;, &amp;quot;leftdefender&amp;quot;, &amp;quot;lb&amp;quot;}, &amp;quot;Defender (association football)#Full-back&amp;quot;, &amp;quot;left%Dback&amp;quot;},&lt;br /&gt;
	{{&amp;quot;leftfullback&amp;quot;}, &amp;quot;Defender (association football)#Full-back&amp;quot;, &amp;quot;left full%Dback&amp;quot;},&lt;br /&gt;
	{{&amp;quot;rightwingback&amp;quot;, &amp;quot;rwb&amp;quot;}, &amp;quot;Defender (association football)#Wing-back&amp;quot;, &amp;quot;right wing%Dback&amp;quot;},&lt;br /&gt;
	{{&amp;quot;leftwingback&amp;quot;, &amp;quot;lwb&amp;quot;}, &amp;quot;Defender (association football)#Wing-back&amp;quot;, &amp;quot;left wing%Dback&amp;quot;},&lt;br /&gt;
	-- Midfielders&lt;br /&gt;
	{{&amp;quot;midfielder&amp;quot;, &amp;quot;midfield&amp;quot;, &amp;quot;mf&amp;quot;}, &amp;quot;Midfielder&amp;quot;, &amp;quot;midfielder&amp;quot;},&lt;br /&gt;
	{{&amp;quot;halfback&amp;quot;, &amp;quot;hb&amp;quot;}, &amp;quot;Midfielder&amp;quot;, &amp;quot;half%Dback&amp;quot;},&lt;br /&gt;
	{{&amp;quot;centralmidfielder&amp;quot;, &amp;quot;centralmidfield&amp;quot;, &amp;quot;cm&amp;quot;}, &amp;quot;Midfielder#Central midfielder&amp;quot;, &amp;quot;central midfielder&amp;quot;},&lt;br /&gt;
	{{&amp;quot;centremidfielder&amp;quot;, &amp;quot;centremidfield&amp;quot;, &amp;quot;centremid&amp;quot;, &amp;quot;centermid&amp;quot;}, &amp;quot;Midfielder#Central midfielder&amp;quot;, &amp;quot;%Ccentre midfielder&amp;quot;},&lt;br /&gt;
	{{&amp;quot;defensivemidfielder&amp;quot;, &amp;quot;defendingmidfielder&amp;quot;, &amp;quot;defensivemidfield&amp;quot;, &amp;quot;dm&amp;quot;}, &amp;quot;Midfielder#Defensive midfielder&amp;quot;, &amp;quot;defensive midfielder&amp;quot;},&lt;br /&gt;
	{{&amp;quot;attackingmidfielder&amp;quot;, &amp;quot;attackingmidfield&amp;quot;, &amp;quot;offensivemidfielder&amp;quot;, &amp;quot;offensivemidfield&amp;quot;, &amp;quot;am&amp;quot;}, &amp;quot;Midfielder#Attacking midfielder&amp;quot;, &amp;quot;attacking midfielder&amp;quot;},&lt;br /&gt;
	{{&amp;quot;widemidfielder&amp;quot;, &amp;quot;sidemidfielder&amp;quot;, &amp;quot;wm&amp;quot;}, &amp;quot;Midfielder#Wide midfielder&amp;quot;, &amp;quot;wide midfielder&amp;quot;},&lt;br /&gt;
	{{&amp;quot;winger&amp;quot;, &amp;quot;wi&amp;quot;}, &amp;quot;Midfielder#Winger&amp;quot;, &amp;quot;winger&amp;quot;},&lt;br /&gt;
	{{&amp;quot;wing&amp;quot;}, &amp;quot;Midfielder#Winger&amp;quot;, &amp;quot;wing&amp;quot;},&lt;br /&gt;
	{{&amp;quot;winghalf&amp;quot;, &amp;quot;winghalfback&amp;quot;, &amp;quot;wh&amp;quot;}, &amp;quot;Midfielder#Wing-half&amp;quot;, &amp;quot;wing%Dhalf&amp;quot;},&lt;br /&gt;
	{{&amp;quot;centraldefensivemidfielder&amp;quot;, &amp;quot;cdm&amp;quot;}, &amp;quot;Midfielder#Defensive midfielder&amp;quot;, &amp;quot;central defensive midfielder&amp;quot;},&lt;br /&gt;
	{{&amp;quot;centredefensivemidfielder&amp;quot;}, &amp;quot;Midfielder#Defensive midfielder&amp;quot;, &amp;quot;%Ccentre defensive midfielder&amp;quot;},&lt;br /&gt;
	{{&amp;quot;leftdefensivemidfielder&amp;quot;, &amp;quot;ldm&amp;quot;}, &amp;quot;Midfielder#Defensive midfielder&amp;quot;, &amp;quot;left defensive midfielder&amp;quot;},&lt;br /&gt;
	{{&amp;quot;rightdefensivemidfielder&amp;quot;, &amp;quot;rdm&amp;quot;}, &amp;quot;Midfielder#Defensive midfielder&amp;quot;, &amp;quot;right defensive midfielder&amp;quot;},&lt;br /&gt;
	{{&amp;quot;centralattackingmidfielder&amp;quot;, &amp;quot;cam&amp;quot;}, &amp;quot;Midfielder#Attacking midfielder&amp;quot;, &amp;quot;central attacking midfielder&amp;quot;},&lt;br /&gt;
	{{&amp;quot;centreattackingmidfielder&amp;quot;}, &amp;quot;Midfielder#Attacking midfielder&amp;quot;, &amp;quot;%Ccentre attacking midfielder&amp;quot;},&lt;br /&gt;
	{{&amp;quot;leftattackingmidfielder&amp;quot;, &amp;quot;lam&amp;quot;}, &amp;quot;Midfielder#Attacking midfielder&amp;quot;, &amp;quot;left attacking midfielder&amp;quot;},&lt;br /&gt;
	{{&amp;quot;rightattackingmidfielder&amp;quot;, &amp;quot;ram&amp;quot;}, &amp;quot;Midfielder#Attacking midfielder&amp;quot;, &amp;quot;right attacking midfielder&amp;quot;},&lt;br /&gt;
	{{&amp;quot;holdingmidfielder&amp;quot;, &amp;quot;holdingmidfield&amp;quot;, &amp;quot;hm&amp;quot;}, &amp;quot;Midfielder#Defensive midfielder&amp;quot;, &amp;quot;holding midfielder&amp;quot;},&lt;br /&gt;
	{{&amp;quot;rightmidfielder&amp;quot;, &amp;quot;rightmidfield&amp;quot;, &amp;quot;rm&amp;quot;}, &amp;quot;Midfielder#Wide midfielder&amp;quot;, &amp;quot;right midfielder&amp;quot;},&lt;br /&gt;
	{{&amp;quot;leftmidfielder&amp;quot;, &amp;quot;leftmidfield&amp;quot;, &amp;quot;lm&amp;quot;}, &amp;quot;Midfielder#Wide midfielder&amp;quot;, &amp;quot;left midfielder&amp;quot;},&lt;br /&gt;
	{{&amp;quot;rightwinger&amp;quot;, &amp;quot;rw&amp;quot;}, &amp;quot;Midfielder#Winger&amp;quot;, &amp;quot;right winger&amp;quot;},&lt;br /&gt;
	{{&amp;quot;rightwing&amp;quot;}, &amp;quot;Midfielder#Winger&amp;quot;, &amp;quot;right wing&amp;quot;},&lt;br /&gt;
	{{&amp;quot;leftwinger&amp;quot;, &amp;quot;lw&amp;quot;}, &amp;quot;Midfielder#Winger&amp;quot;, &amp;quot;left winger&amp;quot;},&lt;br /&gt;
	{{&amp;quot;leftwing&amp;quot;}, &amp;quot;Midfielder#Winger&amp;quot;, &amp;quot;left wing&amp;quot;},&lt;br /&gt;
	{{&amp;quot;oldcentrehalf&amp;quot;, &amp;quot;centrehalfback&amp;quot;, &amp;quot;ch&amp;quot;}, &amp;quot;Midfielder#Centre-half&amp;quot;, &amp;quot;%Ccentre%Dhalf&amp;quot;},&lt;br /&gt;
	{{&amp;quot;righthalf&amp;quot;, &amp;quot;righthalfback&amp;quot;, &amp;quot;rightwinghalf&amp;quot;, &amp;quot;rh&amp;quot;}, &amp;quot;Midfielder#Wing-half&amp;quot;, &amp;quot;right%Dhalf&amp;quot;},&lt;br /&gt;
	{{&amp;quot;lefthalf&amp;quot;, &amp;quot;lefthalfback&amp;quot;, &amp;quot;leftwinghalf&amp;quot;, &amp;quot;lh&amp;quot;}, &amp;quot;Midfielder#Wing-half&amp;quot;, &amp;quot;left%Dhalf&amp;quot;},&lt;br /&gt;
	-- Forwards&lt;br /&gt;
	{{&amp;quot;forward&amp;quot;, &amp;quot;attacker&amp;quot;, &amp;quot;attack&amp;quot;, &amp;quot;fw&amp;quot;}, &amp;quot;Forward (association football)&amp;quot;, &amp;quot;forward&amp;quot;},&lt;br /&gt;
	{{&amp;quot;centreforward&amp;quot;, &amp;quot;centralforward&amp;quot;, &amp;quot;cf&amp;quot;}, &amp;quot;Forward (association football)#Centre-forward&amp;quot;, &amp;quot;%Ccentre%Dforward&amp;quot;},&lt;br /&gt;
	{{&amp;quot;striker&amp;quot;, &amp;quot;st&amp;quot;}, &amp;quot;Forward (association football)#Striker&amp;quot;, &amp;quot;striker&amp;quot;},&lt;br /&gt;
	{{&amp;quot;secondstriker&amp;quot;, &amp;quot;secondarystriker&amp;quot;, &amp;quot;secondforward&amp;quot;, &amp;quot;ss&amp;quot;}, &amp;quot;Forward (association football)#Second striker&amp;quot;, &amp;quot;second striker&amp;quot;},&lt;br /&gt;
	{{&amp;quot;supportingstriker&amp;quot;, &amp;quot;supportstriker&amp;quot;}, &amp;quot;Forward (association football)#Second striker&amp;quot;, &amp;quot;supporting striker&amp;quot;},&lt;br /&gt;
	{{&amp;quot;deeplyingstriker&amp;quot;, &amp;quot;deeplyingforward&amp;quot;}, &amp;quot;Forward (association football)#Second striker&amp;quot;, &amp;quot;deep-lying striker&amp;quot;},&lt;br /&gt;
	{{&amp;quot;insideforward&amp;quot;, &amp;quot;if&amp;quot;}, &amp;quot;Forward (association football)#Inside forward&amp;quot;, &amp;quot;inside forward&amp;quot;},&lt;br /&gt;
	{{&amp;quot;outsideforward&amp;quot;, &amp;quot;of&amp;quot;}, &amp;quot;Forward (association football)#Outside forward&amp;quot;, &amp;quot;outside forward&amp;quot;},&lt;br /&gt;
	{{&amp;quot;rightforward&amp;quot;, &amp;quot;rf&amp;quot;}, &amp;quot;Forward (association football)&amp;quot;, &amp;quot;right forward&amp;quot;},&lt;br /&gt;
	{{&amp;quot;leftforward&amp;quot;, &amp;quot;lf&amp;quot;}, &amp;quot;Forward (association football)&amp;quot;, &amp;quot;left forward&amp;quot;},&lt;br /&gt;
	{{&amp;quot;insideright&amp;quot;, &amp;quot;rightinsideforward&amp;quot;, &amp;quot;ir&amp;quot;}, &amp;quot;Forward (association football)#Inside forward&amp;quot;, &amp;quot;inside right&amp;quot;},&lt;br /&gt;
	{{&amp;quot;insideleft&amp;quot;, &amp;quot;leftinsideforward&amp;quot;, &amp;quot;il&amp;quot;}, &amp;quot;Forward (association football)#Inside forward&amp;quot;, &amp;quot;inside left&amp;quot;},&lt;br /&gt;
	{{&amp;quot;outsideright&amp;quot;, &amp;quot;rightoutsideforward&amp;quot;, &amp;quot;or&amp;quot;}, &amp;quot;Forward (association football)#Outside forward&amp;quot;, &amp;quot;outside right&amp;quot;},&lt;br /&gt;
	{{&amp;quot;outsideleft&amp;quot;, &amp;quot;leftoutsideforward&amp;quot;, &amp;quot;ol&amp;quot;}, &amp;quot;Forward (association football)#Outside forward&amp;quot;, &amp;quot;outside left&amp;quot;},&lt;br /&gt;
	-- Utility player&lt;br /&gt;
	{{&amp;quot;utilityplayer&amp;quot;, &amp;quot;utility&amp;quot;, &amp;quot;ut&amp;quot;}, &amp;quot;Utility player#Association football&amp;quot;, &amp;quot;utility player&amp;quot;},&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Build lookup table from definitions&lt;br /&gt;
local positionData = {}&lt;br /&gt;
for _, def in ipairs(positionDefs) do&lt;br /&gt;
	local names, link, display = def[1], def[2], def[3]&lt;br /&gt;
	local data = {link, display}&lt;br /&gt;
	for _, name in ipairs(names) do&lt;br /&gt;
		positionData[name] = data&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Normalize HTML entities&lt;br /&gt;
local function decodeEntities(str)&lt;br /&gt;
	str = str:gsub(&amp;quot;&amp;amp;nbsp;&amp;quot;, &amp;quot; &amp;quot;)&lt;br /&gt;
	str = mw.text.decode(str, true)&lt;br /&gt;
	return str&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Delink wikilinks&lt;br /&gt;
local function delink(str)&lt;br /&gt;
	return str:gsub(&amp;quot;%[%[(.-)%]%]&amp;quot;, function(match)&lt;br /&gt;
		local pipePos = match:find(&amp;quot;|&amp;quot;)&lt;br /&gt;
		if pipePos then&lt;br /&gt;
			return match:sub(pipePos + 1)&lt;br /&gt;
		else&lt;br /&gt;
			return match&lt;br /&gt;
		end&lt;br /&gt;
	end)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Extract reference placeholders from end of string&lt;br /&gt;
local function extractRefs(str)&lt;br /&gt;
	local refs = &amp;quot;&amp;quot;&lt;br /&gt;
	-- Pattern for MediaWiki strip markers&lt;br /&gt;
	local refPattern = &amp;quot;\127&amp;#039;\&amp;quot;`UNIQ%-%-ref.-QINU`\&amp;quot;&amp;#039;\127&amp;quot;&lt;br /&gt;
	while true do&lt;br /&gt;
		local s, e = str:find(refPattern .. &amp;quot;%s*$&amp;quot;)&lt;br /&gt;
		if s then&lt;br /&gt;
			refs = str:sub(s, e):gsub(&amp;quot;%s*$&amp;quot;, &amp;quot;&amp;quot;) .. refs&lt;br /&gt;
			str = str:sub(1, s - 1)&lt;br /&gt;
		else&lt;br /&gt;
			break&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return mw.text.trim(str), refs&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Normalize for lookup: lowercase, remove dashes/spaces, convert center-&amp;gt;centre&lt;br /&gt;
local function normalizeForLookup(str)&lt;br /&gt;
	local s = str:lower()&lt;br /&gt;
	s = s:gsub(&amp;quot;[-–—−]&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
	s = s:gsub(&amp;quot; &amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
	s = s:gsub(&amp;quot;center&amp;quot;, &amp;quot;centre&amp;quot;)&lt;br /&gt;
	return s&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Detect original formatting for centre/center and dash/space&lt;br /&gt;
local function detectFormatting(original, normalized)&lt;br /&gt;
	local usesCenter = original:lower():find(&amp;quot;center&amp;quot;) ~= nil&lt;br /&gt;
	&lt;br /&gt;
	-- Check for dash variants&lt;br /&gt;
	local dashChar = original:match(&amp;quot;%-&amp;quot;) or original:match(&amp;quot;–&amp;quot;) or original:match(&amp;quot;—&amp;quot;) or original:match(&amp;quot;−&amp;quot;)&lt;br /&gt;
	&lt;br /&gt;
	-- If no dash found, determine if space or no separator was used&lt;br /&gt;
	-- Compare lengths: if original (lowercased, center-&amp;gt;centre) is longer than normalized,&lt;br /&gt;
	-- there must be spaces&lt;br /&gt;
	local spaceInsteadOfDash = false&lt;br /&gt;
	local noSeparator = false&lt;br /&gt;
	&lt;br /&gt;
	if not dashChar then&lt;br /&gt;
		local comparable = original:lower():gsub(&amp;quot;center&amp;quot;, &amp;quot;centre&amp;quot;)&lt;br /&gt;
		if #comparable &amp;gt; #normalized then&lt;br /&gt;
			-- Original has extra characters (spaces)&lt;br /&gt;
			spaceInsteadOfDash = true&lt;br /&gt;
		elseif #comparable == #normalized and #normalized &amp;gt; 1 then&lt;br /&gt;
			-- Same length means no separators were used&lt;br /&gt;
			-- But only set noSeparator if the input looks like a full word (not an abbreviation)&lt;br /&gt;
			-- Abbreviations are short (2-3 chars) and all letters&lt;br /&gt;
			local isAbbreviation = original:match(&amp;quot;^%a%a%a?$&amp;quot;) ~= nil&lt;br /&gt;
			if not isAbbreviation then&lt;br /&gt;
				noSeparator = true&lt;br /&gt;
			end&lt;br /&gt;
			-- If it&amp;#039;s an abbreviation, we fall through to the default dash behavior&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return usesCenter, dashChar, spaceInsteadOfDash, noSeparator&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Apply formatting to display text&lt;br /&gt;
local function applyFormatting(display, usesCenter, dashChar, spaceInsteadOfDash, noSeparator)&lt;br /&gt;
	-- Handle %C placeholder (centre/center)&lt;br /&gt;
	if usesCenter then&lt;br /&gt;
		display = display:gsub(&amp;quot;%%Ccentre&amp;quot;, &amp;quot;center&amp;quot;)&lt;br /&gt;
	else&lt;br /&gt;
		display = display:gsub(&amp;quot;%%C&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Handle %D placeholder (dash)&lt;br /&gt;
	if dashChar then&lt;br /&gt;
		display = display:gsub(&amp;quot;%%D&amp;quot;, &amp;quot;-&amp;quot;)&lt;br /&gt;
	elseif spaceInsteadOfDash then&lt;br /&gt;
		display = display:gsub(&amp;quot;%%D&amp;quot;, &amp;quot; &amp;quot;)&lt;br /&gt;
	elseif noSeparator then&lt;br /&gt;
		display = display:gsub(&amp;quot;%%D&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
	else&lt;br /&gt;
		display = display:gsub(&amp;quot;%%D&amp;quot;, &amp;quot;-&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return display&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Process a single position&lt;br /&gt;
local function processPosition(pos, isFirst, trackingNeeded, linkTargetReplacements, citationNeededTags)&lt;br /&gt;
	local backup = pos&lt;br /&gt;
	&lt;br /&gt;
	-- Extract citation needed placeholders and references from end of position&lt;br /&gt;
	local citationNeeded = &amp;quot;&amp;quot;&lt;br /&gt;
	local refs = &amp;quot;&amp;quot;&lt;br /&gt;
	local cnPlaceholderPattern = &amp;quot;\127CITATIONNEEDED%d+\127&amp;quot;&lt;br /&gt;
	local refPattern = &amp;quot;\127&amp;#039;\&amp;quot;`UNIQ%-%-ref.-QINU`\&amp;quot;&amp;#039;\127&amp;quot;&lt;br /&gt;
&lt;br /&gt;
	while true do&lt;br /&gt;
		local cnStart, cnEnd = pos:find(cnPlaceholderPattern .. &amp;quot;%s*$&amp;quot;)&lt;br /&gt;
		local refStart, refEnd = pos:find(refPattern .. &amp;quot;%s*$&amp;quot;)&lt;br /&gt;
	&lt;br /&gt;
		if cnStart and (not refStart or cnStart &amp;gt; refStart) then&lt;br /&gt;
			-- Citation needed is at the very end&lt;br /&gt;
			local placeholder = pos:sub(cnStart, cnEnd):gsub(&amp;quot;%s*$&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
			citationNeeded = (citationNeededTags[placeholder] or &amp;quot;&amp;quot;) .. citationNeeded&lt;br /&gt;
			pos = pos:sub(1, cnStart - 1)&lt;br /&gt;
		elseif refStart then&lt;br /&gt;
			-- Ref is at the very end&lt;br /&gt;
			refs = pos:sub(refStart, refEnd):gsub(&amp;quot;%s*$&amp;quot;, &amp;quot;&amp;quot;) .. refs&lt;br /&gt;
			pos = pos:sub(1, refStart - 1)&lt;br /&gt;
		else&lt;br /&gt;
			break&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	pos = mw.text.trim(pos)&lt;br /&gt;
	&lt;br /&gt;
	-- Handle special centre-half wikilink&lt;br /&gt;
	local lowerPos = pos:lower()&lt;br /&gt;
	if lowerPos:match(&amp;quot;^%[%[midfielder#centre%-half|cent[re][re]%-?%s?half%]%]$&amp;quot;) then&lt;br /&gt;
		pos = &amp;quot;old centre-half&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Delink&lt;br /&gt;
	pos = delink(pos)&lt;br /&gt;
	pos = mw.text.trim(pos)&lt;br /&gt;
	&lt;br /&gt;
	-- Lookup&lt;br /&gt;
	local normalized = normalizeForLookup(pos)&lt;br /&gt;
	local usesCenter, dashChar, spaceInsteadOfDash, noSeparator = detectFormatting(pos, normalized)&lt;br /&gt;
	local data = positionData[normalized]&lt;br /&gt;
	&lt;br /&gt;
	local result&lt;br /&gt;
	local usedBackup = false&lt;br /&gt;
&lt;br /&gt;
	if data then&lt;br /&gt;
		local link, display = data[1], data[2]&lt;br /&gt;
		display = applyFormatting(display, usesCenter, dashChar, spaceInsteadOfDash, noSeparator)&lt;br /&gt;
	&lt;br /&gt;
		-- Capitalize first position, lowercase others&lt;br /&gt;
		if isFirst then&lt;br /&gt;
			display = display:sub(1, 1):upper() .. display:sub(2):lower()&lt;br /&gt;
		else&lt;br /&gt;
			display = display:lower()&lt;br /&gt;
		end&lt;br /&gt;
	&lt;br /&gt;
		-- Simplify wikilink if link target equals display text (case insensitive)&lt;br /&gt;
		if link:lower() == display:lower() then&lt;br /&gt;
			result = &amp;quot;[[&amp;quot; .. display .. &amp;quot;]]&amp;quot;&lt;br /&gt;
		else&lt;br /&gt;
			result = &amp;quot;[[&amp;quot; .. link .. &amp;quot;|&amp;quot; .. display .. &amp;quot;]]&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		-- No match found - check if this came from a link target replacement&lt;br /&gt;
		if linkTargetReplacements and linkTargetReplacements[pos] then&lt;br /&gt;
			-- Use the original link with separator&lt;br /&gt;
			result = linkTargetReplacements[pos]&lt;br /&gt;
		else&lt;br /&gt;
			-- Use backup, but restore any citation needed placeholders in it first&lt;br /&gt;
			result = backup&lt;br /&gt;
			for placeholder, tag in pairs(citationNeededTags) do&lt;br /&gt;
				result = result:gsub(placeholder, tag)&lt;br /&gt;
			end&lt;br /&gt;
			usedBackup = true  -- Set the flag&lt;br /&gt;
		end&lt;br /&gt;
		trackingNeeded[1] = true&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Re-add references&lt;br /&gt;
	if refs ~= &amp;quot;&amp;quot; and not usedBackup then&lt;br /&gt;
		result = result .. refs&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Re-add citation needed only if we didn&amp;#039;t use the backup&lt;br /&gt;
	-- (backup already contains the citation needed tag)&lt;br /&gt;
	if citationNeeded ~= &amp;quot;&amp;quot; and not usedBackup then&lt;br /&gt;
		result = result .. citationNeeded&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main(frame)&lt;br /&gt;
	local args = frame.args&lt;br /&gt;
	local input = args[1]&lt;br /&gt;
	&lt;br /&gt;
	-- If called from a template, get parent args&lt;br /&gt;
	if input == nil or input == &amp;quot;&amp;quot; then&lt;br /&gt;
		args = frame:getParent().args&lt;br /&gt;
		input = args[1]&lt;br /&gt;
	end&lt;br /&gt;
	input = input or &amp;quot;&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
	-- No input = no output&lt;br /&gt;
	if input == &amp;quot;&amp;quot; or mw.text.trim(input) == &amp;quot;&amp;quot; then&lt;br /&gt;
		return &amp;quot;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Normalize HTML entities&lt;br /&gt;
	input = decodeEntities(input)&lt;br /&gt;
	&lt;br /&gt;
	-- Trim&lt;br /&gt;
	input = mw.text.trim(input)&lt;br /&gt;
	&lt;br /&gt;
	-- Handle hlist/plainlist input&lt;br /&gt;
	local tsPattern = &amp;quot;\127&amp;#039;\&amp;quot;`UNIQ%-%-templatestyles%-.-%QINU`\&amp;quot;&amp;#039;\127%s*&amp;lt;div class=\&amp;quot;&amp;quot;&lt;br /&gt;
	local listMatch = input:match(tsPattern .. &amp;quot;hlist[^\&amp;quot;]*\&amp;quot;[^&amp;gt;]*&amp;gt;(.-)&amp;lt;/div&amp;gt;&amp;quot;) or&lt;br /&gt;
	                  input:match(tsPattern .. &amp;quot;plainlist[^\&amp;quot;]*\&amp;quot;[^&amp;gt;]*&amp;gt;(.-)&amp;lt;/div&amp;gt;&amp;quot;)&lt;br /&gt;
	if listMatch then&lt;br /&gt;
		local listPositions = {}&lt;br /&gt;
		&lt;br /&gt;
		-- Check for HTML list format (&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;...&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;)&lt;br /&gt;
		if listMatch:match(&amp;#039;&amp;lt;ul&amp;gt;&amp;#039;) then&lt;br /&gt;
			for item in listMatch:gmatch(&amp;#039;&amp;lt;li&amp;gt;(.-)&amp;lt;/li&amp;gt;&amp;#039;) do&lt;br /&gt;
				item = mw.text.trim(item)&lt;br /&gt;
				if item ~= &amp;quot;&amp;quot; then&lt;br /&gt;
					table.insert(listPositions, item)&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			-- Wikitext list format (* item)&lt;br /&gt;
			for item in listMatch:gmatch(&amp;#039;%*%s*([^\n]+)&amp;#039;) do&lt;br /&gt;
				item = mw.text.trim(item)&lt;br /&gt;
				if item ~= &amp;quot;&amp;quot; then&lt;br /&gt;
					table.insert(listPositions, item)&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- If we found list items, replace input with comma-separated positions&lt;br /&gt;
		if #listPositions &amp;gt; 0 then&lt;br /&gt;
			input = table.concat(listPositions, &amp;quot;, &amp;quot;)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Break tag pattern&lt;br /&gt;
	local brPattern = &amp;quot;&amp;lt;[bB][rR]%s*/?%s*&amp;gt;&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
	-- Handle and/or adjacent to break tags (convert to just /)&lt;br /&gt;
	input = input:gsub(&amp;quot;%s+[Aa][Nn][Dd]%s*&amp;quot; .. brPattern, &amp;quot;/&amp;quot;)&lt;br /&gt;
	input = input:gsub(&amp;quot;%s+[Oo][Rr]%s*&amp;quot; .. brPattern, &amp;quot;/&amp;quot;)&lt;br /&gt;
	input = input:gsub(brPattern .. &amp;quot;%s*[Aa][Nn][Dd]%s+&amp;quot;, &amp;quot;/&amp;quot;)&lt;br /&gt;
	input = input:gsub(brPattern .. &amp;quot;%s*[Oo][Rr]%s+&amp;quot;, &amp;quot;/&amp;quot;)&lt;br /&gt;
	&lt;br /&gt;
	-- Replace remaining br tags with /&lt;br /&gt;
	input = input:gsub(brPattern, &amp;quot;/&amp;quot;)&lt;br /&gt;
	&lt;br /&gt;
	-- Extract citation needed templates and replace with placeholders&lt;br /&gt;
	-- Match sup tags with Template-Fact class (citation needed)&lt;br /&gt;
	-- Categories may precede the sup tag, so we handle them together&lt;br /&gt;
	local citationNeededTags = {}&lt;br /&gt;
	local citationNeededIndex = 0&lt;br /&gt;
	&lt;br /&gt;
	-- Process from end to start to avoid position shifting issues&lt;br /&gt;
	-- First collect all matches, then replace&lt;br /&gt;
	local matches = {}&lt;br /&gt;
	local searchPos = 1&lt;br /&gt;
	while true do&lt;br /&gt;
		-- Find next sup tag with Template-Fact&lt;br /&gt;
		local supStart, supEnd = input:find(&amp;quot;&amp;lt;sup[^&amp;gt;]*Template%-Fact[^&amp;gt;]*&amp;gt;.-&amp;lt;/sup&amp;gt;&amp;quot;, searchPos)&lt;br /&gt;
		if not supStart then break end&lt;br /&gt;
		&lt;br /&gt;
		-- Look backwards for any immediately preceding categories&lt;br /&gt;
		local catStart = supStart&lt;br /&gt;
		local checkPos = supStart&lt;br /&gt;
		while checkPos &amp;gt; 1 do&lt;br /&gt;
			-- Get the prefix before current position&lt;br /&gt;
			local prefix = input:sub(1, checkPos - 1)&lt;br /&gt;
			-- Try to match a category at the end of prefix (with optional trailing whitespace)&lt;br /&gt;
			local catMatchStart, catMatchEnd = prefix:find(&amp;quot;%[%[Category:[^%]]+%]%]%s*$&amp;quot;)&lt;br /&gt;
			if catMatchStart then&lt;br /&gt;
				catStart = catMatchStart&lt;br /&gt;
				checkPos = catMatchStart&lt;br /&gt;
			else&lt;br /&gt;
				break&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- Assign index now (during collection) to preserve order&lt;br /&gt;
		citationNeededIndex = citationNeededIndex + 1&lt;br /&gt;
		table.insert(matches, {catStart, supEnd, citationNeededIndex})&lt;br /&gt;
		searchPos = supEnd + 1&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Replace matches from end to start to preserve positions&lt;br /&gt;
	for i = #matches, 1, -1 do&lt;br /&gt;
		local startPos, endPos, idx = matches[i][1], matches[i][2], matches[i][3]&lt;br /&gt;
		local fullMatch = input:sub(startPos, endPos)&lt;br /&gt;
		local placeholder = &amp;quot;\127CITATIONNEEDED&amp;quot; .. idx .. &amp;quot;\127&amp;quot;&lt;br /&gt;
		citationNeededTags[placeholder] = fullMatch&lt;br /&gt;
		input = input:sub(1, startPos - 1) .. placeholder .. input:sub(endPos + 1)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Check for tags&lt;br /&gt;
	if input:match(&amp;quot;&amp;lt;[^&amp;gt;]+&amp;gt;&amp;quot;) then&lt;br /&gt;
		-- Add tracking category&lt;br /&gt;
		local category = frame:expandTemplate{&lt;br /&gt;
			title = &amp;quot;main other&amp;quot;,&lt;br /&gt;
			args = {&amp;quot;[[Category:Pages using infobox football biography with tags in position parameter]]&amp;quot;}&lt;br /&gt;
		}&lt;br /&gt;
		-- Restore citation needed tags before returning&lt;br /&gt;
		for placeholder, tag in pairs(citationNeededTags) do&lt;br /&gt;
			input = input:gsub(placeholder, tag)&lt;br /&gt;
		end&lt;br /&gt;
		return input .. category&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Replace remaining line breaks with /&lt;br /&gt;
	input = input:gsub(&amp;quot;\n&amp;quot;, &amp;quot;/&amp;quot;)&lt;br /&gt;
	&lt;br /&gt;
	-- Check for separators in wikilink display text and delink if found&lt;br /&gt;
	local hadSeparatorInDisplayText = false&lt;br /&gt;
	local originalInputBeforeDelink = input&lt;br /&gt;
	local separatorPattern = &amp;quot;[/,;+&amp;amp;]&amp;quot;&lt;br /&gt;
	local hasWordSeparator = function(text)&lt;br /&gt;
		return text:match(&amp;quot;%s+[Aa][Nn][Dd]%s+&amp;quot;) or text:match(&amp;quot;%s+[Oo][Rr]%s+&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	local linkTargetReplacements = {} -- Track original links that had separators in target&lt;br /&gt;
	&lt;br /&gt;
	-- Check each wikilink for separators in display text&lt;br /&gt;
	for wikilink in input:gmatch(&amp;quot;%[%[.-%]%]&amp;quot;) do&lt;br /&gt;
		local pipePos = wikilink:find(&amp;quot;|&amp;quot;)&lt;br /&gt;
		local textToCheck&lt;br /&gt;
		if pipePos then&lt;br /&gt;
			-- Has display text - check the part after the pipe&lt;br /&gt;
			textToCheck = wikilink:sub(pipePos + 1, -3) -- Extract display text (excluding ]])&lt;br /&gt;
			&lt;br /&gt;
			-- Also check if separator is in the link target (before pipe)&lt;br /&gt;
			local linkTarget = wikilink:sub(3, pipePos - 1)&lt;br /&gt;
			if linkTarget:match(separatorPattern) or hasWordSeparator(linkTarget) then&lt;br /&gt;
				-- Store the original link and its display text for later restoration if needed&lt;br /&gt;
				local displayText = textToCheck&lt;br /&gt;
				linkTargetReplacements[displayText] = wikilink&lt;br /&gt;
				-- Remove separators from the link target in the input&lt;br /&gt;
				local cleanedTarget = linkTarget:gsub(separatorPattern, &amp;quot;&amp;quot;):gsub(&amp;quot;%s+and%s+&amp;quot;, &amp;quot;&amp;quot;):gsub(&amp;quot;%s+or%s+&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
				input = input:gsub(&amp;quot;%[%[&amp;quot; .. linkTarget:gsub(&amp;quot;([%^%$%(%)%%%.%[%]%*%+%-%?])&amp;quot;, &amp;quot;%%%1&amp;quot;) .. &amp;quot;|&amp;quot; .. displayText:gsub(&amp;quot;([%^%$%(%)%%%.%[%]%*%+%-%?])&amp;quot;, &amp;quot;%%%1&amp;quot;) .. &amp;quot;%]%]&amp;quot;,&lt;br /&gt;
				                   &amp;quot;[[&amp;quot; .. cleanedTarget .. &amp;quot;|&amp;quot; .. displayText .. &amp;quot;]]&amp;quot;)&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			-- No pipe - check the link target itself (excluding [[]])&lt;br /&gt;
			textToCheck = wikilink:sub(3, -3)&lt;br /&gt;
		end&lt;br /&gt;
		if textToCheck:match(separatorPattern) or hasWordSeparator(textToCheck) then&lt;br /&gt;
			hadSeparatorInDisplayText = true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- If separator found in display text, delink the input&lt;br /&gt;
	if hadSeparatorInDisplayText then&lt;br /&gt;
		input = delink(input)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Convert word separators to / before splitting, but only outside of wikilinks&lt;br /&gt;
	-- First, temporarily replace wikilinks with placeholders&lt;br /&gt;
	local wikilinks = {}&lt;br /&gt;
	local placeholderIndex = 0&lt;br /&gt;
	input = input:gsub(&amp;quot;%[%[.-%]%]&amp;quot;, function(wikilink)&lt;br /&gt;
		placeholderIndex = placeholderIndex + 1&lt;br /&gt;
		local placeholder = &amp;quot;\127WIKILINK&amp;quot; .. placeholderIndex .. &amp;quot;\127&amp;quot;&lt;br /&gt;
		wikilinks[placeholder] = wikilink&lt;br /&gt;
		return placeholder&lt;br /&gt;
	end)&lt;br /&gt;
	&lt;br /&gt;
	-- Now convert word separators&lt;br /&gt;
	input = input:gsub(&amp;quot;%s+[Aa][Nn][Dd]%s+&amp;quot;, &amp;quot;/&amp;quot;)&lt;br /&gt;
	input = input:gsub(&amp;quot;%s+[Oo][Rr]%s+&amp;quot;, &amp;quot;/&amp;quot;)&lt;br /&gt;
	&lt;br /&gt;
	-- Restore wikilinks&lt;br /&gt;
	for placeholder, wikilink in pairs(wikilinks) do&lt;br /&gt;
		input = input:gsub(placeholder, wikilink)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Split by separators&lt;br /&gt;
	local positions = {}&lt;br /&gt;
	local refPattern = &amp;quot;\127&amp;#039;\&amp;quot;`UNIQ%-%-ref.-QINU`\&amp;quot;&amp;#039;\127&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
	-- First, split by separators&lt;br /&gt;
	local rawParts = {}&lt;br /&gt;
	local lastEnd = 1&lt;br /&gt;
	for sepStart, sepEnd in input:gmatch(&amp;quot;()%s*&amp;quot; .. separatorPattern .. &amp;quot;%s*()&amp;quot;) do&lt;br /&gt;
		table.insert(rawParts, input:sub(lastEnd, sepStart - 1))&lt;br /&gt;
		lastEnd = sepEnd&lt;br /&gt;
	end&lt;br /&gt;
	table.insert(rawParts, input:sub(lastEnd))&lt;br /&gt;
	&lt;br /&gt;
	-- Now process parts: if a part starts with ref(s) or citation needed, move them to previous position&lt;br /&gt;
	local cnPlaceholderPattern = &amp;quot;\127CITATIONNEEDED%d+\127&amp;quot;&lt;br /&gt;
	for i, part in ipairs(rawParts) do&lt;br /&gt;
		local leadingRefs = &amp;quot;&amp;quot;&lt;br /&gt;
		local remainder = part&lt;br /&gt;
		&lt;br /&gt;
		-- Extract leading refs and citation needed placeholders&lt;br /&gt;
		while true do&lt;br /&gt;
			local refStart, refEnd = remainder:find(&amp;quot;^%s*&amp;quot; .. refPattern)&lt;br /&gt;
			local cnStart, cnEnd = remainder:find(&amp;quot;^%s*&amp;quot; .. cnPlaceholderPattern)&lt;br /&gt;
			&lt;br /&gt;
			if refStart then&lt;br /&gt;
				leadingRefs = leadingRefs .. remainder:sub(refStart, refEnd)&lt;br /&gt;
				remainder = remainder:sub(refEnd + 1)&lt;br /&gt;
			elseif cnStart then&lt;br /&gt;
				leadingRefs = leadingRefs .. remainder:sub(cnStart, cnEnd)&lt;br /&gt;
				remainder = remainder:sub(cnEnd + 1)&lt;br /&gt;
			else&lt;br /&gt;
				break&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- Attach leading refs/citation needed to previous position&lt;br /&gt;
		if leadingRefs ~= &amp;quot;&amp;quot; and #positions &amp;gt; 0 then&lt;br /&gt;
			positions[#positions] = positions[#positions] .. leadingRefs&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- Add remainder as new position (if not empty)&lt;br /&gt;
		remainder = mw.text.trim(remainder)&lt;br /&gt;
		if remainder ~= &amp;quot;&amp;quot; then&lt;br /&gt;
			table.insert(positions, remainder)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- If no positions found, treat whole input as one position&lt;br /&gt;
	if #positions == 0 then&lt;br /&gt;
		positions = {mw.text.trim(input)}&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Filter out management/executive positions&lt;br /&gt;
	local excludeWords = {&amp;#039;retired&amp;#039;, &amp;#039;unknown&amp;#039;, &amp;#039;?&amp;#039;, &amp;#039;manager&amp;#039;, &amp;#039;coach&amp;#039;, &amp;#039;trainer&amp;#039;, &amp;#039;director&amp;#039;, &amp;#039;president&amp;#039;, &amp;#039;executive&amp;#039;, &amp;#039;chairman&amp;#039;, &amp;#039;ceo&amp;#039;, &amp;#039;referee&amp;#039;}&lt;br /&gt;
	local filteredPositions = {}&lt;br /&gt;
	local hasInvalidPosition = false&lt;br /&gt;
	for _, pos in ipairs(positions) do&lt;br /&gt;
		local lowerPos = pos:lower()&lt;br /&gt;
		local exclude = false&lt;br /&gt;
		for _, word in ipairs(excludeWords) do&lt;br /&gt;
			if lowerPos:find(word, 1, true) then&lt;br /&gt;
				exclude = true&lt;br /&gt;
				hasInvalidPosition = true&lt;br /&gt;
				break&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if not exclude then&lt;br /&gt;
			table.insert(filteredPositions, pos)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	positions = filteredPositions&lt;br /&gt;
	&lt;br /&gt;
	-- Add tracking category for invalid positions&lt;br /&gt;
	local invalidCategory = &amp;quot;&amp;quot;&lt;br /&gt;
	if hasInvalidPosition then&lt;br /&gt;
		invalidCategory = frame:expandTemplate{&lt;br /&gt;
			title = &amp;quot;main other&amp;quot;,&lt;br /&gt;
			args = {&amp;quot;[[Category:Pages using infobox football biography with invalid position]]&amp;quot;}&lt;br /&gt;
		}&lt;br /&gt;
		mw.addWarning(&amp;#039;&amp;lt;span style=&amp;quot;color:#d33&amp;quot;&amp;gt;Error: One or more of the position(s) listed in the infobox parameter is not an actual role for a footballer\&amp;#039;s playing career.&amp;lt;/span&amp;gt;&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- If all positions were filtered out, return only categories&lt;br /&gt;
	if #positions == 0 then&lt;br /&gt;
		return invalidCategory&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Process each position&lt;br /&gt;
	local trackingNeeded = {false}&lt;br /&gt;
	local results = {}&lt;br /&gt;
	for i, pos in ipairs(positions) do&lt;br /&gt;
		table.insert(results, processPosition(pos, i == 1, trackingNeeded, linkTargetReplacements, citationNeededTags))&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Build irregular category if needed&lt;br /&gt;
	local irregularCategory = &amp;quot;&amp;quot;&lt;br /&gt;
	if trackingNeeded[1] then&lt;br /&gt;
		irregularCategory = frame:expandTemplate{&lt;br /&gt;
			title = &amp;quot;main other&amp;quot;,&lt;br /&gt;
			args = {&amp;quot;[[Category:Pages using infobox football biography with irregular position]]&amp;quot;}&lt;br /&gt;
		}&lt;br /&gt;
		mw.addWarning(&amp;#039;&amp;lt;span style=&amp;quot;color:#d33&amp;quot;&amp;gt;Error: One or more of the position(s) listed in the infobox parameter is not a typical position in football.&amp;lt;/span&amp;gt;&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Special handling: if we delinked due to separator in display text,&lt;br /&gt;
	-- and ANY position didn&amp;#039;t match, return original input unchanged&lt;br /&gt;
	if hadSeparatorInDisplayText and trackingNeeded[1] then&lt;br /&gt;
		return originalInputBeforeDelink .. invalidCategory .. irregularCategory&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Build output&lt;br /&gt;
	local output&lt;br /&gt;
	if #results == 1 then&lt;br /&gt;
		output = results[1]&lt;br /&gt;
	else&lt;br /&gt;
		-- Use Module:List hlist&lt;br /&gt;
		output = mHList.makeList(&amp;#039;horizontal&amp;#039;, results)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return output .. invalidCategory .. irregularCategory&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>imported&gt;S.A. Julio</name></author>
	</entry>
</feed>