Interested Article - CategoryMap

Документация
local p = {}

local getSelectors = function( frame )
	local categoryQid = mw.wikibase.getEntityIdForCurrentPage()
	local statement = mw.wikibase.getBestStatements( categoryQid, 'P4224' )[ 1 ]
	
	if not statement then
		return nil
	end

	local selectors = { 'wdt:P31/wdt:P279* wd:' .. statement[ 'mainsnak' ][ 'datavalue' ][ 'value' ][ 'id' ] }
	for property, qualifier in pairs( statement[ 'qualifiers' ] ) do
		if property == 'P131' then
			property = 'P131/wdt:P131*'
		end
		table.insert( selectors, 'wdt:' .. property .. ' wd:' .. qualifier[ 1 ][ 'datavalue' ][ 'value' ][ 'id' ] )
	end
	
	return selectors
end

local getShapesQuery = function( selectors )
	local query = [[
		SELECT (?item as ?id)
		WHERE { ?item ]] .. table.concat( selectors, ';' ) .. [[ . }
		GROUP BY ?item
	]]
	return string.gsub( query, "%s+", ' ' )
end

local getPointsQuery = function( selectors )
	local query = [[
		SELECT
			(?item as ?id)
			?geo
			(IF(BOUND(?link), CONCAT('[', '[w:ru:', SUBSTR(STR(?link),31,400), '{{!}}', ?itemLabel, ']', ']'), CONCAT(?itemLabel, '<sup>[', '[d:', SUBSTR(STR(?item),32,400), '{{!}}&lbrack;d&rbrack;]', ']</sup>')) AS ?title)
			(CONCAT(?itemDesc, IF(BOUND(?img), CONCAT('\\n[', '[File:', SUBSTR(STR(?img), 52, 400), '{{!}}200x150px]', ']'), '')) AS ?description)
		WHERE {
			?item ]] .. table.concat( selectors, ';' ) .. [[;
				wdt:P625 ?geo .
			OPTIONAL { ?item wdt:P18 ?img . } .
			OPTIONAL { ?link schema:about ?item . ?link schema:isPartOf <https://ru.wikipedia.org/> . } .
			SERVICE wikibase:label {
				bd:serviceParam wikibase:language 'ru,en' .
				?item rdfs:label ?itemLabel .
				?item schema:description ?itemDesc .
			}
		}
		GROUP BY ?item ?geo ?img ?link ?itemLabel ?itemDesc
	]]
	return string.gsub( query, "%s+", ' ' )
end

p.main = function( frame )
	local selectors = getSelectors( frame )
	if not selectors then
		return ''
	end

	local shapesQuery = getShapesQuery( selectors )
	local mapContent = [[
		{
			"type": "ExternalData",
			"service": "geoshape",
			"query": "]] .. shapesQuery .. [[",
			"properties": {
				"fill": "#FF0000",
				"fill-opacity": 0.1,
				"stroke": "#FF9999"
			}
		},
		{
			"type": "ExternalData",
			"service": "geoline",
			"query": "]] .. shapesQuery .. [[",
			"properties": {
				"stroke": "#FF9999"
			}
		},
		{
			"type": "ExternalData",
			"service": "geopoint",
			"query": "]] .. getPointsQuery( selectors ) .. [[",
			"properties": {
			    "marker-size": "small",
			    "marker-color": "#3366cc"
			}
		}
	]]

	return frame:extensionTag{
		name = 'mapframe',
		content = '[' .. mapContent .. ']',
		args = {
			align = 'left',
			width = 500,
			height = 300,
		}
	}
end

return p
Источник —

Same as CategoryMap