Module:Infobox : Différence entre versions

De Lagny-sur-Marne Wiki
Aller à : navigation, rechercher
m
Ligne 3 : Ligne 3 :
 
local pagename = mw.title.getCurrentTitle().prefixedText
 
local pagename = mw.title.getCurrentTitle().prefixedText
 
local wikidata = require('Module:Wikidata')
 
local wikidata = require('Module:Wikidata')
 +
local linguistic = require('Module:Linguistique')
 
local infoboxname, infoboxmodule
 
local infoboxname, infoboxmodule
 
local maintenance = '' -- chaîne retournée avec le module : cats de maintenance
 
local maintenance = '' -- chaîne retournée avec le module : cats de maintenance
Ligne 336 : Ligne 337 :
 
return
 
return
 
end  
 
end  
local mapdata =  require('Module:Données cartes')[string.lower(map)]
+
local mapdata =  require('Module:Données cartes')[string.lower(map or '')]
 
if not mapdata or not mapdata.images then
 
if not mapdata or not mapdata.images then
 
addmaintenancecat('Page avec des données de géolocalisation non supportée')
 
addmaintenancecat('Page avec des données de géolocalisation non supportée')
 
return "carte non supportée: " .. map
 
return "carte non supportée: " .. map
 
end
 
end
local name = mapdata.name
+
local name = mapdata.name or '?'
 
local pointsize = tostring(8)
 
local pointsize = tostring(8)
 
local pointheight, pointwidth
 
local pointheight, pointwidth
Ligne 369 : Ligne 370 :
 
file = mapdata.images[maptype] or mapdata.images[1] or mapdata.images['default']
 
file = mapdata.images[maptype] or mapdata.images[1] or mapdata.images['default']
 
end
 
end
local alt = 'voir sur la carte de ' .. (name or '?')
+
local alt = 'voir sur la carte ' .. linguistic.of(name)
 
local map = mw.html.create('div')
 
local map = mw.html.create('div')
 
:css{['text-align'] = 'center'}
 
:css{['text-align'] = 'center'}
 
:addClass("geobox")
 
:addClass("geobox")
:wikitext('<small>Géolocalisation sur la carte de : ' .. name .. '</small>')
+
:wikitext('<small>Géolocalisation sur la carte ' .. linguistic.of(name) .. '</small>')
 
:tag('table')
 
:tag('table')
 
:addClass('DebutCarte')
 
:addClass('DebutCarte')

Version du 5 octobre 2014 à 14:42

La documentation pour ce module peut être créée à Module:Infobox/doc

local p = {}
local infobox = mw.html.create('div')
local pagename = mw.title.getCurrentTitle().prefixedText
local wikidata = require('Module:Wikidata')
local linguistic = require('Module:Linguistique')
local infoboxname, infoboxmodule
local maintenance = '' -- chaîne retournée avec le module : cats de maintenance
local externaltext = '' -- par exemple coordonnées en titre
local localdata = {} -- aramètres du modèle dans l'article
local maincolor -- la couleur par défaut des titres, sous-titres etc.i

local i18n = {
	['see doc'] = 'Documentation du modèle',
	['edit infobox'] = 'modifier l\'infobox',
	['edit item'] = 'modifier Wikidata'
}

local function addwikidatacat(prop)
	maintenance = maintenance .. '[[Catégorie:Page utilisant des données de Wikidata/' .. string.upper(prop) .. ']]'
end

local function getWikidataValue(params, wikidataparam)
	-- Récupère la valeur Wikidata pour la valeur, soit dans le paramètre "wikidata" soit dans le praramètre "property"
	if not item then
		return nil
	end
	local value
	
	if not wikidataparam then -- par défaut la valeur wikidata est dans le paramètre "wikidata" mais dans les structures composées comme "title", il y a plusieurs paramètres wikidata
		wikidataparam = 'wikidata'
	end
	if params[wikidataparam] then
		if type(params[wikidataparam]) == 'function' then
			value = params[wikidataparam]()
		else
			value = params[wikidataparam]
		end
	elseif params.property then
		value = wikidata.formatStatements({property = params.property})
		if value then
			addwikidatacat(params.property)
		end
	end 
	return value
