Aller au contenu

Module:Noble

Cette page fait l’objet d’une mesure de semi-protection étendue.
Une page de Wikipédia, l'encyclopédie libre.

Documentation[voir] [modifier] [historique] [purger]

Utilisation

Fonctions exportables:

  • Noble(frame):implémente le modèle{{Noble}}.
  • Noble_(frame):implémente le modèle{{Noble-}};le modèle se termine par un tiret, la fonction se termine par un souligné.
  • labelInfobox(chaine):appelable directement pour mettre en forme un nom, ne lève aucune erreur.

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

Exemples

Pour des exemples, voir lapage de testpermettant de tester diverses modifications apportées.



localp={}
localRomains=require('Module:Chiffres romains')

--[[
Traitement d'une erreur.
Argument: message d'erreur en texte simple
Résultat: la fonction ne retourne pas à l'appelant, mais après le pcall()

Lorsqu'une erreur est détectée, par exemple un argument invalide dans
l'appel du modèle, cette fonction est appelée. Elle termine tous les appels
de fonction, jusqu'à atteindre un appel à la fonction pcall(), qui retourne
false et le message (s'il n'y avait pas eu d'erreur dans le traitement,
pcall retournait true et les valeurs retournées par la fonction qu'on lui
passe en premier argument).

Cette méthode a l'intérêt de rendre le code nettement plus lisible en ne
traînant pas partout des codes et des messages d'erreur, et accessoirement
de gagner un brin de performance.

Dans ce module, la fonction erreur() peut être appelée à peu près n'importe
quand. Voir les fonctions p.Noble() et p.Noble_() pour l'utilisation de
pcall().
]]
localfunctionerreur(msg)
ifstring.sub(msg,1,5)~='<span'then
-- Romains.conversion() inclut déjà le <span>
msg='<span class= "error" >'..msg..'</span>'
end
error(msg,0)
end

--[[
Génération d'un <span> enrobant un nombre romain.
Argument: chaîne avec des chiffres romains majuscules
Résultat: la même chaîne enrobée dans un <span> avec le bon style
]]
localfunctionhtml_romain(chaine)
return'<span class= "romain" style= "text-transform:uppercase" >'
..chaine
..'</span>'
end

--[[
Génération d'un <abbr> avec l'infobulle, le nombre romain et un exposant
éventuel.
Arguments: infobulle à afficher
nombre en chiffres romains majuscules uniquement
exposant peut être 'er', 're', '' (chaîne vide)
Résultat: les arguments enrobés dans un <abbr>
]]
localfunctionhtml_abbr(infobulle,nombre,exposant)
return'<abbr class= "abbr" title= "'..infobulle..' ">'
..html_romain(nombre)..exposant..'</abbr>'
end

--[[
Génération d'un nombre romain à afficher.
Argument: chaine, noerror
chaine: la chaîne avec uniquement les caractères "IVXLCDMer"
noerror: empeche l'affichage des erreurs
Résultat: le HTML pour afficher le nombre romain, ou
nil si la chaîne doit être ignorée
Notes:
- Si un argument valide comme 'Ier', 'Ire', 'XIV' est fourni, retourne le
HTML.
- Si un argument invalide comme 'Le' ou 'Veere' est fourni, retourne nil.
Dans ce case, l'analyseur doit essayer de trouver un nombre plus loin.
- Si un argument avec on nombre romain clairement invalide comme 'VV' est
fourni, une erreur est causée.
]]
localfunctionromain(chaine,noerror)
ifchaine=="Ier"thenreturnhtml_abbr('premier','I','<sup>er</sup>')end
ifchaine=="Ire"thenreturnhtml_abbr('première','I','<sup>re</sup>')end
ifstring.find(chaine,'e',1,true)thenreturnnilend
ifstring.find(chaine,'r',1,true)thenreturnnilend
localtest,msg,infobulle=Romains.conversion(chaine)
ifnottestthenifnoerrorthenreturnnilelseerreur(msg)endend
returnhtml_abbr(infobulle,chaine,'')
end

