-- Prevent substitution.
if mw.isSubsting() then
return require("Module:unsubst")
end
local m_category_tree = require("Module:category tree")
local m_str_utils = require("Module:string utilities")
local concat = table.concat
local deepcopy = require("Module:table").deepcopy
local get_current_title = mw.title.getCurrentTitle
local insert = table.insert
local split = m_str_utils.split
local split_lang_label = m_category_tree.split_lang_label
local trim = m_str_utils.trim
local yesno = require("Module:yesno")
local export = {}
-- Used in multiple places; create a variable for ease in testing.
local poscatboiler = "poscatboiler"
local topic_cat = "topic cat"
local ws_topic_cat = "ws topic cat"
--[==[
List of handler functions that try to match the page name. A handler should return the name of a submodule to
[[Module:category tree]] and an info table which is passed as an argument to the submodule. If a handler does not
recognize the page name, it should return nil. Note that the order of handlers matters!
]==]
local handlers = {}
-- ws topic cat
insert(handlers, function(titleObject)
local code, label = titleObject.text:match("^Tesaurus:(%l[%a-]*%a):(.+)")
if code then
return ws_topic_cat, {label = label, code = code}
end
end)
-- Topical categories
insert(handlers, function(titleObject)
local code, label = titleObject.text:match("^(%l[%a-]*%a):(.+)")
if code then
return topic_cat, {label = label, code = code}
end
end)
-- Lect categories e.g. for [[:Category:New Zealand English]] or [[:Category:Issime Walser]]
insert(handlers, function(titleObject, args)
local lect = args.lect or args.dialect
if lect ~= "" and yesno(dialect, true) then -- Same as boolean in [[Module:parameters]].
return poscatboiler, {label = titleObject.text, args = args, raw = true}
end
end)
-- poscatboiler lang-specific
insert(handlers, function(titleObject, args)
local lang, label = split_lang_label(titleObject)
if not lang then
return
end
local baseLabel, script = label:match("(.+) dalam tulisan (.-)$")
if script and baseLabel ~= "kata" then
local scriptObj = require("Module:scripts").getByCanonicalName(script)
if scriptObj then
return poscatboiler, {label = baseLabel, code = lang:getCode(), sc = scriptObj:getCode(), args = args}
end
end
return poscatboiler, {label = label, code = lang:getCode(), args = args}
end)
-- poscatboiler umbrella category
insert(handlers, function(titleObject, args)
local label = titleObject.text:match("(.+) mengikut bahasa$")
if label then
-- The poscatboiler code will appropriately lowercase if needed.
return poscatboiler, {label = label, args = args}
end
end)
-- ws topic cat
insert(handlers, function(titleObject)
local label = titleObject.text:match("^Tesaurus:(.+)")
if label then
return ws_topic_cat, {label = label}
end
end)
-- topic cat
insert(handlers, function(titleObject)
return topic_cat, {label = titleObject.text}
end)
-- poscatboiler raw handlers
insert(handlers, function(titleObject, args)
return poscatboiler, {label = titleObject.text, args = args, raw = true}
end)
-- poscatboiler umbrella handlers without 'by language'
insert(handlers, function(titleObject, args)
return poscatboiler, {label = titleObject.text, args = args}
end)
function export.show(frame)
local args = {}
for k, arg in pairs(frame:getParent().args) do
args[k] = trim(arg)
end
local namespace = get_current_title().namespace
if namespace == 10 then -- Template
return "(This template should be used on pages in the Category: namespace.)"
elseif namespace ~= 14 then -- Category
error("This template/module can only be used on pages in the Category: namespace.")
end
local function extra_args_error()
error("Extra arguments to {{((}}auto cat{{))}} not allowed for this category.")
end
local first_error_args_handled, first_error_cattext
-- Go through each handler in turn. If a handler doesn't recognize the format of the
-- category, it will return nil, and we will consider the next handler. Otherwise,
-- it returns a template name and arguments to call it with, but even then, that template
-- might return an error, and we need to consider the next handler. This happens,
-- for example, with the category "CAT:Mato Grosso, Brazil", where "Mato" is the name of
-- a language, so the handler for {{poscatboiler}} fires and tries to find a label
-- "Grosso, Brazil". This throws an error, and previously, this blocked fruther handler
-- consideration, but now we check for the error and continue checking handlers;
-- eventually, {{topic cat}} will fire and correctly handle the category.
for _, handler in ipairs(handlers) do
-- Use a new title object and args table for each handler, to keep them isolated.
local submodule, info = handler(get_current_title(), deepcopy(args))
if submodule then
require("Module:debug").track("auto cat/" .. submodule)
local cattext = m_category_tree.main(submodule, info)
-- FIXME! We check for specific text found in most or all error messages generated
-- by category tree templates (in particular, the second piece of text below should be
-- in all error messages generated when a given module doesn't recognize a category name).
-- If this text ever changes in the source modules (e.g. [[Module:category tree]],
-- it needs to be changed here as well.)
if cattext:find("Kategori:Kategori yang tidak ditakrifkan pada category tree") or
cattext:find("The automatically%-generated contents of this category has errors") then
if not first_error_cattext then
first_error_cattext = cattext
first_error_args_handled = info.args and true or false
end
elseif not info.args and next(args) then
extra_args_error()
else
return cattext
end
end
end
if first_error_cattext then
if not first_error_args_handled and next(args) then
extra_args_error()
end
return first_error_cattext
end
error("{{auto cat}} couldn't recognize format of category name")
end
-- test function for injecting title string
function export.test(title)
local args = {}
if type(title) == "table" then
if type(title.args[1]) == "string" then
args = title.args
else
args = title:getParent().args
end
title = args[1]
end
local titleObject = {}
titleObject.text = title
for _, handler in ipairs(handlers) do
local t = handler(titleObject, args)
if t then
return t.title
end
end
end
return export