Permanently protected module
From Wikipedia, the free encyclopedia

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 bannerSizei 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 shieldsizei

			if size == "" then size = nil end

			-- banner.all describes banners that apply to all multiple shields.

			local shieldBanner = bannerIsNotTable and banner or (banneri or banner.all or {})

			-- Banner size is default if the corresponding entry

			-- in bannerSize table is not set.

			local shieldBannerSize =

				bannersizeIsNotTable and bannersize

				or (bannersizei or bannersize.all or defaultShieldSize)

			local shieldBannerSuffix = bannersuffix and (bannersuffixIsNotTable and bannersuffix or bannersuffixi])

			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 = shieldExistsCacheshield

	if result == nil then

		local file = mw.title.new(shield, 'Media').file

		-- Cache result.

		local exists = file.exists

		result = {exists}

		if exists then result2 = file.width >= file.height end

		shieldExistsCacheshield = result

	end

	if result1 then return true, result2 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(shield1])

	if not exists then return '' end



	local size

	if shield2 then

		local width, height = mw.ustring.match(shield2], "(%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("[[File:%s|x%spx%s|%s]]", shield1], size, link, shield1])

	if not banners1 then return shieldCode end



	for _,banner in ipairs(banners) do

		shieldCode = format("[[File:%s|%spx|link=|alt=]]<br>%s",

			banner1],

			defaultShieldSize,

			shieldCode)

	end

	return '<span style="display: inline-block; vertical-align: baseline; line-height: 0; text-align: center;">' .. shieldCode .. '</span>'

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|%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 = dataargs.country

	return countryData and countryDataabbr

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 = countryModulestate 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 = argsrouteCount * 2 - 1

		if not routeType then break end

		local route = {type = routeType, route = argsrouteCount * 2]}

		for _,v in pairs(params) do

			routev = argsv .. 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 'To ' or ' to '

	end

	return num == 1 and '' or '&nbsp;/ '

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 = '&nbsp;'

		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