Différences entre les pages « Module:Bandeau » et « Module:Outils »

De Les Mots de l'agronomie
(Différence entre les pages)
imported>Jacques Ducloy
m (1 révision importée)
 
imported>Jacques Ducloy
m (1 révision importée)
 
Ligne 1 : Ligne 1 :
--Ce module implémente les modèles de bandeau.
+
local Outils = { }
  
--Standardisation des bandeaux ([[Catégorie:Modèle de bandeau]]).
 
--Créer une fonction exportable pour le modèle {{Bandeau}} (ns:all).
 
--Créer une fonction exportable pour les bandeaux d'article (ns:0).
 
--Créer une fonction exportable pour les bandeaux de section (ns:0).
 
--Créer une fonction exportable pour les bandeaux d'ébauche (ns:0).
 
--Créer une fonction exportable pour les bandeaux de discussion (ns:1).
 
--Créer une fonction exportable pour les bandeaux système (ns:8).
 
--Gérer les images multiples.
 
  
local p = {}
+
--[[
 +
trim nettoie un paramètre non nommé (supprime les espaces et retours ligne au début et à la fin)
 +
retourne  nil si le texte est vide ou n'est pas du texte. Les nombres ne sont PAS considérés
 +
comme du texte.
 +
]]
 +
function Outils.trim( texte )
 +
if type( texte ) == 'string' and texte~= '' then
 +
texte = texte:gsub( '^%s*(%S?.-)%s*$', '%1' )
 +
if texte ~= '' then
 +
return texte
 +
end
 +
end
 +
return nil
 +
end
  
local trim = require('Module:Outils').trim
 
local yesno = require('Module:yesno')
 
local class = mw.loadData('Module:Bandeau/Class')
 
local moduleEbauche = 'Module:Bandeau/Ébauche'
 
-- local paramEbauche = mw.loadData(moduleEbauche) -- ne sera chargé que pour un bandeau d'ébauche.
 
  
local cfg = {
+
-- erreur génère un message d'erreur
forme = 'bandeau-simple',
+
function Outils.erreur( texte )
niveau = 'bandeau-niveau-neutre',
+
local message = Outils.trim( texte ) or "''erreur : raison non précisée''"
formatLien = '[[Fichier:%s|%spx|alt=%s]]',
+
return '<span class="error">' .. message .. "</span>"
tailleIcone = '45x45',
+
end
public = 'domaine public',
 
erreurArgument = 'Paramètre <code>|%s=</code> manquant',
 
erreurEbaucheParam = 'le thème « %s » du modèle [[Modèle:Ébauche|{{ébauche}}]] n’est pas [[Aide:Ébauche/Aide paramètres|défini]].',
 
erreurEbaucheType = 'le thème « %s » doit apparaître en tête de liste du modèle [[Modèle:Ébauche|{{ébauche}}]].',
 
ebaucheImage = '<span style="white-space:nowrap;word-spacing:5px">%s</span>',
 
ebaucheTitre = '%s est une [[Aide:Ébauche|ébauche]].',
 
ebaucheTitreSujet = '%s est une [[Aide:Ébauche|ébauche]] concernant %s.',
 
ebaucheCateg = '[[Catégorie:Wikipédia:ébauche %s]]',
 
}
 
  
local function erreur(texte, formatstring, tag)
 
local res = mw.html.create(tag or 'span')
 
res :addClass('error')
 
:wikitext('Erreur : ')
 
  
if formatstring then
+
--[[
res:wikitext(formatstring:format(texte))
+
validTextArg renvoit le premier paramètre chaine non vide
else
+
Paramètre :
res:wikitext(texte)
+
1 - tableau contenant tous paramètres
 +
2, ... - les noms des paramètres qui doivent êtres testés.
 +
]]
 +
function Outils.validTextArg( args, name, ... )
 +
local texte = Outils.trim( args[name] )
 +
if texte then
 +
return texte
 +
end
 +
if select( '#', ... ) > 0 then
 +
return Outils.validTextArg( args, ... )
 
end
 
end
 
+
return nil
return tostring(res)
 
 
end
 
end
  
function p._bandeau(args)
 
local res = mw.html.create('div')
 
local cells = mw.html.create()
 
local icone = trim(args.image) or trim(args['icône'])
 
local backgroundIcone = class.icones[icone] or ''
 
local texte = (trim(args.texte) or erreur('texte', cfg.erreurArgument))
 
  
res :attr{ id = args.id }
+
--[[
:addClass(class.formes[args.forme] or cfg.forme)
+
notEmpty renvoie le premier paramètre non vide ou nul.
:addClass(class.niveau[args.niveau] or cfg.niveau)
+
Paramètre :  
:addClass('plainlinks')
+
1, ... - les variables qui doivent êtres testés.
:addClass(args.class)
+
]]
:cssText(args.style)
+
function Outils.notEmpty( var, ... )
 +
local tvar = type( var )
 +
 +
if Outils.trim( var ) then
 +
return Outils.trim( var )
 +
elseif tvar == 'table' then
 +
local nextFunc = pairs( var )   -- n'utilise pas next car non défini par mw.loadData
 +
if nextFunc( var ) ~= nil then
 +
return var
 +
end
 +
elseif var == true or ( tvar == 'number' and var ~= 0 ) or tvar == 'function' then
 +
return var
 +
end
 
 
if yesno(args.centrer) then
+
if select( '#', ... ) > 0 then
cells = mw.html.create('div')
+
return Outils.notEmpty( ... )
:addClass('bandeau-centrer')
 
elseif trim(args.droite) then
 
cells = mw.html.create('div')
 
:css{ display = 'table', width = '100%' }
 
 
end
 
end
if icone and backgroundIcone == '' then
+
end
local iconeWiki = icone
+
 
if not icone:match('%[') then
+
 
local alt = args.alt or args['légende'] or ''
+
--[[
if alt:lower() == cfg.public then
+
extractArgs permet de récupérer les arguements du modèle,
alt = '|link='
+
ou la table transmise à la fonction par une autre fonction d'un module
 +
Paramètres :
 +
1 - un objet frame ou une table contenant les paramètre
 +
2, ...  - une liste de nom de paramètre pour déterminé si les paramètres sont transmis
 +
par #invoke. Le premier paramètre de frame sera systématiquement testé.
 +
]]
 +
function Outils.extractArgs ( frame, ... )
 +
if type( frame ) == 'table' then
 +
if type( frame.getParent ) == 'function' then
 +
if Outils.notEmpty( frame.args.invokeArgsOnly ) then
 +
return frame.args
 +
else
 +
local args = frame:getParent().args;
 +
for k,v in pairs( frame.args ) do
 +
args[k] = v;
 +
end
 +
return args
 
end
 
end
if yesno( args['domaine public'] ) then
+
else
alt = alt .. '|link='
+
return frame
end
 
local taille = args['taille icône'] or cfg.tailleIcone
 
iconeWiki = cfg.formatLien:format(icone, taille, alt)
 
 
end
 
end
cells
+
else
:tag('div')
+
return { frame, ... }
:addClass('bandeau-cell bandeau-icone')
 
:wikitext(iconeWiki)
 
:done()
 
elseif backgroundIcone ~= '' and args.forme == 'section' then
 
texte = '&ensp;' .. texte
 
 
end
 
end
cells
 
:tag('div')
 
:addClass('bandeau-cell ' .. backgroundIcone)
 
:wikitext(texte)
 
:newline()
 
:done()
 
if trim(args.droite) then
 
cells
 
:tag('div')
 
:addClass('bandeau-cell')
 
:css( 'padding-left', '1em' )
 
:newline()
 
:wikitext(args.droite)
 
:done()
 
end
 
 
res :node(cells)
 
if trim(args['supplément']) then
 
