Module:Œuvre

Documentation du module [voir] [modifier] [purger]
La documentation de ce module Scribunto écrit en Lua est incluse depuis sa sous-page de documentation.

Ce module est utilisé par {{Œuvre}}.

Après toute modification, vérifier qu’il n'y a pas de régression sur Modèle:Œuvre/tests.

-- Créé à partir :
-- * du module Opera sur it.wikisource, récupéré le 12 mai 2022
--   (https://it.wikisource.org/w/index.php?title=Modulo:Opera&oldid=2764861),
-- * de [[Module:Auteur2]]

local p = {}

function p.errorMessage(text)
    -- Return a html formated version of text stylized as an error.
    local html = mw.html.create('div')
    html:addClass('error')
        :wikitext(text)
        :wikitext('[[Catégorie:Pages faisant un appel erroné au modèle Œuvre]]')
    return tostring(html)
end

-- Améliore la présentation typographique d'un texte pour l'affichage
function p.printable(s)
    return string.gsub(s or "", "'", "’")
end

toromain = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X",
    "XI", "XII", "XIII", "XIV", "XV", "XVI", "XVII", "XVIII", "XIX", "XX",
    "XXI", "XXII"}

-- Améliore la présentation des dates
function p.printableDate(s)
    res = s
    res = string.gsub(res, "(%d+)e siècle", function(d) 
            if toromain[tonumber(d)] then
                d = toromain[tonumber(d)]
            end
            return mw.getCurrentFrame():expandTemplate{title="s", args = {d}}
        end)
    return res
end

-- Met la première lettre en capitales
function p.capitaliser(s)
    if s and type(s) == "string" then 
       if string.len(s) > 1 then
          return string.upper(string.sub(s, 1, 1)) .. string.sub(s, 2)
       else
          return string.upper(s)
       end
    else
       return s
    end
end

-- Transcrit en lettres les nombres inférieurs ou égaux à 10
nb2lettres = {"zéro", "un", "deux", "trois", "quatre", "cinq", 
    "six", "sept", "huit", "neuf", "dix"}
function p.nombre2lettres(nb)
    if((type(nb) == "number") == false) then
        return p.errorMessage("nombre2lettres doit recevoir un nombre et non " .. nb)
    end
    if(nb2lettres[nb+1]) then
        return nb2lettres[nb+1]
    else
        return nb
    end
end

-- Renvoit le code Wikimedia (utilisé dans les qualifiers) correspondant à une entité langue
function p.langue_id_to_code(langue_item_id)
    st = mw.wikibase.getBestStatements(langue_item_id, "P424")
    -- Certaines langues (ex. Q182695) n'ont pas de code Wikimédia
    if st and #st >= 1 and st[1].mainsnak.datavalue then
        return st[1].mainsnak.datavalue.value
    else
        return nil
    end
end
 
