Module:Mapa
local function Infobox(builder, standardMap, frame) local width = 240
local function map(name, mandatory) local result = standardMap[name] if not result and mandatory then result = "{{{"..name.."}}}" end
return result end
builder:wikitext( '{| class="infobox" cellpadding="0"\n', "|-\n", '| colspan="2" style="font-weight:bold; text-align:center; color:grey;" | Mapa lokalizacyjna ', map("dopełniacz", true) ):tag("br"):done():wikitext( "Mapa lokalizacyjna ", map("dopełniacz", true), "\n" )
if not map("bez mapy świata") then local worldMap = mw.loadData("Module:Mapa/dane/świat") local reliefInfo = worldMap[1]["dopełniacz"] or "świata" local reliefImage = worldMap[1]["mapa"] or "World location map.svg" local relief = builder:wikitext( "|-\n", '| colspan="2" style="font-weight:bold; text-align:center; color:grey; border-top:1px solid #aaa;" | Położenie na mapie ', reliefInfo ):tag("br"):done() :tag("div") :addClass("mapa-lokalizacyjna") :css({ margin ="0 auto", width = tostring(width + 2).."px", padding = "3px" }) :tag("div") :css({ position = "relative", border = "0 solid #aaa", padding = "0", width = tostring(width).."px" }) :wikitext("Mapa lokalizacyjna ", reliefInfo, "") local border = "1px solid "..(map("x") and "green" or "red") local top = tostring(map("top")/-1.8+50).."%" local bottom = tostring(map("bottom")/1.8+50).."%" local left = tostring(map("left")/3.6+50).."%" local right = tostring(map("right")/-3.6+50).."%" relief:tag("div") :css({ border = border, position = "absolute", top = top, bottom = bottom, left = left, right = map("left") >= map("right") and "-1px" or right, }) if map("left") >= map("right") then relief:tag("div") :css({ border = border, position = "absolute", top = top, bottom = bottom, left = "-1px", right = right, }) end if map("x") then builder:tag("span") :css({ ["font-style"] = "italic", ["font-weight"] = "normal", }) :wikitext("Zaznaczone granice mają charakter jedynie orientacyjny.") end builder:wikitext("\n") end
local templateName = map("szablon") or map("nazwa alias") or map("link alias") local templateNameVariant = templateName if templateName == "Jugosławia" then templateNameVariant = "złożona" end if templateName then local template = mw.title.new("Szablon:państwo dane "..templateName) if template and template.exists then builder :wikitext( "|-\n", '! colspan="2" | ', "Szablon odpowiada jednostce administracyjnej zdefiniowanej w szablonie" ) :tag("br"):done() :wikitext(frame:expandTemplate{ title = "s", args = { template.text }}, "\n") :wikitext(frame:expandTemplate{ title = "infobox państwo dodaj", args = { templateName, wariant=templateNameVariant }}, "\n") end end
if map("globe") ~= nil then builder:wikitext( "|-\n", "! Opcja „globe” dla geohack\n", "| ", map("globe") or "nie linkuje", "\n" ) end
if map("dokładność") then builder:wikitext( "|-\n", "! Opcja „dokładność” dla ", frame:expandTemplate{ title = "s", args = { "współrzędne" }}, "\n", "| ", map("dokładność"), "\n" ) end
if map("ikona") then builder:wikitext( "|-\n", "! Opcja „ikona” dla współrzędnych\n", "| ", map("ikona"), "\n" ) end
local parent = map("nadrzędna") local parentHeader = "Mapą nadrzędną dla tej mapy" while parent do local c = mw.title.getCurrentTitle() local parentTitle = mw.title.new(c.baseText.."/"..parent, c.nsText) local parentMap = false if parentTitle.exists then local s, m = pcall(mw.loadData, parentTitle.fullText) if s and (type(m[1]) == "table") then parentMap = m end end
builder:wikitext( "|-\n", '| colspan="2" style="font-weight:bold; text-align:center; color:grey; border-top:1px solid #aaa;" | ' ) if parentMap then local d = parentMap[1]["dopełniacz"] or "{Template:Dopełniacz" local p = parentMap[1]["mapa"] or "{{{mapa}}}" builder:wikitext( parentHeader ):tag("br"):done():wikitext( "jest mapa ", d )
if map("x") or parentMap[1].x then builder:tag("br"):done():wikitext("Mapa lokalizacyjna ", d, "\n") else -- mapa z ramką local function getX(longitude, left, right) if longitude == left then return 0 elseif longitude == right then return 100 end
local width = (right - left) % 360 if width == 0 then width = 360 end local distanceFromLeft = (longitude - left) % 360 -- the distance needed past the map to the right equals distanceFromLeft - width. the distance needed past the map to the left equals 360 - distanceFromLeft. to minimize page stretching, go whichever way is shorter if distanceFromLeft - width / 2 >= 180 then distanceFromLeft = distanceFromLeft - 360 end return 100 * distanceFromLeft / width end
local function getY(latitude, top, bottom) return 100 * (top - latitude) / (top - bottom) end
local r = builder:tag("div") :addClass("mapa-lokalizacyjna") :css({ margin ="0 auto", width = tostring(width + 2).."px", padding = "3px" }) :tag("div") :css({ position = "relative", border = "0 solid #aaa", padding = "0", width = tostring(width).."px" }) :wikitext("Mapa lokalizacyjna ", d, "") local border = "1px solid "..(map("x") and "green" or "red") local top = tostring(getY(map("top"), parentMap[1].top, parentMap[1].bottom)).."%" local bottom = tostring(100-getY(map("bottom"), parentMap[1].top, parentMap[1].bottom)).."%" local left = tostring(getX(map("left"), parentMap[1].left, parentMap[1].right)).."%" local right = tostring(100-getX(map("right"), parentMap[1].left, parentMap[1].right)).."%" r:tag("div") :css({ border = border, position = "absolute", top = top, bottom = bottom, left = left, right = right, }) builder:wikitext("\n")
end parent = parentMap[1]["nadrzędna"] parentHeader = "Kolejną nadrzędną" else builder :wikitext( "Mapa nadrzędna nie istnieje\n" ) parent = false end end
local linkAlias = map("link alias")
if linkAlias and (#linkAlias > 0) then
builder:wikitext(
"|-\n",
'! colspan="2" | Wykorzystanie\n',
"|-\n",
'| colspan="2" style="vertical-align:top; text-align:center;" | Infoboksy
Mapy lokalizacyjne\n"
)
end
builder:wikitext( "|-\n", "|}\n" ) end
local function StandardParameters(builder, standardMap) builder:wikitext("== Parametry standardowe ==\n") local wikitable = builder:tag("table") :addClass("wikitable") :tag("tr") :tag("th"):wikitext("nazwa parametru"):done() :tag("th"):wikitext("wartość"):done() :tag("th"):wikitext("wynik"):done() :done()
local function appendRow(paramName, mandatory, description) local value = standardMap[paramName] if value or mandatory then local tr = wikitable:tag("tr") tr:tag("td"):tag("tt"):wikitext(paramName) if value then tr:tag("td"):tag("tt"):wikitext(value) else tr:tag("td"):tag("span"):css("color", "red"):wikitext("niezdefiniowany!") value = "{{{"..paramName.."}}}" end tr:tag("td"):wikitext(mw.ustring.format(description, value)) end end
appendRow("link alias", true, "Główny artykuł (%s)") appendRow("nazwa alias", false, "Skrócona nazwa (do wyświetlania) o ile różna od nazwy artykułu") appendRow("dopełniacz", true, "Dopełniacz nazwy, używany np. do generowania różnych nazw tj. Mapa %s.") appendRow("skrót", false, "Skrót ISO 3166-1 alfa-3 lub ISO 3166-2.") appendRow("nadrzędna", false, "Nazwa mapy nadrzędnej, umieszczonej w module Moduł:Mapa/dane/%s.")
builder:wikitext("\n") end
local function makeMap(map, default, source) return function(name) return name == nil and source or (map[name] or default[name]) end end
local function Map(builder, map, variant, example) builder:wikitext('{| class="wikitable" style="text-align:center; width:700px;"\n') if variant then builder:wikitext('! colspan="4" style="color:blue; font-weight:bold;" | wariant=', variant, '\n') end builder:wikitext( "|-\n", '| colspan="4" | Mapa lokalizacyjna ", map("dopełniacz"), "\n", "|-\n", '| colspan="4" | ' ):tag("code"):wikitext("", map("mapa"), ""):done():wikitext( "\n", "|-\n" ) if map("x") then builder:wikitext( '! colspan="4" | Współrzędne nieliniowe\n', "|-\n", '| colspan="4" style="text-align:left;" | x = ', map("x"), "\n", "|-\n", '| colspan="4" style="text-align:left;" | y = ', map("y"), "\n" ) else builder:wikitext( '! colspan="4" | Współrzędne graniczne\n', "|-\n", "|\n", '| colspan="2" | ', map("top"), "\n", "|\n", "|-\n", '| style="width:33%;" | ', map("left"), "\n", '| style="width:34%;" colspan="2" | ←↕→\n', '| style="width:33%;" | ', map("right"), "\n", "|-\n", "|\n", '| colspan="2" | ', map("bottom"), "\n", "|\n" ) end
if map("right") and map("left") and (map("right") < map("left")) then builder:wikitext( "|-\n", '| colspan="4" | ', "UWAGA! Szablon przekracza południk 180°\n" ) end
if example then builder:wikitext( "|-\n", '! colspan="4" | Przykład\n', "|-\n", '| colspan="4" style="vertical-align:top; text-align:left;" |\n', example ) end
local linkAlias = map("link alias") if linkAlias and (#linkAlias > 0) then builder:wikitext( "\n|-\n", '! colspan="4" | Zobacz też\n', "|-\n", '| colspan="4" style="vertical-align:top; text-align:left;" |\n', "* Podstawowe wykorzystanie w infoboksach\n", "* Wykorzystanie w mapach lokalizacyjnych" ) end
builder:wikitext( "\n|}\n" ) end
local function Example(frame, map, variant) local example = map("przykład") local draw = false local text = mw.html.create():wikitext( "{{mapa lokalizacyjna\n", " |mapa = ", mw.title.new(map()).subpageText, "\n", variant and (" |wariant = "..variant.."\n") or "" ):done()
if example and example[1] then local points = {} text:wikitext(" |punkty mapy = \n") for _, v in ipairs(example) do table.insert(points, require("Module:Współrzędne").punkt({ v[1], opis=v[2] })) text:wikitext("{"description":"\" or \"\", v[2], \"","mark":"Red pog.svg","geohack":"type:city","error":"Invalid parameters: {\", v[1], v[2] and \"}","size":6},\n") end draw = require("Module:Mapa").Thumb({ map(), wariant=variant, ["punkty mapy"] = table.concat(points)}) else draw = require("Module:Mapa").Thumb({ map(), wariant=variant }) end
text:wikitext("}}") local example = tostring(text) local maxWidth = 0 for v in mw.text.gsplit(example, "\n") do local w = mw.ustring.len(v) maxWidth = w > maxWidth and w or maxWidth end
local attributes = nil if maxWidth > 44 then attributes = { style="white-space: pre; clear:right;" } end
local result = tostring(draw)..frame:extensionTag("pre", example, attributes) return result end
local function Footer(builder, standardMap) local title = mw.title.getCurrentTitle() local content = title:getContent() local index = mw.ustring.match(title.text, "^Mapa/dane/(.*)$") or title.text local directCategories = false for category in mw.ustring.gmatch(content, "%[%[[Kk][Aa][Tt][Ee][Gg][Oo][Rr][Ii][Aa]:([^\n\t|%[%]]+)%]%]") do local c = mw.text.trim(category) if #c > 0 then builder:wikitext("") directCategories = true end end if directCategories then return end
local link = standardMap["link alias"] local name = standardMap["nazwa alias"] local abbr = standardMap["skrót"] local template = standardMap.szablon
if name or link then builder:wikitext(mw.getCurrentFrame():callParserFunction("DEFAULTSORT", name or link), "\n") end
builder:wikitext("") if abbr then if (#abbr == 0) or (link == abbr) then builder:wikitext("") end
if (#abbr > 0) and not mw.title.new("Module:Mapa/dane/"..abbr).exists then builder:wikitext("") end end
if name then if (#name == 0) or (name == link) then builder:wikitext("") end end
if title.subpageText == abbr then local content = title:getContent() local redirTo = mw.ustring.match(content, '^%s*return%s+require%s*%(%s*"(.-)"%s*%)%s*$') if not redirTo then builder:wikitext("") end elseif (title.subpageText ~= (template or name or link)) or (template == (name or link)) then builder:wikitext("") end
if not standardMap.top and not standardMap["bez mapy świata"] then builder:wikitext("") end
if standardMap["rozmiar"] then local width = tonumber(standardMap["rozmiar"]) or 238 if width > 238 then builder:wikitext("") end end end
local function SelectVariants(mapData) local index = { ["fizyczna"] = -3, ["kolej"] = -2, ["hydro"] = -1, } if mapData[1].par then for i, v in ipairs(mapData[1].par) do if not index[v] then index[v] = i end end end
local variants = {} for k, v in pairs(mapData) do if (type(k) == "string") and (#k > 0) and (type(v) == "table") then table.insert(variants, k) if not index[k] then local y = tonumber(k) if y and (y >= 1000) and (y <= 9999) then y = 11000 - y else local fold = mw.getContentLanguage():caseFold(k) y = 11000 + mw.ustring.codepoint(fold, 1, 1) + mw.ustring.len(fold) end
index[k] = y end end end
table.sort(variants, function(a, b) return index[a] < index[b] end)
return variants end
return { ['opis'] = function(frame) local moduleName = mw.title.getCurrentTitle().fullText local status, mapData = pcall(mw.loadData, moduleName) if not status then -- logowanie komunikatu błędu może być przydatne mw.log(mapData) return end if type(mapData[1]) ~= "table" then -- nieprawidłowa definicja mapy mw.log("brak danych") return end
local builder = mw.html.create() builder :tag("tt"):wikitext(mw.title.getCurrentTitle().fullText):done() :wikitext(" zawiera dane, które są używane przez szablony map lokalizacyjnych. Zobacz więcej w Wikiprojekcie Szablony lokalizacyjne.\n") Infobox(builder, mapData[1], frame) StandardParameters(builder, mapData[1]) builder:wikitext("== Mapa standardowa ==\n") local mainMap = makeMap(mapData[1], {}, moduleName) local mainExample = Example(frame, mainMap, false) Map(builder, mainMap, false, mainExample ) local variants = SelectVariants(mapData) if #variants > 0 then builder:wikitext("== Inne mapy ==\n") for _, v in ipairs(SelectVariants(mapData)) do local map = makeMap(mapData[v], mapData[1], moduleName) local example = Example(frame, map, v) local title = mapData[v].opis or v builder:wikitext("=== ", title, " ===\n") Map(builder, map, v, example) end end
Footer(builder, mapData[1])
return builder:allDone() end, }
local function getMapParams(map, frame)
mw.logObject(map, "map")
if not map or (#map == 0) then
mw.log("Brak nazwy mapy lokalizacyjnej")
end
local moduleprefix = "Module:Mapa/dane/"
if map then
local moduletitle = mw.title.new(map)
if not moduletitle or (moduletitle.namespace ~= 828) then
moduletitle = mw.title.new(moduleprefix..map)
end
if not moduletitle then
mw.log("„"..map.."” nie jest prawidłową nazwą definicji mapy lokalizacyjnej")
elseif moduletitle.exists then
local status, mapData = pcall(mw.loadData, moduletitle.fullText)
if status then
return function(name, variant)
if name == nil then
--mw.logObject(moduletitle.fullText, "GET module title")
return moduletitle.fullText
end
local variants = variant and mw.text.split(variant, "%s*#%s*") or {}
--mw.logObject(variants, "GET map variants")
if name == true then
for _, v in ipairs(variants) do
--mw.logObject(mapData[v], "GET map variant")
if type(mapData[v]) == "table" then
return v
end
end
return 1
end
for _, v in ipairs(variants) do
if mapData[v] and mapData[v][name] ~= nil then
--mw.logObject({variant=v, name=name, result=mapData[v][name] }, "GET")
return mapData[v][name]
end
end
if mapData[1][name] ~= nil then
--mw.logObject({name=name, result=mapData[1][name] }, "GET")
return mapData[1][name]
end
--mw.logObject({name=name}, "GET")
return ""
end
end
else
mw.log("Cannot find the definition of the specified location map. There is no “"..moduleprefix..map.."”.")
end
end
-- default fallback
local mapData = mw.loadData(moduleprefix.."brak")
return function(name, variant)
if name == nil then
return false
elseif name == false then
return (map and (#map > 0)) and map or false
elseif name == true then
return 1
elseif mapData[1][name] == nil then
return ""
elseif variant and mapData[variant] then
return mapData[variant][name] or mapData[1][name]
else
return mapData[1][name]
end
end
end
local function getX(longitude, left, right)
local width = (right - left) % 360
if width == 0 then
width = 360
end
local distanceFromLeft = (longitude - left) % 360
-- the distance needed past the map to the right equals distanceFromLeft - width. the distance needed past the map to the left equals 360 - distanceFromLeft. to minimize page stretching, go whichever way is shorter
if distanceFromLeft - width / 2 >= 180 then
distanceFromLeft = distanceFromLeft - 360
end
return 100 * distanceFromLeft / width
end
local function getY(latitude, top, bottom)
return 100 * (top - latitude) / (top - bottom)
end
local function formatCoordinates(parameters)
if not parameters.coordinates then
return false
end
local placement = parameters.placement
if not placement then
placement = ((parameters.linkFlag == false) or (mw.title.getCurrentTitle().namespace ~= 0)) and "w tekście" or "inline and at the top"
end
return require("Moduł:Współrzędne")["współrzędne"]({
parameters.coordinates,
parameters.geohack,
["umieść"] = placement,
["dokładność"] = parameters.precision,
["linkuj"] = parameters.linkFlag == false and "nie" or "tak",
symbol = parameters.symbol,
})
end
local function splitCoordinatesAndReferences(input)
return require("Moduł:String/UNIQ").podziel(input, "ref", false)
end
local function loadMap(frame, map, variant)
local getMapParam = getMapParams(map, frame)
return function(param)
return getMapParam(param, variant)
end
end
local function decodePoints(pointsData)
if pointsData and (#pointsData > 0) then
local data = mw.text.jsonDecode("["..pointsData.."{\"dummy\":false}]")
table.remove(data) -- remove last dummy
return data
end
end
local function estimateTextWidth(wikicode, fontSize)
local text = mw.ustring.gsub(wikicode, "%[%[[^\n|%]%[]+|([^\n|%]%[]+)%]%]", "%1")
text = mw.ustring.gsub(text, "%[%[([^\n|%]%[]+)%]%]", "%1")
text = mw.ustring.gsub(text, "<[^>]*>", "")
return mw.ustring.len(text) * fontSize
end
local function positionDescriptionCode(r)
local d = math.abs(r - 50)
local c = false
if d > 40 then
c = '3'
elseif d > 20 then
c = '2'
elseif d > 10 then
c = '1'
else
c = '0'
end
return r > 50 and c..'0' or '0'..c
end
local function relativePositionDescriptionCode(center, neighbour)
local dx = neighbour.x - center.x
local dy = neighbour.y - center.y
local r = '0' if dx > 0 then r = '1' end
local l = '0' if dx < 0 then l = '1' end
local t = '0' if dy < 0 then t = '1' end
local b = '0' if dy > 0 then b = '1' end
local adx = math.abs(dx)
local ady = math.abs(dy)
if adx > (10 * ady) then
t = '0'
b = '0'
elseif ady > (10 * adx) then
r = '0'
l = '0'
end
return r..l..t..b
end
function plainText(content)
if content then
local c
content, c = mw.ustring.gsub(content, "%[%[%s*[Pp]lik%s*:.-%]%]", "")
content, c = mw.ustring.gsub(content, "%[%[%s*[Ff]ile%s*:.-%]%]", "")
content, c = mw.ustring.gsub(content, "%[%[%s*[Gg]rafika%s*:.-%]%]", "")
content, c = mw.ustring.gsub(content, "%[%[%s*[Ii]mage%s*:.-%]%]", "")
content, c = mw.ustring.gsub(content, "%[%[[^|%]]+|(.-)%]%]", "%1")
content, c = mw.ustring.gsub(content, "%[%[(.-)%]%]", "%1")
content, c = mw.ustring.gsub(content, "%[.- (.-)%]", "%1")
content, c = string.gsub(content, "</?[Ss][Pp][Aa][Nn][^>]*>", "")
content, c = string.gsub(content, "</?[Bb][Rr][^>]*>", "")
content, c = string.gsub(content, "</?[AaBbIiPpQqSsUu][^>]*>", "")
content, c = string.gsub(content, "[ \n\r\t]+", " ")
content = mw.text.unstrip(content)
content = mw.text.nowiki(content)
return mw.text.trim(content)
end
end
local function drawMap(builder, get, width, fontSize, data, infoboxCoordinates, customAlt)
local reliefImage = mw.text.trim(get("mapa"))
local reliefTitle = mw.title.new("Plik:"..reliefImage)
if not reliefTitle.file.exists then
reliefTitle = mw.title.new("Plik:Image of nothing.svg")
end
local file = reliefTitle.file
local height = file.height * width / file.width
-- przeliczanie punktów na mapie
local inside = {}
local outside = {}
local errors = {}
local hoverPoints = false
local alt = mw.loadData("Moduł:Mapa/alt")
if data and (#data > 0) then
local x_func = mw.text.trim(get("x"))
local y_func = mw.text.trim(get("y"))
local top = get("top")
local left = get("left")
local bottom = get("bottom")
local right = get("right")
if #x_func == 0 then
x_func = false
end
if #y_func == 0 then
y_func = false
end
for i, v in ipairs(data) do
if v.latitude and v.longitude and v.mark and v.size then
-- przeliczanie współrzędnych na pozycje rysowania
if x_func then
local expx = mw.ustring.gsub(mw.ustring.gsub(x_func, "{{{szerokość}}}", v.latitude), "{{{długość}}}", v.longitude)
v.x = tonumber(mw.ext.ParserFunctions.expr(expx))
else
v.x = getX(v.longitude, left, right)
end
if y_func then
local expy = mw.ustring.gsub(mw.ustring.gsub(y_func, "{{{szerokość}}}", v.latitude), "{{{długość}}}", v.longitude)
v.y = tonumber(mw.ext.ParserFunctions.expr(expy))
else
v.y = getY(v.latitude, top, bottom)
end
v.rx = width * v.x / 100
v.ry = height * v.y / 100
v.posDesc = alt.relativeDescription[positionDescriptionCode(v.x)..positionDescriptionCode(100-v.y)]
if not v.alt then
v.autoAlt = alt.pointDescription[v.mark] or alt.pointDescription[false]
local desc = plainText(v.description)
if desc and #desc > 0 then
v.autoAlt = v.autoAlt..mw.ustring.format(alt.describedAs, desc)
end
end
mw.logObject(v)
if (v.x < 0) or (v.x > 100) or (v.y < 0) or (v.y > 100) then
table.insert(outside, v)
else
table.insert(inside, v)
if not hoverPoints and (v.position == "hover") and v.description then
hoverPoints = true
end
end
elseif v.error then
table.insert(errors, v)
else
-- TODO illegal data or "dummy: false"
mw.logObject(v, "illegal at "..tostring(i))
end
end
end
-- automatyczne pozycjonowanie dwóch punktów
if (#inside == 2) and inside[1].description and inside[2].description and not inside[1].position and not inside[2].position then
local y1 = inside[1].ry
local y2 = inside[2].ry
if (math.abs(y1 - y2) < 16) and (y1 > 8) and (y2 > 8) and ((height - y1) > 8) and ((height - y2) > 8) and (math.abs(inside[1].rx - inside[2].rx) < 80) then
inside[1].position = y2 > y1 and "top" or "bottom"
inside[2].position = y1 > y2 and "top" or "bottom"
end
end
local altInfo = customAlt
if not altInfo then
altInfo = get("alt") or ""
if #altInfo == 0 then
local g = get("dopełniacz")
if g then
altInfo = "Mapa konturowa "..g
end
end
if (#altInfo > 0) and (#inside > 0) then
local extAlt = inside[1].posDesc..alt.thereIs..(inside[1].alt or inside[1].autoAlt)
if #inside == 1 then
altInfo = altInfo..", "..extAlt
elseif #inside == 2 then
local extAlt2 = alt.combine2..inside[2].posDesc..alt.thereIs..(inside[2].alt or inside[2].autoAlt)
if inside[1].posDesc == inside[2].posDesc then
local code = relativePositionDescriptionCode(inside[1], inside[2])
extAlt2 = (alt.relativeDescription2[code] or alt.relativeDescription2[false])..alt.thereIs2..(inside[2].alt or inside[2].autoAlt)
end
altInfo = altInfo..", "..extAlt..", "..extAlt2
elseif (#inside > 1) and infoboxCoordinates then
altInfo = altInfo..", "..extAlt
end
end
end
-- tło mapy
local relief = builder:tag("div")
relief:css({ position = "relative", border = "0 solid #aaa", padding = "0", width = tostring(width).."px" })
relief:wikitext("[[Plik:", reliefImage, "|", width, "px|class=notpageimage|link=")
if #altInfo > 0 then
relief:wikitext("|alt=", altInfo)
end
if not hoverPoints then
local reliefInfo = get("dopełniacz")
if reliefInfo then
relief:wikitext("|Mapa lokalizacyjna ", reliefInfo)
end
end
relief:wikitext("]]")
function showError(category, ...)
local catLink = ""
local known = {
["brak mapy"] = { "'''No map:''' ''%s''", "[[Kategoria:Szablony lokalizacyjne - brak mapy]]", },
["brak kodu mapy"] = { "'''Map code missing'''", "[[Kategoria:Szablony lokalizacyjne - brak kodu mapy]]", },
["współrzędne spoza mapy"] = { "'''Coordinates outside map bounds:''' ''%f %f''", "[[Kategoria:Szablony lokalizacyjne - współrzędne spoza mapy]]", },
["brak współrzędnych"] = { "'''Missing coordinates'''", "[[Kategoria:Szablony lokalizacyjne – brak współrzędnych]]", },
[true] = { "%s", false },
[false] = { "'''''Other error'''''", false, },
}
local k = known[category] or known[false]
local message = mw.ustring.format(k[1], ...)
if k[2] and (mw.title.getCurrentTitle().namespace == 0) then
message = message..k[2]
end
local absolute = relief:tag("div")
:css( { position = "absolute", ["z-index"] = 200, top = "50%", left = "50%", height = 0, width = 0, margin = 0, padding = 0, } )
local msg = absolute:tag("div")
:css( { ["font-size"] = "90%", ["line-height"] = "110%", position = "relative", width = "16em", ["z-index"] = 202, top = "-0.5em", left = "-8em", float = "center", ["text-align"] = "center", background = "white", color = "red", } )
:wikitext(message)
end
-- brak mapy
if not get() then
local map = get(false)
showError(map and "brak mapy" or "brak kodu mapy", map)
if (#inside == 1) and (#outside == 0) then
local v = inside[1]
if (v.longitude == 0) and (v.latitude == 0) then
--mw.log("dummy (0 0) bez mapy nie jest rysowany")
return
end
end
end
-- błędy
if (#inside == 0) and (#outside == 0) then
showError("brak współrzędnych")
end
for i, v in ipairs(outside) do
showError("współrzędne spoza mapy", v.latitude, v.longitude)
end
for i, v in ipairs(errors) do
showError(true, v.error or "?")
end
-- punkty na mapie
for i, v in ipairs(inside) do
local hsize = tostring(v.size/2).."px"
local size = tostring(v.size).."px"
local absolute = relief:tag("div")
:attr("aria-hidden", "true")
:css( { position = "absolute", ["z-index"] = 2, top = tostring(v.y).."%", left = tostring(v.x).."%", height = 0, width = 0, margin = 0, padding = 0, } )
local file = absolute:tag("div")
:css( { position = "relative", ["text-align"] = "center", left = "-"..hsize, top = "-"..hsize, width = size, ["font-size"] = size, ["line-height"] = size, } )
file:wikitext("[[Plik:", v.mark, "|", v.size, "x", size, "|link=", v.link)
if v.description then
file:wikitext("|", v.description)
end
file:wikitext("]]")
-- TODO description
if v.description and (v.position ~= "hover") then
local textWidthLimit = 120
function descriptionWidth(availableWidth)
return availableWidth <= 0 and "auto" or (math.min(availableWidth, textWidthLimit).."px")
end
local descw = "auto"
local css = {}
if v.position == "right" then
descw = descriptionWidth(math.floor(width - v.rx - (v.size / 2) - 5))
css = { top = "-0.5em", left = tostring((v.size / 2) + 2).."px", ["text-align"] = "left", float = "left" }
elseif v.position == "left" then
descw = descriptionWidth(math.floor(v.rx - (v.size / 2) - 5))
css = { top = "-0.5em", right = tostring((v.size / 2) + 2).."px", ["text-align"] = "right", float = "right" }
elseif v.position == "top" then
descw = "10em"
css = { bottom = tostring((v.size / 4) + 2).."px", left = "-5em", ["text-align"] = "center", float = "center" }
elseif v.position == "bottom" then
descw = "10em"
css = { top = tostring((v.size / 4) + 2).."px", left = "-5em", ["text-align"] = "center", float = "center" }
else -- auto
local textWidth = estimateTextWidth(v.description, fontSize) * 0.6
local twoLines = textWidth > textWidthLimit
local minY = fontSize * (twoLines and 1 or 0.5)
local maxY = height - minY
local goodY = (v.ry >= minY) and (v.ry <= maxY)
if goodY and ((v.x < 50) or ((v.rx + textWidth + (v.size / 2) + 2) < width)) then -- right
descw = descriptionWidth(math.floor(width - v.rx - (v.size / 2) - 5))
css = { top = twoLines and "-1em" or "-0.5em", left = tostring((v.size / 2) + 2).."px", ["text-align"] = "left", float = "left" }
elseif goodY and (((v.rx - (v.size / 2) - 2) > textWidth) or (v.x > 70)) then -- left
descw = descriptionWidth(math.floor(v.rx - (v.size / 2) - 5))
css = { top = twoLines and "-1em" or "-0.5em", right = tostring((v.size / 2) + 2).."px", ["text-align"] = "right", float = "right" }
elseif (v.y > 50) then -- top
descw = "10em"
css = { bottom = tostring((v.size / 4) + 2).."px", left = "-5em", ["text-align"] = "center", float = "center" }
else -- bottom
descw = "10em"
css = { top = tostring((v.size / 4) + 2).."px", left = "-5em", ["text-align"] = "center", float = "center" }
end
end
local desc = absolute:tag("div")
:css( { ["font-size"] = tostring(fontSize).."px", ["line-height"] = tostring(1.2*fontSize).."px", ["z-index"] = "90", ["position"] = "absolute", ["width"] = descw, } )
desc:css(css)
desc:tag("span")
:css({ padding = "1px", ["text-shadow"] = "0 0 5px white;" })
:wikitext(v.description)
end
end
end
local function makeTrackingLinks(get, group)
local linkAlias = get("link alias")
local mapVariant = get(true)
if not linkAlias or (#linkAlias == 0) then
return
end
local trackingLink = "Moduł:Mapa/linkujące/"..linkAlias.."/"..group
-- (kosztowne!) _ = mw.title.new(trackingLink).id
-- (kosztowne!) _ = mw.title.new(trackingLink.."/"..mapVariant).id
end
local function adjustPointParams(points, mapgeohack)
for i, p in ipairs(points) do
local link = p.link
if link then
if mapgeohack==false then
p.link = ""
elseif mapgeohack then
p.link = link.."_"..mapgeohack
elseif p.geohack then
p.link = link.."_"..p.geohack
end
end
end
end
local function tryGetMapFor(property)
local pid, qid, props = require("Module:Wikidane/select").selectProperty(property, mw.loadData("Moduł:Mapa/filters"), nil, nil, "najlepsza")
if not qid then
return
end
local maps = {}
for i, v in ipairs(props) do
if v.mainsnak and (v.mainsnak.snaktype == "value") and (v.mainsnak.datatype == "wikibase-item") then
local name = mw.wikibase.getLabelByLang(v.mainsnak.datavalue.value.id, "pl")
if name then
table.insert(maps, name)
end
end
end
if #maps <= 0 then
return
end
local result = table.concat(maps,'#')
mw.logObject(result,"tryGetMapFor("..property..")")
return result
end
local function isKartographerZoom(map, size)
if not map then
return false
end
if string.match(map,"^[1-9]$") or string.match(map, "^1[0-9]$") then
return map
end
local w = tonumber(size)
if w and (w > 0) then
local d, k = string.match(map, "^([0-9]+) ?(k?)m$")
local d = tonumber(d)
if d and (d > 0) then
if k == "k" then
d = d * 1000
end
local z = (math.log(96000) + math.log(w) - math.log(d)) / math.log(2)
local zoom = math.min(math.max(math.floor(z), 1),19)
mw.logObject({w = w, d = d, z=z, zoom=zoom}, "zoom calc")
return zoom
end
end
return false
end
return {
["Value"] = function(frame)
local f = frame.args[1] and frame or frame:getParent()
return getMapParams(f.args[1], frame)(f.args[2], f.args[3])
end,
["Infobox"] = function(frame)
-- log wskazujący na początek wywołania funkcji
mw.log("{{#invoke:Moduł:Mapa|Infobox}}")
local args = require('Module:Arguments').getArgs(frame, {
trim = true,
removeBlanks = true,
wrappers = "Szablon:Infobox mapa lokalizacyjna",
})
local defaultIcon = "[[Plik:Geographylogo.svg|20px|alt=Ziemia|link=Ziemia]]"
local map = args["mapa"]
or tryGetMapFor("P17") -- państwo
or tryGetMapFor("P706") -- region geograficzny
or tryGetMapFor("P30") -- kontynent
or "brak" -- poddaję się
local variant = args["wariant"]
local description = args["opis"]
local mark = args["znak na mapie"] or "Red pog.svg"
local markSize = tonumber(args["wielkość znaku"]) or 6
local coordinates = args["współrzędne"]
local coordsRefs = false
local markalt = args["map marker alt text"]
if not coordinates then
mw.log("the infobox may retrieve coordinates from Wikidata")
else
coordinates, coordsRefs = splitCoordinatesAndReferences(coordinates)
mw.logObject(coordinates, "współrzędne")
if coordsRefs then
-- (kosztowne!) _ = mw.title.new("Moduł:Mapa/przypisy").id
mw.logObject(coordsRefs, "przypisy")
end
end
local precision = args["dokładność"]
local twoMaps = args["dwie mapy"]
local category = args["kategoria"]
local geohack = args["opcje geohack"]
local position = args["pozycja opisu"]
local points = args["punkty mapy"]
mw.logObject({precision = precision, twoMaps = twoMaps, category = category, geohack = geohack, position = position, points = points}, "argumenty")
if points and not string.match(points, "%s*{") then
mw.log("attached map points have an invalid format")
return
end
if not points and not coordinates then
if args["wikidane"] == "nie" then
mw.log("no map points provided and Wikidata access is not permitted")
elseif map ~= "pusta" then
mw.log("neither map points nor coordinates provided; time to use Wikidata")
local display = true
if (map ~= "osobna") and (map ~= "niedostępna") then
display = "#coordinates"
end
local p = require("Moduł:Współrzędne").punkt({
["opcje geohack"] = geohack,
["znak"] = mark,
["rozmiar znaku"] = markSize,
["opis"] = description,
["pozycja"] = position,
["dokładność"] = precision,
["alt"] = markalt,
display = display,
symbol = false,
})
if not p then
mw.log("no map points found even in Wikidata")
end
points = p
end
end
if not points and not coordinates and (mw.title.getCurrentTitle().fullText == frame:getParent():getTitle()) and (type(frame.getParent) == "function") then
--TEST ANY ARG
local any = false
for k, v in pairs(frame:getParent().args) do
any = true
break
end
if not any then
-- brak jakichkolwiek argumentów w szablonie to tryb demo
points = require("Moduł:Współrzędne").punkt({ "0 0", display = true, symbol = false, })
map = "brak"
end
end
if not points and not coordinates then
if not category or (mw.title.getCurrentTitle().namespace ~= 0) or (map == "żadna") or (map == "osobna") or (map == "pusta") or (map == "niedostępna") then
return
end
return '|- style="display:none;"\n!colspan="2"|brak współrzędnych[[Kategoria:Szablony lokalizacyjne – brak współrzędnych – '..category..']]\n|-'
end
local result = {}
local coords = false
if (map == "żadna") or (map == "none") then
-- (kosztowne!) _ = mw.title.new("Moduł:Mapa/linkujące/żadna").id
-- TODO współrzędne, geohack, linkuj=tak, dokładność=kątowo, umieść=w tekście (i na górze)
coords = formatCoordinates({
coordinates = coordinates,
geohack = geohack,
linkFlag = true,
})
elseif map == "osobna" then
-- (kosztowne!) _ = mw.title.new("Moduł:Mapa/linkujące/osobna").id
-- TODO współrzędne, geohack, linkuj=tak, dokładność=kątowo, umieść=w tekście
coords = formatCoordinates({
coordinates = coordinates,
geohack = geohack,
linkFlag = true,
placement = "w tekście",
})
elseif map == "pusta" then
-- (kosztowne!) _ = mw.title.new("Moduł:Mapa/linkujące/pusta").id
-- no map nor coordinates
elseif map == "niedostępna" then
-- (kosztowne!) _ = mw.title.new("Moduł:Mapa/linkujące/niedostępna").id
-- TODO współrzędne, globe:none, linkuj=nie, dokładność=dziesiętnie, normalizacja=auto, ikona=
coords = formatCoordinates({
coordinates = coordinates,
linkFlag = false,
precision = precision or "dziesiętnie",
})
elseif (map == "dynamiczna") or isKartographerZoom(map, 240) then
-- (kosztowne!) _ = mw.title.new("Moduł:Mapa/kartographer").id
-- (kosztowne!) _ = mw.title.new("Moduł:Mapa/kartographer/"..map).id
coords = formatCoordinates({
coordinates = coordinates,
geohack = geohack or "",
linkFlag = true,
precision = precision or "kątowo",
symbol = icon,
})
local primaryPoint = false
if coordinates then
local p = require("Moduł:Współrzędne").punkt({
coordinates,
["znak"] = mark,
["rozmiar znaku"] = markSize,
["opis"] = description,
symbol = false,
})
primaryPoint = true
points = points and (p..points) or p
end
local pointsData = decodePoints(points)
mw.logObject(pointsData, "pointsData")
if not coords and pointsData and (#pointsData > 0) then
icon = false
coords = pointsData[1].display
end
longitude = 0
latitude = 0
for i, v in ipairs(pointsData) do
longitude = longitude + v.longitude
latitude = latitude + v.latitude
end
longitude = longitude / #pointsData
latitude = latitude / #pointsData
local mapWidth = 238
local map1 = mw.html.create("div")
:css( { margin="0 auto", ["text-align"]="center", width=tostring(mapWidth+4).."px" } )
map1:tag("div")
:css( { ["font-weight"]= "bold", color="var(--color-subtle, #54595d);" } )
:wikitext("Location on map")
local content = {}
if #pointsData == 1 then
content.type = "Feature"
content.properties = {}
content.properties["marker-color"] = "f00"
content.properties["marker-size"] = "medium"
content.properties.description = description
content.geometry = {
type = "Point",
coordinates = {longitude, latitude},
}
else
content.type = "FeatureCollection"
content.features = {}
for i, v in ipairs(pointsData) do
p = {}
p.type = "Feature"
p.properties = {}
p.properties["marker-size"] = (primaryPoint and (i == 1)) and "medium" or "small"
p.properties["marker-color"] = (primaryPoint and (i == 1)) and "f00" or "00f"
p.geometry = {
type = "Point",
coordinates = {v.longitude, v.latitude},
}
table.insert(content.features, p)
end
end
mw.logObject(content, "content")
local contentJson = mw.text.jsonEncode(content, mw.text.JSON_PRETTY)
mw.logObject(contentJson, "contentJson")
local zoom = isKartographerZoom(map, 240)
if not zoom then
zoom = (#pointsData > 1)
and nil -- zoom się sam ustali (TODO sprawdź czy punkty są różne)
or 12 -- jeden punkt wymaga konkretnej skali
end
local kartographer = frame:extensionTag('mapframe', contentJson, {
width = mapWidth,
height = mapWidth,
zoom = zoom,
longitude = longitude,
latitude = latitude,
align = "center",
lang = "local",
frameless = 1
})
map1:wikitext(kartographer)
table.insert(result, '|- class="infobox-locationmap" style="background-color:var(--background-color-base, #fff); color:black; text-align:center; border-top:1px solid var(--border-color-base, #a2a9b1);"\n|colspan="2"|')
table.insert(result, tostring(map1:allDone()))
table.insert(result, "\n")
else
local maps = {}
local list = string.match(map, "#")
for v in mw.ustring.gmatch(map, "[^#]+") do
table.insert(maps, mw.text.trim(v))
end
if #maps == 0 then
table.insert(maps, map)
end
if not list and (twoMaps ~= "nie") then
while #map > 0 do
local get = loadMap(frame, map, variant)
map = mw.text.trim(get("nadrzędna") or "")
if #map > 0 then
table.insert(maps, 2, map)
end
end
end
local mapIndex = 1
local map = maps[mapIndex]
local get = loadMap(frame, map, variant)
-- prepare coordinates under the map
local icon = mw.text.trim(get("ikona") or "")
if #icon == 0 then
icon = defaultIcon
end
local mapPrecision = get("dokładność")
if mapPrecision and (#mapPrecision <= 0) then
mapPrecision = nil
end
coords = formatCoordinates({
coordinates = coordinates,
geohack = geohack or get("globe") or "",
linkFlag = get("globe") ~= false,
precision = precision or mapPrecision or "kątowo",
symbol = icon,
})
if coordinates then
local p = require("Moduł:Współrzędne").punkt({
coordinates,
["opcje geohack"] = geohack,
["znak"] = mark,
["rozmiar znaku"] = markSize,
["opis"] = description,
["pozycja"] = position,
alt = markalt,
symbol = false,
})
--primaryPoint = true
points = points and (p..points) or p
end
local pointsData = decodePoints(points)
if pointsData then
adjustPointParams(pointsData, get("globe"))
end
if not coords and pointsData and (#pointsData > 0) then
icon = false
coords = pointsData[1].display
end
-- tracking link, pseudo reference to primary map
makeTrackingLinks(get, "primary")
-- draw maps
while map do
map = nil
-- draw map
local mapWidth = tonumber(get("rozmiar")) or 238
if mapWidth > 238 then
mapWidth = 238
elseif mapWidth < 100 then
mapWidth = 100
end
local map1 = mw.html.create("div")
:css( { margin="0 auto", ["text-align"]="center", width=tostring(mapWidth+4).."px" } )
map1:tag("div")
:css( { ["font-weight"]= "bold", color="var(--color-subtle, #54595d);" } )
:wikitext("Location on map", get("dopełniacz"))
drawMap(map1:tag("div"):addClass("mapa-lokalizacyjna"), get, mapWidth, 12.6, pointsData, coordinates, false)
table.insert(result, '|- class="infobox-locationmap" style="background-color:var(--background-color-base, #fff); color:black; text-align:center; border-top:1px solid var(--border-color-base, #a2a9b1);"\n|colspan="2"|')
table.insert(result, tostring(map1:allDone()))
table.insert(result, "\n")
-- next parent
if mapIndex < #maps then
mapIndex = mapIndex + 1
map = maps[mapIndex]
get = loadMap(frame, map, variant)
end
end
end
if coords then
table.insert(result, '|-\n|colspan="2" style="background-color:var(--background-color-base, #fff); color:black; text-align:center; border-bottom:1px solid var(--border-color-base, #a2a9b1);"|')
table.insert(result, coords)
if coordsRefs then
table.insert(result, coordsRefs)
end
table.insert(result, "\n")
end
if #result > 0 then
table.insert(result, "|-")
end
return table.concat(result)
end,
["Thumb"] = function(frame)
local args = require('Module:Arguments').getArgs(frame, {
trim = true,
removeBlanks = false,
wrappers = "Szablon:Mapa lokalizacyjna",
})
local map = args["mapa"] or args[1] or "{{{1}}}"
if #map == 0 then
map = nil
end
local variant = args["wariant"]
local width = tonumber(args["rozmiar"]) or 238
local fontSize = tonumber(args["font-size"]) or 12.6
local align = args["wyrównanie"] or "right"
local footer = args["podpis"]
local alt = args["alt"]
local pointsData = decodePoints(args["punkty mapy"])
local get = loadMap(frame, map, variant)
if pointsData then
adjustPointParams(pointsData, get("globe"))
end
-- tracking link, pseudo reference to this map
makeTrackingLinks(get, "standalone")
local positionClass = {
["center"] = "center",
["right"] = "tright",
["left"] = "tleft",
[""] = "tnone",
}
local thumb = mw.html.create("div")
:addClass("thumb")
:addClass(positionClass[align] or align)
:addClass("panel-with-scroll")
:wikitext('\n')
local thumbinner = thumb:tag("div")
:addClass("thumbinner")
:css({ width = tostring(width + 2).."px" })
:wikitext('\n')
local border = thumbinner:tag("div")
:css({ border = "1px solid #ccc", width = tostring(width).."px !important" })
local builder = border:tag("div")
--:addClass("mapa-lokalizacyjna")
:css({ margin = "0 auto", width = tostring(width).."px" })
drawMap(builder, get, width, fontSize, pointsData, false, alt)
if pointsData and (#pointsData == 1) and (mw.title.getCurrentTitle().namespace == 0) then
builder:wikitext("[[Kategoria:Mapa lokalizacyjna z jednym punktem]]")
end
thumbinner
:wikitext('\n')
local thumbcaption = thumbinner:tag("div")
:addClass("thumbcaption")
thumbcaption:tag("div")
:addClass("magnify")
:wikitext("[[Plik:Geographylogo.svg|16x16px|link=Wikiprojekt:Szablony lokalizacyjne]]")
if footer and (#footer > 0) then
thumbcaption:wikitext(footer)
else
thumbcaption:wikitext("Location on map", mw.text.nowiki(get("dopełniacz") or ""))
end
thumbinner
:wikitext('\n')
thumb
:wikitext('\n')
return thumb:allDone()
end,
["Inline"] = function(frame)
local args = require('Module:Arguments').getArgs(frame, {
trim = true,
removeBlanks = false,
wrappers = "Szablon:Mapa lokalizacyjna",
})
local map = args["mapa"] or args[1] or "{{{1}}}"
if #map == 0 then
map = nil
end
local variant = args["wariant"]
local width = tonumber(args["rozmiar"]) or 238
local fontSize = tonumber(args["font-size"]) or 12.6
local alt = args["alt"]
local pointsData = decodePoints(args["punkty mapy"])
local get = loadMap(frame, map, variant)
if pointsData then
adjustPointParams(pointsData, get("globe"))
end
-- tracking link, pseudo reference to this map
makeTrackingLinks(get, "standalone")
local builder = mw.html.create("div")
:addClass("mapa-lokalizacyjna")
:css({ margin ="0 auto", width = tostring(width + 2).."px", padding = "3px", margin = "3px" })
drawMap(builder, get, width, fontSize, pointsData, false, alt)
if pointsData and (#pointsData == 1) and (mw.title.getCurrentTitle().namespace == 0) then
builder:wikitext("[[Kategoria:Mapa lokalizacyjna z jednym punktem]]")
end
return builder:allDone()
end,
}
