Basculer le menu
Changer de menu des préférences
Basculer le menu personnel
Non connecté(e)
Votre adresse IP sera visible au public si vous faites des modifications.

« Module:Infobox/Core » : différence entre les versions

De Nefald
Hiob (discussion | contributions)
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
 
Hiob (discussion | contributions)
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 p.build(args, config)
-- Fonction de validation du champ "type"
     if not config then
local function validateTypeField(args, config)
         return '<div class="error">Configuration manquante pour ce type d\'infobox</div>'
    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
      
      
     -- Création de la table principale
     -- Si le champ est requis et vide
     local html = mw.html.create('table')
     if config.typeField.required and (not typeValue or typeValue == '') then
         :addClass('infobox_v2')
         return {
         :attr('cellspacing', '7')
            error = 'Le champ "type" est obligatoire.',
            valid = false
         }
    end
      
      
     -- Titre principal avec classe spécifique
     -- Si pas de valeur, mais pas requis, c'est valide
     local nom = args.nom or mw.title.getCurrentTitle().text
     if not typeValue or typeValue == '' then
    if nom and nom ~= '' then
         return { valid = true }
         local headerClass = 'entete ' .. (config.headerClass or 'monde')
        local headerStyle = string.format(
            'background-color:%s; color:#fff; font-size:1.4em; text-shadow:0.1em 0.1em 0.1em #000',
            config.headerColor or '#86C705'
        )
       
        html:tag('tr')
            :tag('th')
            :attr('colspan', '2')
            :addClass(headerClass)
            :cssText(headerStyle)
            :wikitext(nom)
     end
     end
      
      
     -- Image principale
     -- Nettoyer la valeur
     p.addImage(html, args)
     local cleanType = mw.text.trim(mw.ustring.lower(typeValue))
      
      
     -- Sections
     -- Vérifier si la valeur est dans la liste autorisée
     if config.sections then
     if config.typeField.allowedValues and not config.typeField.allowedValues[cleanType] then
         for _, section in ipairs(config.sections) do
         local errorMsg = config.typeField.errorMessage or 'Valeur de type non autorisée : ' .. typeValue
             p.addSection(html, args, config, section)
        return {
         end
             error = errorMsg,
            valid = false
         }
     end
     end
      
      
     -- Champs personnalisés
     return {
    p.addCustomFields(html, args)
        valid = true,
   
        cleanValue = cleanType,
     return tostring(html)
        displayValue = config.typeField.allowedValues and config.typeField.allowedValues[cleanType] and config.typeField.allowedValues[cleanType].display or typeValue
     }
end
end


function p.addImage(html, args)
-- Fonction pour gérer la catégorisation automatique
     if args.image and args.image ~= '' then
local function addCategories(args, config, frame)
        local imageSize = args.tailleimage or '280x200px'
     -- Vérifier qu'on est dans le namespace principal (0)
        local caption = args.legende or args.legendecarte or mw.title.getCurrentTitle().text
    local title = mw.title.getCurrentTitle()
       
    if title.namespace ~= 0 then
         html:tag('tr')
         return ''
            :tag('td')
            :attr('colspan', '5')
            :cssText('font-size: smaller; text-align: center;')
            :wikitext(string.format('[[Fichier:%s|%s|%s]]', args.image, imageSize, caption))
     end
     end
end
function p.addSection(html, args, config, section)
    if not section.fields then return end
      
      
     -- Vérifier si la section a du contenu
     local categoryString = ''
     local hasContent = false
      
     for _, fieldKey in ipairs(section.fields) do
     -- Catégories automatiques du type (ancien système)
        local field = p.findField(config.fields, fieldKey)
    if config.typeField and config.typeField.allowedValues then
         if field and args[fieldKey] and args[fieldKey] ~= '' then
         local typeValue = args.type or args['type']
             if not field.optional or (field.optional and args[fieldKey] ~= '') then
        if typeValue and typeValue ~= '' then
                 hasContent = true
             local cleanType = mw.text.trim(mw.ustring.lower(typeValue))
                break
            local typeConfig = config.typeField.allowedValues[cleanType]
            if typeConfig and typeConfig.category then
                 categoryString = categoryString .. '[[Catégorie:' .. typeConfig.category .. ']]'
             end
             end
         end
         end
     end
     end
      
      
    if not hasContent then return end
     -- Nouvelles catégories configurables (fonction categories)
   
     if type(config.categories) == 'function' then
     -- Ajouter le titre de section
         local cats = config.categories(args, config, frame)
     html:tag('tr')
         if cats then
        :tag('th')
            for _, cat in ipairs(cats) do
         :attr('colspan', '2')
                categoryString = categoryString .. '[[Catégorie:' .. cat .. ']]'
         :addClass('infoboxcat')
             end
        :cssText('text-align:center; background-color:transparent; padding:3px; margin-top: 20px; border-bottom:1px solid #ccc; color:#099DFF;')
        :wikitext(section.title)
   
    -- Ajouter les champs de la section
    for _, fieldKey in ipairs(section.fields) do
        local field = p.findField(config.fields, fieldKey)
        if field then
             p.addField(html, args, field, fieldKey)
         end
         end
     end
     end
   
    return categoryString
