Module:Routelist row: Difference between revisions

Content deleted Content added
Adding "Formed" column, and merging with "Removed" column
drop nowrap - was causing horizontal scrolling on List of Ontario provincial highways for 407
 
(74 intermediate revisions by 9 users not shown)
Line 1:
local p = { } -- Package to be exported
local getArgs = require('Module:Arguments').getArgs -- Import module function to work with passed arguments
local lang = mw.getContentLanguage()
local lang = mw.getContentLanguage() -- Retrieve built-in locale for date formatting
local mw = require "Module:mw"
local format = mw.ustring.format -- String formatting function
local frame = mw.getCurrentFrame()
 
local routeStates = { } -- Table with route statuses.
--[[ The following tables include the following entries:
routeStates.current = {row = "|- \n", removed = "present"}
row: The start of the row, for this particular type (color)
routeStates.future = {row = "|- style=\"background-color:#ffdead;\" title=\"Future route\"\n", removed = "proposed"}
established: The string to be output in the "Formed" column. For future routes, "proposed" is displayed here. Otherwise, display the year passed in the established parameter.
routeStates.former = {row = "|- style=\"background-color:#d3d3d3;\" title=\"Former route\"\n"}
removed: The string to be output in the "Removed" column. In the case of routeStates.former, the year that the route was decommissioned is output instead.
routeStates.unknown = {row = "|- \n", removed = "—"}
]]--
routeStates.current = {row = "|-", removed = "current"} -- Data for current routes
routeStates.future = {row = '|- style="background-color:#ffdead;" title="Future route"', established = "proposed", removed = "—"} -- Data for future routes
routeStates.former = {row = '|- style="background-color:#d3d3d3;" title="Former route"'} -- Data for former routes
routeStates.formeroverride = {row = '|- style="background-color:#d3d3d3;" title="Former route"', removed = "—"} -- Data for routes marked as former by override
routeStates.unknown = {row = "|-", removed = "—"} -- Data for route with unknown status
 
function getRouteState(argsestablished, decommissioned)
--[[ This function is passed the dates given for the established and decommissioned fields to the template.
local established = args.established
It then returns the entry in the routeStates table corresponding to the status of the route.
local decommissioned = args.decommissioned
]]--
if established == '' then
if decommissioned == 'yes' then --If the decommissioned property just says "yes", then mark it as a former route and display default data.
return routeStates.unknown
return routeStates.formeroverride
elseif decommissioned ~= '' then
elseif decommissioned then -- If the route is decommissioned, then it must be a former route.
return routeStates.former
return routeStates.former
elseif lang:formatDate("Y-m-d") < established then
elseif not established then -- Without the establishment date, there is not enough information to determine the status of the route.
return routeStates.future
return routeStates.unknown
else
elseif established == 'proposed' then -- If the "established date" is the string 'proposed', then it must be a future route.
return routeStates.current
return routeStates.future
end
else -- If none of the first three conditions are true, then it must be a current route.
return routeStates.current
end
end
 
function dtsYeardtsYearCore(date, circa)
-- A limited replacement for {{dts}}. This is passed a date and derives a sort key from it. It returns a string with the hidden sort key, along with the year of the original date.
local year = lang:formatDate('Y', date)
if not date then return false end -- If the date is an empty string, stop and go back to whence it came.
if year == date then
local year = lang:formatDate('Y', date) -- This invocation of lang:formatDate returns just the year.
date = date .. "-01-01"
if year == date then -- If the provided date is just the year:
end
date = date .. "-01-01" -- Tack on January 1 for the sort key to work right.
local month = lang:formatDate('m', date)
end
local day = lang:formatDate('d', date)
local dtsStrmonth = string.formatlang:formatDate("%05d'm', date) -%02d-%02d", year,Stores the month, day)of the date.
local day = lang:formatDate('d', date) -- Stores the day for this date.
local spanParams = {style = "display:none; speak:none"}
local dtsStr = string.format("%05d-%02d-%02d", year, month, day) -- Create and store the formatted hidden sort key. The year must be five digits, per convention.
local dtsSpan = mw.text.tag({name='span', contents=dtsStr, params=spanParams})
local spanParams = {style = "display:none; speak:none"} -- These CSS properties hide the sort key from normal view.
return dtsSpan .. year
local dtsSpan = mw.text.tag({name='span', content=dtsStr, attrs=spanParams}) -- This generates the HTML code necessary for the hidden sort key.
if circa == 'yes' then -- If the date is tagged as circa,
return dtsSpan .. "<abbr title=\"circa\">c.</abbr><span style=\"white-space:nowrap;\">&thinsp;" .. year .. "</span>" -- Add the circa abbreviation to the display. Derived from {{circa}}
else -- Otherwise,
return dtsSpan .. year -- Return the hidden sort key concatenated with the year for this date.
end
end
 
