Edge Rewrite
Jump to content

Module:Regional articles

From Wikipedia, the free encyclopedia

local p = {};
local mRedirect = require('Module:Redirect')
local ISO = require('Module:ISO_3166')
local getArgs = require('Module:Arguments').getArgs

-- Based off https://www.kaggle.com/datasets/andradaolteanu/country-mapping-iso-continent-region
local REGIONS = {
	Northern_Africa = "DZ;EG;EH;LY;MA;SD;TN",
	Sub_Saharan_Africa = "AO;BF;BI;BJ;BW;CD;CF;CG;CI;CM;CV;DJ;ER;ET;GA;GH;GM;GN;GQ;GW;IO;KE;ZW",
	Africa = "DZ;EG;EH;LY;MA;SD;TN;AO;BF;BI;BJ;BW;CD;CF;CG;CI;CM;CV;DJ;ER;ET;GA;GH;GM;GN;GQ;GW;IO;KE;ZW",
	Latin_America = "AG;AI;AR;AW;BB;BL;BO;BQ;BR;BS;BV;BZ;CL;CO;CR;CU;CW;DM;DO;VI",
	Northern_America = "BM;CA;GL;PM;US",
	Americas = "BM;CA;GL;PM;US;AG;AI;AR;AW;BB;BL;BO;BQ;BR;BS;BV;BZ;CL;CO;CR;CU;CW;DM;DO;VI",
	Central_Asia = "KG;KZ;TJ;TM;UZ",
	Eastern_Asia = "CN;HK;JP;KP;KR;MN;MO;TW",
	South_Eastern_Asia = "BN;ID;KH;LA;MM;MY;PH;SG;TH;TL;VN;AF",
	Southern_Asia = "BD;BT;IN;IR;LK;MV;NP;PK",
	Western_Asia = "AE;AM;AZ;BH;CY;GE;IL;IQ;JO;KW;LB;OM;PS;QA;SA;SY;TR;YE",
	Asia = "AE;AM;AZ;BH;CY;GE;IL;IQ;JO;KW;LB;OM;PS;QA;SA;SY;TR;YE;BD;BT;IN;IR;LK;MV;NP;PK;BN;ID;KH;LA;MM;MY;PH;SG;TH;TL;VN;AF;CN;HK;JP;KP;KR;MN;MO;TW;KG;KZ;TJ;TM;UZ",
	Eastern_Europe = "BG;BY;CZ;HU;MD;PL;RO;RU;SK;UA",
	Northern_Europe = "AX;DK;EE;FI;FO;GB;GG;IE;IM;IS;JE;LT;LV;NO;SE;SJ",
	Southern_Europe = "AD;AL;BA;ES;GI;GR;HR;IT;ME;MK;MT;PT;RS;SI;SM;VA",
	Western_Europe = "AT;BE;CH;DE;FR;LI;LU;MC;NL",
	Europe = "AT;BE;CH;DE;FR;LI;LU;MC;NL;AD;AL;BA;ES;GI;GR;HR;IT;ME;MK;MT;PT;RS;SI;SM;VA;AX;DK;EE;FI;FO;GB;GG;IE;IM;IS;JE;LT;LV;NO;SE;SJ;BG;BY;CZ;HU;MD;PL;RO;RU;SK;UA",
	Australia_New_Zealand = "AU;CC;CX;HM;NF;NZ",
	Melanesia = "FJ;NC;PG;SB;VU",
	Micronesia = "FM;GU;KI;MH;MP;NR;PW;UM",
	Polynesia = "AS;CK;NU;PF;PN;TK;TO;TV;WF;WS",
	Oceania = "AS;CK;NU;PF;PN;TK;TO;TV;WF;WS;FM;GU;KI;MH;MP;NR;PW;UM;FJ;NC;PG;SB;VU;AU;CC;CX;HM;NF;NZ",
	all = "AF;AX;AL;DZ;AS;AD;AO;AI;AQ;AG;AR;AM;AW;AU;AT;AZ;BS;BH;BD;BB;BY;BE;BZ;BJ;BM;BT;BO;BO;BQ;BA;BW;BV;BR;IO;BN;BN;BG;BF;MM;BI;KH;CM;CA;CV;KY;CF;TD;CL;CN;CX;CC;CO;KM;CD;CG;CK;CR;CI;HR;CU;CW;CY;CZ;DK;DJ;DM;DO;EC;EG;SV;GQ;ER;EE;ET;FK;FO;FJ;FI;FR;GF;PF;TF;GA;GM;GE;DE;GH;GI;GR;GL;GD;GP;GU;GT;GG;GW;GN;GY;HT;HM;VA;HN;HK;HU;IS;IN;ID;IR;IQ;IE;IM;IL;IT;CI;JM;JP;JE;JO;KZ;KE;KI;KP;KR;XK;KW;KG;LA;LV;LB;LS;LR;LY;LY;LI;LT;LU;MO;MK;MG;MW;MY;MV;ML;MT;MH;MQ;MR;MU;YT;MX;FM;MD;MC;MN;ME;MS;MA;MZ;MM;NA;NR;NP;NL;NC;NZ;NI;NE;NG;NU;NF;MP;NO;OM;PK;PW;PS;PA;PG;PY;PE;PH;PN;PL;PT;PR;QA;RE;RO;RU;RU;RW;BL;SH;KN;LC;MF;PM;VC;VC;WS;SM;ST;SA;SN;RS;SC;SL;SG;SX;SK;SI;SB;SO;ZA;GS;KR;SS;ES;LK;VC;SD;SR;SJ;SZ;SE;CH;SY;TW;TJ;TZ;TH;TL;TG;TK;TO;TT;TN;TR;TM;TC;TV;UG;UA;AE;GB;UM;US;UY;UZ;VU;VE;VE;VN;VN;VG;VI;WF;EH;YE;ZM;ZW",
	us_states = "Alabama;Alaska;Arizona;Arkansas;California;Colorado;Connecticut;Delaware;Florida;Georgia (U.S. state);Hawaii;Idaho;Illinois;Indiana;Iowa;Kansas;Kentucky;Louisiana;Maine;Maryland;Massachusetts;Michigan;Minnesota;Mississippi;Missouri;Montana;Nebraska;Nevada;New Hampshire;New Jersey;New Mexico;New York;North Carolina;North Dakota;Ohio;Oklahoma;Oregon;Pennsylvania;Rhode Island;South Carolina;South Dakota;Tennessee;Texas;Utah;Vermont;Virginia;Washington (state);West Virginia;Wisconsin;Wyoming"
	
};

