Aller au contenu

Module:Titulaires

Une page de Wikipédia, l'encyclopédie libre.
Ceci est une version archivée de cette page, en date du 30 mars 2019 à 06:40 et modifiée en dernier par Alt0160 (discuter | contributions) (Grouper les sources identiques). Elle peut contenir des erreurs, des inexactitudes ou des contenus vandalisés non présents dans la version actuelle.

 Documentation[voir] [modifier] [historique] [purger]

Utilisation

Le module Titulaires est constitué de différentes parties. Ses fonctions sont réutilisées par les modèles {{Titulaires}} et {{Liste des dirigeants successifs}}.

local countryData = require 'Module:Country data'
local duration = require 'Module:Durée'
local formatDate = require 'Module:Date complexe'
local image = require 'Module:Image'
local langue = require 'Module:Langue'
local linguistic = require 'Module:Linguistique'
local n2t = require 'Module:Nombre2texte'
local romains = require 'Module:Chiffres romains'
local wikidata = require 'Module:Wikidata'

local p = {}

local wikidataProperties = {
	['chef d\'État'] = {
		fonction = 'P1906',
		plurielFonction = 'Chefs d\'État',
		listeIndividus = 'P35',
	},
	['chef de l\'exécutif'] = {
		fonction = 'P1313',
		plurielFonction = 'Chefs de l\'exécutif',
		listeIndividus = 'P6',
	},
	['dirigeant'] = {
		plurielFonction = 'Dirigeants',
		listeIndividus = 'P1037'
	},
	['président'] = {
		plurielFonction = 'Présidents',
		listeIndividus = 'P488'
	},
	['secrétaire général'] = {
		plurielFonction = 'Secrétaires généraux',
		listeIndividus = 'P3975'
	},
	['directeur général'] = {
		plurielFonction = 'Directeurs généraux',
		listeIndividus = 'P169'
	},
	['membre du conseil d\'administration'] = {
		plurielFonction = 'Membres du conseil d\'administration',
		listeIndividus = 'P3320'
	},
	['commandant'] = {
		plurielFonction = 'Commandants',
		listeIndividus = 'P4791'
	}
}

local charterToClass = {
	['localité'] = 'localites',
	['commune'] = 'communes',
	['canton'] = 'cantons',
	['arrondissement'] = 'arrondissements',
	['intercommunalité'] = 'intercommunalites',
	['département'] = 'departements',
	['région'] = 'regions'
}

-- Association élément → Charte
local charterMap = {
	Q3455524 = 'région',
	Q6465 = 'département',
	Q702842 = 'arrondissement',
	Q2311958 = 'canton',
	Q3266850 = 'commune',  -- commune
	Q15284 = 'commune', -- municipalité
	Q515 = 'commune' -- ville
}

local function getArgumentValue(argName, leaderType, args)
	if args[argName] then
		return args[argName]
	end
	if leaderType and args[argName .. ' ' .. leaderType] then
		return args[argName .. ' ' .. leaderType]
	end
end

local function getBooleanValue(argName, leaderType, args, default)
	if default == 'always' then
		return true
	end
	local argValue = getArgumentValue(argName, leaderType, args)
	argValue = argValue and string.lower(argValue)
	if argValue == 'non' then
		return false
	elseif argValue == 'oui' then
		return true
	else
		return default
	end
end

local function getCharterRecursively(entity, maxDepth) -- fonction permettant d'aller chercher la charte
	local candidates = {entity}
	for i = 0, maxDepth do
		local newCandidates = {}
		if i == 0 then
			recursiveProperty = 'P31' -- nature de l'élément
		else
			recursiveProperty = 'P279' -- sous-classe
		end
		for _, candidate in pairs(candidates) do
			local superclasses = wikidata.getIds(candidate, {removedupes = true,
				property = recursiveProperty, rank = 'valid'})
			
			newCandidates = wikidata.addNewValues(newCandidates, superclasses)
		end
		
		if #newCandidates == 0 then
			return nil
		end
		
		for _, candidate in pairs(newCandidates) do
			local charte = charterMap[candidate]
			if charte then
				return charte
			end
		end
		
		candidates = newCandidates
	end
