Module:Italiques biologiques

De VSST
Révision datée du 21 janvier 2021 à 13:51 par imported>Jacques Ducloy (1 révision importée)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)

Modèle:Protection

Utilisation

Fonctions exportables :

  • titre_en_italiques(frame) – met le titre en italique, en ignorant la partie (éventuelle) homonymie. Ne met pas l'espace de nom éventuel en italique.
    • paramètre nommé optionnel : "lang=XX", qui insert un span décrivant la langue.
  • ns(frame) − prend en paramètre non nommé un nom scientifique et retourne ce nom en italique inconditionnellement, en respectant les contraintes typographiques de la biologie. (appellé par {{Taxobox taxon}})
  • nt(frame) − similaire à ns(frame) mais utilisé par {{Taxobox}}. Prend en paramètres non nommés (dans l'ordre) nom, nom2 et rang, et utilise nom2 s'il est non vide sinon nom (utile pour s'adapter à la syntaxe de {{Taxobox}} qui peut être « rang | nom » ou « rang | nom wiki | nom ». Important : éviter d'utiliser cette fonction dans un autre contexte car pour des raisons techniques elle utilise du code HTML (et non wiki) pour gérer l'italique
  • titre(frame) – prend en paramètre non nommé un nom scientifique et modifie le titre de l'article pour le mettre en italique. La fonction récupère le titre de l'article et ne met en italiques qui si le titre est de la forme XXXYYY, avec XXX le nom scientifique en paramètre et YYY éventuellement vide. Seule la partie XXX est passée en italique. Ne fait rien dans les autres cas, ni si la fonction est appelée depuis au autre espace de nom que l'espace encyclopédique. (appellé par {{Taxoboxoutils titre en italique}})
    • paramètre nommé optionnel : "titre=XXX" : si ce paramètre est indiqué la fonction utilise XXX comme titre de la page au lieu du titre réel. De plus le résultat est retourné dans un nowiki afin de visualiser ce qui aurait été fait (option servant pour les pages de documentation et de test).

Modules externes et autres éléments dont ce module a besoin pour fonctionner :

  • mw.title (récupération du titre et espace de nom de la page)

Modèle:Section déroulante début Note : ces fonctions ne testent pas s'il est pertinent d'utiliser l'italique.

Fonction ns(frame) :

{{#invoke:Italiques biologiques|ns|Citrus ×paradisi}} → Citrus ×paradisi
{{#invoke:Italiques biologiques|ns|×Sorbopyrus auricularis}} → ×Sorbopyrus auricularis
{{#invoke:Italiques biologiques|ns|Iberodorcadion (Hispanodorcadion) aguadoi}} → Iberodorcadion (Hispanodorcadion) aguadoi
{{#invoke:Italiques biologiques|ns|Pelophylax kl. esculentus}} → Pelophylax kl. esculentus
{{#invoke:Italiques biologiques|ns|Brassica olearacea var. gemmifera}} → Brassica olearacea var. gemmifera
{{#invoke:Italiques biologiques|ns|Bla ×bli var. blo kl. blu}} → Bla ×bli var. blo kl. blu
{{#invoke:Italiques biologiques|ns|Uroplatus (genre)}} → Uroplatus (genre) − cas de mise en italique inconditonnel


Fonction titre(frame)

Note : un retour vide (après le "→") indique que la fonction a décidé de ne pas modifié le titre, elle retourne donc une chaîne vide.

{{#invoke:Italiques biologiques|titre|Citrus ×paradisi|titre=Citrus ×paradisi}} → {{DISPLAYTITLE:<span style="font-style: normal">Citrus ×paradisi</span>|noerror}}
{{#invoke:Italiques biologiques|titre|×Sorbopyrus auricularis|titre=×Sorbopyrus auricularis}} → {{DISPLAYTITLE:<span style="font-style: normal">×Sorbopyrus auricularis</span>|noerror}}
{{#invoke:Italiques biologiques|titre|Uroplatus guentheri|titre=Uroplate de Günther}} →
{{#invoke:Italiques biologiques|titre|Uroplatus guentheri|titre=Uroplatus guentheri (animal)}} → {{DISPLAYTITLE:<span style="font-style: normal">Uroplatus guentheri</span> (animal)|noerror}}
{{#invoke:Italiques biologiques|titre|Brassica olearacea var. gemmifera|titre=Brassica olearacea var. gemmifera}} → {{DISPLAYTITLE:<span style="font-style: normal">Brassica olearacea var. gemmifera</span>|noerror}}
{{#invoke:Italiques biologiques|titre|Brassica olearacea var. gemmifera|titre=Fox à poil dur}} →
{{#invoke:Italiques biologiques|titre|Uroplatus|titre=Uroplatus sikorae}} → {{DISPLAYTITLE:<span style="font-style: normal">Uroplatus</span> sikorae|noerror}} ⇒ limitation : la partie "homonymie" est considérée comme "YYY si le titre est XXXXYYY et que le nom scientifique indiqué est exactement XXXX". On voit ici que si on est titré genre sur l'article mais qu'on pense être l'espèce correspondante ça ne fait pas ce qui est prévu. Si c'est un problème il est possible d'imposer en plus la présence de parenthèses dans la partie homonymie. Me dire.
{{#invoke:Italiques biologiques|titre|Brassica olearacea ''var.'' gemmifera|titre=Fox à poil dur}} → {{Article de Biologie à corriger|clef=NS|doc=Modèle:Taxobox taxon|message=Nom de taxon 'Brassica olearacea ''var.'' gemmifera' non reconnu}} − exemple de présence d'une mise en forme dans le nom scientifique indiqué

Modèle:Projet Scribunto



-- gestion de la mise en italique d'un nom scientifique, en respectant les conventions de la biologie

local p = {}

-- fonction basique mettant le titre courant en italique, sauf la partie namespace et la partie homonymie si présente
-- paramètres : lang → optionnel : ajout d'un tag de langue si présent
function p.titre_en_italiques(frame)

    local titre = mw.title.getCurrentTitle() -- l'objet titre pour la page courante
    local resu  -- le résultat qui sera retourné
    local page = titre.text  -- le nom de la page, sans le namespace
    -- paramètre optionnel : la langue
    local lang = frame.args["lang"] or frame:getParent().args["lang"]

    -- variables contenant l'ouverture et la fermeture du span (ou vide)
    local ospan = ""
    local fspan = ""
    if (lang) then
        ospan = '<span lang="' .. lang .. '">'
        fspan = '</span>'
    end
    
    -- préparation résultat : on commence par le namespace
    if (titre.nsText ~= "") then
        resu = titre.nsText .. ":"
    end
    -- on ajoute le span de la langue si demandé
    resu = resu .. ospan
    -- on ajoute l'italique
    resu = resu .. "''"
    if (mw.ustring.find(page, " (", 1, true)) then
        -- présence d'une homonymie, on ajoute la fin des italiques
        -- avant le " (" (une seule fois, au cas où il y aurait plusieurs ())
        -- on ajoute aussi la fermeture éventuelle du span
        resu = resu .. mw.ustring.gsub(page, " [(]", "''" .. fspan .. " (", 1)
    else
        -- pas d'homonymie, on ajoute la page + la fin de l'italique + fin du span
        resu = resu .. page .. "''" .. fspan
    end
    -- résultat, dans un preprocess afin d'interpréter son action
    return frame:preprocess("{{DISPLAYTITLE:" .. resu .. "|noerror}}")
end

-- retourne le texte après avoir supprimer les espaces, retour ligne... en début et fin de texte.
-- si texte == nil, la fonction retourne nil. 
-- Si le texte est vide ou composé uniquement d'espces, la fonction retourne un texte vide ''.
function p.trim (texte)
    return texte and string.match (texte, '^%s*(.-)%s*$')
end

-- table des éléments à ne pas mettre en italique
-- note : mettre un " " avant un terme qui existe aussi sous forme longue
--  exemple : " var.", à cause de "convar.". Sans l'espace les deux vont s'appliquer
--            au texte analysé. Notez de bien répercuter ce même espace dans la partie de droite
p.exclude = {
    { " cl[.]", " ''cl.''" },
    { "convar[.]", "''convar.''" },
    { " f[.]", " ''f.''" },
    { " gen[.]", " ''gen.''" },
    { "kl[.]", "''kl.''" },
    { "nothog[.]", "''nothog.''" },
    { "nothosp[.]", "''nothosp.''" },
    { "nothovar[.]", "''nothovar.''" },
    { " ord[.]", " ''ord.''" },
    { " fam[.]", " ''fam.''" },
    { " sect[.]", " ''sect.''" },
    { " ser[.]", " ''ser.''" },
    { " sp[.]", " ''sp.''" },
    { "subg[.]", "''subg.''" },
    { "subsp[.]", "''subsp.''" },
    { " tr[.]", " ''tr.''" },
    { " var[.]", " ''var.''" },
    { "×", "''×''" },
    { "[(]", "''(''" },
    { "[)]", "'')''" }
}
-- liste d'exclusion uniquement pour mettre droit dans la partie {{taxobox}} italique (ifgenre)
p.exclude_span = {
    { " cl[.]", " <span style=\"font-style: normal\">cl.</span>" },
    { "convar[.]", "<span style=\"font-style: normal\">convar.</span>" },
    { " f[.]", " <span style=\"font-style: normal\">f.</span>" },
    { " gen[.]", " <span style=\"font-style: normal\">gen.</span>" },
    { "kl[.]", "<span style=\"font-style: normal\">kl.</span>" },
    { "nothog[.]", "<span style=\"font-style: normal\">nothog.</span>" },
    { "nothosp[.]", "<span style=\"font-style: normal\">nothosp.</span>" },
    { "nothovar[.]", "<span style=\"font-style: normal\">nothovar.</span>" },
    { " ord[.]", " <span style=\"font-style: normal\">ord.</span>" },
    { " fam[.]", " <span style=\"font-style: normal\">fam.</span>" },
    { " sect[.]", " <span style=\"font-style: normal\">sect.</span>" },
    { " ser[.]", " <span style=\"font-style: normal\">ser.</span>" },
    { " sp[.]", " <span style=\"font-style: normal\">sp.</span>" },
    { "subg[.]", "<span style=\"font-style: normal\">subg.</span>" },
    { "subsp[.]", "<span style=\"font-style: normal\">subsp.</span>" },
    { " tr[.]", " <span style=\"font-style: normal\">tr.</span>" },
    { " var[.]", " <span style=\"font-style: normal\">var.</span>" },
    { "×", "<span style=\"font-style: normal\">×</span>" },
    { "[(]", "<span style=\"font-style: normal\">(</span>" },
    { "[)]", "<span style=\"font-style: normal\">)</span>" }
}

--[[
  Liste d'exclusion de noms de clades qui sont français et donc ne doivent pas être en italique
--]]
p.exclude_clades = {
    "Angiospermes"
}

--[[
  Retourne vrai si le nom passé est un nom de clade en français (ça *doit* être un rang clade)
--]]
function p.clade_francais(nom)
    local tst -- on regarde si présence d'accents
    tst = mw.ustring.find(nom, "[éèêëàäâçùüüïîôö]")
    if (tst ~= nil) then
        return true -- visiblement en français on laisse sans mettre en italique
    end
    -- liste d'exclusion de noms traités comme français
    local i = 1
    while (p.exclude_clades[i] ~= nil) do
        if (p.exclude_clades[i] == nom) then
            -- exception, en français, on laisse sans italiques
            return true
        end
        i = i + 1 
    end
    return false
end

-- si 'true' indique regne tout en italique
p.regnes = {
 ["test"]=false, ["algue"]=true, ["animal"]=false, ["archaea"]=true,
 ["bactérie"]=true, ["champignon"]=true, ["protiste"]=false, ["végétal"]=true, ["virus"]=true,
 ["neutre"]=true, ["eucaryote"]=false, ["procaryote"]=true
}
-- si true indique rang inférieur (ou égal) au genre
p.rangs = {
 ["clade"]=false, ["type"]=false, ["groupe"]=false, ["non-classé"]=false, ["sous-forme"]=true,
 ["forme"]=true, ["cultivar"]=true, ["variété"]=true, ["sous-espèce"]=true, ["hybride"]=true,
 ["espèce"]=true, ["sous-série"]=true, ["série"]=true, ["sous-section"]=false, ["section"]=false,
 ["sous-genre"]=true, ["genre"]=true, ["sous-tribu"]=false, ["tribu"]=false, ["super-tribu"]=false,
 ["infra-tribu"]=false, ["sous-famille"]=false, ["famille"]=false, ["épifamille"]=false, ["super-famille"]=false,
 ["micro-ordre"]=false, ["infra-ordre"]=false, ["sous-ordre"]=false, ["ordre"]=false, ["super-ordre"]=false,
 ["sous-cohorte"]=false, ["cohorte"]=false, ["super-cohorte"]=false, ["infra-classe"]=false, ["sous-classe"]=false,
 ["classe"]=false, ["super-classe"]=false, ["infra-embranchement"]=false, ["sous-embranchement"]=false, ["embranchement"]=false,
 ["super-embranchement"]=false, ["sous-division"]=false, ["division"]=false, ["super-division"]=false, ["infra-règne"]=false,
 ["rameau"]=false, ["sous-règne"]=false, ["règne"]=false, ["super-règne"]=false, ["sous-domaine"]=false,
 ["domaine"]=false, ["empire"]=false
}
-- retourne true si rang+regne a besoin de l'italique
function p.rang_regne_it(rang, regne)
    if (rang == nil or rang == "" or regne == nil or regne == "") then
        return nil
    end
    local reg = p.regnes[regne]
    if (reg == nil) then
        return nil
    end
    if (reg == true) then
        return true -- tout en italique
    end
    local rag = p.rangs[rang]
    if (rag == nil) then
        return nil
    end
    if (rag == true) then
        return true
    else
        return false
    end
end

-- met un nom scientifique en italique, en respectant les conventions.
-- cette fonction met en italique sans condition.
-- cette fonction présume que le nom passé est *uniquement* un nom scientifique (pas de partie homonyme)
-- la partie rang est utilisée pour détecter les "clades" en français
function p.italique_biologique(nom, rang, regne)
    if (nom == nil or nom == "") then
        return ""
    end
    
    -- si pas besoin de l'italique on laisse
    local it = p.rang_regne_it(rang, regne)
    if (it == nil or it == false) then
        return '<span style="font-style: normal">' .. nom .. '</span>'
    end
    
    -- si rang=clade et qu'on détecte que c'est du français on laisse sans modifier
    if (rang == "clade") then
        if (p.clade_francais(nom)) then
            return '<span style="font-style: normal">' .. nom .. '</span>'
        end
    end
    
    -- on remplace dans le nom toutes les occurrences à protéger
    local i = 1
    while(p.exclude[i] ~= nil) do
        nom = mw.ustring.gsub(nom, p.exclude[i][1], p.exclude[i][2])
        i = i + 1    
    end
    
    -- on retourne la partie traitée
    -- en insérant les italiques au début et à la fin
    -- attention : si on a traité un élément au tout début (ou fin) il faut le virer et ne
    -- pas remettre de '' au début (ou fin)
    local deb = "''"
    local fin = "''"
    if (mw.ustring.find(nom, "^''")) then
        nom = mw.ustring.sub(nom, 3) -- on supprime les 2 1er
        deb = "" -- pas au début
    end
    if (mw.ustring.find(nom, "''$")) then
        nom = mw.ustring.sub(nom, 1, -3) -- on supprime les 2 derniers
        fin = "" -- pas à la fin
    end
    
    return '<span lang="la">' .. deb .. nom .. fin .. '</span>'
end


-- traite un nom scientifique pour la mise en italique
function p.ns(frame)
    -- on récupère le rang (si cultivar, fonction dédiée)
    local rang = mw.ustring.lower(mw.text.trim(frame.args["rang"] or ""))
    -- on récupère le règne
    local regne = mw.ustring.lower(mw.text.trim(frame.args["règne"] or ""))
    -- juste un wrapper
    if (rang == "cultivar") then
        return ( p.italique_cultivar(p.trim(frame.args[1] or frame:getParent().args[1] or "")) )
    else
        return ( p.italique_biologique(p.trim(frame.args[1] or frame:getParent().args[1] or ""), rang, regne) )
    end
end


-- traite la mise en italiques d'un nom de cultivar. La forme est "XXXXX 'YYY'" (apostrophe simple ou typographique)
-- l'italique n'est que sur la première partie. Retourne nil si cette forme n'est pas détectée
function p.italique_cultivar(nom)
    if (nom == nil or nom == "" or type(nom) ~= "string") then
        return nil
    end

    -- on verifie que le nom se termine par ' ou ’
    local der = mw.ustring.sub(nom, -1)
    if (der ~= "'" and der ~= "’") then
        return nil -- pas bon
    end
    -- on cherche la partie YYY
    local pd1, pf1 = mw.ustring.find(nom, "['].*[']$")
    local pd2, pf2 = mw.ustring.find(nom, "[‘].*[’]$")
    if (pd1 == nil and pd2 == nil) then
        return nil -- pas trouvé
    end
    local debut = pd1 or pd2
    local fin = pf1 or pf2
    
    -- on récupère le début (à mettre en italiques)
    local part1 = mw.ustring.sub(nom, 1, debut-1)
    if (part1 == nil or part1 == "") then
        return nil
    end
    local itpart1 = p.italique_biologique(part1, "espèce", "animal")
    local reste = mw.ustring.sub(nom, debut)
    return itpart1 .. reste
end

-- traite un nom de cultivar pour la mise en italique
function p.nc(frame)
    -- juste un wrapper
    return ( p.italique_cultivar(p.trim(frame.args[1] or frame:getParent().args[1] or "")) )
end



-- applique la forme italique pour le titre de l'article (DISPLAYTITLE) à partir du
-- nom scientifique reçu en paramètre. Gère la partie homonymie. Détecte un NV
function p.titre(frame)
    local ttr
    local cat = ""

    -- le nom scientifique
    local ns = p.trim(frame.args[1] or frame:getParent().args[1] or "")
    if (ns == nil or ns == "") then
        -- pas de nom scientifique, on ne peut pas travailler
        return ""
    end
    
    -- on récupère règne et rang si présents
    local regne = frame.args["règne"] or frame:getParent().args["règne"]
    local rang = frame.args["rang"] or frame:getParent().args["rang"]
    regne = mw.text.trim(regne or "")
    rang = mw.text.trim(rang or "")

    -- test temporaire : si le nom scientifique contient de la mise en forme
    -- on range l'article dans une catégorie pour les détecter
    --- selon les combinaisons règne+rang on fait des choses différentes
    local a_tester = "[[{'†éèêëàâäùüûçîïôö]"
    if (regne == "virus") then
        a_tester = nil -- on trouve de tout dans les virus
    end
    if (rang == "clade") then
        a_tester = "[[{'†]" -- pour les clades les noms peuvent être en français
    end
    if (regne == "animal" and rang == "hybride") then
        a_tester = "[[{'†]" -- pour les hybrides animaux les noms peuvent être en français
    end
    if (rang == "cultivar") then
        a_tester = "[[{†]" -- les cultivars contiennent des ' ou ‘’
    end
    
    -- seulement si on a un test à faire
    if (a_tester ~= nil) then
        local tst = mw.ustring.find(ns, a_tester)
        if (tst) then
            cat = "{{Article de Biologie à corriger|clef=NS|"
                 .. "doc=Modèle:Taxobox taxon|message=Nom de taxon '"
                 .. mw.text.nowiki(ns) .. "' non reconnu}}"
        end
    end

    -- spécial : si paramètre "titre" → on utilise à la place
    local ft = frame.args["titre"] or frame:getParent().args["titre"]
    if (ft) then
        -- titre forcé : on l'utilise à la place du titre réel
        -- et on ne vérifie pas le namespace
        ttr = ft
    else
        -- le titre
        local titre = mw.title.getCurrentTitle()
        if (titre.namespace ~= 0) then
            -- seulement les articles !
            return ""
        end
        ttr = titre.text
    end
    
    if (ttr == ns) then
        -- titre exactement NS → direct
        if (ft) then
            if (rang == "cultivar") then
                return frame:preprocess("<nowiki>" .. cat .. "{{DISPLAYTITLE:" .. p.italique_cultivar(ns) .. "|noerror}}</nowiki>")
            else
                return frame:preprocess("<nowiki>" .. cat .. "{{DISPLAYTITLE:" .. p.italique_biologique(ns, rang, regne) .. "|noerror}}</nowiki>")
            end
        else
            if (rang == "cultivar") then
                return frame:preprocess(cat .. "{{DISPLAYTITLE:" .. p.italique_cultivar(ns) .. "|noerror}}")
            else
                return frame:preprocess(cat .. "{{DISPLAYTITLE:" .. p.italique_biologique(ns, rang, regne) .. "|noerror}}")
            end
        end
    end
    
    -- si le titre est plus court que le NS ça ne peut être NS+homonymie
    local lng = mw.ustring.len(ns)
    if ((mw.ustring.len(ttr) <= lng) and (cat ~= "")) then
        if (ft) then
            return frame:preprocess("<nowiki>" .. cat .. "</nowiki>")
        else
            return frame:preprocess(cat) -- on ne fait rien
        end
    end
    
    -- on récupère les 'lng' premiers caractères du titre : ça doit être égal au NS
    -- sinon ça veut dire que ce n'est pas NS+homonymie
    local p1 = mw.ustring.sub(ttr, 1, lng)
    if (p1 ~= ns) then
    	if (cat ~= "") then
        	return frame:preprocess(cat) -- on ne fait rien
    	else
    		return ""
		end
    end
    
    -- la partie homonymie seule
    local hom = mw.ustring.sub(ttr, lng+1)
    
    -- on valide que la partie homonymie contient des ()
    local tst = mw.ustring.find(ttr, "[(]")
    if ((tst == nil) and (cat ~= "")) then
        -- pas de parenthèse, ce n'est pas NS + homonymie
        return frame:preprocess(cat) -- on ne touche rien
    end
    
    -- on retourne la mise en forme du NS italique + la partie homonymie
    if (ft) then
        if (rang == "cultivar") then
            return frame:preprocess("<nowiki>" .. cat .. "{{DISPLAYTITLE:" .. p.italique_cultivar(ns) .. hom .. "|noerror}}</nowiki>")
        else
            return frame:preprocess("<nowiki>" .. cat .. "{{DISPLAYTITLE:" .. p.italique_biologique(ns, rang, regne) .. hom .. "|noerror}}</nowiki>")
        end
    else
        if (rang == "cultivar") then
            return frame:preprocess(cat .. "{{DISPLAYTITLE:" .. p.italique_cultivar(ns) .. hom .. "|noerror}}")
        else
            return frame:preprocess(cat .. "{{DISPLAYTITLE:" .. p.italique_biologique(ns, rang, regne) .. hom .. "|noerror}}")
        end
    end
end


-- met un nom scientifique en italique, en respectant les conventions. Utilisable uniquement :
--  - dans le modèle {{taxobox}} car il utilise une syntaxe HTML et non wiki pour tenir compte du style CSS associé
--  - sur des taxons qui sont à coup sur en italiques (inf. au genre) car ne sait pas quelles sont les conditions autour
--  - ne gère pas la partie homonymie (pas supposé se rencontrer dans les noms de taxon)
function p.italique_taxon(nom, rang)
    if (nom == nil or nom == "") then
        return ""
    end
    
    -- si c'est un clade et détecté français on enlève l'italique
    if (rang == "clade") then
        if (p.clade_francais(nom)) then
            return '<span style="font-style: normal">' .. nom .. '</span>'
        end
    end
    
    -- on remplace dans le nom toutes les occurrences à protéger
    local i = 1
    while(p.exclude[i] ~= nil) do
        nom = mw.ustring.gsub(nom, p.exclude_span[i][1], p.exclude_span[i][2])
        i = i + 1
    end
    
    return nom
end

-- wrapper
function p.nt(frame)
    local nom = mw.text.trim(frame.args[1] or frame:getParent().args[1] or "")
    if (nom == "") then
        return ""
    end
    local nom2 = mw.text.trim(frame.args[2] or frame:getParent().args[2] or "")
    local rang = mw.text.trim(frame.args[3] or frame:getParent().args[3] or "")
    
    local resu
    if (nom2 == "") then
        resu = p.italique_taxon(nom, rang)
    else
        resu = p.italique_taxon(nom2, rang)
    end
    
    if (nom == resu) then
        return " [[" .. resu .. "]]"
    else
        return frame:preprocess(" [[" .. nom .. "|" .. resu .. "]]")
    end
end



-- module
return p