res :tag('p') 
 
:wikitext(args['supplément'])
 
:done()
 
end
 
return tostring(res)
 
 
end
 
end
  
function p._bandeauAvertissement(args)
 
local htmlTexte = mw.html.create()
 
  
htmlTexte
+
--[[
:tag('strong')
+
abr génère une abréviation (discrète par défaut)
:addClass('bandeau-titre')
+
paramètres :  
:wikitext(trim(args.titre) or erreur('titre', cfg.erreurArgument))
+
1 = abréviation,
:done()
+
2 = texte,
:wikitext(args.date)
+
3 = langue,
:newline():newline()
+
nbsp =  '-' pour une espace insécable avant l'abréviation, '+' pour l'avoir après.
:wikitext(args.texte)
+
visible = true pour une abréviation non discrète
 +
]]
 +
function Outils.abr( frame, ... )
 +
local args = Outils.extractArgs( frame, ... )
 +
if args[2] == nil then
 +
return args[1] or ''
 +
-- retoune l'abréviation ou au minimum une chaine vide s'il n'y a pas de texte
 +
end
  
local parametres = {
+
local wikiText = { '<abbr' }
forme = 'article',
+
if not args.visible then
niveau = args.niveau,
+
table.insert( wikiText, ' class="abbr"' )
id = args.id,
+
end
class = args.class,
+
table.insert( wikiText, ' title="' .. args[2] )
['icône'] = trim(args['icône']) or trim(args['icône-complexe']) or args.niveau,
+
if args[3] then
alt = args.alt or args['légende'],
+
table.insert( wikiText, '" lang="' .. args[3] )
['domaine public'] = args['domaine public'],
+
end
texte = tostring(htmlTexte),
+
table.insert( wikiText, '">' .. args[1] .. '</abbr>' )
['supplément'] = args['supplément'],
+
if args.nbsp == '-' then
}
+
table.insert( wikiText, 1, '&nbsp;' )
 +
elseif args.nbsp == '+' then
 +
table.insert( wikiText, '&nbsp;' )
 +
end
  
return p._bandeau(parametres)
+
return table.concat( wikiText )
 
end
 
end
  
function p._bandeauSection(args)
 
local res = mw.html.create('div')
 
local icone = trim(args.image) or trim(args['icône'])
 
local backgroundIcone = class.icones[icone] or ''
 
local texte = '&ensp;' .. (trim(args.texte) or erreur('texte', cfg.erreurArgument))
 
  
res :addClass('bandeau-section')
+
function Outils.nobr( texte )
:addClass(class.niveau[args.niveau] or cfg.niveau)
+
if type( texte ) == 'number' or Outils.trim( texte) then  
+
return '<span class="nowrap">' .. texte .. '</span>'
if icone and backgroundIcone == '' then
+
else
local iconeWiki = icone
+
return ''
if not icone:match('%[') then
 
local alt = args.alt or args['légende'] or ''
 
if alt:lower() == cfg.public then
 
alt = '|link='
 
end
 
iconeWiki = cfg.formatLien:format(icone, 'text-top|20x17', alt)
 
end
 
res :wikitext(iconeWiki)
 
:done()
 
 
end
 
end
res :addClass(backgroundIcone)
+
end
:wikitext(texte)
 
:done()
 
  
return tostring(res)
 
end
 
  
-- fonction qui inverse la casse du premier caractère d'une chaine
+
--[=[
local function inverserCasse( str )
+
texteLien trouve le premier lien interwiki '[[lien|texte]]' de str et retourne : texte, lien
 +
Si le lien est '[[texte]]', retourne : texte, texte.
 +
Si str ne contient pas de lien interwiki, retourne : str (et nil)
 +
Les fichiers et images ne sont pas considérés comme des liens.
 +
Si str n'est pas une chaine, retourne : nil
 +
]=]
 +
function Outils.texteLien( str )
 
if type( str ) == 'string' then
 
if type( str ) == 'string' then
local premierCar = mw.ustring.sub( str, 1, 1 )
+
for lien, texte in string.gmatch( str, '%[%[ *([^%[%]|]*)|? *([^%[%]]*)%]%]' ) do
if mw.ustring.lower( premierCar ) == premierCar then
+
texte = ( texte ~= '' and texte ) or lien or str
return mw.ustring.upper( premierCar ) .. mw.ustring.sub( str, 2 )
+
if not lien then
else
+
return str
return mw.ustring.lower( premierCar ) .. mw.ustring.sub( str, 2 )
 
end
 
end
 
end
 
 
 
-- fonction qui récupètre la ou les tables d'ébauche correspondant au thème
 
local function getEbaucheTable( paramEbauche, theme, feminin )
 
-- suprime les marques de direction ltr
 
theme = theme:gsub( '\226\128\142', '' ):gsub( '_', ' ' )
 
-- récupére les paramètres lié au theme, à partir du module:Bandeau/Ébauche
 
local params = {}
 
local ebauche = paramEbauche[ theme ] or paramEbauche[ inverserCasse( theme ) ]
 
if not ebauche and theme:find( ' ' ) then
 
-- teste si l'un des mots du thème correspond à un adjectif existant
 
for adj in theme:gmatch( ' ([^ ]+)' ) do
 
paramsAdj = getEbaucheTable( paramEbauche, adj, feminin )
 
if paramsAdj and paramsAdj.adjectif == true then
 
local nom = theme:gsub( ' ' .. adj:gsub( '(%p)', '%%%1'), '' )
 
params = getEbaucheTable( paramEbauche, nom, feminin )
 
if params then
 
return params, paramsAdj
 
end
 
 
end
 
end
end
+
local testlien = string.lower( lien )
-- aucun mot ne correspond à un adjectif, on essait une autre methode pour trouver une correspondance avec plusieurs mots
+
local fichier = string.match( testlien, '^fichier:' )  
if theme:find( ' .+ ' ) then
+
or  string.match( testlien, '^image:' )
for adj, paramsAdj in pairs( paramEbauche ) do
+
or  string.match( testlien, '^file:' )
if paramsAdj.adjectif == true and theme:find( ' ' .. adj, 2, true ) then
+
if not fichier then  
local nom = theme:gsub( ' ' .. adj:gsub( '(%p)', '%%%1'), '' )
+
return texte, lien
params = getEbaucheTable( paramEbauche, nom, feminin )
 
if params then
 
return params, paramsAdj
 
end
 
end
 
 
end
 
end
 
end
 
end
 +
return str
 
end
 
end
if feminin and ebauche and ebauche.feminin then  
+
end
ebauche = paramEbauche[ ebauche.feminin ]
+
 
 +
--[=[
 +
texteLien trouve la première lien externe '[adresse texte]' de str et retourne : texte, adresse
 +
Une adresse doit commencer par 'http://'
 +
Si le lien est '[adresse]', retourne : '', adresse.
 +
Si str ne contient pas de lien externe, retourne : str (et nil)
 +
Si adresse ou texte contenienne le caratère '[', retourne l'adresse suivante ou str
 +
Si str n'est pas une chaine, retourne : nil
 +
]=]
 +
function Outils.texteAdresse( str )
 +
if type( str ) == 'string' then
 +
local lien, texte = string.match( str, '%[(https?://[^%[%] ]*) *([^%[%]]-)%]' )
 +
 +
texte = texte or str
 +
return texte, lien
 
end
 
end
if ebauche then
+
end
for n, v in pairs( ebauche ) do
+
 
params[ n ] = v
+
 
end
+
--[[
 +
ordinal renvoie une chaine correspondant à l'abréviation de l'adjectif ordinal du nombre.
 +
Paramètres :
 +
1 = nombre (string ou number)
 +
2 = true pour avoir première au lieu de premier su nombre = 1
 +
--]]
 +
