Jump to content

Module:Jcon/sandbox

From Wikipedia, the free encyclopedia
require('strict')

local p = {}
local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local data = mw.loadData('Module:Jcon/data/sandbox')

-- Place types to remove from lowercase road type
local placeTypes = {
	'municipality',
	'municipal',
	'city',
	'township',
	'district',
	'county',
	'counties',
	'united counties',
	'region',
	'regional',
	'regional municipality',
	'road'
}

-- Normalize the given road type
local function normalizeType(roadType)
	roadType = (roadType or ''):lower() -- Make the road type lowercase

	for index, placeType in ipairs(placeTypes) do
		roadType = roadType -- Remove the place types from the road type
			:gsub('^' .. placeType .. ' of ', '')
			:gsub(' ' .. placeType .. '$', '')
			:gsub(' ' .. placeType .. ' road$', '')
	end

	return data.aliases[roadType] or roadType -- Transform alias into proper name
end

-- Generate the wikitext for the shield
local function shieldWikitext(route, roadInfo, args, prefix)
	local size = args.size or '20px' -- Image size
	local fileName = nil
	
	local shieldKey = prefix == 'to' and 'toShield' or 'shield' -- Shield key in the road data
	local guideKey = prefix == 'to' and 'toGuide' or 'guide' -- Guide key in the road data
	
	if roadInfo.imgExceptions and roadInfo.imgExceptions[route] then
		-- Handle exceptions
		fileName = roadInfo.imgExceptions[route][yesno(args.shield) and shieldKey or guideKey]
	elseif roadInfo.prefix == 'Ontario' and (tonumber(({route:gsub('%D', '')})[1]) or 0) >= 500 then
		-- Handle secondary and tertiary highways
		fileName = 'Ontario Highway ' .. route .. '.svg'
	elseif roadInfo[shieldKey] and yesno(args.shield) then
		-- Shield format (used as reassurance marker)
		fileName = roadInfo[shieldKey]:format(route)
	elseif roadInfo[guideKey] then
		-- Guide format (used on guide signs)
		fileName = roadInfo[guideKey]:format(route)
	else
		return '' -- Return nothing if no file format was found
	end
	
	local titleObj = mw.title.new('File:' .. fileName)

	if not titleObj or not titleObj.file.exists then
		return '' -- Return nothing if no existing file was found
	end
	
	return '[[File:' .. fileName .. '|alt=|link=|' .. size .. ']]' -- Return the file wikitext
end

-- Display a link, accounting for presentation arguments
local function displayLink(link, display, args)
	local titleObj = mw.title.new(link)
	local showLink = ((titleObj and titleObj.exists) or yesno(args.showred)) and not yesno(args.nolink)
	
	if showLink then
		return '[[' .. link .. '|' .. display .. ']]' -- Return the link
	else
		return display -- Fallback to returning the display text
	end
end

-- Generate the text part of the output
local function getText(route, roadInfo, args)
	local link = ''
	local display = ''
	
	if roadInfo.textExceptions and roadInfo.textExceptions[route] then
		-- Handle exceptions
		link = roadInfo.textExceptions[route].link
		display = roadInfo.textExceptions[route].display
	else
		-- Construct links and display from prefix, type, and route number
		link = roadInfo.prefix .. ' ' .. roadInfo.type .. ' ' .. route
		display = roadInfo.type .. ' ' .. route
	end
	
	if yesno(args.fulltext) then
		-- Display the full link title when requested
		display = link
	end
	
	return displayLink(link, display, args)
end

-- Gets the wikitext link for a place
local function getPlace(place, args)
	local placeArticle = place .. ', Ontario'
	local titleObj = mw.title.new(placeArticle)
	
	if (titleObj and titleObj.exists) or yesno(args.showred) then
		return '[[' .. placeArticle .. '|' .. place .. ']]'
	else
		return place
	end
end

