Module:Category tree
Jump to navigation
Jump to search
Documentation for this module may be created at Module:Category tree/doc
local export = {} local m_languages = require('Module:languages') local m_utilities = require('Module:utilities') local inFundamental = mw.loadData("Module:category tree/data") local function capitalize(text) return mw.getContentLanguage():ucfirst(text) end -- The main entry point. -- This is the only function that can be invoked from a template. function export.show(frame) if mw.title.getCurrentTitle().nsText == "Template" then return "(This template should be used on pages in the Category: namespace.)" elseif mw.title.getCurrentTitle().nsText ~= "Category" then error("This template/module can only be used on pages in the Category: namespace.") end local template = frame.args["template"] if not template or template == "" then error("The \"template\" parameter was not specified.") end local submodule = require("Module:category tree/" .. template) -- Get all the parameters and the label data local current if submodule.new_main then current = submodule.new_main(frame) else local info = {} for key, val in pairs(frame.args) do info[key] = val; if info[key] == "" then info[key] = nil end end info.template = nil current = submodule.new(info, true) end local functions = { "getBreadcrumbName", "getDataModule", "canBeEmpty", "getDescription", "getParents", "getChildren", "getUmbrella", "getAppendix", } if current then for i, functionName in pairs(functions) do if type(current[functionName]) ~= "function" then require("Module:debug").track{ "category tree/missing function", "category tree/missing function/" .. functionName } end end end local boxes = {} local display = {} local categories = {} if template == "topic cat" then table.insert(categories, "[[Category:topic cat]]") end -- Check if the category is empty local isEmpty = mw.site.stats.pagesInCategory(mw.title.getCurrentTitle().text, "all") == 0 -- Are the parameters valid? if not current then table.insert(categories, "[[Category:Categories with invalid label]]") table.insert(categories, isEmpty and "[[Category:Empty categories]]" or nil) table.insert(display, show_error( "The label given to the " .. require("Module:template link").format_link{template} .. " template is not valid. You may have mistyped it, or it simply has not been created yet. " .. "To add a new label, please consult the documentation of the template.")) -- Exit here, as all code beyond here relies on current not being nil return table.concat(categories, "") .. table.concat(display, "\n\n") end -- Does the category have the correct name? if mw.title.getCurrentTitle().text ~= current:getCategoryName() then table.insert(categories, "[[Category:Categories with incorrect name]]") table.insert(display, show_error( "Based on the parameters given to the " .. require("Module:template link").format_link{template} .. " template, this category should be called '''[[:Category:" .. current:getCategoryName() .. "]]'''.")) end -- Add cleanup category for empty categories if isEmpty and not current:canBeEmpty() then table.insert(categories, "[[Category:Empty categories]]") end if current:isHidden() then table.insert(categories, "__HIDDENCAT__") end table.insert(boxes, show_editlink(current)) table.insert(boxes, show_pagelist(current)) -- Generate the displayed information table.insert(display, show_breadcrumbs(current)) table.insert(display, show_description(current)) table.insert(display, show_appendix(current)) table.insert(display, show_children(current)) table.insert(display, show_TOC(current)) table.insert(display, show_catfix(current)) show_categories(current, categories) return table.concat(boxes, "\n") .. "\n" .. table.concat(display, "\n\n") .. table.concat(categories, "") end function show_error(text) return mw.getCurrentFrame():expandTemplate{title = "maintenance box", args = { "red", image = "[[File:Ambox warning pn.svg|50px]]", title = "The automatically-generated contents of this category has errors.", text = text, }} end -- Check the name of the current page, and return an error if it's not right. function check_name(current, template, info) local errortext = nil local category = nil if not current then errortext = "The label \"" .. (info.label or "") .. "\" given to the " .. require("Module:template link").format_link{template} .. " template is not valid. " .. "You may have mistyped it, or it simply has not been created yet. To add a new label, please consult the documentation of the template." category = "[[Category:Categories with invalid label]]" else end if errortext then return (category or "") .. show_error(errortext) else return nil end end function show_catfix(current) if current._lang then return m_utilities.catfix(current._lang, (sc and require("Module:scripts").getByCode(info.sc) or nil)) else return nil end end -- Show the parent categories that the current category should be placed in. function show_categories(current, categories) local parents = current:getParents() if not parents then return end for _, parent in ipairs(parents) do if type(parent.name) == "string" then if not (current._lang and current:getCategoryName() == capitalize(current._lang:getCategoryName())) and not (current._sc and current:getCategoryName():find(capitalize(current._sc:getCategoryName()), nil, true)) and current:getInfo().code then require("Module:debug").track("category tree/string") end table.insert(categories, "[[" .. parent.name .. "|" .. parent.sort .. "]]") else table.insert(categories, "[[Category:" .. parent.name:getCategoryName() .. "|" .. parent.sort .. "]]") end end -- Also put the category in its corresponding "umbrella" or "by language" category. local umbrella = current:getUmbrella() if umbrella then local sort if current._lang then sort = current._lang:getCanonicalName() else sort = current:getCategoryName() end if type(umbrella) == "string" then table.insert(categories, "[[" .. umbrella .. "|" .. sort .. "]]") else table.insert(categories, "[[Category:" .. umbrella:getCategoryName() .. "|" .. sort .. "]]") end end end function show_editlink(current) return "<div class=\"noprint plainlinks\" style=\"float: right; clear: both; margin: 0 0 .5em 1em; background: #f9f9f9; border: 1px #aaaaaa solid; margin-top: -1px; padding: 5px; font-weight: bold;\">[" .. tostring(mw.uri.fullUrl(current:getDataModule(), "action=edit")) .. " Edit category data]</div>" end function show_pagelist(current) local namespace = "" local info = current:getInfo() if info.label == "citations" or info.label == "citations of undefined terms" then namespace = "Citations" elseif info.code then local lang = require("Module:languages").getByCode(info.code) if lang then if lang:getType() == "reconstructed" then namespace = "Reconstruction" elseif lang:getType() == "appendix-constructed" then namespace = "Appendix" end end end local recent = mw.getCurrentFrame():callParserFunction{ name = "#tag", args = { "DynamicPageList", "category=" .. mw.title.getCurrentTitle().text .. "\n" .. "namespace=" .. namespace .. "\n" .. "count=10\n" .. "mode=ordered\n" .. "ordermethod=categoryadd\n" .. "order=descending" } } local oldest = mw.getCurrentFrame():callParserFunction{ name = "#tag", args = { "DynamicPageList", "category=" .. mw.title.getCurrentTitle().text .. "\n" .. "namespace=" .. namespace .. "\n" .. "count=10\n" .. "mode=ordered\n" .. "ordermethod=lastedit\n" .. "order=ascending" } } return [=[ {| id="newest-and-oldest-pages" class="wikitable" style="float: right; clear: both; margin: 0 0 .5em 1em;" ! Recent additions to the category |- | id="recent-additions" style="font-size:0.9em;" | ]=] .. recent .. [=[ |- ! Oldest pages ordered by last edit |- | id="oldest-pages" style="font-size:0.9em;" | ]=] .. oldest .. [=[ |}]=] end -- Show navigational "breadcrumbs" at the top of the page. function show_breadcrumbs(current) local steps = {} -- Start at the current label and move our way up the "chain" from child to parent, until we can't go further. while current do local category = nil local display_name = nil if type(current) == "string" then category = current display_name = current:gsub("^Category:", "") else category = "Category:" .. current:getCategoryName() display_name = current:getBreadcrumbName() end display_name = capitalize(display_name) table.insert(steps, 1, "[[:" .. category .. "|" .. display_name .. "]]") -- Move up the "chain" by one level. if type(current) == "string" then current = nil else current = current:getParents() end if current then current = current[1].name elseif inFundamental[category] then current = "Category:Fundamental" end end steps = table.concat(steps, " » ") return "<small>" .. steps .. "</small>" end -- Show a short description text for the category. function show_description(current) return (current:getDescription() or "") end function show_appendix(current) local appendix if current.getAppendix then appendix = current:getAppendix() end if appendix then return "For more information, see [[" .. appendix .. "]]." else return nil end end -- Show a list of child categories. function show_children(current) local children = current:getChildren() if not children then return nil end table.sort(children, function(first, second) return first.sort < second.sort end) local children_list = {} for _, child in ipairs(children) do local child_basic = child.name:getCategoryName() local child_page = mw.title.new("Category:" .. child_basic) if child_page.exists then local child_description = child.name:getDescription("child") table.insert(children_list, "* [[:Category:" .. child_basic .. "]]: " .. child_description) end end return table.concat(children_list, "\n") end -- Show a table of contents with links to each letter in the language's script. function show_TOC(current) local code = current:getInfo().code if code and not require("Module:languages").getByCode(code) then return nil end if not code then code = "en" end -- If category can be empty, then it only contains subcategories. local hasPages = not current:canBeEmpty() local titleText = mw.title.getCurrentTitle().text local inCategory if hasPages then inCategory = mw.site.stats.pagesInCategory(titleText, "pages") else inCategory = mw.site.stats.pagesInCategory(titleText, "subcats") end -- No need for a TOC if all pages or subcategories can fit on one page. if inCategory > 200 then -- This category is very large, see if there is an "extended" version of the TOC. if inCategory > 2500 then local TOC_template_extended = mw.title.new("Template:" .. code .. "-categoryTOC/full") if TOC_template_extended.exists then return mw.getCurrentFrame():expandTemplate{title = TOC_template_extended.text, args = {}} end end local TOC_template = mw.title.new("Template:" .. code .. "-categoryTOC") if TOC_template.exists then return mw.getCurrentFrame():expandTemplate{title = TOC_template.text, args = {}} end end return nil end return export