Module:Infobox mapframe: Difference between revisions
m (1 revision imported) |
mNo edit summary |
||
| Line 11: | Line 11: | ||
local DEFAULT_GEOMASK_STROKE_COLOR = "#777777" | local DEFAULT_GEOMASK_STROKE_COLOR = "#777777" | ||
local DEFAULT_GEOMASK_FILL = "#888888" | local DEFAULT_GEOMASK_FILL = "#888888" | ||
local DEFAULT_GEOMASK_FILL_OPACITY = "0. | local DEFAULT_GEOMASK_FILL_OPACITY = "0.5" | ||
local DEFAULT_SHAPE_STROKE_WIDTH = " | local DEFAULT_SHAPE_STROKE_WIDTH = "3" | ||
local DEFAULT_SHAPE_STROKE_COLOR = "#FF0000" | local DEFAULT_SHAPE_STROKE_COLOR = "#FF0000" | ||
local DEFAULT_SHAPE_FILL = "#606060" | local DEFAULT_SHAPE_FILL = "#606060" | ||
local DEFAULT_SHAPE_FILL_OPACITY = "0. | local DEFAULT_SHAPE_FILL_OPACITY = "0.5" | ||
local DEFAULT_LINE_STROKE_WIDTH = "5" | local DEFAULT_LINE_STROKE_WIDTH = "5" | ||
local DEFAULT_LINE_STROKE_COLOR = "#FF0000" | local DEFAULT_LINE_STROKE_COLOR = "#FF0000" | ||
local DEFAULT_MARKER_COLOR = "#5E74F3" | local DEFAULT_MARKER_COLOR = "#5E74F3" | ||
-- Trim whitespace from args, and remove empty args | -- Trim whitespace from args, and remove empty args | ||
function | function trimArgs(argsTable) | ||
local cleanArgs = {} | local cleanArgs = {} | ||
for key, val in pairs(argsTable) do | for key, val in pairs(argsTable) do | ||
| Line 48: | Line 37: | ||
end | end | ||
function | function getBestStatement(item_id, property_id) | ||
if not(item_id) or not(mw.wikibase.isValidEntityId(item_id)) or not(mw.wikibase.entityExists(item_id)) then | if not(item_id) or not(mw.wikibase.isValidEntityId(item_id)) or not(mw.wikibase.entityExists(item_id)) then | ||
return false | return false | ||
| Line 63: | Line 52: | ||
end | end | ||
function | function hasWikidataProperty(item_id, property_id) | ||
return | return getBestStatement(item_id, property_id) and true or false | ||
end | end | ||
function | function getStatementValue(statement) | ||
return statement and statement.mainsnak and statement.mainsnak.datavalue and statement.mainsnak.datavalue.value or nil | return statement and statement.mainsnak and statement.mainsnak.datavalue and statement.mainsnak.datavalue.value or nil | ||
end | end | ||
function | function relatedEntity(item_id, property_id) | ||
local value = | local value = getStatementValue( getBestStatement(item_id, property_id) ) | ||
return value and value.id or false | return value and value.id or false | ||
end | end | ||
function | function idType(id) | ||
if not id then | if not id then | ||
return nil | return nil | ||
| Line 88: | Line 77: | ||
end | end | ||
function | function getZoom(value, unit) | ||
local length_km | |||
if unit == 'km' then | |||
length_km = tonumber(value) | |||
elseif unit == 'mi' then | |||
length_km = tonumber(value)*1.609344 | |||
elseif unit == 'km2' then | |||
length_km = math.sqrt(tonumber(value)) | |||
elseif unit == 'mi2' then | |||
length_km = math.sqrt(tonumber(value))*1.609344 | |||
end | |||
-- max for zoom 2 is 6400km, for zoom 3 is 3200km, for zoom 4 is 1600km, etc | |||
local zoom = math.floor(8 - (math.log10(length_km) - 2)/(math.log10(2))) | |||
-- limit to values below 17 | |||
zoom = math.min(17, zoom) | |||
-- take off 1 when calculated from area, to account for unusual shapes | |||
if unit == 'km2' or unit == 'mi2' then | |||
zoom = zoom - 1 | |||
end | |||
-- minimum value is 1 | |||
return math.max(1, zoom) | |||
end | |||
function shouldAutoRun(frame) | |||
-- Check if should be running | -- Check if should be running | ||
local explicitlyOn = yesno(mw.text.trim(frame.getParent(frame).args.mapframe or "")) -- true of false or nil | |||
local explicitlyOn = yesno(mw.text.trim( | |||
local onByDefault = (explicitlyOn == nil) and yesno(mw.text.trim(frame.args.onByDefault or ""), false) -- true or false | local onByDefault = (explicitlyOn == nil) and yesno(mw.text.trim(frame.args.onByDefault or ""), false) -- true or false | ||
return explicitlyOn or onByDefault | return explicitlyOn or onByDefault | ||
end | end | ||
function | function argsFromAuto(frame) | ||
-- Get args from the frame (invoke call) and the parent (template call). | -- Get args from the frame (invoke call) and the parent (template call). | ||
-- Frame arguments are default values which are overridden by parent values | -- Frame arguments are default values which are overridden by parent values | ||
-- when both are present | -- when both are present | ||
local args = getArgs(frame, {parentFirst = true}) | local args = getArgs(frame, {parentFirst = true}) | ||
-- Discard args not prefixed with "mapframe-", remove that prefix from those that remain | -- Discard args not prefixed with "mapframe-", remove that prefix from those that remain | ||
local fixedArgs = {} | local fixedArgs = {} | ||
| Line 115: | Line 125: | ||
elseif name == "id" or name == "qid" and not fixedArgs.id then | elseif name == "id" or name == "qid" and not fixedArgs.id then | ||
fixedArgs.id = val | fixedArgs.id = val | ||
end | end | ||
end | end | ||
return fixedArgs | return fixedArgs | ||
end | end | ||
local p = {} | local p = {} | ||
p.autocaption = function(frame) | |||
p. | if not shouldAutoRun(frame) then return "" end | ||
local args = argsFromAuto(frame) | |||
if args.caption then | if args.caption then | ||
return args.caption | return args.caption | ||
elseif args.switcher then | elseif args.switcher then | ||
return | return "" | ||
end | end | ||
local maskItem | local maskItem | ||
local maskType = | local maskType = idType(args.geomask) | ||
if maskType == 'item' then | if maskType == 'item' then | ||
maskItem = args.geomask | maskItem = args.geomask | ||
elseif maskType == "property" then | elseif maskType == "property" then | ||
maskItem = | maskItem = relatedEntity(args.id or mw.wikibase.getEntityIdForCurrentPage(), args.geomask) | ||
end | end | ||
local maskItemLabel = maskItem and mw.wikibase.getLabel( maskItem ) | local maskItemLabel = maskItem and mw.wikibase.getLabel( maskItem ) | ||
return maskItemLabel and "Location in "..maskItemLabel | return maskItemLabel and "Location in "..maskItemLabel or "" | ||
end | end | ||
function parseCustomWikitext(customWikitext) | |||
-- infoboxImage will format an image if given wikitext containing an | |||
-- image, or else pass through the wikitext unmodified | |||
return infoboxImage({ | |||
args = { | |||
image = customWikitext | |||
} | |||
}) | |||
end | |||
p.auto = function(frame) | |||
if not shouldAutoRun(frame) then return "" end | |||
local args = argsFromAuto(frame) | |||
if args.custom then | |||
return frame:preprocess(parseCustomWikitext(args.custom)) | |||
p. | |||
local | |||
if | |||
return | |||
end | end | ||
local mapframe = p._main(args) | |||
return frame:preprocess(mapframe) | |||
end | end | ||
p.main = function(frame) | p.main = function(frame) | ||
local parent = frame.getParent(frame) | local parent = frame.getParent(frame) | ||
local parentArgs = parent.args | local parentArgs = parent.args | ||
local | local mapframe = p._main(parentArgs) | ||
return frame:preprocess(mapframe) | return frame:preprocess(mapframe) | ||
end | end | ||
p._main = function(_config) | |||
return "" | |||
end | end | ||
return p | return p | ||
Latest revision as of 08:17, 18 January 2026
Documentation for this module may be created at Module:Infobox mapframe/doc
local mf = require('Module:Mapframe')
local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local infoboxImage = require('Module:InfoboxImage').InfoboxImage
-- Defaults
local DEFAULT_FRAME_WIDTH = "270"
local DEFAULT_FRAME_HEIGHT = "200"
local DEFAULT_ZOOM = 10
local DEFAULT_GEOMASK_STROKE_WIDTH = "1"
local DEFAULT_GEOMASK_STROKE_COLOR = "#777777"
local DEFAULT_GEOMASK_FILL = "#888888"
local DEFAULT_GEOMASK_FILL_OPACITY = "0.5"
local DEFAULT_SHAPE_STROKE_WIDTH = "3"
local DEFAULT_SHAPE_STROKE_COLOR = "#FF0000"
local DEFAULT_SHAPE_FILL = "#606060"
local DEFAULT_SHAPE_FILL_OPACITY = "0.5"
local DEFAULT_LINE_STROKE_WIDTH = "5"
local DEFAULT_LINE_STROKE_COLOR = "#FF0000"
local DEFAULT_MARKER_COLOR = "#5E74F3"
-- Trim whitespace from args, and remove empty args
function trimArgs(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 getBestStatement(item_id, property_id)
if not(item_id) or not(mw.wikibase.isValidEntityId(item_id)) or not(mw.wikibase.entityExists(item_id)) then
return false
end
local statements = mw.wikibase.getBestStatements(item_id, property_id)
if not statements or #statements == 0 then
return false
end
local hasNoValue = ( statements[1].mainsnak and statements[1].mainsnak.snaktype == 'novalue' )
if hasNoValue then
return false
end
return statements[1]
end
function hasWikidataProperty(item_id, property_id)
return getBestStatement(item_id, property_id) and true or false
end
function getStatementValue(statement)
return statement and statement.mainsnak and statement.mainsnak.datavalue and statement.mainsnak.datavalue.value or nil
end
function relatedEntity(item_id, property_id)
local value = getStatementValue( getBestStatement(item_id, property_id) )
return value and value.id or false
end
function idType(id)
if not id then
return nil
elseif mw.ustring.match(id, "[Pp]%d+") then
return "property"
elseif mw.ustring.match(id, "[Qq]%d+") then
return "item"
else
return nil
end
end
function getZoom(value, unit)
local length_km
if unit == 'km' then
length_km = tonumber(value)
elseif unit == 'mi' then
length_km = tonumber(value)*1.609344
elseif unit == 'km2' then
length_km = math.sqrt(tonumber(value))
elseif unit == 'mi2' then
length_km = math.sqrt(tonumber(value))*1.609344
end
-- max for zoom 2 is 6400km, for zoom 3 is 3200km, for zoom 4 is 1600km, etc
local zoom = math.floor(8 - (math.log10(length_km) - 2)/(math.log10(2)))
-- limit to values below 17
zoom = math.min(17, zoom)
-- take off 1 when calculated from area, to account for unusual shapes
if unit == 'km2' or unit == 'mi2' then
zoom = zoom - 1
end
-- minimum value is 1
return math.max(1, zoom)
end
function shouldAutoRun(frame)
-- Check if should be running
local explicitlyOn = yesno(mw.text.trim(frame.getParent(frame).args.mapframe or "")) -- true of false or nil
local onByDefault = (explicitlyOn == nil) and yesno(mw.text.trim(frame.args.onByDefault or ""), false) -- true or false
return explicitlyOn or onByDefault
end
function argsFromAuto(frame)
-- Get args from the frame (invoke call) and the parent (template call).
-- Frame arguments are default values which are overridden by parent values
-- when both are present
local args = getArgs(frame, {parentFirst = true})
-- Discard args not prefixed with "mapframe-", remove that prefix from those that remain
local fixedArgs = {}
for name, val in pairs(args) do
local fixedName = string.match(name, "^mapframe%-(.+)$" )
if fixedName then
fixedArgs[fixedName] = val
-- allow coord, coordinates, etc to be unprefixed
elseif name == "coordinates" or name == "coord" or name == "coordinate" and not fixedArgs.coord then
fixedArgs.coord = val
-- allow id, qid to be unprefixed, map to id (if not already present)
elseif name == "id" or name == "qid" and not fixedArgs.id then
fixedArgs.id = val
end
end
return fixedArgs
end
local p = {}
p.autocaption = function(frame)
if not shouldAutoRun(frame) then return "" end
local args = argsFromAuto(frame)
if args.caption then
return args.caption
elseif args.switcher then
return ""
end
local maskItem
local maskType = idType(args.geomask)
if maskType == 'item' then
maskItem = args.geomask
elseif maskType == "property" then
maskItem = relatedEntity(args.id or mw.wikibase.getEntityIdForCurrentPage(), args.geomask)
end
local maskItemLabel = maskItem and mw.wikibase.getLabel( maskItem )
return maskItemLabel and "Location in "..maskItemLabel or ""
end
function parseCustomWikitext(customWikitext)
-- infoboxImage will format an image if given wikitext containing an
-- image, or else pass through the wikitext unmodified
return infoboxImage({
args = {
image = customWikitext
}
})
end
p.auto = function(frame)
if not shouldAutoRun(frame) then return "" end
local args = argsFromAuto(frame)
if args.custom then
return frame:preprocess(parseCustomWikitext(args.custom))
end
local mapframe = p._main(args)
return frame:preprocess(mapframe)
end
p.main = function(frame)
local parent = frame.getParent(frame)
local parentArgs = parent.args
local mapframe = p._main(parentArgs)
return frame:preprocess(mapframe)
end
p._main = function(_config)
return ""
end
return p