Mòdul:Taxobox
La documentacion d'utilizacion d'aquel modul se pòt crear a Mòdul:Taxobox/ús
-- module principal (de test) pour générer des taxobox.
-- contient la fonction principale (et unique) "taxobox"
-- l'autre fonction (convertisseur) n'est pas fonctionnelle.
-- il reste des choses à faire, nettoyer…
local z = {}
-- les boîtes à outils
local data = require "Module:Taxobox-data"
local briques = require "Module:Taxobox-teules"
local tools = require "Module:Taxobox-aisinas"
-- preparation : table "globale" contenant les divers paramètres communs
-- contient aussi les tables et éléments pour les retours d'info des fonctions
z.configuration = {}
-- la "frame", nécessaire pour faire du preprocess si besoin
z.configuration.frame = nil -- fram
-- paramètres qui sont des données
z.configuration.regne = nil -- le règne
z.configuration.nv = nil -- le(s) nom(s) vernaculaire(s) si présent
-- informations sur l'article
z.configuration.titre_page = nil -- le titre réel de l'article
z.configuration.article = nil -- le namespace de la page (true=article, false=autre)
-- titre forcé : faire comme si c'était le titre de l'article (implique NS=0)
z.configuration.force_titre = nil
-- informations sur la taxobox (sa structure)
z.configuration.div_nb = 0 -- compte des ouvertures / fermertures de <div>
z.configuration.table_nb = 0 -- compte des ouvertures / fermetures de <table>
z.configuration.fermeture_taxobox = nil -- état de la taxobox (redondant avec div_nb ?)
-- informations calculées
z.configuration.titre_article = nil -- titre mis en forme de l'article (pour modification affichage)
z.configuration.titre_taxobox = nil -- titre de la taxobox (mis en forme) calculé d'après les infos
z.configuration.titre_ns = nil -- si true → article titré avec le (un) nom scientifique, sinon nom vernaculaire
z.configuration.regne_affiche = nil -- le nom wikifié correspondant au règne
z.configuration.regne_lien = nil -- le lien vers lequel pointe ce règne
z.configuration.sous_titre = "" -- le sostitre (éventuel) à insérer
-- zones de stockage d'information pour les retours
z.configuration.r_categories = {} -- stockage des catégories retournées par les fonctions
z.configuration.r_err_categories = {} -- stockage des catégories d'erreur retournées par les fonctions
z.configuration.r_erreurs = {} -- stockage des erreurs retournées par les fonctions
-- fonctions d'accès pour remplir les informations (cat, err-cat, err)
z.configuration.f_categories = nil -- fonction d'ajout d'une catégorie
z.configuration.f_err_categories = nil -- fonction d'ajout d'une catégorie d'erreur
z.configuration.f_erreurs = nil -- fonction d'ajout d'une erreur { type, message }
-- les éléments de contrôle de la sortie
z.configuration.c_titre = nil -- la gestion du titre (oui, non, auto)
z.configuration.c_sous_titre = nil -- la gestion du sostitre (oui, non, auto)
z.configuration.c_categories = nil -- la gestion des catégories (en ligne, boîte, non, auto)
z.configuration.c_err_categories = nil -- la gestion des catégories d'erreurs (en ligne, boîte, non, auto)
z.configuration.c_erreurs = nil -- la gestion des messages d'erreur (oui, non, auto)
-- les éléments réservés aux développeurs
z.configuration.c_raw = nil -- affichage "brut" de la taxobox
z.configuration.c_debug = nil -- mode debug. Ne fait rien actuellement
-- l'ensemble des paramètres non-nommés, sous forme de table de tables (1 par ligne)
local descriptions = {}
local nb_lignes -- nombre de lignes dans la description
-- variables d'état de la taxobox : contient les états en cours
local etat_precedent = "" -- ce qu'on a traité juste avant
local liste_taxons = {} -- liste des taxons trouvés
local nb_taxons -- nombre de lignes dans liste_taxons
local cible_taxon = nil -- si présent, l'utiliser plutôt que nb_taxons pour choix du titre
local nb_debut = 0 -- pour gérer les ouvertures / fermetures
local nb_cites = 0 -- pour gérer la proximité
local nb_uicn = 0 -- pour gérer la proximité
local pdebug = "" -- pour le mode debug
-- fonctions de manipulation des infos
function z.ajoute_r_categories(nom)
if (nom == nil) then
return
end
table.insert(z.configuration.r_categories, nom)
end
function z.ajoute_r_err_categories(nom)
if (nom == nil) then
return
end
table.insert(z.configuration.r_err_categories, nom)
end
function z.ajoute_r_erreurs(tp, desc)
if (tp ~= nil and tp ~= "" and desc ~= nil and desc ~= "") then
local ll = ""
if (type(z.configuration.ligne_courante) == "string") then
ll = z.configuration.ligne_courante
elseif (type(z.configuration.ligne_courante) == "table") then
ll = table.concat(z.configuration.ligne_courante, "|")
else
ll = "- pas d'information -"
end
table.insert(z.configuration.r_erreurs, {tp,desc .. "<br/>(" .. ll .. ")" })
end
end
-- initialisation des fonctions de traitement de catégorie
z.configuration.f_categories = z.ajoute_r_categories
z.configuration.f_err_categories = z.ajoute_r_err_categories
z.configuration.f_erreurs = z.ajoute_r_erreurs
-- cette fonction nettoie les blancs au début et à la fin du texte. Utile pour nettoyer
-- les paramètres reçus qui peuvent contenir des blancs selon la mise en forme à l'appel
function z.nettoie(nom)
-- histoire de ne pas générer d'erreur
if (nil == nom) then
return nil
end
local tmp = string.gsub (nom, "^[%s]*", "")
return string.gsub (tmp, "[%s]*$", "")
end
-- indique si un mot est dans une liste. Si oui retourne la position dans la liste
function z.est_dans_liste(mot, liste)
local i = 1
if (liste == nil) then
return 0
end
while (liste[i] ~= nil) do
if (liste[i] == mot) then
return i
end
i = i + 1
end
return 0
end
-- lecture d'une ligne de paramètres
-- desc est la description symbolique de ce qu'on attend
-- ligne est une table (de string) contenant la ligne découpée
-- depart est l'offset dans la table où commencer
-- Retourne une table où se trouvent fixées les valeurs trouvées
-- Format de la description :
-- {
-- ["noname"] = { "key1", "key2", ... },
-- ["flags"] = { { { "f1", "f1b", ... }, "key" }, { { "f2", "f2b", ... }, "key2" }, ... },
-- |"values"] = { { { "v1", "v1b", ... }, "key" }, { { "v2", "v2b", ... }, "key2" }, ... }
-- }
-- noname : paramètres sans nom sur la ligne. La fonction associe tout paramètre qui n'est ni un
-- flag ni un value à la liste de mots-clés. Dans la table retournée on aura tab["key1"] = "le premier champs non nommé",
-- tab["key2" = "le 2ème champs non nommé"... Ceux non présents valent nil. Si trop de paramètres non nommés sont présents
-- les derniers sont ignorés et une erreur est retournée (voir la gestion des erreurs plus bas)
-- flags : paramètres ayant un nom et qui ne sont gérés que par présent/absent. La fonction compare chaque paramètre à la liste
-- des mots-clés possibles pour chaque flag (f1, f1b pour le premier, f2, f2b…). Si l'un est présent la fonction fixe
-- tab["key"] = true (nil sinon)
-- si un flag est donné plus d'une fois cela génère une erreur
-- values : identique aux flags, mais la fonction cherche une valeur associée, qui est le paramètre suivant. Cette valeur
-- est passée par tab["key"] = "valeur lue".
-- Si une value n'a pas de valeur (dernier élément de la liste) ou est donnée plusieurs fois cela génère une erreur
-- Erreurs : si tab["erreurs"] est non nil / non vide c'est qu'une erreur s'est produite. tab["erreurs"] contient un message
-- expliquant l'erreur
-----
----- TODO : remplacer z.ajoute_erreur ici pour transmettre l'erreur à celui qui appelle.
-----
function z.lecture_parametres(ligne, depart, desc)
local i = depart
local buf = ""
local res = {}
local j
local tmpf
-- on parcours les entrées
while (ligne[i] ~= nil) do
v = z.nettoie(ligne[i])
--- on cherche si 'v' correspond à un élément des descriptions
j = 1
if (desc["flags"] == nil) then
tmpf = 0 -- pas de flags
else
while (desc["flags"][j] ~= nil) do
tmpf = z.est_dans_liste(v, desc["flags"][j][1])
if (tmpf > 0) then
break
end
j = j + 1
end
end
if (tmpf > 0) then
-- on a trouvé, c'est un flag
-- on vérifie qu'il n'est pas déjà donné
if (res[desc["flags"][j][2]] ~= nil) then
res["erreurs"] = "Element ''" .. ligne[i] .. "'' en exemplars multiples"
end
-- quoi qu'il en soit c'est le dernier qui gagne
res[desc["flags"][j][2]] = true
else
-- pas un flag, on regarde les "values"
j = 1
if (desc["values"] == nil) then
tmpf = 0
else
while (desc["values"][j] ~= nil) do
tmpf = z.est_dans_liste(v, desc["values"][j][1])
if (tmpf > 0) then
break
end
j = j + 1
end
end
if (tmpf > 0) then
-- on a trouvé, c'est un values
-- on vérifie qu'il y a un élément en plus
if (ligne[i+1] == nil) then
-- c'est une erreur
res.erreurs = "Valor ''" .. v .. "'' sens contengut (casa seguenta)."
else
-- on vérifie qu'il n'est pas déjà donné
if (res[desc["values"][j][2]] ~= nil) then
res.erreurs = "Element ''" .. ligne[j] .. "'' en exemplars multiples."
end
-- quoi qu'il en soit c'est le dernier qui gagne
res[desc["values"][j][2]] = z.nettoie(ligne[i+1])
-- on saute l'élément
i = i + 1
end
else
-- c'est un paramètre non nommé
-- on cherche le premier non nommé qui soit nil
j = 1
while (desc["noname"][j] ~= nil) do
if (res[desc["noname"][j]] == nil) then
break
end
j = j + 1
end
if (desc["noname"][j] == nil) then
-- donc il y a trop de paramètres -> erreur
res.erreurs = "Tròp de paramètres"
else
-- on fixe sa valeur
res[desc["noname"][j]] = v
end
end
end
-- entrée suivante
i = i + 1
end
return res
end
--- fonctions de traitement des lignes de description
-- wrapper effectuant la lecture des paramètres et traitant les erreurs
function z.traite_avec_erreur(ligne, syntaxe)
local params = z.lecture_parametres(ligne, 2, syntaxe)
if (params.erreurs ~= nil) then
return nil, "sintaxi", params.erreurs
end
return params, nil, nil
end
-- devrait disparaitre aussi : il faut revoir l'appel explicite dans la fonction principale
-- fin de la taxobox. Syntaxe :
-- fin
function z.traite_fin(ligne)
-- si la taxobox n'est pas ouverte
if (fermeture_taxobox == true) then
z.ajoute_r_erreurs("sintaxi", "Tampadura de taxobox sens que siá dobèrta.")
z.ajoute_r_err_categories("Taxobox amb error/sintaxi")
return ""
end
-- on indique que la taxobox est fermée
fermeture_taxobox = true
local tmp = tools.t_vraie_fin(z.configuration)
return tmp
end
-- prend une ligne en paramètre et appelle la bonne fonction, et gère les erreurs
function z.traite_ligne(ligne)
local prems
local res = ""
local courant
if (ligne == nil) then
z.ajoute_r_erreurs("interne (traite_ligne)", "La linha correnta val ''nil''.")
z.ajoute_r_err_categories("Taxobox amb error/intèrne")
return nil
end
prems = ligne[1]
if (prems == nil) then
z.ajoute_r_erreurs("interne (traite_ligne)", "Pas de primièr element dins la linha recebuda.")
z.ajoute_r_err_categories("Taxobox amb error/intèrne")
return nil
end
-- on récupère la ligne décrivant cet élément
local desc = tools.d_syntaxe[prems]
if (desc == nil) then
z.ajoute_r_erreurs("sintaxi", "Lo mot clau " .. prems .. " es desconegut.")
z.ajoute_r_err_categories("Taxobox amb error/sintaxi")
return nil
end
-- desc contient dans l'ordre le niveau de criticité de la ligne (1/2/3),
-- la description du format de la ligne, la fonction à appeler
-- on évalue la ligne
local vals, stl, msg = z.traite_avec_erreur(ligne, desc[2])
-- erreur de syntaxe ?
if (vals == nil) then
-- on retourne une erreur, fatale si demandé
z.ajoute_r_erreurs(stl, msg)
z.ajoute_r_err_categories("Taxobox amb error/" .. stl)
if (desc[1] == 2) then
return nil -- erreur fatale
else
return "" -- ligne ignorée
end
end
-- on appelle la fonction de traitement
courant = ligne[1] -- on note l'élément en cours de traitement
z.configuration.ligne_courante = ligne -- pour les erreurs
local reterr, tmp = pcall( desc[3], vals, z.configuration )
if (reterr ~= true) then -- erreur
if (desc[1] == 2) then
-- pas de gestion des messages d'erreur+cat : c'est fait dans les fonctions
return nil -- erreur fatale
else
-- pas de gestion des messages d'erreur+cat : c'est fait dans les fonctions
return "" -- ligne ignorée
end
end
-- si tmp == nil et qu'on est là c'est qu'on ignore la ligne :
if (tmp == nil) then
tmp = ""
end
--- ici on insert les tests de cohérence sur la structure des éléments
-- début doit être le premier. Il ne peut y en avoir qu'un
if (courant == "començament" and nb_debut > 0) then
z.ajoute_r_erreurs("estructura", "Mai de un ''començament'' donat.")
z.ajoute_r_err_categories("Taxobox amb error/estructura")
return nil -- c'est fatal
end
if (courant ~= "començament" and nb_debut == 0) then
z.ajoute_r_erreurs("estructura", "Element ''" .. courant .. "'' abans un ''començament''.")
z.ajoute_r_err_categories("Taxobox amb error/estructura")
return nil -- c'est fatal
end
if (courant == "començament") then
nb_debut = nb_debut + 1
end
-- si on sort d'un "rang" on doit fermer la table
if ( (etat_precedent == "reng" or etat_precedent == "conflicte") and (courant ~= "reng" and courant ~= "conflicte") ) then
res = res .. "</table>\n"
z.configuration.table_nb = z.configuration.table_nb - 1
end
-- si on rentre dans un "rang" il faut qu'on soit dans une table.
-- ici on accepte mais on génère une erreur
if ( (courant == "reng" or courant == "conflicte") and z.configuration.table_nb == 0) then
z.ajoute_r_erreurs("estructura", "Element ''" .. courant .. "'' en defòra d'una zòna de classificacion.")
z.ajoute_r_err_categories("Taxobox amb error/estructura")
-- on ouvre une table (pas propre) pour traiter
res = res .. "<table>"
end
-- rang/conflit : un rang ne peut apparaître que :
-- - après un autre rang (on est dans la classification)
-- - après "début" (sauf si phylo est indiqué)
-- - après "bandeau phylo" (non implémenté encore)
-- dans les autres cas : erreur, ignore ou corrige (<table[/]>) selon option
-- légende/reparticion légende : une légende ne peut que suivre une légende ou une image
-- taxon : les taxons devraient être donnés à la suite, pas séparés
if (courant == "taxon" and (etat_precedent ~= "taxon" and etat_precedent ~= "reng" and etat_precedent ~= "conflicte") ) then
z.ajoute_r_erreurs("estructura", "Element ''taxon'' a una posicion incorrècta.")
z.ajoute_r_err_categories("Taxobox amb error/estructura")
end -- mais ce n'est pas fatal
-- UICN / CITES : devraient être groupés s'il y en a plusieurs ?
if (courant == "cites") then
if (nb_cites > 0 and etat_precedent ~= "cites") then
z.ajoute_r_erreurs("estructura", "Element ''CITES'' multiples mas pas consecutius.")
z.ajoute_r_err_categories("Taxobox amb error/estructura")
end
nb_cites = nb_cites + 1
end
if (courant == "uicn") then
if (nb_uicn > 0 and etat_precedent ~= "uicn") then
z.ajoute_r_erreurs("estructura", "Element ''UICN'' multiples mas pas consecutius.")
z.ajoute_r_err_categories("Taxobox amb error/estructura")
end
nb_uicn = nb_uicn + 1
end
-- synonymes / taxons : devrait être au plus près du dernier taxon
-- ...
-- on ajoute l'élément
res = res .. tmp
-- bascule courant / précédent
if (courant ~= nil) then -- on ne touche pas si erreur car on n'a rien fait
etat_precedent = courant
end
-- on retourne le résultat
return res
end
-- cette fonction traite tous les paramètres non-nommés pour créer la table globale associée
-- retourne le nombre total
function z.traite_parametres(pframe)
local k, v
local ligne = {}
local pos = 1
local pd = 1
for k,v in pframe:argumentPairs() do
if (type(k) == "number") then
local temp = string.sub(v, -1)
local txt = z.nettoie(v)
if (pos == 1) then
-- le premier est passé en minuscules
if (txt ~= nil) then
ligne[pos] = string.lower(txt)
else
ligne[pos] = txt
end
else
ligne[pos] = txt
end
pos = pos + 1
if (temp == "\n") then
descriptions[pd] = ligne
pd = pd + 1
ligne = {}
pos = 1
end
end
end
return pd - 1
end
-- retourne vrai si le mot-clé "titre" ou "en titre" est présent
-- dans la table, sinon faux (ainsi qu'en cas d'erreur)
function z.presence_titre(lst)
if (lst == nil or type(lst) ~= "table") then
return false
end
local i = 1
while (lst[i] ~= nil) do
if (type(lst[i]) == "string") then
if (lst[i] == "títol" or lst[i] == "en títol") then
return true
end
end
i = i + 1
end
return false
end
-- cette fonction cherche toutes les occurrences de "taxon" pour déterminer s'il y en a et combien
-- génère la liste des taxons qui est une table { rang, nom } et retourne le nombre trouvé
-- ils sont classés dans l'ordre
-- si une ligne taxon est invalide elle est ignorée (ici)
-- si le mot-clé "titre" ou "en titre" est présent le 3ème champs est mis à vrai
function z.cherche_taxons()
local nb = 0
local pos = 1
-- tant qu'il y a des entrées
while (descriptions[pos] ~= nil) do
-- si c'est "taxon"
if (descriptions[pos][1] == "taxon") then
local rang = descriptions[pos][2]
local nom = descriptions[pos][3]
-- gestion des erreurs
if (rang ~= nil and nom ~= nil) then
-- présence de "titre" ?
local ttl = false
if (z.presence_titre(descriptions[pos])) then
ttl = true
cible_taxon = nb + 1
end
-- on l'ajoute
nb = nb + 1
liste_taxons[nb] = { rang, nom, ttl }
end
end
pos = pos + 1
end
return nb
end
-- utilise liste_taxons pour trouver les titres
function z.cherche_titres(frame)
local pos = 1
-- en premier lieu on cherche le taxon le plus "bas" pour le titre de la taxobox
local ligne
if (cible_taxon ~= nil) then
ligne = liste_taxons[cible_taxon]
if (ligne == nil) then
-- protection
ligne = liste_taxons[nb_taxons]
z.ajoute_r_erreurs("intèrne/cibla_taxon", "cibla_taxon=" .. cible_taxon .. " mentre que nb_taxons=" .. nb_taxons .. ", retorn a ''nil''.")
z.ajoute_r_err_categories("Taxobox amb error/intèrne")
end
else
ligne = liste_taxons[nb_taxons]
end
z.configuration.titre_taxobox = tools.formate_ns(z.configuration.regne, ligne[1], ligne[2], false, false)
-- on découpe le titre de l'article pour extraire la partie homonymie
local tmp = tools.decoupe_homonymie(z.configuration.titre_page)
-- on cherche dans la liste des taxons si l'un d'entre-eux correspond au nom (sans partie homonynie)
local trouve = 0
for i = 1, nb_taxons do
if (tmp[1] == liste_taxons[i][2]) then
trouve = i
-- si celui qui correspond au titre n'est pas le dernier on insert une erreur+cat
-- sauf si il est explicitement indiqué comme titre
if (i ~= nb_taxons) then
if (liste_taxons[i][3] == false) then
z.ajoute_r_erreurs("estructura/taxons", "Taxobox gigònha mas article pas titolat amb lo taxon lo mai bas")
z.ajoute_r_err_categories("Taxobox amb error/estructura")
end
end
break
end
end
-- si pas trouvé : probablement titré en nom vernaculaire
if (trouve == 0) then
-- on ne touche pas au titre
z.configuration.titre_article = nil
-- on met en sostitre la liste des taxons
for i = 1, nb_taxons do
-- on met en forme le nom scientifique
local ttr = tools.formate_ns(z.configuration.regne, liste_taxons[i][1], liste_taxons[i][2], false, false)
if (i < nb_taxons) then
z.configuration.sous_titre = z.configuration.sous_titre .. ttr .. ", "
else
z.configuration.sous_titre = z.configuration.sous_titre .. ttr
end
end
else
-- la mise en forme du titre
z.configuration.titre_article = tools.formate_ns(z.configuration.regne, liste_taxons[trouve][1], tmp[1], true, false)
if (tmp[2] ~= nil) then
z.configuration.titre_article = z.configuration.titre_article .. " " .. tmp[2]
end
-- puisque NS on ajoute les NV en sostitre si présents
if (z.configuration.nv == nil or z.configuration.nv == "") then
z.configuration.sous_titre = nil
else
z.configuration.sous_titre = z.configuration.nv
end
end
end
function z.essai(frame)
tools.t_test(nil, z.configuration)
if (z.configuration.r_erreurs ~= nil) then
return z.configuration.r_erreurs[1][1] .. " : " .. z.configuration.r_erreurs[1][2] .. "<br/>"
else
return "Pas cap de retorn.<br/>"
end
end
-- génère une box lisant les erreurs (selon le mode)
function z.box_erreurs(mode)
local tx = ""
local pos = 1
if (mode == "non" or z.configuration.r_erreurs == nil or z.configuration.r_erreurs[1] == nil) then
return "" -- rien (rien à faire ou mode "pas d'erreurs")
end
-- si mode auto et article → on ne fait rien non plus
if (mode == "auto" and z.configuration.article == true) then
return ""
end
-- donc là on affiche (soit mode="òc" soit mode="auto" + article)
tx = tx .. briques.t_debut("error", "Errors detectadas")
while (z.configuration.r_erreurs[pos] ~= nil) do
tx = tx .. "<small>" .. z.configuration.r_erreurs[pos][1] .." : " .. z.configuration.r_erreurs[pos][2] .. "</small>"
pos = pos + 1
end
tx = tx .. briques.t_end()
return tx
end
-- "pousse" la table de catégories selon le bon mode
function z.mef_categories(liste, mode, msg1, msg2)
local ret = ""
-- vide, ou bien mode = "non"
if (mode == "non" or liste == nil or liste[1] == nil) then
return ""
end
local t -- 1=inline, 2=box
if (mode == "en linha") then
t = 1
elseif (mode == "bóstia") then
t = 2
else -- si mode "auto" on regarde dans quel espace on est
if (z.configuration.article == true) then
t = 1 -- dans les articles mode inline
else
t = 2 -- sinon mode box
end
end
-- mode boite : entête
if (t == 2) then
ret = ret .. briques.t_debut(msg1, msg2)
end
local pos = 1
while (liste[pos] ~= nil) do -- on parcours
local p1 = nil -- catégorie
local p2 = nil -- clé éventuelle
if (type(liste[pos]) == "string") then
p1 = liste[pos]
p2 = nil
elseif (type(liste[pos]) == "table") then
p1 = liste[pos][1] or "Taxobox amb error/intèrne"
p2 = liste[pos][2]
else
p1 = "Taxobox amb error/intèrne"
p2 = nil
end
if (t == 1) then
if (p2 == nil) then
ret = ret .. "[[Categoria:" .. p1 .. "]]"
else
ret = ret .. "[[Categoria:" .. p1 .. "|" .. p2 .. "]]"
end
else
if (p2 == nil) then
ret = ret .. "[[:Categoria:" .. p1 .. "|" .. p1 .. "]]<br/>"
else
ret = ret .. "[[:Categoria:" .. p1 .. "|" .. p1 .. " (" .. p2 .. ")]]<br/>"
end
end
pos = pos + 1
end
-- mode boite : la fin
if (t == 2) then
ret = ret .. briques.t_end()
end
return ret
end
-- génère une box listant les catégories ou les incluant (selon le mode)
function z.box_categories()
local tx = ""
local pos = 1
-- categories "normales"
tx = tx .. z.mef_categories(z.configuration.r_categories, z.configuration.c_categories, "", "Categorias pas inclusas")
-- catégories d'erreur
tx = tx .. z.mef_categories(z.configuration.r_err_categories, z.configuration.c_err_categories, "error", "Categorias d'error pas inclusas")
return tx
end
-- fonction principale
function z.taxobox(frame)
local pframe = frame:getParent()
local args = pframe.args
local tx = ""
local tmp
-- on conserve la frame
z.configuration.frame = frame
-- on récupère le NAMESPACE tout de suite, pour que les briques erreur puissent catégoriser correctement
z.configuration.article = frame:preprocess("{{NAMESPACE}}") -- le namespace de la page
if (z.configuration.article == "") then
-- c'est un article
z.configuration.article = true
else
z.configuration.article = false
end
-- -- gestion des paramètres nommés (debug, options, éléments obligatoires)
-- - paramètres éditoriaux
-- on récupère le règne
z.configuration.regne = z.nettoie(args["règne"]) or nil
-- pas de règne, erreur tout de suite
if (z.configuration.regne == nil) then
return briques.t_erreur("Lo paramètre nomenat ''règne'' es obligatòri.", "règne", z.configuration)
end
-- on recupère les noms vernaculaires
z.configuration.nv = z.nettoie(args["nv"] or args["nom vernacular"] or args["noms vernaculars"]) or nil
-- - paramètres modifiant le comportement (note : passer ça en minuscules)
-- titre : oui, non, auto → contrôle la modification (éventuelle) du titre
z.configuration.c_titre = z.nettoie(args["títol"]) or nil
if (z.configuration.c_titre == nil) then
z.configuration.c_titre = data.defauts.titre -- mode par défaut
end
-- validation du paramètre
if (z.configuration.c_titre == "bóstia") then
z.configuration.c_titre = "bóstia"
end
if (z.configuration.c_titre ~= "òc" and z.configuration.c_titre ~= "non" and z.configuration.c_titre ~= "bòstia" and z.configuration.c_titre ~= "auto") then
return briques.t_erreur("Lo paramètre nomenat ''títol'' pòt pas prene que las valors ''òc'', ''non'' o ''auto''.", "títol", z.configuration)
end
-- sostitre : oui, non, auto → contrôle la modification (éventuelle) du sostitre
z.configuration.c_sous_titre = z.nettoie(args["sostítol"]) or nil
if (z.configuration.c_sous_titre == nil) then
z.configuration.c_sous_titre = data.defauts.sous_titre -- mode par défaut
end
-- validation du paramètre
if (z.configuration.c_sous_titre == "bóstia") then
z.configuration.c_sous_titre = "bóstia"
end
if (z.configuration.c_sous_titre ~= "òc" and z.configuration.c_sous_titre ~= "non" and z.configuration.c_sous_titre ~= "bóstia" and z.configuration.c_sous_titre ~= "auto") then
return briques.t_erreur("Lo paramètre nomenat ''sostítol'' pòt pas prene que las valors ''òc'', ''non'' o ''auto''.", "sostítol", z.configuration)
end
-- erreurs : oui, non, auto → contrôle l'insertion des messages d'erreur
z.configuration.c_erreurs = z.nettoie(args["errors"]) or nil
if (z.configuration.c_erreurs == nil) then
z.configuration.c_erreurs = data.defauts.erreurs -- mode par défaut
end
-- validation du paramètre
if (z.configuration.c_erreurs ~= "òc" and z.configuration.c_erreurs ~= "non" and z.configuration.c_erreurs ~= "auto") then
return briques.t_erreur("Lo paramètre nomenat ''errors'' pòt pas prene que las valors ''òc'', ''non'' o ''auto''.", "errors", z.configuration)
end
-- catégories : en ligne, boite, non, auto → contrôle l'insertion des catégories "normales"
z.configuration.c_categories = z.nettoie(args["categorias"] or args["categoria"] or args["categories"] or args["categorie"]) or nil
if (z.configuration.c_categories == nil) then
z.configuration.c_categories = data.defauts.categories -- mode par défaut
end
-- validation du paramètre
if (z.configuration.c_categories == "bóstia") then
z.configuration.c_categories = "bóstia"
end
if (z.configuration.c_categories ~= "en linha" and z.configuration.c_categories ~= "bóstia" and z.configuration.c_categories ~= "non" and z.configuration.c_categories ~= "auto") then
return briques.t_erreur("Lo paramètre nomenat ''categorias'' pòt pas prene que las valors ''en linha'', ''bóstia'', ''non'' o ''auto''.", "categorias", z.configuration)
end
-- catégories d'erreurs : en ligne, boite, non, auto → contrôle l'insertion des catégories d'erreurs
z.configuration.c_err_categories = z.nettoie(args["categorias errors"] or args["categoria errors"] or args["categories erreurs"] or args["categorie erreurs"]) or nil
if (z.configuration.c_err_categories == nil) then
z.configuration.c_err_categories = data.defauts.err_categories -- mode par défaut
end
-- validation du paramètre
if (z.configuration.c_err_categories == "bóstia") then
z.configuration.c_err_categories = "bóstia"
end
if (z.configuration.c_err_categories ~= "en linha" and z.configuration.c_err_categories ~= "bóstia" and z.configuration.c_err_categories ~= "non" and z.configuration.c_err_categories ~= "auto") then
return briques.t_erreur("Lo paramètre nomenat ''categorias errors'' pòt pas prene que las valors ''en linha'', ''bóstia'', ''non'' o ''auto''.", "categorias errors", z.configuration)
end
-- - paramètres de debug (réservés aux développeurs)
-- paramètre "raw" : sortie brute, non interprétée, du résultat (debug)
z.configuration.c_raw = z.nettoie(args["raw"]) or nil
if (z.configuration.c_raw == nil) then
z.configuration.c_raw = data.defauts.raw
end
if (z.configuration.c_raw == "òc") then
tx = "<nowiki>"
end
-- paramètre "debug" : ne fait presque rien actuellement
z.configuration.c_debug = z.nettoie(args["debug"]) or nil
if (z.configuration.c_debug == nil) then
z.configuration.c_debug = data.defauts.debug
end
-- paramètre "force titre" : fait comme si c'était un article dont le titre est indiqué
z.configuration.force_titre = z.nettoie(args["fòrça titol"]) or nil
-- on analyse le règne indiqué, pour validation/préparation
z.configuration.regne_affiche = data.premier_regne(z.configuration.regne) -- le nom wikif du règne
if ( nil == z.configuration.regne_affiche or "" == z.configuration.regne_affiche ) then
-- ce n'est pas un règne valide
return briques.t_erreur("Lo paramètre nomenat ''règne'' es pas valid (" .. z.configuration.regne .. ").", "règne", z.configuration) .. z.box_erreurs("òc") -- on force l'erreur
end
local tmp2 = data.est_rang("règne")
z.configuration.regne_lien = tmp2[2][1]
-- on récupère les informations externes sur l'article en cours
if (z.configuration.force_titre ~= nil) then
-- dans ce cas on utilise ce titre-là
z.configuration.titre_page = z.configuration.force_titre
else
z.configuration.titre_page = frame:preprocess("{{PAGENAME}}") -- titre de la page
end
-- on génère la table qui décrit la taxobox
nb_lignes = z.traite_parametres(pframe)
if (nb_lignes == nil or nb_lignes <= 0) then
-- une taxobox vide !
return briques.t_erreur("La taxobox es voida", "sintaxi", z.configuration) .. z.box_erreurs("òc") -- on force l'erreur
end
-- on extrait les taxons (nécessaire pour savoir de qui on parle)
nb_taxons = z.cherche_taxons()
if (nb_taxons <= 0) then
return briques.t_erreur("Pas cap d'entrada ''taxon'' de provesida", "sintaxi", z.configuration) .. z.box_erreurs("òc") -- on force l'erreur
end
-- on détermine les titres et autres
z.cherche_titres(frame)
-- on parcours les lignes de structuration pour générer la sortie
for i = 1, nb_lignes do
tmp = z.traite_ligne(descriptions[i])
if (tmp == nil) then
-- erreur qui ne peut être ignorée
return briques.t_erreur("Error de linha ''començament'' o ''filogenia bendèl", "sintaxi", z.configuration) .. z.box_erreurs("òc") -- on force l'erreur
end
tx = tx .. tmp
end
-- si la taxobox n'est pas fermée on la ferme
if (fermeture_taxobox == false) then
z.traite_fin() -- fermeture implicite, rendant donc "fin" optionnel
end
-- tout c'est passé correctement, on modifie le titre/sostitre
-- si présent, et si article, on traite le sostitre
if (z.configuration.sous_titre == nil) then
pdebug = pdebug .. "sostítol = <nil><br/>"
else
pdebug = pdebug .. "sostítol = " .. z.configuration.sous_titre .. "<br/>"
end
local boite_titres = ""
if (z.configuration.sous_titre ~= nil and z.configuration.sous_titre ~= "") then
-- on détermine si la gestion du sostitre est active
local t = false
local b = false
if (z.configuration.c_sous_titre == "non") then
t = false
elseif (z.configuration.c_sous_titre == "òc") then
t = true
else
if (z.configuration.article == true) then
t = true
else
t = false
b = true -- boîte
end
end
if (z.configuration.c_sous_titre == "bóstia" or b == true) then
boite_titres = boite_titres .. "Sostítol :<br/>" .. z.configuration.sous_titre .. "<br/>"
else
if (t == true) then
tx = tx .. briques.t_sous_titre(z.configuration.sous_titre)
end
end
else
if (z.configuration.c_sous_titre == "bóstia" or (z.configuration.c_sous_titre == "auto" and z.configuration.article == false)) then
boite_titres = boite_titres .. "Sostítol :<br/> ''pas cap''<br/>"
end
end
if (z.configuration.titre_article == nil) then
pdebug = pdebug .. "títol_article = <nil><br/>"
else
pdebug = pdebug .. "títol_article = " .. z.configuration.titre_article .. "<br/>"
end
-- si présent, et si article, on traite la modification du titre
if (z.configuration.titre_article ~= nil and z.configuration.titre_article ~= "") then
-- est-ce qu'on doit modifier ?
local t = false
local b = false
if (z.configuration.c_titre == "òc") then
t = true
elseif (z.configuration.c_titre == "non") then
t = false
else -- auto
if (z.configuration.article == true) then
t = true
else
t = false
b = true -- mode boîte si auto
end
end
if (z.configuration.c_titre == "bóstia" or b == true) then
boite_titres = boite_titres .. "Titol :<br/>" .. z.configuration.titre_article .. "<br/>"
else
if (t == true) then
local modif = "{{DISPLAYTITLE:" .. z.configuration.titre_article .. "}}"
tx = tx .. frame:preprocess(modif)
end
end
else
if (z.configuration.c_titre == "bóstia" or (z.configuration.c_titre == "auto" and z.configuration.article == false)) then
boite_titres = boite_titres .. "Titol :<br/> ''pas cap''<br/>"
end
end
-- on insert les catégories et les erreurs
tx = tx .. z.box_categories()
tx = tx .. z.box_erreurs(z.configuration.c_erreurs)
-- on insert la boîte des titres (à faire en fonction)
if (boite_titres ~= "") then
tx = tx .. briques.t_debut("", "Títol/sostítol")
tx = tx .. "<small>" .. boite_titres .. "</small>"
tx = tx .. briques.t_end()
end
-- spécial : le mode "raw" nécessite quelques ajustements
if (z.configuration.c_raw == "òc") then
tx = tx .. "</nowiki>"
return frame:preprocess(tx)
end
if (z.configuration.c_debug == "òc") then
return data.message .. tx .. pdebug -- cette partie seulement si demandée
else
return data.message .. tx
end
end
local sup = ""
-- recupère le contenu du modèle suivant complet
function z.extrait_modele(texte, depart)
local cnt = 0
local pos = depart
local npos
local debut = nil
local fin = nil
local t
if (depart > string.len(texte)) then
return nil, nil
end
debut = string.find(texte, "{{", pos, true)
if (debut == nil) then
return nil, nil
end
cnt = 1
while (true) do
local p1 = string.find(texte, "{{", pos+2, true)
local p2 = string.find(texte, "}}", pos+2, true)
if (p2 == nil) then
return nil, nil
end
if (p1 == nil) then
cnt = cnt - 1
npos = p2+2
if (cnt == 0) then
return debut, p2+1
end
elseif (p1 < p2) then
cnt = cnt + 1
npos = p1+2
else
cnt = cnt - 1
npos = p2+2
if (cnt == 0) then
return debut, p2+1
end
end
pos = npos
end
end
-- cherche le | suivant, en ignorant ceux dans des modèles ou wikiliens
-- retourne une position (utf8)
function z.pipe_suivant(ligne, posr)
local pos = posr
local cnt = 0
while (true) do
local c = mw.ustring.sub(ligne, pos, pos)
if (c == nil or c == "") then
if (pos <= posr) then
return nil
else
return pos
end
end
-- on comptabilise les entrées/sorties de modèle/lien
if (c == "[" or c == "{") then
cnt = cnt + 1
elseif (c == "]" or c == "}") then
cnt = cnt - 1
elseif (c == "|") then
-- si | on retourne la position que si cnt = 0
if (cnt == 0) then
return pos
end
end
pos = pos + 1
end
-- on ne vient pas là
return nil
end
-- découpe selon les | et range dans une table
function z.decoupe_pipe(ligne)
local tbl = {}
local pos
local courant = 1
pos = z.pipe_suivant(ligne, 1)
if (pos == nil) then
table.insert(tbl, ligne) -- un seul élément
return tbl
end
while (pos ~= nil) do
-- on recupere de "courant" à pos
local tmp = mw.ustring.sub(ligne, courant, pos-1)
table.insert(tbl, tmp)
courant = pos + 1
-- on recupere la partie suivante
pos = z.pipe_suivant(ligne, courant)
end
return tbl
end
-- cette fonction reçoit (non processé) une taxobox et retourne la même chose
-- avec la syntaxe actuelle
function z.convertisseur(frame)
local tx = "{{user:Hexasoft/Scribunto/Taxobox\n"
local txt = [=[
{{Taxobox début | algue | une_image.jpg | légende | classification=AlgaeBASE }}
{{Taxobox | sosrègne | Hacrobia }}
{{Taxobox | sosrègne | Hacrobia (truc) | Hacrobia}}
{{Taxobox | sosrègne | Hacrobia | ancien=oui }}
{{Taxobox taxon | algue | embrancament | Haptophyta | <autors>, <data> }}
{{Taxobox taxon | algue | embrancament | Haptophyta | <autors>, <data> }}
{{Taxobox taxon | algue | embrancament | Haptophyta | <autors>, <data> }}
{{Taxobox taxons |
* classa ''[[Pavlovophyceae]]''
** òrdre ''[[Pavlovales]]''
* classa ''[[Prymnesiophyceae]]'' Hibberd, 1976
** òrdre ''[[Prymnesiales]]''
** òrdre ''[[Phaeocystales]]''
** òrdre ''[[coccolithophore|Isochrysidales]]''
** òrdre ''[[coccolithophore|Coccolithales]]''
}}
{{taxobox synonymes |
* ''Turlu tutu'' <small>Chapeau Pointu</small> }}
{{Taxobox UICN | LC | 1Ab12-coulé | chez moi }}
{{Taxobox UICN | VU | 1Ab12-coulé | ailleurs }}
{{Taxobox position | {{Phylogénie Eukaryota}} | Cryptophyta }}
{{Taxobox fin}}
]=]
local ligne
local tbl = {}
debut, fin = z.extrait_modele(txt, 1)
if (debut == nil) then
return "''Sintaxi probablament erronèa.''<br/>" .. sup
end
while (debut ~= nil) do
-- on récupère la ligne
ligne = string.sub(txt, debut+2, fin-2)
-- on découpe selon les | présents
tbl = z.decoupe_pipe(ligne)
if (tbl[1] ~= nil) then
-- on analyse le premier
local tmp = z.nettoie(string.lower(tbl[1]))
if (tmp == "taxobox començament") then
-- le règne
regne = z.nettoie(tbl[2])
tx = tx .. "|règne=" .. regne .. "\n"
-- les autres parametres
tx = tx .. "|començament "
local i = 3
while (tbl[i] ~= nil) do
local rr = string.find(tbl[i], "=")
if (rr == nil) then
tx = tx .. "|" .. z.nettoie(tbl[i]) .. " "
else
-- on remplace le = par un |
tx = tx .. "|" .. z.nettoie(string.gsub(tbl[i], "=", "| ")) .. " "
end
i = i + 1
end
tx = tx .. "\n"
elseif (tmp == "taxobox filogenia bendèl") then
tx = tx .. "|filogenia bendèl "
local i = 2
while (tbl[i] ~= nil) do
local rr = string.find(tbl[i], "=")
if (rr == nil) then
tx = tx .. "|" .. z.nettoie(tbl[i]) .. " "
else
-- on remplace le = par un |
tx = tx .. "|" .. z.nettoie(string.gsub(tbl[i], "=", "| ")) .. " "
end
i = i + 1
end
tx = tx .. "\n"
elseif (tmp == "taxobox") then
tx = tx .. "|rang "
local i = 2
while (tbl[i] ~= nil) do
local rr = string.find(tbl[i], "=")
if (rr == nil) then
tx = tx .. "|" .. z.nettoie(tbl[i]) .. " "
else
local p1 = mw.ustring.match(tbl[i], "^%s*(%a*)%s*=")
if (p1 == "ancian") then
tx = tx .. "|ancian "
else
-- on remplace le = par un |
tx = tx .. "|" .. z.nettoie(string.gsub(tbl[i], "=", "| ")) .. " "
end
end
i = i + 1
end
tx = tx .. "\n"
elseif (tmp == "taxobox fin") then
tx = tx .. "|fin\n"
elseif (tmp == "taxobox taxon") then
tx = tx .. "|taxon "
local i = 3
while (tbl[i] ~= nil) do
local rr = string.find(tbl[i], "=")
if (rr == nil) then
tx = tx .. "|" .. z.nettoie(tbl[i]) .. " "
else
-- obsolète ou nouveau ?
local p1 = mw.ustring.match(tbl[i], "%s*(%a*)%s*=")
if (p1 == "obsolèt") then
tx = tx .. "| obsolèt "
else
-- on remplace le = par un |
tx = tx .. "|" .. z.nettoie(string.gsub(tbl[i], "=", "| ")) .. " "
end
end
i = i + 1
end
tx = tx .. "\n"
elseif (tmp == "taxobox imatge") then
tx = tx .. "|imatge "
local i = 2
while (tbl[i] ~= nil) do
local rr = string.find(tbl[i], "=")
if (rr == nil) then
tx = tx .. "|" .. z.nettoie(tbl[i]) .. " "
else
-- obsolète ou nouveau ?
local p1 = mw.ustring.match(tbl[i], "%s*(%a*)%s*=")
if (p1 == "separator") then
tx = tx .. "| separator "
else
-- on remplace le = par un |
tx = tx .. "|" .. z.nettoie(string.gsub(tbl[i], "=", "| ")) .. " "
end
end
i = i + 1
end
tx = tx .. "\n"
elseif (tmp == "taxobox conflicte") then
tx = tx .. "|conflicte "
local i = 2
while (tbl[i] ~= nil) do
local rr = string.find(tbl[i], "=")
if (rr == nil) then
tx = tx .. "|" .. z.nettoie(tbl[i]) .. " "
else
-- on remplace le = par un |
tx = tx .. "|" .. z.nettoie(string.gsub(tbl[i], "=", "| ")) .. " "
end
i = i + 1
end
tx = tx .. "\n"
elseif (tmp == "taxobox reparticion començament") then
tx = tx -- pas res a far perque inutile
elseif (tmp == "taxobox reparticion fin") then
tx = tx -- pas res a far perque inutile
elseif (tmp == "taxobox reparticion legenda") then
tx = tx .. "|reparticion legenda "
local i = 2
while (tbl[i] ~= nil) do
local rr = string.find(tbl[i], "=")
if (rr == nil) then
tx = tx .. "|" .. z.nettoie(tbl[i]) .. " "
else
-- on remplace le = par un |
tx = tx .. "|" .. z.nettoie(string.gsub(tbl[i], "=", "| ")) .. " "
end
i = i + 1
end
tx = tx .. "\n"
elseif (tmp == "taxobox uicn") then
tx = tx .. "|uicn "
local i = 2
while (tbl[i] ~= nil) do
tx = tx .. "|" .. z.nettoie(tbl[i]) .. " "
i = i + 1
end
tx = tx .. "\n"
elseif (tmp == "taxobox legenda") then
tx = tx .. "|legenda "
local i = 2
while (tbl[i] ~= nil) do
tx = tx .. "|" .. z.nettoie(tbl[i]) .. " "
i = i + 1
end
tx = tx .. "\n"
elseif (tmp == "taxobox parents") then
tx = tx .. "|parents "
local i = 2
while (tbl[i] ~= nil) do
tx = tx .. "|" .. z.nettoie(tbl[i]) .. " "
i = i + 1
end
tx = tx .. "\n"
elseif (tmp == "taxobox cites") then
tx = tx .. "|cites "
local i = 2
while (tbl[i] ~= nil) do
tx = tx .. "|" .. z.nettoie(tbl[i]) .. " "
i = i + 1
end
tx = tx .. "\n"
elseif (tmp == "taxobox taxons") then
tx = tx .. "|taxons "
if (tbl[2] ~= nil) then
tx = tx .. "|" .. tbl[2] .. " "
end
if (tbl[3] ~= nil) then
tx = tx .. "|" .. tbl[3] .. " "
end
tx = tx .. "\n"
elseif (tmp == "taxobox sinonims") then
tx = tx .. "|sinonims "
if (tbl[2] ~= nil) then
tx = tx .. "|" .. tbl[2] .. " "
end
tx = tx .. "\n"
elseif (tmp == "taxobox posicion") then
tx = tx .. "|posicion "
if (tbl[2] ~= nil) then
tx = tx .. "|" .. tbl[2] .. " "
end
if (tbl[3] ~= nil) then
tx = tx .. "|" .. tbl[3] .. " "
end
tx = tx .. "\n"
else
tx = tx .. "|Element desconegut (" .. tmp .. ")\n"
end
end
-- le suivant
cur = fin + 1
debut, fin = z.extrait_modele(txt, cur)
end
tx = tx .. "}}"
tx = "<pre>" .. txt .. "</pre>\n\n" .. "<pre>" .. tx .. "</pre>\n\n" .. tx .. "\n"
-- reste à faire : phylo arbre, phylo inexistant, reparticion, reparticion image
return frame:preprocess(tx)
end
-- cette fonction génère une erreur d'exécution
function z.fonction_en_erreur(frame)
local t = string.find(nil, nil)
end
function z.mw_title(frame)
res = ""
-- afficher le contenu de mw.title
for k, v in pairs( mw.title ) do
res = res .. "mw.title: " .. k .. " → " .. type(v) .. "<br/>\n"
end
return res
end
return z