Module:Infobox mapframe: திருத்தங்களுக்கு இடையிலான வேறுபாடு

தமிழர்விக்கியிலிருந்து
Jump to navigation Jump to search
உள்ளடக்கம் நீக்கப்பட்டது உள்ளடக்கம் சேர்க்கப்பட்டது
imported>Kanags
சிNo edit summary
imported>Balajijagadesh
சி en:Module:Infobox_mapframe இலிருந்து திருத்தம் இறக்குமதி செய்யப்பட்டன
 
வரிசை 11: வரிசை 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.5"
local DEFAULT_GEOMASK_FILL_OPACITY = "0.25"
local DEFAULT_SHAPE_STROKE_WIDTH = "3"
local DEFAULT_SHAPE_STROKE_WIDTH = "2"
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.5"
local DEFAULT_SHAPE_FILL_OPACITY = "0.1"
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"


local util = {}

function util.noop(info)
local DEFAULT_NOOP_OUTPUT = ""

-- uncomment this when debugging
-- DEFAULT_NOOP_OUTPUT = "debug: mapframe no-op: " .. info
-- mw.log(DEFAULT_NOOP_OUTPUT)

return DEFAULT_NOOP_OUTPUT
end


-- Trim whitespace from args, and remove empty args
-- Trim whitespace from args, and remove empty args
function trimArgs(argsTable)
function util.trimArgs(argsTable)
local cleanArgs = {}
local cleanArgs = {}
for key, val in pairs(argsTable) do
for key, val in pairs(argsTable) do
வரிசை 37: வரிசை 48:
end
end


function getBestStatement(item_id, property_id)
function util.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
வரிசை 52: வரிசை 63:
end
end


function hasWikidataProperty(item_id, property_id)
function util.hasWikidataProperty(item_id, property_id)
return getBestStatement(item_id, property_id) and true or false
return util.getBestStatement(item_id, property_id) and true or false
end
end


function getStatementValue(statement)
function util.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 relatedEntity(item_id, property_id)
function util.relatedEntity(item_id, property_id)
local value = getStatementValue( getBestStatement(item_id, property_id) )
local value = util.getStatementValue( util.getBestStatement(item_id, property_id) )
return value and value.id or false
return value and value.id or false
end
end


function idType(id)
function util.idType(id)
if not id then
if not id then
return nil
return nil
வரிசை 77: வரிசை 88:
end
end


function util.shouldAutoRun(frame)


function shouldAutoRun(frame)
-- Check if should be running
-- Check if should be running
local pargs = frame.getParent(frame).args
local pargs = frame.getParent(frame).args
வரிசை 88: வரிசை 97:
end
end


function argsFromAuto(frame)
function util.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 = {}
வரிசை 106: வரிசை 115:
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
-- allow captionstyle to be unprefixed, for compatibility with [[Module:Infobox]]
elseif name == "captionstyle" and not fixedArgs.captionstyle then
fixedArgs.captionstyle = val
end
end
end
end
return fixedArgs
return fixedArgs
end


function util.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

function util.trackAndWarn(trackingCat, warning)
local title = mw.title.getCurrentTitle()
local results = title and title.namespace == 0 and trackingCat and '[[Category:'..trackingCat..']]' or ''
if warning then
local warn = require('Module:If preview')._warning
results = results..warn({warning})
end
return results
end


function util.ternary(flag, other)
other = other or 'other'
flag = flag == 'none' and 'no' or flag
local yesNoOut = yesno(flag,other)
local yes = (yesNoOut == true)
local no = (yesNoOut == false)
return yes, no
end
end


local p = {}
local p = {}



p.autocaption = function(frame)
p._caption = function(args)
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 util.noop("no caption or switcher")
end
end
local maskItem
local maskItem
local maskType = idType(args.geomask)
local maskType = util.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 = relatedEntity(args.id or mw.wikibase.getEntityIdForCurrentPage(), args.geomask)
maskItem = util.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 or ""
return maskItemLabel and "Location in "..maskItemLabel
or util.noop("missing maskItemLabel with type " .. (maskType or "nil") .. " and item " .. (maskItem or "nil"))
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))
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


--A list of types for objects that are too small to allow Kartographer to take over zoom
--A list of types for objects that are too small to allow Kartographer to take over zoom
வரிசை 169: வரிசை 186:


p._main = function(_config)
p._main = function(_config)
-- accumulate tracking cats
local tracking = ''
-- `config` is the args passed to this module
-- `config` is the args passed to this module
local config = trimArgs(_config)
local config = util.trimArgs(_config)
-- allow alias for config.coord
-- allow alias for config.coord
வரிசை 178: வரிசை 197:
local wikidataId = config.id or mw.wikibase.getEntityIdForCurrentPage()
local wikidataId = config.id or mw.wikibase.getEntityIdForCurrentPage()
if not(wikidataId) and not(config.coord) then
if not(wikidataId) and not(config.coord) then
return false, util.trackAndWarn('Pages using infobox mapframe with missing coordinates')
return ''
end
end


-- Require coords (specified or from wikidata), so that map will be centred somewhere
-- Require coords (specified or from wikidata), so that map will be centred somewhere
-- (P625 = coordinate location)
-- (P625 = coordinate location)
local hasCoordinates = hasWikidataProperty(wikidataId, 'P625') or config.coord
local wdCoordinates = util.getStatementValue(util.getBestStatement(wikidataId, 'P625'))
if not (config.coord or wdCoordinates) then
if not hasCoordinates then
return false, util.trackAndWarn('Pages using infobox mapframe with missing coordinates')
return ''
end
end


வரிசை 199: வரிசை 218:
args["frame-align"] = "center"
args["frame-align"] = "center"


