Module:Infobox
La documentation pour ce module peut être créée à Module:Infobox/doc
local p = {} -- variables globales alimentées par les paramètres utilisés item = nil -- l'élément Wikidata lié moduledata = nil -- la sous-page de module:Infobox demandée localdata = {}-- données concernant les paramètres passés au modèle maincolor = '#E1E1E1' page = { -- données concernant la page où est affichée l'infobox name = mw.title.getCurrentTitle().prefixedText, namespace = mw.title.getCurrentTitle().namespace } -- l'objet principal à retournerp local infobox = mw.html.create('div') -- objes secondaires à retourner local maintenance = '' -- chaîne retournfoée avec le module : cats de maintenance local externaltext = '' -- par exemple coordonnées en titre -- modules importés local wikidata = require('Module:Wikidata') local defaultstyle = require('Module:Infobox/Style') local mapmod = require('Module:Carte') local i18n = { ['see doc'] = 'Documentation du modèle', ['edit'] = 'modifier', ['edit code'] = 'modifier le code', ['edit item'] = 'modifier Wikidata', ['tracking cat'] = "Page utilisant des données de Wikidata", ['invalid block type'] = "Bloc de données invalide dans le module d'infobox", ['default cat'] = "Maintenance des infobox", } local function addwikidatacat(prop) maintenance = maintenance .. '[[Category:' .. i18n['tracking cat'] .. '/' .. string.upper(prop) .. ']]' end local function expandquery(query) local value, number -- valeur à retourner, nombre de valeurs pour accorder le libellé if not query.entity then query.entity = item end if not query.conjtype then query.conjtype = 'comma' end local claims = wikidata.getClaims(query) if (not claims) then return nil end return wikidata.formatAndCat(query), #claims -- pour l'accord au pluriel 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, number 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 return params[wikidataparam](item) elseif type(params[wikidataparam]) == 'table' then return expandquery(params[wikidataparam]) else return params[wikidataparam] end end end local function getvalue(val, params) if type(val) == 'string' then return localdata[val] elseif type(val) == 'function' then return val(localdata, item, params) elseif type(val) == 'table' then for i, j in pairs(val) do -- si plusieurs paramètres possibles (legacy de vieux code), prendre le preimeir non bide if localdata[j] then return localdata[j] end end end end local function addmaintenancecat(cat, sortkey) if page.namespace ~= 0 then return '' end if cat then maintenance = maintenance .. '[[Category:' .. cat .. '|' .. (sortkey or page.name) .. ']]' end end function p.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 icon = params.icon or '' if icon ~= '' and not params.large then icon = 'icon ' .. icon end local class = 'entete ' .. icon -- overwrites with those provided in the module local style = {} if maincolor then style['background-color'] = maincolor end if params.style then for i, j in pairs(params.style) do style[i] = j end end local title = mw.html.create('div') :addClass(class) :css(style) :tag('div') :wikitext(text) :allDone() return title end function p.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] or getWikidataValue(params, 'previouswikidata') if not previousval and params['previousproperty'] then previousval = wikidata.formatAndCat{entity = item, property = params['previousproperty']} end local nextval = localdata[params.nextparameter] or getWikidataValue(params, 'nextwikidata') if not nextval and params['nextproperty'] then nextval = wikidata.formatAndCat{entity = item, property = params['nextproperty']} end 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 function p.buildimages(params) local images = {} local size, link, caption 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 -- Images de Wikidata 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 type(images[1]) == 'table' then for i, j in pairs(images) do if j.mainsnak.snaktype ~= 'value' then return end if i > (params.numval) then images[i] = nil else images[i] = j.mainsnak.datavalue.value end end end -- Images par défaut local isdefault = false if #images == 0 then if params.maintenancecat then local maintenancecat = getvalue(params.maintenancecat, params) addmaintenancecat(maintenancecat, params.sortkey) end if params.defaultimages then images = params.defaultimages if type(images) == 'string' then images = {images} end end size, caption, link = params.defaultimagesize, params.defaultimagecaption, params.defaultimagelink end if #images == 0 then return nil end size = size or getvalue(params.sizeparameter) or params.defaultsize or '280x400px' link = link or getvalue(params.linkparameter) or params.defaultlink caption = caption or getvalue(params.captionparameter) or params.defaultcaption or '' if type(size) == 'function' then size = size(localdata) end if type(link) == 'function' then link = link() end if type(caption) == 'function' then caption = caption(localdata) end local numsize = mw.ustring.gsub(size, 'x.*', '') numsize = numsize:gsub('px', '') numsize = tonumber(numsize) if type(numsize) ~= 'number' or numsize > 280 then addmaintenancecat("taille d'image invalide") end if link then link = '|link=' .. link else link = '' end local style = params.style or {padding ='2px 0',} -- Partie image local imagesString = '' for i,image in pairs(images) do if image == '-' then return end imagesString = imagesString .. '[[Fichier:' .. image .. link .. '|frameless|' .. size 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') :addClass("images") :css(style) :wikitext(imagesString) -- Partie légende local captionobj = mw.html.create('p') if caption then captionobj :wikitext(caption) :css(params.style or {}) :addClass("legend") :done() end -- séparateur local separator if params.separator then local separatorStyle = params['separator style'] or {} separatorStyle.height = separatorStyle.height or '2px' separatorStyle['background-color'] = separatorStyle['background-color'] or maincolor separator = mw.html.create('hr') separator:css( separatorStyle ) end return mw.html.create('div'):node(image):node(captionobj):node(separator):done() end function p.buildtext(params) local class = params.class or '' local style = defaultstyle['boldline'] if params.style then for i, j in pairs(params.style) do style[i] = j end 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 function p.buildrow(params) local class = params.class or '' local style = params.style or {} local value, number = getvalue(params.value, params) if not value then value, number = getWikidataValue(params, 'wikidata') end if (not value) and (params.property) then value, number = expandquery({property = params.property}) -- the property key takes a string value, that would not work well using the wikidata key end if not value then value = params.defaultvalue end if value == '-' then return nil end if not number then number = 0 -- == indéfini end if not value then if params.maintenancecat then local maintenancecat = getvalue(params.maintenancecat, params) addmaintenancecat(maintenancecat, params.sortkey) end return nil end local label = params.label if number > 1 and (params.plurallabel) then label = params.plurallabel elseif number == 1 and (params.singularlabel) then label = params.singularlabel end if type(label) == 'function' then label = label(localdata, item) end -- format local formattedvalue = mw.html.create('div') :wikitext('\n' .. value) -- Le '\n' est requis lorsque value est une liste commençant par '*' ou '#' 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 if label then formattedlabel = mw.html.create('th') :attr('scope', 'row') :wikitext(label) :done() end local row = mw.html.create('tr') :addClass(class) :css(style) :node(formattedlabel) :node(formattedvalue) :done() return row end function p.buildtable(params) local tab = mw.html.create('table'):css(params.style or {}) 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 params.title = {} else text = getvalue(title.value) or error('no value provided for this title') end local titlestyle = params.title.style or {['text-align'] = 'center', color = '000000'} if not titlestyle['background-color'] then titlestyle['background-color'] = maincolor end local colspan = params.title.colspan or '2' title = mw.html.create('caption') :attr({colspan = 2}) :css(titlestyle) :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) == 'table' and l.type == 'multi' then -- when a single function is used for return several rows table.remove(params.rows, k) local count = 0 for m, n in pairs(l.rows) do table.insert(params.rows, k + count, n) count = count + 1 end l = params.rows[k] end 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)) else local row = p.buildblock(l) table.insert(rows, row) end end if #rows > 0 then if title then tab:node(title) end for i, j in pairs (rows) do tab:node(j) end tab:allDone() return tab else return nil end end function p.buildinvalidblock(args) addmaintenancecat(defaultcat) local text = '' if type(args) ~= 'table' then text = "Les blocs d'infobox doivent être des tables" else text = i18n["invalid block type"] .. ' : ' .. (args.type or '??') end return text end function p.buildmap(params) local maplist = getvalue(params.maps) local pointimage = params.pointimage local maptype = params.maptype -- choisit le type de carte le plus approprié (relief, administratif, etc.) if type(maplist) == 'function' then maplist = maplist(localdata, item) end local width = tonumber(params.width) or 280 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 local latitude, longitude if type(params.latitude) == 'function' then latitude, longitude = params.latitude(localdata, item), params.longitude(localdata, item) else latitude, longitude = localdata[params.latitude], 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(item, query) 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 local newparams = {maplist = maplist, pointimage = pointimage, width = width, item = item, latitude = latitude, longitude = longitude} if params.params and type(params.params) == 'table' then -- paramètres additionnels for i, j in pairs(params.params) do newparams[i] = j end end return mapmod.multimap(newparams) end function p.buildfooter(params) if not params then params = {} end local class = 'navbar noprint ' .. (params.class or '') local style = params.style or {} style['border-top'] = style['border-top'] or '1px solid ' .. maincolor local backlinkstr = '[' .. tostring( mw.uri.fullUrl( page.name, '&veaction=edit§ion=0' ) ) .. ' ' .. i18n['edit'] .. ']' .. ' - [' .. tostring( mw.uri.fullUrl( page.name, '&action=edit§ion=0' ) ) .. ' ' .. i18n['edit code'] .. ']' 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=' .. localdata.templatename .. '|' .. i18n['see doc'] .. ']]' -- si ce lien ne marche pas toujours, il faut ajouter un variable pour le nom de l'infobox récupéré par le frame 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.buildblock(block) if type(block) == 'function' then block = block() end local blocktypes = { -- list of functions for block buildings ['invalid'] = p.buildinvalidblock, ['external text'] = p.buildexternaltext, ['footer'] = p.buildfooter, ['images'] = p.buildimages, ['map']= p.buildmap, ['mixed'] = p.buildrow, ['navbox'] = p.buildnavbox, ['table'] = p.buildtable, ['row'] = p.buildrow, ['text'] = p.buildtext, ['title'] = p.buildtitle, } if type(block) ~= 'table' or (not block.type) or (not blocktypes[block.type]) then return blocktypes['invalid'](block) end return blocktypes[block.type](block) end function p._build(modulename, params, templatename) -- fill-up global variable localdata using params for i, j in pairs(params) do if j and mw.text.trim(j) ~= '' then -- empty parameters are ignored localdata[i] = j end end localdata.templatename = templatename or modulename -- guess "rank" of the infobox local infoboxrank = 'main' -- main infobox of the page, with coordinates displayed in title etc. if page.namespace ~= 0 then infoboxrank = 'secondary' end localdata.infoboxrank = infoboxrank -- load wikidata item as a global variable: if localdata.wikidata == 'non' then item = nil elseif (not localdata.wikidata) or (localdata.wikidata == '') then item = mw.wikibase.getEntityObject() else item = nil -- topic of the infobox corresponds to another Wikidata item, should eventually be fetched through arbitrary access localdata.infoboxrank = 'secondary' end -- load infobox module page moduledata = require('Module:Infobox/' .. modulename) moduledata.name = modulename -- defines main color maincolor = localdata['couleur infobox'] or localdata['couleur boîte'] or moduledata.maincolor or maincolor if maincolor:match( '^%x%x%x%x%x%x$' ) or maincolor:match( '^%x%x%x$' ) then maincolor = '#' .. maincolor end -- class local class = 'infobox_v3' if moduledata.class then class = class .. ' ' .. moduledata.class end -- style local style = moduledata.style or {} if not style['max-width'] then style['max-width'] = '300px' end -- build infobox infobox :addClass(class) :css(style) for i, j in pairs( moduledata.parts ) do infobox:node( p.buildblock(j) ) end infobox :node(p.buildfooter(moduledata.footer)) :done() return tostring(infobox) .. externaltext, maintenance end function p.build(frame) local name = frame.args.nom local parent = frame:getParent() local templatename = parent:getTitle() -- au cas où il soit différent du nom du module local params = parent.args return p._build(name, params, templatename) end return p