Moduł:Brudnopis/Paweł Ziemian/Duplikaty
Wygląd
Dokumentacja dla tego modułu może zostać utworzona pod nazwą Moduł:Brudnopis/Paweł Ziemian/Duplikaty/opis
local FindPositionsInReverseOrder = function(text, plainPattern)
local result = {}
if #plainPattern > 0 then
local init = 1
while init do
init = string.find(text, plainPattern, init, true)
if init then
table.insert(result, 1, init)
init = init + #plainPattern
end
end
end
return result
end
local RemoveInPlace = function(text, start, len)
local before = start > 1 and string.sub(text, 1, start-1) or ""
local stop = start + len
local after = stop <= #text and string.sub(text, stop) or ""
return before..string.rep("_", len)..after
end
local function FindTemplatesWithDuplicatedArguments(contents)
-- zgumkowanie obszarów nie podlegających szablonowej analize
local text = contents
-- komentarze HTML
text = string.gsub(text, "<!%-%-.-%-%->", function(s) return string.rep('_', #s) end)
-- sekcje <nowiki>
text = string.gsub(text, "<nowiki>.-</nowiki>", function(s) return string.rep('_', #s) end)
-- wzory matematyczne
text = string.gsub(text, "<math>.-</math>", function(s) return string.rep('_', #s) end)
-- wikilinki iteracyjnie od końca
for _, startPos in ipairs(FindPositionsInReverseOrder(text, "[[")) do
local endPos = string.find(text, "]]", startPos, true)
if endPos then
local eol = string.find(text, "\n", startPos, true)
if eol and (eol < endPos) then
endPos = nil
end
end
local len = endPos and (endPos - startPos + 2) or 2
text = RemoveInPlace(text, startPos, len)
end
-- wyszukiwanie pozycji szablonów
local templatePositions = {}
-- iteracyjnie od ostatniego
for _, startPos in ipairs(FindPositionsInReverseOrder(text, "{{")) do
local endPos = string.find(text, "}}", startPos, true)
local len = endPos and (endPos - startPos + 2) or 2
if (len > 2) then
local template = string.sub(text, startPos, startPos+len-1)
local separators = {}
local init = 2
while init do
init = string.find(template, "|", init, true)
if init then
table.insert(separators, startPos+init-1)
init = init + 1
end
end
-- tylko szablony z wieloma parametrami są interesujące
if #separators >= 2 then
local index = 0
local m = {}
local d = {}
local hasDuplicates = false
local params = {}
for i, v in ipairs(separators) do
local p = {
start = separators[i],
len = (separators[i+1] or endPos) - separators[i] - 1,
}
local param = string.sub(contents, p.start+1, p.start+p.len)
local eqPos = string.find(param, "=", 1, true)
if eqPos then
p.name = mw.text.trim(string.sub(param, 1, eqPos-1))
p.namelen = eqPos-1
else
index = index + 1
p.name = tostring(index)
end
table.insert(params, p)
if not m[p.name] then
m[p.name] = p
elseif not d[p.name] then
hasDuplicates = true
d[p.name] = { m[p.name], p }
else
table.insert(d[p.name], p)
end
end
if hasDuplicates then
local suspectedTemplate = { start=startPos, len=len, duplicates = d, params = params }
table.insert(templatePositions, 1, suspectedTemplate)
end
end
end
text = RemoveInPlace(text, startPos, len)
end
return #templatePositions > 0 and templatePositions or false
end
local function FormatReportWithDuplicatedArgumentsInTemplates(duplicates, contents)
local builder = mw.html.create("ul")
for k, v in pairs(duplicates) do
local item = builder:tag("li")
item:tag("pre"):wikitext(mw.text.nowiki(string.sub(contents, v.start, v.start+v.len-1)))
local dups = item:tag("ol")
for _, p in pairs(v.params) do
if v.duplicates[p.name] then
local item = dups:tag("li")
item:tag("tt"):wikitext(mw.text.nowiki(string.sub(contents, p.start, p.start+p.len)))
if not p.namelen then
item:tag("sup"):wikitext("(", mw.text.nowiki(p.name), ")")
end
end
end
end
return tostring(builder)
end
local function Process(contents)
if not contents or (#contents <= 0) then
return
end
local duplicates = FindTemplatesWithDuplicatedArguments(contents)
if duplicates then
return FormatReportWithDuplicatedArgumentsInTemplates(duplicates, contents)
end
end
return {
["w tekście"] = function (frame)
return Process(require('Module:Arguments').getArgs(frame)[1])
end,
["na stronie"] = function (frame)
return Process(mw.title.getCurrentTitle():getContent())
end,
}