end
end


function p.addField(html, args, field, fieldKey)
function p.build(args, config, frame)
     local value = args[fieldKey]
    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')
      
      
    -- Champs spéciaux avec conditions
     if args.image and args.image ~= '' then
     if fieldKey == 'coordonnees' or fieldKey == 'spawn' then
         local imageDiv = mw.html.create('div')
         if args.x and args.y and args.z then
             :addClass('infobox-image')
             local worldName = args.monde or 'Harlan2'
       
            local linkText = string.format('%s, %s, %s', args.x, args.y, args.z)
        local imageSize = args.tailleimage or '280px'
             local mapUrl = string.format(
        local imageCode = string.format('[[Fichier:%s|%s|center', args.image, imageSize)
                'https://map.nefald.fr/?worldname=%s&mapname=surface&zoom=4&x=%s&y=%s&z=%s',
        if args.legende and args.legende ~= '' then
                worldName, args.x, args.y, args.z
             imageCode = imageCode .. '|' .. args.legende
            )
            value = string.format("''[%s %s]''", mapUrl, linkText)
        else
            return -- Pas de coordonnées complètes
         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)
      
      
     -- Vérifier si le champ doit être affiché
     header:node(titleDiv)
     if not value or value == '' then
 
         if field.optional then
     if args.soustitre and args.soustitre ~= '' then
             return -- Champ optionnel vide, on l'ignore
         local subtitleDiv = mw.html.create('div')
         end
             :addClass('infobox-subtitle')
            :wikitext(args.soustitre)
         header:node(subtitleDiv)
     end
     end
      
 
     -- Formatage spécial pour certains champs
     root:node(header)
     if field.format then
 
         if field.format == 'seed' then
     -- Corps avec les champs
             value = string.format('<span style="color:#099DFF;">\'\'%s\'\'</span>', value)
     local body = mw.html.create('div')
        elseif field.format == 'link' and value then
        :addClass('infobox-body')
             value = string.format('[[%s]]', value)
 
    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
    end
   
    -- Ajouter la ligne du champ
    local row = html:tag('tr')
    row:tag('th')
        :attr('scope', 'row')
        :wikitext(field.label)
    row:tag('td')
        :wikitext(value or '')
end


function p.addCustomFields(html, args)
        -- Vérifier si on doit afficher les coordonnées automatiquement
    -- Champs personnalisés (champ1/valeur1, champ2/valeur2, etc.)
        local hasCoordinates = args.x and args.x ~= '' and args.y and args.y ~= '' and args.z and args.z ~= ''
    for i = 1, 10 do
        local coordinatesDisplayed = false
        local champKey = 'champ' .. i
 
        local valeurKey = 'valeur' .. i
        for _, champ in ipairs(section.champs or {}) do
       
            -- Détection automatique des coordonnées
        if args[champKey] and args[valeurKey] and args[champKey] ~= '' and args[valeurKey] ~= '' then
            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 row = html:tag('tr')
                local rowDiv = mw.html.create('div')
            row:tag('th')
                    :addClass('infobox-row')
                :attr('scope', 'row')
               
                :wikitext(args[champKey])
                local labelDiv = mw.html.create('div')
            row:tag('td')
                    :addClass('infobox-label')
                :wikitext(args[valeurKey])
                    :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
end


-- Fonction pour ajouter des images spéciales (comme carte)
    root:node(body)
function p.addSpecialImage(html, args, imageKey, sizeKey, captionKey)
   
     if args[imageKey] and args[imageKey] ~= '' then
    -- Traiter l'icône APRÈS avoir construit tout le HTML
         local imageSize = args[sizeKey] or '280x200px'
    local finalResult = tostring(root)
         local caption = args[captionKey] or mw.title.getCurrentTitle().text
   
     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 .. '}}'
          
          
         html:tag('tr')
         if currentFrame then
            :tag('td')
             iconeContent = currentFrame:preprocess(iconeContent)
            :attr('colspan', '5')
            :cssText('font-size: smaller; text-align: center;')
             :wikitext(string.format('[[Fichier:%s|%s|%s]]', args[imageKey], imageSize, caption))
    end
end
 
function p.findField(fields, key)
    for _, field in ipairs(fields) do
        if field.key == key then
            return field
         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 nil
   
    -- 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