From Wikipedia, the free encyclopedia

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

				cleanArgskey = val

			end

		else

			cleanArgskey = 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 = ( statements1].mainsnak and statements1].mainsnak.snaktype == 'novalue' )

	if hasNoValue then

		return false

	end

	return statements1

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

			fixedArgsfixedName = 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)

	-- `config` is the args passed to this module

	local config = trimArgs(_config)

	

	-- Require wikidata item, or specified coords

	local wikidataId = config.id or mw.wikibase.getEntityIdForCurrentPage()

	if not(wikidataId) and not(config.coord) then

		return ''

	end



	-- Require coords (specified or from wikidata), so that map will be centred somewhere

	-- (P625 = coordinate location)

	local hasCoordinates = hasWikidataProperty(wikidataId, 'P625') or config.coordinates or config.coord

	if not hasCoordinates then  

		return ''

	end



	-- `args` is the arguments which will be passed to the mapframe module

	local args = {}



	-- Some defaults/overrides for infobox presentation

	args.display = "inline"

	args.frame = "yes"

	args.plain = "yes"

	args"frame-width"  = config"frame-width" or config.width or DEFAULT_FRAME_WIDTH

	args"frame-height" = config"frame-height" or config.height or DEFAULT_FRAME_HEIGHT

	args"frame-align"  = "center"



	args"frame-coord" = config"frame-coordinates" or config"frame-coord" or ""

	-- Note: config["coordinates"] or config["coord"] should not be used for the alignment of the frame;

	-- see talk page ( /info/en/?search=Special:Diff/876492931 )



	-- deprecated lat and long parameters

	args"frame-lat"    = config"frame-lat" or config"frame-latitude" or ""

	args"frame-long"   = config"frame-long" or config"frame-longitude" or ""



	-- Calculate zoom from length or area (converted to km or km2)

	if config.length_km then

		args.zoom = getZoom(config.length_km, 'km')

	elseif config.length_mi then

		args.zoom = getZoom(config.length_mi, 'mi')

	elseif config.area_km2 then

		args.zoom = getZoom(config.area_km2, 'km2')

	elseif config.area_mi2 then

		args.zoom = getZoom(config.area_mi2, 'mi2')

	else

		args.zoom = config.zoom or DEFAULT_ZOOM

	end



	-- Conditionals: whether point, geomask should be shown

	local hasOsmRelationId = hasWikidataProperty(wikidataId, 'P402') -- P402 is OSM relation ID

	local shouldShowPointMarker;

	if config.point == "on" then

		shouldShowPointMarker = true 

	elseif config.point == "none" then

		shouldShowPointMarker = false

	else

		shouldShowPointMarker = not(hasOsmRelationId) or (config.marker and config.marker ~= 'none') or (config.coordinates or config.coord)

	end

	local shouldShowShape = config.shape ~= 'none'

	local shapeType = config.shape == 'inverse' and 'shape-inverse' or 'shape'

	local shouldShowLine = config.line ~= 'none'

	local maskItem

	local useWikidata = wikidataId and true or false -- Use shapes/lines based on wikidata id, if there is one

	-- But do not use wikidata when local coords are specified (and not turned off), unless explicitly set

	if useWikidata and config.coord and shouldShowPointMarker then

		useWikidata = config.wikidata and true or false

	end

	

	-- Switcher

	if config.switcher == "zooms" then

		-- switching between zoom levels

		local maxZoom = math.max(tonumber(args.zoom), 3) -- what zoom would have otherwise been (if 3 or more, otherwise 3)

		local minZoom = 1 -- completely zoomed out

		local midZoom = math.floor((maxZoom + minZoom)/2) -- midway between maxn and min

		args.switch = "zoomed in, zoomed midway, zoomed out"

		args.zoom = string.format("SWITCH:%d,%d,%d", maxZoom, midZoom, minZoom)

	elseif config.switcher == "auto" then

		-- switching between P276 and P131 areas with recursive lookup, e.g. item's city,

		-- that city's state, and that state's country

		args.zoom = nil -- let kartographer determine the zoom

		local maskLabels = {}

		local maskItems = {}

		local maskItemId = relatedEntity(wikidataId, "P276") or  relatedEntity(wikidataId, "P131") 

		local maskLabel = mw.wikibase.getLabel(maskItemId)

		while maskItemId and maskLabel and mw.text.trim(maskLabel) ~= "" do

			table.insert(maskLabels, maskLabel)

			table.insert(maskItems, maskItemId)

			maskItemId = maskItemId and relatedEntity(maskItemId, "P131")

			maskLabel = maskItemId and mw.wikibase.getLabel(maskItemId)

		end

		if #maskLabels > 1 then

			args.switch = table.concat(maskLabels, "###")

			maskItem = "SWITCH:" .. table.concat(maskItems, ",")

		elseif #maskLabels == 1 then

			maskItem = maskItemId1

		end

	elseif config.switcher == "geomasks" and config.geomask then

		-- switching between items in geomask parameter

		args.zoom = nil -- let kartographer determine the zoom

		local separator = (mw.ustring.find(config.geomask, "###", 0, true ) and "###") or

			(mw.ustring.find(config.geomask, ";", 0, true ) and ";") or ","

		local pattern = "%s*"..separator.."%s*"

		local maskItems = mw.text.split(mw.ustring.gsub(config.geomask, "SWITCH:", ""), pattern)

		local maskLabels = {}

		if #maskItems > 1 then

			for i, item in ipairs(maskItems) do

				table.insert(maskLabels, mw.wikibase.getLabel(item))

			end

			args.switch = table.concat(maskLabels, "###")

			maskItem = "SWITCH:" .. table.concat(maskItems, ",")

		end

	end

	

	-- resolve geomask item id (if not using geomask switcher)

	if not maskItem then --  

		local maskType = idType(config.geomask)

		if maskType == 'item' then

			maskItem = config.geomask

		elseif maskType == "property" then

			maskItem = relatedEntity(wikidataId, config.geomask)

		end

	end

	

	-- Keep track of arg numbering

	local argNumber = ''

	local function incrementArgNumber()

		if argNumber == '' then

			argNumber = 2

		else

			argNumber = argNumber + 1

		end

	end

	

	-- Geomask

	if maskItem then

		args"type"..argNumber = "shape-inverse"

		args"id"..argNumber = maskItem

		args"stroke-width"..argNumber = config"geomask-stroke-width" or DEFAULT_GEOMASK_STROKE_WIDTH

		args"stroke-color"..argNumber = config"geomask-stroke-color" or config"geomask-stroke-colour" or DEFAULT_GEOMASK_STROKE_COLOR

		args"fill"..argNumber = config"geomask-fill" or DEFAULT_GEOMASK_FILL

		args"fill-opacity"..argNumber = config"geomask-fill-opacity" or DEFAULT_SHAPE_FILL_OPACITY

		-- Let kartographer determine zoom and position, unless it is explicitly set in config

		if not config.zoom and not config.switcher then

			args.zoom = nil

			args"frame-coord" = nil

			args"frame-lat" = nil

			args"frame-long" = nil 	

			local maskArea = getStatementValue( getBestStatement(maskItem, 'P2046') )

		end

		incrementArgNumber()

		-- Hack to fix phab:T255932

		if not args.zoom then

			args"type"..argNumber = "line"

			args"id"..argNumber = maskItem

			args"stroke-width"..argNumber = 0

			incrementArgNumber()

		end

	end

	

	-- Shape (or shape-inverse)

	if useWikidata and shouldShowShape then

		args"type"..argNumber = shapeType

		if config.id then args"id"..argNumber = config.id end

		args"stroke-width"..argNumber = config"shape-stroke-width" or config"stroke-width" or DEFAULT_SHAPE_STROKE_WIDTH

		args"stroke-color"..argNumber = config"shape-stroke-color" or config"shape-stroke-colour" or config"stroke-color" or config"stroke-colour" or DEFAULT_SHAPE_STROKE_COLOR

		args"fill"..argNumber = config"shape-fill" or DEFAULT_SHAPE_FILL

		args"fill-opacity"..argNumber = config"shape-fill-opacity" or DEFAULT_SHAPE_FILL_OPACITY

		incrementArgNumber()

	end

	

	-- Line

	if useWikidata and shouldShowLine then

		args"type"..argNumber = "line"

		if config.id then args"id"..argNumber = config.id end

		args"stroke-width"..argNumber = config"line-stroke-width" or config"stroke-width" or DEFAULT_LINE_STROKE_WIDTH

		args"stroke-color"..argNumber = config"line-stroke-color" or config"line-stroke-colour" or config"stroke-color" or config"stroke-colour" or DEFAULT_LINE_STROKE_COLOR

		incrementArgNumber()

	end



	-- Point

	if shouldShowPointMarker then

		args"type"..argNumber = "point"

		if config.id then args"id"..argNumber = config.id end

		if config.coord then args"coord"..argNumber = config.coord end

		if config.marker then args"marker"..argNumber = config.marker end

		args"marker-color"..argNumber = config"marker-color" or config"marker-colour" or DEFAULT_MARKER_COLOR

		incrementArgNumber()

	end



	local mapframe = args.switch and mf.multi(args) or mf._main(args)

	local tracking = hasOsmRelationId and '' or '[[Category:Infobox mapframe without OSM relation ID on Wikidata]]'

	return mapframe .. tracking