end

local function getOfficesRecursively(entity, officeProp, maxDepth)
	if not officeProp then
		return nil
	end
	local candidates = {entity}
	for i = 0, maxDepth do
		local officesTable = {}
		for _, candidate in pairs(candidates) do
			local claims = wikidata.getClaims({entity = candidate,
				property = officeProp, rank = 'valid'})
			officesTable = wikidata.addNewValues(officesTable, claims)
		end
		
		if #officesTable > 0 then
			stringTable, _ = wikidata.stringTable({
				claims = wikidata.chronoSort(officesTable), removedupes = true,
				--[[Si une page correspondant à la fonction n'est pas disponible
				 sur Wikipédia en français, essayer d'obtenir la page de liste
				 correspondante (e.g. Liste des maires de Paris) et, si non
				 disponible, la superclasse
				 ]]
				defaultlinkquery = {property = {'P2354', 'P279'}},
				--Afficher les dates de validité de la fonction
				showdate = true
			})
			local formattedOffices = linguistic.conj(stringTable, 'or')
			if i == 0 then
				return formattedOffices
			else
				local locationName = wikidata.getLabel(entity)
				return formattedOffices .. ' ' .. linguistic.of(locationName)
			end
		end

		local newCandidates = {}
		if i == 0 then
			recursiveProperty = 'P31' -- nature de l'élément
		else
			recursiveProperty = 'P279' -- sous-classe
		end
		for _, candidate in pairs(candidates) do
			local superclasses = wikidata.getIds(candidate, {removedupes = true,
				property = recursiveProperty, rank = 'valid'})
			newCandidates = wikidata.addNewValues(newCandidates, superclasses)
		end
		
		if #newCandidates == 0 then
			return nil
		end
		
		candidates = newCandidates
	end
end

local function getDefaultTitle(entity, wProps)
	local formattedOffices = getOfficesRecursively(entity, wProps.fonction, 5)
	
	if formattedOffices then
		return 'Individus ayant assumé la fonction de ' .. formattedOffices .. '.'
	end

	local locationName = wikidata.getLabel(entity)
	if locationName then
		return wProps.plurielFonction .. ' ' .. linguistic.of(locationName) .. '.'
	end
	return wProps.plurielFonction .. '.'
end

local function getDeterminationMethod(statement) -- fonction permettant d'aller chercher la méthode de détermination, comme une élection
	local params = {conjtype = 'new line', removedupes = true,
		displayFormat = 'raw'}
	return wikidata.getFormattedQualifiers(statement, 'P459', params)
end

local function getEndCause(statement) -- fonction permettant d'aller chercher le motif de fin, comme une mort en cours de mandat ou une démission
	local params = {conjtype = 'comma', removedupes = true,
		displayFormat = 'raw'}
	return wikidata.getFormattedQualifiers(statement, 'P1534', params)
end

local function dateObject(orig)
	--[[ transforme un snak en un nouvel objet utilisable par Module:Date complexe
		{type = 'dateobject', timestamp = str, era = '+' ou '-', year = number, month = number, day = number, calendar = calendar}
		Inspiré de Module:Wikidata
	]]-- 
	local newobj = formatDate.splitDate(orig.time, orig.calendarmodel)
	
	newobj.precision = orig.precision
	newobj.type = 'dateobject'
	return newobj
end

-- établit la variable gender pour l'élément
-- copié depuis Module:Infobox/Fonctions/Personne
local function getGenderedValue(entity, valueF, valueM, valueDefault)
	local gender = wikidata.formatStatements{entity = entity, property = 'P21',
		displayformat = 'raw'}
	if gender == 'Q6581072' or gender == 'Q1052281' or gender == 'Q43445' then
		return valueF
	elseif gender == 'Q6581097' or gender == 'Q2449503' or gender == 'Q44148' then
		return valueM
	else
		return valueDefault
	end
