Moduł:Navbox/diag
Przejdź do nawigacji
Przejdź do wyszukiwania
Dokumentacja dla tego modułu może zostać utworzona pod nazwą Moduł:Navbox/diag/opis
local res = mw.loadData('Moduł:Navbox/res')
local function fullMatch ( str )
return '^'..mw.ustring.gsub( str, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" )..'$'
end
local function templateMatch ( name )
local title = mw.title.new(name)
local text = title.namespace ~= 10 and name or title.text
return "{{%s*"..mw.ustring.gsub( text, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" ).."[%s|]"
end
local function loadKeys ( tab )
local result = {}
for k, v in pairs(tab) do
table.insert(result, k)
end
return result
end
local function copySequenceExcept(tab, unwanted)
local skip = {}
if unwanted then
for i, v in ipairs(unwanted) do
skip[v] = true
end
end
local result = {}
for i, v in ipairs(tab) do
if not skip[v] then
table.insert(result, v)
end
end
return result
end
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 diag = {
classStats = "navbox-statistics",
categoryCSS = "[[Kategoria:Szablony nawigacyjne ze stylami]]",
categoryProblems = "[[Kategoria:Szablony nawigacyjne – spisy do sprawdzenia]]",
categorySuspected = "[[Kategoria:Szablony nawigacyjne – spisy podejrzane]]",
categoryWikilinks0 = "[[Kategoria:Szablony nawigacyjne – spisy bez linków]]",
categoryWikilinks1 = "[[Kategoria:Szablony nawigacyjne – tylko 1 link]]",
categoryWikilinks2 = "[[Kategoria:Szablony nawigacyjne – tylko 2 linki]]",
categoryWikilinks3 = "[[Kategoria:Szablony nawigacyjne – tylko 3 linki]]",
categoryWikilinks4 = "[[Kategoria:Szablony nawigacyjne – tylko 4 linki]]",
categoryLargeList = "[[Kategoria:Szablony nawigacyjne – ponad 500 pozycji]]",
categoryUnknownArgs = "[[Kategoria:Szablony nawigacyjne – nieznane parametry]]",
categoryManyColumns = "[[Kategoria:Szablony nawigacyjne – dużo kolumn]]",
categoryVertical = "[[Kategoria:Szablony nawigacyjne – pionowe]]",
categoryBadName = "[[Kategoria:Szablony nawigacyjne ze złym parametrem nazwa]]",
categoryNavboxInside = "[[Kategoria:Szablony nawigacyjne – zagnieżdżone]]",
categoryAnonymousLists = "[[Kategoria:Szablony nawigacyjne – nieopisane spisy]]",
categoryCheckWikicode = "[[Kategoria:Szablony nawigacyjne – wikikod do sprawdzenia]]",
categoryUnusedArgs = "[[Kategoria:Szablony nawigacyjne – nieużywane parametry]]",
categoryUnverifiedArgs = "[[Kategoria:Szablony nawigacyjne – nieprawidłowe parametry]]",
categoryMissingArgs = "[[Kategoria:Szablony nawigacyjne – brakujące parametry]]",
categoryEmptyArgs = "[[Kategoria:Szablony nawigacyjne – puste parametry]]",
categoryMissingWikilink = "[[Kategoria:Szablony nawigacyjne – spis bez linków]]",
listItem = "^[%*#:]",
wikilink = "%[%[ *%S[^\r\n]- *%]%]",
problemIndicator = '<sup class="problemy-w-navbox problemy">?</sup>',
suspectedIndicator = '<sup class="suspected problemy">!</sup>',
navboxInside = '^<([a-z]+) class="navbox ',
-- wzory wyrażeń regularnych
verificators = {
["nazwa"] = {
inverted = true,
patterns = {
"[%c#%[%]%{%}|<>_\127]", -- niedozwolone znaki
"^:", -- artykuły?
"^%.$",
"^%.%.$",
"^%./",
"^%.%./",
"/%./",
"/%.%./",
"/%.$",
"/%.%.$",
"~~+",
},
},
["tytuł"] = {
inverted = true,
patterns = {
-- pliki
"%[%[ *[Pp][Ll][Ii][Kk] *:.-%]%]",
"%[%[ *[Ff][Ii][Ll][Ee] *:.-%]%]",
-- listy
"^[%*#:]",
"\n[%*#:]",
},
},
["klasa"] = {
inverted = false,
patterns = {
"^[%w%-_ ]+$",
},
},
["lista"] = {
inverted = false,
patterns = {
"^[%*#:]",
"\n[%*#:]",
},
},
["tekst lub lista"] = {
inverted = false,
patterns = {
"%S", -- cokolwiek byle nie pusto
},
},
["grafika"] = {
inverted = false,
patterns = {
"%[%[ *[Pp][Ll][Ii][Kk] *:.-%]%]",
"%[%[ *[Ff][Ii][Ll][Ee] *:.-%]%]",
"%[%[ *[Gg][Rr][Aa][Ff][Ii][Kk][Aa] *:.-%]%]",
},
},
["zwijanie"] = {
inverted = false,
patterns = {
fullMatch(res.arg.collapsible.collapsed),
fullMatch(res.arg.collapsible.expanded),
fullMatch(res.arg.collapsible.auto),
fullMatch(res.arg.collapsible.disabled),
},
},
},
statsMessage = "Pozycje linkujące: $1, specjalne: $2, problemy$3: $4, '''RAZEM: $5'''",
suspectedMessage = " (podejrzane$1: $2)",
templateCats = {
args = { "kategoria", "kategoria2", "kategoria3", "kategoria4", "kategoria5", "kategoria6", },
ns = "Kategoria",
prefix = "Szablony nawigacyjne - ",
default = "Kategoria:Szablony nawigacyjne",
disabled = "nie",
},
sourceCatsPatterns = {
"%[%[ *[Kk][Aa][Tt][Ee][Gg][Oo][Rr][Ii][Aa] *: *([^|%[%]]-) *|[^|%[%]]-%]%]",
"%[%[ *[Kk][Aa][Tt][Ee][Gg][Oo][Rr][Ii][Aa] *: *([^|%[%]]-) *%]%]",
"%[%[ *[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy] *: *([^|%[%]]-) *|[^|%[%]]-%]%]",
"%[%[ *[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy] *: *([^|%[%]]-) *%]%]",
},
brPattern = "<[bB][Rr] ?/?>",
suspectedText = {
'•', '•', '•', '•',
'·', '·', '·', '·',
'∙', '∙', '∙',
},
brackets = {
pattern = "[%(%)%[%]]",
['('] = ')',
['['] = ']',
[')'] = '(',
[']'] = '[',
}
}
local function printStatistics(builder, diagItems)
local wikilinks = 0
local nowikis = 0
local problems = 0
local suspected = 0
for k, v in pairs(diagItems) do
wikilinks = wikilinks + v.wikilinks
nowikis = nowikis + v.nowikis
problems = problems + v.problems
suspected = suspected + v.suspected
end
--local lang = mw.getContentLanguage()
local message = mw.message.newRawMessage(diag.statsMessage)
:numParams(wikilinks, nowikis)
:rawParams(diag.problemIndicator)
:numParams(problems, wikilinks + nowikis + problems)
local report = builder:tag('div')
:addClass(diag.classStats)
:wikitext(message:plain())
if suspected > 0 then
local message = mw.message.newRawMessage(diag.suspectedMessage)
:rawParams(diag.suspectedIndicator)
:numParams(suspected)
report:wikitext(message:plain())
end
report:wikitext(problems > 0 and diag.categoryProblems or nil)
report:wikitext(suspected > 0 and diag.categorySuspected or nil)
if wikilinks == 0 then
report:wikitext(diag.categoryWikilinks0)
elseif wikilinks == 1 then
report:wikitext(diag.categoryWikilinks1)
elseif wikilinks == 2 then
report:wikitext(diag.categoryWikilinks2)
elseif wikilinks == 3 then
report:wikitext(diag.categoryWikilinks3)
elseif wikilinks == 4 then
report:wikitext(diag.categoryWikilinks4)
elseif (wikilinks + nowikis + problems) > 500 then
report:wikitext(diag.categoryLargeList)
end
end
local function printListWithoutWikilinks(report, diagItems)
local nowikilinks = {}
for k, v in pairs(diagItems) do
if (v.wikilinks <= 0) and mw.ustring.match(k, '^'..res.arg.list.name..'%d') then
table.insert(nowikilinks, k)
end
end
if #nowikilinks > 0 then
report:newline():wikitext("; brak wikilinków: ", #nowikilinks, diag.categoryMissingWikilink)
for i, v in ipairs(nowikilinks) do
report:newline():wikitext(":* ", v)
end
end
end
local function printNested(report, diagItems)
--mw.logObject(diagItems, "nested")
local nested = {}
for k, v in pairs(diagItems) do
if v.inside then
table.insert(nested, k)
end
end
if #nested > 0 then
report:newline():wikitext("; zagnieżdżone szablony nawigacyjne: ", #nested, diag.categoryNavboxInside)
for i, v in ipairs(nested) do
report:newline():wikitext(":* ", v)
end
end
end
local function printWikicodeAnalyze(report)
local contents = mw.title.getCurrentTitle():getContent()
--mw.logObject(contents, 'contents')
local text = contents or "" -- pusty tekst jeśli nie ma strony
-- gumkowanie
text = string.gsub(text, "<!%-%-.-%-%->", '')
text = string.gsub(text, "<nowiki>.-</nowiki>", '')
text = string.gsub(text, "<math>.-</math>", '')
text = string.gsub(text, "<pre>.-</pre>", '')
text = string.gsub(text, "<noinclude>.-</noinclude>", '')
text = string.gsub(text, "<includeonly>(.-)</includeonly>", '%1')
--mw.logObject(text, 'text')
local cleanContents = text
-- 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
local paramPos = {}
local templPos = {}
local ob = string.byte('{')
local cb = string.byte('}')
for _, startPos in ipairs(FindPositionsInReverseOrder(text, "{{")) do
local endPos = string.find(text, "}}", startPos, true)
local len = endPos and (endPos - startPos + 2) or 2
local sPos = startPos
if (startPos > 1) and ((startPos + len) <= #text) and (string.byte(text, startPos + 2) == ob) and (string.byte(text, startPos + len) == cb) then
-- parametr szablonu
len = len + 1
paramPos[startPos] = len
elseif len ~= 2 then
templPos[startPos] = len
end
-- usuń szablony zawarte wewnątrz znaleziska
local inside = {}
local ePos = sPos + len
for s, l in pairs(templPos) do
local e = s + l
if (s > sPos) and (s < ePos) and (e > sPos) and (e < ePos) then
table.insert(inside, s)
end
end
for i, v in ipairs(inside) do
templPos[v] = nil
end
-- zarejestruj pozycję znaleziska
text = RemoveInPlace(text, sPos, len)
end
local notFound = 10000000000
local params = {}
for k, v in pairs(paramPos) do
local e1 = string.find(cleanContents, "|", k, true) or notFound
local e2 = string.find(cleanContents, "\n", k, true) or notFound
local e3 = string.find(cleanContents, "}}}", k, true) or notFound
local e = math.min(e1, e2, e3)
assert(e < notFound)
assert(e > (k + 2))
local paramname = mw.text.trim(string.sub(cleanContents, k + 3, e - 1))
params[paramname] = true
end
local paramnames = loadKeys(params)
local templates = {}
for k, v in pairs(templPos) do
local e1 = string.find(cleanContents, "|", k, true) or notFound
local e2 = string.find(cleanContents, "\n", k, true) or notFound
local e3 = string.find(cleanContents, "}}", k, true) or notFound
local e = math.min(e1, e2, e3)
local p1 = false
if (e3 < notFound) and (e1 < e3) then
local e11 = string.find(cleanContents, "|", e1 + 1, true) or e3
p1 = mw.text.trim(string.sub(cleanContents, e1+1, e11-1))
end
assert(e < notFound)
assert(e > (k + 2))
local templateName = mw.text.trim(string.sub(cleanContents, k + 2, e - 1))
local invokeName = mw.ustring.match(templateName, "^#invoke:%s*(.+)$")
if invokeName and p1 then
templateName = "#invoke:"..mw.title.new(invokeName, "Module").text..'|'..p1
end
table.insert(templates, {
start = k,
len = v,
name = templateName,
})
end
report:newline():wikitext("; definicja szablonu")
if #templates == 1 then
local template = templates[1]
report:newline():wikitext(":"):tag('code'):wikitext(template.name)
if template.start > 1 then
local before = mw.text.nowiki(mw.text.trim(string.sub(cleanContents, 1, template.start - 1)))
if #before > 0 then
report:newline():wikitext(": znaleziono treść przed szablonem")
:newline():wikitext(":*"):tag('code'):wikitext(before)
else
report:newline():wikitext(": znaleziono odstęp przed szablonem")
end
report:wikitext(diag.categoryCheckWikicode)
end
local endPos = template.start + template.len
--mw.logObject(endPos, 'endPos')
--mw.logObject(#cleanContents, '#cleanContents')
if (endPos == #cleanContents) and (string.sub(cleanContents, endPos, endPos) == '\n') then
report:newline():wikitext(": znaleziono znak nowej linii za szablonem")
elseif endPos <= #cleanContents then
local after = mw.text.nowiki(mw.text.trim(string.sub(cleanContents, endPos)))
if #after > 0 then
report:newline():wikitext(": znaleziono treść za szablonem")
:newline():wikitext(":*"):tag('code'):wikitext(after)
else
report:newline():wikitext(": znaleziono odstęp za szablonem")
end
report:wikitext(diag.categoryCheckWikicode)
end
elseif #templates < 1 then
local text = mw.text.trim(cleanContents)
if #text > 0 then
report:newline():wikitext(": znaleziono jakąś treść zamiast szablonu")
else
report:newline():wikitext(": nie znaleziono żadnego szablonu")
end
report:wikitext(diag.categoryCheckWikicode)
else
report:newline():wikitext(": znaleziono wywołanie wielu szablonów", diag.categoryCheckWikicode)
for i, t in ipairs(templates) do
report:newline():wikitext(":*"):tag('code'):wikitext(t.name)
end
end
if #paramnames > 0 then
report:newline():wikitext("; wykryto parametry")
for i, v in ipairs(paramnames) do
report:newline():wikitext(':'):tag('code'):wikitext(v)
end
end
end
local function printTemplateCategories(report, categories)
local pagename = mw.title.getCurrentTitle().text
report:newline():wikitext("; zadeklarowane kategorie: ")
if categories == false then
report:wikitext("''wyłączone''")
else
local count = 0
for k, v in pairs(categories) do
count = count + 1
end
if count <= 0 then
report:wikitext("''brak''", '[[', diag.templateCats.default, '|', pagename, ']]')
else
report:wikitext(count)
local nameIndex = mw.ustring.len(diag.templateCats.ns)
+ mw.ustring.len(diag.templateCats.prefix)
+ 2
for v, s in pairs(categories) do
report:newline():wikitext(':*', mw.ustring.sub(v, nameIndex), '[[', v, '|', s, ' ]]')
if #s == 0 then
report:wikitext(' '):tag('small'):wikitext('(pusty klucz)')
elseif s ~= pagename then
report:wikitext(' '):tag('small'):wikitext('(klucz: ', s, ')')
end
end
end
end
end
local function printSourceCategories(report)
local function print(description, content)
if not content then
return
end
local categories = {}
for i, pattern in ipairs(diag.sourceCatsPatterns) do
for c in mw.ustring.gmatch(content, pattern) do
local title = mw.title.makeTitle(diag.templateCats.ns, c)
if title then
table.insert(categories, title.text)
end
end
end
report:newline():wikitext("; ", description, " : ", #categories)
for i, v in ipairs(categories) do report:newline():wikitext(':*', v) end
end
local content = mw.title.getCurrentTitle():getContent() or ""
print('kategorie w kodzie', content)
local docTitle = mw.title.getCurrentTitle():subPageTitle(res.aux.docSubpageText)
if docTitle and docTitle.exists then
print('kategorie w dokumentacji', docTitle:getContent())
end
local otherDoc = mw.ustring.match(content, "{{ *[Dd]okumentacja *| *([^|%[%]]-/opis) *}}")
if otherDoc then
local otherDocTitle = mw.title.new(otherDoc)
if otherDocTitle then
print('kategorie w dołączonej dokumentacji', otherDocTitle:getContent())
end
end
end
local function printLogSummary(report, printlog)
if printlog.levels then
report:newline():wikitext("; głębokość drzewa :", printlog.levels)
end
if printlog.leafs then
report:newline():wikitext("; liczba liści :", printlog.leafs)
end
if printlog.notree then
report:newline():wikitext("; drzewo : ''nie''")
end
if printlog.example then
report:newline():wikitext("; przykład : ''tak''")
end
if printlog.pionowy then
report:wikitext(diag.categoryVertical)
end
if printlog.cols then
report:newline():wikitext("; liczba kolumn :", printlog.cols)
if printlog.cols > 3 then
report:wikitext(diag.categoryManyColumns)
end
end
if printlog.allCols then
report:newline():wikitext("; liczba wszystkich komórek kolumnowych :", printlog.allCols)
end
if printlog.templateClassName then
report:newline():wikitext("; prywatny CSS")
report:newline():wikitext(": ", printlog.templateClassName)
if printlog.privateCSS then
report:newline():wikitext(": [[", printlog.privateCSS, "|styles.css]]", diag.categoryCSS)
end
end
if printlog.unknownClasses then
report:newline():wikitext("; nieużywane klasy", diag.categoryUnknownArgs)
for i, v in ipairs(printlog.unknownClasses) do
report:newline():wikitext(": ", #v <= 0 and "''pusta''" or v)
end
end
end
local function printEmptyArguments(report, argsTree)
local result = {}
for k, v in pairs(argsTree.args) do
if not v.value or (#v.value <= 0) then
table.insert(result, k)
end
end
if #result <= 0 then
return
end
report:newline():wikitext("; puste pola", diag.categoryEmptyArgs)
for i, v in ipairs(result) do
report:newline():wikitext(": ", v)
end
end
local function printUnverifiedArguments(report, argsTree)
local result = {}
for k, v in pairs(argsTree.args) do
if argsTree.used[k] and not v.verified then
table.insert(result, k)
end
end
if #result <= 0 then
return
end
report:newline():wikitext("; nieprawidłowe pola", diag.categoryUnverifiedArgs)
for i, v in ipairs(result) do
report:newline():wikitext(": ", v)
end
end
local function printUnknownArguments(report, argsTree)
local result = {}
for k, v in pairs(argsTree.args) do
if not v.recognized and not v.obsolete and not argsTree.used[k] then
table.insert(result, k)
end
end
if #result <= 0 then
return
end
report:newline():wikitext("; nieznane pola", diag.categoryUnknownArgs)
for i, v in ipairs(result) do
report:newline():wikitext(": ", v)
end
end
local function printUnusedArguments(report, argsTree)
local result = {}
local cat = false
for k, v in pairs(argsTree.args) do
if (#v.value > 0) and not argsTree.used[k] and (v.recognized or v.obsolete) then
cat = k ~= res.arg.collapsible.name -- omiń ponad 10k wywołań
table.insert(result, k)
end
end
if #result <= 0 then
return
end
report:newline():wikitext("; nieużywane pola", cat and diag.categoryUnusedArgs or '')
for i, v in ipairs(result) do
report:newline():wikitext(": ", v)
end
end
local function printMissingArguments(report, missing)
local result = {}
for k, v in pairs(missing) do
table.insert(result, k)
end
if #result <= 0 then
return
end
report:newline():wikitext("; brakujące pola", diag.categoryMissingArgs)
for i, v in ipairs(result) do
report:newline():wikitext(": ", v)
end
end
local function printTestListDescriptions(report, tree)
local direct = {}
local parent = {}
local function argName(node)
local address = string.sub(node.address(), 2)
return res.arg.list.name..string.gsub(address, '_', '.')
end
local function parseNode(node)
if #node <= 0 then
-- liści nie obrabiamy
return
end
local suspected = {}
for i, n in ipairs(node) do
if not n.peek(res.arg.group.name) and n.peek(res.arg.list.name) then
table.insert(suspected, i)
end
end
if #suspected > 1 then
for i, v in ipairs(suspected) do
table.insert(direct, argName(node[v]))
end
elseif (#suspected > 0) and node.address() and not node.peek(res.arg.group.name) then
table.insert(parent, argName(node[suspected[1]]))
end
for i, n in ipairs(node) do
parseNode(n)
end
end
parseNode(tree)
if (#direct <= 0) and (#parent <= 0) then
return
end
if #direct > 0 then
report:newline():wikitext("; nieopisany spis w grupie", diag.categoryAnonymousLists)
for i, v in ipairs(direct) do
report:newline():wikitext(": ", v)
end
end
if #parent > 0 then
report:newline():wikitext("; zagnieżdżony nieopisany spis", diag.categoryAnonymousLists)
for i, v in ipairs(parent) do
report:newline():wikitext(": ", v)
end
end
end
local function formatArgs(args)
local padindex = '................................................'
local orders = {
["nazwa"] = { p = 'A', s = '1', n = ' ', },
["tytuł"] = { p = 'A', s = '2', n = ' ', },
["klasa"] = { p = 'A', s = '3', n = ' ', },
["góra"] = { p = 'B', s = '1', n = '\n', },
["przed"] = { p = 'C', s = '1', n = ' ', },
["po"] = { p = 'C', s = '2', n = ' ', },
["grafika"] = { p = 'C', s = '3', n = ' ', },
["opis"] = { p = 'D', s = '1', n = ' ', },
["zwijanie"] = { p = 'D', s = '2', n = ' ', },
["spis"] = { p = 'D', s = '3', n = '\n', },
["dół"] = { p = 'E', s = '1', n = '\n', },
[false] = { p = 'Z', s = '1', n = ' ', },
}
local list = {}
local i = 0
for k, v in pairs(args) do
i = i + 1
local prefix, suffix = mw.ustring.match(k, "^(.-)([1-9][%.0-9]*)$")
if not prefix then
prefix = k
suffix = padindex
else
suffix = string.sub(suffix..padindex, 1, #padindex)
end
local ord = orders[prefix] or orders[false]
local item = {
o = string.format('%s-%s-%s-%08d', ord.p, suffix, ord.s, i),
k = k,
v = v,
n = ord.n,
}
table.insert(list, item)
end
table.sort(list, function(a,b) return a.o < b.o end)
local result = {}
for i, v in ipairs(list) do
table.insert(result, '| '..v.k..' ='..v.n..v.v..(v.n == '\n' and v.n or ''))
end
return table.concat(result, '\n')
end
local function verify(argInfo)
local verificator = diag.verificators[argInfo.recognized]
if verificator then
argInfo.verified = verificator.inverted
for i, v in ipairs(verificator.patterns) do
if mw.ustring.match(argInfo.value, v) then
argInfo.verified = not verificator.inverted
break
end
end
end
end
local function testBrackets(text)
local stack = {}
for b in mw.ustring.gmatch(text, diag.brackets.pattern) do
if (b == '(') or (b == '[') then
table.insert(stack, b)
elseif (b == ')') or (b == ']') then
if (#stack > 0) and stack[#stack] == diag.brackets[b] then
table.remove(stack, #stack)
else
return false -- brak otwartego nawiasu
end
end
end
return #stack == 0 -- oczekiwane zamknięte wszystkie nawiasy
end
local function check(text, br)
local lines = mw.text.split(text, '\n', true)
local wikilinks = 0
local nowikis = 0
local problems = 0
local suspected = 0
local result = {}
for i, v in ipairs(lines) do
local t = v
if not mw.ustring.match(v, diag.listItem) then
-- to nie jest wikilista
elseif mw.ustring.match(v, diag.wikilink) then
wikilinks = wikilinks + 1
elseif string.match(v,'\127') then
-- nowiki, ref, etc
nowikis = nowikis + 1
else
problems = problems + 1
t = v..diag.problemIndicator
end
if br and mw.ustring.match(v, diag.brPattern) then
suspected = suspected + 1
t = t..diag.suspectedIndicator
elseif not testBrackets(v) then
suspected = suspected + 1
t = t..diag.suspectedIndicator
else
-- zamieniam wikilinki na tekst do testowania
local s, c = string.gsub(v, "%[%[.-|(.-)%]%]", "%1") -- nie patrz w linki
local s, c = string.gsub(s, "%[%[[^|\n%[%]]+%]%]", "ok") -- lub zamień je na dobry tekst
for i, p in ipairs(diag.suspectedText) do
if mw.ustring.match(s, p, 1, true) then
suspected = suspected + 1
t = t..diag.suspectedIndicator
break
end
end
end
table.insert(result, t)
end
return {
value = table.concat(result,'\n'),
wikilinks = wikilinks,
nowikis = nowikis,
problems = problems,
suspected = suspected,
inside = string.match(lines[1], diag.navboxInside) and true or false,
}
end
local function argsService(templateContext)
local argsTree = {
args = {},
missing = {},
used = {},
diag = {},
}
local staticArgs = {}
local dynamicArgs = {}
for k, v in pairs(res.arg) do
if templateContext and templateContext.aliases then
local alias = templateContext.aliases[v.name]
if v.static and alias then staticArgs[alias] = v.static end
if v.dynamic and alias then dynamicArgs[alias] = v.dynamic end
end
if v.static then staticArgs[v.name] = v.static end
if v.dynamic then dynamicArgs[v.name] = v.dynamic end
if v.template and templateContext then staticArgs[v.name] = v.template end
end
local function add(k, v, prefix)
--mw.logObject({k, v, prefix}, "analyzeArg")
local argInfo = {
value = v,
recognized = staticArgs[k] or (prefix and dynamicArgs[prefix])
}
if argInfo.recognized then
verify(argInfo)
elseif templateContext and templateContext.obsolete then
argInfo.obsolete = prefix and templateContext.obsolete[prefix]
or (templateContext.obsolete[k] == false)
end
argsTree.args[k] = argInfo
--mw.logObject(argInfo, k)
end
local peekName = function(name)
if (not argsTree.args[name] or (#argsTree.args[name].value <= 0)) and templateContext and templateContext.aliases then
local alias = templateContext.aliases[name]
if alias and argsTree.args[alias] and (#argsTree.args[alias].value > 0) then
return alias
end
end
return name
end
local function peek(name)
--mw.logObject(name, "peek")
local name = peekName(name)
local arg = argsTree.args[name]
return (arg and (#arg.value > 0)) and arg.value or nil
end
local function use(name)
local name = peekName(name)
local arg = argsTree.args[name]
local result = arg and arg.value or nil
--mw.logObject({name, result}, "use")
argsTree.used[name] = (argsTree.used[name] or 0) + 1
return result
end
local function get(name)
local name = peekName(name)
local result = use(name)
if result == nil then
argsTree.missing[name] = (argsTree.missing[name] or 0) + 1
result = res.aux.missingArgNamePrefix..name..res.aux.missingArgNameSuffix
elseif not argsTree.diag[name] then
local br = mw.ustring.match(name, '^'..res.arg.list.name..'%d')
argsTree.diag[name] = check(result, br)
result = argsTree.diag[name].value
end
--mw.logObject({name, result}, "get")
return result
end
local function dump()
local buffer = {}
for k, v in pairs(argsTree.args) do
buffer[k] = v.value
end
return mw.text.jsonEncode(buffer)
end
local function loadTemplateCategories()
local pagename = mw.title.getCurrentTitle().text
local map = {}
for i, argName in ipairs(diag.templateCats.args) do
if i > 1 then -- piersza inaczej
local catName = peek(argName)
if catName and (#catName > 0) then
local name, sort = mw.ustring.match(catName, "^(.-)%s*|%s*(.*)$")
if not name then
name = catName
sort = pagename
end
local categoryTitle = mw.title.makeTitle(diag.templateCats.ns, diag.templateCats.prefix..name)
if categoryTitle and (#categoryTitle.fragment <= 0) and not map[categoryTitle.fullText] then
use(argName)
argsTree.args[argName].verified = true
map[categoryTitle.fullText] = sort
end
end
end
end
local cat1arg = diag.templateCats.args[1]
local cat1 = peek(cat1arg)
if cat1 == diag.templateCats.disabled then
use(cat1arg)
argsTree.args[cat1arg].verified = true
for k, v in pairs(map) do
return map
end
return false
end
if cat1 and (#cat1 > 0) then
local name, sort = mw.ustring.match(cat1, "^(.-)%s*|%s*(.*)$")
if not name then
name = cat1
sort = pagename
end
local categoryTitle = mw.title.makeTitle(diag.templateCats.ns, diag.templateCats.prefix..name)
if categoryTitle and (#categoryTitle.fragment <= 0) and not map[categoryTitle.fullText] then
use(cat1arg)
argsTree.args[cat1arg].verified = true
map[categoryTitle.fullText] = sort
end
end
return map
end
local function diagnosticView (builder, printlog, tree)
printStatistics(builder, argsTree.diag)
local summaryReport = mw.html.create('div')
:addClass('navbox-summary')
:addClass("mw-collapsible mw-collapsed")
summaryReport:tag('div')
:addClass('title')
:wikitext('Informacje diagnostyczne')
local report = summaryReport:tag('div')
--:addClass('hlist')
:addClass('mw-collapsible-content')
if printlog.badName then
report:wikitext(diag.categoryBadName)
end
printWikicodeAnalyze(report)
if printlog.useTemplateCategories then
printTemplateCategories(report, loadTemplateCategories())
end
printSourceCategories(report)
report:newline():wikitext('----')
printLogSummary(report, printlog)
report:newline():wikitext('----')
printListWithoutWikilinks(report, argsTree.diag)
printEmptyArguments(report, argsTree)
printUnverifiedArguments(report, argsTree)
printUnusedArguments(report, argsTree)
printUnknownArguments(report, argsTree)
printMissingArguments(report, argsTree.missing)
printNested(report, argsTree.diag)
if tree then
printTestListDescriptions(report, tree)
end
local argsReport = ''
local formattedArgs = formatArgs(mw.text.jsonDecode(dump()))
if formattedArgs and (#formattedArgs > 0) then
local report = mw.html.create('div')
:addClass('navbox-summary')
:addClass("mw-collapsible mw-collapsed")
report:tag('div')
:addClass('title')
:wikitext('Kanoniczne zestawienie parametrów')
local content = mw.getCurrentFrame():extensionTag('pre', formattedArgs, {class='mw-collapsible-content'})
report:wikitext(content)
argsReport = tostring(report)
end
local navbox = tostring(builder)
local details = tostring(summaryReport)
local catReport = ''
local function hideCategories()
local currentTitle = mw.title.getCurrentTitle()
if currentTitle.isTalkPage then
return true
elseif currentTitle.namespace ~= 2 then
return false
else -- Wikipedysta - może programista?
local navboxDeveloper = mw.title.makeTitle(2, currentTitle.rootText..'/navbox-developer')
return not navboxDeveloper or not navboxDeveloper.exists
end
end
if hideCategories() then
local categories = {}
local function extractCategories(text)
local function foundCat(category)
table.insert(categories, category)
return ''
end
local t1, c1 = mw.ustring.gsub(text, diag.sourceCatsPatterns[1], foundCat)
local t2, c2 = mw.ustring.gsub(t1, diag.sourceCatsPatterns[2], foundCat)
return t2
end
navbox = extractCategories(navbox)
details = extractCategories(details)
if #categories > 0 then
local report = mw.html.create('div')
:addClass('navbox-summary')
:addClass("mw-collapsible mw-collapsed")
report:tag('div')
:addClass('title')
:wikitext('Kategorie')
local content = report:tag('div')
:addClass('mw-collapsible-content')
for i, v in ipairs(categories) do
content:newline():wikitext('*', '[[:Kategoria:', v, ']]')
end
content:newline()
catReport = tostring(report)
end
end
local result = navbox..details..argsReport..catReport
return result
end
return {
add = add,
peek = peek,
use = use,
get = get,
dump = dump,
diagnosticView = diagnosticView,
}
end
return {
argsService = argsService,
diagnosticView = function(builder, args, printlog)
return args.diagnosticView(builder, printlog, args.tree and args.tree() or nil)
end,
verifyTemplateName = function(currentTitle, expectedTitle, templateName)
local content = currentTitle:getContent()
if not content then
mw.log("Navbox:verifyTemplateName: brak zawartości strony")
return false
end
mw.logObject(templateName, "Navbox:verifyTemplateName: templateName")
local navboxTemplate = templateMatch(templateName)
mw.logObject(navboxTemplate, "Navbox:verifyTemplateName: navboxTemplate")
local s, e = mw.ustring.find(content, navboxTemplate, 1)
if not s then
mw.log("Navbox:verifyTemplateName: myślę, że jest ok, bo tu nie widzę kodu szablonu nawigacyjnego")
return true
end
local exists1 = function(pattern)
local s, e = mw.ustring.find(content, pattern, s)
if not s then
return 0
end
local s, e = mw.ustring.find(content, pattern, e)
if not s then
return 1
end
return 2
end
if 1 == exists1("|%s*nazwa%s*=%s*{{%s*#invoke:Navbox%s*|%s*Name%s*}}%s*[|}]") then
mw.log("Navbox:verifyTemplateName: myślę, że jest ok, automatyczna nazwa jest tylko raz -> true")
return true
end
mw.logObject(expectedTitle, "Navbox:verifyTemplateName: zadeklarowana nazwa w szablonie")
mw.logObject(currentTitle, "Navbox:verifyTemplateName: obrabiana strona")
-- w naszym szablonie oczekuję jednej nazwy
-- w przeciwnym razie nie oczekuję żadnej nazwy
local expectedCount = mw.title.equals(currentTitle, expectedTitle) and 1 or 0
mw.logObject(expectedCount, "Navbox:verifyTemplateName: oczekiwana liczba wystąpień podanej nazwy w szablonie")
local name = mw.ustring.gsub(expectedTitle.text, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" );
local pattern = ((expectedTitle.namespace == 10) or (0 < exists1("|%s*przestrzeń%s*=%s*"..expectedTitle.nsText.."%s*[|}]")))
and ("|%s*nazwa%s*=%s*"..name.."%s*[|}]") -- zwykła nazwa (w szablonie lub jawnie zadeklarowanej przestrzeni)
or ("|%s*nazwa%s*=%s*"..expectedTitle.nsText..":"..name.."%s*[|}]") -- pełna nazwa (w szablonie w innej przestrzeni)
mw.logObject(pattern, "Navbox:verifyTemplateName: szukam nazwy w szablonie według wzoru")
local count = exists1(pattern)
mw.logObject(count, "Navbox:verifyTemplateName: liczba wyników wyszukiwania")
return expectedCount == count
end,
}