Module:Coordinates
From Neodyland Wiki
More actions
This documentation is transcluded from Module:Coordinates/doc.
--[[
Module:Coordinates (lightweight Neodyland version)
Provides a minimal LocationTemplateCore used by {{Location}} and {{Object location}}.
Wikidata/SDC-free: coordinates are taken from template parameters only.
Uses GeoData's {{#coordinates:}} parser function when available.
]]
local p = {}
local i18n = require('Module:I18n/coordinates')
local CoorCat = {
dms = '[[Category:Media with coordinates in DMS format]]',
erroneous = '[[Category:Location templates with invalid parameters]]',
}
local function dms2deg(v)
-- parse "34° 05′ 32.36″ N" or "34|5|32.36|N" style input to decimal degrees
local parts = {}
for num in string.gmatch(v, "%d+%.?%d*") do
table.insert(parts, tonumber(num))
end
if #parts < 2 then return nil end
local deg = parts[1]
local min = parts[2] or 0
local sec = parts[3] or 0
local val = deg + min / 60 + sec / 3600
if v:find('[Ss]') or v:find('[Ww]') then val = -val end
return val
end
local function parseLatLon(args)
local lat, lon
if args.lat and args.lon then
lat, lon = args.lat, args.lon
elseif args[4] then
-- DMS with pipes: 34|5|32.36|N|116|9|24.55|W
lat = dms2deg(args[1] .. ' ' .. args[2] .. "' " .. args[3] .. '" ' .. args[4])
lon = dms2deg(args[5] .. ' ' .. args[6] .. "' " .. args[7] .. '" ' .. args[8])
elseif args[2] then
lat, lon = args[1], args[2]
elseif args[1] then
-- "34° 05′ N, 116° 09′ W"
local s = mw.text.split(args[1], ',')
if #s == 2 then
lat, lon = s[1], s[2]
end
end
if lat then
local n = tonumber(lat)
if not n then n = dms2deg(lat) end
lat = n
end
if lon then
local n = tonumber(lon)
if not n then n = dms2deg(lon) end
lon = n
end
return lat, lon
end
local function formatCoor(lat, lon, lang)
if not lat or not lon then return '' end
local ns, ew = 'N', 'E'
if lat < 0 then lat = -lat; ns = 'S' end
if lon < 0 then lon = -lon; ew = 'W' end
local nsew = i18n.NSEW[lang] or i18n.NSEW.en
local latStr = string.format("%.4f° %s", lat, nsew[ns])
local lonStr = string.format("%.4f° %s", lon, nsew[ew])
return latStr .. ' ' .. lonStr
end
function p._LocationTemplateCore(args)
local lang = args.lang or mw.language.getContentLanguage().code
local lat, lon = parseLatLon(args)
local templateText, Categories, coorTag = '', '', ''
if lat and lon then
templateText = formatCoor(lat, lon, lang)
-- Validate range
if math.abs(lon) > 180 or math.abs(lat) > 90 then
Categories = Categories .. '<span style="color:red;font-weight:bold">Error: Invalid parameters! (coordinates are outside allowed range)</span>\n' .. CoorCat.erroneous
lat, lon = nil, nil
end
end
if lat and lon then
-- Add {{#coordinates:}} tag (GeoData) for File/Category namespaces
local ns = mw.title.getCurrentTitle().nsText
if ns == 'File' or ns == 'Category' or ns == 'Gallery' then
local status = 'primary'
local args3 = args.attributes or ''
coorTag = mw.getCurrentFrame():callParserFunction('#coordinates', { status, lat, lon, args3 })
end
else
Categories = Categories .. '<span style="color:red;font-weight:bold">Error: Invalid parameters! (coordinates are missing or not numeric)</span>\n' .. CoorCat.erroneous
end
return templateText, Categories, coorTag
end
function p.LocationTemplateCore(frame)
local args = require('Module:Arguments').getArgs(frame)
args.namespace = mw.title.getCurrentTitle().nsText
local templateText, Categories, cat, coorTag
local lat, lon = parseLatLon(args)
-- validate numeric
if lat and lon then
local l1, l2 = tonumber(lat), tonumber(lon)
if not l1 or not l2 then
args.lat = dms2deg(tostring(lat) or '') or lat
args.lon = dms2deg(tostring(lon) or '') or lon
if args.namespace == 'File' or args.namespace == 'Category' then
cat = CoorCat.dms
end
end
end
templateText, Categories, coorTag = p._LocationTemplateCore(args)
return templateText .. Categories .. (cat or '') .. (coorTag or '')
end
return p