end

local function getDateObjectFromQualif(statement, qualif)
	if (not statement.qualifiers) or not (statement.qualifiers[qualif]) then
		return nil
	end
	local v = statement.qualifiers[qualif][1]
	if v.snaktype == 'value' then
		return dateObject(v.datavalue.value)
	end
end

local function getDateObjectFromProperty(entity, property)
	-- dateObject
	local claim = wikidata.getClaims({entity = entity, property = property,
		numval=1})
	if not claim then
		return
	end
	local snak = claim[1].mainsnak
	if snak.snaktype == 'value' then
		return dateObject(snak.datavalue.value)
	end
end

local function getDateWithPrefix(dateObject)
	local formattedDate = formatDate.simplestring(dateObject)
	local prefix
	if dateObject.precision <= 7 then  -- siècle, millénaire, ...
		prefix = 'au '
	elseif dateObject.precison == 8 then  -- décennie
		prefix = 'dans les '
	elseif dateObject.precision <= 10 then  -- mois, année, décénnie
		prefix = 'en '
	else  -- jour et moins
		prefix = 'le '
	end
	return prefix .. formattedDate
end

local function getBirthDeathDates(statement)
	local entity = wikidata.getMainId(statement)
	local dateOfBirth = getDateObjectFromProperty(entity, 'P569')
	local dateOfDeath = getDateObjectFromProperty(entity, 'P570')
	
	if dateOfBirth and dateOfDeath then
		return formatDate.simplestring(dateOfBirth)
		.. '-' 
		.. formatDate.simplestring(dateOfDeath)
	elseif dateOfBirth then
		return getGenderedValue(entity, 'née ', 'né ', 'né(e) ')
			.. getDateWithPrefix(dateOfBirth)
	elseif dateOfDeath then
		return getGenderedValue(entity, 'morte ', 'mort ', 'mort(e) ')
			.. getDateWithPrefix(dateOfDeath)
	end
end

local langDirCache = {}  -- cache pour la direction d'une langue

local function getNameInOtherLanguage(statement, lang)
	local entity = wikidata.getMainId(statement)
	local label = wikidata.getLabel(entity, lang)
	if label then
		local dir = langDirCache[lang]
		if not dir then
			dir = langue.directionLangue({lang})
			langDirCache[lang] = dir  -- stocker la direction dans le cache
		end
		return langue.indicationDeLangue({'', lang, texte = label, dir = dir})
	end
end

