Module:Infobox
Révision datée du 29 janvier 2016 à 17:05 par Zolo (discussion) (récupération de la légende de Wikidata, si l'image provient de Wikidata)
La documentation pour ce module peut être créée à Module:Infobox/doc
local p = {} local lang = 'fr' -- 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 page = { -- données concernant la page où est affichée l'infobox name = mw.title.getCurrentTitle().prefixedText, namespace = mw.title.getCurrentTitle().namespace } local maincolor, secondcolor = '#E1E1E1', '#000000' -- 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:Interface Wikidata".fromLua 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 .. wikidata.addtrackingcat(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.separator(params) local style = params['separator style'] or {} style.height = style.height or '2px' style['background-color'] = style['background-color'] or maincolor return mw.html.create('hr'):css( style ) 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 = {} style['background-color'] = maincolor style['color'] = secondcolor 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 upright, link, caption, size -- size is deprecated 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{entity = 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 local wdcaptions, wdcaption local q = images[i].qualifiers if q then wdcaptions = q['P2096'] end if wdcaptions then for k, l in pairs(wdcaptions) do if l.datavalue.value and l.datavalue.value.language == lang then wdcaption = wd.formatSnak(l) end end end if wdcaption and caption then -- si deux légendes, désactivées pour éviter les conflits caption = nil elseif wdcaption then caption = wdcaption 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 upright, caption, link = params.defaultimageupright, params.defaultimagecaption, params.defaultimagelink end if #images == 0 then return nil end upright = size or getvalue(params.uprightparameter) or params.defaultupright or "1.2" 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 -- taille avec "size" (obsolète) size = size or getvalue(params.sizeparameter) or params.defaultsize -- deprecated if size then local numsize = size:gsub('px', '') numsize = mw.ustring.gsub(numsize, 'x.*', '') numsize = tonumber(numsize) if type(numsize) ~= 'number' or numsize > 280 then addmaintenancecat("taille d'image invalide") end if tonumber(size) then size = size .. 'px' end size = '|' .. size else size = '' 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 upright then imagesString = imagesString .. '|upright=' .. 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 separator = separator(params) 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 {}) -- CREATE ROWS local rows = {} 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 return nil end -- ADD TITLE local title if params.title or params.singulartitle or params.pluraltitle then local text if #rows > 1 and params.pluraltitle then text = pluraltitle elseif #rows == 1 and params.singulartitle then text = pluraltitle else text = params.title end local style = params.titlestyle or {} style['text-align'] = style['text-align'] or 'center' style['color'] = style['color'] or secondcolor style['background-color'] = style['background-color'] or maincolor local colspan ='2' title = mw.html.create('caption') :attr({colspan = colspan}) :css(style) :wikitext(text) :done() end if title then tab:node(title) end for i, j in pairs (rows) do tab:node(j) end if params.separator then local separator = p.separator(params) tab:node(separator) end tab:allDone() return tab 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)-- TODO : gestion de plusieurs points local maplist = getvalue(params.maps) local pointtype = params.pointtype 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 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 params.wikidata then local query = params.wikidata if type(query) == 'function' then query = query() end if not query then return nil end query.excludespecial = true query.entity = query.entity or item local claims = wikidata.getClaims(query) if not claims then return nil end local val = claims[1].mainsnak.datavalue.value latitude, longitude = val.latitude, val.longitude end if not latitude or not longitude then return nil end local newparams = {maplist = maplist, pointtype = pointtype, maptype = maptype, 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:Info Simple.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 -- load wikidata item as a global variable: if localdata.wikidata == '-' then item = nil else item = wikidata.getEntity(localdata.wikidata) end -- assign rank to the infobox, "secondary" means special formatting like no displaytitle for coordinates local infoboxrank = 'main' -- main infobox of the page, with coordinates displayed in title etc. if page.namespace ~= 0 then infoboxrank = 'secondary' end -- if infobox is linked to another item: rank = secondary if item then local itemlink = mw.wikibase.sitelink(item.id) local pagetitle = mw.title.getCurrentTitle().text if (itemlink or '') ~= pagetitle then infoboxrank = 'secondary' end end localdata.infoboxrank = infoboxrank -- 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 secondcolor = moduledata.secondcolor or secondcolor 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