Module:Category handler: Difference between revisions
Jump to navigation
Jump to search
Created page with "-- This module follows User:Ganaram inukshuk/Provisional style guide for Lua 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, or table of excluded -- suffixes (subpages). -- The most common categorizing templates that have/require complex rules are: --..." |
ArrowHead294 (talk | contribs) m Wikitext debugger option |
||
| (33 intermediate revisions by one other user not shown) | |||
| Line 1: | Line 1: | ||
-- This module follows [[User:Ganaram inukshuk/Provisional style guide for Lua]] | -- This module follows [[User:Ganaram inukshuk/Provisional style guide for Lua]] | ||
local getArgs = require("Module:Arguments").getArgs | |||
local yesno = require("Module:Yesno") | local yesno = require("Module:Yesno") | ||
| Line 11: | Line 12: | ||
-- - Infoboxes; these usually shouldn't categorize if they're outside the main | -- - Infoboxes; these usually shouldn't categorize if they're outside the main | ||
-- namespace. | -- namespace. | ||
-- - Certain mboxes; some mboxes categorize | -- - Certain mboxes; some mboxes categorize pages, but if that mbox categorizes | ||
-- categorize their own | -- templates/modules and are placed on that page's /doc subpage, it should | ||
-- categorize the page on which the documentation is transcluded, not the /doc | |||
-- page itself. | |||
-- - Categorizing templates used on their own /doc pages as examples; a special | |||
-- case of the previous case; passing in debug=1 disables all categorization. | |||
-- Default list of namespaces in which to suppress categorization. Most | -- Default list of namespaces in which to suppress categorization. Most | ||
| Line 21: | Line 26: | ||
-- Adjust as needed! | -- Adjust as needed! | ||
local DEFAULT_SUPPRESSED_NAMESPACES = { | local DEFAULT_SUPPRESSED_NAMESPACES = { | ||
["main"] = false, | |||
["talk"] = true, | ["talk"] = true, | ||
["user"] = true, | ["user"] = true, | ||
| Line 44: | Line 50: | ||
"sandbox", | "sandbox", | ||
} | } | ||
-- List of namespace aliases | |||
-- For "main", this is so editors can type in "main" since the main namespace's | |||
-- actual name is "". For "xw"-related namespaces, these are shorthands. | |||
local NAMESPACE_ALIASES = { | |||
[""] = "main", -- "" is treated as "main" | |||
["xw"] = "xenharmonic wiki", -- Shorthand | |||
["xw talk"] = "xenharmonic wiki talk" -- Shorthand | |||
} | |||
-- Helper function | |||
-- Converts namespace aliases to their actual names | |||
-- Must be placed before is_suppressed_namespace() | |||
local function normalize_ns(ns) | |||
ns = mw.ustring.lower(mw.text.trim(ns or "")) -- Convert to lowercase and and trim extra spaces | |||
if ns == "" then ns = "main" end -- Empty-string is assumed to be "main" | |||
if NAMESPACE_ALIASES[ns] then | |||
return NAMESPACE_ALIASES[ns] | |||
end | |||
return ns | |||
end | |||
-- Helper function: check if current namespace is excluded | -- Helper function: check if current namespace is excluded | ||
-- Accepts an optional table, containing or overriding other namespaces' rules | -- Accepts an optional table, containing or overriding other namespaces' rules | ||
local function is_suppressed_namespace(ns_override) | local function is_suppressed_namespace(ns_override) | ||
-- Get current namespace, as lowercase | -- Get current namespace, or aliased namespace, as lowercase | ||
local curr_ns = | local curr_ns = normalize_ns(mw.title.getCurrentTitle().nsText) | ||
-- Build table of suppressed namespaces; start with default list | -- Build table of suppressed namespaces; start with default list | ||
local namespaces = {} | local namespaces = {} | ||
for k, v in pairs(DEFAULT_SUPPRESSED_NAMESPACES) do | for k, v in pairs(DEFAULT_SUPPRESSED_NAMESPACES) do | ||
namespaces[k] = v | namespaces[normalize_ns(k)] = v | ||
end | end | ||
| Line 60: | Line 87: | ||
if type(ns_override) == "table" then | if type(ns_override) == "table" then | ||
for k, v in pairs(ns_override) do | for k, v in pairs(ns_override) do | ||
namespaces[k] = v | namespaces[normalize_ns(k)] = v | ||
end | end | ||
end | end | ||
| Line 107: | Line 134: | ||
-- Disallows categories if it's in a suppressed namespace or the page has a | -- Disallows categories if it's in a suppressed namespace or the page has a | ||
-- suppressed suffix (subpage) | -- suppressed suffix (subpage) | ||
function p._category_handler(cats, ns_override, suffixes | function p._category_handler(cats, is_debug, ns_override, suffixes) | ||
local cats = cats or {} | local cats = cats or {} | ||
local is_debug = yesno(is_debug, false) | local is_debug = yesno(is_debug, false) | ||
| Line 134: | Line 161: | ||
return result | return result | ||
end | end | ||
-- Wrapper for templates calling via #invoke | -- Wrapper for templates calling via #invoke | ||
function p.category_handler(frame) | function p.category_handler(frame) | ||
local args = frame | local args = getArgs(frame) | ||
local | local excluded_ns_unparsed = args["excluded_ns"] or "" -- Additional namespaces to exclude (EG, a template that should not be used within main namespace, which is allowed by default) | ||
local | local allowed_ns_unparsed = args["allowed_ns" ] or "" -- Namespaces to allow; overrides default list (EG, a template that should be used within user namespace, which is disallowed by default) | ||
local suffixes_unparsed = args["suffixes" ] or "" | local suffixes_unparsed = args["suffixes" ] or "" -- Additional page suffixes in which to disallow categories | ||
local is_debug = yesno(args["debug"], false) | local is_debug = yesno(args["debug"], false) -- Parse debug mode; setting this to TRUE disables all categories | ||
local wtext = yesno(args["wtext"]) -- Used to show the underlying Wikitext | |||
-- Parse categories | -- Parse categories | ||
-- Categories are entered using unnamed params | |||
local cats = {} | local cats = {} | ||
for cat in | for _, cat in ipairs(args) do | ||
cat = mw.text.trim(cat) | cat = mw.text.trim(cat) | ||
if cat ~= "" then | if cat ~= "" then | ||
| Line 162: | Line 190: | ||
if ns ~= "" then | if ns ~= "" then | ||
ns_override[ns] = true | ns_override[ns] = true | ||
end | |||
end | |||
-- Parse allowed namespaces | |||
-- This gets added to the ns_override array, with values set to FALSE | |||
-- EG, Template:TODO is used in several namespaces that are normally | |||
-- suppressed: user, talk, help, and maybe xw talk | |||
for ns in mw.text.gsplit(allowed_ns_unparsed, "[;\n]") do | |||
ns = mw.text.trim(ns) | |||
if ns ~= "" then | |||
ns_override[ns] = false | |||
end | end | ||
end | end | ||
| Line 174: | Line 213: | ||
end | end | ||
local result = p._category_handler(cats, is_debug, ns_override, suffixes) | |||
if wtext then | |||
result = "<syntaxhighlight lang=\"wikitext\">" .. result .. "</syntaxhighlight>" | |||
end | |||
return frame:preprocess(result) | |||
end | end | ||
return p | return p | ||
Latest revision as of 23:19, 5 December 2025
- This module may be invoked by templates using its corresponding template Template:Category handler, or used directly from other modules.
| Introspection summary for Module:Category handler | |||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
| ||||||||||||||||||
No function descriptions were provided. The Lua code may have further information.
-- This module follows [[User:Ganaram inukshuk/Provisional style guide for Lua]]
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, or table of excluded
-- suffixes (subpages).
-- 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 pages, but if that mbox categorizes
-- templates/modules and are placed on that page's /doc subpage, it should
-- categorize the page on which the documentation is transcluded, not the /doc
-- page itself.
-- - Categorizing templates used on their own /doc pages as examples; a special
-- case of the previous case; passing in debug=1 disables all categorization.
-- 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 = {
["main"] = false,
["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",
}
-- List of namespace aliases
-- For "main", this is so editors can type in "main" since the main namespace's
-- actual name is "". For "xw"-related namespaces, these are shorthands.
local NAMESPACE_ALIASES = {
[""] = "main", -- "" is treated as "main"
["xw"] = "xenharmonic wiki", -- Shorthand
["xw talk"] = "xenharmonic wiki talk" -- Shorthand
}
-- Helper function
-- Converts namespace aliases to their actual names
-- Must be placed before is_suppressed_namespace()
local function normalize_ns(ns)
ns = mw.ustring.lower(mw.text.trim(ns or "")) -- Convert to lowercase and and trim extra spaces
if ns == "" then ns = "main" end -- Empty-string is assumed to be "main"
if NAMESPACE_ALIASES[ns] then
return NAMESPACE_ALIASES[ns]
end
return ns
end
-- Helper function: check if current namespace is excluded
-- Accepts an optional table, containing or overriding other namespaces' rules
local function is_suppressed_namespace(ns_override)
-- Get current namespace, or aliased namespace, as lowercase
local curr_ns = normalize_ns(mw.title.getCurrentTitle().nsText)
-- Build table of suppressed namespaces; start with default list
local namespaces = {}
for k, v in pairs(DEFAULT_SUPPRESSED_NAMESPACES) do
namespaces[normalize_ns(k)] = v
end
-- Then extend/override list using ns_override, if available
if type(ns_override) == "table" then
for k, v in pairs(ns_override) do
namespaces[normalize_ns(k)] = v
end
end
-- Return; if no namespace found, default to false
return namespaces[curr_ns] 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(suffixes_override)
local title = mw.title.getCurrentTitle()
local pagename = mw.ustring.lower(title.text)
-- Build table of suppressed suffixes, start with default suffixes
local suffixes = {}
for _, suffix in ipairs(DEFAULT_SUPPRESSED_SUFFIXES) do
table.insert(suffixes, suffix)
end
-- Then append additional suffixes, if available (append, not replace)
if type(suffixes_override) == "table" then
for _, suffix in ipairs(suffixes_override) do
table.insert(suffixes, suffix)
end
end
-- Find and match suffix
for _, suffix in ipairs(suffixes) do
suffix = mw.ustring.lower(mw.text.trim(suffix or '')) -- Also normalize
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
-- "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, is_debug, ns_override, suffixes)
local cats = cats or {}
local is_debug = yesno(is_debug, false)
-- Test values; should be commented out for normal use
--local cats = cats or {"Abstract MOS patterns", "7-tone scales"}
--local ns_override = ns_override or { ["module"] = true }
-- If in a suppressed namespace/prefix, or in debug mode (suppresses ALL
-- categorization) don't bother
if is_suppressed_namespace(ns_override)
or has_suppressed_suffix(suffixes)
or is_debug then
return ''
end
-- Otherwise, categorize
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 excluded_ns_unparsed = args["excluded_ns"] or "" -- Additional namespaces to exclude (EG, a template that should not be used within main namespace, which is allowed by default)
local allowed_ns_unparsed = args["allowed_ns" ] or "" -- Namespaces to allow; overrides default list (EG, a template that should be used within user namespace, which is disallowed by default)
local suffixes_unparsed = args["suffixes" ] or "" -- Additional page suffixes in which to disallow categories
local is_debug = yesno(args["debug"], false) -- Parse debug mode; setting this to TRUE disables all categories
local wtext = yesno(args["wtext"]) -- Used to show the underlying Wikitext
-- Parse categories
-- Categories are entered using unnamed params
local cats = {}
for _, cat in ipairs(args) do
cat = mw.text.trim(cat)
if cat ~= "" then
table.insert(cats, cat)
end
end
-- Parse excluded namespaces
-- These are added in addition to the default list
-- This currently can't force-allow suppressed namespaces as template input,
-- only disallow additional namespaces
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 allowed namespaces
-- This gets added to the ns_override array, with values set to FALSE
-- EG, Template:TODO is used in several namespaces that are normally
-- suppressed: user, talk, help, and maybe xw talk
for ns in mw.text.gsplit(allowed_ns_unparsed, "[;\n]") do
ns = mw.text.trim(ns)
if ns ~= "" then
ns_override[ns] = false
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
local result = p._category_handler(cats, is_debug, ns_override, suffixes)
if wtext then
result = "<syntaxhighlight lang=\"wikitext\">" .. result .. "</syntaxhighlight>"
end
return frame:preprocess(result)
end
return p