end



return p
From Wikipedia, the free encyclopedia

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

				cleanArgskey = val

			end

		else

			cleanArgskey = 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 = ( statements1].mainsnak and statements1].mainsnak.snaktype == 'novalue' )

	if hasNoValue then

		return false

	end

	return statements1

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

			fixedArgsfixedName = 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)

	-- `config` is the args passed to this module

	local config = trimArgs(_config)

	

	-- Require wikidata item, or specified coords

	local wikidataId = config.id or mw.wikibase.getEntityIdForCurrentPage()

	if not(wikidataId) and not(config.coord) then

		return ''

	end



	-- Require coords (specified or from wikidata), so that map will be centred somewhere

	-- (P625 = coordinate location)

	local hasCoordinates = hasWikidataProperty(wikidataId, 'P625') or config.coordinates or config.coord

	if not hasCoordinates then  

		return ''

	end



	-- `args` is the arguments which will be passed to the mapframe module

	local args = {}



	-- Some defaults/overrides for infobox presentation

	args.display = "inline"

	args.frame = "yes"

	args.plain = "yes"

	args"frame-width"  = config"frame-width" or config.width or DEFAULT_FRAME_WIDTH

	args"frame-height" = config"frame-height" or config.height or DEFAULT_FRAME_HEIGHT

	args"frame-align"  = "center"



	args"frame-coord" = config"frame-coordinates" or config"frame-coord" or ""

	-- Note: config["coordinates"] or config["coord"] should not be used for the alignment of the frame;

	-- see talk page ( /info/en/?search=Special:Diff/876492931 )



	-- deprecated lat and long parameters

	args"frame-lat"    = config"frame-lat" or config"frame-latitude" or ""

	args"frame-long"   = config"frame-long" or config"frame-longitude" or ""



	-- Calculate zoom from length or area (converted to km or km2)

	if config.length_km then

		args.zoom = getZoom(config.length_km, 'km')

	elseif config.length_mi then

		args.zoom = getZoom(config.length_mi, 'mi')

	elseif config.area_km2 then

		args.zoom = getZoom(config.area_km2, 'km2')

	elseif config.area_mi2 then

		args.zoom = getZoom(config.area_mi2, 'mi2')

	else

		args.zoom = config.zoom or DEFAULT_ZOOM

	end



	-- Conditionals: whether point, geomask should be shown

	local hasOsmRelationId = hasWikidataProperty(wikidataId, 'P402') -- P402 is OSM relation ID

	local shouldShowPointMarker;

	if config.point == "on" then

		shouldShowPointMarker = true 

	elseif config.point == "none" then

		shouldShowPointMarker = false

	else

		shouldShowPointMarker = not(hasOsmRelationId) or (config.marker and config.marker ~= 'none') or (config.coordinates or config.coord)

	end

	local shouldShowShape = config.shape ~= 'none'

	local shapeType = config.shape == 'inverse' and 'shape-inverse' or 'shape'

	local shouldShowLine = config.line ~= 'none'

	local maskItem

	local useWikidata = wikidataId and true or false -- Use shapes/lines based on wikidata id, if there is one

	-- But do not use wikidata when local coords are specified (and not turned off), unless explicitly set

	if useWikidata and config.coord and shouldShowPointMarker then

		useWikidata = config.wikidata and true or false

	end

	

	-- Switcher

	if config.switcher == "zooms" then

		-- switching between zoom levels

		local maxZoom = math.max(tonumber(args.zoom), 3) -- what zoom would have otherwise been (if 3 or more, otherwise 3)

		local minZoom = 1 -- completely zoomed out

		local midZoom = math.floor((maxZoom + minZoom)/2) -- midway between maxn and min

		args.switch = "zoomed in, zoomed midway, zoomed out"

		args.zoom = string.format("SWITCH:%d,%d,%d", maxZoom, midZoom, minZoom)

	elseif config.switcher == "auto" then

		-- switching between P276 and P131 areas with recursive lookup, e.g. item's city,

		-- that city's state, and that state's country

		args.zoom = nil -- let kartographer determine the zoom

		local maskLabels = {}

		local maskItems = {}

		local maskItemId = relatedEntity(wikidataId, "P276") or  relatedEntity(wikidataId, "P131") 

		local maskLabel = mw.wikibase.getLabel(maskItemId)

		while maskItemId and maskLabel and mw.text.trim(maskLabel) ~= "" do

			table.insert(maskLabels, maskLabel)

			table.insert(maskItems, maskItemId)

			maskItemId = maskItemId and relatedEntity(maskItemId, "P131")

			maskLabel = maskItemId and mw.wikibase.getLabel(maskItemId)

		end

		if #maskLabels > 1 then

			args.switch = table.concat(maskLabels, "###")

			maskItem = "SWITCH:" .. table.concat(maskItems, ",")

		elseif #maskLabels == 1 then

			maskItem = maskItemId1

		end

	elseif config.switcher == "geomasks" and config.geomask then

		-- switching between items in geomask parameter

		args.zoom = nil -- let kartographer determine the zoom

		local separator = (mw.ustring.find(config.geomask, "###", 0, true ) and "###") or

			(mw.ustring.find(config.geomask, ";", 0, true ) and ";") or ","

		local pattern = "%s*"..separator.."%s*"

		local maskItems = mw.text.split(mw.ustring.gsub(config.geomask, "SWITCH:", ""), pattern)

		local maskLabels = {}

		if #maskItems > 1 then

			for i, item in ipairs(maskItems) do

				table.insert(maskLabels, mw.wikibase.getLabel(item))

			end

			args.switch = table.concat(maskLabels, "###")

			maskItem = "SWITCH:" .. table.concat(maskItems, ",")

		end

	end

	

	-- resolve geomask item id (if not using geomask switcher)

	if not maskItem then --  

		local maskType = idType(config.geomask)

		if maskType == 'item' then

			maskItem = config.geomask

		elseif maskType == "property" then

			maskItem = relatedEntity(wikidataId, config.geomask)

		end

	end

	

	-- Keep track of arg numbering

	local argNumber = ''

	local function incrementArgNumber()

		if argNumber == '' then

			argNumber = 2

		else

			argNumber = argNumber + 1

		end

	end

	

	-- Geomask

	if maskItem then

		args"type"..argNumber = "shape-inverse"

		args"id"..argNumber = maskItem

		args"stroke-width"..argNumber = config"geomask-stroke-width" or DEFAULT_GEOMASK_STROKE_WIDTH

		args"stroke-color"..argNumber = config"geomask-stroke-color" or config"geomask-stroke-colour" or DEFAULT_GEOMASK_STROKE_COLOR

		args"fill"..argNumber = config"geomask-fill" or DEFAULT_GEOMASK_FILL

		args"fill-opacity"..argNumber = config"geomask-fill-opacity" or DEFAULT_SHAPE_FILL_OPACITY

		-- Let kartographer determine zoom and position, unless it is explicitly set in config

		if not config.zoom and not config.switcher then

			args.zoom = nil

			args"frame-coord" = nil

			args"frame-lat" = nil

			args"frame-long" = nil 	

			local maskArea = getStatementValue( getBestStatement(maskItem, 'P2046') )

		end

		incrementArgNumber()

		-- Hack to fix phab:T255932

		if not args.zoom then

			args"type"..argNumber = "line"

			args"id"..argNumber = maskItem

			args"stroke-width"..argNumber = 0

			incrementArgNumber()

		end

	end

	

	-- Shape (or shape-inverse)

	if useWikidata and shouldShowShape then

		args"type"..argNumber = shapeType

		if config.id then args"id"..argNumber = config.id end

		args"stroke-width"..argNumber = config"shape-stroke-width" or config"stroke-width" or DEFAULT_SHAPE_STROKE_WIDTH

		args"stroke-color"..argNumber = config"shape-stroke-color" or config"shape-stroke-colour" or config"stroke-color" or config"stroke-colour" or DEFAULT_SHAPE_STROKE_COLOR

		args"fill"..argNumber = config"shape-fill" or DEFAULT_SHAPE_FILL

		args"fill-opacity"..argNumber = config"shape-fill-opacity" or DEFAULT_SHAPE_FILL_OPACITY

		incrementArgNumber()

	end

	

	-- Line

	if useWikidata and shouldShowLine then

		args"type"..argNumber = "line"

		if config.id then args"id"..argNumber = config.id end

		args"stroke-width"..argNumber = config"line-stroke-width" or config"stroke-width" or DEFAULT_LINE_STROKE_WIDTH

		args"stroke-color"..argNumber = config"line-stroke-color" or config"line-stroke-colour" or config"stroke-color" or config"stroke-colour" or DEFAULT_LINE_STROKE_COLOR

		incrementArgNumber()

	end



	-- Point

	if shouldShowPointMarker then

		args"type"..argNumber = "point"

		if config.id then args"id"..argNumber = config.id end

		if config.coord then args"coord"..argNumber = config.coord end

		if config.marker then args"marker"..argNumber = config.marker end

		args"marker-color"..argNumber = config"marker-color" or config"marker-colour" or DEFAULT_MARKER_COLOR

		incrementArgNumber()

	end



	local mapframe = args.switch and mf.multi(args) or mf._main(args)

	local tracking = hasOsmRelationId and '' or '[[Category:Infobox mapframe without OSM relation ID on Wikidata]]'

	return mapframe .. tracking

end



return p

Videos

Youtube | Vimeo | Bing

Websites

Google | Yahoo | Bing

Encyclopedia

Google | Yahoo | Bing

Facebook