« Module:Infobox/Core » : différence entre les versions
De Nefald
Autres actions
m Catégorie multiple selon champ 'type' |
Aucun résumé des modifications Balise : Révoqué |
||
| Ligne 2 : | Ligne 2 : | ||
local getArgs = require('Module:Arguments').getArgs | local getArgs = require('Module:Arguments').getArgs | ||
-- Fonction de | -- Fonction pour créer l'HTML de l'infobox | ||
function p.createInfobox(config, args) | |||
local | local root = mw.html.create('div') | ||
:addClass('infobox') | |||
:attr('role', 'region') | |||
:attr('aria-label', 'Infobox') | |||
-- En-tête avec titre | |||
local header = root:tag('div'):addClass('infobox-header') | |||
-- | -- Conteneur pour l'icône et le titre | ||
local headerContent = header:tag('div'):addClass('infobox-header-content') | |||
-- | -- Gestion de l'icône | ||
if config. | if config.icone then | ||
local iconSpan = headerContent:tag('span'):addClass('infobox-icon') | |||
if type(config.icone) == 'table' then | |||
-- Icône FontAwesome | |||
local iconType = config.icone.type or 'fas' | |||
local iconName = config.icone.nom or 'info-circle' | |||
iconSpan:addClass(iconType):addClass('fa-' .. iconName) | |||
elseif type(config.icone) == 'string' then | |||
-- Image personnalisée | |||
iconSpan:wikitext(string.format('[[Fichier:%s|20px|link=]]', config.icone)) | |||
end | |||
end | end | ||
-- | -- Titre | ||
local titre = type(config.titre) == 'function' and config.titre(args) or config.titre | |||
headerContent:tag('span') | |||
:addClass('infobox-title') | |||
:wikitext(titre) | |||
-- Image si définie | |||
if config.image then | |||
-- | local imageData = type(config.image) == 'function' and config.image(args) or config.image | ||
if imageData and imageData.nom then | |||
if | local imageDiv = root:tag('div'):addClass('infobox-image') | ||
local taille = imageData.taille or '300px' | |||
local legende = imageData.legende | |||
-- Construction du wikitext pour l'image | |||
local imageWikitext = string.format('[[Fichier:%s|%s|center', imageData.nom, taille) | |||
if legende and legende ~= '' then | |||
imageWikitext = imageWikitext .. '|' .. legende | |||
if | |||
end | end | ||
imageWikitext = imageWikitext .. ']]' | |||
imageDiv:wikitext(imageWikitext) | |||
end | end | ||
end | end | ||
-- | -- Corps de l'infobox avec les sections | ||
local | local body = root:tag('div'):addClass('infobox-body') | ||
-- Variable pour suivre si les coordonnées ont été affichées | |||
local coordinatesDisplayed = false | |||
local | |||
if config.sections then | |||
for _, section in ipairs(config.sections) do | |||
if | -- Créer la section seulement si elle a des champs à afficher | ||
local hasVisibleFields = false | |||
for _, champ in ipairs(section.champs) do | |||
if args[champ.cle] and args[champ.cle] ~= '' then | |||
hasVisibleFields = true | |||
break | |||
end | |||
end | |||
-- Vérifier aussi les coordonnées groupées | |||
if not coordinatesDisplayed and args.x and args.y and args.z then | |||
for _, champ in ipairs(section.champs) do | |||
if champ.cle == 'x' or champ.cle == 'y' or champ.cle == 'z' then | |||
hasVisibleFields = true | |||
break | |||
end | |||
end | |||
end | |||
if hasVisibleFields then | |||
local sectionDiv = body:tag('div'):addClass('infobox-section') | |||
local | |||
-- Titre de section | |||
if section.titre then | |||
sectionDiv:tag('div') | |||
:addClass('infobox-section-title') | |||
:wikitext(section.titre) | |||
end | |||
-- Vérifier si cette section contient les coordonnées (x, y, z) | |||
local hasCoordinates = false | |||
if not coordinatesDisplayed and args.x and args.y and args.z then | |||
for _, champ in ipairs(section.champs) do | |||
if args. | if champ.cle == 'x' or champ.cle == 'y' or champ.cle == 'z' then | ||
hasCoordinates = true | |||
break | |||
end | |||
end | |||
end | end | ||
-- Si la section contient les coordonnées, les afficher groupées | |||
if hasCoordinates and not coordinatesDisplayed then | |||
coordinatesDisplayed | -- Vérifier si on peut créer un lien (worldname obligatoire) | ||
local canCreateLink = args.worldname and args.worldname ~= '' | |||
local labelDiv = mw.html.create('div') | |||
:addClass('infobox-label') | |||
:wikitext("'''Coordonnées'''") | |||
local valueDiv = mw.html.create('div') | |||
:addClass('infobox-value') | |||
-- | if canCreateLink then | ||
-- Construction du lien avec worldname | |||
local mapname = args.mapname and args.mapname ~= '' and args.mapname or 'flat' | |||
local zoom = args.zoom and args.zoom ~= '' and args.zoom or '4' | |||
local mapUrl = string.format( | |||
'https://map.nefald.fr/?worldname=%s&mapname=%s&zoom=%s&x=%s&y=%s&z=%s', | |||
mw.uri.encode(args.worldname), | |||
mw.uri.encode(mapname), | |||
mw.uri.encode(zoom), | |||
mw.uri.encode(args.x), | |||
mw.uri.encode(args.y), | |||
mw.uri.encode(args.z) | |||
) | |||
local displayText = string.format('%s, %s, %s', args.x, args.y, args.z) | |||
valueDiv:wikitext(string.format('[%s %s]', mapUrl, displayText)) | |||
else | |||
-- Affichage simple sans lien si worldname manque | |||
local displayText = string.format('%s, %s, %s', args.x, args.y, args.z) | |||
valueDiv:wikitext(displayText) | |||
end | end | ||
-- | local rowDiv = mw.html.create('div'):addClass('infobox-row') | ||
rowDiv:node(labelDiv):node(valueDiv) | |||
local rowDiv = | sectionDiv:node(rowDiv) | ||
coordinatesDisplayed = true | |||
end | |||
-- Champs de la section | |||
for _, champ in ipairs(section.champs) do | |||
local value = args[champ.cle] | |||
-- Ignorer les coordonnées individuelles si elles ont été affichées groupées | |||
if coordinatesDisplayed and (champ.cle == 'x' or champ.cle == 'y' or champ.cle == 'z') then | |||
-- Ne rien faire, on a déjà affiché les coordonnées groupées | |||
elseif value and value ~= '' then | |||
local rowDiv = sectionDiv:tag('div'):addClass('infobox-row') | |||
-- Label | |||
rowDiv:tag('div') | |||
:addClass('infobox-label') | :addClass('infobox-label') | ||
:wikitext(champ.label) | :wikitext("'''" .. champ.label .. "'''") | ||
local valueDiv = | -- Valeur | ||
local valueDiv = rowDiv:tag('div'):addClass('infobox-value') | |||
-- | -- Traiter la valeur (fonction ou chaîne) | ||
if champ. | if type(champ.format) == 'function' then | ||
valueDiv:wikitext( | valueDiv:wikitext(champ.format(value, args)) | ||
else | else | ||
valueDiv:wikitext( | valueDiv:wikitext(value) | ||
end | end | ||
end | end | ||
end | end | ||
| Ligne 200 : | Ligne 174 : | ||
end | end | ||
root | return tostring(root) | ||
end | |||
-- Fonction pour valider le type | |||
function p.validateType(args, config) | |||
if not config.typeField then | |||
return true, nil | |||
end | |||
local typeValue = args.type | |||
if not typeValue or typeValue == '' then | |||
if config.typeField.required then | |||
return false, "Le champ 'type' est obligatoire" | |||
end | |||
return true, nil | |||
end | |||
if config. | -- Vérifier si le type est dans les valeurs autorisées | ||
local | if config.typeField.allowedValues then | ||
local typeConfig = config.typeField.allowedValues[typeValue:lower()] | |||
if not typeConfig then | |||
return false, config.typeField.errorMessage or "Type non reconnu" | |||
if | |||
end | end | ||
return true, typeConfig | |||
-- | end | ||
return true, nil | |||
end | |||
-- Fonction pour générer les catégories | |||
function p.generateCategories(args, config, typeConfig) | |||
if not config.categories then | |||
return '' | |||
end | |||
return config.categories(args, typeConfig) | |||
end | |||
-- Fonction principale appelée par {{#invoke:}} | |||
function p.main(frame) | |||
local args = getArgs(frame, {parentFirst = true}) | |||
-- Récupérer le type d'infobox depuis les arguments du frame | |||
local infoboxType = frame.args[1] or frame.args.type | |||
if not infoboxType or infoboxType == '' then | |||
return '<div class="error">Type d\'infobox requis</div>' | |||
end | |||
-- Charger la configuration appropriée | |||
local configModule = 'Module:Infobox/Configs/' .. infoboxType | |||
local success, config = pcall(require, configModule) | |||
if not success then | |||
return '<div class="error">Configuration introuvable pour : ' .. infoboxType .. '</div>' | |||
end | |||
-- Valider le type si nécessaire | |||
local isValid, typeConfig = p.validateType(args, config) | |||
if not isValid then | |||
return '<div class="error">' .. typeConfig .. '</div>' | |||
end | end | ||
-- Ajouter les catégories | -- Générer l'infobox | ||
local categories = | local infobox = p.createInfobox(config, args) | ||
-- Ajouter les catégories | |||
local categories = p.generateCategories(args, config, typeConfig) | |||
return | return infobox .. categories | ||
end | end | ||
return p | return p | ||
Version du 23 octobre 2025 à 13:59
La documentation pour ce module peut être créée à Module:Infobox/Core/doc
local p = {}
local getArgs = require('Module:Arguments').getArgs
-- Fonction pour créer l'HTML de l'infobox
function p.createInfobox(config, args)
local root = mw.html.create('div')
:addClass('infobox')
:attr('role', 'region')
:attr('aria-label', 'Infobox')
-- En-tête avec titre
local header = root:tag('div'):addClass('infobox-header')
-- Conteneur pour l'icône et le titre
local headerContent = header:tag('div'):addClass('infobox-header-content')
-- Gestion de l'icône
if config.icone then
local iconSpan = headerContent:tag('span'):addClass('infobox-icon')
if type(config.icone) == 'table' then
-- Icône FontAwesome
local iconType = config.icone.type or 'fas'
local iconName = config.icone.nom or 'info-circle'
iconSpan:addClass(iconType):addClass('fa-' .. iconName)
elseif type(config.icone) == 'string' then
-- Image personnalisée
iconSpan:wikitext(string.format('[[Fichier:%s|20px|link=]]', config.icone))
end
end
-- Titre
local titre = type(config.titre) == 'function' and config.titre(args) or config.titre
headerContent:tag('span')
:addClass('infobox-title')
:wikitext(titre)
-- Image si définie
if config.image then
local imageData = type(config.image) == 'function' and config.image(args) or config.image
if imageData and imageData.nom then
local imageDiv = root:tag('div'):addClass('infobox-image')
local taille = imageData.taille or '300px'
local legende = imageData.legende
-- Construction du wikitext pour l'image
local imageWikitext = string.format('[[Fichier:%s|%s|center', imageData.nom, taille)
if legende and legende ~= '' then
imageWikitext = imageWikitext .. '|' .. legende
end
imageWikitext = imageWikitext .. ']]'
imageDiv:wikitext(imageWikitext)
end
end
-- Corps de l'infobox avec les sections
local body = root:tag('div'):addClass('infobox-body')
-- Variable pour suivre si les coordonnées ont été affichées
local coordinatesDisplayed = false
if config.sections then
for _, section in ipairs(config.sections) do
-- Créer la section seulement si elle a des champs à afficher
local hasVisibleFields = false
for _, champ in ipairs(section.champs) do
if args[champ.cle] and args[champ.cle] ~= '' then
hasVisibleFields = true
break
end
end
-- Vérifier aussi les coordonnées groupées
if not coordinatesDisplayed and args.x and args.y and args.z then
for _, champ in ipairs(section.champs) do
if champ.cle == 'x' or champ.cle == 'y' or champ.cle == 'z' then
hasVisibleFields = true
break
end
end
end
if hasVisibleFields then
local sectionDiv = body:tag('div'):addClass('infobox-section')
-- Titre de section
if section.titre then
sectionDiv:tag('div')
:addClass('infobox-section-title')
:wikitext(section.titre)
end
-- Vérifier si cette section contient les coordonnées (x, y, z)
local hasCoordinates = false
if not coordinatesDisplayed and args.x and args.y and args.z then
for _, champ in ipairs(section.champs) do
if champ.cle == 'x' or champ.cle == 'y' or champ.cle == 'z' then
hasCoordinates = true
break
end
end
end
-- Si la section contient les coordonnées, les afficher groupées
if hasCoordinates and not coordinatesDisplayed then
-- Vérifier si on peut créer un lien (worldname obligatoire)
local canCreateLink = args.worldname and args.worldname ~= ''
local labelDiv = mw.html.create('div')
:addClass('infobox-label')
:wikitext("'''Coordonnées'''")
local valueDiv = mw.html.create('div')
:addClass('infobox-value')
if canCreateLink then
-- Construction du lien avec worldname
local mapname = args.mapname and args.mapname ~= '' and args.mapname or 'flat'
local zoom = args.zoom and args.zoom ~= '' and args.zoom or '4'
local mapUrl = string.format(
'https://map.nefald.fr/?worldname=%s&mapname=%s&zoom=%s&x=%s&y=%s&z=%s',
mw.uri.encode(args.worldname),
mw.uri.encode(mapname),
mw.uri.encode(zoom),
mw.uri.encode(args.x),
mw.uri.encode(args.y),
mw.uri.encode(args.z)
)
local displayText = string.format('%s, %s, %s', args.x, args.y, args.z)
valueDiv:wikitext(string.format('[%s %s]', mapUrl, displayText))
else
-- Affichage simple sans lien si worldname manque
local displayText = string.format('%s, %s, %s', args.x, args.y, args.z)
valueDiv:wikitext(displayText)
end
local rowDiv = mw.html.create('div'):addClass('infobox-row')
rowDiv:node(labelDiv):node(valueDiv)
sectionDiv:node(rowDiv)
coordinatesDisplayed = true
end
-- Champs de la section
for _, champ in ipairs(section.champs) do
local value = args[champ.cle]
-- Ignorer les coordonnées individuelles si elles ont été affichées groupées
if coordinatesDisplayed and (champ.cle == 'x' or champ.cle == 'y' or champ.cle == 'z') then
-- Ne rien faire, on a déjà affiché les coordonnées groupées
elseif value and value ~= '' then
local rowDiv = sectionDiv:tag('div'):addClass('infobox-row')
-- Label
rowDiv:tag('div')
:addClass('infobox-label')
:wikitext("'''" .. champ.label .. "'''")
-- Valeur
local valueDiv = rowDiv:tag('div'):addClass('infobox-value')
-- Traiter la valeur (fonction ou chaîne)
if type(champ.format) == 'function' then
valueDiv:wikitext(champ.format(value, args))
else
valueDiv:wikitext(value)
end
end
end
end
end
end
return tostring(root)
end
-- Fonction pour valider le type
function p.validateType(args, config)
if not config.typeField then
return true, nil
end
local typeValue = args.type
if not typeValue or typeValue == '' then
if config.typeField.required then
return false, "Le champ 'type' est obligatoire"
end
return true, nil
end
-- Vérifier si le type est dans les valeurs autorisées
if config.typeField.allowedValues then
local typeConfig = config.typeField.allowedValues[typeValue:lower()]
if not typeConfig then
return false, config.typeField.errorMessage or "Type non reconnu"
end
return true, typeConfig
end
return true, nil
end
-- Fonction pour générer les catégories
function p.generateCategories(args, config, typeConfig)
if not config.categories then
return ''
end
return config.categories(args, typeConfig)
end
-- Fonction principale appelée par {{#invoke:}}
function p.main(frame)
local args = getArgs(frame, {parentFirst = true})
-- Récupérer le type d'infobox depuis les arguments du frame
local infoboxType = frame.args[1] or frame.args.type
if not infoboxType or infoboxType == '' then
return '<div class="error">Type d\'infobox requis</div>'
end
-- Charger la configuration appropriée
local configModule = 'Module:Infobox/Configs/' .. infoboxType
local success, config = pcall(require, configModule)
if not success then
return '<div class="error">Configuration introuvable pour : ' .. infoboxType .. '</div>'
end
-- Valider le type si nécessaire
local isValid, typeConfig = p.validateType(args, config)
if not isValid then
return '<div class="error">' .. typeConfig .. '</div>'
end
-- Générer l'infobox
local infobox = p.createInfobox(config, args)
-- Ajouter les catégories
local categories = p.generateCategories(args, config, typeConfig)
return infobox .. categories
end
return p