local p = {}  -- Change to "" upon deployment. local moduleSuffix = ""  local parserModuleName = "Module:Road data/parser" .. moduleSuffix local statenameModuleName = "Module:Jct/statename" .. moduleSuffix -- TODO transition local cityModuleName = "Module:Jct/city" .. moduleSuffix  local concat = table.concat local insert = table.insert local format = mw.ustring.format local trim = mw.text.trim  local parserModule = require(parserModuleName) local parser = parserModule.parser local util = require("Module:Road data/util")  -- Shields local defaultShieldSize = 17  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 		-- This route type does not define shield. 		-- Find shield in the default banner table. 		shield = parser(route, 'shield', name, bannerModule) 		if shield and shield ~=  then 			if suffix == 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 = defaultShieldSize 		-- Add banner plate. 		insert(bannerSpec, {shield, shieldSize}) 	end end  local function bannerSpec(banner, bannerSize, bannerSuffix, route) 	local banners = {} 	if type(banner) == "table" then 		local bannerSizeIsNotTable = type(bannerSize) ~= "table" 		for i,filename in ipairs(banner) do 			local bannersize = bannerSizeIsNotTable and bannerSize or bannerSize[i] or defaultShieldSize 			insert(banners, {filename, bannersize}) 		end 	elseif banner ~=  then 		insert(banners, {banner, bannerSize}) 	end  	if route.dir then 		addContextBanner(route, 'dir', bannerSuffix, banners) 	end 	if route.to then 		addContextBanner(route, 'to', bannerSuffix, banners) 	end  	return banners end  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 ==  then return shieldSpec end 	local orientation = parser(route, 'orientation')  	local shieldsize = defaultShieldSize 	 	local banner = parser(route, 'banner') or {} 	local bannersize = defaultShieldSize 	local bannersuffix = parser(route, 'bannersuffix')  	local bannerIsNotTable = type(banner) ~= "table" 	local bannersizeIsNotTable = type(bannersize) ~= "table" 	local bannersuffixIsNotTable = type(bannersuffix) ~= "table"  	if type(shield) == "table" then 		for i,filename in ipairs(shield) do 			local size = shieldsize or shieldsize[i] 			if size == "" 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, { 				shield = {filename, size}, 				banners = bannerSpec(shieldBanner, shieldBannerSize, shieldBannerSuffix, route) 			}) 		end 	elseif shield ~=  then 		if shieldsize == "" then shieldsize = nil end 		insert(shieldSpec, { 			shield = {shield, shieldsize}, 			banners = bannerSpec(banner, bannersize,  bannersuffix, route) 		}) 	end  	return shieldSpec end  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 == nil then 		local file = mw.title.new(shield, 'Media').file 		-- Cache result. 		local exists = file.exists 		result = {exists} 		if exists then result[2] = file.width >= file.height end 		shieldExistsCache[shield] = result 	end 	if result[1] then return true, result[2] end 	insert(missingShields, shield) 	return false end  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, defaultShieldSize * scale) 	end 	local link = showLink and "" or "|link=" 	local shieldCode = format("x%spx%s|%s", shield[1], size, link, shield[1]) 	if not banners[1] then return shieldCode end  	for _,banner in ipairs(banners) do 		shieldCode = format("%spx|link=|alt=%s", 			banner[1], 			defaultShieldSize, 			shieldCode) 	end 	return '' .. shieldCode .. '' end  function p.shield(route, scale, showLink, mainShield) 	missingShields = {}  	scale = 1  	local rendered = {} 	for _,entry in ipairs(shieldSpec(route, mainShield)) do 		insert(rendered, render(entry, scale, showLink)) 	end 	return concat(rendered) end  function p.link(route) 	local abbr, errMsg = parser(route, 'abbr') 	if not abbr then end 	if route.nolink then return abbr, abbr end  	local link = parser(route, 'link') or 	if link ==  then return abbr, abbr end  	return format("%s", link, abbr), abbr end  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  -- Links/abbreviations local function routeText(route, frame) 	local link 	local type = route.type 	if not type or type ==  then 		link = route.route 	else 		link = p.link(route) 	end  	local dir = route.dir and ' ' .. string.lower(route.dir) or  	local routeText = link .. dir  	local name = route.name 	if name and name ~=  then 		local mainText = routeText 		local parenText = name  	return frame:expandTemplate{ title = 'BSsplit', args = {mainText, parenText, align = 'left', valign = 'middle' } } 	else 		return routeText 	end end  local function parseArgs(args) 	local state = args.state or args.province or  	args.state = state 	local country 	if args.country and args.country ~=  then 		country = string.upper(args.country) 	else 		local countryModule = mw.loadData("Module:Road data/countrymask") 		country = countryModule[state] or 'UNK' 	end 	args.country = country  	local params = {'denom', 'county', 'township', 'dab', 'nolink', 'noshield', 'to', 'dir', 'name'} 	local routes = {} 	local routeCount = 1 	local seenTo = false 	while true do 		local routeType = args[routeCount * 2 - 1] 		if not routeType then break end 		local route = {type = routeType, route = args[routeCount * 2]} 		for _,v in pairs(params) do 			route[v] = args[v .. routeCount] 		end 		route.country = country 		route.state = state  		-- Set the first .to to true. 		-- Set all following .to to . 		if seenTo then 			if route.to then 				-- Report duplicate to flag. 				route.toerror = true 			end 			route.to = 		elseif route.to then 			route.to = true 			seenTo = true 		end  		route.rdt = args.rdt 		insert(routes, route) 		routeCount = routeCount + 1 	end 	return routes end  local function prefix(to, num) 	if to and to ~=  then 		return num == 1 and 'পর্যন্ত ' or ' পর্যন্ত ' 	end 	return num == 1 and  or ' / ' end  function p._jctrdt(args, frame) 	local routes = parseArgs(args) 	local shields = {} 	local links = {} 	frame = frame or mw.getCurrentFrame() 	for num,route in ipairs(routes) do 		if not (args.noshield or route.noshield) then 			local shield = p.shield(route) 			insert(shields, shield) 		end 		local prefix = prefix(route.to, num) 		if prefix ~=  then insert(links, prefix) end 		insert(links, routeText(route, frame)) 	end 	local graphics = concat(shields) .. ' ' 	local linkText = concat(links) 	local cities = 	if args.city1 or args.location1 then 		local citiesPrefix 		if args.citiesprefix then 			citiesPrefix = args.citiesprefix ~=  and format(" %s ", args.citiesprefix) or '' 		else 			citiesPrefix = ' ' 		end 		local cityModule = require(cityModuleName) 		cities = citiesPrefix .. cityModule.city(args) 	end  	return graphics .. linkText .. cities end  function p.jctrdt(frame) 	-- Import module function to work with passed arguments 	local getArgs = require('Module:Arguments').getArgs 	local args = getArgs(frame, {removeBlanks = false}) 	return p._jctrdt(args, frame) end  return p