Moduł:Navbox
Przejdź do nawigacji
Przejdź do wyszukiwania
Dokumentacja dla tego modułu może zostać utworzona pod nazwą Moduł:Navbox/opis
Błąd skryptu: Błąd Lua: Nie można utworzyć procesu: proc_open(/dev/null): failed to open stream: Operation not permitted
require ("Moduł:No globals") local res = mw.loadData('Moduł:Navbox/res') local function encodeClass(name) local t = mw.getContentLanguage():lcfirst(name) local s = mw.ustring.gsub(t, ".", { ['ł'] = 'l', ['Ł'] = 'L', ['_'] = ' '}) -- wstępne zmiany ł->l i _-> spacja local p = mw.ustring.gsub(s, "%p+", "-") -- znaczki nieliterowe na minusy local q = mw.ustring.gsub(p, "%s+", "_") -- odstępy na podkreślenia local r = mw.ustring.toNFD(q) -- wyodrębnij diakrytyki local e = string.gsub(r,"[\127-\255]+",'') -- usuń to czego nie ma w ASCII return e end local function getPrinter(name) local printer = res.printers[name] return printer and require(printer) or nil end local function printSubTree(container, tree, currentPrinter, printlog) local function printList(container, node, collapsibleContent) local mwCCC = collapsibleContent and 'mw-collapsible-content' or nil if #node <= 0 then if printlog then printlog.printedLeafs = (printlog.printedLeafs or 0) + 1 end local leaf if (currentPrinter.leaf == 'table') and mwCCC then -- zwijanie tabelki i skórka timeless się gryzą leaf = container:tag('div') :addClass(mwCCC) :tag(currentPrinter.leaf) elseif currentPrinter.leaf then leaf = container:tag(currentPrinter.leaf) :addClass(mwCCC) else leaf = container :addClass(mwCCC) end if currentPrinter.update then currentPrinter.update(leaf, true, node, printlog) end leaf :addClass(node.odd()) :addClass(node.even()) :newline() :wikitext(node.get(res.arg.list.name)) :newline() else local subprinter = getPrinter(node.peek(res.arg.list.name)) if subprinter then node.use(res.arg.list.name) else subprinter = getPrinter(true) end local subtag = subprinter.root or subprinter.leaf or 'div' local subtree = ((subtag == 'table') and mwCCC) and container:tag('div'):addClass(mwCCC):tag(subtag) -- zwijanie tabelki i skórka timeless się gryzą or container:tag(subtag):addClass(mwCCC) if currentPrinter.update then currentPrinter.update(subtree, false, node, printlog) end printSubTree(subtree, node, subprinter, printlog) end end currentPrinter.print(container, tree, printList, printlog) end local function argsService(templateContext) local args = {} local function add(k, v, prefix) if v and #v > 0 then args[k] = v end end local peekName = function(name) if not args[name] and templateContext and templateContext.aliases then local alias = templateContext.aliases[name] if alias and args[alias] then return alias end end return name end local function peek(name) return args[peekName(name)] end local function get(name) return peek(peekName(name)) or (res.aux.missingArgNamePrefix..name..res.aux.missingArgNameSuffix) end local function dump() return mw.text.jsonEncode(args) end return { add = add, peek = peek, use = peek, get = get, dump = dump, } end local function loadArgsTree(args, printlog, templateContext) local dynamicArgs = {} for k, v in pairs(res.arg) do if templateContext and templateContext.aliases then local alias = templateContext.aliases[v.name] if v.dynamic and alias then dynamicArgs[alias] = v.dynamic end end if v.dynamic then dynamicArgs[v.name] = v.dynamic end end local splitArgName = function(name) if type(name) ~= "string" then --mw.logObject(name, "to nie jest tekst") return false, nil end local prefix, suffix = mw.ustring.match(name, "^(.-)([1-9][%.0-9]*)$") if not prefix or not dynamicArgs[prefix] then --mw.logObject(name, "wzór nie pasuje lub nierozpoznany") return false, nil end local keys = mw.text.split(suffix,'.',true) for i = 1, #keys do keys[i] = tonumber(keys[i]) if not keys[i] or (keys[i] == 0) then --mw.logObject({name, keys, i, keys[i]}, "wzór ma błędy") return false, nil end end return prefix, keys end local updateIndex = function(node, k) node.index = node.index or {} for i, v in ipairs(node.index) do if v == k then return end end table.insert(node.index, k) table.sort(node.index) end local argsTree = not printlog and argsService(templateContext) or require('Moduł:Navbox/diag').argsService(templateContext) local argsTree_add = argsTree.add argsTree.add = nil local argsTree_tree = nil local tree = function() if not argsTree_tree or (#argsTree_tree <= 0) then return nil end local function createNode(v) local peekName = function(name) if not v.address then return nil end if argsTree.peek(name..v.address) then return name..v.address end if templateContext and templateContext.aliases then local alias = templateContext.aliases[name] if alias and peek(alias..v.address) then return alias..v.address end end return nil end local node = { address = function() return v.address and "a"..string.gsub(v.address, '%.', '_') or nil end, peek = function(name) return peekName(name) and argsTree.peek(peekName(name)) or (templateContext and templateContext.defaults and templateContext.defaults[name]) end, use = function(name) return peekName(name) and argsTree.use(peekName(name)) or nil end, get = function(name) return peekName(name) and argsTree.get(peekName(name)) or nil end, odd = function() return v.odd and res.class.odd or nil end, even = function() return v.even and res.class.even or nil end, } local function calculateTest() local pattern = mw.loadData("Moduł:Navbox/title").wikilinkPattern local s1 = argsTree.peek(res.arg.group.name..v.address) if s1 and mw.ustring.match(s1, pattern) then return true end local s2 = argsTree.peek(res.arg.list.name..v.address) if s2 and mw.ustring.match(s2, pattern) then return true end for i, n in ipairs(node) do if n.test(pattern) then return true end end return false end local testCache node.test = function() if testCache == nil then testCache = calculateTest() end return testCache end return node end local function buildTree(buffer, tree) for i, v in ipairs(tree.index) do local data = tree[v] local node = createNode(data) table.insert(buffer, node) if data.index then buildTree(node, data) end end end local rootNode = createNode({}) buildTree(rootNode, argsTree_tree) return rootNode end local function analyzeArg(k, v, prefix, keys) argsTree_add(k, v, prefix) if prefix and v and (#v > 0) then argsTree_tree = argsTree_tree or {} local node = argsTree_tree for i = 1, #keys do local k = keys[i] local child = node[k] updateIndex(node, k) if not child then child = { address = node.address and (node.address..'.'..tostring(k)) or tostring(k), } node[k] = child end node = child end end end for k, v in pairs(args) do local prefix, keys = splitArgName(k) local json, subargs if (prefix == res.arg.list.name) and v and (#v > 0) then json, subargs = pcall(mw.text.jsonDecode, v) end if json then --analyzeArg(k, '* szablon *', prefix, keys) for vk, vv in pairs(subargs) do local vprefix, vkeys = splitArgName(vk) if not vprefix and (vk == res.arg.list.name) then vprefix = vk vkeys = {} end if vprefix and prefix then local newKeys = {} for j, u in ipairs(keys) do table.insert(newKeys, u) end for j, u in ipairs(vkeys) do table.insert(newKeys, u) end local n = {} for j, u in ipairs(newKeys) do table.insert(n, tostring(u)) end local name = vprefix..table.concat(n, '.') analyzeArg(name, vv, vprefix, newKeys) end end else analyzeArg(k, v, prefix, keys) end end if templateContext and getPrinter(templateContext.list) then analyzeArg(res.arg.list.name, templateContext.list, nil, nil) end if argsTree_tree then local tree = argsTree_tree local function loadLeafNodes(tree, buffer, level) if not tree.index then table.insert(buffer, tree) else local n = level for i, v in ipairs(tree.index) do local k = loadLeafNodes(tree[v], buffer, level + 1) if k > n then n = k end end level = n end return level end local buffer = {} local levels = loadLeafNodes(tree, buffer, 0) for i, v in ipairs(buffer) do v.odd = (i % 2) == 1 v.even = (i % 2) == 0 end if printlog then printlog.levels = levels printlog.leafs = #buffer end end argsTree.tree = tree --mw.logObject(printlog, 'printlog') --mw.logObject(argsTree, 'argsTree') return argsTree end local function drawMiniNavBar(container, title, tags) local pde = container:tag('ul') :addClass('tnavbar') :addClass('noprint') :addClass('plainlinks') :addClass('hlist') -- p local p = pde:tag('li'):wikitext("[[", title.nsText, ':', title.text, '|') p:tag('span'):attr('title', res.navbar.p):wikitext(tags.p) p:wikitext(']]') -- d if not title.isTalkPage then local tt = title.talkPageTitle local d = pde:tag('li'):wikitext("[[", tt.nsText, ':', tt.text, '|') d:tag('span'):attr('title', res.navbar.d):wikitext(tags.d) d:wikitext(']]') end -- e pde:tag('li') :attr('title', res.navbar.e) :wikitext('[', title:fullUrl("action=edit"), ' ', tags.e, ']') -- U if mw.title.equals(title, mw.title.getCurrentTitle()) and (title.namespace == 10) then local fullpagenamee = mw.uri.encode(title.fullText, "WIKI") pde:tag('li') :attr('title', res.navbar.U) :wikitext('[https://tools.wmflabs.org/templatetransclusioncheck/index.php?lang=pl&name=', fullpagenamee, ' ', tags.U, ']') end end local function splitCustomClasses(customClasses, navboxName) if not customClasses then return {} end local result = {} local cc = mw.text.split(customClasses,"%s+") for i, v in ipairs(cc) do result[v] = res.validExtraClasses[v] ~= nil end -- pionowy szablon tylko na początku artykułu if result.pionowy and navboxName then local title = mw.title.getCurrentTitle() if title and title.namespace == 0 then local content = title:getContent() if content then local navboxStart = mw.ustring.find(content, "{{%s*"..mw.ustring.gsub( navboxName, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" ).."%s*}}") if navboxStart then local firstSectionStart = mw.ustring.find(content, "\n==.-==[ \t]*\n") if firstSectionStart and (firstSectionStart < navboxStart) then mw.logObject(result, "splitCustomClasses KASUJĘ pionowy bo nie jest na początku artykułu") result.pionowy = false end end end end end return result end local function makeContainer(args, title, contentTag, printlog) local templateClassName = (title and (title.namespace > 0) and not title.isTalkPage) and encodeClass(title.namespace == 10 and title.text or title.fullText) or nil local builder = mw.html.create('div') :addClass(res.class.navbox) :addClass('do-not-make-smaller') local classes = splitCustomClasses(args.use(res.arg.class.name), args.peek(res.arg.name.name)) for c, valid in pairs(classes) do builder:addClass((valid and res.validExtraClasses[c]) and c or nil) end if title and mw.title.equals(title, mw.title.getCurrentTitle()) or (classes[templateClassName] ~= nil) then builder:addClass(templateClassName and res.class.name..templateClassName or nil) end builder:wikitext(mw.getCurrentFrame():extensionTag( 'templatestyles', '', {src = "Szablon:Navbox/styles.css"})) local privateCSS = false if classes[templateClassName] ~= nil then privateCSS = tostring(title.fullText.."/styles.css") builder:wikitext(mw.getCurrentFrame():extensionTag( 'templatestyles', '', {src = privateCSS})) end if not classes.pionowy then builder:addClass('mw-collapsible'):attr('data-expandtext', res.aux.expandText):attr('data-collapsetext', res.aux.collapseText) local collapse = function() if args.peek(res.arg.collapsible.name) == res.arg.collapsible.collapsed then return 'mw-collapsed' end if mw.title.getCurrentTitle().namespace ~= 10 then return 'autocollapse' end return nil end if title then builder:addClass(not mw.title.equals(title, mw.title.getCurrentTitle()) and collapse() or nil) drawMiniNavBar(builder, title, res.navbar.mini) else builder :addClass(mw.title.getCurrentTitle().namespace ~= 10 and collapse() or nil) :tag('span'):addClass(res.navbar.fake) end end builder:tag('div') :addClass(res.class.caption) :wikitext(args.get(res.arg.title.name)) local content if not args.peek(res.arg.above.name) and not args.peek(res.arg.below.name) and not args.peek(res.arg.before.name) and not args.peek(res.arg.after.name) and not classes.pionowy then if contentTag == 'table' then -- zwijanie tabeli gryzie się ze skórką timeless content = builder:tag('div') :addClass('mw-collapsible-content') :tag(contentTag) else content = builder:tag(contentTag) :addClass('mw-collapsible-content') end elseif not args.peek(res.arg.above.name) and not args.peek(res.arg.below.name) and not classes.pionowy then local flex = builder:tag('div') :addClass('mw-collapsible-content') :addClass(res.class.flex) if args.peek(res.arg.before.name) then flex:tag('div'):addClass(res.class.before):newline():wikitext(args.get(res.arg.before.name)):newline() end content = flex:tag(contentTag) if args.peek(res.arg.after.name) then flex:tag('div'):addClass(res.class.after):newline():wikitext(args.get(res.arg.after.name)):newline() end else local content1 = builder:tag('div') :addClass('mw-collapsible-content') if args.peek(res.arg.above.name) then content1:tag('div'):addClass(res.class.hlist):addClass(res.class.above):newline():wikitext(args.get(res.arg.above.name)):newline() end local flex = (not classes.pionowy and ((args.peek(res.arg.before.name) or args.peek(res.arg.after.name)))) and content1:tag('div'):addClass(res.class.flex) or content1 if args.peek(res.arg.before.name) then flex:tag('div'):addClass(res.class.before):newline():wikitext(args.get(res.arg.before.name)):newline() end content = flex:tag(contentTag) if args.peek(res.arg.after.name) then flex:tag('div'):addClass(res.class.after):newline():wikitext(args.get(res.arg.after.name)):newline() end if (title and classes.pionowy) or args.peek(res.arg.below.name) then local below = content1:tag('div'):addClass(res.class.hlist):addClass(res.class.below) if args.peek(res.arg.below.name) then below:newline():wikitext(args.get(res.arg.below.name)):newline() end if title and classes.pionowy then if args.peek(res.arg.below.name) then below:wikitext("----"):newline() end drawMiniNavBar(below, title, res.navbar.short) end end end content:addClass(res.class.main) for c, valid in pairs(classes) do content:addClass((valid and not res.validExtraClasses[c]) and c or nil) end if printlog then printlog.pionowy = classes.pionowy printlog.templateClassName = templateClassName printlog.privateCSS = privateCSS for c, valid in pairs(classes) do if not valid and (c ~= templateClassName) then local u = printlog.unknownClasses or {} table.insert(u, c) printlog.unknownClasses = u end end end return builder, content end local function createNavbox(args, title, printlog) local rootPrinter = getPrinter(args.peek(res.arg.list.name)) if rootPrinter then args.use(res.arg.list.name) end local rootTree = args.tree() local rootTag = 'div' if rootTree then rootPrinter = rootPrinter or getPrinter(true) rootTag = rootPrinter and (rootPrinter.root or rootPrinter.leaf) or 'div' end local builder, content = makeContainer(args, title, rootTag, printlog) if rootTree then printSubTree(content, rootTree, rootPrinter or getPrinter(true), printlog) elseif not rootPrinter and args.peek(res.arg.list.name) then if printlog then printlog.notree = true end content :newline() :wikitext(args.get(res.arg.list.name)) :newline() else if printlog then printlog.example = true end local exampleTree = {{ address = function() return res.class.address.."1" end, peek = function(name) return nil end, use = function(name) return nil end, get = function(name) return args.get(name.."1") end, odd = function(name) return nil end, even = function(name) return nil end, }} printSubTree(content, exampleTree, rootPrinter or getPrinter(true), printlog) end return not printlog and tostring(builder) or require('Moduł:Navbox/diag').diagnosticView(builder, args, printlog) end return { ["Navbox"] = function(frame) local title = mw.title.new(frame:getParent():getTitle()) local printlog = mw.title.equals(title,mw.title.getCurrentTitle()) and {} or nil local args = loadArgsTree(frame.args, printlog) return createNavbox(args, title, printlog) end, ["Template"] = function(frame) mw.log('\n== '..frame:getParent():getTitle()..' ==\n') -- specjalne traktowanie nazwy local name = frame:getParent().args[res.arg.name.name] local expectedTitle = (name and (#name > 0)) and mw.title.new(name, "Template") or nil local printlog = false if expectedTitle then local currentTitle = mw.title.getCurrentTitle() if (currentTitle.namespace == expectedTitle.namespace) and (currentTitle.namespace ~= 0) -- bez artykułów and (currentTitle.namespace ~= 2) -- bez brudnopisów and not currentTitle.isTalkPage and (currentTitle.subpageText ~= res.aux.docSubpageText) -- bez opisów and (not expectedTitle.exists or not require('Moduł:Navbox/diag').verifyTemplateName(currentTitle, expectedTitle, frame:getParent():getTitle())) then printlog = {} printlog.badName = true elseif mw.title.equals(currentTitle, expectedTitle) then printlog = {} end elseif name and (#name > 0) then -- tutaj nie ma żadnych możliwości sprawdzenia czy to jest szablon -- czy jego transkluzja local currentTitle = mw.title.getCurrentTitle() if (currentTitle.namespace ~= 0) and not currentTitle.isTalkSpace then printlog = {} printlog.badName = true end end local status, templateContext = pcall(mw.text.jsonDecode, frame.args.context or '[]') if not status then -- mw.logObject(frame.args.context, templateContext) templateContext = {} end -- mw.logObject(templateContext, 'templateContext') local args = loadArgsTree(frame:getParent().args, printlog, templateContext) if args.peek(res.arg.name.name) then args.use(res.arg.name.name) end --mw.logObject(mw.text.jsonDecode(args.dump()), 'args.dump()') if printlog and templateContext.list then printlog.useTemplateCategories = true end local navbox = args.peek(res.arg.name.name) or args.peek(res.arg.title.name) or args.peek(res.arg.class.name) or args.peek(res.arg.above.name) or args.peek(res.arg.below.name) or args.peek(res.arg.before.name) or args.peek(res.arg.after.name) if navbox then -- mw.log("----> createNavbox") return createNavbox(args, expectedTitle, printlog) end -- mw.log("----> dump") return args.dump() end, }