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, }