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:PageInfo » : différence entre les versions

De Nefald
Hiob (discussion | contributions)
Aucun résumé des modifications
Hiob (discussion | contributions)
Annulation des modifications 735 de Hiob (discussion)
Balise : Annulation
 
(3 versions intermédiaires par le même utilisateur non affichées)
Ligne 1 : Ligne 1 :
local p = {}
local p = {}


-- Fonction pour extraire la description d'une page
-- Fonction principale qui retourne toutes les infos d'une page
function p.getDescription(frame)
function p.getInfo(frame)
     local pageName = frame.args[1]
     local pageName = frame.args[1]
     if not pageName or pageName == '' then
     if not pageName or pageName == '' then
         return ''
         return "'''Erreur :''' Aucun nom de page fourni"
     end
     end
      
      
     local pageObj = mw.title.new(pageName)
     local pageObj = mw.title.new(pageName)
     if not pageObj or not pageObj.exists then
     if not pageObj then
         return "''Page inexistante''"
         return "'''Erreur :''' Titre invalide : " .. pageName
     end
     end
      
      
    -- Extraire le contenu de la page
     if not pageObj.exists then
    local content = pageObj:getContent()
         return "'''Erreur :''' La page '" .. pageName .. "' n'existe pas"
     if not content then
         return ''
     end
     end
      
      
     -- Chercher une description dans différents formats
     local result = {}
      
      
     -- 1. Chercher dans un modèle {{Description|...}}
     -- Informations de base
     local desc = content:match('{{[Dd]escription%s*|%s*([^}]+)}}')
    table.insert(result, "=== Informations de la page ===")
     if desc then
    table.insert(result, "* '''Titre complet :''' " .. pageObj.prefixedText)
         return mw.text.trim(desc)
     table.insert(result, "* '''Namespace :''' " .. pageObj.nsText)
    table.insert(result, "* '''Titre (sans namespace) :''' " .. pageObj.text)
    table.insert(result, "* '''URL :''' " .. pageObj:fullUrl())
    table.insert(result, "* '''ID de la page :''' " .. pageObj.id)
   
    -- Contenu
    local content = pageObj:getContent()
     if content then
         local contentLength = mw.ustring.len(content)
        table.insert(result, "* '''Taille du contenu :''' " .. contentLength .. " caractères")
       
        -- Compter les sections
        local _, sectionCount = content:gsub('\n==', '\n==')
        table.insert(result, "* '''Nombre de sections :''' " .. sectionCount)
     end
     end
      
      
     -- 2. Chercher dans un champ description d'infobox
     -- Catégories
    desc = content:match('|%s*[Dd]escription%s*=%s*([^\n|]+)')
    local categories = pageObj.categories
     if desc then
    if categories and #categories > 0 then
         return mw.text.trim(desc)
        table.insert(result, "* '''Catégories :''' " .. #categories)
        local catList = {}
        for _, cat in ipairs(categories) do
            table.insert(catList, cat.text)
        end
        table.insert(result, "** " .. table.concat(catList, ", "))
     else
         table.insert(result, "* '''Catégories :''' Aucune")
     end
     end
      
      
     -- 3. Chercher dans un modèle {{Info|description=...}}
     -- Protection
    desc = content:match('{{[Ii]nfo[^}]*|%s*[Dd]escription%s*=%s*([^|}\n]+)')
    if pageObj.protectionLevels and next(pageObj.protectionLevels) then
     if desc then
        table.insert(result, "* '''Protection :''' Oui")
         return mw.text.trim(desc)
        for action, level in pairs(pageObj.protectionLevels) do
            table.insert(result, "** " .. action .. " : " .. table.concat(level, ", "))
        end
     else
         table.insert(result, "* '''Protection :''' Non")
     end
     end
      
      
     -- 4. Extraire le premier paragraphe (hors modèles)
     -- Redirection
     -- Nettoyer les modèles et les balises
     if pageObj.isRedirect then
    local cleaned = content:gsub('{{[^}]+}}', '')  -- Enlever les modèles
        table.insert(result, "* '''Type :''' Page de redirection")
    cleaned = cleaned:gsub('%[%[Category:[^%]]+%]%]', '') -- Enlever les catégories
     else
     cleaned = cleaned:gsub('%[%[Catégorie:[^%]]+%]%]', '')
        table.insert(result, "* '''Type :''' Page normale")
    cleaned = cleaned:gsub('<[^>]+>', '')  -- Enlever les balises HTML
    cleaned = cleaned:gsub('^%s*==+[^=]+==[^\n]*\n', '')  -- Enlever les titres
   
    -- Extraire le premier paragraphe significatif
    for line in cleaned:gmatch('[^\n]+') do
        line = mw.text.trim(line)
        if line ~= '' and not line:match('^[*#:]') and not line:match('^%s*{|') then
            -- Limiter la longueur
            if #line > 150 then
                line = line:sub(1, 147) .. '...'
            end
            return line
        end
     end
     end
      
      
     return "''Aucune description disponible''"
     return table.concat(result, "\n")
end
end


-- Fonction pour extraire le lien de documentation
-- Fonction pour obtenir uniquement le titre
function p.getDocumentation(frame)
function p.getTitle(frame)
     local pageName = frame.args[1]
     local pageName = frame.args[1]
     if not pageName or pageName == '' then
     if not pageName or pageName == '' then
Ligne 71 : Ligne 80 :
     local pageObj = mw.title.new(pageName)
     local pageObj = mw.title.new(pageName)
     if not pageObj or not pageObj.exists then
     if not pageObj or not pageObj.exists then
         return ''
         return "''Page inexistante''"
     end
     end
      
      
     local content = pageObj:getContent()
     return pageObj.text
     if not content then
end
 
-- Fonction pour obtenir le namespace
function p.getNamespace(frame)
    local pageName = frame.args[1]
     if not pageName or pageName == '' then
         return ''
         return ''
     end
     end
      
      
     -- Chercher différents formats de liens de documentation
     local pageObj = mw.title.new(pageName)
    if not pageObj or not pageObj.exists then
        return "''Page inexistante''"
    end
      
      
     -- 1. Lien externe direct [http://... Documentation]
     return pageObj.nsText ~= '' and pageObj.nsText or 'Principal'
     local docLink = content:match('%[%s*(https?://[^%s%]]+)%s+[Dd]ocumentation%s*%]')
end
     if docLink then
 
         return '[' .. docLink .. ' Documentation]'
-- Fonction pour obtenir l'URL complète
function p.getUrl(frame)
     local pageName = frame.args[1]
     if not pageName or pageName == '' then
         return ''
     end
     end
      
      
     -- 2. Lien externe avec texte alternatif
     local pageObj = mw.title.new(pageName)
    docLink = content:match('%[%s*(https?://[^%s%]]+)%s+[^%]]*[Dd]oc[^%]]*%]')
     if not pageObj or not pageObj.exists then
     if docLink then
         return "''Page inexistante''"
         return '[' .. docLink .. ' Documentation]'
     end
     end
      
      
     -- 3. Modèle {{Documentation|url=...}}
     return pageObj:fullUrl()
     docLink = content:match('{{[Dd]ocumentation%s*|%s*[Uu][Rr][Ll]%s*=%s*([^}|]+)')
end
     if docLink then
 
        docLink = mw.text.trim(docLink)
-- Fonction pour obtenir les catégories
         return '[' .. docLink .. ' Documentation]'
function p.getCategories(frame)
     local pageName = frame.args[1]
     if not pageName or pageName == '' then
         return ''
     end
     end
      
      
     -- 4. Champ documentation dans une infobox
     local pageObj = mw.title.new(pageName)
    docLink = content:match('|%s*[Dd]ocumentation%s*=%s*%[%s*(https?://[^%s%]]+)')
     if not pageObj or not pageObj.exists then
     if docLink then
         return "''Page inexistante''"
         return '[' .. docLink .. ' Documentation]'
     end
     end
      
      
     -- 5. Chercher n'importe quel lien externe (dernier recours)
     local categories = pageObj.categories
     docLink = content:match('%[%s*(https?://[^%s%]]+)')
     if not categories or #categories == 0 then
    if docLink then
         return "''Aucune catégorie''"
         return '[' .. docLink .. ' Lien externe]'
     end
     end
      
      
    -- 6. Vérifier si une sous-page /Documentation existe
     local catList = {}
     local docPage = pageName .. '/Documentation'
     for _, cat in ipairs(categories) do
     local docPageObj = mw.title.new(docPage)
         table.insert(catList, cat.text)
    if docPageObj and docPageObj.exists then
         return '[[' .. docPage .. '|Documentation]]'
     end
     end
      
      
     return "''Aucune documentation''"
     return table.concat(catList, ', ')
end
end


-- Fonction pour obtenir toutes les infos d'une page (debug)
-- Fonction pour extraire la description d'une page
function p.getInfo(frame)
function p.getDescription(frame)
     local pageName = frame.args[1]
     local pageName = frame.args[1]
     if not pageName or pageName == '' then
     if not pageName or pageName == '' then
         return 'Erreur : aucun nom de page fourni'
         return ''
     end
     end
      
      
     local pageObj = mw.title.new(pageName)
     local pageObj = mw.title.new(pageName)
     if not pageObj then
     if not pageObj or not pageObj.exists then
         return 'Erreur : titre invalide'
         return "''Page inexistante''"
    end
   
    local content = pageObj:getContent()
    if not content then
        return ''
     end
     end
      
      
     if not pageObj.exists then
    -- PRIORITÉ 1 : Chercher {{SHORTDESC:...}} (magic word de l'extension)
         return 'Erreur : la page n\'existe pas'
    local desc = content:match('{{SHORTDESC:([^}]+)}}')
     if desc then
        desc = mw.text.trim(desc)
         if desc ~= '' then
            return desc
        end
     end
     end
      
      
     local result = {}
     -- PRIORITÉ 1bis : Chercher aussi {{Short description|...}} (template standard)
    table.insert(result, "'''Informations sur la page : " .. pageName .. "'''")
     desc = content:match('{{[Ss]hort%s+description%s*|%s*([^}]+)}}')
     table.insert(result, "\n* '''Existe :''' Oui")
     if desc then
     table.insert(result, "\n* '''Namespace :''' " .. pageObj.namespace)
        desc = mw.text.trim(desc)
    table.insert(result, "\n* '''Titre complet :''' " .. pageObj.fullText)
        desc = desc:gsub('|.*$', '') -- Nettoyer paramètres supplémentaires
        if desc ~= '' then
            return desc
        end
    end
      
      
     local content = pageObj:getContent()
     -- PRIORITÉ 2 : Chercher dans un champ description d'infobox
     if content then
    desc = content:match('|%s*description%s*=%s*([^\n|]+)')
         table.insert(result, "\n* '''Longueur du contenu :''' " .. #content .. " caractères")
     if desc then
         table.insert(result, "\n* '''Premiers 200 caractères :'''\n<pre>" .. content:sub(1, 200) .. "...</pre>")
         desc = mw.text.trim(desc)
         if desc ~= '' and #desc > 10 then
            return desc
        end
     end
     end
      
      
     table.insert(result, "\n* '''Description extraite :''' " .. p.getDescription(frame))
     -- PRIORITÉ 3 : Extraire le premier paragraphe après l'infobox
     table.insert(result, "\n* '''Documentation extraite :''' " .. p.getDocumentation(frame))
     local afterInfobox = content:match('}}%s*\n(.+)')
      
      
     return table.concat(result)
     if afterInfobox then
        local beforeSection = afterInfobox:match('^(.-)%s*\n%s*==')
       
        if not beforeSection then
            beforeSection = afterInfobox
        end
       
        local cleaned = beforeSection
       
        -- Supprimer les magic words et templates
        cleaned = cleaned:gsub('{{SHORTDESC:[^}]+}}', '')
        cleaned = cleaned:gsub('{{[^}]+}}', '')
        cleaned = cleaned:gsub('%[%[[Cc]ategor[yi]e?:[^%]]+%]%]', '')
        cleaned = cleaned:gsub('<[^>]+>', '')
        cleaned = cleaned:gsub('\n\n+', '\n')
        cleaned = cleaned:gsub("'''", '')
        cleaned = cleaned:gsub("''", '')
       
        for line in cleaned:gmatch('[^\n]+') do
            line = mw.text.trim(line)
           
            if line ~= ''
              and not line:match('^[*#:;]')
              and not line:match('^%s*{|')
              and not line:match('^%s*|}')
              and not line:match('^%s*|[^%[]')
              and #line > 30 then
               
                if #line > 300 then
                    local cut = line:sub(1, 297)
                    local lastPeriod = cut:match('.*()%.%s')
                    if lastPeriod and lastPeriod > 200 then
                        line = cut:sub(1, lastPeriod)
                    else
                        line = cut .. '...'
                    end
                end
               
                return line
            end
        end
    end
   
    return "''Aucune description disponible''"
end
end


-- Fonction pour obtenir des statistiques sur une page
-- Fonction pour obtenir la taille de la page
function p.getStats(frame)
function p.getSize(frame)
     local pageName = frame.args[1]
     local pageName = frame.args[1]
     if not pageName or pageName == '' then
     if not pageName or pageName == '' then
Ligne 165 : Ligne 244 :
     local pageObj = mw.title.new(pageName)
     local pageObj = mw.title.new(pageName)
     if not pageObj or not pageObj.exists then
     if not pageObj or not pageObj.exists then
         return ''
         return "''Page inexistante''"
     end
     end
      
      
     local content = pageObj:getContent()
     local content = pageObj:getContent()
     if not content then
     if not content then
         return ''
         return '0'
     end
     end
      
      
     local stats = {}
     return tostring(mw.ustring.len(content))
    stats.longueur = #content
    stats.lignes = select(2, content:gsub('\n', '\n')) + 1
    stats.mots = select(2, content:gsub('%S+', ''))
   
    return string.format('%d caractères, %d lignes, ~%d mots',
        stats.longueur, stats.lignes, stats.mots)
end
end


-- Fonction pour extraire l'auteur/créateur
-- Fonction pour compter les sections
function p.getAuthor(frame)
function p.countSections(frame)
     local pageName = frame.args[1]
     local pageName = frame.args[1]
     if not pageName or pageName == '' then
     if not pageName or pageName == '' then
         return ''
         return '0'
     end
     end
      
      
     local pageObj = mw.title.new(pageName)
     local pageObj = mw.title.new(pageName)
     if not pageObj or not pageObj.exists then
     if not pageObj or not pageObj.exists then
         return ''
         return "''Page inexistante''"
     end
     end
      
      
     local content = pageObj:getContent()
     local content = pageObj:getContent()
     if not content then
     if not content then
         return ''
         return '0'
     end
     end
      
      
    -- Chercher un champ auteur
     local _, count = content:gsub('\n==', '\n==')
     local author = content:match('|%s*[Aa]uteur%s*=%s*([^\n|]+)')
    return tostring(count)
     if author then
end
         return mw.text.trim(author)
 
-- Fonction pour vérifier si une page est protégée
function p.isProtected(frame)
    local pageName = frame.args[1]
     if not pageName or pageName == '' then
         return 'Non'
     end
     end
      
      
     author = content:match('|%s*[Aa]uthor%s*=%s*([^\n|]+)')
     local pageObj = mw.title.new(pageName)
     if author then
     if not pageObj or not pageObj.exists then
         return mw.text.trim(author)
         return "''Page inexistante''"
     end
     end
      
      
     author = content:match('{{[Aa]uteur%s*|%s*([^}]+)}}')
     if pageObj.protectionLevels and next(pageObj.protectionLevels) then
     if author then
        return 'Oui'
         return mw.text.trim(author)
     else
         return 'Non'
     end
     end
   
    return ''
end
end


-- Fonction pour extraire la version
-- Fonction pour vérifier si une page est une redirection
function p.getVersion(frame)
function p.isRedirect(frame)
     local pageName = frame.args[1]
     local pageName = frame.args[1]
     if not pageName or pageName == '' then
     if not pageName or pageName == '' then
         return ''
         return 'Non'
     end
     end
      
      
     local pageObj = mw.title.new(pageName)
     local pageObj = mw.title.new(pageName)
     if not pageObj or not pageObj.exists then
     if not pageObj or not pageObj.exists then
         return ''
         return "''Page inexistante''"
     end
     end
      
      
     local content = pageObj:getContent()
     return pageObj.isRedirect and 'Oui' or 'Non'
     if not content then
end
 
-- Fonction pour obtenir l'ID de la page
function p.getId(frame)
    local pageName = frame.args[1]
     if not pageName or pageName == '' then
         return ''
         return ''
     end
     end
      
      
    -- Chercher un champ version
     local pageObj = mw.title.new(pageName)
     local version = content:match('|%s*[Vv]ersion%s*=%s*([^\n|]+)')
     if not pageObj or not pageObj.exists then
     if version then
         return "''Page inexistante''"
         return mw.text.trim(version)
     end
     end
      
      
     version = content:match('{{[Vv]ersion%s*|%s*([^}]+)}}')
     return tostring(pageObj.id)
     if version then
end
         return mw.text.trim(version)
 
-- Fonction pour obtenir le titre complet (avec namespace)
function p.getFullTitle(frame)
    local pageName = frame.args[1]
     if not pageName or pageName == '' then
         return ''
     end
     end
      
      
     -- Chercher un pattern v1.2.3 ou version 1.2.3
     local pageObj = mw.title.new(pageName)
    version = content:match('[Vv]ersion%s*:?%s*(%d+%.%d+[%.%d]*)')
     if not pageObj or not pageObj.exists then
     if version then
         return "''Page inexistante''"
         return version
    end
   
    version = content:match('v(%d+%.%d+[%.%d]*)')
    if version then
        return version
     end
     end
      
      
     return ''
     return pageObj.prefixedText
end
end


-- Fonction pour extraire la date de mise à jour
-- Fonction pour extraire l'image principale de la page
function p.getUpdateDate(frame)
function p.getMainImage(frame)
     local pageName = frame.args[1]
     local pageName = frame.args[1]
     if not pageName or pageName == '' then
     if not pageName or pageName == '' then
Ligne 269 : Ligne 349 :
     local pageObj = mw.title.new(pageName)
     local pageObj = mw.title.new(pageName)
     if not pageObj or not pageObj.exists then
     if not pageObj or not pageObj.exists then
         return ''
         return "''Page inexistante''"
     end
     end
      
      
Ligne 277 : Ligne 357 :
     end
     end
      
      
     -- Chercher une date de mise à jour
     -- Chercher dans l'infobox d'abord
     local date = content:match('|%s*[Mm]ise%s*à%s*jour%s*=%s*([^\n|]+)')
     local image = content:match('|%s*image%s*=%s*([^\n|]+)')
     if date then
     if image then
         return mw.text.trim(date)
         image = mw.text.trim(image)
        -- Nettoyer les éventuels paramètres de taille
        image = image:gsub('%s*|.*$', '')
        if image ~= '' then
            return image
        end
     end
     end
      
      
     date = content:match('|%s*[Uu]pdate[Dd]?%s*=%s*([^\n|]+)')
     -- Chercher la première image dans le contenu
     if date then
    image = content:match('%[%[Fichier:([^%]|]+)')
         return mw.text.trim(date)
    if not image then
        image = content:match('%[%[File:([^%]|]+)')
    end
    if not image then
        image = content:match('%[%[Image:([^%]|]+)')
    end
   
     if image then
         return mw.text.trim(image)
    end
   
    return "''Aucune image''"
end
 
-- Fonction pour obtenir la date de dernière modification
function p.getLastModified(frame)
    local pageName = frame.args[1]
    if not pageName or pageName == '' then
        return ''
    end
   
    local pageObj = mw.title.new(pageName)
    if not pageObj or not pageObj.exists then
        return "''Page inexistante''"
     end
     end
      
      
     date = content:match('|%s*[Dd]ate%s*=%s*([^\n|]+)')
     -- Utiliser l'API pour obtenir la date de dernière modification
     if date then
    local revId = pageObj.latest
         return mw.text.trim(date)
     if not revId then
         return "''Indisponible''"
     end
     end
      
      
     return ''
     return "Révision #" .. revId
end
end


return p
return p

Dernière version du 7 octobre 2025 à 11:52

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

local p = {}

-- Fonction principale qui retourne toutes les infos d'une page
function p.getInfo(frame)
    local pageName = frame.args[1]
    if not pageName or pageName == '' then
        return "'''Erreur :''' Aucun nom de page fourni"
    end
    
    local pageObj = mw.title.new(pageName)
    if not pageObj then
        return "'''Erreur :''' Titre invalide : " .. pageName
    end
    
    if not pageObj.exists then
        return "'''Erreur :''' La page '" .. pageName .. "' n'existe pas"
    end
    
    local result = {}
    
    -- Informations de base
    table.insert(result, "=== Informations de la page ===")
    table.insert(result, "* '''Titre complet :''' " .. pageObj.prefixedText)
    table.insert(result, "* '''Namespace :''' " .. pageObj.nsText)
    table.insert(result, "* '''Titre (sans namespace) :''' " .. pageObj.text)
    table.insert(result, "* '''URL :''' " .. pageObj:fullUrl())
    table.insert(result, "* '''ID de la page :''' " .. pageObj.id)
    
    -- Contenu
    local content = pageObj:getContent()
    if content then
        local contentLength = mw.ustring.len(content)
        table.insert(result, "* '''Taille du contenu :''' " .. contentLength .. " caractères")
        
        -- Compter les sections
        local _, sectionCount = content:gsub('\n==', '\n==')
        table.insert(result, "* '''Nombre de sections :''' " .. sectionCount)
    end
    
    -- Catégories
    local categories = pageObj.categories
    if categories and #categories > 0 then
        table.insert(result, "* '''Catégories :''' " .. #categories)
        local catList = {}
        for _, cat in ipairs(categories) do
            table.insert(catList, cat.text)
        end
        table.insert(result, "** " .. table.concat(catList, ", "))
    else
        table.insert(result, "* '''Catégories :''' Aucune")
    end
    
    -- Protection
    if pageObj.protectionLevels and next(pageObj.protectionLevels) then
        table.insert(result, "* '''Protection :''' Oui")
        for action, level in pairs(pageObj.protectionLevels) do
            table.insert(result, "** " .. action .. " : " .. table.concat(level, ", "))
        end
    else
        table.insert(result, "* '''Protection :''' Non")
    end
    
    -- Redirection
    if pageObj.isRedirect then
        table.insert(result, "* '''Type :''' Page de redirection")
    else
        table.insert(result, "* '''Type :''' Page normale")
    end
    
    return table.concat(result, "\n")
end

-- Fonction pour obtenir uniquement le titre
function p.getTitle(frame)
    local pageName = frame.args[1]
    if not pageName or pageName == '' then
        return ''
    end
    
    local pageObj = mw.title.new(pageName)
    if not pageObj or not pageObj.exists then
        return "''Page inexistante''"
    end
    
    return pageObj.text
end

-- Fonction pour obtenir le namespace
function p.getNamespace(frame)
    local pageName = frame.args[1]
    if not pageName or pageName == '' then
        return ''
    end
    
    local pageObj = mw.title.new(pageName)
    if not pageObj or not pageObj.exists then
        return "''Page inexistante''"
    end
    
    return pageObj.nsText ~= '' and pageObj.nsText or 'Principal'
end

-- Fonction pour obtenir l'URL complète
function p.getUrl(frame)
    local pageName = frame.args[1]
    if not pageName or pageName == '' then
        return ''
    end
    
    local pageObj = mw.title.new(pageName)
    if not pageObj or not pageObj.exists then
        return "''Page inexistante''"
    end
    
    return pageObj:fullUrl()
end

-- Fonction pour obtenir les catégories
function p.getCategories(frame)
    local pageName = frame.args[1]
    if not pageName or pageName == '' then
        return ''
    end
    
    local pageObj = mw.title.new(pageName)
    if not pageObj or not pageObj.exists then
        return "''Page inexistante''"
    end
    
    local categories = pageObj.categories
    if not categories or #categories == 0 then
        return "''Aucune catégorie''"
    end
    
    local catList = {}
    for _, cat in ipairs(categories) do
        table.insert(catList, cat.text)
    end
    
    return table.concat(catList, ', ')
end

-- Fonction pour extraire la description d'une page
function p.getDescription(frame)
    local pageName = frame.args[1]
    if not pageName or pageName == '' then
        return ''
    end
    
    local pageObj = mw.title.new(pageName)
    if not pageObj or not pageObj.exists then
        return "''Page inexistante''"
    end
    
    local content = pageObj:getContent()
    if not content then
        return ''
    end
    
    -- PRIORITÉ 1 : Chercher {{SHORTDESC:...}} (magic word de l'extension)
    local desc = content:match('{{SHORTDESC:([^}]+)}}')
    if desc then
        desc = mw.text.trim(desc)
        if desc ~= '' then
            return desc
        end
    end
    
    -- PRIORITÉ 1bis : Chercher aussi {{Short description|...}} (template standard)
    desc = content:match('{{[Ss]hort%s+description%s*|%s*([^}]+)}}')
    if desc then
        desc = mw.text.trim(desc)
        desc = desc:gsub('|.*$', '') -- Nettoyer paramètres supplémentaires
        if desc ~= '' then
            return desc
        end
    end
    
    -- PRIORITÉ 2 : Chercher dans un champ description d'infobox
    desc = content:match('|%s*description%s*=%s*([^\n|]+)')
    if desc then
        desc = mw.text.trim(desc)
        if desc ~= '' and #desc > 10 then
            return desc
        end
    end
    
    -- PRIORITÉ 3 : Extraire le premier paragraphe après l'infobox
    local afterInfobox = content:match('}}%s*\n(.+)')
    
    if afterInfobox then
        local beforeSection = afterInfobox:match('^(.-)%s*\n%s*==')
        
        if not beforeSection then
            beforeSection = afterInfobox
        end
        
        local cleaned = beforeSection
        
        -- Supprimer les magic words et templates
        cleaned = cleaned:gsub('{{SHORTDESC:[^}]+}}', '')
        cleaned = cleaned:gsub('{{[^}]+}}', '')
        cleaned = cleaned:gsub('%[%[[Cc]ategor[yi]e?:[^%]]+%]%]', '')
        cleaned = cleaned:gsub('<[^>]+>', '')
        cleaned = cleaned:gsub('\n\n+', '\n')
        cleaned = cleaned:gsub("'''", '')
        cleaned = cleaned:gsub("''", '')
        
        for line in cleaned:gmatch('[^\n]+') do
            line = mw.text.trim(line)
            
            if line ~= '' 
               and not line:match('^[*#:;]') 
               and not line:match('^%s*{|')
               and not line:match('^%s*|}')
               and not line:match('^%s*|[^%[]')
               and #line > 30 then
                
                if #line > 300 then
                    local cut = line:sub(1, 297)
                    local lastPeriod = cut:match('.*()%.%s')
                    if lastPeriod and lastPeriod > 200 then
                        line = cut:sub(1, lastPeriod)
                    else
                        line = cut .. '...'
                    end
                end
                
                return line
            end
        end
    end
    
    return "''Aucune description disponible''"
end

-- Fonction pour obtenir la taille de la page
function p.getSize(frame)
    local pageName = frame.args[1]
    if not pageName or pageName == '' then
        return ''
    end
    
    local pageObj = mw.title.new(pageName)
    if not pageObj or not pageObj.exists then
        return "''Page inexistante''"
    end
    
    local content = pageObj:getContent()
    if not content then
        return '0'
    end
    
    return tostring(mw.ustring.len(content))
end

-- Fonction pour compter les sections
function p.countSections(frame)
    local pageName = frame.args[1]
    if not pageName or pageName == '' then
        return '0'
    end
    
    local pageObj = mw.title.new(pageName)
    if not pageObj or not pageObj.exists then
        return "''Page inexistante''"
    end
    
    local content = pageObj:getContent()
    if not content then
        return '0'
    end
    
    local _, count = content:gsub('\n==', '\n==')
    return tostring(count)
end

-- Fonction pour vérifier si une page est protégée
function p.isProtected(frame)
    local pageName = frame.args[1]
    if not pageName or pageName == '' then
        return 'Non'
    end
    
    local pageObj = mw.title.new(pageName)
    if not pageObj or not pageObj.exists then
        return "''Page inexistante''"
    end
    
    if pageObj.protectionLevels and next(pageObj.protectionLevels) then
        return 'Oui'
    else
        return 'Non'
    end
end

-- Fonction pour vérifier si une page est une redirection
function p.isRedirect(frame)
    local pageName = frame.args[1]
    if not pageName or pageName == '' then
        return 'Non'
    end
    
    local pageObj = mw.title.new(pageName)
    if not pageObj or not pageObj.exists then
        return "''Page inexistante''"
    end
    
    return pageObj.isRedirect and 'Oui' or 'Non'
end

-- Fonction pour obtenir l'ID de la page
function p.getId(frame)
    local pageName = frame.args[1]
    if not pageName or pageName == '' then
        return ''
    end
    
    local pageObj = mw.title.new(pageName)
    if not pageObj or not pageObj.exists then
        return "''Page inexistante''"
    end
    
    return tostring(pageObj.id)
end

-- Fonction pour obtenir le titre complet (avec namespace)
function p.getFullTitle(frame)
    local pageName = frame.args[1]
    if not pageName or pageName == '' then
        return ''
    end
    
    local pageObj = mw.title.new(pageName)
    if not pageObj or not pageObj.exists then
        return "''Page inexistante''"
    end
    
    return pageObj.prefixedText
end

-- Fonction pour extraire l'image principale de la page
function p.getMainImage(frame)
    local pageName = frame.args[1]
    if not pageName or pageName == '' then
        return ''
    end
    
    local pageObj = mw.title.new(pageName)
    if not pageObj or not pageObj.exists then
        return "''Page inexistante''"
    end
    
    local content = pageObj:getContent()
    if not content then
        return ''
    end
    
    -- Chercher dans l'infobox d'abord
    local image = content:match('|%s*image%s*=%s*([^\n|]+)')
    if image then
        image = mw.text.trim(image)
        -- Nettoyer les éventuels paramètres de taille
        image = image:gsub('%s*|.*$', '')
        if image ~= '' then
            return image
        end
    end
    
    -- Chercher la première image dans le contenu
    image = content:match('%[%[Fichier:([^%]|]+)')
    if not image then
        image = content:match('%[%[File:([^%]|]+)')
    end
    if not image then
        image = content:match('%[%[Image:([^%]|]+)')
    end
    
    if image then
        return mw.text.trim(image)
    end
    
    return "''Aucune image''"
end

-- Fonction pour obtenir la date de dernière modification
function p.getLastModified(frame)
    local pageName = frame.args[1]
    if not pageName or pageName == '' then
        return ''
    end
    
    local pageObj = mw.title.new(pageName)
    if not pageObj or not pageObj.exists then
        return "''Page inexistante''"
    end
    
    -- Utiliser l'API pour obtenir la date de dernière modification
    local revId = pageObj.latest
    if not revId then
        return "''Indisponible''"
    end
    
    return "Révision #" .. revId
end

return p