-- Renvoit la valeur d'une propriété d'un item (lorsque la valeur n'est pas elle-même une structure)
function p.get_property_value(item, property_id)
    statements = item:getBestStatements(property_id)
    if #statements and statements[1] and statements[1].mainsnak.datavalue then
         return statements[1].mainsnak.datavalue.value
    end
end

-- Renvoit la valeur d'une propriété d'un item en vérifiant la langue
function p.get_property_value_lang(item, property_id, lang)
    statements = item:getBestStatements(property_id)
    for _,statement in pairs(statements) do
        value = statement.mainsnak.datavalue.value
        if value.language and value.language == lang then
            return value.text
        end
    end
    return nil
end

-- Même chose, mais renvoit toutes les valeurs
function p.get_property_values(item, property_id)
    statements = item:getBestStatements(property_id)
    values = {}
    for _,statement in pairs(statements) do
        if statement.mainsnak.datavalue then
            table.insert(values, statement.mainsnak.datavalue.value)
        end
    end
    return values
end

-- Renvoit le texte d'une propriété d'un item
function p.get_property_value_text(item, property_id)
    statements = item:getBestStatements(property_id)
    if #statements and statements[1] and statements[1].mainsnak.datavalue then
         return statements[1].mainsnak.datavalue.value.text
    end
end

-- Renvoit le label de l'item désigné par une propriété d'un autre item
function p.get_property_value_label(item, property_id)
    statements = item:getBestStatements(property_id)
    if #statements and statements[1] and statements[1].mainsnak.datavalue then
         return mw.wikibase.getLabel(statements[1].mainsnak.datavalue.value.id)
    end
end

-- Rappel : précisions
-- 0 — milliard d’années, 1 — centaine de million d’années, …, 6 — millénaire, 
-- 7 — siècle, 8 — décennie, 9 — année, 10 — mois, 11 — jour, 12 — heure, 13 — minute, 14 — seconde

-- Renvoit le siècle à partir de l'année
function p.computeCenturyFromYear(year)
    if year >= 0 then
        return math.ceil(year / 100)
    else
        return -math.ceil(-year / 100)
    end
end

-- Renvoit le siècle en chiffres romains
function p.getTextForCentury(century, withHtml)
    local romanNumbers1 = {'', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X'}
    local romanNumbers2 = {'', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'}

    local text = romanNumbers2[math.floor(math.abs(century) / 10) + 1] .. romanNumbers1[math.floor(math.abs(century) % 10) + 1]
    if century == 1 or century == -1 then
         term = 'er'
    else
         term = 'e'
    end
    if withHtml then
        text = text .. '<sup>' .. term .. '</sup>'
    else
        text = text .. term
    end
    if century > 0 then
        return text .. ' siècle'
    else
        return text .. ' siècle av. J.-C.'
    end
end

function p.getTextForYear(year)
    local text = math.abs(year)
    if year < 0 then
        text = text .. ' av. J.-C.'
    end
    return text
end

function p.getDateFromTimeStatements(statements, field)
    if #statements == 0 then
        return {
            text = "",
            precision = 0
        }
    end

    local time = nil
    for _, statement in pairs(statements) do
        local newTime = p.getDateFromTimeStatement(statement, field)
        if time == nil then
            time = newTime
        elseif time.year ~= newTime.year then --années contradictoires
            mw.addWarning('Plusieurs années'  .. (field and ' de ' .. field or '') .. ' possibles sur Wikidata. Une manière simple de résoudre se problème est de mettre la date à afficher au rang "préféré".')
        end
    end

    if time == nil then
        return {
            text = "",
            precision = 0
        }
    end

    return time
end

function p.parseWbTime(value)
    local _,_, year = string.find(value.time, '([%+%-]%d%d%d+)%-')
    year = tonumber(year)
    
    return {
        year = year,
        century = p.computeCenturyFromYear(year),
        text = nil,
        precision = value.precision
    }
end

function p.getDateFromDataValue(datavalue, field)
    struct = p.parseWbTime(datavalue.value)
    local prefix = struct.prefix or ''

    --Create text
    if struct.precision >= 9 then
        struct.text = prefix .. p.getTextForYear(struct.year)
    elseif struct.precision == 8 then
        struct.text = prefix .. p.getTextForYear(struct.year)
    elseif struct.precision == 7 then
        struct.text = prefix .. p.getTextForCentury(struct.century, true)
    else
        struct.text = p.errorMessage('La date de ' .. field .. ' a une précision trop faible sur Wikidata')
    end
    
    return struct
end

function p.getDateFromTimeStatement(statement, field)
    local struct = {
        year = nil,
        century = nil,
        text = nil,
        precision = 0
    }
    local snak = statement.mainsnak
    if snak.snaktype == 'novalue' then
        return struct
    end
    if snak.snaktype == 'somevalue' then
        struct.text = '??'
        return struct
    end

    struct = p.getDateFromDataValue(snak.datavalue)

    if statement.qualifiers ~= nil then
        --Extract circa
        if statement.qualifiers.P1480 ~= nil then
            for _,qualifier in pairs(statement.qualifiers.P1480) do
                if qualifier.datavalue.value.id == 'Q5727902' then
                    prefix = 'circa '
                    struct.precision = 8 --TODO: hacky
                end
            end
        end

        -- Date de début et de fin
        if struct.precision <= 8 then
            if statement.qualifiers.P580 ~= nil then
                startdate = p.getDateFromDataValue(statement.qualifiers.P580[1].datavalue)
            end
            if statement.qualifiers.P582 ~= nil then
                enddate = p.getDateFromDataValue(statement.qualifiers.P582[1].datavalue)
            end
            if startdate and enddate then
                struct.text = startdate.year .. "-" .. enddate.year
                -- struct.text = mw.wikibase.renderSnaks(statement.qualifiers)
            end
        end

        --Use before and after if precision <= century
        if struct.precision <= 7 then
            if statement.qualifiers.P1319 ~= nil then
                for _,qualifier in pairs(statement.qualifiers.P1319) do
                    struct = p.parseWbTime(qualifier.datavalue.value)
                    struct.prefix = 'après '
                    struct.precision = 8 --TODO: hacky
               end
            elseif statement.qualifiers.P1326 ~= nil then
                for _,qualifier in pairs(statement.qualifiers.P1326) do
                    struct = p.parseWbTime(qualifier.datavalue.value)
                    struct.prefix = 'avant '
                    struct.precision = 8 --TODO: hacky
                end
            elseif statement.qualifiers.P1317 ~= nil then
                for _,qualifier in pairs(statement.qualifiers.P1317) do
                    struct = p.parseWbTime(qualifier.datavalue.value)
                    struct.prefix = 'floruit '
                    struct.precision = 8 --TODO: hacky
                end
           end
        end
    end

    return struct
end

function p.addCat(donnees, name)
    -- TODO si on crée un namespace Œuvre : vérifier le namespace (mw.title.getCurrentTitle().nsText) 
    if name then
        cattxt = '[[' .. mw.site.namespaces[14].name .. ':' .. name .. ']]'
        donnees.categories = donnees.categories .. cattxt 
    end
end

-- renvoit le nom du ou des traducteurs et éditeurs d'une édition.
function p.getTraducteursEditeursFromStatement(statement)
    res = ''
    premier = 0

    itemid = statement.mainsnak.datavalue.value.id
    traducteurs = mw.wikibase.getBestStatements(itemid, 'P655')
    for k, personne in pairs(traducteurs) do
        personneid = personne.mainsnak.datavalue.value.id
        name = mw.wikibase.getLabel(personneid)
        if name then
            sitelink = mw.wikibase.getSitelink(personneid)
            if premier == 0 then 
                premier = 1
                res = res .. "trad. "
            else 
                if k == 1 then res = res .. " trad. " end 
                res = res .. ", " 
            end
            if sitelink then 
                res = res .. '[[' .. sitelink .. '|' .. name .. ']]'
            else
                res = res .. name
            end
        end
    end
    editeurs = mw.wikibase.getBestStatements(itemid, 'P123')
    for _, editeur in pairs(editeurs) do
        editeurid = editeur.mainsnak.datavalue.value.id
        name = mw.wikibase.getLabel(editeurid )
        if string.len(res) > 0 then res = res .. ', ' end
        res = res .. "éd. " .. name
    end
    return res
end

-- Trie les éditions par ordre chronologique
function p.sort_editions(a, b)
    if a.pubdat and a.pubdat.precision > 0 and b.pubdat and b.pubdat.precision > 0 then
        return (a.pubdat.year < b.pubdat.year)
    else
        return 1
    end
end

-- Renvoit un lien d'édition de propriété sur Wikidata (icône stylo)
function p.dataEdit(itemId, propertyId)
    local edit_message = mw.message.new('vector-view-edit'):plain()
    res = '&nbsp;[[File:OOjs UI icon edit-ltr.svg|' .. edit_message .. '|12px|baseline|class=noviewer|link=https://www.wikidata.org/wiki/' .. itemId
    if propertyId then
        res = res .. '#' .. propertyId 
    end
    res = res .. ']]'
    return res
end

function p.auteurAblatif(nom, html)
    if string.match(nom:sub(1,1):lower(), '[aâeéêèiîoôuuy]') then
        return "d’"
    else
        if html then
            return "de&nbsp;"
        else
            return "de "
        end
    end
end

-- Récupère toutes les données de l'oeuvre
function p.getDonneesOeuvre(item)
    donnees = {}
    item_id = item:getId()

    -- On vérifie d'abord que le modèle n'a pas été appliqué par 
    -- erreur sur une édition
    natures = item:getBestStatements('P31')
    for _,nature in pairs(natures) do
        if nature.mainsnak.datavalue.value.id == 'Q3331189' then
            donnees.erreur = "[[d:" .. item:getId() .. "|" .. item:getId() .. "]] (" .. item:getLabel() .. ") est une édition, pas une œuvre."
            return donnees
        end       
    end

    donnees.wikidata = item_id
    donnees.categories = ""

    -- le label de l'item sur Wikidata    
    donnees.label = p.printable(item:getLabel())

    -- le titre de la page, en retirant le nom de l'auteur et d'autres choses
    donnees.titre = mw.title.getCurrentTitle().text
    donnees.titre = p.printable(string.gsub(donnees.titre, ' %(.*%)', ''))
    
    -- la langue de l'œuvre
    langues = item:getBestStatements('P407')
    langues_codes = {}
    lst_langues = {}
    if langues and #langues >= 1 then
        for _, langue in pairs(langues) do 
            langue_value = langue.mainsnak.datavalue.value
            table.insert(langues_codes, p.langue_id_to_code(langue_value.id))
            table.insert(lst_langues, mw.wikibase.getLabel(langue_value.id))
        end
    end
    donnees.langues = lst_langues
    
    -- Titre original de l'œuvre (P357 est l'ancienne propriété dépréciée, mais elle est encore
    -- utilisée sur de nombreux items)

    tous_titres = item:getBestStatements('P1476')
    for _, v in pairs(item:getBestStatements('P357')) do
         table.insert(tous_titres, v)
    end

    -- P1705 n'est pas prévu pour les oeuvres littéraires
    -- titre_original = item:getBestStatements('P1705')
    -- if #titre_original > 0 then
    --     donnees.titreOriginal = p.printable(titre_original [1].mainsnak.datavalue.value.text)
    --     donnees.titreOriginalEditer = p.dataEdit(item_id, 'P1705')
    -- end

    for _, titre in pairs(tous_titres) do
        titre_value = titre.mainsnak.datavalue.value
        if titre_value.language == 'fr' then
            donnees.titreEnFrancais = p.printable(titre_value.text)
        elseif #langues_codes > 0 and titre_value.language == langues_codes[1] then
            -- On ne gère qu'un seul titre original
            donnees.titreOriginal = p.printable(titre_value.text)
            donnees.titreOriginalEditer = p.dataEdit(item_id, 'P1476')
        end
    end
    
    -- Sous-titre
    donnees.sousTitre = p.printable(p.get_property_value_text(item, 'P1680'))
    -- donnees.sousTitre = c.getClaimValue(c.getSingleClaimByProperty(item, 'P1680'))
    
    -- Forme (roman, etc.) de l'oeuvre
    donnees.forme = p.printable(p.get_property_value_label(item, 'P7937'))

    -- Auteurs
    auteurs = item:getBestStatements('P50')
	listeAuteurs = {}
	listeLiensAuteurs = {}
    ablatif = nil
	for _, auteur in pairs(auteurs) do
        auteur_id = auteur.mainsnak.datavalue.value.id

        labelAuteur = mw.wikibase.getLabel(auteur_id) or "Anonyme"
		table.insert(listeAuteurs, labelAuteur)

        lien = mw.wikibase.sitelink(auteur_id)
        if lien then
   	        lienAuteur = '[[' .. mw.wikibase.sitelink(auteur_id) .. '|' .. labelAuteur .. ']]'
        else
            lienAuteur = labelAuteur
        end
        table.insert(listeLiensAuteurs, lienAuteur)
    end
    auteursHorsWikidata = item:getBestStatements('P2093')
    for _, auteur in pairs(auteursHorsWikidata) do
        table.insert(listeAuteurs, auteur.mainsnak.datavalue.value)
        table.insert(listeLiensAuteurs, auteur.mainsnak.datavalue.value)
    end
    donnees.auteur = p.printable(mw.text.listToText(listeLiensAuteurs, ', ', ' et '))
    if #listeAuteurs > 0 then 
        donnees.auteurAblatif = p.auteurAblatif(listeAuteurs[1], true)
    else
        donnees.auteurAblatif = "de "
    end

    -- Genre : pas très intéressant me semble-t-il
    -- donnees.genre = string.lower(c.concat(c.getLabelsFromPropertyValues(item, 'P136'), ', '))
    
    -- Date de publication
    datePublication = item:getBestStatements('P577')
    if datePublication and #datePublication > 0 and datePublication[1].mainsnak then        
        -- donnees.datePublication = p.getDateFromTimeStatement(datePublication[1]).text
        donnees.datePublication = p.printableDate(mw.wikibase.renderSnak(datePublication[1].mainsnak))
        donnees.anneePublication = p.getDateFromTimeStatement(datePublication[1]).year
    end 
    
    -- Composition
    dateCreation = item:getBestStatements('P571')
    if dateCreation and #dateCreation > 0 and dateCreation[1].mainsnak then
        -- donnees.dateCreation = p.getDateFromTimeStatement(dateCreation[1]).text
        -- donnees.dateCreation = p.printableDate(mw.wikibase.renderSnak(dateCreation[1].mainsnak))
        donnees.anneeCreation = p.getDateFromTimeStatement(dateCreation[1]).year
        donnees.dateCreation = p.printableDate(p.getDateFromTimeStatements(dateCreation, nil).text)
    end 
    
    -- Identifiant dans le catalogue de la BNF
    bnfid = item:getBestStatements('P268')
    if bnfid and #bnfid > 0 then
        donnees.bnfid = bnfid[1].mainsnak.datavalue.value
    end

 
    -- Sujet principal
    donnees.arguments = {}
    arguments = item:getBestStatements('P921')
    if #arguments and arguments[1] and arguments[1].mainsnak.datavalue then
         table.insert(donnees.arguments,
                      mw.wikibase.getLabel(arguments[1].mainsnak.datavalue.value.id))
    end
        
    -- Mouvement
    donnees.mouvements = {}
    mouvements = item:getBestStatements('P135')
    if #mouvements and mouvements [1] and mouvements [1].mainsnak.datavalue then
         table.insert(donnees.mouvements,
                      mw.wikibase.getLabel(mouvements [1].mainsnak.datavalue.value.id))
    end
    
    -- Fait partie de
    -- donnees.partieOeuvre = c.getClaimValuesByProperty('P361')
    -- donnees.partieOeuvre = c.getLinksParteOpere(donnees.partieOeuvre )
    
    -- Incipit de l'œuvre
    donnees.incipit = p.get_property_value_text(item, 'P1922')
    
    -- Liens vers autres projets
    donnees.wikipedia = item:getSitelink('frwiki')
    donnees.wikiquote = item:getSitelink('frwikiquote')
    donnees.wikibooks = item:getSitelink('frwikibooks')
    donnees.commons = item:getSitelink('commonswiki')
    donnees.commonscat = p.get_property_value(item, 'P373')
    
    -- Image
    donnees.image = p.get_property_value(item, 'P18')
    
    -- Éditions
    donnees.editions = item:getBestStatements('P747')
    donnees.editions_editer = p.dataEdit(item_id, 'P747')
    editions_info = {}
    
    donnees.listeEditionsEnFrancais = ''
    nbEditionsEnFrancais = 0
    itemLangueFrancaise = 'Q150'
    for _, edition in pairs(donnees.editions) do
        edition_id = edition.mainsnak.datavalue.value.id
        edition_item = mw.wikibase.getEntity(edition_id)
        langues = edition_item:getBestStatements('P407')
        -- On se limite aux éditions en français
        est_francais = false
        if langues and #langues > 0 then
            for _, langue in pairs(langues) do
                if langue.mainsnak.datavalue.value.id == itemLangueFrancaise then
                     est_francais = true
                     break
                end
            end
        end
        if est_francais then
            edition_info = {
                ["id"] = edition_id,                 
                ["lien"] = edition_item:getSitelink(),
                ["label"] = edition_item:getLabel(),
                ["titre"] = p.get_property_value_lang(edition_item, 'P1476', 'fr'),
                ["sousTitre"] = p.get_property_value_lang(edition_item, 'P1680', 'fr') ,
                ["wikisourcePageName"] = edition_item:getSitelink('frwikisource'),
                ["pubdat"] = p.getDateFromTimeStatements(edition_item:getBestStatements('P577')),
                ["traducteursEditeurs"] = 
                    p.printable(p.getTraducteursEditeursFromStatement(edition)),
                ["wsindexpages"] = p.get_property_values(edition_item, 'P1957'),
                ["facsimiles"] = edition_item:getBestStatements('P996'),
                ["gallicaid"] = p.get_property_value(edition_item, 'P4258'),
                ["sitelinks"] = edition_item["sitelinks"],
            }
            table.insert(editions_info, edition_info)
        end
    end
    table.sort(editions_info, p.sort_editions)
    for _, edition_info in pairs(editions_info) do
        if edition_info.titre and string.len(edition_info.titre) > 0 then
            intitule = p.printable(edition_info.titre)
            if edition_info.sousTitre and string.len(edition_info.sousTitre) > 0 then
                postIntitule = edition_info.sousTitre
            end
        elseif edition_info.label and string.len(edition_info.label) > 0 then
            intitule = p.printable(edition_info.label)
        else
            intitule = ""
        end

        -- Icône pour l'avancement
		q_badges = {
			["Q28064618"] = nil,  -- libellé Wikidata : document numérique
			["Q20748094"] = nil,  -- libellé Wikidata : texte incomplet 
			["Q20748091"] = "3/4",  -- libellé Wikidata : texte non corrigé
			["Q20748092"] = "4/4",  -- libellé Wikidata : texte relu et corrigé
			["Q20748093"] = "validé" -- libellé Wikidata : texte validé
		}
		avancement = nil
		if edition_info.sitelinks and edition_info.sitelinks["frwikisource"] and edition_info.sitelinks["frwikisource"]["badges"] then
			badges = edition_info.sitelinks["frwikisource"]["badges"]
			for _, badge in pairs(badges) do
				if q_badges[badge] then
					avancement = mw.getCurrentFrame():expandTemplate{
						title = q_badges[badge], 
						args = {}
					}
				end
			end
		end

        lien = edition_info.lien or label
        wspagename = edition_info.wikisourcePageName or intitule
        facsimiles = edition_info.facsimiles
	    fs_main = nil
        if #facsimiles >= 2 then
            -- On cherche si l'un des facsimiles a la propriété "volume" = 1
            for idx_fs, facsimile in pairs(facsimiles) do
                if facsimile["qualifiers"] then
    		        for qualifierid, val in pairs(facsimile["qualifiers"]) do
	    		        if qualifierid == "P478" and val[1].datavalue.value == "1" then
    				        fs_main = facsimile
		    		        break
			            end
		            end
                end
		        if fs_main then
			        break
		        end
	        end
        elseif #facsimiles == 1 then
            fs_main = facsimiles[1]
        end
        if fs_main then
            -- Utilisation du modèle L2S si un fac-similé a priorité sur les autres
            indexfile = 'Livre:' ..  fs_main.mainsnak.datavalue.value
            desc = mw.getCurrentFrame():expandTemplate{
                title = "Livre2Scanné", 
                args = {wspagename, indexfile, intitule}
            }
        else
            -- Sinon, simple liste des fac-similes
            if edition_info.wikisourcePageName then
                desc = '[[' .. edition_info.wikisourcePageName .. "|" .. intitule .. ']]'
            else
                desc = intitule
            end
        end
        if postIntitule then desc = desc .. " " .. postIntitule end
        if edition_info.pubdat and edition_info.pubdat.precision > 0 then
            desc = desc .. " (" .. edition_info.pubdat.text
            if string.len(edition_info.traducteursEditeurs) > 0 then
                desc = desc .. ", " .. edition_info.traducteursEditeurs
            end
            desc = desc .. ")"
        elseif string.len(edition_info.traducteursEditeurs) > 0 then
            desc = desc .. " (" .. edition_info.traducteursEditeurs .. ")"
        end
        if fs_main == nil then
            if #facsimiles > 1 then
                -- Liens vers les fac-similés, aucun n'étant privilégié
                desc = desc .. " — "
                for k, facsimile in pairs(facsimiles) do 
                    if k > 1 then desc = desc .. ", " end
                    desc = desc .. "[[Livre:" .. facsimile.mainsnak.datavalue.value .. "|index " .. k .. "]]"
                end
            elseif not #facsimiles == 0 then
                -- On ne met le lien vers Gallica que si on n'a pas encore de fac-similé
                if edition_info.gallicaid then
                    desc = desc .. "  — [https://gallica.bnf.fr/ark:/12148/" .. edition_info.gallicaid .. " fac-similé] sur Gallica"
                end
            end
        end
        if avancement then
            desc = desc .. " " .. avancement
        end
        desc = desc .. " " .. p.dataEdit(edition_info.id)       
        donnees.listeEditionsEnFrancais = donnees.listeEditionsEnFrancais .. '\n* ' .. desc
    end
    donnees.nbEditionsEnFrancais = #editions_info
    donnees.nbEditionsEnFrancaisLettres = p.capitaliser(p.nombre2lettres(#editions_info))
    
    return donnees
end

function p.main(frame)
    --Table de paramètres sans les paramètres vides
    local args = {}
    if type(frame) == "string" then
        args["item"] = frame -- ex. "Q512807"
    else
        for k,v in pairs(frame:getParent().args) do
            if v ~= '' then
                args[k] = v
           end
        end
    end

    -- Contenu de la page
    local contenu = args["contenu"]

    -- Argument à passer pour éviter l'affichage des catégories (ex. dans une page de test)
    local nocat = args["nocat"]
 
    -- Pour forcer l'image (si l'image de Wikidata est trop large, par exemple)
    local image = args["image"]

    -- On peut passer l'argument "item" (ex. pour faire des tests)
    if args["item"] == nil then
        item = mw.wikibase.getEntityObject()
    else
        item = mw.wikibase.getEntity(args["item"])
    end    

    donneesOeuvre = p.getDonneesOeuvre(item)

    if donneesOeuvre.erreur then
        output = "<div class=error>'''Erreur''' : " .. donneesOeuvre.erreur .. "</div>"
        output = output .. '[[' .. mw.site.namespaces[14].name .. ':Pages appliquant le modèle Œuvre à une édition]]'
        return output
    end

    -- On peut désactiver l'affichage de la liste des éditions
    if args["éditions"] == "non" then
        donneesOeuvre["afficherEditions"] = nil
    else
        donneesOeuvre["afficherEditions"] = "oui"
    end 

    donnees = donneesOeuvre

    if nocat == "oui" then
        donnees.nocat = "oui"
    end

    if image then
        donnees.image = image
    end

    -- Date de création
    if donnees.anneeCreation == nil then
        p.addCat(donnees, 'Œuvres sans date de création')
    else
        -- Siècle
        siecle = p.getTextForCentury(p.computeCenturyFromYear(donnees.anneeCreation))
        p.addCat(donnees, siecle) 
    end
    
    -- Œuvres de l'auteur
    if listeAuteurs == nil or next(listeAuteurs) == nil then
        p.addCat(donnees, 'Œuvres d’auteur inconnu')
    else
        for _, auteur in pairs(listeAuteurs) do 
            p.addCat(donnees, 'Œuvres ' .. p.auteurAblatif(auteur, false) .. auteur) 
        end
    end
    
    -- Langue originale de l'œuvre
    if #donnees.langues > 0 then 
        for _, langue in pairs(donnees.langues) do
            p.addCat(donnees, 'Œuvre de langue originale en '..langue) 
        end
    else
        p.addCat(donnees, 'Œuvre sans langue originale sur Wikidata')
    end
    
    -- Catégories par éditions
    -- Intérêt limité, car cela correspond au nombre d'éditions sur 
    --   Wikidata, pas sur Wikisource
    -- if #donnees.editions > 1 then p.addCat(donnees, 'Éditions multiples')
    -- elseif #donnees.editions == 1 then p.addCat(donnees, 'Œuvres avec une seule édition')
    -- else p.addCat(donnees, 'Œuvres sans édition') end
    
    -- Catégorie par argument ou mouvement artistique
    for _, arg in pairs(donnees.arguments) do p.addCat(donnees, arg) end
    for _, mov in pairs(donnees.mouvements) do p.addCat(donnees, mov) end

    -- Et le contenu de la page créé par l'utilisateur du modèle
    if contenu then 
        donnees.contenu = contenu 
    end

    -- On appelle le modèle « boîte » pour afficher toutes ces données
	cleanArgs = {}
	for i, v in pairs(donnees) do
		if type(v) ~= "table" then cleanArgs[i] = v end
	end
    output = mw.getCurrentFrame():expandTemplate{title = 'Œuvre/boîte', args = cleanArgs}

    return output 
end

function p.oeuvre( frame )
    return p.main( frame )
end

return p