Module:Jcon
Appearance
This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
This module depends on the following other modules: |
This module implements Template:Jcon and Template:Shieldlist.
require('strict')
local p = {}
local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local parser = require('Module:Road data/parser').parser
local dataModuleName = 'Module:Jcon/data'
local data = mw.loadData(dataModuleName)
-- Normalize the given road type
local function normalizeType(roadType)
roadType = (roadType or ''):lower() -- Make the road type lowercase
for index, placeType in ipairs(data._placeTypes) do
roadType = roadType -- Remove the place types from the road type
:gsub('^' .. placeType .. ' of ', '')
:gsub(' ' .. placeType .. '$', '')
:gsub(' ' .. placeType .. ' road$', '')
end
return roadType
end
-- Generate wikitext to show an icon
local function showFile(fileName, args, sign)
local size = args.size or '20px' -- Image size
if sign then
fileName = data._signs[fileName] -- Get the file name from the sign definition
else
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
end
return '[[File:' .. fileName .. '|alt=|link=|' .. size .. ']]' -- Return the file wikitext
end
-- Get the first defined shield from a table
local function getShield(parserArgs, shield, to)
-- Shield format for "to" routes
if to and shield then
local res = parser(parserArgs, 'shieldtomain', nil, dataModuleName)
if res then return res end
end
-- Guide format for "to" routes
if to then
local res = parser(parserArgs, 'shieldto', nil, dataModuleName)
if res then return res end
end
-- Shield format (used as reassurance marker)
if shield then
local res = parser(parserArgs, 'shieldlist', nil, dataModuleName)
if res then return res end
end
-- Guide format (used on guide signs)
local res = parser(parserArgs, 'shield', nil, dataModuleName)
if res then return res end
return ''
end
-- Generate the wikitext for the shield
local function shieldWikitext(parserArgs, args, prefix)
local shield = getShield(parserArgs, yesno(args.shield), prefix == 'to')
if type(shield) == 'table' then
local out = {}
for i, single in ipairs(shield) do
table.insert(out, showFile(single, args))
end
return table.concat(out, ' ') -- Add a space between multiple shields
end
return showFile(shield, args)
end
-- Display a link, accounting for presentation arguments
local function displayLink(link, display, args, followNoLink, noSelfRedirect)
local titleObj = mw.title.new(link)
local noLink = followNoLink and yesno(args.nolink)
local showRed = yesno(args.showred)
if
(not noLink)
and (showRed or (titleObj and titleObj.exists))
and not (noSelfRedirect and titleObj and titleObj.redirectTarget == mw.title.getCurrentTitle())
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(parserArgs, args, noSelfRedirect)
local link = parser(parserArgs, 'link', nil, dataModuleName)
local display = ''
if yesno(args.fulltext) then
-- Display the full link title when requested
display = parser(parserArgs, 'name', nil, dataModuleName)
else
display = parser(parserArgs, 'abbr', nil, dataModuleName)
end
return displayLink(link, display, args, true, noSelfRedirect)
end
-- Gets the wikitext link for a place
local function getPlace(place, args)
return displayLink(place .. ', Ontario', place, args)
end
-- Process routes present in the provided arguments
local function processRoutes(roadType, showShield, showText, args, prefix, name)
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 routeRoadType = roadType -- Local copy of the road info
if typeParam and args[typeParam] then
-- Override the road info if one is provided
routeRoadType = normalizeType(args[typeParam])
end
-- Arguments for the road data parser
local parserArgs = {
ignoreifexists = true,
country = 'CAN',
province = 'ON',
type = routeRoadType,
route = args[paramName]
}
if showShield then
local routeShield = shieldWikitext(parserArgs, args, prefix) -- Generate route shield
if routeShield ~= '' then
if shield ~= '' then shield = shield .. ' ' end -- Add space after existing shields
shield = shield .. routeShield -- Add the shield
end
end
if showText then
local routeText = getText(parserArgs, args) -- Generate route text
if routeText ~= '' then
if text ~= '' then text = text .. ' / ' end -- Add " / " after existing text
text = text .. routeText -- 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
if name and yesno(args.namefirst) then
text = name .. ' (' .. text .. ')' -- Output name before text when namefirst is set to yes
elseif name then
text = text .. ' (' .. name .. ')' -- Add the name to the produced text
end
return shield, text -- Return generated shield and text wikitext
end
-- Entry function for {{jcon}}
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 = showFile(roadType, args, true)
text = args[2] or ''
elseif data[roadType] then
-- Handle numbered roads
shield, text = processRoutes(roadType, showShield, showText, args, 'con', args[3])
-- Handle to and via parameters
local toShield, toText = processRoutes(roadType, showShield, showText, args, 'to', args.toname)
local viaShield, viaText = processRoutes(roadType, showShield, showText, args, 'via', args.vianame)
if toShield ~= '' then
shield = shield .. (shield == '' and '' or ' ') .. 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 '​' -- 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 .. showFile(args.sign, args, true)
end
if yesno(args.tch) then
if showShield then
if shield ~= '' then shield = shield .. ' ' end -- Add space after existing shields
shield = shield .. showFile('tch', args, true) -- Add the TCH shield
end
if showText then
if text ~= '' then text = text .. ' / ' 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 .. ' ' end -- Add a NBSP after the shield if it exists
output = output .. text -- Add the generated text 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
-- Entry function for {{shieldlist}}
function p.shieldlist(frame)
local args = getArgs(frame)
local type = normalizeType(args[1])
local route = args[2]
local size = args.size or '36px'
if not data[type] then return '' end
-- Add table
local out = '<table style="background: transparent; margin: 0; padding: 0; width: 100%; align: left;">'
-- Add a table row
out = out .. '<tr>'
-- Arguments for the road data parser
local parserArgs = {
ignoreifexists = true,
country = 'CAN',
province = 'ON',
type = type,
route = route
}
-- Generate route shield
local routeShield = shieldWikitext(parserArgs, { size = size, shield = true })
if routeShield ~= '' then
out = out .. '<td style="background: transparent; border: 0px; margin: 0px; padding: 0px;">' .. routeShield .. '</td>'
end
-- Generate route text
local routeText = getText(parserArgs, { fulltext = true }, true)
if routeText ~= '' then
out = out .. '<td style="background: transparent; border: 0px; margin: 0px; padding: 0px; text-align: center;">' .. routeText .. '</td>'
end
out = out .. '</tr></table>' -- Finish the table and table row
return out
end
return p