-- Utils
--- String splitting helper
local function split(inputstr, sep)
    if sep == nil then
        sep = "%s+" -- default to splitting by one or more whitespace characters
    end
    local t, i = {}, 1
    -- The pattern "([^"..sep.."]+)" matches one or more characters that are *not* the separator.
    for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
        t[i] = str
        i = i + 1
    end
    return t
end

--- Turn country codes into names, add "the " as prefix to some countries
local function country_name(iso_code)
	local name = ""
	local messy_names = "BS;NL;GB;UK;US;AE;DO;PH;CD;CG;CF;VI;FO;AX;IM;CK;MH;FM"
	if string.find(messy_names, iso_code) then
		name = "the "
	end
	-- If it's bigger than that it's not a country code presumably
	if #iso_code > 3 then
		return iso_code
	end
	iso_name = ISO.name({iso_code})
	if iso_name == "" then
		name = name .. iso_code
	else
		name = name .. iso_name
	end
	return name
end



--- Expand pre-coded regions
local function parse_regions(raw_regions)
	return REGIONS[raw_regions] or raw_regions
end


-- Table generation functions
local function prettify_cell(raw_title, region, short, stat)
	local title = mw.ustring.gsub(raw_title, "XXX", region)
	local titleObj = mw.title.new(title)
	local out = ""
	local redirTarget = ""
	local tl = "[[" .. title 
		if short == "yes" then
			tl = tl .. "|" .. region
		end
	tl = tl .. "]]"
	if stat == "no" then
		return tl
	end
	if titleObj and titleObj.isRedirect then
		out = "{{Class/icon|Redirect}} " .. tl
		redirTarget = titleObj.redirectTarget
	elseif titleObj and titleObj.exists then
		-- disable protection icon for now, if going to enable, better to directly call the invoked module in the aad template for performance
		out = "{{aad|aq|" .. title .. "}} " .. tl -- .. " {{aad|protection|" .. title .. "}}" 
	else
		out = "{{Class/icon|}} " .. tl
	end
	if redirTarget ~= "" then
		out = out .. "{{br}}→<small>" .. mRedirect.luaMain(title, 1) .. "</small>"
	end
	return out
end

local function make_row(cols, label)
	local row = "|-\n"
	if label == "no" then
		row = row .. "| "
	else
		row = row .. "! "	
	end
	local col_count = #cols
	for i, col in ipairs(cols) do
		if i == 1 then
			if label ~= "no" then
				row = row .. col .. "\n| "
			end
		else
			row = row .. col
			if i ~= col_count then
				row = row .. " || "
			end			
		end

	end
	return row .. "\n"
end

local function make_header_row(cols, label)
	local row = "|-\n"
	if label ~= "no" then
		row = row .. "! Title/Region\n"
	end
	for i, col in ipairs(cols) do
		row = row .. "! " .. col .. "\n"
	end
	return row
end

local function make_table(titles, rows, label, height)
	local t = '<templatestyles src="Template:Sticky table start/styles.css" />\n'
	local style = "scrollbar-gutter: stable; height: " .. (height or "")
	t = t .. '<div class="sticky-table-scroll" style="' .. style .. '">\n'
	t = t .. '{| class="wikitable sticky-table-row1" \n'
	t = t .. make_header_row(titles, label)
	for k, cols in ipairs(rows) do 
		t = t .. make_row(cols, label)
	end
	t = t .. "|}\n</div>"
	return t
end

-- Helper function to cut down expensive parser functions
--- This reduced EPF count by factor of 25
local function batch_lookup(titles, regions)
	local all_titles = {}
	for rkey, region_code in ipairs(regions) do
		local region = country_name(region_code)
		for tkey, title in ipairs(titles) do
			all_titles[#all_titles + 1] =  mw.ustring.gsub(title, "XXX", region)
		end
	end
	mw.title.newBatch(all_titles):lookupExistence():getTitles()
end

function p.main( frame )
	local f = getArgs(frame, {
		wrappers = 'Template:Regional articles'
	})
	local titles = split(f["titles"], ";")
	local regions = split(parse_regions(f["regions"]), ";")
	local label = f["label"] or "no"
	local short = f["short"] or "no"
	local height = f["height"] or ""
	local stat = f["status"] or "yes"

	batch_lookup(titles, regions)
	local rows, r_i = {}, 1
	for rkey, region_code in ipairs(regions) do
		local region = country_name(region_code)
		local cols, c_i = {region}, 2
		for tkey, title in ipairs(titles) do
			cols[c_i] = prettify_cell(title, region, short, stat)
			c_i = c_i + 1
		end
		rows[r_i] = cols
		r_i = r_i + 1

	end
	if f["test"] == "yes" then
		return make_table(titles, rows, label, height)
	end
	return frame:preprocess(make_table(titles, rows, label, height))
end

return p