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.
Version datée du 28 octobre 2025 à 20:39 par Hiob (discussion | contributions) (map)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)

La documentation pour ce module peut être créée à Module:Infobox/Core/doc

local p = {}
local getArgs = require('Module:Arguments').getArgs

-- Fonction pour générer le lien de carte dynamique
local function buildMapLink(args)
    -- Vérifier les champs obligatoires
    if not args.x or args.x == '' then return nil end
    if not args.y or args.y == '' then return nil end
    if not args.z or args.z == '' then return nil end
    if not args.worldname or args.worldname == '' then return nil end
    
    -- Valeurs par défaut pour les champs optionnels
    local mapname = args.mapname or 'flat'
    local zoom = args.zoom or '4'
    
    -- Construction de l'URL
    local url = string.format(
        'https://map.nefald.fr/?worldname=%s&mapname=%s&zoom=%s&x=%s&y=%s&z=%s',
        mw.uri.encode(args.worldname, 'PATH'),
        mw.uri.encode(mapname, 'PATH'),
        zoom,
        args.x,
        args.y,
        args.z
    )
    
    -- Retourner le lien formaté
    return string.format('[%s %s, %s, %s]', url, args.x, args.y, args.z)
end

-- 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 = ''
    
    -- 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')

    -- Vérifier si on a des coordonnées complètes
    local mapLink = buildMapLink(args)
    local coordinatesDisplayed = false

    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

        for _, champ in ipairs(section.champs or {}) do
            -- Gestion spéciale pour les coordonnées
            if mapLink and not coordinatesDisplayed and (champ.cle == 'x' or champ.cle == 'y' or champ.cle == 'z' or champ.cle == 'worldname' 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')
                    :wikitext(mapLink)
                
                rowDiv:node(labelDiv):node(valueDiv)
                body:node(rowDiv)
                coordinatesDisplayed = true
                
            -- Traitement normal des autres champs (ignorer x, y, z, worldname s'ils sont déjà affichés comme coordonnées)
            elseif not (mapLink and (champ.cle == 'x' or champ.cle == 'y' or champ.cle == 'z' or champ.cle == 'worldname' or champ.cle == 'mapname' or champ.cle == 'zoom')) 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
    local categories = addCategories(args, config, frame)
    
    return finalResult .. categories
end

return p
Les témoins (''cookies'') nous aident à fournir nos services. En utilisant nos services, vous acceptez notre utilisation de témoins.