Module:Liste des corrections
La documentation pour ce module peut être créée à Module:Liste des corrections/Documentation
local p = {}
-- Dresse la liste des corrections apportées dans un livre
function p.liste (frame)
local args = frame.args
local index = args[1]
local section = "correction" -- nom de la section, par défaut celui du modèle {{Page Discussion}}
local total = 0 -- nombre total de corrections
local out = mw.html.create()
local corrections = mw.html.create( 'table' )
local NS = "Discussion_Page" -- par défaut les explications sont sur les pages de discussion de l'espace Page
if not index or index == "" then
return "Le nom du livre n’a pas été donné."
end
-- on change le nom de la section des corrections si besoin
if args[2] ~= nil and args[2] ~= "" then
section = args[2]
end
-- si on souhaite récupérer la liste des corrections
-- directement avec le modèle {{corr}}
if args.avec ~= nil and args.avec == "corr" then
NS = "Page"
end
local l = mw.title.new(index, "Media")
if l.exists then
local pagelist = p.get_pagelist(index)
local npages = #l.file.pages
if npages then
local i=1 -- page du fichier
local n=1 -- page en fonction du décalage
local nt= nil
local pn = nil
local page = nil
while (i<=npages) do
pn = pagelist["p"][tostring(i)]
if pn ~= nil then
if tonumber(pn) ~= nil then
n = tonumber(pn)
nt=n
else
nt = pn
end
else
nt=n
end
for _, r in ipairs( pagelist["r"] ) do
if i>= r[1] and i<=r[2] then
nt=p.int2roman(n)
end
end
page = mw.title.new(index.."/"..i, NS)
local content = page:getContent()
-- BUG limite 500 appels (cf Sujet:Unmn96gkz9zox8uh)
-- NE PAS UTILISER page.exists ci dessous, cette fonction coûteuse
-- incrémente $wgExpensiveParserFunctionLimit et bloque le script à la 501ème page
-- au lieu de cela, on teste si son contenu est différent de nil (la page n'existe pas) ou vide
-- problème : la page est enregistrée comme une transclusion
if content ~= nil and content ~="" then
local corr = nil
if NS == "Page" then
corr = p.get_corr(content)
else
corr = frame:callParserFunction{
name = '#lst:'..page.fullText ,
args = { section }
}
end
if (corr ~= "" and corr ~= nil) then
local tr = mw.html.create( 'tr' )
local td_page = mw.html.create( 'td' )
local td_corr = mw.html.create( 'td' )
local expl_txt = ""
if NS == "Page" then
-- on cherche si {{CorrBandeau}} est utilisé dans la page
local explications = string.find(content, "{{[Cc]orrBandeau}}")
if explications == nil then
-- on cherche si {{CorrDiscussion}} est utilisé dans la page de discussion
page_d = mw.title.new(index.."/"..i, "Discussion_Page")
content_d = page_d:getContent()
if content_d ~= nil then
explications = string.find(content_d, "{{[Cc]orrDiscussion")
end
end
if explications ~= nil then
expl_txt = ' <sup>([[Discussion_Page:'..page.text..'|expl.]])</sup>'
end
end
td_page:wikitext("'''Page [["..page.fullText.."|"..nt.."]]'''"..expl_txt.." :")
:css("padding","0.5em 0.5em 0 0")
:css("white-space","nowrap")
if NS == "Page" then
if corr == false then
corr = frame:expandTemplate{
title = 'rouge' ,
args = { frame:preprocess('Une erreur avec un modèle {{m|corr}} a été détectée sur cette page.') }
}
td_corr:wikitext(corr)
else
for _, c in ipairs(corr) do
-- le deuxième argument peut contenir du wikicode
local cm = frame:expandTemplate{
title = 'CorrDiscussion' ,
args = { c[1], frame:preprocess(c[2]), nombre=c[3] }
}
td_corr:node(cm)
end
end
else
td_corr:wikitext(corr)
end
tr:node(td_page):node(td_corr)
:css("vertical-align","top")
corrections:node(tr)
total = total +1
end
end
i = i+1
n = n+1
end
if total > 0 then
if next(pagelist["p"]) ~= nil then
out:wikitext("''Les informations relatives aux pages (numéro, libellé) correspondent à ceux de la balise <pagelist/> provenant de [[Index:"..index.."|l’index]].''")
else
out:wikitext("''Les numéros de page correspondent à ceux du fichier.''")
end
if NS == "Page" then
local mc = frame:expandTemplate{ title = 'm', args = {'corr'} }
out:wikitext("<br/>''La liste des corrections est dressée à partir des modèles "..mc.." utilisés.''")
end
out:node(corrections)
return out
else
return "''Aucune correction n’a été apportée à ce livre."
end
end
else
return "Le livre « [[Livre:"..index.."|"..index.."]] » n’existe pas."
end
end
-- Récupère les différents <pagelist/> sur la page d'index
-- @param index string : nom de l'index sans le préfixe
-- @return array : tableau contenant les décalages (9=3) et libellés (2=TdM) des différents <pagelist/>
function p.get_pagelist(index)
local page = mw.title.new(index, "Index")
local content = page:getContent()
local pages = {}
local roman={}
for pl in string.gmatch(content, "<pagelist[^>]+/>") do
-- récupère et stocke la valeur la page (9=3, 2=Tdm,...)
for pi,pv in string.gmatch(pl, "%s([1-9][0-9]*)=([^%s/]+)") do
pages[pi]=mw.text.trim( pv, '"' ) -- enlève les "" en début et fin de chaine
end
-- récupère les pages devant apparaître comme des nombres romains
for fr,to in string.gmatch(pl, "([1-9][0-9]*)to([1-9][0-9]*)=roman") do
table.insert( roman, {tonumber(fr),tonumber(to)} )
end
end
return {["p"]=pages,["r"]=roman}
end
-- Récupère tous les modèles {{corr}} sur une page.
-- Attention, le deuxième argument du modèle corr peut contenir un autre modèle
-- @param c string : contenu de la page
-- @return array|nil : tableau contenant les valeurs des corr, nil si aucun corr
function p.get_corr(c)
local corr = {}
local init= 1
while true do
p_start,p_end = mw.ustring.find(c, "{{[Cc]orr%|", init)
-- si le motif n'est plus dans la chaine on stop la recherche
if p_start == nil then break end
-- on récupère ce qui est après le motif
local after_p = mw.ustring.sub(c, p_end+1)
-- on recherche la fin réelle du modèle
-- correspond à 0 par addition et soustraction de { et }
local corr_i = 2; -- les deux déjà dans le motif
local corr_args = nil
for i = 1, #after_p do
local char = mw.ustring.sub(after_p,i,i)
if char == "{" then
corr_i = corr_i+1
elseif char == "}" then
corr_i = corr_i-1
end
if corr_i == 0 then
corr_args = mw.ustring.sub(after_p,1,i-2)
break
end
end
if corr_args ~= nil then
local fist_pipe_pos = mw.ustring.find(corr_args, "|", 1, true)
if fist_pipe_pos ~= nil then
local corr_arg1 = mw.ustring.sub(corr_args,1,fist_pipe_pos-1)
local corr_arg2 = mw.ustring.sub(corr_args,fist_pipe_pos+1)
-- si la correction est multiple on ne la stocke qu'une fois
local m = false
for i, v in ipairs(corr) do
if corr_arg1==v[1] and corr_arg2==v[2] then
corr[i][3] = v[3]+1
m=true
end
end
if not m then
table.insert(corr, {corr_arg1, corr_arg2, 1})
end
else
return false -- erreur
end
end
init = p_end -- reprend la recherche à la fin du motif
end
if #corr == 0 then return nil else return corr end
end
-- Transforme un entier (5) en nombre romain minuscule (v)
-- honteusement copié de https://www.rosettacode.org/wiki/Roman_numerals/Encode#Lua
-- Module:MathRoman ne semble pas fonctionner
-- @param s integer|string : entier à transformer
-- @return string : nombre romain
function p.int2roman(s)
romans = {
{1000, "M"},
{900, "CM"}, {500, "D"}, {400, "CD"}, {100, "C"},
{90, "XC"}, {50, "L"}, {40, "XL"}, {10, "X"},
{9, "IX"}, {5, "V"}, {4, "IV"}, {1, "I"}
}
s = tonumber(s) -- donne nil si s n'est pas un nombre
if not s then return s end -- renvoit nil
out = ""
for _, v in ipairs(romans) do --note that this is -not- ipairs.
val, let = unpack(v)
while s >= val do
s = s - val
out = out .. let
end
end
return string.lower(out)
end
return p