function dtsYear(date, circa)
--This function determines if this is a future route, present route, or decommissioned route, and colors the row appropriately.
local success, result = pcall(dtsYearCore, date, circa)
function p.rowcolor(frame)
if success then
local pframe = frame:getParent()
return result
local config = frame.args -- the arguments passed BY the template, in the wikitext of the template itself
else
local args = pframe.args -- the arguments passed TO the template, in the wikitext that transcludes the template
return string.format('%s<span class="error">Error: Invalid date "%s".</span>', circa and '<abbr title="circa">c.</abbr>&thinsp;' or '', date)
end
--Import parameters from template
end
local established = config[1]
local decommissioned = config[2]
local dates = {["established"] = established, ["decommissioned"] = decommissioned}
local routeState = getRouteState(dates)
 
function removed(routeState, decommissioned, circa)
return routeState.row
-- This function returns the proper value for the removed column.
return routeState.removed or dtsYear(decommissioned, circa) -- Returns the removed attribute of the provided routeState table or, if empty, the dtsYear-formatted decommissioned date.
end
 
function formed(routeState, established, circa)
--This function determines if this is a beltway or not, and displays the termini columns appropriately.
-- This function returns the proper value for the formed column.
function p.termini(frame)
return routeState.established or dtsYear(established, circa) or "—" -- Returns 'proposed' if the route is proposed, the dtsYear-formatted established date if one was provided, or an em-dash.
local pframe = frame:getParent()
end
local config = frame.args -- the arguments passed BY the template, in the wikitext of the template itself
local args = pframe.args -- the arguments passed TO the template, in the wikitext that transcludes the template
--Import parameters from template
local beltway = config[1]
local terminus_a = config[2]
local terminus_b = config[3]
 
function sortkey(args)
--The template passes this function an empty string if {{{beltway}}} is not specified by the template user.
-- This function return the sort key for the route (not to be confused with the previous function, which generates a sort key for the established and decommissioned dates.)
if beltway ~= '' then
local key = args.sortkey
return "|colspan=2 align=center|" .. beltway
local type = args.type
else
local route = args.route or ''
return '|' .. terminus_a .. '||' .. terminus_b
if key then -- If a sort key already exists:
end
return key -- Simply return it.
else -- Otherwise:
local routeKey
local routeNum = tonumber(route)
if routeNum then
routeKey = string.format('%04d', route) -- This invocation is equivalent to the {{0000expr}} template. It zero-pads the given route number up to 4 digits.
else
local num, suffix = string.match(route, "(%d*)(.+)")
routeKey = (tonumber(num) and string.format('%04d', num) or '') .. suffix
end
return type .. routeKey -- Return the sort key for this route, composed of the type and zero-padded route number.
end
end
 
function termini(args)
--This function returns the proper value for the removed column.
-- This function determines if this is a beltway or not, and displays the termini columns appropriately.
function removed(routeState)
local beltway = args["beltway"] -- Text in this parameter will span both termini columns.
return routeState.removed or dtsYear(decommissioned)
local terminus_a = args["terminus_a"] or '—' -- Southern or western terminus
local terminus_b = args["terminus_b"] or '—' -- Northern or eastern terminus
if beltway then
return "|colspan=2 align=center|" .. beltway -- This text will, again, span both columns.
else
return '|' .. terminus_a .. '||' .. terminus_b -- Fill in the termini columns
end
end
 
function dates(established, decommissioned, routeState, args)
--This function displays the date columns.
-- This function displays the date columns.
function p.dates(frame)
local pframe = frame:getParent()
local config = frame.args -- the arguments passed BY the template, in the wikitext of the template itself
if args.gazette == 'yes' then
local args = pframe.args -- the arguments passed TO the template, in the wikitext that transcludes the template
local established = args.established or "—"
local established_ref = args.established_ref or ''
--Import parameters from template
local established = config[1]
return "|align=center|" .. established .. established_ref
local decommissioned = config[2]
else
local established_ref = args.established_ref or '' -- Reference for date established
local dates = {["established"] = established, ["decommissioned"] = decommissioned}
local decommissioned_ref = args.decommissioned_ref or '' -- Reference for date decommissioned
local routeState = getRouteState(dates)
local output = return "|align=center|" .. dtsYearformed(routeState, established), args.. "|align=center|"circa_established) .. removed(routeState)
established_ref .. "||align=center|" .. removed(routeState, decommissioned, args.circa_decommissioned) ..
decommissioned_ref
end
end
 
--- Return output for the length columns for a given route, with the appropriate conversions.
local function length(args)
local km = args["length_km"] or '' -- Length in kilometers
local mi = args["length_mi"] or '' -- Length in miles
local ref = args["length_ref" ] or ''
 
if mi == '' and km == '' then
return format("|align=right|—||align=right|—")
elseif mi ~= '0' and km == '' then
return format("|align=right|") .. mi .. ref .. format("||align=right|") .. frame:expandTemplate{ title = 'convert', args = { mi, "mi", "km", disp = "output number only"}}
else
return format("|align=right|") .. km .. ref .. format("||align=right|") .. frame:expandTemplate{ title = 'convert', args = { km, "km", "mi", disp = "output number only"}}
end
end
 
function localname(args)
-- This function generates a "Local names" cell if necessary
local enabled = args[1] or ''
local localName = args["local"] or ''
if mw.text.trim(enabled) == "local" then
return "|" .. localName
else
return ''
end
end
 
