UWAGA |
---|
Większość artykułów w portalu to nasze własne teksty z kluczowych dziedzin związanych z naszą misją. Spora część materiałów pochodzi też z polskiej wersji Wikipedii, gdzie były odrzucone ze względu na politykę redaktorów (przeczytaj o krytyce Wikipedii). Są też i takie, które zostały przeniesione na nasze strony, gdyż stanowią istotne uzupełnienie merytorycznej treści naszego serwisu. Wszystkie artykuły podlegają edycji przez naszych Użytkowników, dlatego ich wersje mogą się różnić od prezentowanych na innych witrynach. |
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,
}