--[[
Formatage d'une chaîne. Une homonymie entre parenthèses est conservée.
Argument: chaine, noerror
chaine: chaîne à formater
noerror: empêche l'affichage des erreurs
Résultat: texte, complement
texte: nom et numéro formatés, par exemple Louis II, avec mise en
forme; vide si pas de numéro
complement: le complément de nom, par exemple de Bavière (1229-1294)

La recherche de patterns en unicode est relativement coûteuse, donc on essaie
de ne pas multiplier les recherches: on ratisse large et on trie après. Comme
il peut y avoir plusieurs nombres en chiffres romains dans la chaîne, on
utilise une boucle pour les trouver un par un et on accumule le texte formaté
au fur et à mesure.

La fonction utilise les variables suivantes:
sujet: la chaîne à formater, à laquelle on a ajouté une espace au début et
à la fin parce que mw.ustring.find() a besoin d'un caractère avant
et après les chiffres romains, pour détecter un nombre romain dans
un mot isolé, et ne pas détecter le D dans Désirée.
texte: accumule le texte analysé jusqu'ici; soit vide, soit se terminant par
un nombre romain formaté. Peut contenir plusieurs fois des nombres
romains.
index: index dans le sujet du premier caractère qui n'a pas encore été
copié dans la variable texte.
Exprimé en caractères, pas en bytes.
init: position où débuter la recherche de pattern. Souvent identique à
index, mais pourrait en différer. Par exemple avec le sujet "Louis
de Veere Ier "le pattern trouvera d'abord" Veere "mais
romain(capture) retournera nil, et donc texte restera inchangé
(vide), index aussi (2) mais init indiquera le premier caractère
après "Veere" (16).
Exprimé en caractères, pas en bytes.

Cette fonction est le coeur du module, à ne modifier qu'avec d'infinies
précautions!
]]
localfunctionformatage2(chaine,noerror)
localsujet=' '..chaine..' '-- la chaîne à formater
localtexte=''-- accumule le texte formaté
localindex=2-- premier caractère de sujet non copié dans texte
localinit=1-- position où démarrer la recherche de pattern
whiletruedo
localdebut,fin,capture
=mw.ustring.find(sujet,'%W([IVXLCDM]+[er]*)%W',init)
ifnotdebutthen-- plus aucun nombre romain
returntexte,mw.ustring.sub(sujet,index,-2)
end
capture=romain(capture,noerror)-- formate le nombre romain
ifcapturethen-- accumuler avec le nombre romain
texte=texte..mw.ustring.sub(sujet,index,debut)
ifstring.sub(texte,-1)==' 'then-- Louis XIV
texte=string.sub(texte,1,-2)..'&nbsp;'
elseifstring.sub(texte,-2)==' ('then-- Louis (XIV)
texte=string.sub(texte,1,-3)..'&nbsp;('
elseifstring.sub(texte,-2)==' ['then-- Louis [XIV]
texte=string.sub(texte,1,-3)..'&nbsp;['
end
texte=texte..capture
index=fin
init=fin--.. et chercher le suivant
else-- fausse alerte, par exemple 'Veere'
init=fin
end
end
end

--[[
Formatage d'une chaîne. Une homonymie entre parenthèses est ignorée.
Arguments: chaine, noerror
chaine: chaîne à formater
noerror: empêcher l'affichage des erreurs
Résultat: texte, complement
texte: nom et numéro formatés, par exemple Louis II, avec mise en
forme; vide si pas de numéro
complement: le complément de nom, par exemple de Bavière

Pour l'instant, l'homonymie est défini comme le texte à partir de la dernière
parenthèse ouvrante, pourvu que le dernier caractère de la chaîne soit une
parenthèse fermante. Une définition plutôt rudimentaire, qui devrait
probablement être affinée avec l'expérience.
]]
localfunctionformatage1(chaine,noerror)
ifstring.sub(chaine,-1,-1)~=")"then
returnformatage2(chaine,noerror)
end
localparen=0-- position de la dernière parenthèse ouvrante
localteste-- dernier index testé
repeat
teste=string.find(chaine,"(",paren+1,true)
iftestethenparen=testeend
untilteste==nil
ifparen==0thenreturnformatage2(chaine,noerror)
elsereturnformatage2(string.sub(chaine,1,paren-1),noerror)
end
end