function Outils.ordinal( nombre, feminin )
 +
local num = tonumber( nombre )
 +
if num == nil then
 +
return Outils.trim( tostring( nombre ) ) or ''
 
else
 
else
params = nil
+
local nom = Outils.nombre2texte_reel( nombre, nil, 'ordinal', 'réformée', feminin and 'féminin' )
 +
return Outils.abr{ num .. '<sup>e</sup>', nom }
 
end
 
end
return params, nil
 
 
end
 
end
p.getEbaucheTable = getEbaucheTable
 
  
local function femininFromWikidata()
+
 
local entity = mw.wikibase.getEntity()
+
--[[
if entity then
+
  Fonction de traitement d'une "tranche" de nombres entre 0 et 999.
local p31 = entity:getBestStatements( 'P31' )
+
  Retourne la forme texturelle (5 → cinq, 46 → quarante six, 432 → quatre cent trente deux…)
local estHumain = type( p31 ) == 'table'
+
  Les paramètres sont les chiffres, du plus grand au plus petit (centaine, dizaine, unité).
and #p31 == 1
+
  La valeur nil signifie "0" (pour n'importe lequel des paramètres)
and type( p31[ 1 ].mainsnak ) == 'table'
+
  La fonction retourne le texte ou 'nil' si la valeur est zéro (pour gérer les 0 millier…)
and type( p31[ 1 ].mainsnak.datavalue ) == 'table'
+
  Le paramètre 'langue' indique la variante de langue (fr, be, ch ou ch2).
and type( p31[ 1 ].mainsnak.datavalue.value ) == 'table'
+
  Data est la table des données (issue de loadData())
and p31[ 1 ].mainsnak.datavalue.value['numeric-id'] == 5
+
--]]
local p21 = entity:getBestStatements( 'P21' )
+
function Outils.traite_tranche(_c1, _c2, _c3, langue, Data)
local estFeminin = type( p21 ) == 'table'
+
    local c1, c2, c3
and #p21 == 1
+
if (_c1 == nil) then c1 = 0 else c1 = tonumber(_c1) or 0 end
and type( p21[ 1 ].mainsnak ) == 'table'
+
if (_c2 == nil) then c2 = 0 else c2 = tonumber(_c2) or 0 end
and type( p21[ 1 ].mainsnak.datavalue ) == 'table'
+
if (_c3 == nil) then c3 = 0 else c3 = tonumber(_c3) or 0 end
and type( p21[ 1 ].mainsnak.datavalue.value ) == 'table'
+
 
and p21[ 1 ].mainsnak.datavalue.value['numeric-id'] == 6581072
+
if (c1 == 0 and c2 == 0 and c3 == 0) then
return estHumain, estFeminin
+
return nil -- sil signifie "zéro" (mais à traiter spécialement quand entouré)
 
end
 
end
return false, false
+
local resu = ""
end
 
 
 
p['_ébauche'] = function ( args )
 
local paramEbauche = mw.loadData( moduleEbauche )
 
local page = mw.title.getCurrentTitle()
 
local ebauches, gestionErreur = {}, {}
 
local humain, feminin = femininFromWikidata()
 
feminin = yesno( args["féminin"], true ) or feminin
 
local estFeminin
 
 
 
-- fonction qui retourne la valeur de param pour l'ébauche i, ou une valeur par défaut
+
-- on calcule la valeur restante (sans les centaines)
local ebaucheParam = function( i, param )
+
local val = 10*c2 + c3
return ebauches[ i ] and ebauches[ i ][ param ] or paramEbauche[''][ param ]
+
-- présence d'une centaine ?
end
+
if (c1 ~= 0) then
 
+
if (c1 == 1) then
-- récupération des paramètres de tous les thèmes
+
resu = "cent " -- séparateur
for i, theme in ipairs( args ) do
+
else
theme = trim( theme )
+
-- plusieurs centaines : on ajoute l'unité
if theme then
+
resu = Data.infcent[c1] .. " cent"
local t, tAdj = getEbaucheTable( paramEbauche, theme, feminin )
+
-- si pas d'unité 100 prend un 's'
if t then
+
if (val == 0) then
table.insert( ebauches, t )
+
resu = resu .. "s "
table.insert( ebauches, tAdj )
 
 
else
 
else
table.insert(
+
resu = resu .. " "
gestionErreur,
 
erreur( theme, cfg.erreurEbaucheParam, 'div' )
 
)
 
 
end
 
end
 
end
 
end
 
end
 
end
+
-- reste = 0 ?
-- récupération des différents titres, images et catégories
+
if (val == 0) then
local images, titres, categs = {}, {}, {}
+
-- on retourne directement la centaine
local tailleIcone = '45x35'
+
return resu
if #ebauches > 3 then
+
end
tailleIcone = '35x25'
+
-- c'est forcément un nombre pré-défini
 +
local vvv
 +
if (langue == "fr") then
 +
vvv = Data.infcent[val]
 +
elseif (langue == "be") then
 +
vvv = Data.infcent_be[val] or Data.infcent[val]
 +
elseif (langue == "ch") then
 +
vvv = Data.infcent_ch[val] or Data.infcent_be[val] or Data.infcent[val]
 +
else
 +
vvv = Data.infcent_ch2[val] or Data.infcent_be[val] or Data.infcent[val]
 
end
 
end
for i, ebauche in ipairs( ebauches ) do
+
return resu .. vvv .. " "
-- création du lien de l'image
+
-- note : cette fonction retourne *toujours* un " " à la fin du terme
local alt = ebauche.altIcone
+
end
if not alt then
+
 
if ebauche.sujet then
+
--[[
alt = 'image illustrant ' .. ebauche.sujet
+
  Fonction principale
else
+
  Reçoit en paramètre (premier non nommé) le nombre à traiter.
alt = ''
+
  Retourne la forme textuelle de ce nombre.
end
+
--]]
end
+
function Outils.nombre2texte_reel(pnombre, plangue, ptype, porthographe, pgenre, pmajuscule, pordinal)
if ebauche.icone then
+
-- le nombre à convertir (vient toujours du modèle)
local image = cfg.formatLien:format( ebauche.icone, tailleIcone, alt )
+
local valeur = pnombre
table.insert( images, image )
+
if (valeur == nil) then
end
+
return Outils.erreur("Il faut un paramètre non nommé numérique.")
if math.fmod( #ebauches, 3 ) == 1 and ( #ebauches - i ) == 2
+
elseif type(valeur) == "sting" then
or math.fmod( i, 3 ) == 0 and ( #ebauches - i ) > 1
 
then
 
-- sur plusieurs lignes s'il y a plus de 3 images, avec minimum deux images sur la dernière ligne
 
table.insert( images, '<br> ' )
 
end
 
 
if i > 1 and ebauche.type and ebauche.type ~= paramEbauche[''].type then
 
-- remplace "Cet article par "Ce portail" ou autre en fonction du premier thème
 
table.insert(
 
gestionErreur,
 
erreur( ebauche.nom, cfg.erreurEbaucheType, 'div' )
 
)
 
end
 
 
 
-- récupères les différents noms de thème
+
-- s'il y a une virgule, on l'ignore
if ebauche.adjectif and #titres > 0 then
+
local bla = mw.ustring.find(valeur, "[.,]")
local sujet = ebauche.sujet or ebauche.nom
+
if (bla ~= nil) then
if estFeminin then
+
-- extraction de la partie avant la virgule
sujet = ebauche.sujetF or sujet:gsub(
+
valeur = mw.ustring.match(mw.text.trim(valeur), "^[-]?[0-9]*")
ebauche.nom:gsub( '(%p)', '%%%1') .. '%f[%W]',
 
ebauche.feminin
 
)
 
end
 
-- ajout du sujet de l'adjectif dans le sujet de l'ébauche précédente
 
local titre, subst = titres[ #titres ]:gsub(  
 
'<(adj[^>]*)>',  
 
{ adjectif = sujet, adj = ebauche.nom, adjF = ebauche.feminin }
 
)
 
if subst > 0 then
 
titres[ #titres ] = titre
 
else
 
titres[ #titres ] = titre .. ' ' .. sujet
 
end
 
else
 
table.insert( titres, ebauche.sujet )
 
estFeminin = ebauche.estFeminin or ( ebauche.sujet == '' and estFeminin )
 
 
end
 
end
+
elseif type(valeur) == "number" then
-- mise en forme des catégories
+
valeur = math.floor(valeur)
if ebauche.adjectif then
 
-- tentative d'ajout du nom de l'adjectif dans les catégories précédentes
 
local modif = false
 
for k, v in ipairs( categs ) do
 
local cat, subst = v:gsub(
 
'<(adj[^>]*)>',
 
{ adj = ebauche.nom, adjF = ebauche.feminin,  adjectif = ebauche.nom }
 
)
 
if subst == 0 then
 
cat = v .. ' ' .. ebauche.nom
 
end
 
if mw.title.new( 'Catégorie:Wikipédia:ébauche ' .. cat ).exists then
 
categs[ k ] = cat
 
modif = true
 
end
 
end
 
if not modif
 
and humain
 
and mw.title.new( 'Catégorie:Wikipédia:ébauche personnalité ' .. ebauche.feminin ).exists
 
then
 
table.insert( categs, 'personnalité ' .. ebauche.feminin )
 
end
 
end
 
table.insert( categs, ebauche.categ )
 
table.insert( categs, ebauche.categ2 )
 
 
end
 
end
 
 
-- mise en forme des images
+
local nvaleur = tonumber(valeur)
local image
+
if (type(nvaleur) ~= "number") then
if trim( args['icône'] ) then
+
return Outils.erreur("Le paramètre doit être un nombre.")
local theme = getEbaucheTable( paramEbauche, args['icône'] )
+
end
if theme and theme.icone then
+
-- limites
image = cfg.formatLien:format(
+
if (nvaleur < -999999999999 or nvaleur > 999999999999) then
theme.icone,
+
return Outils.erreur("Nombre trop grand ou trop petit.")
tailleIcone,
+
end
theme.altIcone or ( 'image illustrant ' .. theme.sujet )
+
-- note : ici il faudrait s'assurer que le nombre est un entier !
)
+
 
end
+
-- on extrait le moins si présent
elseif #images == 1 then
+
local signe = false
image = images[ 1 ]
+
if (nvaleur < 0) then
elseif #images > 1 then
+
nvaleur = -nvaleur
image = cfg.ebaucheImage:format( table.concat( images, ' ' ) )
+
signe = true
 
end
 
end
+
 
-- mise en forme du titre
+
-- option : choix de la langue
local titre
+
local langue = plangue
if #titres > 0 then
+
if (langue == nil) then
titre = cfg.ebaucheTitreSujet:format(
+
langue = "fr"
ebaucheParam( 1, 'type' ),
 
mw.text.listToText( titres )
 
)
 
 
else
 
else
titre = cfg.ebaucheTitre:format( ebaucheParam( 1, 'type' ) )
+
langue = mw.text.trim(langue)
 
end
 
end
+
-- validation des valeurs permises
-- mise en forme du texte
+
if (langue ~= "fr" and langue ~= "be" and langue ~= "ch" and langue ~= "ch2") then
local texte
+
return Outils.erreur("Paramètre langue non reconnu (fr, be, ch ou ch2).")
if #ebauches == 0 then
+
end
texte = ( ebaucheParam( 1, 'message' ) ) .. '.'
+
 
else
+
-- type de résultat : seule valeur autorisée : 'ordinal'
local message = ebaucheParam( 1, 'message' )
+
local style = ptype
local selon = ebaucheParam( 1, 'selon' )
+
if (style ~= nil and style ~= "ordinal") then
-- ajout d'un point si le paramètre selon commence par un retour ligne ou une majuscule
+
style = nil
if message:sub( -1 ) == ')' and ( selon:sub( 1, 3 ) == '<br' or mw.ustring.match( selon, '^%u' ) ) then
 
texte = ( ebaucheParam( 1, 'message' ) ) .. '. ' .. ( ebaucheParam( 1, 'selon' ) ) .. '.'
 
else
 
texte = ( ebaucheParam( 1, 'message' ) ) .. ' ' .. ( ebaucheParam( 1, 'selon' ) ) .. '.'
 
end
 
 
end
 
end
-- ajout d'un texte s'il y a une liste de tâches
+
 
local todo = mw.title.makeTitle( mw.site.namespaces[ page.namespace ].talk.id, page.text .. '/À faire' )
+
-- type d'orthographe
if todo.exists then
+
local ortho = porthographe
texte = texte .. '\n\n'
+
if (ortho ~= nil and ortho ~= "réformée") then
.. 'Consultez la liste des <b>tâches à accomplir</b> en [['
+
ortho = nil
.. page.talkPageTitle.prefixedText
 
.. '|page de discussion]].'
 
 
end
 
end
 
 
-- paramètres pour le bandeau
+
-- genre : uniquement pour l'ordinal "premier / première"
local parametres = {
+
local genre = pgenre
niveau = 'ébauche',
+
if (genre ~= nil and genre ~= "féminin") then
['icône'] = image,
+
genre = nil
titre = titre:gsub( ' <adj[^>]*>', '' ),
+
end
texte = texte,
 
id = args.id
 
}
 
 
 
-- concaténation des différentes catégories (pas de catégorisation si nocat, ou page de discussion, ou espace utilisateur)
+
-- majuscule : mettre une majuscule au premier mot
local categ = ''
+
local maj = pmajuscule
local messageErreur = table.concat( gestionErreur )
+
if (maj ~= nil and maj ~= "oui") then
if not ( yesno( args.nocat, true, false ) or page.isTalkPage or page.namespace == 2 ) then
+
maj = nil
for i = 1, #categs do
+
end
categs[ i ] = cfg.ebaucheCateg:format( categs[ i ] )
+
 
end
+
-- cas (très) simple : 0
categ = table.concat( categs ):gsub( ' <[^>]*>', '' )
+
if (nvaleur == 0) then
if categ == '' then
+
if (style == "ordinal") then
categ = cfg.ebaucheCateg:format('')
+
if (maj) then
end
+
return "Zéroième"
if #gestionErreur > 0 then
+
else
messageErreur = messageErreur .. '[[Catégorie:Ébauche inconnue]]'
+
return "zéroième"
 +
end
 +
else
 +
if (maj) then
 +
return "Zéro"
 +
else
 +
return "zéro"
 +
end
 
end
 
end
 
end
 
end
 
 
  
return p._bandeauAvertissement( parametres ) .. messageErreur .. categ
+
-- on charge les données
end
+
local Data = mw.loadData( 'Module:Outils/Data' )
  
---
+
-- on traite les autres cas simples : le nombre est pré-codé
-- fonction retournant un paramètre d'une table d'ébauche.
+
local val
-- Elle est prévue pour être appelée directement par #invoke:
+
if (langue == "fr") then
-- avec pour paramètres le thème et le paramètre désiré
+
val = Data.infcent[nvaleur]
-- Cette fonction est principalement destinée à la page d'aide.
+
elseif (langue == "be") then
function p.parametreEbauche( frame )
+
val = Data.infcent_be[nvaleur] or Data.infcent[nvaleur]
local paramEbauche = mw.loadData( moduleEbauche )
+
elseif (langue == "ch") then
local theme = frame.args[1]
+
val = Data.infcent_ch[nvaleur] or Data.infcent_be[nvaleur] or Data.infcent[nvaleur]
local param = frame.args[2]
+
else
if paramEbauche[ theme ] then
+
val = Data.infcent_ch2[nvaleur] or Data.infcent_be[nvaleur] or Data.infcent[nvaleur]
return paramEbauche[ theme ][ param ]
 
elseif paramEbauche[ inverserCasse( theme ) ] then
 
return paramEbauche[ inverserCasse( theme ) ][ param ]
 
 
end
 
end
end
 
  
---
+
local res = val or ""
-- Fonction retournant le féminin d'un théme d'ébauche
+
if (val == nil) then
-- Elle est prévue pour être appelée directement par #invoke:
+
-- pas de résultat, on fait le "calcul"
-- avec pour paramètres le thème et le paramètre désiré
+
 
-- Cette fonction est principalement destinée au modèle {{Catégorie d'ébauche}}, donc une valeur n'est retournée que si les catégories sont identiques
+
-- on l'éclate en une table des différents caractères
function p.femininEbauche( frame )
+
local tvaleur = mw.text.split(valeur, "")
local paramEbauche = mw.loadData( moduleEbauche )
+
local nb = #tvaleur -- nombre d'éléments
local theme = frame.args[1]
+
 
local themeF
+
-- on boucle sur les triplets de chiffres et on stocke le résultat dans une table
if theme then
+
local tbl = {}
local t = getEbaucheTable( paramEbauche, theme )
+
while (true) do
local tF, tAdjF = getEbaucheTable( paramEbauche, theme, true )
+
-- on prend les 3 valeurs concernées
if t.feminin and  tF.categ == t.categ then
+
local p1 = tvaleur[nb-2]
if tAdjF then
+
local p2 = tvaleur[nb-1]
themeF = tF.nom .. ' ' .. tAdjF.feminin
+
local p3 = tvaleur[nb]
elseif tF then
+
-- si les 3 sont 'nil' on a terminé
themeF = tF.nom
+
if (p1 == nil and p2 == nil and p3 == nil) then
 +
break
 
end
 
end
return themeF
+
-- on calcule la valeur du bloc concerné (rangé dans la table)
 +
local tmp = mw.text.trim(Outils.traite_tranche(p1, p2, p3, langue, Data) or "zéro")
 +
table.insert(tbl, tmp)
 +
-- décalage
 +
nb = nb - 3
 
end
 
end
end
 
end
 
  
---
+
-- on construit le résultat final en combinant les éléments
-- fonction qui contruit deux tableaux récapitulatif de l'ensemble des paramètres d'ébauche
+
-- et en ajoutant les milliers/millions/...
function p.tableParametresEbauches( frame )
+
local pos = 1
local paramEbauche = mw.loadData( moduleEbauche )
+
while (tbl[pos] ~= nil) do
local params, paramAdj, paramType = {}, {}, {}
+
local el = ""
local wikiTab = { '<table class="wikitable sortable" style="table-layout:fixed;">' }
+
-- on l'ajoute, s'il existe
wikiTab.insert = function ( t, value )
+
if (tbl[pos] ~= "zéro " and tbl[pos] ~= "zéro") then
table.insert( t, value )
+
if (pos == 1) then
return t
+
-- rang "1", on ajoute simplement la valeur
end
+
el = tbl[pos] .. " "
+
else
for clef, ebauche in pairs( paramEbauche ) do
+
-- si la valeur est "un" on ajoute seulement le rang
local kEbauche = {}
+
if (tbl[pos] == "un " or tbl[pos] == "un") then
for k, v in pairs( ebauche ) do
+
el = Data.sup[pos] .. " "
kEbauche[ k ] = v
+
else
 +
-- on ajoute X + rang
 +
el = tbl[pos] .. " " .. Data.sup[pos]
 +
-- le pluriel, sauf pour 1000, et le séparateur
 +
if (pos ~= 2) then
 +
el = el .. "s "
 +
else
 +
el = el .. " "
 +
end
 +
end
 +
end
 +
end
 +
-- on insert
 +
res = el .. res
 +
 
 +
-- on passe au suivant
 +
pos = pos + 1
 
end
 
end
kEbauche.clef = clef
+
 
if ebauche.type then
+
-- suppression espaces
table.insert( paramType, kEbauche )
+
res = mw.text.trim(res)
elseif ebauche.adjectif then
+
 
if clef == ebauche.nom or clef ~= ebauche.feminin then
+
end -- fin (si on n'avait pas trouvé en pré-défini)
table.insert( paramAdj, kEbauche )
+
 
 +
if (style ~= nil) then
 +
-- ordinal : on cherche la fin du nombre pour ajouter le "ième" qui convient
 +
if (res == "zéro") then
 +
res = "zéroième" -- eurk!
 +
elseif (res == "un") then
 +
if (genre == nil) then
 +
res = "premier"
 +
else
 +
res = "première"
 
end
 
end
 
else
 
else
table.insert( params, kEbauche )
+
-- on récupère le dernier mot
 +
local fin = mw.ustring.match(res, "%a*$")
 +
-- on récupère le reste (début)
 +
local debut = mw.ustring.gsub(res, "%a*$", "")
 +
 +
-- on génère la fin en ordinal
 +
local nfin = Data.iemes[fin]
 +
if (nfin == nil) then
 +
nfin = Outils.erreur("erreur interne d'ordinal.")
 +
end
 +
res = debut .. nfin
 
end
 
end
 
end
 
end
local comp = function( eb1, eb2 )
+
 
return eb1.clef < eb2.clef
+
-- si orthographe réformée on remplace les espaces par des tirets
end
+
if (ortho == "réformée") then
table.sort( params, comp )
+
res = mw.ustring.gsub(res, "[ ]", "-")
table.sort( paramAdj, comp )
+
else
table.sort( paramType, comp )
+
-- sinon on remplace les espaces par des insécables
+
res = mw.ustring.gsub(res, "[ ]", "&#160;")
wikiTab
 
:insert('\n=== Ébauches normales ===\n')
 
:insert('<caption>Liste des paramètres d\'ébauche</caption>')
 
:insert('<th scope=col style="width:15%;">nom</th>')
 
:insert('<th scope=col style="width:50px; box-sizing:border-box;">i</th>')
 
:insert('<th scope=col style="width:20%;">sujet</th>')
 
:insert('<th scope=col style="width:20%;">catégorie</th>')
 
:insert('<th scope=col>selon</th>')
 
for k, ebauche in ipairs( params ) do
 
wikiTab
 
:insert('<tr><td>')
 
:insert( ebauche.clef )
 
:insert('</td><td>')
 
if ebauche.icone then
 
wikiTab:insert( cfg.formatLien:format( ebauche.icone, '45x35', ebauche.altIcone or '' ) )
 
end
 
wikiTab
 
:insert('</td><td>')
 
:insert( ebauche.sujet )
 
:insert('</td><td>')
 
if ebauche.categ then
 
wikiTab
 
:insert( '[[:Catégorie:Wikipédia:ébauche ' .. ebauche.categ .. '|' .. ebauche.categ .. ']]' )
 
end
 
if ebauche.cageg2 then
 
wikiTab
 
:insert('<br>')
 
:insert( '[[:Catégorie:Wikipédia:ébauche ' .. ebauche.categ2 .. '|' .. ebauche.categ2 .. ']]' )
 
end
 
wikiTab
 
:insert('</td><td>')
 
:insert( ebauche.selon )
 
:insert('</td></tr>')
 
 
end
 
end
wikiTab:insert('</table>')
+
if (style == nil) then
+
-- traitement de signe éventuel (sauf ordinaux)
-- seconde table pour les adjectifs
+
if (signe) then
wikiTab
+
res = "moins&#160;" .. res
:insert('\n=== Adjectifs ===\n')
 
:insert('<table class="wikitable">')
 
:insert('<caption>Liste des adjectifs</caption>')
 
:insert('<th scope=col>adjectif</th>')
 
:insert('<th scope=col>féminin</th>')
 
:insert('<th scope=col style="width:50px;">icone</th>')
 
:insert('<th scope=col>sujet</th>')
 
:insert('<th scope=col>sujet féminin</th>')
 
:insert('<th scope=col>catégorie</th>')
 
for k, ebauche in ipairs( paramAdj ) do
 
wikiTab
 
:insert('<tr><td>')
 
:insert( ebauche.clef )
 
:insert('</td><td>')
 
:insert( ebauche.feminin )
 
:insert('</td><td>')
 
if ebauche.icone then
 
wikiTab
 
:insert( cfg.formatLien:format( ebauche.icone, '45x35', ebauche.altIcone or '' ) )
 
 
end
 
end
wikiTab
 
:insert('</td><td>')
 
:insert( ebauche.sujet )
 
:insert('</td><td>')
 
:insert( ebauche.sujetF or ebauche.sujet:gsub( ebauche.nom .. '%f[%W]', ebauche.feminin ) )
 
:insert('</td><td>')
 
if ebauche.categ then
 
wikiTab
 
:insert( '[[:Catégorie:Wikipédia:ébauche ' .. ebauche.categ .. '|' .. ebauche.categ .. ']]' )
 
end
 
wikiTab
 
:insert('</td></tr>')
 
 
end
 
end
wikiTab:insert('</table>')
+
 
+
-- si demandé on passe la première lettre en majuscule
-- troisième table pour les types
+
if (maj) then
wikiTab
+
local langage = mw.getContentLanguage()
:insert('\n=== Types ===\n')
+
res = langage:ucfirst(res)
:insert('<table class="wikitable">')
 
:insert('<caption>Liste des paramètres de type</caption>')
 
:insert('<th scope=col style="width:15%;">nom</th>')
 
:insert('<th scope=col style="width:50px;">icone</th>')
 
:insert('<th scope=col style="width:20%;">type</th>')
 
:insert('<th scope=col style="width:15%;">sujet</th>')
 
:insert('<th scope=col style="width:15%;">catégorie</th>')
 
:insert('<th scope=col>message</th>')
 
for k, ebauche in ipairs( paramType ) do
 
wikiTab
 
:insert('<tr><td>')
 
:insert( ebauche.clef )
 
:insert('</td><td>')
 
if ebauche.icone then
 
wikiTab:insert( cfg.formatLien:format( ebauche.icone, '45x35', ebauche.altIcone or '' ) )
 
end
 
wikiTab
 
:insert('</td><td>')
 
:insert ( ebauche.type )
 
:insert('</td><td>')
 
:insert( ebauche.sujet )
 
:insert('</td><td>')
 
if ebauche.categ then
 
wikiTab:insert( '[[:Catégorie:Wikipédia:ébauche ' .. ebauche.categ .. '|' .. ebauche.categ .. ']]' )
 
end
 
wikiTab
 
:insert('</td><td>')
 
:insert( ebauche.message )
 
:insert('</td></tr>')
 
 
end
 
end
wikiTab:insert('</table>')
 
 
return table.concat( wikiTab ):gsub( ' <adjF?>', '' )
 
end
 
  
-- fonction destiné au gadget MediaWiki:Gadget-BandeauxEbauches.js
+
-- on retourne
function p.listeEbauches( frame )
+
return res
local paramEbauche = mw.loadData( moduleEbauche )
 
local liste = {}
 
for k in pairs( paramEbauche ) do
 
if k ~="" then
 
table.insert( liste, k )
 
end
 
end
 
table.sort( liste )
 
return table.concat( liste, '\n' )
 
 
end
 
end
  
 +
--[[
 +
  Fonction principale
 +
  Reçoit en paramètre (premier non nommé) le nombre à traiter.
 +
  Retourne la forme textuelle de ce nombre.
 +
--]]
 +
function Outils.nombre2texte(frame)
 +
local pframe = frame:getParent()
  
 +
return Outils.nombre2texte_reel(
 +
pframe.args[1] or frame.args[1], -- pas obligé. Pour permettre des exemples, avec priorité au modèle
 +
frame.args["langue"] or pframe.args["langue"],
 +
frame.args["type"] or pframe.args["type"],
 +
frame.args["orthographe"] or pframe.args["orthographe"],
 +
frame.args["genre"] or pframe.args["genre"],
 +
frame.args["majuscule"] or pframe.args["majuscule"],
 +
frame.args["ordinal"] or pframe.args["ordinal"]);
 +
end
  
-- Insertion dans la table p des fonctions appelées par les
+
--[[
-- modèles à l'aide d'un adaptateur de fonction.
+
  Comportement proche − mais plus simple − de notEmpty()
local function adaptateur(nomFonction)
+
  Fait pour être appelé directement (#invoke), et retourne le premier de ses
return function (frame)
+
    paramètres d'appel qui n'est pas vide (au sens contient autre chose que
local args
+
    des espaces, retours à la ligne…)
if frame.args.texte or frame.args.titre then
+
  Paramètres non nommés uniquement, appelé directement (#invoke)
args = frame.args
+
--]]
else
+
function Outils.premiereValeur(frame)
args = frame:getParent().args
+
local args = frame.args;  -- paramètres '''du module'''
 +
for k,v in pairs( args ) do  -- parcours
 +
if (mw.text.trim(v) ~= "") then
 +
-- si non vide on le retourne
 +
return mw.text.trim(v)
 
end
 
end
return p[nomFonction](args)
 
 
end
 
end
 +
-- trouvé aucun non vide, on retourne vide
 +
return ""
 
end
 
end
 
local nomsFonction = {'bandeau', 'bandeauAvertissement', 'bandeauSection', 'ébauche' }
 
for _, nomFonction in ipairs(nomsFonction) do
 
p[nomFonction] = adaptateur('_' .. nomFonction)
 
end
 
  
return p
+
 
 +
return Outils

Version actuelle datée du 7 décembre 2020 à 16:43

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

local Outils = { }


--[[
	trim nettoie un paramètre non nommé (supprime les espaces et retours ligne au début et à la fin)
	retourne  nil si le texte est vide ou n'est pas du texte. Les nombres ne sont PAS considérés 
	comme du texte.
]]
function Outils.trim( texte )
	if type( texte ) == 'string' and texte~= '' then
		texte = texte:gsub( '^%s*(%S?.-)%s*$', '%1' )
		if texte ~= '' then
			return texte
		end
	end
	return nil
end


-- erreur génère un message d'erreur
function Outils.erreur( texte )
	local message = Outils.trim( texte ) or "''erreur : raison non précisée''"
	return '<span class="error">' .. message .. "</span>"
end


--[[
	validTextArg renvoit le premier paramètre chaine non vide
	Paramètre : 
		1 - tableau contenant tous paramètres
		2, ... - les noms des paramètres qui doivent êtres testés.
]]
function Outils.validTextArg( args, name, ... ) 
	local texte = Outils.trim( args[name] )
	if texte then
		return texte
	end
	if select( '#', ... ) > 0 then
		return Outils.validTextArg( args, ... )
	end
	return nil
end


--[[
	notEmpty renvoie le premier paramètre non vide ou nul. 
	Paramètre : 
		1, ... - les variables qui doivent êtres testés.
]]
function Outils.notEmpty( var, ... )
	local tvar = type( var )
	
	if Outils.trim( var ) then
		return Outils.trim( var )
	elseif tvar == 'table' then
		local nextFunc = pairs( var )   -- n'utilise pas next car non défini par mw.loadData
		if nextFunc( var ) ~= nil then
			return var
		end 
	elseif var == true or ( tvar == 'number' and var ~= 0 ) or tvar == 'function' then
		return var
	end
	
	if select( '#', ... ) > 0 then
		return Outils.notEmpty(  ... )
	end
end


--[[
	extractArgs permet de récupérer les arguements du modèle, 
	ou la table transmise à la fonction par une autre fonction d'un module
	Paramètres : 
		1 - un objet frame ou une table contenant les paramètre
		2, ...  - une liste de nom de paramètre pour déterminé si les paramètres sont transmis 
			par #invoke. Le premier paramètre de frame sera systématiquement testé.
]]
function Outils.extractArgs ( frame, ... )
	if type( frame ) == 'table' then
		if type( frame.getParent ) == 'function' then
			if Outils.notEmpty( frame.args.invokeArgsOnly ) then
				return frame.args
			else
				local args = frame:getParent().args;
				for k,v in pairs( frame.args ) do
					args[k] = v;
				end
				return args
			end
		else
			return frame 
		end
	else
		return { frame, ... }
	end
end


--[[
	abr génère une abréviation (discrète par défaut)
	paramètres : 
		1 = abréviation, 
		2 = texte, 
		3 = langue, 
		nbsp =  '-' pour une espace insécable avant l'abréviation, '+' pour l'avoir après.
		visible = true pour une abréviation non discrète
]]
function Outils.abr( frame, ... )
	local args = Outils.extractArgs( frame, ... )
	if args[2] == nil then 
		return args[1] or ''	
		-- retoune l'abréviation ou au minimum une chaine vide s'il n'y a pas de texte
	end

	local wikiText = { '<abbr' }
	if not args.visible then
		table.insert( wikiText, ' class="abbr"' )
	end
	table.insert( wikiText, ' title="' .. args[2] )
	if args[3] then 
		table.insert( wikiText, '" lang="' .. args[3] )
	end
	table.insert( wikiText, '">' .. args[1] .. '</abbr>' )
	if args.nbsp == '-' then
		table.insert( wikiText, 1, '&nbsp;' )
	elseif args.nbsp == '+' then
		table.insert( wikiText, '&nbsp;' )
	end

	return table.concat( wikiText )
end


function Outils.nobr( texte )
	if type( texte )  == 'number' or Outils.trim( texte) then 
		return '<span class="nowrap">' .. texte .. '</span>'
	else
		return ''
	end
end


--[=[
	texteLien trouve le premier lien interwiki '[[lien|texte]]' de str et retourne : texte, lien
	Si le lien est '[[texte]]', retourne : texte, texte.
	Si str ne contient pas de lien interwiki, retourne : str (et nil)
	Les fichiers et images ne sont pas considérés comme des liens.
	Si str n'est pas une chaine, retourne : nil
]=]
function Outils.texteLien( str )
	if type( str ) == 'string' then
		for lien, texte in string.gmatch( str, '%[%[ *([^%[%]|]*)|? *([^%[%]]*)%]%]' ) do
			texte = ( texte ~= '' and texte ) or lien or str
			if not lien then
				return str
			end
			local testlien = string.lower( lien )
			local fichier = string.match( testlien, '^fichier:' ) 
				or  string.match( testlien, '^image:' )
				or  string.match( testlien, '^file:' )
			if not fichier then 
				return texte, lien
			end
		end
		return str
	end
end

--[=[
	texteLien trouve la première lien externe '[adresse texte]' de str et retourne : texte, adresse
	Une adresse doit commencer par 'http://'
	Si le lien est '[adresse]', retourne : '', adresse.
	Si str ne contient pas de lien externe, retourne : str (et nil)
	Si adresse ou texte contenienne le caratère '[', retourne l'adresse suivante ou str
	Si str n'est pas une chaine, retourne : nil
]=]
function Outils.texteAdresse( str )
	if type( str ) == 'string' then
		local lien, texte = string.match( str, '%[(https?://[^%[%] ]*) *([^%[%]]-)%]' )
		
		texte = texte or str
		return texte, lien
	end
end


--[[
	ordinal renvoie une chaine correspondant à l'abréviation de l'adjectif ordinal du nombre.
	Paramètres :
		1 = nombre (string ou number) 
		2 = true pour avoir première au lieu de premier su nombre = 1
--]]
function Outils.ordinal( nombre, feminin )
	local num = tonumber( nombre )
	if num == nil then
		return Outils.trim( tostring( nombre ) ) or ''
	else
		local nom = Outils.nombre2texte_reel( nombre, nil, 'ordinal', 'réformée', feminin and 'féminin' )
		return Outils.abr{ num .. '<sup>e</sup>', nom }
	end
end


--[[
  Fonction de traitement d'une "tranche" de nombres entre 0 et 999.
  Retourne la forme texturelle (5 → cinq, 46 → quarante six, 432 → quatre cent trente deux…)
  Les paramètres sont les chiffres, du plus grand au plus petit (centaine, dizaine, unité).
  La valeur nil signifie "0" (pour n'importe lequel des paramètres)
  La fonction retourne le texte ou 'nil' si la valeur est zéro (pour gérer les 0 millier…)
  Le paramètre 'langue' indique la variante de langue (fr, be, ch ou ch2).
  Data est la table des données (issue de loadData())
--]]
function Outils.traite_tranche(_c1, _c2, _c3, langue, Data)
    local c1, c2, c3
	if (_c1 == nil) then c1 = 0 else c1 = tonumber(_c1) or 0 end
	if (_c2 == nil) then c2 = 0 else c2 = tonumber(_c2) or 0 end
	if (_c3 == nil) then c3 = 0 else c3 = tonumber(_c3) or 0 end

	if (c1 == 0 and c2 == 0 and c3 == 0) then
		return nil -- sil signifie "zéro" (mais à traiter spécialement quand entouré)
	end
	local resu = ""
	
	-- on calcule la valeur restante (sans les centaines)
	local val = 10*c2 + c3
	-- présence d'une centaine ?
	if (c1 ~= 0) then
		if (c1 == 1) then
			resu = "cent " -- séparateur
		else
			-- plusieurs centaines : on ajoute l'unité
			resu = Data.infcent[c1] .. " cent"
			-- si pas d'unité 100 prend un 's'
			if (val == 0) then
				resu = resu .. "s "
			else
				resu = resu .. " "
			end
		end
	end
	-- reste = 0 ?
	if (val == 0) then
		-- on retourne directement la centaine
		return resu
	end
	-- c'est forcément un nombre pré-défini
	local vvv
	if (langue == "fr") then
		vvv = Data.infcent[val]
	elseif (langue == "be") then
		vvv = Data.infcent_be[val] or Data.infcent[val]
	elseif (langue == "ch") then
		vvv = Data.infcent_ch[val] or Data.infcent_be[val] or Data.infcent[val]
	else
		vvv = Data.infcent_ch2[val] or Data.infcent_be[val] or Data.infcent[val]
	end
	return resu .. vvv .. " "
	-- note : cette fonction retourne *toujours* un " " à la fin du terme
end

--[[
  Fonction principale
  Reçoit en paramètre (premier non nommé) le nombre à traiter.
  Retourne la forme textuelle de ce nombre.
--]]
function Outils.nombre2texte_reel(pnombre, plangue, ptype, porthographe, pgenre, pmajuscule, pordinal)
	-- le nombre à convertir (vient toujours du modèle)
	local valeur = pnombre
	if (valeur == nil) then
		return Outils.erreur("Il faut un paramètre non nommé numérique.")
	elseif type(valeur) == "sting" then
		
		-- s'il y a une virgule, on l'ignore
		local bla = mw.ustring.find(valeur, "[.,]")
		if (bla ~= nil) then
			-- extraction de la partie avant la virgule
			valeur = mw.ustring.match(mw.text.trim(valeur), "^[-]?[0-9]*")
		end
	elseif type(valeur) == "number" then
		valeur = math.floor(valeur)
	end
	
	local nvaleur = tonumber(valeur)
	if (type(nvaleur) ~= "number") then
		return Outils.erreur("Le paramètre doit être un nombre.")
	end
	-- limites
	if (nvaleur < -999999999999 or nvaleur > 999999999999) then
		return Outils.erreur("Nombre trop grand ou trop petit.")
	end
	-- note : ici il faudrait s'assurer que le nombre est un entier !

	-- on extrait le moins si présent
	local signe = false
	if (nvaleur < 0) then
		nvaleur = -nvaleur
		signe = true
	end

	-- option : choix de la langue
	local langue = plangue
	if (langue == nil) then
		langue = "fr"
	else
		langue = mw.text.trim(langue)
	end
	-- validation des valeurs permises
	if (langue ~= "fr" and langue ~= "be" and langue ~= "ch" and langue ~= "ch2") then
		return Outils.erreur("Paramètre langue non reconnu (fr, be, ch ou ch2).")
	end

	-- type de résultat : seule valeur autorisée : 'ordinal'
	local style = ptype
	if (style ~= nil and style ~= "ordinal") then
		style = nil
	end

	-- type d'orthographe
	local ortho = porthographe
	if (ortho ~= nil and ortho ~= "réformée") then
		ortho = nil
	end
	
	-- genre : uniquement pour l'ordinal "premier / première"
	local genre = pgenre
	if (genre ~= nil and genre ~= "féminin") then
		genre = nil
	end
	
	-- majuscule : mettre une majuscule au premier mot
	local maj = pmajuscule
	if (maj ~= nil and maj ~= "oui") then
		maj = nil
	end

	-- cas (très) simple : 0
	if (nvaleur == 0) then
		if (style == "ordinal") then
			if (maj) then
				return "Zéroième"
			else
				return "zéroième"
			end
		else
			if (maj) then
				return "Zéro"
			else
				return "zéro"
			end
		end
	end

	-- on charge les données
	local Data = mw.loadData( 'Module:Outils/Data' )

	-- on traite les autres cas simples : le nombre est pré-codé
	local val
	if (langue == "fr") then
		val = Data.infcent[nvaleur]
	elseif (langue == "be") then
		val = Data.infcent_be[nvaleur] or Data.infcent[nvaleur]
	elseif (langue == "ch") then
		val = Data.infcent_ch[nvaleur] or Data.infcent_be[nvaleur] or Data.infcent[nvaleur]
	else
		val = Data.infcent_ch2[nvaleur] or Data.infcent_be[nvaleur] or Data.infcent[nvaleur]
	end

	local res = val or ""
	if (val == nil) then
		-- pas de résultat, on fait le "calcul"

		-- on l'éclate en une table des différents caractères
		local tvaleur = mw.text.split(valeur, "")
		local nb = #tvaleur -- nombre d'éléments

		-- on boucle sur les triplets de chiffres et on stocke le résultat dans une table
		local tbl = {}
		while (true) do
			-- on prend les 3 valeurs concernées
			local p1 = tvaleur[nb-2]
			local p2 = tvaleur[nb-1]
			local p3 = tvaleur[nb]
			-- si les 3 sont 'nil' on a terminé
			if (p1 == nil and p2 == nil and p3 == nil) then
				break
			end
			-- on calcule la valeur du bloc concerné (rangé dans la table)
			local tmp = mw.text.trim(Outils.traite_tranche(p1, p2, p3, langue, Data) or "zéro")
			table.insert(tbl, tmp)
			-- décalage
			nb = nb - 3
		end

		-- on construit le résultat final en combinant les éléments
		-- et en ajoutant les milliers/millions/...
		local pos = 1
		while (tbl[pos] ~= nil) do
			local el = ""
			-- on l'ajoute, s'il existe
			if (tbl[pos] ~= "zéro " and tbl[pos] ~= "zéro") then
				if (pos == 1) then
					-- rang "1", on ajoute simplement la valeur
					el = tbl[pos] .. " "
				else
					-- si la valeur est "un" on ajoute seulement le rang
					if (tbl[pos] == "un " or tbl[pos] == "un") then
						el = Data.sup[pos] .. " "
					else
						-- on ajoute X + rang
						el = tbl[pos] .. " " .. Data.sup[pos]
						-- le pluriel, sauf pour 1000, et le séparateur
						if (pos ~= 2) then
							el = el .. "s "
						else
							el = el .. " "
						end
					end
				end
			end
			-- on insert
			res = el .. res

			-- on passe au suivant
			pos = pos + 1
		end

		-- suppression espaces
		res = mw.text.trim(res)

	end -- fin (si on n'avait pas trouvé en pré-défini)

	if (style ~= nil) then
		-- ordinal : on cherche la fin du nombre pour ajouter le "ième" qui convient
		if (res == "zéro") then
			res = "zéroième" -- eurk!
		elseif (res == "un") then
			if (genre == nil) then
				res = "premier"
			else
				res = "première"
			end
		else
			-- on récupère le dernier mot
			local fin = mw.ustring.match(res, "%a*$")
			-- on récupère le reste (début)
			local debut = mw.ustring.gsub(res, "%a*$", "")
			
			-- on génère la fin en ordinal
			local nfin = Data.iemes[fin]
			if (nfin == nil) then
				nfin = Outils.erreur("erreur interne d'ordinal.")
			end
			res = debut .. nfin
		end
	end

	-- si orthographe réformée on remplace les espaces par des tirets
	if (ortho == "réformée") then
		res = mw.ustring.gsub(res, "[ ]", "-")
	else
		-- sinon on remplace les espaces par des insécables
		res = mw.ustring.gsub(res, "[ ]", "&#160;")
	end
	if (style == nil) then
		-- traitement de signe éventuel (sauf ordinaux)
		if (signe) then
			res = "moins&#160;" .. res
		end
	end

	-- si demandé on passe la première lettre en majuscule
	if (maj) then
		local langage = mw.getContentLanguage()
		res = langage:ucfirst(res)
	end

	-- on retourne
	return res
end

--[[
  Fonction principale
  Reçoit en paramètre (premier non nommé) le nombre à traiter.
  Retourne la forme textuelle de ce nombre.
--]]
function Outils.nombre2texte(frame)
	local pframe = frame:getParent()

	return Outils.nombre2texte_reel(
		 pframe.args[1] or frame.args[1], -- pas obligé. Pour permettre des exemples, avec priorité au modèle
		 frame.args["langue"] or pframe.args["langue"],
		 frame.args["type"] or pframe.args["type"],
		 frame.args["orthographe"] or pframe.args["orthographe"],
		 frame.args["genre"] or pframe.args["genre"],
		 frame.args["majuscule"] or pframe.args["majuscule"],
		 frame.args["ordinal"] or pframe.args["ordinal"]);
end

--[[
  Comportement proche − mais plus simple − de notEmpty()
  Fait pour être appelé directement (#invoke), et retourne le premier de ses
    paramètres d'appel qui n'est pas vide (au sens contient autre chose que
    des espaces, retours à la ligne…)
  Paramètres non nommés uniquement, appelé directement (#invoke)
--]]
function Outils.premiereValeur(frame)
	local args = frame.args;  -- paramètres '''du module'''
	for k,v in pairs( args ) do  -- parcours
		if (mw.text.trim(v) ~= "") then
			-- si non vide on le retourne
			return mw.text.trim(v)
		end
	end
	-- trouvé aucun non vide, on retourne vide
	return ""
end


return Outils