function notes(notes)
-- This function generates a "Notes" cell if necessary.
if notes == 'none' then
return '| ' --create empty cell
elseif notes then
return '|' .. notes --display notes in cell
else
return '' --create no cell
end
end
 
function gap(args)
local text = args.text or "''Number not designated''"
if notes then
return '|align=center colspan=7|' .. text --display notes in cell
else
return '|align=center colspan=6|' .. text --display notes in cell
end
end
 
function route(args)
-- This function displays the shield and link.
local format = mw.ustring.format
local parserModule = require "Module:Road data/parser"
local parser = parserModule.parser
local noshield = args.noshield
local bannerFile = parser(args, 'banner')
local banner
if not noshield and bannerFile and bannerFile ~= '' then
local widthCode = parser(args, 'width') or 'square'
if widthCode == 'square' then
banner = format("[[File:%s|25px|link=|alt=]]", bannerFile)
elseif widthCode == 'expand' then
local route = args.route
if #route >= 3 then
banner = format("[[File:No image.svg|3px|link=|alt=]][[File:%s|25px|link=|alt=]][[File:No image.svg|3px|link=|alt=]]", bannerFile)
else
banner = format("[[File:%s|25px|link=|alt=]]", bannerFile)
end
elseif widthCode == 'wide' then
banner = format("[[File:No image.svg|3px|link=|alt=]][[File:%s|25px|link=|alt=]][[File:No image.svg|3px|link=|alt=]]", bannerFile)
elseif widthCode == 'MOSupp' then
local route = args.route
if #route >= 2 then
banner = format("[[File:No image.svg|3px|link=|alt=]][[File:%s|25px|link=|alt=]][[File:No image.svg|3px|link=|alt=]]", bannerFile)
else
banner = format("[[File:%s|25px|link=|alt=]]", bannerFile)
end
elseif widthCode == 'US1926' then
banner = format("[[File:%s|25px|link=|alt=]][[File:No image.svg|1px|link=|alt=]]", bannerFile)
elseif args.state == 'CA' then
local route = args.route
local type = args.type
if type == 'US-Bus' then
if #route >= 3 then
banner = format("[[File:No image.svg|2px|link=|alt=]][[File:%s|25px|link=|alt=]][[File:No image.svg|2px|link=|alt=]]", bannerFile)
else
banner = format("[[File:%s|25px|link=|alt=]]", bannerFile)
end
elseif type == 'CA-Bus' or type == 'SR-Bus' then
if #route >= 3 then
banner = format("[[File:No image.svg|1px|link=|alt=]][[File:%s|25px|link=|alt=]][[File:No image.svg|2px|link=|alt=]]", bannerFile)
else
banner = format("[[File:%s|24px|link=|alt=]]", bannerFile)
end
end
end
banner = banner .. '<br>'
else
banner = ''
end
 
local shield
if not noshield then
local shieldFile, second = parser(args, 'shieldlist') or parser(args, 'shield') or ''
if shieldFile == nil or shieldFile == '' then
shield = ''
elseif type(shieldFile) == 'table' then
shieldFile, second = shieldFile[1], shieldFile[2]
end
if second and type(second) == 'string' then
local shield1 = format("[[File:%s|x25px|alt=|link=]]", shieldFile)
local shield2 = format("[[File:%s|x25px|alt=|link=]]", second)
shield = shield1 .. shield2
elseif shield == '' then
shield = ''
else
shield = shieldFile and format("[[File:%s|x25px|alt=|link=]]", shieldFile) or ''
end
else
shield = ''
end
local linkTarget = (not args.nolink) and parser(args, 'link')
local abbr = parser(args, 'abbr')
local link
if linkTarget then
link = format("[[%s|%s]]", linkTarget, abbr)
else
link = abbr
end
if not link then error("Type not in database: " .. args.type) end
local sortkey = sortkey(args)
local sortedLink = format("<span data-sort-value=\"%s&#32;!\">%s</span>", sortkey, link)
local route = banner .. shield .. ' ' .. sortedLink
return '|' .. route
end
 
function p.row(frame)
local args = getArgs(frame) -- Gather passed arguments into easy-to-use table
local established = args.established
local decommissioned = args.decommissioned
local routeState = getRouteState(established, decommissioned)
local anchor = args.anchor or sortkey(args)
local rowdef = routeState.row .. string.format(' id="%s"', anchor)
local route = route(args)
local length = length(args)
local termini = termini(args)
local localname = localname(args)
local dates = dates(established, decommissioned, routeState, args)
local notesArg = args.notes
local notes = notes(notesArg)
local row = {rowdef, route, length, termini, localname, dates, notes}
return table.concat(row, '\n')
end
 
function p.gap(frame)
local args = getArgs(frame) -- Gather passed arguments into easy-to-use table
 
local routeState = getRouteState(established, decommissioned)
local anchor = args.anchor or sortkey(args)
local rowdef = routeState.row .. string.format(' id="%s"', anchor)
local route = route(args)
local gap = gap(args)
local row = {rowdef, route, gap}
return table.concat(row, '\n')
end