end

local function getvalue(val, params)
	if type(val) == 'string' then
		return localdata[val]
	elseif type(val) == 'function' then
		return val(localdata, item, params)
	end
end
local function addmaintenancecat(cat, sortkey)
	if mw.title.getCurrentTitle().namespace ~= 0 then
		return
	end
	if cat then
		maintenance = maintenance .. '[[Category:' .. cat .. '|' .. (sortkey or infoboxname) .. ']]'
	end
end

local function buildtitle(params)
	local text = getvalue(params.value, params) or params.textdefaultvalue or  getWikidataValue(params) or mw.title.getCurrentTitle().text
	local subtext = getvalue(params.subtitle) or  getWikidataValue(params, 'wikidatasubtitle') or params.subtitledefaultvalue
	if subtext and (subtext ~= text) then
		text = text .. '<br /><small>' .. subtext .. '</small>'
	end
	local class = params.class or "entete"
	local style = params.style or {}
	if not style['background-color'] then
		style['background-color'] = maincolor
	end
	local title = mw.html.create('p')
		:addClass(class)
		:css(style)
		:wikitext(text)
		:done()
	return title
end

local function buildnavbox(params)
	local class = "overflow nav " .. (params.class or '')  
	local style = params.style or {['border-width'] = '1px'}
	if not style['border-color']
		then style['border-color'] = maincolor
	end
	local previousval = localdata[params.previousparameter]
	local nextval = localdata[params.nextparameter]
	local navbox =
	mw.html.create('p')
		:addClass(class)
		:css(style)
		:tag('span')
			:addClass('prev_bloc')
			:wikitext(previousval)
			:done()
		:tag('span')
			:addClass('next_bloc')
			:wikitext(nextval)
			:done()
		:done()
		return navbox
end
	

