Modul:Infobox mapframe

Documentation icon Dokumentacija modula[predogled] [uredi] [zgodovina] [osveži]

Usage

uredi

Module that automatically makes a mapframe suitable for an infobox automatically, if a page's linked Wikidata item has coordinates (geografske koordinate (P625)). Otherwise, an empty string is returned. The coordinates will be displayed as a point feature unless oznaka relacije OpenStreetMap (P402) is specified on the Wikidata item.

Can be used from {{Infobox mapframe}}, or invoked directly by a template, or imported to another Lua module.


local mf = require('Modul:Mapframe')local getArgs = require('Modul:Arguments').getArgslocal yesno = require('Modul:Yesno')local infoboxImage = require('Module:InfopoljeSlika').InfopoljeSlika-- Defaultslocal DEFAULT_FRAME_WIDTH = "270"local DEFAULT_FRAME_HEIGHT = "200"local DEFAULT_ZOOM = 10local 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 argsfunction trimArgs(argsTable)local cleanArgs = {}for key, val in pairs(argsTable) doif type(val) == 'string' thenval = val:match('^%s*(.-)%s*$')if val ~= '' thencleanArgs[key] = valendelsecleanArgs[key] = valendendreturn cleanArgsendfunction getBestStatement(item_id, property_id)if not(item_id) or not(mw.wikibase.isValidEntityId(item_id)) or not(mw.wikibase.entityExists(item_id)) thenreturn falseendlocal statements = mw.wikibase.getBestStatements(item_id, property_id)if not statements or #statements == 0 thenreturn falseendlocal hasNoValue = ( statements[1].mainsnak and statements[1].mainsnak.snaktype == 'novalue' )if hasNoValue thenreturn falseendreturn statements[1]endfunction hasWikidataProperty(item_id, property_id)return getBestStatement(item_id, property_id) and true or falseendfunction getStatementValue(statement)return statement and statement.mainsnak and statement.mainsnak.datavalue and statement.mainsnak.datavalue.value or nilendfunction relatedEntity(item_id, property_id)local value = getStatementValue( getBestStatement(item_id, property_id) )return value and value.id or falseendfunction idType(id)if not id then return nilelseif mw.ustring.match(id, "[Pp]%d+") thenreturn "property"elseif mw.ustring.match(id, "[Qq]%d+") thenreturn "item"elsereturn nilendendfunction getZoom(value, unit)local length_kmif unit == 'km' thenlength_km = tonumber(value)elseif unit == 'mi' thenlength_km = tonumber(value)*1.609344elseif unit == 'km2' thenlength_km = math.sqrt(tonumber(value))elseif unit == 'mi2' thenlength_km = math.sqrt(tonumber(value))*1.609344end-- max for zoom 2 is 6400km, for zoom 3 is 3200km, for zoom 4 is 1600km, etclocal zoom = math.floor(8 - (math.log10(length_km) - 2)/(math.log10(2)))-- limit to values below 17zoom = math.min(17, zoom)-- take off 1 when calculated from area, to account for unusual shapesif unit == 'km2' or unit == 'mi2' thenzoom = zoom - 1end-- minimum value is 1return math.max(1, zoom)endfunction shouldAutoRun(frame)-- Check if should be runninglocal explicitlyOn = yesno(mw.text.trim(frame.getParent(frame).args.mapframe or "")) -- true of false or nillocal onByDefault = (explicitlyOn == nil) and yesno(mw.text.trim(frame.args.onByDefault or ""), false) -- true or falsereturn explicitlyOn or onByDefaultendfunction 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 presentlocal args = getArgs(frame, {parentFirst = true})-- Discard args not prefixed with "mapframe-", remove that prefix from those that remainlocal fixedArgs = {}for name, val in pairs(args) dolocal fixedName = string.match(name, "^mapframe%-(.+)$" )if fixedName thenfixedArgs[fixedName] = val-- allow coord, coordinates, etc to be unprefixedelseif name == "coordinates" or name == "coord" or name == "coordinate" and not fixedArgs.coord thenfixedArgs.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 thenfixedArgs.id = valendendreturn fixedArgsendlocal p = {}p.autocaption = function(frame)if not shouldAutoRun(frame) then return "" endlocal args = argsFromAuto(frame)if args.caption thenreturn args.captionelseif args.switcher then return ""endlocal maskItemlocal maskType = idType(args.geomask)if maskType == 'item' thenmaskItem = args.geomaskelseif maskType == "property" thenmaskItem = relatedEntity(args.id or mw.wikibase.getEntityIdForCurrentPage(), args.geomask)endlocal maskItemLabel = maskItem and mw.wikibase.getLabel( maskItem )return maskItemLabel and "Location in "..maskItemLabel or ""endfunction parseCustomWikitext(customWikitext)--InfopoljeSlika will format an image if given wikitext containing an-- image, or else pass through the wikitext unmodifiedreturn infoboxImage({args = {image = customWikitext}})endp.auto = function(frame)if not shouldAutoRun(frame) then return "" endlocal args = argsFromAuto(frame)if args.custom thenreturn frame:preprocess(parseCustomWikitext(args.custom))endlocal mapframe = p._main(args)return frame:preprocess(mapframe)endp.main = function(frame)local parent = frame.getParent(frame)local parentArgs = parent.argslocal mapframe = p._main(parentArgs)return frame:preprocess(mapframe)endp._main = function(_config)-- `config` is the args passed to this modulelocal config = trimArgs(_config)-- Require wikidata item, or specified coordslocal wikidataId = config.id or mw.wikibase.getEntityIdForCurrentPage()if not(wikidataId) and not(config.coord) thenreturn ''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.coordif not hasCoordinates then  return ''end-- `args` is the arguments which will be passed to the mapframe modulelocal args = {}-- Some defaults/overrides for infobox presentationargs.display = "inline"args.frame = "yes"args.plain = "yes"args["frame-width"]  = config["frame-width"] or config.width or DEFAULT_FRAME_WIDTHargs["frame-height"] = config["frame-height"] or config.height or DEFAULT_FRAME_HEIGHTargs["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 ( https://www.how.com.vn/wiki/en/Special:Diff/876492931 )-- deprecated lat and long parametersargs["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 thenargs.zoom = getZoom(config.length_km, 'km')elseif config.length_mi thenargs.zoom = getZoom(config.length_mi, 'mi')elseif config.area_km2 thenargs.zoom = getZoom(config.area_km2, 'km2')elseif config.area_mi2 thenargs.zoom = getZoom(config.area_mi2, 'mi2')elseargs.zoom = config.zoom or DEFAULT_ZOOMend-- Conditionals: whether point, geomask should be shownlocal hasOsmRelationId = hasWikidataProperty(wikidataId, 'P402') -- P402 is OSM relation IDlocal shouldShowPointMarker;if config.point == "on" thenshouldShowPointMarker = true elseif config.point == "none" thenshouldShowPointMarker = falseelseshouldShowPointMarker = not(hasOsmRelationId) or (config.marker and config.marker ~= 'none') or (config.coordinates or config.coord)endlocal shouldShowShape = config.shape ~= 'none'local shapeType = config.shape == 'inverse' and 'shape-inverse' or 'shape'local shouldShowLine = config.line ~= 'none'local maskItemlocal 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 setif useWikidata and config.coord and shouldShowPointMarker thenuseWikidata = config.wikidata and true or falseend-- Switcherif config.switcher == "zooms" then-- switching between zoom levelslocal maxZoom = math.max(tonumber(args.zoom), 3) -- what zoom would have otherwise been (if 3 or more, otherwise 3)local minZoom = 1 -- completely zoomed outlocal midZoom = math.floor((maxZoom + minZoom)/2) -- midway between maxn and minargs.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 countryargs.zoom = nil -- let kartographer determine the zoomlocal 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) ~= "" dotable.insert(maskLabels, maskLabel)table.insert(maskItems, maskItemId)maskItemId = maskItemId and relatedEntity(maskItemId, "P131")maskLabel = maskItemId and mw.wikibase.getLabel(maskItemId)endif #maskLabels > 1 thenargs.switch = table.concat(maskLabels, "###")maskItem = "SWITCH:" .. table.concat(maskItems, ",")elseif #maskLabels == 1 thenmaskItem = maskItemId[1]endelseif config.switcher == "geomasks" and config.geomask then-- switching between items in geomask parameterargs.zoom = nil -- let kartographer determine the zoomlocal 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 thenfor i, item in ipairs(maskItems) dotable.insert(maskLabels, mw.wikibase.getLabel(item))endargs.switch = table.concat(maskLabels, "###")maskItem = "SWITCH:" .. table.concat(maskItems, ",")endend-- resolve geomask item id (if not using geomask switcher)if not maskItem then --  local maskType = idType(config.geomask)if maskType == 'item' thenmaskItem = config.geomaskelseif maskType == "property" thenmaskItem = relatedEntity(wikidataId, config.geomask)endend-- Keep track of arg numberinglocal argNumber = ''local function incrementArgNumber()if argNumber == '' thenargNumber = 2elseargNumber = argNumber + 1endend-- Geomaskif maskItem thenargs["type"..argNumber] = "shape-inverse"args["id"..argNumber] = maskItemargs["stroke-width"..argNumber] = config["geomask-stroke-width"] or DEFAULT_GEOMASK_STROKE_WIDTHargs["stroke-color"..argNumber] = config["geomask-stroke-color"] or config["geomask-stroke-colour"] or DEFAULT_GEOMASK_STROKE_COLORargs["fill"..argNumber] = config["geomask-fill"] or DEFAULT_GEOMASK_FILLargs["fill-opacity"..argNumber] = config["geomask-fill-opacity"] or DEFAULT_SHAPE_FILL_OPACITY-- Let kartographer determine zoom and position, unless it is explicitly set in configif not config.zoom and not config.switcher thenargs.zoom = nilargs["frame-coord"] = nilargs["frame-lat"] = nilargs["frame-long"] = nil local maskArea = getStatementValue( getBestStatement(maskItem, 'P2046') )endincrementArgNumber()-- Hack to fix phab:T255932if not args.zoom thenargs["type"..argNumber] = "line"args["id"..argNumber] = maskItemargs["stroke-width"..argNumber] = 0incrementArgNumber()endend-- Shape (or shape-inverse)if useWikidata and shouldShowShape thenargs["type"..argNumber] = shapeTypeif config.id then args["id"..argNumber] = config.id endargs["stroke-width"..argNumber] = config["shape-stroke-width"] or config["stroke-width"] or DEFAULT_SHAPE_STROKE_WIDTHargs["stroke-color"..argNumber] = config["shape-stroke-color"] or config["shape-stroke-colour"] or config["stroke-color"] or config["stroke-colour"] or DEFAULT_SHAPE_STROKE_COLORargs["fill"..argNumber] = config["shape-fill"] or DEFAULT_SHAPE_FILLargs["fill-opacity"..argNumber] = config["shape-fill-opacity"] or DEFAULT_SHAPE_FILL_OPACITYincrementArgNumber()end-- Lineif useWikidata and shouldShowLine thenargs["type"..argNumber] = "line"if config.id then args["id"..argNumber] = config.id endargs["stroke-width"..argNumber] = config["line-stroke-width"] or config["stroke-width"] or DEFAULT_LINE_STROKE_WIDTHargs["stroke-color"..argNumber] = config["line-stroke-color"] or config["line-stroke-colour"] or config["stroke-color"] or config["stroke-colour"] or DEFAULT_LINE_STROKE_COLORincrementArgNumber()end-- Pointif shouldShowPointMarker thenargs["type"..argNumber] = "point"if config.id then args["id"..argNumber] = config.id endif config.coord then args["coord"..argNumber] = config.coord endif config.marker then args["marker"..argNumber] = config.marker endargs["marker-color"..argNumber] = config["marker-color"] or config["marker-colour"] or DEFAULT_MARKER_COLORincrementArgNumber()endlocal mapframe = args.switch and mf.multi(args) or mf._main(args)local tracking = hasOsmRelationId and '' or '[[Kategorija:Infopolje mapframe brez OSM relation ID na  Wikipodatkih]]'return mapframe .. trackingendreturn p