« Module:Infobox/Core » : différence entre les versions
De Nefald
Autres actions
Page créée avec « local p = {} function p.build(args, config) if not config then return '<div class="error">Configuration manquante pour ce type d\'infobox</div>' end -- Création de la table principale local html = mw.html.create('table') :addClass('infobox_v2') :attr('cellspacing', '7') -- Titre principal avec classe spécifique local nom = args.nom or mw.title.getCurrentTitle().text if nom and nom ~= '' then... » Balises : Modification par mobile Modification par le web mobile |
m liens des champs (processed) |
||
(13 versions intermédiaires par le même utilisateur non affichées) | |||
Ligne 1 : | Ligne 1 : | ||
local p = {} | local p = {} | ||
local getArgs = require('Module:Arguments').getArgs | |||
function | -- Fonction de validation du champ "type" | ||
if not config then | local function validateTypeField(args, config) | ||
return | local typeValue = args.type or args['type'] | ||
-- Si pas de configuration pour le type, pas de validation | |||
if not config.typeField then | |||
return { valid = true } | |||
end | end | ||
-- | -- Si le champ est requis et vide | ||
if config.typeField.required and (not typeValue or typeValue == '') then | |||
return { | |||
error = 'Le champ "type" est obligatoire.', | |||
valid = false | |||
} | |||
end | |||
-- | -- Si pas de valeur, mais pas requis, c'est valide | ||
if not typeValue or typeValue == '' then | |||
return { valid = true } | |||
end | end | ||
-- | -- Nettoyer la valeur | ||
local cleanType = mw.text.trim(mw.ustring.lower(typeValue)) | |||
-- | -- Vérifier si la valeur est dans la liste autorisée | ||
if config. | if config.typeField.allowedValues and not config.typeField.allowedValues[cleanType] then | ||
local errorMsg = config.typeField.errorMessage or 'Valeur de type non autorisée : ' .. typeValue | |||
return { | |||
error = errorMsg, | |||
valid = false | |||
} | |||
end | end | ||
return { | |||
valid = true, | |||
cleanValue = cleanType, | |||
displayValue = config.typeField.allowedValues and config.typeField.allowedValues[cleanType] and config.typeField.allowedValues[cleanType].display or typeValue | |||
} | |||
end | end | ||
function | -- Fonction pour gérer la catégorisation automatique | ||
local function addCategories(args, config, frame) | |||
-- Vérifier qu'on est dans le namespace principal (0) | |||
local title = mw.title.getCurrentTitle() | |||
if title.namespace ~= 0 then | |||
return '' | |||
end | end | ||
local categoryString = '' | |||
-- Catégories automatiques du type (ancien système) | |||
if config.typeField and config.typeField.allowedValues then | |||
local typeValue = args.type or args['type'] | |||
if typeValue and typeValue ~= '' then | |||
local cleanType = mw.text.trim(mw.ustring.lower(typeValue)) | |||
local typeConfig = config.typeField.allowedValues[cleanType] | |||
if typeConfig and typeConfig.category then | |||
categoryString = categoryString .. '[[Catégorie:' .. typeConfig.category .. ']]' | |||
end | end | ||
end | end | ||
end | end | ||
-- Nouvelles catégories configurables (fonction categories) | |||
if type(config.categories) == 'function' then | |||
-- | local cats = config.categories(args, config, frame) | ||
if cats then | |||
for _, cat in ipairs(cats) do | |||
categoryString = categoryString .. '[[Catégorie:' .. cat .. ']]' | |||
end | |||
end | end | ||
end | end | ||
return categoryString | |||
end | end | ||
function p. | function p.build(args, config, frame) | ||
local | if not args.nom or args.nom == '' then | ||
return '<div class="error">Nom requis pour l\'infobox</div>' | |||
end | |||
-- Validation du champ type | |||
local typeValidation = validateTypeField(args, config) | |||
if not typeValidation.valid then | |||
return '<div class="error">' .. typeValidation.error .. '</div>' | |||
end | |||
local root = mw.html.create('div') | |||
:addClass('infobox-table') | |||
:attr('role', 'table') | |||
-- En-tête avec nom | |||
local header = mw.html.create('div') | |||
:addClass('infobox-header') | |||
if args.image and args.image ~= '' then | |||
if | local imageDiv = mw.html.create('div') | ||
:addClass('infobox-image') | |||
local | |||
local imageSize = args.tailleimage or '280px' | |||
local imageCode = string.format('[[Fichier:%s|%s|center', args.image, imageSize) | |||
if args.legende and args.legende ~= '' then | |||
imageCode = imageCode .. '|' .. args.legende | |||
end | end | ||
imageCode = imageCode .. ']]' | |||
imageDiv:wikitext(imageCode) | |||
header:node(imageDiv) | |||
end | end | ||
-- Titre sans icône (icône déplacée en bas à droite) | |||
local titleDiv = mw.html.create('div') | |||
:addClass('infobox-title') | |||
:wikitext(args.nom) | |||
header:node(titleDiv) | |||
if | |||
if args.soustitre and args.soustitre ~= '' then | |||
local subtitleDiv = mw.html.create('div') | |||
:addClass('infobox-subtitle') | |||
:wikitext(args.soustitre) | |||
header:node(subtitleDiv) | |||
end | end | ||
-- | root:node(header) | ||
if | -- Corps avec les champs | ||
local body = mw.html.create('div') | |||
:addClass('infobox-body') | |||
for _, section in ipairs(config.sections or {}) do | |||
if section.titre then | |||
local sectionDiv = mw.html.create('div') | |||
:addClass('infobox-section-title') | |||
:wikitext(section.titre) | |||
body:node(sectionDiv) | |||
end | end | ||
-- Vérifier si on doit afficher les coordonnées automatiquement | |||
local hasCoordinates = args.x and args.x ~= '' and args.y and args.y ~= '' and args.z and args.z ~= '' | |||
local coordinatesDisplayed = false | |||
for _, champ in ipairs(section.champs or {}) do | |||
-- Détection automatique des coordonnées | |||
if hasCoordinates and not coordinatesDisplayed and (champ.cle == 'x' or champ.cle == 'y' or champ.cle == 'z' or champ.cle == 'spawn' or champ.cle == 'coordonnees') then | |||
local rowDiv = mw.html.create('div') | |||
:addClass('infobox-row') | |||
local labelDiv = mw.html.create('div') | |||
:addClass('infobox-label') | |||
:wikitext('Coordonnées') | |||
local valueDiv = mw.html.create('div') | |||
:addClass('infobox-value') | |||
-- Construction du lien vers la carte si le paramètre monde existe | |||
if args.monde and args.monde ~= '' then | |||
local mapUrl = string.format('[https://map.nefald.fr/?worldname=%s&mapname=surface&zoom=4&x=%s&y=%s&z=%s %s, %s, %s]', | |||
args.monde, args.x, args.y, args.z, args.x, args.y, args.z) | |||
valueDiv:wikitext("''" .. mapUrl .. "''") | |||
else | |||
-- Affichage simple sans lien | |||
valueDiv:wikitext(string.format('%s, %s, %s', args.x, args.y, args.z)) | |||
end | |||
rowDiv:node(labelDiv):node(valueDiv) | |||
body:node(rowDiv) | |||
coordinatesDisplayed = true | |||
-- *** NOUVELLE LOGIQUE POUR TRAITEMENT DES CHAMPS *** | |||
elseif not (hasCoordinates and (champ.cle == 'x' or champ.cle == 'y' or champ.cle == 'z')) then | |||
local rawValue = args[champ.cle] | |||
-- Si le champ a une valeur OU une fonction process qui peut générer une valeur | |||
if (rawValue and rawValue ~= '') or champ.process then | |||
local finalValue = rawValue | |||
-- Appliquer la fonction process si elle existe | |||
if champ.process and type(champ.process) == 'function' then | |||
finalValue = champ.process(rawValue, args, frame) | |||
end | |||
-- N'afficher que si on a une valeur finale | |||
if finalValue and finalValue ~= '' then | |||
local rowDiv = mw.html.create('div') | |||
:addClass('infobox-row') | |||
local labelDiv = mw.html.create('div') | |||
:addClass('infobox-label') | |||
:wikitext(champ.label) | |||
local valueDiv = mw.html.create('div') | |||
:addClass('infobox-value') | |||
-- Formatage spécial pour le champ "type" | |||
if champ.cle == 'type' and typeValidation.displayValue then | |||
valueDiv:wikitext(typeValidation.displayValue) | |||
else | |||
valueDiv:wikitext(finalValue) | |||
end | |||
rowDiv:node(labelDiv):node(valueDiv) | |||
body:node(rowDiv) | |||
end | |||
end | |||
end | |||
end | end | ||
end | end | ||
-- | root:node(body) | ||
if | -- Traiter l'icône APRÈS avoir construit tout le HTML | ||
local | local finalResult = tostring(root) | ||
local | |||
if config.icone then | |||
local iconeType = config.icone.type or 'fas' | |||
local iconeNom = config.icone.nom | |||
-- Utiliser mw.getCurrentFrame() si frame n'est pas disponible | |||
local currentFrame = frame or mw.getCurrentFrame() | |||
local iconeContent = '{{#' .. iconeType .. ':' .. iconeNom .. '}}' | |||
if currentFrame then | |||
iconeContent = currentFrame:preprocess(iconeContent) | |||
: | |||
end | end | ||
-- Créer la div d'icône séparément et l'ajouter au résultat | |||
local iconeHtml = string.format( | |||
'<div class="infobox-icon-bottom">%s</div>', | |||
iconeContent | |||
) | |||
-- Injecter l'icône juste avant la fermeture de la div principale | |||
finalResult = finalResult:gsub('</div>$', iconeHtml .. '</div>') | |||
end | end | ||
return | |||
-- Ajouter les catégories automatiques (ancien + nouveau système) | |||
local categories = addCategories(args, config, frame) | |||
return finalResult .. categories | |||
end | end | ||
return p | return p |
Dernière version du 1 octobre 2025 à 13:04
La documentation pour ce module peut être créée à Module:Infobox/Core/doc
local p = {}
local getArgs = require('Module:Arguments').getArgs
-- Fonction de validation du champ "type"
local function validateTypeField(args, config)
local typeValue = args.type or args['type']
-- Si pas de configuration pour le type, pas de validation
if not config.typeField then
return { valid = true }
end
-- Si le champ est requis et vide
if config.typeField.required and (not typeValue or typeValue == '') then
return {
error = 'Le champ "type" est obligatoire.',
valid = false
}
end
-- Si pas de valeur, mais pas requis, c'est valide
if not typeValue or typeValue == '' then
return { valid = true }
end
-- Nettoyer la valeur
local cleanType = mw.text.trim(mw.ustring.lower(typeValue))
-- Vérifier si la valeur est dans la liste autorisée
if config.typeField.allowedValues and not config.typeField.allowedValues[cleanType] then
local errorMsg = config.typeField.errorMessage or 'Valeur de type non autorisée : ' .. typeValue
return {
error = errorMsg,
valid = false
}
end
return {
valid = true,
cleanValue = cleanType,
displayValue = config.typeField.allowedValues and config.typeField.allowedValues[cleanType] and config.typeField.allowedValues[cleanType].display or typeValue
}
end
-- Fonction pour gérer la catégorisation automatique
local function addCategories(args, config, frame)
-- Vérifier qu'on est dans le namespace principal (0)
local title = mw.title.getCurrentTitle()
if title.namespace ~= 0 then
return ''
end
local categoryString = ''
-- Catégories automatiques du type (ancien système)
if config.typeField and config.typeField.allowedValues then
local typeValue = args.type or args['type']
if typeValue and typeValue ~= '' then
local cleanType = mw.text.trim(mw.ustring.lower(typeValue))
local typeConfig = config.typeField.allowedValues[cleanType]
if typeConfig and typeConfig.category then
categoryString = categoryString .. '[[Catégorie:' .. typeConfig.category .. ']]'
end
end
end
-- Nouvelles catégories configurables (fonction categories)
if type(config.categories) == 'function' then
local cats = config.categories(args, config, frame)
if cats then
for _, cat in ipairs(cats) do
categoryString = categoryString .. '[[Catégorie:' .. cat .. ']]'
end
end
end
return categoryString
end
function p.build(args, config, frame)
if not args.nom or args.nom == '' then
return '<div class="error">Nom requis pour l\'infobox</div>'
end
-- Validation du champ type
local typeValidation = validateTypeField(args, config)
if not typeValidation.valid then
return '<div class="error">' .. typeValidation.error .. '</div>'
end
local root = mw.html.create('div')
:addClass('infobox-table')
:attr('role', 'table')
-- En-tête avec nom
local header = mw.html.create('div')
:addClass('infobox-header')
if args.image and args.image ~= '' then
local imageDiv = mw.html.create('div')
:addClass('infobox-image')
local imageSize = args.tailleimage or '280px'
local imageCode = string.format('[[Fichier:%s|%s|center', args.image, imageSize)
if args.legende and args.legende ~= '' then
imageCode = imageCode .. '|' .. args.legende
end
imageCode = imageCode .. ']]'
imageDiv:wikitext(imageCode)
header:node(imageDiv)
end
-- Titre sans icône (icône déplacée en bas à droite)
local titleDiv = mw.html.create('div')
:addClass('infobox-title')
:wikitext(args.nom)
header:node(titleDiv)
if args.soustitre and args.soustitre ~= '' then
local subtitleDiv = mw.html.create('div')
:addClass('infobox-subtitle')
:wikitext(args.soustitre)
header:node(subtitleDiv)
end
root:node(header)
-- Corps avec les champs
local body = mw.html.create('div')
:addClass('infobox-body')
for _, section in ipairs(config.sections or {}) do
if section.titre then
local sectionDiv = mw.html.create('div')
:addClass('infobox-section-title')
:wikitext(section.titre)
body:node(sectionDiv)
end
-- Vérifier si on doit afficher les coordonnées automatiquement
local hasCoordinates = args.x and args.x ~= '' and args.y and args.y ~= '' and args.z and args.z ~= ''
local coordinatesDisplayed = false
for _, champ in ipairs(section.champs or {}) do
-- Détection automatique des coordonnées
if hasCoordinates and not coordinatesDisplayed and (champ.cle == 'x' or champ.cle == 'y' or champ.cle == 'z' or champ.cle == 'spawn' or champ.cle == 'coordonnees') then
local rowDiv = mw.html.create('div')
:addClass('infobox-row')
local labelDiv = mw.html.create('div')
:addClass('infobox-label')
:wikitext('Coordonnées')
local valueDiv = mw.html.create('div')
:addClass('infobox-value')
-- Construction du lien vers la carte si le paramètre monde existe
if args.monde and args.monde ~= '' then
local mapUrl = string.format('[https://map.nefald.fr/?worldname=%s&mapname=surface&zoom=4&x=%s&y=%s&z=%s %s, %s, %s]',
args.monde, args.x, args.y, args.z, args.x, args.y, args.z)
valueDiv:wikitext("''" .. mapUrl .. "''")
else
-- Affichage simple sans lien
valueDiv:wikitext(string.format('%s, %s, %s', args.x, args.y, args.z))
end
rowDiv:node(labelDiv):node(valueDiv)
body:node(rowDiv)
coordinatesDisplayed = true
-- *** NOUVELLE LOGIQUE POUR TRAITEMENT DES CHAMPS ***
elseif not (hasCoordinates and (champ.cle == 'x' or champ.cle == 'y' or champ.cle == 'z')) then
local rawValue = args[champ.cle]
-- Si le champ a une valeur OU une fonction process qui peut générer une valeur
if (rawValue and rawValue ~= '') or champ.process then
local finalValue = rawValue
-- Appliquer la fonction process si elle existe
if champ.process and type(champ.process) == 'function' then
finalValue = champ.process(rawValue, args, frame)
end
-- N'afficher que si on a une valeur finale
if finalValue and finalValue ~= '' then
local rowDiv = mw.html.create('div')
:addClass('infobox-row')
local labelDiv = mw.html.create('div')
:addClass('infobox-label')
:wikitext(champ.label)
local valueDiv = mw.html.create('div')
:addClass('infobox-value')
-- Formatage spécial pour le champ "type"
if champ.cle == 'type' and typeValidation.displayValue then
valueDiv:wikitext(typeValidation.displayValue)
else
valueDiv:wikitext(finalValue)
end
rowDiv:node(labelDiv):node(valueDiv)
body:node(rowDiv)
end
end
end
end
end
root:node(body)
-- Traiter l'icône APRÈS avoir construit tout le HTML
local finalResult = tostring(root)
if config.icone then
local iconeType = config.icone.type or 'fas'
local iconeNom = config.icone.nom
-- Utiliser mw.getCurrentFrame() si frame n'est pas disponible
local currentFrame = frame or mw.getCurrentFrame()
local iconeContent = '{{#' .. iconeType .. ':' .. iconeNom .. '}}'
if currentFrame then
iconeContent = currentFrame:preprocess(iconeContent)
end
-- Créer la div d'icône séparément et l'ajouter au résultat
local iconeHtml = string.format(
'<div class="infobox-icon-bottom">%s</div>',
iconeContent
)
-- Injecter l'icône juste avant la fermeture de la div principale
finalResult = finalResult:gsub('</div>$', iconeHtml .. '</div>')
end
-- Ajouter les catégories automatiques (ancien + nouveau système)
local categories = addCategories(args, config, frame)
return finalResult .. categories
end
return p