local p = -- Package to be exported
-- Change to "" upon deployment.local moduleSuffix = ""
local lang = mw.getContentLanguage -- Built-in locale for date formattinglocal format = mw.ustring.format -- String formatting functionlocal insert = table.insertlocal concat = table.concatlocal util = require("Module:Road data/util")local frame = mw.getCurrentFrame
local parserModuleName = "Module:Road data/parser" .. moduleSuffixlocal statenameModuleName = "Module:Jct/statename" .. moduleSuffix -- TODO transition
local concat = table.concatlocal insert = table.insertlocal format = mw.ustring.formatlocal trim = mw.text.trim
local parserModule = require(parserModuleName)local parser = parserModule.parser
-- Shieldslocal defaultShieldSize = 28
local function addContextBanner(args, name, suffix, bannerSpec) local bannerModule = 'Module:Road data/banners/' .. string.upper(args.country) local shieldfield = name .. 'shield' local shield = parser(args, shieldfield) if shield
nil then suffix = parser(args, 'shield', 'suffix', bannerModule) end if suffix and suffix ~= then shield = shield .. " " .. suffix end shield = shield .. ".svg" end end if shield and shield ~= then local shieldSize = defaultShieldSize -- Add banner plate. insert(bannerSpec,) endend
local function bannerSpec(banner, bannerSize, bannerSuffix, route) local banners = if type(banner)
return bannersend
local function shieldSpec(args, mainShield, shieldList) local shieldSpec =
local shield
if not shield then shield = parser(args, 'shieldlist') or parser(args, 'shield') or end if shield
local function size(args) if orientation
local bannerIsNotTable = type(banner) ~= "table" local bannersizeIsNotTable = type(bannersize) ~= "table" local bannersuffixIsNotTable = type(bannersuffix) ~= "table"
if type(shield)
"" then size = nil end -- banner.all describes banners that apply to all multiple shields. local shieldBanner = bannerIsNotTable and banner or (banner[i] or banner.all or) -- Banner size is default if the corresponding entry -- in bannerSize table is not set. local shieldBannerSize = bannersizeIsNotTable and bannersize or (bannersize[i] or bannersize.all or defaultShieldSize) local shieldBannerSuffix = bannersuffix and (bannersuffixIsNotTable and bannersuffix or bannersuffix[i]) insert(shieldSpec,) end elseif shield ~= then if shieldsize
return shieldSpecend
local missingShields
local shieldExistsCache =
local function render(shieldEntry, scale, showLink) local shield = shieldEntry.shield local banners = shieldEntry.banners
local size if shield[2] then local width, height = mw.ustring.match(shield[2], "(%d*)x?(%d*)") width = tonumber(width) height = tonumber(height) local sizeparts = if width then insert(sizeparts, format("%d", width * scale)) end if height then insert(sizeparts, format("x%d", height * scale)) end size = concat(sizeparts) else size = format("%s%d", landscape and "x" or "", defaultShieldSize * scale) end local shieldCode = format("", shield[1], size) if not banners[1] then return shieldCode end
for _,banner in ipairs(banners) do shieldCode = format("
%s", banner[1], defaultShieldSize, shieldCode) end return '
function p.shield(args, scale, showLink, mainShield, shieldList) missingShields =
scale = scale or 1
local rendered = for _,entry in ipairs(shieldSpec(args, mainShield, shieldList)) do insert(rendered, render(entry, scale, showLink)) end return concat(rendered), missingShieldsend
-- Links/abbreviationsfunction p.link(args) local nolink = args.nolink local abbr = parser(args, 'abbr') if nolink then return abbr else local link = parser(args, 'link') if not link or link
local function stateName(args) -- TODO transition local data = mw.loadData(statenameModuleName) local abbr = args.state or args.province local countryData = data[args.country] return countryData and countryData[abbr]end
-------------------------------Route statuses.@list <#status>local routeStatuses =
---Return the route status.@param #string established `established` argument passed to the module@param #string decommissioned `decommissioned` argument passed to the module@return #status the status of the route.local function getRouteStatus(established, decommissioned) if decommissioned
'proposed' then -- a future route return routeStatuses.future else -- a current route return routeStatuses.current endend
---A limited replacement for .Derive the sort key from a given date.@param #string date@param #string circa "yes" if `date` is tagged as circa@return #string true the hidden sort key, along with the year of the original date@return #boolean false if the sort key cannot be derivedlocal function dtsYearCore(date) local year = lang:formatDate('Y', date) -- year for this date if year
local function dtsYear(date, circa) local success, result = pcall(dtsYearCore, date) if not success then result = end -- Generate the HTML code necessary for the hidden sort key. local dtsStyle = format("style=\"white-space:nowrap;\" data-sort-value=\"%s\"", result[1]) local year = result[2] if circa
--- Return formatting and output for a date column.local function date(text, date, circa, ref) -- Returns the text if specified, or the dtsYear-formatted date, and an em-dash. local style, output if text then output = text elseif date then style, output = dtsYear(date, circa) else output = "—" end return format("|align=center %s|%s%s", style or "", output, ref)end
--- Return output for the date columns for a given route.local function dates(established, decommissioned, routeStatus, args) local established_ref = args.established_ref or -- Reference for date established local decommissioned_ref = args.decommissioned_ref or -- Reference for date decommissioned return format("%s\n%s", date(routeStatus.established, established, args.circa_established, established_ref), date(routeStatus.removed, decommissioned, args.circa_decommissioned, decommissioned_ref))end
--- Return output for the termini columns for a given route.local function termini(args) local beltway = args["beltway"] if beltway then -- The given route is a beltway. -- `beltway` text will span both termini columns. return "|colspan=2 align=center|" .. beltway else local terminus_a = args["terminus_a"] or '—' -- Southern or western terminus local terminus_b = args["terminus_b"] or '—' -- Northern or eastern terminus -- Fill in the termini columns return '|' .. terminus_a .. '||' .. terminus_b endend
--- 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
then return format("|align=right|—||align=right|—") elseif mi ~= '0' and km
--- Generate a "Local names" cell if necessary.local function localname(args) local enabled = args[1] or if enabled
--- Generate a "Notes" cell if necessary.local function notes(notes) if notes
--- Derive the sort key from a given route.local function sortkey(abbr) -- Split `abbr` into three possibly empty parts, with number in the middle. local prefix, num, suffix = mw.ustring.match(abbr, "([^0-9]*)(%d*)(.*)") -- If `abbr` does not contain a number, the entry appears at the bottom. num = tonumber(num) num = type(num)
local function route(args, shieldSize) local link, abbr = p.link(args) -- Use the sort key if already specified. local sortkey = args.sortkey or sortkey(abbr or "") local shield = p.shield(args)
if shield
--- Derive the anchor from a given route.local function anchor(routeType, routeNo) -- Split `routeNo` into three possibly empty parts, with number in the middle. local prefix, num, suffix = mw.ustring.match(routeNo, "([^0-9]*)(%d*)(.*)") -- Zero-pad route number to 4 digits if `routeNo` does contain a number. num = tonumber(num) num = type(num)
function p._row(args) local established = args.established local decommissioned = args.decommissioned local routeStatus = getRouteStatus(established, decommissioned) local anchor = args.anchor or anchor(args.type, args.route) local rowdef = format('%s id="%s"', routeStatus.row, anchor) local route = route(args) local length = length(args) local termini = termini(args) local localname = localname(args) local dates = dates(established, decommissioned, routeStatus, args) local notes = notes(args.notes)
local row = return concat(row, '\n')end
function p.row(frame) -- Import module function to work with passed arguments local getArgs = require('Module:Arguments').getArgs local args = getArgs(frame) -- Gather passed arguments into easy-to-use table return p._row(args);end
return p