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 4 avril 2019 à 10:46 et modifiée en dernier par Alt0160 (discuter | contributions) (Simplification et optimisation). 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 langue = require 'Module:Langue'
local linguistic = require 'Module:Linguistique'
local roman = require 'Module:Romain'
local tools = require 'Module:Outils'
local wikidata = require 'Module:Wikidata'
local yn = require 'Module:Yesno'

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(params, argName)
	return tools.validTextArg(params.args, argName,
		argName .. ' ' .. params.leaderType)
end

local function getBooleanArgumentValue(params, argName, default)
	return yn(getArgumentValue(params, argName) or '', default)
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)
		.. '&nbsp;- ' 
		.. 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 getIdentity(statement, params)
	local name = wikidata.formatSnak(statement.mainsnak) or ''
	
	if params:yesno('sources', true) then
		local references = wikidata.getReferences(statement)
		name = name .. (wikidata.sourceStr(references) or '')
	end
	
	local showNameInOtherLanguage = params:arg('nom dans la langue')
	if showNameInOtherLanguage then
		local labelInOtherLanguage = getNameInOtherLanguage(statement, 
			showNameInOtherLanguage)
		if labelInOtherLanguage then
			name = name .. '<br />' .. labelInOtherLanguage
		end
	end
	
	if params:yesno('dates de vie', true) 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)
	if not sortValue then
		return text
	end
	return '<span data-sort-value="' .. sortValue .. '">' .. text .. '</span>'
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 getShortNameIfAvailable(qid)
	local shortName = wikidata.formatStatements{entity = qid,
		property = 'P1813', numval = 1, isinlang = 'locallang'}
	return shortName or mw.wikibase.label(qid)
end

local function getPartyOrParliamentaryGroup(statement, prop, params, abbreviate)
	local qualifiers = wikidata.getQualifiers(statement, prop)
	if not qualifiers then
		return nil
	end
	
	local showPoliticalColors = params:yesno('couleur politique', false)

	for i, qualifier in ipairs(qualifiers) do
		local partyFormatParams = {}
		if abbreviate then
			partyFormatParams.labelformat = getShortNameIfAvailable
		end
		local formattedSnak = wikidata.formatSnak(qualifier, partyFormatParams)
		if showPoliticalColors then
			local qid = wikidata.getId(qualifier)
			local coloredSquare = getPartyColoredSquare(qid)
			if coloredSquare then
				formattedSnak = coloredSquare .. ' ' .. formattedSnak
				local partyName = wikidata.getLabel(qid)
				formattedSnak = textWithSortValue(formattedSnak, partyName)
			end
		end
		qualifiers[i] = formattedSnak
	end
	return linguistic.conj(qualifiers, 'new line')
end

local function getParty(statement, params)
	return getPartyOrParliamentaryGroup(statement, 'P102', params,
		 params:yesno('abréger étiquette', false))
end

local function getParliamentaryGroup(statement, params)
	return getPartyOrParliamentaryGroup(statement, 'P4100', params,
		 params:yesno('abréger groupe parlementaire', false))
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 ipairs(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

	return (roman.toRoman(ordinal) or ordinal) 
		.. '<sup>' .. exposant .. '</sup>'
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
	
	if params:yesno('abréger législature', false) then
		local countOrdinals = 0
		for _, qualifier in ipairs(qualifiers) do
			local qualifierId = wikidata.getId(qualifier)
			local ordinal = getParliamentaryOrdinal(qualifierId)
			if ordinal then
				local qualifierLabel = mw.wikibase.label(qualifierId) or ''
				local termLabel = '<span title="' .. qualifierLabel .. '">'
					.. getParliamentaryTermLabel(ordinal)
					.. '</span>'
				ordinalLabels[qualifierId] = termLabel
				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
	
	local args = {defaultlinkquery = 'P2354',
		labelformat = function(qid)
			return ordinalLabels[qid] or mw.wikibase.label(qid)
		end
	}
	for i, qualifier in ipairs(qualifiers) do
		qualifiers[i] = wikidata.formatSnak(qualifier, args)
	end
	
	return textWithSortValue(linguistic.conj(qualifiers, 'and'),
		smallestOrdinal)
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 or 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)
		if personName then
			caption = 'Pas de portrait sous licence libre disponible pour '
				.. personName .. '.'
		else
			caption = 'Pas de portrait sous licence libre disponible.'
		end
	end
	
	return '[[Fichier:' .. mediaName .. '|border|80px|' .. caption .. ']]'
end

local numero = '<abbr class="abbr" title="Numéro">N<sup>o</sup></abbr>'

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 getColumnsAndCellKinds(params)
	local headerColumns = {}
	local cellKinds = {}
	
	for _, column in ipairs(orderedColumnsWithDefaultVisibility) do
		local shouldShowColumn = column.defaultVisibility == 'always'
			or params:yesno(column.name, column.defaultVisibility)
		if shouldShowColumn 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(params, entity, wProps)
	local title = params:arg('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}
	params.arg = getArgumentValue
	params.yesno = getBooleanArgumentValue
	
	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
			params.leaderType = leaderType
			local title = getTitle(params, entity, wProps)
			
			local headerColumns, cellKinds = getColumnsAndCellKinds(params)
			
			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
			-- 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 args = tools.extractArgs(frame)
	
	-- Entité Wikidata
	local entity = wikidata.getEntity(args.wikidata)
	
	local wPropsList
	if args.types then
		wPropsList = {}
		for leaderType in mw.text.gsplit(args.types, '%s*,%s*') do
			wPropsList[leaderType] = wikidataProperties[leaderType]
		end
	else
		wPropsList = wikidataProperties
	end
	
	-- Charte
	local charter = args.charte or getCharterRecursively(entity, 2)
	
	return peopleList(entity, args, wPropsList, charter)
end
 
return p