local function sourceStr(sources, groupSameSources)
	if not sources or (#sources == 0) then
		return nil
	end
	
	local frame = mw.getCurrentFrame()
	for i, source in pairs(sources) do
		local refArgs = {name = 'ref', content = source}
		if groupSameSources then
			-- Ajout du nom de la référence pour le groupement
			refArgs.args = {name = 'source-from-wikidata-' 
				.. mw.hash.hashValue('sha3-512', source)}
		end
		sources[i] = mw.getCurrentFrame():extensionTag(refArgs)
	end
	return table.concat(sources, '<sup class="reference cite_virgule">,</sup>')
end

local function getIdentity(statement, params)
	local name = wikidata.formatSnak(statement.mainsnak) or ''
	
	local showSources = getBooleanValue('sources', params.leaderType,
		params.args, true)
	if showSources then
		local references = wikidata.getReferences(statement)
		local groupSameSources = getBooleanValue('grouper les sources',
			params.leaderType, params.args, true)
		local formattedReferences = sourceStr(references, groupSameSources)
		name = name .. (formattedReferences or '')
	end
	
	local showNameInOtherLanguage = getArgumentValue('nom dans la langue',
		params.leaderType, params.args)
	if showNameInOtherLanguage then
		local labelInOtherLanguage = getNameInOtherLanguage(statement, 
			showNameInOtherLanguage)
		if labelInOtherLanguage then
			name = name .. '<br />' .. labelInOtherLanguage
		end
	end
	
	local showDoBDoD = getBooleanValue('dates de vie', params.leaderType,
		params.args, true)
	if showDoBDoD then
		local dates = getBirthDeathDates(statement)
		if dates then
			name = name .. '<br /><small>(' .. dates .. ')</small>'
		end
	end
	
	return name
end

local function getCitizenship(statement)
	local entity = wikidata.getMainId(statement)
	return countryData.getNationality({item = entity, mindate = '-',
		conjtype = 'new line'})
end

local function getSeriesOrdinal(statement)
	local params = {conjtype = 'comma', removedupes = true}
	return wikidata.getFormattedQualifiers(statement, 'P1545', params)
end

local function getStartDate(statement)
	local dateObj = getDateObjectFromQualif(statement, 'P580')
	return formatDate.simplestring(dateObj)
end

local function textWithSortValue(text, sortValue)
	return tostring(mw.html.create('span')
		:attr('data-sort-value', sortValue)
		:wikitext(text)
		:done())
end

-- Valeur "en cours", avec clé de tri maximale, affichée grâce à un rang privilégié
local currentNode = textWithSortValue('En cours', '999999-12-12')

local function getEndDate(statement, params)
	local dateObj = getDateObjectFromQualif(statement, 'P582')
	if dateObj then
		local endDate = formatDate.simplestring(dateObj)
		local endCause = getEndCause(statement)
		if endCause then
			return endDate .. '<br /><small>(' .. endCause .. ')</small>'
		end
		return endDate
	elseif params.latest and statement.rank == 'preferred' then
		return currentNode
	end
end

local function getDuration(statement, params)
	local startDate = getDateObjectFromQualif(statement, 'P580')
	if not startDate then
		return
	end
	local precision = startDate.precision
	local endDate = getDateObjectFromQualif(statement, 'P582')
	if endDate then
		precision = math.min(precision, endDate.precision)
	elseif not (params.latest and statement.rank == 'preferred') then
		-- Mandat non considéré comme "en cours"
		return
	else
		endDate = {}
	end
	if precision < 9 then
		-- No year
		return
	end
	if precision < 11 then
		-- No day
		startDate.day = nil
		endDate.day = nil
		if precision < 10 then
			-- No month
			startDate.month = nil
			endDate.month = nil
		end
	end
	return duration._duree({startDate.day, startDate.month, startDate.year,
		endDate.day, endDate.month, endDate.year})
end
	

local function getPartyColoredSquare(qid) -- Permet d'aller chercher la couleur politique d'un parti ; celle-ci est définie dans son élément via la propriété P465 couleur triplet hexadécimal sRGB
	local partyColor = wikidata.formatStatements{entity = qid,
		property = 'P465', numval = 1}
	if partyColor then
		return mw.getCurrentFrame():expandTemplate{
			title = 'Carré couleur', args = {'#' .. partyColor }
		}
	end
end

local function getPartyOrParliamentaryGroup(statement, prop,
		showPoliticalColors)
	local qualifiers = wikidata.getQualifiers(statement, prop)
	if not qualifiers then
		return nil
	end

	for i, qualifier in pairs(qualifiers) do
		local formattedSnak = wikidata.formatSnak(qualifier)
		local qid = wikidata.getId(qualifier)
		if qid and showPoliticalColors then
			local coloredSquare = getPartyColoredSquare(qid)
			if coloredSquare then
				formattedSnak = coloredSquare .. ' ' .. formattedSnak
				local partyName = wikidata.getLabel(qid)
				if partyName then
					formattedSnak = textWithSortValue(formattedSnak, partyName)
				end
			end
		end
		qualifiers[i] = formattedSnak
	end
	return linguistic.conj(qualifiers, 'new line')
end

local function shouldShowPoliticalColors(params)
	return getBooleanValue('couleur politique', params.leaderType,
		params.args, false)
end

local function getParty(statement, params)
	return getPartyOrParliamentaryGroup(statement, 'P102',
		shouldShowPoliticalColors(params))
end

local function getParliamentaryGroup(statement, params)
	return getPartyOrParliamentaryGroup(statement, 'P4100',
		shouldShowPoliticalColors(params))
end

local function getPositionsHeld(statement)
	local params = {conjtype = 'new line', removedupes = true}
	return wikidata.getFormattedQualifiers(statement, 'P39', params)
end

local function getParliamentaryOrdinal(entity)
	-- Recherche de nature de l'élément = Q15238777
	local legislativeTermInfos = wikidata.getClaims({entity = entity,
		property = 'P31', rank = 'valid', targetvalue = 'Q15238777',
	})
	if not legislativeTermInfos then
		return nil
	end
	
	for _, legislativeTermInfo in pairs(legislativeTermInfos) do
		if legislativeTermInfo.qualifiers then
			local parliamentaryTermOf = legislativeTermInfo.qualifiers['P642']
			local seriesOrdinal = legislativeTermInfo.qualifiers['P1545']
			if parliamentaryTermOf and #parliamentaryTermOf == 1
					and seriesOrdinal and #seriesOrdinal == 1
					and seriesOrdinal[1].snaktype == 'value' then
				return tonumber(seriesOrdinal[1].datavalue.value)
			end
		end
	end
end

local function getParliamentaryTermLabel(ordinal)
	local exposant
	if ordinal == 1 then exposant = 're' else exposant = 'e' end
	
	local seriesOrdinalValueText = n2t.nombre2texte_reel(ordinal, nil,
		'ordinal', nil, 'féminin')
		
	return tostring(mw.html.create('span')
		:attr('title', seriesOrdinalValueText)
		:node(romains._ChiffresRomains(ordinal) .. '<sup>' .. exposant .. '</sup>')
		:done())
end

local function getParliamentaryTerm(statement, params)
	if not statement.qualifiers then
		return nil
	end

	local qualifiers = statement.qualifiers['P2937'] -- Législature
	if not qualifiers or #qualifiers == 0 then
		return nil
	end
	
	local ordinalLabels = {}
	local smallestOrdinal
	
	local abbreviateLegislature = getBooleanValue('abréger législature',
		params.leaderType, params.args, true)
	if abbreviateLegislature then
		local countOrdinals = 0
		for i, qualifier in ipairs(qualifiers) do
			local qualifierId = wikidata.getId(qualifier)
			local ordinal = getParliamentaryOrdinal(qualifierId)
			if ordinal then
				ordinalLabels[qualifierId] = getParliamentaryTermLabel(ordinal)
				qualifier._parliamentOrdinal = ordinal
				countOrdinals = countOrdinals + 1
			end
		end
		
		if countOrdinals == #qualifiers then
			-- Autant d'ordinaux que de qualifiers, on peut trier
			table.sort(qualifiers,
				function(a, b)
					return a._parliamentOrdinal < b._parliamentOrdinal
				end)
			smallestOrdinal = qualifiers[1]._parliamentOrdinal
		end
	end

	for i, qualifier in ipairs(qualifiers) do
		qualifiers[i] = wikidata.formatSnak(qualifier,
			{defaultlinkquery = 'P2354',
				labelformat = function(qid)
					return ordinalLabels[qid] or mw.wikibase.label(qid)
				end
			})
	end
	
	local str = linguistic.conj(qualifiers, 'and')
	if smallestOrdinal then
		return textWithSortValue(str, smallestOrdinal)
	end
	return str
end

local function getPicture(statement)
	local entity = wikidata.getMainId(statement)
	local claims = wikidata.getClaims({entity = entity, rank = 'best',
		property = 'P18', numval = 1})
	local caption
	local mediaName
	
	if claims then
		local claim = claims[1]
	
		mediaName = wikidata.formatStatement(claim)
		caption = wikidata.getFormattedQualifiers(claim, {'P2096'},
			{isinlang = 'fr', conjtype = 'comma'})

		if not caption then
			local personName = mw.wikibase.label(entity)
			if personName then
				caption = personName
				local pictureDate = wikidata.getFormattedQualifiers(claim,
					{'P585'}, {conjtype = 'comma'})
				if pictureDate then
					caption = caption .. ', ' .. pictureDate .. '.'
				end
			end
		end
	else
		-- Pas de portrait
		mediaName = getGenderedValue(entity,
			'Gray - replace this image female.svg',
			'Gray - replace this image male.svg',
			'Sin foto.svg')
		local personName = mw.wikibase.label(entity)
		caption = 'Pas de portrait sous licence libre disponible pour '
			.. personName .. '.'
	end
	
	return image.image({image = mediaName, taille = '80',
		['légende'] = caption})
end

local numero = tostring(mw.html.create('abbr')
	:wikitext('N<sup>o</sup>')
	:addClass('abbr')
	:attr('title', 'numéro')
	:done())

local cellKindProperties = {
	['ordre'] = {fn = getSeriesOrdinal, dataSortType = 'unsortable',
		columnName = numero},
	['portrait'] = {fn = getPicture, dataSortType = 'unsortable'},
	['identité'] = {fn = getIdentity, dataSortType = 'text'},
	['nationalité'] = {fn = getCitizenship, dataSortType = 'text'},
	['début'] = {fn = getStartDate},
	['fin'] = {fn = getEndDate},
	['durée'] = {fn = getDuration},
	['étiquette'] = {fn = getParty, dataSortType = 'text'},
	['groupe parlementaire'] = {fn = getParliamentaryGroup, dataSortType = 'text'},
	['fonction'] = {fn = getPositionsHeld, dataSortType = 'text'},
	['législature'] = {fn = getParliamentaryTerm, dataSortType = 'number'},
	['méthode de détermination'] = {fn = getDeterminationMethod,
		dataSortType = 'text', columnName = 'Déterminé par'},
}

local multiColumns = {
	['période'] = {'début', 'fin'}
}

local orderedColumnsWithDefaultVisibility = {
	{name = 'ordre', defaultVisibility = false},
	{name = 'portrait', defaultVisibility = false},
	{name = 'identité', defaultVisibility = 'always'},
	{name = 'nationalité', defaultVisibility = false},
	{name = 'période', defaultVisibility = true},
	{name = 'durée', defaultVisibility = true},
	{name = 'étiquette', defaultVisibility = false},
	{name = 'groupe parlementaire', defaultVisibility = false},
	{name = 'fonction', defaultVisibility = false},
	{name = 'législature', defaultVisibility = false},
	{name = 'méthode de détermination', defaultVisibility = false},
}

local function shouldShowColumn(column, leaderType, args)
	return getBooleanValue(column.name, leaderType, args,
		column.defaultVisibility)
end

local function getColumnsAndCellKinds(args, leaderType)
	local headerColumns = {}
	local cellKinds = {}
	
	for _, column in ipairs(orderedColumnsWithDefaultVisibility) do
		if shouldShowColumn(column, leaderType, args) then
			table.insert(headerColumns, column.name)
			local columnCellKinds = multiColumns[column.name] or {column.name}
			for _, cellKind in ipairs(columnCellKinds) do
				table.insert(cellKinds, cellKind)
			end
		end
	end
	
	return headerColumns, cellKinds
end

local function getHeaderBaseCell(column)
	columnProperties = cellKindProperties[column] or {}

	local columnName = columnProperties.columnName or linguistic.ucfirst(column)
	local baseCell = mw.html.create('th')
		:attr('scope', 'col')
		:wikitext(columnName)
		
	local dataSortType = cellKindProperties[column] 
		and cellKindProperties[column].dataSortType
	if dataSortType then
		if dataSortType == 'unsortable' then
			baseCell = baseCell:addClass('unsortable')
		else
			baseCell = baseCell:attr('data-sort-type', dataSortType)
		end
	end

	return baseCell
end

local function getHeader(columns)
	local headerFirstRow = mw.html.create('tr')
	local headerSecondRow = mw.html.create('tr')
		
	for _, column in pairs(columns) do
		local cell = getHeaderBaseCell(column)
			
		local subcolumns = multiColumns[column]
		if subcolumns then
			cell = cell:attr('colspan', #subcolumns)
			for _, subColum in ipairs(subcolumns) do
				headerSecondRow:node(getHeaderBaseCell(subColum):done())
			end
		else
			cell = cell:attr('rowspan', 2)
		end
		
		headerFirstRow = headerFirstRow:node(cell:done())
	end
	
	return headerFirstRow:done(), headerSecondRow:done()
end

local function getLeaderRow(cellKinds, statement, params)
	local row = mw.html.create('tr'):css({['vertical-align'] = 'top'})
		
	for _, cellKind in pairs(cellKinds) do
		local success, result = pcall(cellKindProperties[cellKind].fn, statement, params)
		if not success then
			result = tostring(mw.html.create('span')
				:wikitext('Erreur')
				:attr('title', result)
				:css('font-style', 'italic')
				:css('font-size', 'small')
				:done())
		end
		row = row:node(mw.html.create('td')
			:wikitext(result or '')
			:done())
	end
	
	return row:done()
end

local function getTitle(args, leaderType, entity, wProps)
	local title = args['titre ' .. leaderType] 
		or args.titre 
		or getDefaultTitle(entity, wProps)
	
	-- Bouton d'édition wikidata
	title = wikidata.addLinkBack(title, entity, wProps.listeIndividus)
	
	-- Formattage du titre
	return mw.html.create('caption')
		:wikitext(title)
		:done()
end

local function peopleList(entity, args, wPropsList, charter)
	if not entity then
		return mw.html.create('span')
			:addClass('error')
			:wikitext('Pas d\'entité Wikidata pour l\'élément.')
			:done()
	end
	
	local params = {entity = entity, args = args}
	
	local maxWidth = args['largeur maximale'] or '900px'
		
	local tables = {}
	for leaderType, wProps in pairs(wPropsList) do
		local elus = wikidata.getClaims({entity = entity,
			property = wProps.listeIndividus, sorttype = 'chronological',
			rank = 'valid'})
		
		if elus then
			local title = getTitle(args, leaderType, entity, wProps)
			
			local headerColumns, cellKinds = getColumnsAndCellKinds(args,
				leaderType)
			
			local firstHeadRow, secondHeaderRow = getHeader(headerColumns)
			
			local tab = mw.html.create('table')
				:addClass('wikitable')
				:addClass('centre')
				:addClass('sortable')
				:addClass(charterToClass[charter])
				:css('max-width', maxWidth)  -- largeur maximale du tableau
				:node(title)  -- titre
				:node(firstHeadRow)  -- première ligne
				:node(secondHeaderRow)  -- deuxième ligne
				
			params.latest = 0
			params.leaderType = leaderType
			-- Ajout des lignes des dirigeants
			for i, statement in ipairs(elus) do
				if i == #elus then
					params.latest = 1
				end
				local leaderRow = getLeaderRow(cellKinds, statement, params)
				tab = tab:node(leaderRow)
			end

			table.insert(tables, tostring(tab:done()))
		end
	end
	
	return table.concat(tables, '\n')
end

function p.listeDesDirigeantsSuccessifs(frame)
	local templateArgs = frame:getParent().args
	
	-- Entité Wikidata
	local entity = wikidata.getEntity(templateArgs.wikidata)
	
	local wPropsList
	if templateArgs.types then
		wPropsList = {}
		for leaderType in mw.text.gsplit(templateArgs.types, '%s*,%s*') do
			wPropsList[leaderType] = wikidataProperties[leaderType]
		end
	else
		wPropsList = wikidataProperties
	end
	
	-- Charte
	local charter = templateArgs.charte or getCharterRecursively(entity, 2)
	
	return peopleList(entity, templateArgs, wPropsList, charter)
end
 
return p