--[[
Formatage du texte à afficher.
Arguments: arg1, arg2, arg3, noerror
arg1: premier argument reçu de l'appel du modèle
arg2: deuxième argument reçu de l'appel du modèle
arg3: troisième argument reçu de l'appel du modèle
noerror: empêche l'affichage des erreurs
Résultat: texte à afficher
]]
localfunctionaffichage(arg1,arg2,arg3,noerror)
localtexte,reste="",""
ifnotarg2orarg2=="*"then
-- second argument absent: on formate le premier argument
-- avec le complément
texte,reste=formatage1(arg1,noerror)
elseifarg2=="-"orarg2==""then
-- second argument "-": on formate le premier argument
-- sans le complément
texte=formatage1(arg1,noerror)
elseifarg2=="+"then
-- second argument "+": on formate le premier argument
-- avec le complément et l'homonyùie
texte,reste=formatage2(arg1,noerror)
else
-- second argument présent, avec ou sans un numéro
texte,reste=formatage2(arg2,noerror)
iftexte==""then
-- pas de numéro: on prend le nom et le numéro du premier argument
texte=formatage1(arg1,noerror)
end
end
-- Assemblage des éléments
texte=mw.text.trim(texte)
reste=mw.text.trim(reste)
ifreste==""then-- Louis II
-- Pas de reste, le texte est bon
elseiftexte==""then-- Charlemagne
-- Il n'y avait pas de chiffres romains,
-- il faut prendre le reste sans ajouter d'espace
texte=reste
else
localdebut=string.sub(reste,1,1)-- premier caractère du reste
ifdebut==')'or-- {{noble|Louis (II)}}
debut==']'or-- {{noble|Louis [II]}}
debut==','or-- {{noble|Louis II, le Jeune}}
debut=='.'-- {{noble|Karl I. der Große}}
then
-- Le reste commence par un caractère particulier,
-- il ne faut pas insérer d'espace avant le reste.
texte=texte..reste
else-- {{noble|Louis II le Jeune}}
-- Le reste ne commence pas par un caractère particulier,
-- il faut insérer une espace avant le reste, puisque des
-- espaces au début avaient été supprimées par trim().
texte=texte..""..reste
end
end
ifarg3then
-- troisième argument présent
localsuppl,reste=formatage2(arg3,noerror)
localdebut
debut=string.sub(suppl,1,1)-- premier caractère du supplément
ifdebut==')'or-- {{noble|Louis (II)}}
debut==']'or-- {{noble|Louis [II]}}
debut==','or-- {{noble|Louis II, le Jeune}}
debut=='.'-- {{noble|Karl I. der Große}}
then
-- Le supplément commence par un caractère particulier,
-- il ne faut pas insérer d'espace avant le supplément.
texte=texte..suppl
else-- {{noble|Louis II le Jeune}}
-- Le supplément ne commence pas par un caractère particulier,
-- il faut insérer une espace avant le supplément, puisque des
-- espaces au début avaient été supprimées par trim().
texte=texte..""..suppl
end
debut=string.sub(reste,1,1)-- premier caractère du reste
ifdebut==')'or-- {{noble|Louis (II)}}
debut==']'or-- {{noble|Louis [II]}}
debut==','or-- {{noble|Louis II, le Jeune}}
debut=='.'-- {{noble|Karl I. der Große}}
then
-- Le reste commence par un caractère particulier,
-- il ne faut pas insérer d'espace avant le reste.
texte=texte..reste
else-- {{noble|Louis II le Jeune}}
-- Le supplément ne commence pas par un caractère particulier,
-- il faut insérer une espace avant le reste, puisque des
-- espaces au début avaient été supprimées par trim().
texte=texte..""..reste
end
end
-- Correction du bug qui empêche la gestion correcte des insécables
-- dans un lien wiki
texte=mw.ustring.gsub(texte,'« ','«&nbsp;')
texte=mw.ustring.gsub(texte,' »','&nbsp;»')
returntexte
end

--[[
Nettoyage d'une chaîne.
Argument: valeur reçue de l'appel du modèle
Résultat: l'argument, avec les diverses espaces HTML remplacés par des
espaces normales

Ce code est utile, par exemple avec arg2 = "Louis&nbsp;XIV". Si on ne le
fait pas, les résultats ne seront pas les résultats attendus.
]]
localfunctionnettoyage(chaine)
iftype(chaine)~="string"thenreturnchaineend
returnchaine
-- nbsp
:gsub('\194\160',' ')
:gsub('&#160;',' ')
:gsub('&nbsp;',' ')
-- narrow nbsp
:gsub('\226\128\175',' ')
:gsub('&#8239;',' ')
-- thin space
:gsub('\226\128\137',' ')
:gsub('&#8201;',' ')
:gsub('&thinsp;',' ')
-- simple space
:gsub('&#32;',' ')
end

--[[
Validation du premier argument, qui doit être présent, non vide et différent
de "-".
Argument: valeur reçue de l'appel du modèle
Résultat: l'argument, éventuellement modifié
]]
localfunctionvalide1(valeur)
ifvaleur==nilthen
erreur("L'argument 1 est requis")
end
ifvaleur==""then
erreur("L'argument 1 ne peut pas être vide")
end
ifvaleur=="-"then
erreur("L'argument 1 ne peut pas être un simple tiret")
end
returnnettoyage(valeur)
end

--[[
Validation du deuxième argument, qui peut être présent, vide, ou "-".
Argument: valeur reçue de l'appel du modèle
Résultat: l'argument, éventuellement modifié
]]
localfunctionvalide2(valeur)
returnnettoyage(valeur)
end

--[[
Validation du troisième argument optionnel.
Argument: valeur reçue de l'appel du modèle
Résultat: l'argument, éventuellement modifié
]]
localfunctionvalide3(valeur)
returnnettoyage(valeur)
end

--[[
Traitement de l'appel.
Argument: frame reçu du modèle
Résultat: le texte à retourner au modèle, et
le premier argument (pour la construction du lien)
]]
localfunctiontraitement(frame)
localargs=frame:getParent().args
localarg1=valide1(args[1]);
localarg2=valide2(args[2]);
localarg3=valide3(args[3]);
localtexte=affichage(arg1,arg2,arg3);
returntexte,arg1
end

--[[
Formatage d'un nom dynastique, avec lien: modèle Noble.
Note: Le <span> est nécessaire pour supporter [{{Noble:Louis XIV}}] sans
obtenir des triple crochets dans l'affichage.
]]
functionp.Noble(frame)
localok,texte,arg1=pcall(traitement,frame)
ifokthenreturn'<span>[['..arg1..'|'..texte..']]</span>'
elsereturntexte
end
end

--[[
Formatage d'un nom dynastique, sans lien: modèle Noble-.
]]
functionp.Noble_(frame)
localok,texte=pcall(traitement,frame)
returntexte
end

functionp.labelInfobox(label)
returnaffichage(nettoyage(label),'+',nil,true)
end

returnp