local split = require("Module:string utilities").split
local export = {}
-- Used in multiple places; create a variable for ease in testing.
local poscatboiler_template = "poscatboiler"
local find = mw.ustring.find
local match = mw.ustring.match
local sub = mw.ustring.sub
local labelPatterns = {
"คำ.-", "เลข", "รูปผัน.-", "พาร์ทิซิเพิล.-", "อุปสรรค", "ปัจจัย", "อาคม", "หน่วยคำ.-", "อักษรย่อ.-",
"เครื่องหมายวรรคตอน", "ตัวอักษร", "ตัวเลข", "พยางค์", "สัญลักษณ์", "วลี", "ประโยค", "ฮิรางานะ.-", "คาตากานะ.-",
"ภาพพจน์", "สำนวน", "เฉิงยฺหวี่", "พาลินโดรม", "สแลง.-", "ชื่อ.-", "นามสกุล",
"จำนวน.-", --เป็นได้ทั้ง POS และ topic
"การ.-", "ภาคผนวก", "มอดูล.-", "แม่แบบ.-", "หน้าที่มีลิงก์แดง", "หน้าที่มีคำแปล", "รายการอรรถาภิธาน",
}
local function split_label_lang(titleObject)
local getByCanonicalName = require("Module:languages").getByCanonicalName
local canonicalName
local label, lang
local pattern
--[=[
-- Progressively add another word to the potential canonical name until it
-- matches an actual canonical name.
local words = split(titleObject.text, " ", true)
for i = #words - 1, 1, -1 do
canonicalName = table.concat(words, " ", 1, i)
lang = getByCanonicalName(canonicalName)
if lang then
break
end
end
local label = lang and sub(titleObject.text, #canonicalName + 2)
or titleObject.text
--]=]
if find(titleObject.text, "^ศัพท์") then
-- ตามลำดับ "แบ่ง" ขึ้นก่อนเพราะมีหมวดหมู่ "หน้าที่"
canonicalName, label = match(titleObject.text, "^ศัพท์ภาษา(.+)(แบ่ง.+)$")
if not canonicalName then
canonicalName, label = match(titleObject.text, "^ศัพท์ภาษา(.+)(ที่.+)$")
end
if canonicalName then
label = "ศัพท์" .. label
lang = getByCanonicalName(canonicalName)
else
label = titleObject.text
lang = nil
end
else
for _,pattern in ipairs(labelPatterns) do
label, canonicalName = match(titleObject.text, "^(" .. pattern .. ")ภาษา(.+)$")
if canonicalName then
canonicalName1, inScript = match(canonicalName, "^(.+)(ในอักษร.+)$")
if canonicalName1 and inScript then
canonicalName = canonicalName1
label = label .. inScript
end
lang = getByCanonicalName(canonicalName)
break
end
end
end
return label, lang
end
--[==[
Copy the arguments in `source` to those in `receiver`, offsetting numeric arguments by `offset`.
Handlers that invoke {{tl|poscatboiler}} use this to pass user-specified arguments to {{tl|poscatboiler}} along with
arguments specifying the category and its type. Specifically, {{tl|poscatboiler}} requires arguments specified in 1=
(the language name embedded in the category), 2= (the category name minus the language name and any suffixed script),
3= (the script code of categories of the form [[:Category:Pali nouns in Devanagari script]]) and raw= (true for raw
categories). User-specified numeric parameters are passed in 4= and above hence `offset` will normally be 3.
]==]
function export.copy_args(receiver, source, offset)
for k, v in pairs(source) do
if type(k) == "number" then
receiver[k + offset] = v
else
receiver[k] = v
end
end
return receiver
end
-- List of handler functions that try to match the page name. A handler should return a table of template title plus
-- arguments to be passed to frame:expandTemplate(). If a handler does not recognize the page name, it should return
-- nil. Note that the order of functions matters!
local handlers = {}
local function add_handler(func)
table.insert(handlers, func)
end
-- ws topic cat
add_handler(function(titleObject)
if not find(titleObject.text, "^อรรถาภิธาน:[a-z-]+:.") then
return nil
end
local code, label = match(titleObject.text, "^อรรถาภิธาน:([a-z-]+):(.+)$")
return {title = "ws topic cat", args = {code, label}}
end)
-- Topical categories
add_handler(function(titleObject)
if not find(titleObject.text, "^[a-z-]+:.") then
return nil
end
local code, label = match(titleObject.text, "^([a-z-]+):(.+)$")
return {title = "topic cat", args = {code, label}}
end)
-- Fancy version of ine() (if-not-empty). Converts empty string to nil, but also strips leading/trailing space.
function export.ine(arg)
if not arg then return nil end
arg = mw.text.trim(arg)
if arg == "" then return nil end
return arg
end
-- Dialect categories e.g. for [[:Category:New Zealand English]] or [[:Category:Issime Walser]]
add_handler(function(titleObject, args)
if export.ine(args.dialect) then
local args = export.copy_args({nil, titleObject.text}, args, 3)
args.raw = true
return {
title = poscatboiler_template,
args = args,
}, true
end
end)
-- poscatboiler lang-specific
add_handler(function(titleObject, args)
local label, lang = split_label_lang(titleObject)
if lang then
local baseLabel, script = match(label, "(.+)ในอักษร(.-)$")
if script and baseLabel ~= "ศัพท์" then
local scriptObj = require("Module:scripts").getByCanonicalName(script)
if scriptObj then
return {title = poscatboiler_template, args =
export.copy_args({lang:getCode(), baseLabel, scriptObj:getCode()}, args, 3)}, true
end
end
return {title = poscatboiler_template, args = export.copy_args({lang and lang:getCode() or "", label}, args, 3)}, true
end
end)
-- poscatboiler umbrella category
add_handler(function(titleObject, args)
local label = match(titleObject.text, "(.+)แบ่งตามภาษา$")
if label then
return {
title = poscatboiler_template,
-- The poscatboiler code will appropriately lowercase if needed.
args = export.copy_args({nil, label}, args, 3)
}, true
end
end)
-- ws topic cat
add_handler(function(titleObject)
if not find(titleObject.text, "^อรรถาภิธาน:") then
return nil
end
return {title = "ws topic cat", args = {nil, string.sub(titleObject.text, 11)}}
end)
-- fixed กลุ่มภาษา... must come before topic cat
add_handler(function(titleObject, args)
local args = export.copy_args({nil, titleObject.text}, args, 3)
args.raw = true
if match(titleObject.text, "^กลุ่มภาษา.+$") then
return {
title = poscatboiler_template,
args = args,
}, true
end
end)
-- fixed ภาษา... must come before topic cat
add_handler(function(titleObject, args)
local args = export.copy_args({nil, titleObject.text}, args, 3)
args.raw = true
if match(titleObject.text, "^ภาษา.+$") and titleObject.text ~= "ภาษา (หัวข้อ)" and titleObject.text ~= "ภาษาศาสตร์" then
return {
title = poscatboiler_template,
args = args,
}, true
end
end)
-- topic cat
add_handler(function(titleObject)
return {title = "topic cat", args = {nil, titleObject.text}}
end)
-- poscatboiler raw handlers
add_handler(function(titleObject, args)
local args = export.copy_args({nil, titleObject.text}, args, 3)
args.raw = true
return {
title = poscatboiler_template,
args = args,
}, true
end)
-- poscatboiler umbrella handlers without 'by language'
add_handler(function(titleObject, args)
local args = export.copy_args({nil, titleObject.text}, args, 3)
return {
title = poscatboiler_template,
args = args,
}, true
end)
function export.show(frame)
local args = frame:getParent().args
local titleObject = mw.title.getCurrentTitle()
if titleObject.nsText == "แม่แบบ" then
return "(This template should be used on pages in the Category: namespace.)"
elseif titleObject.nsText ~= "หมวดหมู่" then
error("This template/module can only be used on pages in the Category: namespace.")
end
local function extra_args_error(templateObject)
local numargstext = {}
local argstext = {}
local maxargnum = 0
for k, v in pairs(templateObject.args) do
if type(v) == "number" and v > maxargnum then
maxargnum = v
else
table.insert(numargstext, "|" .. k .. "=" .. v)
end
end
for i = 1, maxargnum do
local v = templateObject.args[i]
if v == nil then
v = "(nil)"
elseif v == true then
v = "(true)"
elseif v == false then
v = "(false)"
end
table.insert(argstext, "|" .. v)
end
error("Extra arguments to {{auto cat}} not allowed for this category (recognized as {{[[Template:" ..
templateObject.title .. "|" .. templateObject.title .. "]]" .. numargstext .. argstext .. "}}")
end
local first_error_templateObject, 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
local templateObject, args_handled = handler(titleObject, args)
if templateObject then
require("Module:debug").track("auto cat/" .. templateObject.title)
local cattext = frame:expandTemplate(templateObject)
-- 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("Category:Categories that are not defined in the category tree") or
cattext:find("The automatically%-generated contents of this category has errors") then
if not first_error_cattext then
first_error_templateObject = templateObject
first_error_args_handled = args_handled
first_error_cattext = cattext
end
else
if not args_handled and next(args) then
extra_args_error(templateObject)
end
return cattext
end
end
end
if first_error_cattext then
if not first_error_args_handled and next(args) then
extra_args_error(first_error_templateObject)
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
-- use ExpandTemplates to "transclude" this on any Category: namespace page
function export.testTransclusion(frame)
local args = frame.args
local title = args[1]
local titleObject = {}
titleObject.text = title
for _, handler in ipairs(handlers) do
local t = handler(titleObject, {})
if t then
return frame:expandTemplate(t)
end
end
end
return export