Movatterモバイル変換


[0]ホーム

URL:


Jump to content
WikipediaThe Free Encyclopedia
Search

Module:Mapframe

Permanently protected module
From Wikipedia, the free encyclopedia
Module documentation[view] [edit] [history] [purge]
Thismodule is rated asbeta. It is considered ready for widespread use, but as it is still relatively new, it should be applied with some caution to ensure results are as expected.
Page template-protectedThis module is currentlyprotected from editing.
See theprotection policy andprotection log for more details. Please discuss any changes on thetalk page; you maysubmit an edit request to ask anadministrator to make an edit if it isuncontroversial or supported byconsensus. You may alsorequest that this page be unprotected.
WarningThis Lua module is used onapproximately 1,290,000 pages, or roughly 2% of all pages.
To avoid major disruption and server load, any changes should be tested in the module's/sandbox or/testcases subpages, or in your ownmodule sandbox. The tested changes can be added to this page in a single edit. Consider discussing changes on thetalk page before implementing them.
This module depends on the following other modules:
CSSThis module usesTemplateStyles:

On English Wikipedia, this module is called by{{Maplink}}. See that template's documentation for usage instructions.

Usage

Standard usage
Just use{{Maplink}}, which passes its parameters to this module'smain function as default.
If a page has a rendering time by Lua of between 5 seconds and 10 seconds using{{Maplink}} the use of the direct module call by syntax like:{{#tag:mapframe|[raw GeoJSON]|frameless=[1 for frame]|align=[left/right/center]|text=[caption]|width=[in px]|height=[in px]|latitude=[decimal degrees]|longitude=[decimal degrees]|zoom=[zoom factor]}} saves Lua over-head. An example of this substitution is athttps://en.wikipedia.org/w/index.php?diff=970846012. Such code minimises the chances of hitting the ten second Lua timeout if the back-end servers are busy.
From another module
  1. Import this module, e.g.local mf = require('Module:Mapframe')
  2. Pass a table of parameter names/values to the_main function. See{{Maplink}} documentation for parameter names and descriptions. E.g.local mapframe = mf._main(parameters)
  3. Preprocess_main's output before returning it, e.g.return frame:preprocess(mapframe)

Set up on another wiki

  1. Create template and module:
    • Import this module and its template to that wiki (or copy the code over, giving attribution in the edit summary). Optionally, give them a name that makes sense in that wiki's language
    • On Wikidata, add them to the itemsModule:Mapframe(Q52554979) andTemplate:Maplink(Q27882107)
  2. Localise the module
    • Edit the top bits of the module, between the comments-- ##### Localisation (L10n) settings ##### and-- #### End of L10n settings ####, replacing values between"" symbols with local values (when necessary)
  3. Add documentation
    • to the template (e.g. by translatingTemplate:Maplink/doc, adjusting as necessary per any localisations made in the previous step)
    • to the module (please transfer/translate these instructions so that wikimedians who read your wiki but not the English Wikipedia can also set up the module and template on another wiki).
The abovedocumentation istranscluded fromModule:Mapframe/doc.(edit |history)
Editors can experiment in this module'ssandbox(edit |diff) andtestcases(edit) pages.
Subpages of this module.

-- Note: Originally written on English Wikipedia at https://en.wikipedia.org/wiki/Module:Mapframe--[[---------------------------------------------------------------------------- ##### Localisation (L10n) settings ##### Replace values in quotes ("") with localised values----------------------------------------------------------------------------]]--localL10n={}-- Modue dependencieslocaltranscluder-- local copy of https://www.mediawiki.org/wiki/Module:Transcluder loaded lazily-- "strict" should not be used, at least until all other modules which require this module are not using globals.-- Template parameter names (unnumbered versions only)--   Specify each as either a single string, or a table of strings (aliases)--   Aliases are checked left-to-right, i.e. `{ "one", "two" }` is equivalent to using `{{{one| {{{two|}}} }}}` in a templateL10n.para={display="display",type="type",id={"id","ids"},from="from",raw="raw",title="title",description="description",strokeColor={"stroke-color","stroke-colour"},strokeWidth="stroke-width",strokeOpacity="stroke-opacity",fill="fill",fillOpacity="fill-opacity",coord="coord",marker="marker",markerColor={"marker-color","marker-colour"},markerSize="marker-size",radius={"radius","radius_m"},radiusKm="radius_km",radiusFt="radius_ft",radiusMi="radius_mi",edges="edges",text="text",icon="icon",zoom="zoom",frame="frame",plain="plain",frameWidth="frame-width",frameHeight="frame-height",frameCoordinates={"frame-coordinates","frame-coord"},frameLatitude={"frame-lat","frame-latitude"},frameLongitude={"frame-long","frame-longitude"},frameAlign="frame-align",switch="switch",overlay="overlay",overlayBorder="overlay-border",overlayHorizontalAlignment="overlay-horizontal-alignment",overlayVerticalAlignment="overlay-vertical-alignment",overlayHorizontalOffset="overlay-horizontal-offset",overlayVerticalOffset="overlay-vertical-offset"}-- Names of other templates this module can extract coordinates fromL10n.template={coord={-- The coord template, as well as templates with output that contains {{coord}}"Coord","Coord/sandbox","NRHP row","NRHP row/sandbox","WikidataCoord","WikidataCoord/sandbox","Wikidatacoord","Wikidata coord"}}-- Error messagesL10n.error={badDisplayPara="Invalid display parameter",noCoords="Coordinates must be specified on Wikidata or in |"..(type(L10n.para.coord)=='table'andL10n.para.coord[1]orL10n.para.coord).."=",wikidataCoords="Coordinates not found on Wikidata",noCircleCoords="Circle centre coordinates must be specified, or available via Wikidata",negativeRadius="Circle radius must be a positive number",noRadius="Circle radius must be specified",negativeEdges="Circle edges must be a positive number",noSwitchPara="Found only one switch value in |"..(type(L10n.para.switch)=='table'andL10n.para.switch[1]orL10n.para.switch).."=",oneSwitchLabel="Found only one label in |"..(type(L10n.para.switch)=='table'andL10n.para.switch[1]orL10n.para.switch).."=",noSwitchLists="At least one parameter must have a SWITCH: list",switchMismatches="All SWITCH: lists must have the same number of values",-- "%s" and "%d" tokens will be replaced with strings and numbers when usedoneSwitchValue="Found only one switch value in |%s=",fewerSwitchLabels="Found %d switch values but only %d labels in |"..(type(L10n.para.switch)=='table'andL10n.para.switch[1]orL10n.para.switch).."=",noNamedCoords="No named coordinates found in %s"}-- Other stringsL10n.str={-- valid values for display parameter, e.g. (|display=inline) or (|display=title) or (|display=inline,title) or (|display=title,inline)inline="inline",title="title",dsep=",",-- separator between inline and title (comma in the example above)-- valid values for type parameterline="line",-- geoline feature (e.g. a road)shape="shape",-- geoshape feature (e.g. a state or province)shapeInverse="shape-inverse",-- geomask feature (the inverse of a geoshape)data="data",-- geoJSON data page on Commonspoint="point",-- single point feature (coordinates)circle="circle",-- circular area around a pointnamed="named",-- all named coordinates in an article or section-- Keyword to indicate a switch list. Must NOT use the special characters ^$()%.[]*+-?switch="SWITCH",-- valid values for icon, frame, and plain parametersaffirmedWords=' '..table.concat({"add","added","affirm","affirmed","include","included","on","true","yes","y"},' ')..' ',declinedWords=' '..table.concat({"decline","declined","exclude","excluded","false","none","not","no","n","off","omit","omitted","remove","removed"},' ')..' '}-- Default values for parametersL10n.defaults={display=L10n.str.inline,text="Map",frameWidth="300",frameHeight="200",frameAlign="right",markerColor="5E74F3",markerSize=nil,strokeColor="#ff0000",strokeWidth=6,edges=32,-- number of edges used to approximate a circleoverlayBorder="1px solid white",overlayHorizontalAlignment="right",overlayHorizontalOffset="0",overlayVerticalAlignment="bottom",overlayVerticalOffset="0"}-- #### End of L10n settings ####--[[---------------------------------------------------------------------------- Utility methods----------------------------------------------------------------------------]]--localutil={}--[[Looks up a parameter value based on the id (a key from the L10n.para table) andoptionally a suffix, for parameters that can be suffixed (e.g. type2 is typewith suffix 2).@param {table} args  key-value pairs of parameter names and their values@param {string} param_id  id for parameter name (key from the L10n.para table)@param {string} [suffix]  suffix for parameter name@returns {string|nil} parameter value if found, or nil if not found]]--functionutil.getParameterValue(args,param_id,suffix)suffix=suffixor''iftype(L10n.para[param_id])~='table'thenreturnargs[L10n.para[param_id]..suffix]endfor_i,paramAliasinipairs(L10n.para[param_id])doifargs[paramAlias..suffix]thenreturnargs[paramAlias..suffix]endendreturnnilend--[[Trim whitespace from args, and remove empty args. Also fix control characters.@param {table} argsTable@returns {table} trimmed args table]]--functionutil.trimArgs(argsTable)localcleanArgs={}forkey,valinpairs(argsTable)doiftype(key)=='string'andtype(val)=='string'thenval=val:match('^%s*(.-)%s*$')ifval~=''then-- control characters inside json need to be escaped, but stripping them is simpler-- See also T214984-- However, *don't* strip control characters from wikitext (text or description parameters) or you'll break strip markers-- Alternatively it might be better to only strip control char from raw parameter contentifutil.matchesParam('text',key)orutil.matchesParam('description',key,key:gsub('^%D+(%d+)$','%1'))thencleanArgs[key]=valelsecleanArgs[key]=val:gsub('%c',' ')endendelsecleanArgs[key]=valendendreturncleanArgsend--[[Check if a parameter name matches an unlocalized parameter key@param {string} key - the unlocalized parameter name to search through@param {string} name - the localized parameter name to check@param {string|nil} - an optional suffix to apply to the value(s) from the localization key@returns {boolean} true if the name matches the parameter, false otherwise]]--functionutil.matchesParam(key,name,suffix)localparam=L10n.para[key]suffix=suffixor''iftype(param)=='table'thenfor_,vinpairs(param)doif(v..suffix)==namethenreturntrueendendreturnfalseendreturn((param..suffix)==name)end--[[Check if a value is affirmed (one of the values in L10n.str.affirmedWords)@param {string} val  Value to be checked@returns {boolean} true if affirmed, false otherwise]]--functionutil.isAffirmed(val)ifnot(val)thenreturnfalseendreturnstring.find(L10n.str.affirmedWords,' '..val..' ',1,true)andtrueorfalseend--[[Check if a value is declined (one of the values in L10n.str.declinedWords)@param {string} val  Value to be checked@returns {boolean} true if declined, false otherwise]]--functionutil.isDeclined(val)ifnot(val)thenreturnfalseendreturnstring.find(L10n.str.declinedWords,' '..val..' ',1,true)andtrueorfalseend--[[Check if the name of a template matches the known coord templates or wrappers(in L10n.template.coord). The name is normalised when checked, so e.g. the names"Coord", "coord", and "  Coord" all return true.@param {string} name@returns {boolean} true if it is a coord template or wrapper, false otherwise]]--functionutil.isCoordTemplateOrWrapper(name)name=mw.text.trim(name)localinputTitle=mw.title.new(name,'Template')ifnotinputTitlethenreturnfalseend-- Create (or reuse) mw.title objects for each known coord template/wrapper.-- Stored in L10n.template.title so that they don't need to be recreated-- each time this function is calledifnotL10n.template.titlesthenL10n.template.titles={}for_,vinpairs(L10n.template.coord)dotable.insert(L10n.template.titles,mw.title.new(v,'Template'))endendfor_,templateTitleinpairs(L10n.template.titles)doifmw.title.equals(inputTitle,templateTitle)thenreturntrueendendreturnfalseend--[[Recursively extract coord templates which have a name parameter.@param {string} wikitext@returns {table} table sequence of coord templates]]--functionutil.extractCoordTemplates(wikitext)localoutput={}localtemplates=mw.ustring.gmatch(wikitext,'{%b{}}')localsubtemplates={}fortemplateintemplatesdolocaltemplateName=mw.ustring.match(template,'{{([^}|]+)')localnameParam=mw.ustring.match(template,"|%s*name%s*=%s*[^}|]+")ifutil.isCoordTemplateOrWrapper(templateName)thenifnameParamthentable.insert(output,template)endelseifmw.ustring.find(mw.ustring.sub(template,2),"{{")thenlocalsubOutput=util.extractCoordTemplates(mw.ustring.sub(template,2))for_,tinpairs(subOutput)dotable.insert(output,t)endendend-- ensure coords are not using title displayfork,vinpairs(output)dooutput[k]=mw.ustring.gsub(v,"|%s*display%s*=[^|}]+","|display=inline")endreturnoutputend--[[Gets all named coordiates from a page or a section of a page.@param {string|nil} page  Page name, or name#section, to get named coordinates  from. If the name is omitted, i.e. #section or nil or empty string, then  the current page will be used.@returns {table} sequence of {coord, name, description} tables where coord is  the coordinates in a format suitable for #util.parseCoords, name is a string,  and description is a string (coordinates in a format suitable for displaying  to the reader). If for some reason the name can't be found, the description  is nil and the name contains display-format coordinates.@throws {L10n.error.noNamedCoords} if no named coordinates are found.]]--functionutil.getNamedCoords(page)iftranscluder==nilthen-- load [[Module:Transcluder]] lazily so it is only transcluded on pages that-- actually use named coordinatestranscluder=require("Module:Transcluder")endlocalparts=mw.text.split(pageor"","#",true)localname=parts[1]==""andmw.title.getCurrentTitle().prefixedTextorparts[1]localsection=parts[2]localpageWikitext=transcluder.get(sectionandname.."#"..sectionorname)localcoordTemplates=util.extractCoordTemplates(pageWikitext)if#coordTemplates==0thenerror(string.format(L10n.error.noNamedCoords,pageorname),0)endlocalframe=mw.getCurrentFrame()localsep="________"localexpandedContent=frame:preprocess(table.concat(coordTemplates,sep))localexpandedTemplates=mw.text.split(expandedContent,sep)localnamedCoords={}for_,expandedTemplateinpairs(expandedTemplates)dolocalcoord=mw.ustring.match(expandedTemplate,"<span class=\"geo%-dec\".->(.-)</span>")ifcoordthenlocalname=(-- name specified by a wrapper template, e.g [[Article|Name]]mw.ustring.match(expandedTemplate,"<span class=\"mapframe%-coord%-name\">(.-)</span>")or-- name passed into coord templatemw.ustring.match(expandedTemplate,"<span class=\"fn org\">(.-)</span>")or-- default to the coordinates if the name can't be retrievedcoord)localdescription=name~=coordandcoordlocalcoord=mw.ustring.gsub(coord,"[° ]","_")table.insert(namedCoords,{coord=coord,name=name,description=description})endendif#namedCoords==0thenerror(string.format(L10n.error.noNamedCoords,pageorname),0)endreturnnamedCoordsend--[[Parse coordinate values from the params passed in a GeoHack url (such as//tools.wmflabs.org/geohack/geohack.php?pagename=Example&params=1_2_N_3_4_W_ or//tools.wmflabs.org/geohack/geohack.php?pagename=Example&params=1.23_S_4.56_E_ )or non-url string in the same format (such as `1_2_N_3_4_W_` or `1.23_S_4.56_E_`)@param {string} coords  string containing coordinates@returns {number, number} latitude, longitude]]--functionutil.parseCoords(coords)localcoordsPattifmw.ustring.find(coords,"params=",1,true)then-- prevent false matches from page name, e.g. ?pagename=Lorem_S._IpsumcoordsPatt='params=([_%.%d]+[NS][_%.%d]+[EW])'else-- not actually a geohack url, just the same formatcoordsPatt='[_%.%d]+[NS][_%.%d]+[EW]'endlocalparts=mw.text.split((mw.ustring.match(coords,coordsPatt)or''),'_')locallat_d=tonumber(parts[1])assert(lat_d,"Unable to get latitude from input '"..coords.."'.")locallat_m=tonumber(parts[2])-- nil if coords are in decimal formatlocallat_s=lat_mandtonumber(parts[3])-- nil if coords are either in decimal format or degrees and minutes onlylocallat=lat_d+(lat_mor0)/60+(lat_sor0)/3600ifparts[#parts/2]=='S'thenlat=lat*-1endlocallong_d=tonumber(parts[1+#parts/2])assert(long_d,"Unable to get longitude from input '"..coords.."'.")locallong_m=tonumber(parts[2+#parts/2])-- nil if coords are in decimal formatlocallong_s=long_mandtonumber(parts[3+#parts/2])-- nil if coords are either in decimal format or degrees and minutes onlylocallong=long_d+(long_mor0)/60+(long_sor0)/3600ifparts[#parts]=='W'thenlong=long*-1endreturnlat,longend--[[Get coordinates from a Wikidata item@param {string} item_id  Wikidata item id (Q number)@returns {number, number} latitude, longitude@throws {L10n.error.noCoords} if item_id is invalid or the item does not exist@throws {L10n.error.wikidataCoords} if the the item does not have a P625  statement (coordinates), or it is set to "no value"]]--functionutil.wikidataCoords(item_id)ifnot(item_idandmw.wikibase.isValidEntityId(item_id)andmw.wikibase.entityExists(item_id))thenerror(L10n.error.noCoords,0)endlocalcoordStatements=mw.wikibase.getBestStatements(item_id,'P625')ifnotcoordStatementsor#coordStatements==0thenerror(L10n.error.wikidataCoords,0)endlocalhasNoValue=(coordStatements[1].mainsnakand(coordStatements[1].mainsnak.snaktype=='novalue'orcoordStatements[1].mainsnak.snaktype=='somevalue'))ifhasNoValuethenerror(L10n.error.wikidataCoords,0)endlocalwdCoords=coordStatements[1]['mainsnak']['datavalue']['value']returntonumber(wdCoords['latitude']),tonumber(wdCoords['longitude'])end--[[Creates a polygon that approximates a circle@param {number} lat  Latitude@param {number} long  Longitude@param {number} radius  Radius in metres@param {number} n  Number of edges for the polygon@returns {table} sequence of {latitude, longitude} table sequences, where  latitude and longitude are both numbers]]--functionutil.circleToPolygon(lat,long,radius,n)-- n is number of edges-- Based on https://github.com/gabzim/circle-to-polygon, ISC licencelocalfunctionoffset(cLat,cLon,distance,bearing)locallat1=math.rad(cLat)locallon1=math.rad(cLon)localdByR=distance/6378137-- distance divided by 6378137 (radius of the earth) wgs84locallat=math.asin(math.sin(lat1)*math.cos(dByR)+math.cos(lat1)*math.sin(dByR)*math.cos(bearing))locallon=lon1+math.atan2(math.sin(bearing)*math.sin(dByR)*math.cos(lat1),math.cos(dByR)-math.sin(lat1)*math.sin(lat))return{math.deg(lon),math.deg(lat)}endlocalcoordinates={};locali=0;whilei<ndotable.insert(coordinates,offset(lat,long,radius,(2*math.pi*i*-1)/n))i=i+1endtable.insert(coordinates,offset(lat,long,radius,0))returncoordinatesend--[[Get the number of key-value pairs in a table, which might not be a sequence.@param {table} t@returns {number} count of key-value pairs]]--functionutil.tableCount(t)localcount=0fork,vinpairs(t)docount=count+1endreturncountend--[[For a table where the values are all tables, returns either the util.tableCountof the subtables if they are all the same, or nil if they are not all the same.@param {table} t@returns {number|nil} count of key-value pairs of subtable, or nil if subtables  have different counts]]--functionutil.subTablesCount(t)localcount=nilfork,vinpairs(t)doifcount==nilthencount=util.tableCount(v)elseifcount~=util.tableCount(v)thenreturnnilendendreturncountend--[[Splits a list into a table sequence. The items in the list may be separated bycommas, or by semicolons (if items may contain commas), or by "###" (if itemsmay contain semicolons).@param {string} listString@returns {table} sequence of list items]]--functionutil.tableFromList(listString)iftype(listString)~="string"orlistString==""thenreturnnilendlocalseparator=(mw.ustring.find(listString,"###",0,true)and"###")or(mw.ustring.find(listString,";",0,true)and";")or","localpattern="%s*"..separator.."%s*"returnmw.text.split(listString,pattern)end-- Boolean in outer scope indicating if Kartographer should be able to-- automatically calculate coordinates (see phab:T227402)localcoordsDerivedFromFeatures=false;--[[---------------------------------------------------------------------------- Make methods: These take in a table of arguments, and return either a string or a table to be used in the eventual output.----------------------------------------------------------------------------]]--localmake={}--[[Makes content to go inside the maplink or mapframe tag.@param {table} args@returns {string} tag content]]--functionmake.content(args)ifutil.getParameterValue(args,'raw')thencoordsDerivedFromFeatures=true-- Kartographer should be able to automatically calculate coords from raw geoJSONreturnutil.getParameterValue(args,'raw')endlocalcontent={}localargsExpanded={}fork,vinpairs(args)dolocalindex=string.match(k,'^[^0-9]+([0-9]*)$')ifindex~=nilthenlocalindexNumber=''ifindex~=''thenindexNumber=tonumber(index)elseindexNumber=1endifargsExpanded[indexNumber]==nilthenargsExpanded[indexNumber]={}endargsExpanded[indexNumber][string.gsub(k,index,'')]=vendendforcontentIndex,contentArgsinpairs(argsExpanded)dolocalargType=util.getParameterValue(contentArgs,"type")-- Kartographer automatically calculates coords if geolines/shapes are used (T227402)ifnotcoordsDerivedFromFeaturesthencoordsDerivedFromFeatures=(argType==L10n.str.lineorargType==L10n.str.shape)andtrueorfalseendifargType==L10n.str.namedthenlocalnamedCoords=util.getNamedCoords(util.getParameterValue(contentArgs,"from"))localtypeKey=type(L10n.para.type)=="table"andL10n.para.type[1]orL10n.para.typelocalcoordKey=type(L10n.para.coord)=="table"andL10n.para.coord[1]orL10n.para.coordlocaltitleKey=type(L10n.para.title)=="table"andL10n.para.title[1]orL10n.para.titlelocaldescKey=type(L10n.para.description)=="table"andL10n.para.description[1]orL10n.para.descriptionfor_,namedCoordinpairs(namedCoords)docontentArgs[typeKey]="point"contentArgs[coordKey]=namedCoord.coordcontentArgs[titleKey]=namedCoord.namecontentArgs[descKey]=namedCoord.descriptioncontent[#content+1]=make.contentJson(contentArgs)endelsecontent[#content+1]=make.contentJson(contentArgs)endend--Single item, no array neededif#content==1thenreturncontent[1]end--Multiple items get placed in a FeatureCollectionlocalcontentArray='[\n'..table.concat(content,',\n')..'\n]'returncontentArrayend--[[Make coordinates from the coord arg, or the id arg, or the current page'sWikidata item.@param {table} args@param {boolean} [plainOutput]@returns {Mixed} Either:  {number, number} latitude, longitude  if plainOutput is true; or  {table} table sequence of longitude, then latitude (gives the required format   for GeoJSON when encoded)]]--functionmake.coords(args,plainOutput)localcoords,lat,longlocalframe=mw.getCurrentFrame()ifutil.getParameterValue(args,'coord')thencoords=frame:preprocess(util.getParameterValue(args,'coord'))lat,long=util.parseCoords(coords)elselat,long=util.wikidataCoords(util.getParameterValue(args,'id')ormw.wikibase.getEntityIdForCurrentPage())endifplainOutputthenreturnlat,longendreturn{[0]=long,[1]=lat}end--[[Makes a table of coordinates that approximate a circle.@param {table} args@returns {table} sequence of {latitude, longitude} table sequences, where  latitude and longitude are both numbers@throws {L10n.error.noCircleCoords} if centre coordinates are not specified@throws {L10n.error.noRadius} if radius is not specified@throws {L10n.error.negativeRadius} if radius is negative or zero@throws {L10n.error.negativeEdges} if edges is negative or zero]]--functionmake.circleCoords(args)locallat,long=make.coords(args,true)localradius=util.getParameterValue(args,'radius')ifnotradiusthenradius=util.getParameterValue(args,'radiusKm')andtonumber(util.getParameterValue(args,'radiusKm'))*1000ifnotradiusthenradius=util.getParameterValue(args,'radiusMi')andtonumber(util.getParameterValue(args,'radiusMi'))*1609.344ifnotradiusthenradius=util.getParameterValue(args,'radiusFt')andtonumber(util.getParameterValue(args,'radiusFt'))*0.3048endendendlocaledges=util.getParameterValue(args,'edges')orL10n.defaults.edgesifnotlatornotlongthenerror(L10n.error.noCircleCoords,0)elseifnotradiusthenerror(L10n.error.noRadius,0)elseiftonumber(radius)<=0thenerror(L10n.error.negativeRadius,0)elseiftonumber(edges)<=0thenerror(L10n.error.negativeEdges,0)endreturnutil.circleToPolygon(lat,long,radius,tonumber(edges))end--[[Makes JSON data for a feature@param contentArgs  args for this feature. Keys must be the non-suffixed version  of the parameter names, i.e. use type, stroke, fill,... rather than type3,  stroke3, fill3,...@returns {string} JSON encoded data]]--functionmake.contentJson(contentArgs)localdata={}ifutil.getParameterValue(contentArgs,'type')==L10n.str.pointorutil.getParameterValue(contentArgs,'type')==L10n.str.circlethenlocalisCircle=util.getParameterValue(contentArgs,'type')==L10n.str.circledata.type="Feature"data.geometry={type=isCircleand"LineString"or"Point",coordinates=isCircleandmake.circleCoords(contentArgs)ormake.coords(contentArgs)}data.properties={title=util.getParameterValue(contentArgs,'title')ormw.getCurrentFrame():getParent():getTitle()}ifisCirclethen-- TODO: This is very similar to below, should be extracted into a functiondata.properties.stroke=util.getParameterValue(contentArgs,'strokeColor')orL10n.defaults.strokeColordata.properties["stroke-width"]=tonumber(util.getParameterValue(contentArgs,'strokeWidth'))orL10n.defaults.strokeWidthlocalstrokeOpacity=util.getParameterValue(contentArgs,'strokeOpacity')ifstrokeOpacitythendata.properties['stroke-opacity']=tonumber(strokeOpacity)endlocalfill=util.getParameterValue(contentArgs,'fill')iffillthendata.properties.fill=filllocalfillOpacity=util.getParameterValue(contentArgs,'fillOpacity')data.properties['fill-opacity']=fillOpacityandtonumber(fillOpacity)or0.6endelse-- is a pointlocalmarkerSymbol=util.getParameterValue(contentArgs,'marker')orL10n.defaults.marker-- allow blank to be explicitly specified, for overriding infoboxes or other templates with a default valueifmarkerSymbol~="blank"thendata.properties["marker-symbol"]=markerSymbolenddata.properties["marker-color"]=util.getParameterValue(contentArgs,'markerColor')orL10n.defaults.markerColordata.properties["marker-size"]=util.getParameterValue(contentArgs,'markerSize')orL10n.defaults.markerSizeendelsedata.type="ExternalData"ifutil.getParameterValue(contentArgs,'type')==L10n.str.dataorutil.getParameterValue(contentArgs,'from')thendata.service="page"elseifutil.getParameterValue(contentArgs,'type')==L10n.str.linethendata.service="geoline"elseifutil.getParameterValue(contentArgs,'type')==L10n.str.shapethendata.service="geoshape"elseifutil.getParameterValue(contentArgs,'type')==L10n.str.shapeInversethendata.service="geomask"endifutil.getParameterValue(contentArgs,'id')or(not(util.getParameterValue(contentArgs,'from'))andmw.wikibase.getEntityIdForCurrentPage())thendata.ids=util.getParameterValue(contentArgs,'id')ormw.wikibase.getEntityIdForCurrentPage()elsedata.title=util.getParameterValue(contentArgs,'from')enddata.properties={stroke=util.getParameterValue(contentArgs,'strokeColor')orL10n.defaults.strokeColor,["stroke-width"]=tonumber(util.getParameterValue(contentArgs,'strokeWidth'))orL10n.defaults.strokeWidth}localstrokeOpacity=util.getParameterValue(contentArgs,'strokeOpacity')ifstrokeOpacitythendata.properties['stroke-opacity']=tonumber(strokeOpacity)endlocalfill=util.getParameterValue(contentArgs,'fill')iffilland(data.service=="geoshape"ordata.service=="geomask")thendata.properties.fill=filllocalfillOpacity=util.getParameterValue(contentArgs,'fillOpacity')iffillOpacitythendata.properties['fill-opacity']=tonumber(fillOpacity)endendenddata.properties.title=util.getParameterValue(contentArgs,'title')ormw.title.getCurrentTitle().textifutil.getParameterValue(contentArgs,'description')thendata.properties.description=util.getParameterValue(contentArgs,'description')endreturnmw.text.jsonEncode(data)end--[[Makes attributes for the maplink or mapframe tag.@param {table} args@param {boolean} [isTitle]  Tag is to be displayed in the title of page rather  than inline@returns {table<string,string>} key-value pairs of attribute names and values]]--functionmake.tagAttribs(args,isTitle)localattribs={}ifutil.getParameterValue(args,'zoom')thenattribs.zoom=util.getParameterValue(args,'zoom')endifutil.isDeclined(util.getParameterValue(args,'icon'))thenattribs.class="no-icon"endifutil.getParameterValue(args,'type')==L10n.str.pointandnotcoordsDerivedFromFeaturesthenlocallat,long=make.coords(args,'plainOutput')attribs.latitude=tostring(lat)attribs.longitude=tostring(long)endifutil.isAffirmed(util.getParameterValue(args,'frame'))andnot(isTitle)thenattribs.width=util.getParameterValue(args,'frameWidth')orL10n.defaults.frameWidthattribs.height=util.getParameterValue(args,'frameHeight')orL10n.defaults.frameHeightifutil.getParameterValue(args,'frameCoordinates')thenlocalframeLat,frameLong=util.parseCoords(util.getParameterValue(args,'frameCoordinates'))attribs.latitude=frameLatattribs.longitude=frameLongelseifutil.getParameterValue(args,'frameLatitude')thenattribs.latitude=util.getParameterValue(args,'frameLatitude')endifutil.getParameterValue(args,'frameLongitude')thenattribs.longitude=util.getParameterValue(args,'frameLongitude')endendifnotattribs.latitudeandnotattribs.longitudeandnotcoordsDerivedFromFeaturesthenlocalsuccess,lat,long=pcall(util.wikidataCoords,util.getParameterValue(args,'id')ormw.wikibase.getEntityIdForCurrentPage())ifsuccessthenattribs.latitude=tostring(lat)attribs.longitude=tostring(long)endendifutil.getParameterValue(args,'frameAlign')thenattribs.align=util.getParameterValue(args,'frameAlign')endifutil.isAffirmed(util.getParameterValue(args,'plain'))thenattribs.frameless="1"elseattribs.text=util.getParameterValue(args,'text')orL10n.defaults.textendelseattribs.text=util.getParameterValue(args,'text')orL10n.defaults.textendreturnattribsend--[[Makes maplink wikitext that will be located in the top-right of the title of thepage (the same place where coords with |display=title are positioned).@param {table} args@param {string} tagContent  Content for the maplink tag@returns {string}]]--functionmake.titleOutput(args,tagContent)localtitleTag=mw.text.tag('maplink',make.tagAttribs(args,true),tagContent)localspanAttribs={style="font-size: small;",id="mapframe-coordinates"}localindicatorContent=mw.text.tag('span',spanAttribs,titleTag)returnmw.getCurrentFrame():extensionTag{name="indicator",content=indicatorContent,args={name="zzz-mapframe"--zzz: show as last indicator}}end--[[Makes maplink or mapframe wikitext that will be located inline.@param {table} args@param {string} tagContent  Content for the maplink tag@returns {string}]]--functionmake.inlineOutput(args,tagContent)localtagName='maplink'ifutil.getParameterValue(args,'frame')thentagName='mapframe'endreturnmw.text.tag(tagName,make.tagAttribs(args),tagContent)end--[[Makes the HTML required for the swicther to work, including the templatestylestag.@param {table} params  table sequence of {map, label} tables  @param {string} params{}.map  Wikitext for mapframe map  @param {string} params{}.label  Label text for swicther option@param {table} options  @param {string} options.alignment  "left" or "center" or "right"  @param {boolean} options.isThumbnail  Display in a thumbnail  @param {string} options.width  Width of frame, e.g. "200"  @param {string} [options.caption]  Caption wikitext for thumnail@retruns {string} swicther HTML]]--functionmake.switcherHtml(params,options)options=optionsor{}localframe=mw.getCurrentFrame()localstyles=frame:extensionTag{name="templatestyles",args={src="Template:Maplink/styles-multi.css"}}localcontainer=mw.html.create("div"):addClass("switcher-container"):addClass("mapframe-multi-container")ifoptions.alignment=="left"oroptions.alignment=="right"thencontainer:addClass("float"..options.alignment)else-- alignment is "center"container:addClass("center")endfori=1,#paramsdocontainer:tag("div"):wikitext(params[i].map):tag("span"):addClass("switcher-label"):css("display","none"):wikitext(mw.text.trim(params[i].label))endifnotoptions.isThumbnailthenreturnstyles..tostring(container)endlocalclasslist=container:getAttr("class")classlist=mw.ustring.gsub(classlist,"%a*"..options.alignment,"")container:attr("class",classlist)localouterCountainer=mw.html.create("div"):addClass("mapframe-multi-outer-container"):addClass("mw-kartographer-container"):addClass("thumb")ifoptions.alignment=="left"oroptions.alignment=="right"thenouterCountainer:addClass("t"..options.alignment)else-- alignment is "center"outerCountainer:addClass("tnone"):addClass("center")endouterCountainer:tag("div"):addClass("thumbinner"):css("width",options.width.."px"):node(container):node(options.captionandmw.html.create("div"):addClass("thumbcaption"):wikitext(options.caption))returnstyles..tostring(outerCountainer)end--[[Makes the HTML required for an overlay map to worktag.@param {string} overlayMap  wikitext for the overlay map@param {string} baseMap  wikitext for the base map@param {table} options  various styling/display options  @param {string} options.align  "left" or "center" or "right"  @param {string|number} options.width  Width of the base map, e.g. "300"  @param {string|number} options.width  Height of the base map, e.g. "200"  @param {string} options.border  Border style for the overlayed map, e.g. "1px solid white"  @param {string} options.horizontalAlignment  Horizontal alignment for overlay map, "left" or "right"  @param {string|number} options.horizontalOffset  Horizontal offset in pixels from the alignment edge, e.g "10"  @param {string} options.verticalAlignment  Vertical alignment for overlay map, "top" or "bottom"  @param {string|number} options.verticalOffset  Vertical offset in pixels from the alignment edge, e.g. is "10"  @param {boolean} options.isThumbnail  Display in a thumbnail  @param {string} [options.caption]  Caption wikitext for thumnail@retruns {string} HTML for basemap with overlay]]--functionmake.overlayHtml(overlayMap,baseMap,options)options=optionsor{}localcontainerFloatClass="float"..(options.alignor"none")ifoptions.align=="center"thencontainerFloatClass="center"endlocalcontainerStyle={position="relative",width=options.width.."px",height=options.height.."px",overflow="hidden"-- mobile/minerva tends to add scrollbars for a couple of pixels}ifoptions.align=="center"thencontainerStyle["margin-left"]="auto"containerStyle["margin-right"]="auto"endlocalcontainer=mw.html.create("div"):addClass("mapframe-withOverlay-container"):addClass(containerFloatClass):addClass("noresize"):css(containerStyle)localoverlayStyle={position="absolute",["z-index"]="1",border=options.borderor"1px solid white"}ifoptions.horizontalAlignment=="right"thenoverlayStyle.right=options.horizontalOffset.."px"elseoverlayStyle.left=options.horizontalOffset.."px"endifoptions.verticalAlignment=="bottom"thenoverlayStyle.bottom=options.verticalOffset.."px"elseoverlayStyle.top=options.verticalOffset.."px"endlocaloverlayDiv=mw.html.create("div"):css(overlayStyle):wikitext(overlayMap)container:node(overlayDiv):wikitext(baseMap)ifnotoptions.isThumbnailthenreturntostring(container)endlocalclasslist=container:getAttr("class")classlist=mw.ustring.gsub(classlist,"%a*"..options.align,"")container:attr("class",classlist)localouterCountainer=mw.html.create("div"):addClass("mapframe-withOverlay-outerContainer"):addClass("mw-kartographer-container"):addClass("thumb")ifoptions.align=="left"oroptions.align=="right"thenouterCountainer:addClass("t"..options.align)else-- alignment is "center"outerCountainer:addClass("tnone"):addClass("center")endouterCountainer:tag("div"):addClass("thumbinner"):css("width",options.width.."px"):node(container):node(options.captionandmw.html.create("div"):addClass("thumbcaption"):wikitext(options.caption))returntostring(outerCountainer)end--[[---------------------------------------------------------------------------- Package to be exported, i.e. methods which will available to templates and other modules.----------------------------------------------------------------------------]]--localp={}-- Entry point for templatesfunctionp.main(frame)localparent=frame.getParent(frame)-- Check for overlay optionlocaloverlay=util.getParameterValue(parent.args,'overlay')localhasOverlay=overlayandmw.text.trim(overlay)~=""-- Check for switch optionlocalswitch=util.getParameterValue(parent.args,'switch')localisMulti=switchandmw.text.trim(switch)~=""-- Create output by choosing method to suit optionslocaloutputifhasOverlaythenoutput=p.withOverlay(parent.args)elseifisMultithenoutput=p.multi(parent.args)elseoutput=p._main(parent.args)end-- Preprocess output before returning itreturnframe:preprocess(output)end-- Entry points for modulesfunctionp._main(_args)localargs=util.trimArgs(_args)localtagContent=make.content(args)localdisplay=mw.text.split(util.getParameterValue(args,'display')orL10n.defaults.display,'%s*'..L10n.str.dsep..'%s*')localdisplayInTitle=display[1]==L10n.str.titleordisplay[2]==L10n.str.titlelocaldisplayInline=display[1]==L10n.str.inlineordisplay[2]==L10n.str.inlinelocaloutputifdisplayInTitleanddisplayInlinethenoutput=make.titleOutput(args,tagContent)..make.inlineOutput(args,tagContent)elseifdisplayInTitlethenoutput=make.titleOutput(args,tagContent)elseifdisplayInlinethenoutput=make.inlineOutput(args,tagContent)elseerror(L10n.error.badDisplayPara)endreturnoutputendfunctionp.multi(_args)localargs=util.trimArgs(_args)ifnotargs[L10n.para.switch]thenerror(L10n.error.noSwitchPara,0)endlocalswitchParamValue=util.getParameterValue(args,'switch')localswitchLabels=util.tableFromList(switchParamValue)if#switchLabels==1thenerror(L10n.error.oneSwitchLabel,0)endlocalmapframeArgs={}localswitchParams={}forname,valinpairs(args)do-- Copy to mapframeArgs, if not the switch labels or a switch parameterifval~=switchParamValueandnotstring.match(val,"^"..L10n.str.switch..":")thenmapframeArgs[name]=valend-- Check if this is a param to switch. If so, store the name and switch-- values in switchParams table.localswitchList=string.match(val,"^"..L10n.str.switch..":(.+)")ifswitchList~=nilthenlocalvalues=util.tableFromList(switchList)if#values==1thenerror(string.format(L10n.error.oneSwitchValue,name),0)endswitchParams[name]=valuesendendifutil.tableCount(switchParams)==0thenerror(L10n.error.noSwitchLists,0)endlocalswitchCount=util.subTablesCount(switchParams)ifnotswitchCountthenerror(L10n.error.switchMismatches,0)elseifswitchCount>#switchLabelsthenerror(string.format(L10n.error.fewerSwitchLabels,switchCount,#switchLabels),0)end-- Ensure a plain frame will be used (thumbnail will be built by the-- make.switcherHtml function if required, so that switcher options are-- inside the thumnail)mapframeArgs.plain="yes"localswitcher={}fori=1,switchCountdolocallabel=switchLabels[i]forname,valuesinpairs(switchParams)domapframeArgs[name]=values[i]endtable.insert(switcher,{map=p._main(mapframeArgs),label="Show "..label})endreturnmake.switcherHtml(switcher,{alignment=args["frame-align"]or"right",isThumbnail=(args.frameandnotargs.plain)andtrueorfalse,width=args["frame-width"]orL10n.defaults.frameWidth,caption=args.text})endfunctionp.withOverlay(_args)-- Get and trim wikitext for overlay maplocaloverlayMap=_args.overlayiftype(overlayMap)=='string'thenoverlayMap=overlayMap:match('^%s*(.-)%s*$')endlocalisThumbnail=(util.getParameterValue(_args,"frame")andnotutil.getParameterValue(_args,"plain"))andtrueorfalse-- Get base map using the _main function, as a plain maplocalargs=util.trimArgs(_args)args.plain="yes"localbasemap=p._main(args)-- Extract overlay options from argslocaloverlayOptions={width=util.getParameterValue(args,"frameWidth")orL10n.defaults.frameWidth,height=util.getParameterValue(args,"frameHeight")orL10n.defaults.frameHeight,align=util.getParameterValue(args,"frameAlign")orL10n.defaults.frameAlign,border=util.getParameterValue(args,"overlayBorder")orL10n.defaults.overlayBorder,horizontalAlignment=util.getParameterValue(args,"overlayHorizontalAlignment")orL10n.defaults.overlayHorizontalAlignment,horizontalOffset=util.getParameterValue(args,"overlayHorizontalOffset")orL10n.defaults.overlayHorizontalOffset,verticalAlignment=util.getParameterValue(args,"overlayVerticalAlignment")orL10n.defaults.overlayVerticalAlignment,verticalOffset=util.getParameterValue(args,"overlayVerticalOffset")orL10n.defaults.overlayVerticalOffset,isThumbnail=isThumbnail,caption=util.getParameterValue(args,"text")orL10n.defaults.text}-- Make the HTML for the overlaying mapsreturnmake.overlayHtml(overlayMap,basemap,overlayOptions)endreturnp
Retrieved from "https://en.wikipedia.org/w/index.php?title=Module:Mapframe&oldid=1297723839"
Category:
Hidden categories:

[8]ページ先頭

©2009-2025 Movatter.jp