<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://linguifex.com/w/index.php?action=history&amp;feed=atom&amp;title=Module%3Aauto_cat</id>
	<title>Module:auto cat - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://linguifex.com/w/index.php?action=history&amp;feed=atom&amp;title=Module%3Aauto_cat"/>
	<link rel="alternate" type="text/html" href="https://linguifex.com/w/index.php?title=Module:auto_cat&amp;action=history"/>
	<updated>2026-04-04T16:32:57Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>https://linguifex.com/w/index.php?title=Module:auto_cat&amp;diff=230902&amp;oldid=prev</id>
		<title>Sware at 20:30, 13 July 2021</title>
		<link rel="alternate" type="text/html" href="https://linguifex.com/w/index.php?title=Module:auto_cat&amp;diff=230902&amp;oldid=prev"/>
		<updated>2021-07-13T20:30:59Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 20:30, 13 July 2021&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l209&quot;&gt;Line 209:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 209:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;		&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;		&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;		if templateObject then&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;		if templateObject then&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;			require(&quot;Module:debug&quot;).track(&quot;auto cat/&quot; .. templateObject.title)&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;			local cattext = frame:expandTemplate(templateObject)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;			local cattext = frame:expandTemplate(templateObject)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;			-- FIXME! We check for specific text found in most or all error messages generated&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;			-- FIXME! We check for specific text found in most or all error messages generated&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Sware</name></author>
	</entry>
	<entry>
		<id>https://linguifex.com/w/index.php?title=Module:auto_cat&amp;diff=228925&amp;oldid=prev</id>
		<title>Sware: Created page with &quot;local export = {}  -- Used in multiple places; create a variable for ease in testing. local poscatboiler_submodule = &quot;poscatboiler&quot;   local function splitLabelLang(titleObject...&quot;</title>
		<link rel="alternate" type="text/html" href="https://linguifex.com/w/index.php?title=Module:auto_cat&amp;diff=228925&amp;oldid=prev"/>
		<updated>2021-06-08T10:29:00Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;local export = {}  -- Used in multiple places; create a variable for ease in testing. local poscatboiler_submodule = &amp;quot;poscatboiler&amp;quot;   local function splitLabelLang(titleObject...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local export = {}&lt;br /&gt;
&lt;br /&gt;
-- Used in multiple places; create a variable for ease in testing.&lt;br /&gt;
local poscatboiler_submodule = &amp;quot;poscatboiler&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function splitLabelLang(titleObject)&lt;br /&gt;
	local getByCanonicalName = require(&amp;quot;Module:languages&amp;quot;).getByCanonicalName&lt;br /&gt;
	local canonicalName&lt;br /&gt;
	local lang&lt;br /&gt;
	&lt;br /&gt;
	-- Progressively add another word to the potential canonical name until it&lt;br /&gt;
	-- matches an actual canonical name.&lt;br /&gt;
	local words = mw.text.split(titleObject.text, &amp;quot; &amp;quot;)&lt;br /&gt;
	for i = #words - 1, 1, -1 do&lt;br /&gt;
		canonicalName = table.concat(words, &amp;quot; &amp;quot;, 1, i)&lt;br /&gt;
		lang = getByCanonicalName(canonicalName)&lt;br /&gt;
		if lang then&lt;br /&gt;
			break&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local label = lang and titleObject.text:sub(#canonicalName + 2)&lt;br /&gt;
		or titleObject.text&lt;br /&gt;
	&lt;br /&gt;
	return label, lang&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-- Add the arguments in `source` to those in `receiver`, offsetting numeric arguments by `offset`.&lt;br /&gt;
local function add_args(receiver, source, offset)&lt;br /&gt;
	for k, v in pairs(source) do&lt;br /&gt;
		if type(k) == &amp;quot;number&amp;quot; then&lt;br /&gt;
			receiver[k + offset] = v&lt;br /&gt;
		else&lt;br /&gt;
			receiver[k] = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return receiver&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-- List of handler functions that try to match the page name.&lt;br /&gt;
-- A handler should return a table of template title plus arguments&lt;br /&gt;
-- that is passed to frame:expandTemplate.&lt;br /&gt;
-- If a handler does not recognise the page name, it should return nil.&lt;br /&gt;
-- Note that the order of functions matters!&lt;br /&gt;
&lt;br /&gt;
local handlers = {}&lt;br /&gt;
&lt;br /&gt;
local function add_handler(func)&lt;br /&gt;
	table.insert(handlers, func)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-- Topical categories&lt;br /&gt;
add_handler(function(titleObject)&lt;br /&gt;
	if not titleObject.text:find(&amp;quot;^[a-z-]+:.&amp;quot;) then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local code, label = titleObject.text:match(&amp;quot;^([a-z-]+):(.+)$&amp;quot;)&lt;br /&gt;
	return {title = &amp;quot;topic cat&amp;quot;, args = {code, label}}&lt;br /&gt;
end)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-- Letter names&lt;br /&gt;
add_handler(function(titleObject)&lt;br /&gt;
	if not titleObject.text:find(&amp;quot;letter names$&amp;quot;) then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local langCode = titleObject.text:match(&amp;quot;^([^:]+):&amp;quot;)&lt;br /&gt;
	local lang, cat&lt;br /&gt;
	&lt;br /&gt;
	if langCode then&lt;br /&gt;
		lang = require(&amp;quot;Module:languages&amp;quot;).getByCode(langCode) or error(&amp;#039;The language code &amp;quot;&amp;#039; .. langCode .. &amp;#039;&amp;quot; is not valid.&amp;#039;)&lt;br /&gt;
		cat = titleObject.text:match(&amp;quot;:(.+)$&amp;quot;)&lt;br /&gt;
	else&lt;br /&gt;
		cat = titleObject.text&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return {title = &amp;quot;topic cat&amp;quot;, args = {lang and lang:getCode() or nil, cat}}&lt;br /&gt;
end)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-- letter cat&lt;br /&gt;
add_handler(function(titleObject)&lt;br /&gt;
	-- Only recognize cases consisting of an uppercase letter followed by the&lt;br /&gt;
	-- corresponding lowercase letter, either as the entire category name or&lt;br /&gt;
	-- followed by a colon (for cases like [[Category:Gg: ⠛]]). Cases that&lt;br /&gt;
	-- don&amp;#039;t fit this profile (e.g. for Turkish [[Category:İi]] and&lt;br /&gt;
	-- [[Category:Iı]]) need to call {{letter cat}} directly. Formerly this&lt;br /&gt;
	-- handler was much less restrictive and would fire on categories named&lt;br /&gt;
	-- [[Category:zh:]], [[Category:RFQ]], etc.&lt;br /&gt;
	local upper, lower = mw.ustring.match(titleObject.text, &amp;quot;^(%u)(%l)%f[:%z]&amp;quot;)&lt;br /&gt;
	if not upper or mw.ustring.upper(lower) ~= upper then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return {title = &amp;quot;letter cat&amp;quot;}&lt;br /&gt;
end)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-- poscatboiler lang-specific&lt;br /&gt;
add_handler(function(titleObject, args)&lt;br /&gt;
	local label, lang = splitLabelLang(titleObject)&lt;br /&gt;
	if lang then&lt;br /&gt;
		local baseLabel, script = label:match(&amp;quot;(.+) in (.-) script$&amp;quot;)&lt;br /&gt;
		if script and baseLabel ~= &amp;quot;terms&amp;quot; then&lt;br /&gt;
			local scriptObj = require(&amp;quot;Module:scripts&amp;quot;).getByCanonicalName(script)&lt;br /&gt;
			if scriptObj then&lt;br /&gt;
				return {title = poscatboiler_submodule, args = add_args({lang:getCode(), baseLabel, scriptObj:getCode()}, args, 3)}, true&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		return {title = poscatboiler_submodule, args = add_args({lang:getCode(), label}, args, 3)}, true&lt;br /&gt;
	end&lt;br /&gt;
end)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-- poscatboiler umbrella category&lt;br /&gt;
add_handler(function(titleObject, args)&lt;br /&gt;
	local label = titleObject.text:match(&amp;quot;(.+) by language$&amp;quot;)&lt;br /&gt;
	if label then&lt;br /&gt;
		return {&lt;br /&gt;
			title = poscatboiler_submodule,&lt;br /&gt;
			args = add_args({nil, mw.getContentLanguage():lcfirst(label)}, args, 3)&lt;br /&gt;
		}, true&lt;br /&gt;
	end&lt;br /&gt;
end)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-- topic cat&lt;br /&gt;
add_handler(function(titleObject)&lt;br /&gt;
	return {title = &amp;quot;topic cat&amp;quot;, args = {nil, titleObject.text}}&lt;br /&gt;
end)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-- poscatboiler raw handlers&lt;br /&gt;
add_handler(function(titleObject, args)&lt;br /&gt;
	local args = add_args({nil, titleObject.text}, args, 3)&lt;br /&gt;
	args.raw = true&lt;br /&gt;
	return {&lt;br /&gt;
		title = poscatboiler_submodule,&lt;br /&gt;
		args = args,&lt;br /&gt;
	}, true&lt;br /&gt;
end)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-- poscatboiler umbrella handlers without &amp;#039;by language&amp;#039;&lt;br /&gt;
add_handler(function(titleObject, args)&lt;br /&gt;
	local args = add_args({nil, mw.getContentLanguage():lcfirst(titleObject.text)}, args, 3)&lt;br /&gt;
	return {&lt;br /&gt;
		title = poscatboiler_submodule,&lt;br /&gt;
		args = args,&lt;br /&gt;
	}, true&lt;br /&gt;
end)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function export.show(frame)&lt;br /&gt;
	local args = frame:getParent().args&lt;br /&gt;
	local titleObject = mw.title.getCurrentTitle()&lt;br /&gt;
	&lt;br /&gt;
	if titleObject.nsText == &amp;quot;Template&amp;quot; then&lt;br /&gt;
		return &amp;quot;(This template should be used on pages in the Category: namespace.)&amp;quot;&lt;br /&gt;
	elseif titleObject.nsText ~= &amp;quot;Category&amp;quot; then&lt;br /&gt;
		error(&amp;quot;This template/module can only be used on pages in the Category: namespace.&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function extra_args_error(templateObject)&lt;br /&gt;
		local numargstext = {}&lt;br /&gt;
		local argstext = {}&lt;br /&gt;
		local maxargnum = 0&lt;br /&gt;
		for k, v in pairs(templateObject.args) do&lt;br /&gt;
			if type(v) == &amp;quot;number&amp;quot; and v &amp;gt; maxargnum then&lt;br /&gt;
				maxargnum = v&lt;br /&gt;
			else&lt;br /&gt;
				table.insert(numargstext, &amp;quot;|&amp;quot; .. k .. &amp;quot;=&amp;quot; .. v)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		for i = 1, maxargnum do&lt;br /&gt;
			local v = templateObject.args[i]&lt;br /&gt;
			if v == nil then&lt;br /&gt;
				v = &amp;quot;(nil)&amp;quot;&lt;br /&gt;
			elseif v == true then&lt;br /&gt;
				v = &amp;quot;(true)&amp;quot;&lt;br /&gt;
			elseif v == false then&lt;br /&gt;
				v = &amp;quot;(false)&amp;quot;&lt;br /&gt;
			end&lt;br /&gt;
			table.insert(argstext, &amp;quot;|&amp;quot; .. v)&lt;br /&gt;
		end&lt;br /&gt;
		error(&amp;quot;Extra arguments to {{auto cat}} not allowed for this category (recognized as {{[[Template:&amp;quot; ..&lt;br /&gt;
			templateObject.title .. &amp;quot;|&amp;quot; .. templateObject.title .. &amp;quot;]]&amp;quot; .. numargstext .. argstext .. &amp;quot;}}&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local first_error_templateObject, first_error_args_handled, first_error_cattext&lt;br /&gt;
&lt;br /&gt;
	-- Go through each handler in turn. If a handler doesn&amp;#039;t recognize the format of the&lt;br /&gt;
	-- category, it will return nil, and we will consider the next handler. Otherwise,&lt;br /&gt;
	-- it returns a template name and arguments to call it with, but even then, that template&lt;br /&gt;
	-- might return an error, and we need to consider the next handler. This happens,&lt;br /&gt;
	-- for example, with the category &amp;quot;CAT:Mato Grosso, Brazil&amp;quot;, where &amp;quot;Mato&amp;quot; is the name of&lt;br /&gt;
	-- a language, so the handler for {{poscatboiler}} fires and tries to find a label&lt;br /&gt;
	-- &amp;quot;Grosso, Brazil&amp;quot;. This throws an error, and previously, this blocked fruther handler&lt;br /&gt;
	-- consideration, but now we check for the error and continue checking handlers;&lt;br /&gt;
	-- eventually, {{topic cat}} will fire and correctly handle the category.&lt;br /&gt;
	for _, handler in ipairs(handlers) do&lt;br /&gt;
		local templateObject, args_handled = handler(titleObject, args)&lt;br /&gt;
		&lt;br /&gt;
		if templateObject then&lt;br /&gt;
			require(&amp;quot;Module:debug&amp;quot;).track(&amp;quot;auto cat/&amp;quot; .. templateObject.title)&lt;br /&gt;
			local cattext = frame:expandTemplate(templateObject)&lt;br /&gt;
			-- FIXME! We check for specific text found in most or all error messages generated&lt;br /&gt;
			-- by category tree templates (in particular, the second piece of text below should be&lt;br /&gt;
			-- in all error messages generated when a given module doesn&amp;#039;t recognize a category name).&lt;br /&gt;
			-- If this text ever changes in the source modules (e.g. [[Module:category tree]],&lt;br /&gt;
			-- it needs to be changed here as well.)&lt;br /&gt;
			if cattext:find(&amp;quot;Category:Categories with invalid label&amp;quot;) or&lt;br /&gt;
				cattext:find(&amp;quot;The automatically%-generated contents of this category has errors&amp;quot;) then&lt;br /&gt;
				if not first_error_cattext then&lt;br /&gt;
					first_error_templateObject = templateObject&lt;br /&gt;
					first_error_args_handled = args_handled&lt;br /&gt;
					first_error_cattext = cattext&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				if not args_handled and next(args) then&lt;br /&gt;
					extra_args_error(templateObject)&lt;br /&gt;
				end&lt;br /&gt;
				return cattext&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if first_error_cattext then&lt;br /&gt;
		if not first_error_args_handled and next(args) then&lt;br /&gt;
			extra_args_error(first_error_templateObject)&lt;br /&gt;
		end&lt;br /&gt;
		return first_error_cattext&lt;br /&gt;
	end&lt;br /&gt;
	error(&amp;quot;{{auto cat}} couldn&amp;#039;t recognize format of category name&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- test function for injecting title string&lt;br /&gt;
function export.test(title)&lt;br /&gt;
	if type(title) == &amp;quot;table&amp;quot; then&lt;br /&gt;
		title = title:getParent().args[1]&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local titleObject = {}&lt;br /&gt;
	titleObject.text = title&lt;br /&gt;
	&lt;br /&gt;
	for _, handler in ipairs(handlers) do&lt;br /&gt;
		local t = handler(titleObject)&lt;br /&gt;
		&lt;br /&gt;
		if t then&lt;br /&gt;
			return t.title&lt;br /&gt;
		end&lt;br /&gt;
	end	&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return export&lt;/div&gt;</summary>
		<author><name>Sware</name></author>
	</entry>
</feed>