local p =
-- Change to "" upon deployment.local moduleSuffix = ""
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.parserlocal util = require("Module:Road data/util")local sizeModule = require("Module:Road data/size").size
-- Shieldslocal defaultShieldSize = 30
local function addContextBanner(route, name, suffix, bannerSpec) local bannerModule = 'Module:Road data/banners/' .. string.upper(route.country) local shieldfield = name .. 'shield' local shield = parser(route, shieldfield) if shield
nil then suffix = parser(route, '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 = sizeModule -- Add banner plate. insert(bannerSpec,) endend
local function bannerSpec(banner, bannerSize, bannerSuffix, route) local banners = if type(banner)
if route.dir then addContextBanner(route, 'dir', bannerSuffix, banners) end if route.to then addContextBanner(route, 'to', bannerSuffix, banners) end
return bannersend
local function shieldSpec(route, mainShield) local shieldSpec =
local shield if mainShield then shield = parser(route, "shieldmain") end if not shield then shield = parser(route, 'shield') or end if shield
local function size(route) 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 =
-- Return up to two booleans.-- The first boolean is false if `shield` does not exist, and true otherwise.-- If the first boolean is true, the second boolean is true if the shield is-- landscape (width >= height), and false otherwise.local function shieldExists(shield) local result = shieldExistsCache[shield] if result
local function render(shieldEntry, scale, showLink) local shield = shieldEntry.shield local banners = shieldEntry.banners local exists, landscape = shieldExists(shield[1]) if not exists then return end
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 if shieldExists(banner[1]) then shieldCode = format("
%s", banner[1], banner[2], shieldCode) end end return '
function p.shield(route, scale, showLink, mainShield) missingShields = if route.rdt then local shieldSize = mw.ustring.match(route.rdt, '^(%d+)$') or 17 scale = shieldSize/defaultShieldSize end scale = scale or 1
local rendered = for _,entry in ipairs(shieldSpec(route, mainShield)) do insert(rendered, render(entry, scale, showLink)) end return concat(rendered), missingShieldsend
function p.link(route) local abbr, errMsg = parser(route, 'abbr') if not abbr then route.typeerror = true return util.err(errMsg or format("Invalid type: %s", route.type or "(nil)")) end if route.nolink then return abbr, abbr end
local link = parser(route, 'link') or if link
return format("%s", link, abbr), abbrend
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
function p.locations(args, module, group) module = module or "" local modulearticle = module .. "article" local moduleprefix = module .. "prefix" local modulenameprefix = module .. "nameprefix" local modulenamesuffix = module .. "namesuffix"
local warnings =
-- Region, for disambiguation local region = parserModule.parser(args, "region", " common ") if not region then -- TODO transition if args.region then warnings.region = "region parameter is deprecated" region = args.region elseif args.country and (args.state or args.province) then warnings.region = "Inferring region from country and state/province" region = stateName(args) end end local regionName local regionText if type(region)
local locations = parserModule.parser(args, "locations", " common ") or
-- Primary topic requires no specialization to supplied locations. local primaryTopic = not locations and module
-- Independent city local indepCityText if args.indep_city_special then indepCityText = args.indep_city_special -- Overrides `indep_city` argument. elseif args.indep_city then local indepCity = args.indep_city local spec = locations.indep_city if spec then local link = format("%s%s%s", spec.linkprefix or "", indepCity, spec.linksuffix or "") local name = format("%s%s%s", spec[modulenameprefix] or spec.nameprefix or "", indepCity, spec[modulenamesuffix] or spec.namesuffix or "") indepCityText = format("%s%s%s", spec[modulearticle] or spec.article or "", spec[moduleprefix] or spec.prefix or "", link, name) else -- TODO transition warnings.indep_city = "Spec for indep_city parameter undefined in road data module" local cityLink -- Wikilink for independent city if primaryTopic then cityLink = format('%s', indepCity) else -- Specialize independent city to the region. cityLink = format('%s', indepCity, region, indepCity) end indepCityText = "City of " .. cityLink end end if indepCityText then return end
-- First-level subdivision, e.g., county -- Name of the type of subdivision, e.g., "County" and "Parish" local sub1name = args.sub1name -- TODO transition local sub1Text if args.sub1_special then sub1Text = args.sub1_special -- Overrides `sub1` argument. elseif args.sub1 then local sub1 = args.sub1 local article local link = sub1 local name = sub1 -- Type of first-level subdivision area, as a form of disambiguation local sub1area = args.sub1area if sub1area then local sub1areaSpec = locations.sub1areas and locations.sub1areas[sub1area] if sub1areaSpec then article = sub1areaSpec[modulearticle] or sub1areaSpec.article or "" link = format("%s%s%s", sub1areaSpec.linkprefix or "", link, sub1areaSpec.linksuffix or "") name = format("%s%s%s", group and "" or sub1areaSpec[modulenameprefix] or sub1areaSpec.nameprefix or "", name, group and "" or sub1areaSpec[modulenamesuffix] or sub1areaSpec.namesuffix or "") else -- TODO report error local errMsg = util.err(format("Undefined sub1area: %s", sub1area)) name = format("%s%s", name, errMsg) end end if locations.sub1 then local spec = locations.sub1 -- Prepend and append text from spec. link = format("%s%s%s", spec.linkprefix or "", link, spec.linksuffix or "") name = format("%s%s%s", spec[modulenameprefix] or spec.nameprefix or "", name, spec[modulenamesuffix] or spec.namesuffix or "") sub1Text = format("%s%s", article or "", link, name) else -- TODO transition warnings.sub1 = "Spec for sub1 parameter undefined in road data module" -- Add type (if specified) to wikilink for first-level subdivision. local sub1Link = sub1name and trim(format("%s %s", sub1, sub1name)) or sub1 local sub1Name = module
-- Second-level subdivision, e.g., city and town local sub2Text if args.sub2_special then sub2Text = args.sub2_special -- Overrides `sub2` argument. elseif args.sub2 then local sub2 = args.sub2 if sub2
" " then -- TODO transition warnings.sub2 = " argument for sub2 parameter is deprecated" sub2Text = "" -- Zero-width space elseif primaryTopic then -- TODO transition sub2Text = format("%s", sub2) else local article local link = sub2 local name = sub2 -- Type of area, e.g., city and village, as a form of disambiguation local sub2area = args.sub2area --TODO transition or args.area if sub2area then local sub2areaSpec = locations.sub2areas and locations.sub2areas[sub2area] if not sub2areaSpec then -- TODO transition warnings.sub2 = format("Spec for area parameter '%s' undefined in road data module", sub2area) local sub2areas = sub2areaSpec = sub2areas[sub2area] end if sub2areaSpec then article = sub2areaSpec[modulearticle] or sub2areaSpec.article or "" link = format("%s%s%s", sub2areaSpec.linkprefix or "", link, sub2areaSpec.linksuffix or "") name = format("%s%s%s", group and "" or sub2areaSpec[modulenameprefix] or sub2areaSpec.nameprefix or "", name, group and "" or sub2areaSpec[modulenamesuffix] or sub2areaSpec.namesuffix or "") else -- TODO report error local errMsg = util.err(format("Undefined sub2area: %s", sub2area)) name = format("%s%s", name, errMsg) end end if locations.sub2 then local spec = locations.sub2 -- Prepend and append text from spec. link = format("%s%s%s", spec.linkprefix or "", link, spec.linksuffix or "") name = format("%s%s%s", spec[modulenameprefix] or spec.nameprefix or "", name, spec[modulenamesuffix] or spec.namesuffix or "") else -- TODO transition warnings.sub2 = "Spec for sub2 parameter undefined in road data module" -- Some second-level subdivisions are not unique in a given region. -- `sub1dab` is the first-level subdivision to be used for disambiguation. local sub1dab = args.sub1dab if sub1dab then sub1dab = sub1name and trim(format("%s %s", sub1dab, sub1name)) or sub1dab link = format("%s, %s", link, sub1dab) end link = format("%s, %s", link, region) -- Add region to wikilink end sub2Text = format("%s%s", article or "", link, name) end end return end
return p