args["frame-coord"] = config["frame-coordinates"] or config["frame-coord"] or ""
args["frame-coord"] = config["frame-coordinates"] or config["frame-coord"]
-- Note: config["coordinates"] or config["coord"] should not be used for the alignment of the frame;
-- Note: config["coordinates"] or config["coord"] should not be used for the alignment of the frame;
-- see talk page ( https://en.wikipedia.org/wiki/Special:Diff/876492931 )
-- see talk page ( https://en.wikipedia.org/wiki/Special:Diff/876492931 )


-- deprecated lat and long parameters
-- deprecated lat and long parameters
args["frame-lat"] = config["frame-lat"] or config["frame-latitude"] or ""
args["frame-lat"] = config["frame-lat"] or config["frame-latitude"]
args["frame-long"] = config["frame-long"] or config["frame-longitude"] or ""
args["frame-long"] = config["frame-long"] or config["frame-longitude"]


-- if zoom isn't specified from config:
-- if zoom isn't specified from config, first check wikidata
local zoom = config.zoom
local zoom = config.zoom or util.getStatementValue(util.getBestStatement(wikidataId, 'P6592'))
if not zoom then
if not zoom then
-- Calculate zoom from length or area (converted to km or km2)
-- Calculate zoom from length or area (converted to km or km2)
வரிசை 218: வரிசை 237:
area_ha=config.area_ha, area_acre=config.area_acre,
area_ha=config.area_ha, area_acre=config.area_acre,
type=config.type, population=config.population,
type=config.type, population=config.population,
viewport_px=math.min(args["frame-width"],args["frame-height"])})
viewport_px=math.min(args["frame-width"],args["frame-height"]),
latitude=wdCoordinates and wdCoordinates.latitude})
end
end
args.zoom = zoom or DEFAULT_ZOOM
args.zoom = zoom or DEFAULT_ZOOM
வரிசை 224: வரிசை 244:
-- Use OSM relation ID if available; otherwise use geoshape if that is available
-- Use OSM relation ID if available; otherwise use geoshape if that is available
-- (geoshape is required for defunct entities, which are outside OSM's scope)
-- (geoshape is required for defunct entities, which are outside OSM's scope)
local hasOsmRelationId = hasWikidataProperty(wikidataId, 'P402') -- P402 is OSM relation ID
local hasOsmRelationId = util.hasWikidataProperty(wikidataId, 'P402') -- P402 is OSM relation ID
local hasGeoshape = hasWikidataProperty(wikidataId, 'P3896') -- P3896 is geoshape
local hasGeoshape = util.hasWikidataProperty(wikidataId, 'P3896') -- P3896 is geoshape
local wikidataProvidesGeo = hasOsmRelationId or hasGeoshape
local wikidataProvidesGeo = hasOsmRelationId or hasGeoshape
local shouldShowPointMarker;


-- determine marker argument value, determine whether to show marker
-- determine marker argument value, determine whether to show marker
local pointValue = config.point
local forcePoint, suppressPoint = util.ternary(config.point)
local forceMarker, suppressMarker = util.ternary(config.marker,true)
if pointValue == 'none' then
pointValue = 'no'
end
pointValue = yesno(pointValue,'other')
local markerValue = config.marker
if markerValue == 'none' then
markerValue = 'no'
end
markerValue = yesno(markerValue,true)


forcePoint = forcePoint or forceMarker
if pointValue == true then
suppressPoint = suppressPoint or suppressMarker
shouldShowPointMarker = true

elseif pointValue == false then
local showMarker = not suppressPoint and (forcePoint or not wikidataProvidesGeo or config.coord)
shouldShowPointMarker = false
else
-- wikidata = "yes" turns on both shape and line
shouldShowPointMarker = not(wikidataProvidesGeo) or markerValue or config.coord
-- wikidata = "no" turns off both shape and line
end
-- otherwise show both if wikidata provides geo
local forceWikidata, suppressWikidata = util.ternary(config.wikidata)
local showShape = not suppressWikidata and (forceWikidata or wikidataProvidesGeo or not config.coord)
local showLine = showShape


-- determine shape parameter value, determine whether to show or suppress shape
-- determine shape parameter value, determine whether to show or suppress shape
-- also determine whether to invert shape
-- also determine whether to invert shape
local shapeValue = config.shape
local forceShape, suppressShape = util.ternary(config.shape)
showShape = wikidataId and not suppressShape and (forceShape or showShape)
if shapeValue == 'none' then
shapeValue = 'no'
end
shapeValue = yesno(shapeValue,'other')

local forceShape = shapeValue == true and wikidataProvidesGeo
local suppressShape = shapeValue == false
local shapeType = config.shape == 'inverse' and 'shape-inverse' or 'shape'
local shapeType = config.shape == 'inverse' and 'shape-inverse' or 'shape'


-- determine line parameter value, determine whether to show or suppress line
-- determine line parameter value, determine whether to show or suppress line
local lineValue = config.line
local forceLine, suppressLine = util.ternary(config.line)
showLine = wikidataId and not suppressLine and (forceLine or showLine)
if lineValue == 'none' then
lineValue = 'no'
end
local lineValue = yesno(lineValue,'other')


local maskItem
local forceLine = lineValue == true and wikidataProvidesGeo
local suppressLine = lineValue == false

-- determine whether to use wikidata (independent of shape/line)
local maskItem
local useWikidata = wikidataId -- by default, if wikidata is supplied, use wikidata
-- 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 = yesno(config.wikidata,true)
end
-- Switcher
-- Switcher
if config.switcher == "zooms" then
if config.switcher == "zooms" then
வரிசை 293: வரிசை 289:
local maskLabels = {}
local maskLabels = {}
local maskItems = {}
local maskItems = {}
local maskItemId = relatedEntity(wikidataId, "P276") or relatedEntity(wikidataId, "P131")
local maskItemId = util.relatedEntity(wikidataId, "P276") or util.relatedEntity(wikidataId, "P131")
local maskLabel = mw.wikibase.getLabel(maskItemId)
local maskLabel = mw.wikibase.getLabel(maskItemId)
while maskItemId and maskLabel and mw.text.trim(maskLabel) ~= "" do
while maskItemId and maskLabel and mw.text.trim(maskLabel) ~= "" do
table.insert(maskLabels, maskLabel)
table.insert(maskLabels, maskLabel)
table.insert(maskItems, maskItemId)
table.insert(maskItems, maskItemId)
maskItemId = maskItemId and relatedEntity(maskItemId, "P131")
maskItemId = maskItemId and util.relatedEntity(maskItemId, "P131")
maskLabel = maskItemId and mw.wikibase.getLabel(maskItemId)
maskLabel = maskItemId and mw.wikibase.getLabel(maskItemId)
end
end
வரிசை 326: வரிசை 322:
-- resolve geomask item id (if not using geomask switcher)
-- resolve geomask item id (if not using geomask switcher)
if not maskItem then --
if not maskItem then --
local maskType = idType(config.geomask)
local maskType = util.idType(config.geomask)
if maskType == 'item' then
if maskType == 'item' then
maskItem = config.geomask
maskItem = config.geomask
elseif maskType == "property" then
elseif maskType == "property" then
maskItem = relatedEntity(wikidataId, config.geomask)
maskItem = util.relatedEntity(wikidataId, config.geomask)
end
end
end
end
வரிசை 340: வரிசை 336:
-- and if the object size inferred from its type is not too small
-- and if the object size inferred from its type is not too small
-- then let Kartographer "take over" zoom
-- then let Kartographer "take over" zoom
if (forceLine or forceShape or (useWikidata and not (suppressShape and suppressLine)))
if (showLine or showShape) and wikidataProvidesGeo and not maskItem
and wikidataProvidesGeo and not maskItem and not config.zoom
and not config.zoom and not (config.type and tinyType[config.type]) then
and not (config.type and tinyType[config.type]) then
args.zoom = nil
args.zoom = nil
end
end

if not maskItem and not showShape and not showLine and not showMarker then
return false, util.trackAndWarn('Pages using infobox mapframe with no geometry','No geometry specified for mapframe')
end
-- Keep track of arg numbering
-- Keep track of arg numbering
வரிசை 370: வரிசை 369:
args["frame-lat"] = nil
args["frame-lat"] = nil
args["frame-long"] = nil
args["frame-long"] = nil
local maskArea = getStatementValue( getBestStatement(maskItem, 'P2046') )
local maskArea = util.getStatementValue( util.getBestStatement(maskItem, 'P2046') )
end
end
incrementArgNumber()
incrementArgNumber()
வரிசை 383: வரிசை 382:
-- Shape (or shape-inverse)
-- Shape (or shape-inverse)
if showShape then
if forceShape or (useWikidata and not suppressShape) then
args["type"..argNumber] = shapeType
args["type"..argNumber] = shapeType
if hasGeoshape and not hasOsmRelationId then
if hasGeoshape and not hasOsmRelationId then
args["from"..argNumber] = string.sub( getStatementValue( getBestStatement(wikidataId, 'P3896') ), 6)
args["from"..argNumber] = string.sub( util.getStatementValue( util.getBestStatement(wikidataId, 'P3896') ), 6)
elseif config.id then
elseif config.id then
args["id"..argNumber] = config.id
args["id"..argNumber] = config.id
வரிசை 398: வரிசை 397:
-- Line
-- Line
if showLine then
if forceLine or (useWikidata and not suppressLine) then
args["type"..argNumber] = "line"
args["type"..argNumber] = "line"
if hasGeoshape and not hasOsmRelationId then
if hasGeoshape and not hasOsmRelationId then
args["from"..argNumber] = string.sub( getStatementValue( getBestStatement(wikidataId, 'P3896') ), 6)
args["from"..argNumber] = string.sub( util.getStatementValue( util.getBestStatement(wikidataId, 'P3896') ), 6)
elseif config.id then
elseif config.id then
args["id"..argNumber] = config.id
args["id"..argNumber] = config.id
வரிசை 410: வரிசை 409:
end
end


-- Point
-- Point marker
if shouldShowPointMarker then
if showMarker then
args["type"..argNumber] = "point"
args["type"..argNumber] = "point"
if config.id then args["id"..argNumber] = config.id end
if config.id then args["id"..argNumber] = config.id end
வரிசை 419: வரிசை 418:
incrementArgNumber()
incrementArgNumber()
end
end

-- if Wikidata doesn't link to OSM and the map has no mask or point,
-- then center the map on the coordinates either from the infobox or from wikidata
if not maskItem and not showMarker and not wikidataProvidesGeo then
if config.coord then
args["frame-coord"] = args["frame-coord"] or config.coord
else
args["frame-lat"] = args["frame-lat"] or wdCoordinates.latitude
args["frame-long"] = args["frame-long"] or wdCoordinates.longitude
end
tracking = tracking..util.trackAndWarn('Pages using infobox mapframe with forced centering')
end

-- protect against nil frame arguments
args["frame-coord"] = args["frame-coord"] or ""
args["frame-lat"] = args["frame-lat"] or ""
args["frame-long"] = args["frame-long"] or ""


local mapframe = args.switch and mf.multi(args) or mf._main(args)
local mapframe = args.switch and mf.multi(args) or mf._main(args)
tracking = tracking..((showLine or showShape) and not wikidataProvidesGeo
local tracking = hasOsmRelationId and '' or '[[Category:Infobox mapframe without OSM relation ID on Wikidata]]'
and util.trackAndWarn('Pages using infobox mapframe without shape links in Wikidata')
return mapframe .. tracking
or '')
return true, mapframe.. tracking
end
end


-- Entry points

p.main = function(frame)
local parent = frame.getParent(frame)
local parentArgs = parent.args
local _, mapframe = p._main(parentArgs)
return frame:preprocess(mapframe)
end

p.auto = function(frame)
if not util.shouldAutoRun(frame) then
return util.noop("auto should not autorun")
end
local args = util.argsFromAuto(frame)
if args.custom then
return frame:preprocess(util.parseCustomWikitext(args.custom))
end
local _, mapframe = p._main(args)
return frame:preprocess(mapframe)
end

p.autocaption = function(frame)
if not util.shouldAutoRun(frame) then
return util.noop("autocaption should not autorun")
end
local args = util.argsFromAuto(frame)
local caption = p._caption(args)
return caption
end

p.autoWithCaption = function(frame)
if not util.shouldAutoRun(frame) then
return util.noop("autoWithCaption should not autorun")
end
local args = util.argsFromAuto(frame)
local wikitext
local caption
local ok
if args.custom then
ok = true
wikitext = util.parseCustomWikitext(args.custom)
else
ok, wikitext = p._main(args)
end
if not ok then return wikitext end
wikitext = frame:preprocess(wikitext)
caption = p._caption(args)
local data = mw.html.create():wikitext(wikitext)
data:tag('div')
:addClass('infobox-caption')
:cssText(args.captionstyle)
:wikitext(caption)
return tostring(data)
end
return p
return p

10:33, 27 திசம்பர் 2025 இல் கடைசித் திருத்தம்

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.25"
local DEFAULT_SHAPE_STROKE_WIDTH = "2"
local DEFAULT_SHAPE_STROKE_COLOR = "#FF0000"
local DEFAULT_SHAPE_FILL = "#606060"
local DEFAULT_SHAPE_FILL_OPACITY = "0.1"
local DEFAULT_LINE_STROKE_WIDTH = "5"
local DEFAULT_LINE_STROKE_COLOR = "#FF0000"
local DEFAULT_MARKER_COLOR = "#5E74F3"

local util = {}

function util.noop(info)
	local DEFAULT_NOOP_OUTPUT = ""

	-- uncomment this when debugging
	-- DEFAULT_NOOP_OUTPUT = "debug: mapframe no-op: " .. info
	-- mw.log(DEFAULT_NOOP_OUTPUT)

	return DEFAULT_NOOP_OUTPUT
end

-- Trim whitespace from args, and remove empty args
function util.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 util.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 util.hasWikidataProperty(item_id, property_id)
	return util.getBestStatement(item_id, property_id) and true or false
end

function util.getStatementValue(statement)
	return statement and statement.mainsnak and statement.mainsnak.datavalue and statement.mainsnak.datavalue.value or nil
end

function util.relatedEntity(item_id, property_id)
	local value = util.getStatementValue( util.getBestStatement(item_id, property_id) )
	return value and value.id or false
end

function util.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 util.shouldAutoRun(frame)
	-- Check if should be running
	local pargs = frame.getParent(frame).args
	local explicitlyOn = yesno(mw.text.trim(pargs.mapframe or "")) -- true of false or nil
	if pargs.coordinates == "{{{coordinates}}}" then explicitlyOn = false end
	local onByDefault = (explicitlyOn == nil) and yesno(mw.text.trim(frame.args.onByDefault or ""), false) -- true or false
	return explicitlyOn or onByDefault
end

function util.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
        -- allow captionstyle to be unprefixed, for compatibility with [[Module:Infobox]]
        elseif name == "captionstyle" and not fixedArgs.captionstyle then
            fixedArgs.captionstyle = val
		end
	end
	return fixedArgs
end


function util.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

function util.trackAndWarn(trackingCat, warning)
    local title = mw.title.getCurrentTitle()
    local results = title and title.namespace == 0 and trackingCat and '[[Category:'..trackingCat..']]' or ''
    if warning then
        local warn = require('Module:If preview')._warning
        results = results..warn({warning})
    end
    return results
end


function util.ternary(flag, other)
    other = other or 'other'
    flag = flag == 'none' and 'no' or flag
    local yesNoOut = yesno(flag,other)
    local yes = (yesNoOut == true)
    local no = (yesNoOut == false)
    return yes, no
end

local p = {}


p._caption = function(args)
	if args.caption then
		return args.caption
	elseif args.switcher then 
		return util.noop("no caption or switcher")
	end
	local maskItem
	local maskType = util.idType(args.geomask)
	if maskType == 'item' then
		maskItem = args.geomask
	elseif maskType == "property" then
		maskItem = util.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 util.noop("missing maskItemLabel with type " .. (maskType or "nil") .. " and item " .. (maskItem or "nil"))
end


--A list of types for objects that are too small to allow Kartographer to take over zoom
local tinyType = {
    landmark=true,
    railwaystation=true,
    edu=true,
    pass=true,
    camera=true
}                 

p._main = function(_config)
    -- accumulate tracking cats
    local tracking = ''
	-- `config` is the args passed to this module
	local config = util.trimArgs(_config)
	
    -- allow alias for config.coord
    config.coord = config.coord or config.coordinates

	-- Require wikidata item, or specified coords
	local wikidataId = config.id or mw.wikibase.getEntityIdForCurrentPage()
	if not(wikidataId) and not(config.coord) then
		return false, util.trackAndWarn('Pages using infobox mapframe with missing coordinates')
	end

	-- Require coords (specified or from wikidata), so that map will be centred somewhere
	-- (P625 = coordinate location)
    local wdCoordinates = util.getStatementValue(util.getBestStatement(wikidataId, 'P625'))
    if not (config.coord or wdCoordinates) then
		return false, util.trackAndWarn('Pages using infobox mapframe with missing coordinates')
	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"]
	-- Note: config["coordinates"] or config["coord"] should not be used for the alignment of the frame;
	-- see talk page ( https://en.wikipedia.org/wiki/Special:Diff/876492931 )

	-- deprecated lat and long parameters
	args["frame-lat"]    = config["frame-lat"] or config["frame-latitude"]
	args["frame-long"]   = config["frame-long"] or config["frame-longitude"]

    -- if zoom isn't specified from config, first check wikidata
    local zoom = config.zoom or util.getStatementValue(util.getBestStatement(wikidataId, 'P6592'))
    if not zoom then
	    -- Calculate zoom from length or area (converted to km or km2)
	    -- Zoom so that length or area is completely included in mapframe
	    local getZoom = require('Module:Infobox dim')._zoom
	    zoom = getZoom({length_km=config.length_km, length_mi=config.length_mi,
                        width_km=config.width_km, width_mi=config.width_mi,
		                area_km2=config.area_km2, area_mi2=config.area_mi2,
                        area_ha=config.area_ha, area_acre=config.area_acre,
                        type=config.type, population=config.population,
		                viewport_px=math.min(args["frame-width"],args["frame-height"]),
                        latitude=wdCoordinates and wdCoordinates.latitude})
    end
    args.zoom = zoom or DEFAULT_ZOOM

	-- Use OSM relation ID if available; otherwise use geoshape if that is available
	-- (geoshape is required for defunct entities, which are outside OSM's scope)
	local hasOsmRelationId = util.hasWikidataProperty(wikidataId, 'P402') -- P402 is OSM relation ID
	local hasGeoshape = util.hasWikidataProperty(wikidataId, 'P3896') -- P3896 is geoshape
	local wikidataProvidesGeo = hasOsmRelationId or hasGeoshape

    -- determine marker argument value, determine whether to show marker
    local forcePoint, suppressPoint = util.ternary(config.point)
    local forceMarker, suppressMarker = util.ternary(config.marker,true)

    forcePoint = forcePoint or forceMarker
    suppressPoint = suppressPoint or suppressMarker

    local showMarker = not suppressPoint and (forcePoint or not wikidataProvidesGeo or config.coord)
    
    -- wikidata = "yes" turns on both shape and line
    -- wikidata = "no" turns off both shape and line
    -- otherwise show both if wikidata provides geo
    local forceWikidata, suppressWikidata = util.ternary(config.wikidata)
    local showShape = not suppressWikidata and (forceWikidata or wikidataProvidesGeo or not config.coord)
    local showLine = showShape

    -- determine shape parameter value, determine whether to show or suppress shape
    -- also determine whether to invert shape
    local forceShape, suppressShape = util.ternary(config.shape)
    showShape = wikidataId and not suppressShape and (forceShape or showShape)
	local shapeType = config.shape == 'inverse' and 'shape-inverse' or 'shape'

    -- determine line parameter value, determine whether to show or suppress line
    local forceLine, suppressLine = util.ternary(config.line)
    showLine = wikidataId and not suppressLine and (forceLine or showLine)

    local maskItem
	-- 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 = util.relatedEntity(wikidataId, "P276") or  util.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 util.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 = maskItemId[1]
		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 = util.idType(config.geomask)
		if maskType == 'item' then
			maskItem = config.geomask
		elseif maskType == "property" then
			maskItem = util.relatedEntity(wikidataId, config.geomask)
		end
	end

    -- if asking for shape or line from Wikidata
    -- and if Wikidata actually has shape/line data (wikidataProvidesGeo=true)
    -- and if no geomask
    -- and if zoom not explicitly set
    -- and if the object size inferred from its type is not too small
    -- then let Kartographer "take over" zoom
    if (showLine or showShape) and wikidataProvidesGeo and not maskItem
       and not config.zoom and not (config.type and tinyType[config.type]) then
	    args.zoom = nil
    end	

    if not maskItem and not showShape and not showLine and not showMarker then
        return false, util.trackAndWarn('Pages using infobox mapframe with no geometry','No geometry specified for mapframe')
    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 = util.getStatementValue( util.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 showShape then
		args["type"..argNumber] = shapeType
		if hasGeoshape and not hasOsmRelationId then
			args["from"..argNumber] = string.sub( util.getStatementValue( util.getBestStatement(wikidataId, 'P3896') ), 6)
		elseif 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 showLine then
		args["type"..argNumber] = "line"
		if hasGeoshape and not hasOsmRelationId then
			args["from"..argNumber] = string.sub( util.getStatementValue( util.getBestStatement(wikidataId, 'P3896') ), 6)
		elseif 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 marker
	if showMarker 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

    -- if Wikidata doesn't link to OSM and the map has no mask or point,
    -- then center the map on the coordinates either from the infobox or from wikidata
    if not maskItem and not showMarker and not wikidataProvidesGeo then
        if config.coord then
            args["frame-coord"] = args["frame-coord"] or config.coord
        else
            args["frame-lat"] = args["frame-lat"] or wdCoordinates.latitude
            args["frame-long"] = args["frame-long"] or wdCoordinates.longitude
        end
        tracking = tracking..util.trackAndWarn('Pages using infobox mapframe with forced centering')
    end

    -- protect against nil frame arguments
    args["frame-coord"] = args["frame-coord"] or ""
    args["frame-lat"] = args["frame-lat"] or ""
    args["frame-long"] = args["frame-long"] or ""

	local mapframe = args.switch and mf.multi(args) or mf._main(args)
	tracking = tracking..((showLine or showShape) and not wikidataProvidesGeo 
                          and util.trackAndWarn('Pages using infobox mapframe without shape links in Wikidata')
                          or '')
	return true, mapframe.. tracking
end

-- Entry points

p.main = function(frame)
	local parent = frame.getParent(frame)
	local parentArgs = parent.args
	local _, mapframe = p._main(parentArgs)
	return frame:preprocess(mapframe)
end

p.auto = function(frame)
	if not util.shouldAutoRun(frame) then
		return util.noop("auto should not autorun")
	end
	local args = util.argsFromAuto(frame)
	if args.custom then
		return frame:preprocess(util.parseCustomWikitext(args.custom))
	end
	local _, mapframe = p._main(args)
	return frame:preprocess(mapframe)
end

p.autocaption = function(frame)
	if not util.shouldAutoRun(frame) then
		return util.noop("autocaption should not autorun")
	end
	local args = util.argsFromAuto(frame)
    local caption = p._caption(args)
    return caption
end

p.autoWithCaption = function(frame)
	if not util.shouldAutoRun(frame) then
		return util.noop("autoWithCaption should not autorun")
	end
	local args = util.argsFromAuto(frame)
    local wikitext
    local caption
    local ok
    if args.custom then
        ok = true
        wikitext = util.parseCustomWikitext(args.custom)
    else
        ok, wikitext = p._main(args)
    end
    if not ok then return wikitext end
    wikitext = frame:preprocess(wikitext)
    caption = p._caption(args)
    local data = mw.html.create():wikitext(wikitext)
    data:tag('div')
	    :addClass('infobox-caption')
		:cssText(args.captionstyle)
		:wikitext(caption)
    return tostring(data)
end
    
return p
"https://tamilar.wiki/w/index.php?title=Module:Infobox_mapframe&oldid=383391" இலிருந்து மீள்விக்கப்பட்டது