Modul:category tree
Modul ini digunakan untuk menghasilkan templat kategori boilerplate. Itu tidak dimaksudkan untuk digunakan secara langsung. Sebaliknya, setiap templat akan memiliki submodulnya sendiri, yang akan menangani spesifikasi templat tersebut.
Dokumentasi ini hanya mencakup generik dari sistem pohon kategori. Jika Anda mencari dokumentasi tentang template tertentu, atau tentang cara menambahkan atau mengubah informasi kategori, lihat dokumentasi template tersebut.
local export = {}
local m_utilities = require("Modul:utilities")
local inFundamental = mw.loadData("Modul:category tree/data")
local show_error, check_name, link_box, show_catfix, show_categories, show_intro, show_editlink, show_pagelist,
show_breadcrumbs, show_description, show_appendix, show_children, show_TOC
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)
local template = frame.args["template"]
if not template or template == "" then
error("The \"template\" parameter was not specified.")
end
if mw.title.getCurrentTitle().nsText == "Templat" then
local text = {}
table.insert(text, "This template should be used on pages in the Category: namespace, ")
table.insert(text, "and automatically generates descriptions and categorization for categories of a recognized type (see below).")
table.insert(text, " It is implemented by [[Module:category tree]] and its submodule [[Module:category tree/")
table.insert(text, template .. "]].")
if frame.args["useautocat"] then
table.insert(text, " It is preferable not to invoke this template directly, but to simply use ")
table.insert(text, require("Module:template link").format_link({"auto cat"}))
table.insert(text, " (with no parameters), which will automatically invoke this template on appropriately-named category pages.")
end
return table.concat(text)
elseif mw.title.getCurrentTitle().nsText ~= "Kategori" then
error("This template/module can only be used on pages in the Category: namespace.")
end
local submodule = require("Modul: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
if val ~= "" and key ~= "useautocat" then
info[key] = val
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, "[[Kategori: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, "[[Kategori:Kategori dengan label invalid]]")
table.insert(categories, isEmpty and "[[Kategori:Kategori kosong]]" 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, "[[Kategori:Kategori dengan nama yang tidak tepat]]")
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 '''[[:Kategori:" .. current:getCategoryName() .. "]]'''."))
end
-- Add cleanup category for empty categories
local canBeEmpty = current:canBeEmpty()
if isEmpty and not canBeEmpty then
table.insert(categories, "[[Kategori:Kategori kosong]]")
end
if current:isHidden() then
table.insert(categories, "__HIDDENCAT__")
end
if canBeEmpty then
table.insert(categories, " __EXPECTUNUSEDCATEGORY__")
end
table.insert(boxes, show_intro(current))
table.insert(boxes, show_editlink(current))
table.insert(boxes, show_related_changes())
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 = "[[Kategori:Kategori dengan label tidak vaild]]"
else
end
if errortext then
return (category or "") .. show_error(errortext)
else
return nil
end
end
local function get_catfix_info(current)
local lang, sc
if current.getCatfixInfo then
lang, sc = current:getCatfixInfo()
elseif not (current._info and current._info.no_catfix) then
-- FIXME: This is hacky and should be removed.
lang = current._lang
sc = current._info and current._info.sc and require("Module:scripts").getByCode(current._info.sc) or nil
end
return lang, sc
end
-- Show the "catfix" that adds language attributes and script classes to the page.
function show_catfix(current)
local lang, sc = get_catfix_info(current)
if lang then
return m_utilities.catfix(lang, sc)
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, "[[Kategori:" .. 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, "[[Kategori:" .. umbrella:getCategoryName() .. "|" .. sort .. "]]")
end
end
end
function link_box(content)
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;\">"
.. content .. "</div>"
end
function show_related_changes()
local title = mw.title.getCurrentTitle().fullText
return link_box(
"["
.. tostring(mw.uri.fullUrl("Special:RecentChangesLinked", {
target = title,
showlinkedto = 0,
}))
.. ' <span title="Recent edits and other changes to pages in ' .. title .. '">Recent changes</span>]')
end
function show_editlink(current)
return link_box(
"[" .. tostring(mw.uri.fullUrl(current:getDataModule(), "action=edit"))
.. " Edit category data]")
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
local nocap = nil
if type(current) == "string" then
category = current
display_name = current:gsub("^Kategori:", "")
else
category = "Kategori:" .. current:getCategoryName()
display_name, nocap = current:getBreadcrumbName()
end
if not nocap then
display_name = capitalize(display_name)
end
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 = "Kategori:Fundamental"
end
end
steps = table.concat(steps, " » ")
return "<small>" .. steps .. "</small>"
end
-- Show the intro text that goes at the very top of the page.
function show_intro(current)
return (current.getIntro and current:getIntro() or "")
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_pagetitle
if type(child.name) == "string" then
child_pagetitle = child.name
else
child_pagetitle = "Kategori:" .. child.name:getCategoryName()
end
local child_page = mw.title.new(child_pagetitle)
if child_page.exists then
local child_description =
child.description or
type(child.name) == "string" and child.name:gsub("^Kategori:", "") .. "." or
child.name:getDescription("child")
table.insert(children_list, "* [[:" .. child_pagetitle .. "]]: " .. 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 titleText = mw.title.getCurrentTitle().text
local inCategoryPages = mw.site.stats.pagesInCategory(titleText, "pages")
local inCategorySubcats = mw.site.stats.pagesInCategory(titleText, "subcats")
local TOC_type
-- Compute type of table of contents required.
if inCategoryPages > 2500 or inCategorySubcats > 2500 then
TOC_type = "full"
elseif inCategoryPages > 200 or inCategorySubcats > 200 then
TOC_type = "normal"
else
-- No (usual) need for a TOC if all pages or subcategories can fit on one page;
-- but allow this to be overridden by a custom TOC handler.
TOC_type = "none"
end
if current.getTOC then
local TOC_text = current:getTOC(TOC_type)
if TOC_text ~= true then
return TOC_text
end
end
if TOC_type ~= "none" then
local lang, sc = get_catfix_info(current)
local code = lang and lang:getCode() or "en"
local TOC_template
if TOC_type == "full" then
-- This category is very large, see if there is a "full" version of the TOC.
local TOC_template_full = mw.title.new("Templat:" .. code .. "-categoryTOC/full")
if TOC_template_full.exists then
TOC_template = TOC_template_full
end
end
if not TOC_template then
local TOC_template_normal = mw.title.new("Templat:" .. code .. "-categoryTOC")
if TOC_template_normal.exists then
TOC_template = TOC_template_normal
end
end
if TOC_template then
return mw.getCurrentFrame():expandTemplate{title = TOC_template.text, args = {}}
end
end
return nil
end
function export.test(frame)
local template = frame.args[1]
local submodule = require("Modul:category tree/" .. template)
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
end
return export