Module:Mapframe
Documentation for this module may be created at Module:Mapframe/doc
local defaults = {
display = 'inline',
text = 'Map',
["frame-width"] = '300',
["frame-height"] = '200'
}
function setCleanArgs(argsTable)
local cleanArgs = {}
for key, val in pairs(argsTable) do
if type(val) == 'string' then
val = val:match('^%s*(.-)%s*$')
if val ~= '' then
cleanArgs[key] = val
end
else
cleanArgs[key] = val
end
end
return cleanArgs
end
function isAffirmed(val)
if not(val) then return false end
local affirmedWords = ' add added affirm affirmed include included on true yes y '
return string.find(affirmedWords, ' '..val..' ', 1, true ) and true or false
end
function isDeclined(val)
if not(val) then return false end
local declinedWords = ' decline declined exclude excluded false none not no n off omit omitted remove removed '
return string.find(declinedWords , ' '..val..' ', 1, true ) and true or false
end
function makeContent(args)
if args.raw then
return args.raw
end
local content = {};
local contentIndex = '';
while args['type'..contentIndex] or args['from'..contentIndex] do
local contentArgs = {}
for k, v in pairs(args) do
if string.match(k, '.*'..contentIndex) then
contentArgs[string.gsub(k, contentIndex, '')] = v
end
end
if contentIndex == '' then contentIndex = 1 end
content[contentIndex] = makeContentJson(contentArgs)
contentIndex = contentIndex + 1
end
--Single item, no array needed
if #content==1 then return content[1] end
--Multiple items get placed in a FeatureCollection
local contentArray = '[\n' .. table.concat( content, ',\n') .. '\n]'
return contentArray
end
function parseCoords(coords)
local parts = mw.text.split((mw.ustring.match(coords,'[%.%d]+°[NS] [%.%d]+°[EW]') or ''), ' ')
latParts = mw.text.split(parts[1], '°')
longParts = mw.text.split(parts[2], '°')
if latParts[2] == 'S' then latParts[1] = '-'..latParts[1] end
if longParts[2] == 'W' then longParts[1] = '-'..longParts[1] end
return tonumber(latParts[1]), tonumber(longParts[1])
end
function makeCoords(args, plainOutput)
local coords
local frame = mw.getCurrentFrame()
if args.coord then
coords = frame:preprocess(args.coord)
else
coords = frame:preprocess('{{WikidataCoord|display=|'..(args.id or args.ids or mw.wikibase.getEntityIdForCurrentPage())..'}}')
end
local lat, long = parseCoords(coords)
if plainOutput then
return lat, long
end
return {[0] = long, [1] = lat}
end
function makeContentJson(args)
local data = {}
if args.type == 'point' then
data.type = "Feature"
data.geometry = {
type = "Point",
coordinates = makeCoords(args)
}
data.properties = {
title = args.title or mw.getCurrentFrame():getParent():getTitle(),
["marker-symbol"] = args.marker or "marker",
["marker-color"] = "5E74F3"
}
else
data.type = "ExternalData"
if args.type == "data" or args.from then
data.service = "page"
elseif args.type == "line" then
data.service = "geoline"
elseif args.type == "shape" then
data.service = "geoshape"
elseif args.type == "shape-inverse" then
data.service = "geomask"
end
if args.id or args.ids or (not (args.from) and mw.wikibase.getEntityIdForCurrentPage()) then
data.ids = args.id or args.ids or mw.wikibase.getEntityIdForCurrentPage()
else
data.title = args.from
end
data.properties = {
stroke = args["stroke-color"] or args["stroke-colour"] or "#ff0000",
["stroke-width"] = tonumber(args["stroke-width"]) or 6
}
end
data.properties.title = args.title or mw.getCurrentFrame():getParent():getTitle()
if args.description then
data.properties.description = args.description
end
return mw.text.jsonEncode(data)
end
function makeTagAttribs(args, isTitle)
local attribs = {}
if args.zoom then
attribs.zoom = args.zoom
end
if isDeclined(args.icon) then
attribs.class = "no-icon"
end
if args.type == 'point' then
local lat, long = makeCoords(args, 'plainOutput')
attribs.latitude = tostring(lat)
attribs.longitude = tostring(long)
end
if isAffirmed(args.frame) and not(isTitle) then
attribs.width = args["frame-width"] or defaults["frame-width"]
attribs.height = args["frame-height"] or defaults["frame-height"]
if args["frame-lat"] or args["frame-latitude"] then
attribs.latitude = args["frame-lat"] or args["frame-latitude"]
end
if args["frame-long"] or args["frame-longitude"] then
attribs.longitude = args["frame-long"] or args["frame-longitude"]
end
if isAffirmed(args.plain) then
attribs.frameless = "1"
else
attribs.text = args.text or defaults.text
end
else
attribs.text = args.text or defaults.text
end
return attribs
end
function makeTitleOutput(args, tagContent)
local titleTag = mw.text.tag('maplink', makeTagAttribs(args, true), tagContent)
local spanAttribs = {
style = "font-size: small;",
id = "coordinates"
}
return mw.text.tag('span', spanAttribs, titleTag)
end
function makeInlineOutput(args, tagContent)
local tagName = 'maplink'
if args.frame then
tagName = 'mapframe'
end
return mw.text.tag(tagName, makeTagAttribs(args), tagContent)
end
local p = {}
function p.main(frame)
local parent = frame.getParent(frame)
local args = setCleanArgs(parent.args)
local tagContent = makeContent(args)
local display = mw.text.split(args.display or defaults.display, '%s*,%s*')
local displayInTitle = display[1] == 'title' or display[2] == 'title'
local displayInline = display[1] == 'inline' or display[2] == 'inline'
local output
if displayInTitle and displayInline then
output = makeTitleOutput(args, tagContent) .. makeInlineOutput(args, tagContent)
elseif displayInTitle then
output = makeTitleOutput(args, tagContent)
elseif displayInline then
output = makeInlineOutput(args, tagContent)
else
error( 'Invalid display parameter')
end
return frame:preprocess(output)
end
return p