- This module may be invoked by templates using its corresponding template Template:Category handler, or used directly from other modules.
|
Module:Category handler is ready for use. This message indicates that a module is ready for use, or has recently been repaired. This message may be removed once this module has been used on several pages or once it is verified to work as intended.
Details: Functionally complete. Default lists may be adjusted still.
|
| Introspection summary for Module:Category handler
|
Functions provided (2)
| Line
|
Function
|
Params
|
| 130
|
_category_handler (main)
|
(cats, ns_override, suffixes_override, is_debug)
|
| 175
|
category_handler (invokable)
|
(frame)
|
|
|
No function descriptions were provided. The Lua code may have further information.
local getArgs = require("Module:Arguments").getArgs
local yesno = require("Module:Yesno")
local p = {}
-- Basic category handler, based on Wikipedia's category handler. It categorizes
-- pages, given a table of categories as input, and suppresses categorization if
-- the page is in the table of excluded namespaces.
-- The most common categorizing templates that have/require complex rules are:
-- - Infoboxes; these usually shouldn't categorize if they're outside the main
-- namespace.
-- - Certain mboxes; some mboxes categorize certain pages, but they shouldn't
-- categorize their own documentation.
-- Default list of namespaces in which to suppress categorization. Most
-- categorizing templates are expected to be placed in main, template, or
-- module; those that don't are likely special-use templates (like idiosyncratic
-- and editable user page) which likely won't need this module, or templates
-- with very basic categorization rules for which this is overkill.
-- Adjust as needed!
local DEFAULT_SUPPRESSED_NAMESPACES = {
["talk"] = true,
["user"] = true,
["user talk"] = true,
["file talk"] = true,
["mediawiki talk"] = true,
["template talk"] = true,
["help"] = true,
["help talk"] = true,
["category talk"] = true,
["module talk"] = true,
["xenharmonic wiki"] = true,
["xenharmonic wiki talk"] = true,
["media"] = true,
}
-- Inversely, the following namespaces are unsuppressed: main, file, mediawiki,
-- template, category, module
-- Default list of page suffixes in which to suppress categorization.
-- Adjust as needed!
local DEFAULT_SUPPRESSED_SUFFIXES = {
"doc",
"sandbox",
}
-- Helper function: check if current namespace is excluded
-- Accepts an optional table, containing or overriding other namespaces' rules
local function is_suppressed_namespace(title, ns_override)
local ns_text
if type(title) == "table" and title.nsText then
ns_text = mw.ustring.lower(title.nsText or '')
elseif type(title) == "string" then
ns_text = mw.ustring.lower(title)
else
ns_text = mw.ustring.lower(mw.title.getCurrentTitle().nsText or '')
end
local namespaces = {}
for k, v in pairs(DEFAULT_SUPPRESSED_NAMESPACES) do
namespaces[k] = v
end
if type(ns_override) == "table" then
for k, v in pairs(ns_override) do
namespaces[k] = v
end
end
return namespaces[ns_text] or false
end
-- Helper function
-- Checks whether the page title ends in a suppressed suffix
-- Accepts an opiontal table, containing additional suffixes to suppress
-- Suffix and custom suffixes are lowercased to guarantee matching
local function has_suppressed_suffix(title, suffixes_override)
local title_obj
if type(title) == "table" and title.text then
title_obj = title
elseif type(title) == "string" then
title_obj = mw.title.new(title)
else
title_obj = mw.title.getCurrentTitle()
end
local pagename = mw.ustring.lower(title_obj.text or '')
local suffixes = {}
-- Include default suppressed suffixes
for _, suffix in ipairs(DEFAULT_SUPPRESSED_SUFFIXES) do
table.insert(suffixes, suffix)
end
-- Add custom overrides
if type(suffixes_override) == "table" then
for _, suffix in ipairs(suffixes_override) do
table.insert(suffixes, suffix)
end
end
-- Check if the page name ends with any of the suffixes (as subpages)
for _, suffix in ipairs(suffixes) do
suffix = mw.text.trim(mw.ustring.lower(suffix or ''))
if suffix ~= '' then
local pattern = '/' .. mw.ustring.gsub(suffix, '([%^%$%(%)%%%.%[%]%*%+%-%?])', '%%%1') .. '$'
if mw.ustring.match(pagename, pattern) then
return true
end
end
end
return false
end
-- Helper function: strips suffix from title
local function strip_suffix(title, suffix)
local text = title.text
if mw.ustring.sub(text, -mw.ustring.len(suffix)) == suffix then
return mw.title.new(mw.ustring.sub(text, 1, -mw.ustring.len(suffix)-1), title.ns)
end
return title
end
-- "Main" function; can be called by other modules
-- Categorizes a page, given a table of categories
-- Disallows categories if it's in a suppressed namespace or the page has a
-- suppressed suffix (subpage)
function p._category_handler(cats, ns_override, suffixes_override, is_debug)
cats = cats or {}
is_debug = yesno(is_debug, false)
local frame = mw.getCurrentFrame()
local parent_frame = frame:getParent()
local parent_title = parent_frame and mw.title.new(parent_frame:getTitle()) or mw.title.getCurrentTitle()
-- If parent page is a documentation subpage (e.g. ends with /doc), switch to base page
parent_title = strip_suffix(parent_title, "/doc")
local suppressed_ns = is_suppressed_namespace(parent_title, ns_override)
local suppressed_suffix = has_suppressed_suffix(parent_title, suffixes_override)
local is_content = parent_title.isContentPage
if is_debug or suppressed_ns or suppressed_suffix or not is_content then
local reason = is_debug and "debug mode"
or (suppressed_ns and "suppressed namespace")
or (suppressed_suffix and "suppressed suffix")
or (not is_content and "non-content page")
or "unknown"
-- Return a debug comment explaining why categorization was suppressed
return string.format(
"<!-- categorization suppressed: %s; is_debug=%s; suppressed_ns=%s; suppressed_suffix=%s; is_content=%s -->",
reason,
tostring(is_debug),
tostring(suppressed_ns),
tostring(suppressed_suffix),
tostring(is_content)
)
end
local result = ''
for _, cat in ipairs(cats) do
cat = mw.text.trim(cat or '')
if cat ~= '' then
result = result .. string.format('[[Category:%s]]', cat)
end
end
return result
end
-- Wrapper for templates calling via #invoke
function p.category_handler(frame)
local args = getArgs(frame)
local cats_unparsed = args["categories"] or ""
local excluded_ns_unparsed = args["excluded_ns"] or ""
local suffixes_unparsed = args["suffixes"] or ""
local is_debug = yesno(args["debug"], false)
-- Parse categories
local cats = {}
for cat in mw.text.gsplit(cats_unparsed, "[,\n]") do
cat = mw.text.trim(cat)
if cat ~= "" then
table.insert(cats, cat)
end
end
-- Parse excluded namespaces (added/overrides default)
local ns_override = {}
for ns in mw.text.gsplit(excluded_ns_unparsed, "[;\n]") do
ns = mw.text.trim(ns)
if ns ~= "" then
ns_override[ns] = true
end
end
-- Parse excluded suffixes
local suffixes = {}
for suffix in mw.text.gsplit(suffixes_unparsed, "[;\n]") do
suffix = mw.text.trim(suffix)
if suffix ~= "" then
table.insert(suffixes, suffix)
end
end
return p._category_handler(cats, ns_override, suffixes, is_debug)
end
return p