-- Process routes present in the provided arguments
local function processRoutes(roadType, showShield, showText, args, prefix)
	local roadInfo = data.types[roadType]
	
	local shield = '' -- Generated shield wikitext
	local text = '' -- Generated text/link wikitext
	
	local conNumber = prefix ~= 'con' and 1 or 0 -- The number of the entry being processed
	local paramName = prefix ~= 'con' and prefix or 2 -- Route number parameter name
	local typeParam = prefix ~= 'con' and  prefix .. 'type' or nil -- Road type override parameter name
	local dirParam =  prefix ~= 'con' and prefix .. 'dir' or 'dir' -- Direction parameter name

	while args[paramName] do
		local routeRoadInfo = roadInfo -- Local copy of the road info
		
		if typeParam and args[typeParam] then
			-- Override the road info if one is provided
			local overrideRoadType = normalizeType(args[typeParam])
			routeRoadInfo = data.types[overrideRoadType]
		end
		
		if showShield then
			local routeShield = shieldWikitext(args[paramName], routeRoadInfo, args, prefix) -- Generate route shield
			
			if routeShield ~= '' then
				if shield ~= '' then shield = shield .. ' ' end -- Add space after existing shields
				shield = shield .. shieldWikitext(args[paramName], routeRoadInfo, args, prefix) -- Add the shield
			end
		end
		
		if showText then
			local routeText = getText(args[paramName], routeRoadInfo, args) -- Generate route text
			
			if routeText ~= '' then
				if text ~= '' then text = text .. ' / ' end -- Add " / " after existing text
				text = text .. getText(args[paramName], routeRoadInfo, args) -- Add route text
			end
		end
		
		if args[dirParam] then
			text = text .. ' ' .. args[dirParam] -- Add the direction
		end
		
		conNumber = conNumber + 1 -- Move on to the next concurrency
		local suffix = conNumber == 1 and '' or conNumber -- Calculate the next parameter suffix

		-- Update the parameter names
		paramName = prefix .. suffix
		typeParam = prefix .. 'type' .. suffix
		dirParam = prefix .. 'dir' .. suffix
	end
	
	return shield, text -- Return generated shield and text wikitext
end

-- Entry function
function p.jcon(frame)
	local args = getArgs(frame)

	if yesno(args.ot) then
		-- Set correct arguments if output should be only text
		args.nosh = 'yes'
		args.nolink = 'yes'
	end

	local roadType = normalizeType(args[1]) -- The first road type
	local showShield = not yesno(args.nosh)
	local showText = not yesno(args.notext)
	local shieldAfter = yesno(args.picaft or args['pic aft'])
	
	local shield = nil -- Generated shield wikitext
	local text = nil -- Generated text/name wikitext
	
	if data.signs[roadType] then
		-- Handle MTO signs
		shield = data.signs[roadType]
		text = args[2] or ''
	elseif data.types[roadType] then
		-- Handle numbered roads
		shield, text = processRoutes(roadType, showShield, showText, args, 'con')
		
		-- Handle to and via parameters
		local toShield, toText = processRoutes(roadType, showShield, showText, args, 'to')
		local viaShield, viaText = processRoutes(roadType, showShield, showText, args, 'via')
		
		if toShield ~= '' then
			shield = shield .. ' ' .. toShield -- Add to shields to output
		end
		
		if toText ~= '' then
			text = text .. (text == '' and 'To ' or ' to ') .. toText -- Add to text
		end
		
		if viaShield ~= '' then
			-- Add via shields to the output
			shield = shield .. (shield == '' and '' or ' <span style="vertical-align:middle;">Via</span> ') .. viaShield
		end
		
		if viaText ~= '' then
			-- Add via text to the output
			text = text .. (text == '' and 'Via ' or ' via ') .. viaText
		end
	else
		return '&#8203;' -- Return ZWSP if road type is not supported
	end
	
	if args.sign and showShield then
		if shield ~= '' then shield = shield .. ' ' end -- Add space after existing shields
		-- Add the MTO sign if provided
		shield = shield .. data.signs[args.sign]
	end
	
	if yesno(args.tch) then
		if showShield then
			if shield ~= '' then shield = shield .. ' ' end -- Add space after existing shields
			shield = shield .. '[[File:TCH-blank.svg|x20px]]' -- Add the TCH shield
		end

		if showText then
			if text ~= '' then text = text .. '&nbsp;/ ' end -- Add " / " after existing text
			text = text .. '[[Trans-Canada Highway|TCH]]' -- Add the TCH text
		end
	end
	
	local output = '' -- The returned output
	
	if not shieldAfter then
		-- Add the shield if it goes first
		output = output .. shield
	end
	
	if text ~= '' then
		if output ~= '' then output = output .. '&nbsp;' end -- Add a NBSP after the shield if it exists
		output = output .. text -- Add the generated text to the output
	end

	if args[3] then
		output = output .. ' (' .. args[3] .. ')' -- Add the name to the output
	end
	
	-- Process control cities
	if args.city or args.town then
		output = output .. ' – ' .. getPlace(args.city or args.town, args) -- Add the first city
		
		local extraCityNum = 2 -- The number of the additional city being processed
		
		while args['city' .. extraCityNum] or args['town' .. extraCityNum] do
			local val = args['city' .. extraCityNum] or args['town' .. extraCityNum]
			output = output .. ', ' .. getPlace(val, args) -- Add extra cities
			extraCityNum = extraCityNum + 1
		end
	end

	if shieldAfter and shield then
		if output ~= '' then output = output .. ' ' end -- Add a space if output already has text
		output = output .. shield -- Add the shield if it goes last
	end

	return output
end

return p