释义 |
local p = {} -- Change to "" upon deploymentlocal moduleSuffix = "/sandbox" local parserModuleName = "Module:Road data/parser" .. moduleSuffix local browseModuleName = "Module:Road data/browse" .. moduleSuffix local colorModuleName = "Module:Infobox road/color" .. moduleSuffix local locationsModuleName = "Module:Infobox road/locations" .. moduleSuffix local mapModuleName = "Module:Infobox road/map" .. moduleSuffix local concat = table.concat local insert = table.insert local format = mw.ustring.format local roadDataModule = require("Module:Road data") local util = require("Module:Road data/util") local parserModule = require(parserModuleName) local shieldScale = 3.5 -- Error typeslocal errorTypes = { marker = {prefix = "S"}, photo = {prefix = "%"}, locations = {prefix = "%"}, law = {prefix = "L"}, tourist = {prefix = "%"}, type = {prefix = "#"}, spur = {prefix = "$"} } -- Error messages to be added to the outputlocal errors = {} -- Warning typeslocal warningTypes = { browse = {prefix = "B"}, marker = {prefix = "S"}, name = {prefix = "N"}, translation = {prefix = "T"}, spur = {prefix = "A"}, law = {prefix = "L"}, maint = {prefix = "M"}, browselinks = {prefix = "1"}, subtype = {prefix = "2"}, } -- Warning categories to be trackedlocal warningCats = {law = true, maint = true} -- Warningslocal warnings = {} local function headerStyle(origArgs) local deleted = origArgs.decommissioned or origArgs.deleted if deleted then return "background:#AAA;" end local styles = mw.loadData(colorModuleName) local headerType = origArgs.header_type local headerTypeStyle = styles[headerType] if headerTypeStyle then return headerTypeStyle end local country = origArgs.country local countryStyle = styles[country] if countryStyle then return countryStyle[origArgs.type] or countryStyle.default end -- Try loading country-specific module. local success, countryModule = pcall(require, format("Module:Infobox road/color/%s", country)) if success then return countryModule.colors:color(origArgs) end return 'background:#cedff2;' end local function transformLengthUnits(lengths) if lengths.comp == "mi" then local mi = tonumber(lengths.mi) if mi and mi < 0.25 then lengths.comp = "ft" end elseif lengths.comp == "km" then local km = tonumber(lengths.km) if km and km < 1 then lengths.comp = "m" end end return lengths end local function length(args, num) num = num or "" local mi = args["length_mi" .. num] local km = args["length_km" .. num] if not (mi or km) then return nil end local lengths = transformLengthUnits(util.convertLengths({ mi = mi, km = km, prec = args["length_round" .. num] }, "N/A")) local ref = args["length_ref" .. num] local notes = args["length_notes" .. num] local text = {} if lengths[lengths.orig] then insert(text, format("%s %s", lengths[lengths.orig], lengths.orig)) if ref then insert(text, ref) end insert(text, format(" (%s %s)", lengths[lengths.comp], lengths.comp)) end if lengths.error then insert(text, lengths.error) end if notes then insert(text, format(" %s", notes)) end if #text == 0 then return nil end return concat(text) end local function allocationLabel(country) if country == "AUS" then return "Allocation:" end return "Component highways:" end local function dirLabel(dir, default) if dir then return dir .. " end:" end return default end local function browseLinks(browseSpec, depth) if not browseSpec then return nil end depth = depth or 0 local result = {} for _,entry in ipairs(browseSpec) do local entryLinks if #entry > 0 then entryLinks = browseLinks(entry, depth + 1) else if entry.link then entryLinks = format("%s", entry.link, entry.name or entry.link) else entryLinks = entry.name end if entryLinks then if entry.bold then entryLinks = format("%s", entryLinks) end entryLinks = format("%s%s", string.rep("*", depth), entryLinks) end end if entryLinks then if entry.noprint then entryLinks = format(' \%s\ ', entryLinks) end insert(result, entryLinks) end end return concat(result, depth > 0 and "\" or "") end local displayedRegions = {} local function browseLinksRegion(browseInfo, args, num) local suffix = num or "" local route = {country = args.country} local regionKey = {} for _,key in ipairs({"state", "province", "county"}) do local value = args["browse_" .. key .. suffix] or not num and args[key] route[key] = value insert(regionKey, value or "#") end if num and not (route.state or route.province) then return nil end -- Avoid displaying links for the same region twice. regionKey = concat(regionKey) if displayedRegions[regionKey] then return "" end displayedRegions[regionKey] = true return browseLinks(parserModule.parser(route, "browse", " common ")) end local function navRow(args, num) num = num or "" local previous_route = args["previous_route" .. num] local next_route = args["next_route" .. num] if not (previous_route and next_route) then return nil end local boxModule = require(browseModuleName) local route = { country = args.country, state = args["browse_state" .. num] or args.state, province = args["browse_province" .. num] or args.province, county = args["browse_county" .. num] or args.county, previous_type = args["previous_type" .. num], previous_route = previous_route, previous_dab = args["previous_dab" .. num], browse_route = args["browse_route" .. num], next_type = args["next_type" .. num], next_route = next_route, next_dab = args["next_dab" .. num] } local row = boxModule._browse(route) if route.typeerror then args.typeerror = true end return row end local function browse(args) local navRows = {} local primaryNavRow = navRow(args) if primaryNavRow then insert(navRows, primaryNavRow) end local num = 0 repeat num = num + 1 local row = navRow(args, num) if row then insert(navRows, row) end until row == nil navRows = concat(navRows) if navRows == "" then navRows = nil end local extended = args.browse if navRows or extended then local box = mw.html.create('table'):cssText("width:100%; background:none; border-collapse:collapse") if navRows then box:wikitext(navRows) end if extended then -- FIXME Wikipedia -- Apparently, Wikipedia parser doesn't like newlines between table rows. warnings.browse = "browse parameter is deprecated" extended = mw.ustring.gsub(extended, " |
%c+") box:wikitext(extended)
end
return tostring(box)
else
return nil
end
end
local function addRowIfExists(rows, class, label, data, ...)
if data then
if type(label) == "function" then
label = label(...)
end
insert(rows, {class = class, label = label, data = data})
end
end
local function addSection(dst, src, header, row)
row = row + 1
dst["header" .. row] = header
for _,entry in ipairs(src) do
row = row + 1
if entry.label then
dst["label" .. row] = entry.label
end
if entry.class then
dst["class" .. row] = entry.class
end
dst["data" .. row] = entry.data
end
return row
end
function p.infobox(frame)
-- Import module function to work with passed arguments
local getArgs = require('Module:Arguments').getArgs
local origArgs = getArgs(frame)
local state = origArgs.state or origArgs.province
if not origArgs.country then
local countryMask = mw.loadData("Module:Road data/countrymask")
origArgs.country = countryMask[state] or "UNK"
end
local country = origArgs.country
local args = {
bodystyle = "width:300px; font-size:90%; padding:0",
headerstyle = headerStyle(origArgs),
labelstyle = "text-align:right",
belowstyle = "line-height:150%"
}
-- ROUTE MARKER AND ROUTE NAME
local markerImage = origArgs.marker_image
if markerImage == "none" then markerImage = nil
elseif not markerImage then
local missingShields
-- begin transition code
local origType = origArgs.type
if origArgs.subtype then
origArgs.type = format("%s-%s", origArgs.type, origArgs.subtype)
end
markerImage, missingShields = roadDataModule.shield(origArgs, shieldScale, true, true)
origArgs.type = origType
-- end transition code
-- TODO transition
-- markerImage, missingShields = roadDataModule.shield(origArgs, shieldScale, true, true)
if #missingShields > 0 then
errors.marker = format("Missing marker graphics: %s", concat(missingShields, ", "))
end
if markerImage == "" then markerImage = nil end
if not markerImage and country ~= "UNK" then
-- Fall back to template.
warnings.marker = "Using marker from template"
markerImage = frame:expandTemplate{
title = "Infobox road/shieldmain/" .. country,
args = {
state = origArgs.state,
province = origArgs.province,
type = origArgs.type,
route = origArgs.route,
county = origArgs.county,
subtype = frame:expandTemplate{
title = "Infobox road/meta/mask/subtype1",
args = {origArgs.subtype}
}
}
}
if markerImage == "none" or markerImage == "" then markerImage = nil end
end
end
local name = origArgs.name
if name == "none" then name = nil
elseif not name then
-- begin transition code
local origType = origArgs.type
if origArgs.subtype then
origArgs.type = format("%s-%s", origArgs.type, origArgs.subtype)
end
name = parserModule.parser(origArgs, "name")
origArgs.type = origType
-- end transition code
-- TODO transition
-- name = parserModule.parser(origArgs, "name")
if not name and country ~= "UNK" then
-- Fall back to template.
warnings.name = "Using name from template"
name = frame:expandTemplate{
title = "Infobox road/name/" .. country,
args = {
state = origArgs.state,
province = origArgs.province,
type = origArgs.type,
route = origArgs.route,
county = origArgs.county,
subtype = frame:expandTemplate{
title = "Infobox road/meta/mask/subtype1",
args = {origArgs.subtype}
}
}
}
if name == "none" or name == "" then name = nil end
end
end
if country == "AUS" then
local above = {}
if name then
insert(above, name)
end
if origArgs.alternate_name then
insert(above,
format("
%s",
origArgs.alternate_name))
end
if markerImage then
insert(above, format("
%s
", markerImage)) end
args.above = concat(above)
else
local above = {}
if markerImage then
insert(above, format("
%s
", markerImage)) end
if name then
insert(above, name)
end
args.above = concat(above)
args.subheader2 = origArgs.alternate_name
end
local translation = origArgs.translation
if not translation then
-- begin transition code
local origType = origArgs.type
if origArgs.subtype then
origArgs.type = format("%s-%s", origArgs.type, origArgs.subtype)
end
translation = parserModule.parser(origArgs, "translation")
origArgs.type = origType
-- end transition code
-- TODO transition
-- translation = parserModule.parser(origArgs, "translation")
if not translation then
-- Fall back to template.
local success, translation_ = pcall(frame.expandTemplate, frame, {
title = "Infobox road/translation/" .. country,
args = {
state = state,
type = origArgs.type,
route = origArgs.route,
subtype = frame:expandTemplate{
title = "Infobox road/meta/mask/subtype1",
args = {origArgs.subtype}
}
}
})
if success then
warnings.translation = "Using translation from template"
translation = translation_
end
if translation == "none" or translation == "" then translation = nil end
end
end
if translation then
args.subheader = format("%s", translation)
end
-- MAP
args.image = require(mapModuleName)._map(origArgs)
if args.image and args.image ~= then
args.caption = origArgs.map_notes
end
local photo = origArgs.photo or origArgs.image
if photo then
local displayPhoto = parserModule.parser(origArgs, "photo", country,
"Module:Infobox road/display")
if displayPhoto == "yes" then
local photoWidth = origArgs.photo_width or origArgs.image_width or "290"
local photoAlt = origArgs.photo_alt or origArgs.image_alt or ""
args.image2 = format("", photo, photoWidth, photoAlt)
else
errors.photo = "photo parameter not permitted for the region"
end
args.caption2 = origArgs.photo_notes or origArgs.image_notes
end
local row = 0
-- LOCATION INFORMATION (SOME PARAMETERS ARE DISABLED FOR CERTAIN COUNTRIES)
local locations, locationsError =
require(locationsModuleName)._locations(origArgs)
if #locations > 0 then
row = addSection(args, locations, "Location", row)
end
errors.locations = locationsError
-- ROUTE INFORMATION
local routeInfo = {}
if origArgs.spur_of then
local spurInfo = origArgs.spur_aux
if not spurInfo and origArgs.spur_auxtype then
local auxSpec = parserModule.parser(origArgs, origArgs.spur_auxtype, " aux ")
if auxSpec then spurInfo = auxSpec.aux end
end
-- begin transition code
local origType = origArgs.type
if origArgs.subtype then
origArgs.type = format("%s-%s", origArgs.type, origArgs.subtype)
end
spurInfo = parserModule.parser(origArgs, "aux")
origArgs.type = origType
if not spurInfo and not origArgs.subtype then
spurInfo = "Auxiliary route"
end
-- end transition code
-- TODO transition
-- spurInfo = parserModule.parser(origArgs, "aux")
-- if not spurInfo then
-- spurInfo = "Auxiliary route"
-- end
if not spurInfo and country ~= "UNK" then
-- Fall back to template.
warnings.spur = "Using spur from template"
spurInfo = frame:expandTemplate{
title = "Infobox road/meta/spur of/sandbox",
args = {
parent_type = origArgs.spur_type,
parent = origArgs.spur_of,
country = country,
state = state,
type = origArgs.type,
route = origArgs.route,
county = origArgs.county,
subtype = origArgs.subtype
}
}
if spurInfo == "" then spurInfo = nil end
else
local origRoute = origArgs.route
local origDab = origArgs.dab
origArgs.type = origArgs.spur_type
origArgs.route = origArgs.spur_of
origArgs.dab = origArgs.spur_dab
local parentLink = roadDataModule.link(origArgs)
origArgs.type = origType
origArgs.route = origRoute
origArgs.dab = origDab
spurInfo = parentLink and format("%s of %s", spurInfo, parentLink) or nil
end
addRowIfExists(routeInfo, nil, nil, spurInfo)
end
local network = origArgs["e-road"] or origArgs.ahn or origArgs.tahn or origArgs.mrn
if network then
local shield = origArgs["e-road-shield"] or origArgs["ahn-shield"] or origArgs["tahn-shield"] or origArgs["mrn-shield"] or ""
insert(routeInfo, {data = format("%s Part of %s", shield, network)})
end
if origArgs.section then
local lawInfo = parserModule.parser(origArgs, "law")
if not lawInfo then
-- Fall back to template.
local success, lawInfo_ = pcall(frame.expandTemplate, frame, {
title = "Infobox road/law/" .. country,
args = {
state = state,
type = origArgs.type,
route = origArgs.route,
section = origArgs.section,
subsection = origArgs.subsection
}
})
if success then
warnings.law = "Using law from template"
lawInfo = lawInfo_
end
if lawInfo == "" then lawInfo = nil end
else
lawInfo = "Defined by " .. lawInfo
end
if lawInfo then
insert(routeInfo, {data = lawInfo})
else
errors.law = "section parameter defined without law specifications"
end
end
local maint = origArgs.maint
if not maint then
maint = parserModule.parser(origArgs, "maint")
if not maint then
-- Fall back to template.
local success, maint_ = pcall(frame.expandTemplate, frame, {
title = "Infobox road/maint/" .. country,
args = {
state = state or "¬",
type = origArgs.type
}
})
if success and maint_ ~= "" then
warnings.maint = "Using maint from template"
maint = maint_
end
else
maint = "Maintained by " .. maint
end
elseif maint ~= "none" then
maint = "Maintained by " .. maint
end
addRowIfExists(routeInfo, nil, nil, maint)
addRowIfExists(routeInfo, nil, "Length:", length(origArgs))
if origArgs.header_type then
local lcHeaderType = mw.ustring.lower(origArgs.header_type)
if lcHeaderType == "under construction"
or lcHeaderType == "uc"
or lcHeaderType == "const"
or lcHeaderType == "historic"
or lcHeaderType == "historical"
or lcHeaderType == "hist"
or lcHeaderType == "former"
or lcHeaderType == "decommissioned" then
addRowIfExists(routeInfo, nil, "Status:", origArgs.status)
end
end
local established = origArgs.established or origArgs.formed
local decommissioned = origArgs.decommissioned or origArgs.deleted or "present"
addRowIfExists(routeInfo, nil, "Existed:",
established and format("%s – %s", established, decommissioned))
addRowIfExists(routeInfo, nil, "History:", origArgs.history)
if origArgs.time_period then
addRowIfExists(routeInfo, nil, "Established by:", origArgs.established_by)
insert(routeInfo, {label = "Time period:", data = origArgs.time_period})
addRowIfExists(routeInfo, nil, "Cultural
significance:", origArgs.significance)
addRowIfExists(routeInfo, nil, "Related
routes:", origArgs.related)
end
addRowIfExists(routeInfo, nil, allocationLabel, origArgs.allocation, country)
if origArgs.tourist then
local displayTourist = parserModule.parser(origArgs, "tourist", country,
"Module:Infobox road/display")
if displayTourist == "yes" then
insert(routeInfo, {label = "Tourist
routes:", data = origArgs.tourist})
else
errors.tourist = "tourist parameter not permitted for the region"
end
end
addRowIfExists(routeInfo, nil, "Restrictions:", origArgs.restrictions)
if #routeInfo > 0 then
row = addSection(args, routeInfo, "Route information", row)
end
-- MAJOR JUNCTIONS (FOR MOST ROUTES)
local majorJcts = {}
local loop = {
ring_road = "Ring road",
beltway_city = "Beltway",
orbital = "Orbital",
loop = "Loop",
tloop = "Tourist loop"
}
for key,entry in pairs(loop) do
local center = origArgs[key]
if center then
if center == "none" then center = nil end
insert(majorJcts, {data = entry .. (center and " around " .. center or "")})
end
end
local from = origArgs.terminus_a or origArgs.end_a
addRowIfExists(majorJcts, nil, dirLabel, from, origArgs.direction_a, "From:")
addRowIfExists(majorJcts, nil, "",
origArgs.junction and mw.ustring.gsub(origArgs.junction, "
%s*%c", "
"))
local to = origArgs.terminus_b or origArgs.end_b
addRowIfExists(majorJcts, nil, dirLabel, to, origArgs.direction_b, "To:")
if #majorJcts > 0 then
row = addSection(args, majorJcts, origArgs.section0 or "Major junctions", row)
end
-- MAJOR JUNCTIONS (IF DIVIDED UP)
local segment = 0
repeat
segment = segment + 1
local segmentInfo = {}
addRowIfExists(segmentInfo, nil, "Length:", length(origArgs, segment))
local segmentJcts = {}
local segmentFrom = origArgs["terminus_a" .. segment] or origArgs["end_a" .. segment]
local fromDir = origArgs["direction_a" .. segment] or origArgs.direction_a
addRowIfExists(segmentJcts, nil, dirLabel, segmentFrom, fromDir, "From:")
addRowIfExists(segmentJcts, nil, "",
origArgs["junction" .. segment]
and mw.ustring.gsub(origArgs["junction" .. segment], "
%s*%c", "
"))
local segmentTo = origArgs["terminus_b" .. segment] or origArgs["end_b" .. segment]
local toDir = origArgs["direction_b" .. segment] or origArgs.direction_b
addRowIfExists(segmentJcts, nil, dirLabel, segmentTo, toDir, "To:")
if #segmentJcts > 0 then
insert(segmentInfo, {data = "Major junctions"})
for _,entry in ipairs(segmentJcts) do
insert(segmentInfo, entry)
end
end
if #segmentInfo > 0 then
row = addSection(args, segmentInfo, origArgs["section" .. segment] or "Section " .. segment, row)
end
until #segmentInfo == 0
-- HIGHWAY SYSTEM
-- LINKS AND BROWSE SECTION
if not origArgs.nobrowse then
local browseInfo = {}
addRowIfExists(browseInfo, "hlist", nil, origArgs.system)
local browseInfoCount = #browseInfo
addRowIfExists(browseInfo, "hlist", nil,
browseLinks(parserModule.parser(origArgs, "browse")))
if not parserModule.parser(origArgs, "nocommonbrowse") then
addRowIfExists(browseInfo, "hlist", nil,
browseLinksRegion(browseInfo, origArgs))
local num = 0
repeat
num = num + 1
local regionLinks = browseLinksRegion(browseInfo, origArgs, num)
addRowIfExists(browseInfo, "hlist", nil, regionLinks)
until regionLinks == nil
end
if #browseInfo == browseInfoCount and country ~= "UNK" then
-- Fall back to template.
warnings.browselinks = "Using browselinks from template"
local browseLinks = frame:expandTemplate{
title = "Infobox road/browselinks/" .. country,
args = {
state = origArgs.state,
province = origArgs.province,
type = origArgs.type,
route = origArgs.route,
county = origArgs.county
}
}
if browseLinks == "none" or browseLinks == "" then browseLinks = nil end
addRowIfExists(browseInfo, "hlist", nil, browseLinks)
end
addRowIfExists(browseInfo, "hlist", nil, browse(origArgs))
if #browseInfo > 0 then
local system
if country == "GBR" or country == "IRL" then
system = "Road network"
else
system = "Highway system"
end
row = addSection(args, browseInfo, system, row)
end
end
-- HISTORICAL DESIGNATION, NRHP, EMBEDDED INFOBOXES
local embedded = origArgs.nrhp or origArgs.embedded
if embedded then
row = row + 1
args["data" .. row] = embedded
end
-- Nested infobox
if origArgs.extra then
row = row + 1
args["data" .. row] = origArgs.extra
end
-- ERROR TRACKING CATEGORIES
if origArgs.type and country == "UNK" then
errors.type = "type parameter defined with unknown country"
end
if origArgs.spur_of and not origArgs.spur_type then
errors.spur = "spur_of parameter defined without spur_type"
end
if origArgs.subtype then
warnings.subtype = "subtype parameter is deprecated"
end
-- Prepare error messages.
local errorCode
local errorMsg = {}
for key,msg in pairs(errors) do
insert(errorMsg, util.err(msg))
errorCode = errorCode or errorTypes[key].prefix
end
if #errorMsg > 0 then
row = row + 1
args["data" .. row] = concat(errorMsg)
end
local trackers = {}
for key,msg in pairs(warnings) do
-- add hidden message
insert(trackers, format('Module:Infobox road warning: %s', msg))
if warningCats[key] then
errorCode = errorCode or warningTypes[key].prefix
end
end
if errorCode then
-- Add the transcluding page to an error tracking category.
insert(trackers,
format("",
errorCode))
end
if origArgs.header_color then
insert(trackers, "")
end
if origArgs.header_type then
insert(trackers, "")
end
if origArgs.map_custom then
insert(trackers, "")
end
if origArgs.marker_image then
if origArgs.marker_image == "none" then
insert(trackers, "")
else
insert(trackers, "")
end
end
if origArgs.name then
insert(trackers, "")
end
if origArgs.map and origArgs.map ~= frame:callParserFunction("#property:P15") then
insert(trackers, "")
end
if mw.title.getCurrentTitle().namespace == 0 then
if frame:callParserFunction("#property:P17") == "" then
insert(trackers, "")
end
if frame:callParserFunction("#property:P31") == "" then
insert(trackers, "")
end
end
local tracker
if #trackers > 0 then
local page = mw.title.getCurrentTitle().prefixedText -- Get transcluding page's title
tracker = mw.ustring.gsub(concat(trackers), "%%page%%", page)
else
tracker = ""
end
return require("Module:Infobox").infobox(args) .. tracker
end
return p
10 : Infobox road transclusion errors|Infobox road temporary tracking category 1|Infobox road temporary tracking category 1|Infobox road temporary tracking category 1|Infobox road temporary tracking category 1|Infobox road temporary tracking category 1|Infobox road temporary tracking category 1|Infobox road maps for Wikidata migration|Infobox road articles without wikidata country|Infobox road articles without wikidata instance of