local function buildimages(params)
	local images = {}
	if type(params.imageparameters) == 'string' then
		params.imageparameters = {params.imageparameters}
	end
	if not params.imageparameters then -- s'il n'y a pa de paramètre image, continuer, peut-être y-a-t-il une image par défaut définie dans le module d'infobox
		params.imageparameters = {}
	end
	for j, k in ipairs(params.imageparameters) do
		table.insert(images, localdata[k])
	end
	if #images == 0 and item then
		if params.property then
			images = wikidata.getClaims{item= item, property = params.property} or {}
			if #images > 0 then addwikidatacat(params.property) end
		end
		if params.wikidata then
			images = params.wikidata()
			if type(images) == 'string' then return images end -- c'est probablement une erreur dans la requête => afficher le message
		end
	end
	if ((not images) or (#images == 0)) and params.defaultimages then
		images = params.defaultimages
		if type(images) == 'string' then
			images = {images}
		end
	end		
	if (not images) or #images == 0 then
		if params.maintenancecat then
			local maintenancecat = getvalue(params.maintenancecat, params)
			addmaintenancecat(maintenancecat, params.sortkey)
		end
		return
	end
	-- extrait les images des valeurs Wikidata
	if type(images[1]) == 'table' then
		for i, j in pairs(images) do
		if j.mainsnak.snaktype ~= 'value' then
			return
		end
		if i > (params.numval or #images) then
			table.remove(images, i)
		else
			images[i] = j.mainsnak.datavalue.value
		end
		end
	end
	if not images then
		return nil
	end
	local captiontext = localdata[params.captionparameter] or params.defaultcaption
	if type(captiontext) == 'function' then
		captiontext = captiontext(localdata)
	end
	local style = params.style or {padding ='5px 0'}
	local class = "images"
	if  #images == 2 then
		class = "image2"
	end

	-- Partie image

	local imagesString = ''
	for i,image in pairs(images) do
		if image == '-' then
			return
		end
		imagesString = imagesString ..  '[[Fichier:' .. image .. '|frameless'
		if #images == 1 then
			imagesString = imagesString .. '|center'
		end
		if image.upright then
			imagesString = imagesString .. '|upright=' .. image.upright
		else
			imagesString = imagesString .. '|upright=' .. ( 1 / #images )
		end
        imagesString = imagesString .. ']]'
    end

	local image = mw.html.create('div')
		:css(style)
		:addClass("images")
		:wikitext(imagesString)

	-- Partie légende
	local caption = mw.html.create('p')
	if captiontext then
		caption
			:wikitext(captiontext)
			:css(params.style or {})
			:addClass("legend")
			:done()
	end

	return image, caption
end

local function buildtext(params)
	local class = params.class or ''
	local style = params.style or {}
	if not style['text-align'] then
		style['text-align'] = 'center'
	end
	if not style['padding'] then
		style['padding'] = '10px'
	end
	if not style['font-weight'] then
		style['font-weight'] = 'bold'
	end
	local text = getvalue(params.value, params) or getWikidataValue(params) or params.defaultvalue
	if text == '-' then
		return
	end
	if not text then
		addmaintenancecat(params.maintenancecat, params.sortkey)
		return nil
	end
	local formattedtext = mw.html.create('p')
		:addClass(class)
		:css(style)
		:wikitext(text)
		:done()
	return formattedtext
end

local function buildmixedrow(params)
	local class = params.class or ''
	local style = params.style or {}
	local value =  getvalue(params.value, params)
	
	if not value then
		value =  getWikidataValue(params) or params.defaultvalue
	end
	
	local label = params.label
	if not value then
		addmaintenancecat(params.maintenancecat, params.sortkey)
		return nil
	end
	if value == '-' then
		return
	end
-- formatting
	local formattedvalue = mw.html.create('div')
		:wikitext(value)
		
	if (params.hidden == true)then
		formattedvalue
			:attr({class="NavContent", style="display: none; text-align: left;"})
		formattedvalue = mw.html.create('div')
			:attr({class="NavFrame", title="[Afficher]/[Masquer]", style="border: none; padding: 0;"})
			:node(formattedvalue)
	end
	formattedvalue =  mw.html.create('td')
			:node(formattedvalue)
			:allDone()
	
	local formattedlabel = mw.html.create('th')
		:attr('scope', 'row')
		:wikitext(label)
		:done()

	local row = mw.html.create('tr') 
		:addClass(class)
		:css(style)
		:node(formattedlabel)
		:node(formattedvalue)
		:done()
	
	return row
end
local function buildtable(params)
	local tab = mw.html.create('table')
	local title
	if params.title then
		local text
		if type(params.title) == 'string' then -- raccourci moche mais pratique : n'utiliser qu'une chaîne pour le titre
			text = params.title
		else
			text = params.title.value or error('no value provided for this title')
			params = {}
		end
		local style = params.title.style or {['text-align'] = 'center', color = '000000'}
		if not style['background-color'] then
			style['background-color']  = maincolor
		end
		local colspan = params.title.colspan or '2'
		title = mw.html.create('caption')
			:attr({colspan = 2})
			:css(style)
			:wikitext(text)
			:done()
	end
	local rows = {} -- does not add the rows directly to tab: check if some rows are non empty beoforehand so that we do not add a title if there are no data to show
	for k, l in pairs(params.rows) do
		if type(l) == 'function' then --accepte les fonctions qui retournent des tables
			l = l(localdata, item)
		end
		if type(l) == 'nil' then 
			--ne rien faire (quand la valeur est originellemenet une fonctin elle peut retourner nil)
		elseif type(l) ~= 'table' then
			return error('les lignes d\'infobox ("rows") doivent être des tables, est ' .. type(l))
		elseif l.type == 'mixed' then
			local row = buildmixedrow(l)
			if row then
				table.insert(rows, row)
			end
		elseif l.type == 'external text' then
			externaltext = externaltext .. l.value()
		elseif l.type then
			return error('type de ligne inconnue dans l\'infobox : ' .. l.type)
		else 
			return error('veuillez spécifier un type pour toutes les lignes d\'infobox')
		end
	end
	if title and (#rows > 0) then
		tab:node(title)
	end
	if #rows > 0 then
		for i, j in pairs (rows) do
			tab:node(j)
		end
	end
	tab:allDone()
	return tab	
end


local function buildsinglemap(map, maptype, width, latitude, longitude, pointimage, caption) -- fonction d'aige pour buildmap
	if map == '-' then
		return
	end 
	local mapdata =  require('Module:Données cartes')[string.lower(map or '')]
	if not mapdata or not mapdata.images then
		addmaintenancecat('Page avec des données de géolocalisation non supportée')
		return "carte non supportée: " .. map
	end
	local name = mapdata.name or '?'
	local pointsize = tostring(8)
	local pointheight, pointwidth
	if mapdata.projection ==  'Projection équirectangulaire' then
		pointheight = 100 *  (latitude - mapdata.top) / (mapdata.bottom - mapdata.top) 
		pointwidth = 100 *  (longitude - mapdata.left) / (mapdata.right - mapdata.left) 
	else
		return "système cartographique non supporté"
	end
	if (pointheight > 100) or (pointwidth) > 100 or (pointheight < 0) or (pointwidth < 0) then 
		addmaintenancecat('Article avec une géolocalisation hors-carte') return 'lat: ' .. latitude .. '//' .. pointheight
	end
	local htmlheight = tostring(pointheight) .. '%'
	local htmlwidth = tostring(pointwidth) .. '%'

	local pointdiv = mw.html.create('div')
		:css{position = 'absolute', border = 'none', top = htmlheight, left = htmlwidth}
		:tag('div')
			:css{position = 'absolute', top = '-4px', left = '-4px', ['line-height'] = '0'}
			:wikitext('[[Image:' .. pointimage .. '|8px]]')
		:done()
	local mapname = mapdata.name
	local file
	if type(mapdata.images) == 'string' then
		file = mapdata.images
	else 
		file = mapdata.images[maptype] or mapdata.images[1] or mapdata.images['default']
	end
	local alt = 'voir sur la carte ' .. linguistic.of(name)
	local map = mw.html.create('div')
		:css{['text-align'] = 'center'}
		:addClass("geobox")
		:wikitext('<small>Géolocalisation sur la carte ' .. linguistic.of(name) .. '</small>')
		:tag('table')
			:addClass('DebutCarte')
			:attr({border="0", cellspacing="0", cellpadding="0"})
			:css({margin = '0', border = 'none', padding = '0'})
				:tag('tr')
					:tag('td')
						:tag('div')
							:css({position= 'relative', margin = "auto",})
							:wikitext('[[Fichier:' .. file .. '|' .. width .. '|' .. alt .. ']]' )
							:node(pointdiv)
							:done()
						:done()
					:done()
				:done()
	return map
end

local function buildmap(params)
	
	local maplist = params.maps
	if type(maplist) == 'function' then
		maplist = maplist(localdata, item)
	end
	if not maplist then
		return nil
	end
	local width = params.width or 280
	if type(width) ~= 'number' then 
		width = 280
		maintenance = addmaintenancecat('Erreur d\'Infobox/Format d\'image invalide')
	end
	if width > 280 then
		addmaintenancecat('Erreur d\'Infobox/Image trop grande')
		return 'image trop grande, la largeur doit être inférieure ou égale à 280px'
	end
	width = tostring(280) .. 'px'
	local div =  mw.html.create('div'):addClass('img_toogle')
	local pointimage = params.pointimage
	if not pointimage then
		pointimage = 'Point carte.svg'
	end
	local maptype = params.maptype -- choisit le type de carte le plus approprié (relief, administratif, etc.)
	local latitude, longitude
	if type(params.latitude) == 'function' then
		latitude, longitude = params.latitude(localdata, item), params.longitude(localdata, item)
	else 
		latitude, longitude = tonumber(localdata[params.latitude]), tonumber(localdata[params.longitude])
	end 
	if (not latitude or not longitude) and item and params.wikidata then
		if not type(params.wikidata) == 'function'
			then return error('valeur wikidata incorrecte pour la géolocalisation')
		end
		local val = params.wikidata(localdata, item)
		if not val then return nil end
		if (not type(val) == 'table')  then
			return error("mauvaise requête pour les coordonnées de géolocalisation")
		end
		val = val[1]
		if val.mainsnak.snaktype == 'value' then
			latitude, longitude = val.mainsnak.datavalue.value.latitude, val.mainsnak.datavalue.value.longitude
		end
	end  
	if not latitude or not longitude then
		return nil
	end
	for i, map in pairs(maplist) do 
		local newmap = buildsinglemap( mw.ustring.lower(map), maptype, width, latitude, longitude, pointimage, caption)
		div:node(newmap)
	end
	return div
end

local function buildfooter(params)
	if not params then params = {} end
	
	local class = 'navbar noprint ' .. (params.class or '')
	local style = params.style or {}
	if not style['border-top-style'] then
		style['border-top-style'] = 'solid'
	end
	if not style['border-width'] then
		style['border-width'] = '1px'
	end
	if not style['border-color'] then
		style['border-color'] = maincolor
	end
	if not style['font-size'] then
		style['font-size'] = '80%'
	end
	local backlinkstr = '[' .. tostring( mw.uri.fullUrl( pagename, '&action=edit&section=0' ) ) .. ' ' .. i18n['edit infobox'] .. ']'

	local itemlinkstr
	if item then
		itemlinkstr = '[[d:' .. item.id .. '|' .. i18n['edit item'] .. ']]'
	end
	local editstr = backlinkstr
	if itemlinkstr then
		editstr = editstr .. ' - ' .. itemlinkstr
	end
	local editlinkspan =  mw.html.create('span')
		:css({['text-align'] = "left"})
		:addClass('plainlinks')
		:wikitext(editstr)
		:done()
	
	local doclinkstr = '[[Image:Gtk-dialog-info.svg|12px|link=' .. infoboxname .. '|' .. i18n['see doc'] .. ']]'
	local doclinkspan = mw.html.create('span')
		:css({['text-align'] = "right"})
		:wikitext(doclinkstr)
		:done()
	
	local footer = mw.html.create('p')
		:addClass(class)
		:css(style)
		:node(editlinkspan)
		:node(doclinkspan)
	return footer
end

function p._build(localinfoboxmodule)
	-- analyse le module d'infobox
	local style = localinfoboxmodule.style or {}
	local class = localinfoboxmodule.class or "infobox_v3"
	local parts = localinfoboxmodule.parts
	maincolor = localinfoboxmodule.maincolor or "#E1E1E1"
	local footerparams = localinfoboxmodule.footer or {}
	infobox:css(style)
	infobox:addClass(class)

	for i, j in pairs(parts) do
		if type(j) ~= 'table' then
			return error("les éléments du module doivent être des tables (est ".. type(j) .. ')')
		elseif j.type == 'title' then
			infobox:node(buildtitle(j))
		elseif j.type == 'images' then
			local image, caption = buildimages(j)
			infobox:node(image):node(caption)
		elseif j.type == 'text' then
			infobox:node(buildtext(j))
		elseif j.type == 'map' then
			infobox:node(buildmap(j))
		elseif j.type == 'navbox' then
			infobox:node(buildnavbox(j))
		elseif j.type == 'table' then
			infobox:node(buildtable(j))
		end
	end
	local div = mw.html.create('div')
	infobox:node(div):node(tab)
	infobox
		:node(buildfooter(footerparams))
		:done()
	return tostring(infobox) .. externaltext, maintenance
end

function p.build(frame)
	-- set variables
	infoboxname = 'Module:Infobox/' .. frame.args.nom
	localinfoboxmodule = require(infoboxname)
	
	-- get the localinfoboxmodule parameter values and clen them up
	for i, j in pairs(frame:getParent().args) do
		if j and mw.text.trim(j) ~= '' then
			localdata[i] = j
		end
	end
	-- fetch wikidata item and assign it to the item global variable
	if localdata.wikidata == 'non' then
		item = nil
	elseif (not localdata.wikidata) or (localdata.wikidata == '') then
		item = mw.wikibase.getEntityObject()
	else
		item = mw.wikibase.getEntityObject() -- todo: fetch arbitrary item and check for errors
	end
	-- build infobox
	return p._build(localinfoboxmodule) 
end

return p