Module:InfoboxCharacterCategories: Difference between revisions
Making the module |
Tweaking how it outputs links in the infobox |
||
| Line 2: | Line 2: | ||
-- Purpose: | -- Purpose: | ||
-- 1) Auto-categorize character pages based on *infobox parameters* so editors | -- 1) Auto-categorize character pages based on *infobox parameters* so editors | ||
-- don't have to | -- don't have to duplicate manual [[Category:...]] tags at the bottom. | ||
-- 2) | -- 2) Format selected infobox fields so the *displayed* values link to the | ||
-- | -- relevant category pages (not to nonexistent article pages). | ||
-- | -- | ||
-- Rules ( | -- Rules (per your requests): | ||
-- - residence: ignored (no categories) | -- - residence: ignored (no categories, no special formatting) | ||
-- - affiliation: ONLY linked items | -- - affiliation: ONLY linked items become categories. Plain text is ignored. | ||
-- affiliation = [[Cheer squad]], [[Senior friend group]] | -- affiliation = [[Cheer squad]], [[Senior friend group]] | ||
-- -> [[Category:Cheer squad]][[Category:Senior friend group]] | -- -> page categories: [[Category:Cheer squad]][[Category:Senior friend group]] | ||
-- - occupation: hardcoded mapping from occupation -> category (pluralization | -- -> infobox display: links point to [[:Category:Cheer squad]] etc. | ||
-- Student -> Students | -- - occupation: hardcoded mapping from occupation -> category (for pluralization). | ||
-- Burger-Tron employee -> Burger-Tron employees | -- Student -> Category:Students | ||
-- Roseville cinema employee -> Roseville cinema employees | -- Burger-Tron employee -> Category:Burger-Tron employees | ||
-- School faculty -> School faculty | -- Roseville cinema employee -> Category:Roseville cinema employees | ||
-- School faculty -> Category:School faculty | |||
-- Works whether the editor wrote Student bare or as [[Student]]. | |||
-- | -- | ||
-- Optional: | -- Optional: | ||
| Line 27: | Line 29: | ||
if s == "" then return nil end | if s == "" then return nil end | ||
return s | return s | ||
end | |||
-- Build a link to a category page without categorizing the current page. | |||
-- Example: [[:Category:Students|Student]] | |||
local function catlink(cat, label) | |||
cat = trim(cat) | |||
label = trim(label) or cat | |||
if not cat then return "" end | |||
return ("[[:Category:%s|%s]]"):format(cat, label) | |||
end | end | ||
| Line 44: | Line 55: | ||
end | end | ||
-- Split a | -- Split a list like "Student, Burger-Tron employee" | ||
-- Also handles someone typing a link; we strip links to their target for matching. | -- Also handles someone typing a link; we strip links to their target for matching. | ||
local function split_list(wikitext) | local function split_list(wikitext) | ||
| Line 74: | Line 85: | ||
local function lookup_occupation_category(occupation) | local function lookup_occupation_category(occupation) | ||
occupation = trim(occupation) | |||
if not occupation then return nil end | if not occupation then return nil end | ||
-- Exact match first | -- Exact match first | ||
if OCCUPATION_TO_CATEGORY[occupation] then | if OCCUPATION_TO_CATEGORY[occupation] then | ||
return OCCUPATION_TO_CATEGORY[occupation] | return OCCUPATION_TO_CATEGORY[occupation] | ||
end | end | ||
-- Case-insensitive match | -- Case-insensitive match | ||
local lower = mw.ustring.lower(occupation) | local lower = mw.ustring.lower(occupation) | ||
| Line 89: | Line 103: | ||
end | end | ||
-- Formatter used by the infobox display: | -- Formatter used by the infobox display for occupation. | ||
-- | -- Always links recognized occupations to their CATEGORY pages. | ||
-- | -- Examples: | ||
-- | -- "Student" -> [[:Category:Students|Student]] | ||
-- "[[Student]]" -> [[:Category:Students|Student]] | |||
-- "Student, Burger-Tron employee" -> both linked to their categories | |||
function p.formatOccupation(frame) | function p.formatOccupation(frame) | ||
local raw = frame.args[1] or frame.args.value | local raw = frame.args[1] or frame.args.value | ||
raw = trim(raw) | raw = trim(raw) | ||
if not raw then return "" end | if not raw then return "" end | ||
local parts = split_list(raw) | local parts = split_list(raw) | ||
if #parts == 0 then return raw end | if #parts == 0 then return raw end | ||
for i, part in ipairs(parts) do | for i, part in ipairs(parts) do | ||
local cat = lookup_occupation_category(part) | |||
parts[i] = ( | if cat then | ||
-- Display singular label, link to plural category. | |||
parts[i] = catlink(cat, part) | |||
else | |||
parts[i] = part | |||
end | end | ||
end | end | ||
| Line 118: | Line 130: | ||
end | end | ||
-- Category emission used at the bottom of the template. | -- Formatter used by the infobox display for affiliation. | ||
-- Converts any wikilinks into links to the corresponding CATEGORY page: | |||
-- [[Cheer squad]] -> [[:Category:Cheer squad|Cheer squad]] | |||
-- [[Cheer squad|Squad]] -> [[:Category:Cheer squad|Squad]] | |||
-- Plain text remains unchanged. | |||
function p.formatAffiliation(frame) | |||
local raw = frame.args[1] or frame.args.value | |||
raw = trim(raw) | |||
if not raw then return "" end | |||
-- Replace [[Target|Label]] first | |||
raw = raw:gsub("%[%[([^%]|#]+)%|([^%]]+)%]%]", function(target, label) | |||
target = trim(target) | |||
label = trim(label) | |||
if not target or not label then return "" end | |||
return catlink(target, label) | |||
end) | |||
-- Replace [[Target]] | |||
raw = raw:gsub("%[%[([^%]|#]+)%]%]", function(target) | |||
target = trim(target) | |||
if not target then return "" end | |||
return catlink(target, target) | |||
end) | |||
return raw | |||
end | |||
-- Category emission used at the bottom of the infobox template. | |||
function p.categories(frame) | function p.categories(frame) | ||
local args = frame:getParent().args | local args = frame:getParent().args | ||
Latest revision as of 02:25, 5 January 2026
Documentation for this module may be created at Module:InfoboxCharacterCategories/doc
-- Module:InfoboxCharacterCategories
-- Purpose:
-- 1) Auto-categorize character pages based on *infobox parameters* so editors
-- don't have to duplicate manual [[Category:...]] tags at the bottom.
-- 2) Format selected infobox fields so the *displayed* values link to the
-- relevant category pages (not to nonexistent article pages).
--
-- Rules (per your requests):
-- - residence: ignored (no categories, no special formatting)
-- - affiliation: ONLY linked items become categories. Plain text is ignored.
-- affiliation = [[Cheer squad]], [[Senior friend group]]
-- -> page categories: [[Category:Cheer squad]][[Category:Senior friend group]]
-- -> infobox display: links point to [[:Category:Cheer squad]] etc.
-- - occupation: hardcoded mapping from occupation -> category (for pluralization).
-- Student -> Category:Students
-- Burger-Tron employee -> Category:Burger-Tron employees
-- Roseville cinema employee -> Category:Roseville cinema employees
-- School faculty -> Category:School faculty
-- Works whether the editor wrote Student bare or as [[Student]].
--
-- Optional:
-- - pass |nocat=yes in the infobox to suppress categorization (useful for sandbox/test pages)
local p = {}
local function trim(s)
if s == nil then return nil end
s = mw.text.trim(s)
if s == "" then return nil end
return s
end
-- Build a link to a category page without categorizing the current page.
-- Example: [[:Category:Students|Student]]
local function catlink(cat, label)
cat = trim(cat)
label = trim(label) or cat
if not cat then return "" end
return ("[[:Category:%s|%s]]"):format(cat, label)
end
-- Extract link targets like [[Cheer squad]] or [[Cheer squad|Squad]].
-- Returns just the link target ("Cheer squad").
local function extract_link_targets(wikitext)
local targets = {}
if not wikitext or wikitext == "" then return targets end
for target in wikitext:gmatch("%[%[([^%]|#]+)") do
target = trim(target)
if target then
targets[#targets + 1] = target
end
end
return targets
end
-- Split a list like "Student, Burger-Tron employee"
-- Also handles someone typing a link; we strip links to their target for matching.
local function split_list(wikitext)
local out = {}
if not wikitext or wikitext == "" then return out end
-- Convert any links to their target text for matching.
-- Example: [[Student]] -> Student ; [[Foo|Bar]] -> Foo
local s = wikitext:gsub("%[%[([^%]|#]+)[^%]]*%]%]", "%1")
-- Normalize separators
s = s:gsub("<br%s*/?>", ",")
s = s:gsub("[;\n]", ",")
for part in mw.text.gsplit(s, ",", true) do
part = trim(part)
if part then out[#out + 1] = part end
end
return out
end
-- Hardcoded occupation -> category mapping
local OCCUPATION_TO_CATEGORY = {
["School faculty"] = "School faculty",
["Student"] = "Students",
["Burger-Tron employee"] = "Burger-Tron employees",
["Roseville cinema employee"] = "Roseville cinema employees",
}
local function lookup_occupation_category(occupation)
occupation = trim(occupation)
if not occupation then return nil end
-- Exact match first
if OCCUPATION_TO_CATEGORY[occupation] then
return OCCUPATION_TO_CATEGORY[occupation]
end
-- Case-insensitive match
local lower = mw.ustring.lower(occupation)
for k, v in pairs(OCCUPATION_TO_CATEGORY) do
if mw.ustring.lower(k) == lower then
return v
end
end
return nil
end
-- Formatter used by the infobox display for occupation.
-- Always links recognized occupations to their CATEGORY pages.
-- Examples:
-- "Student" -> [[:Category:Students|Student]]
-- "[[Student]]" -> [[:Category:Students|Student]]
-- "Student, Burger-Tron employee" -> both linked to their categories
function p.formatOccupation(frame)
local raw = frame.args[1] or frame.args.value
raw = trim(raw)
if not raw then return "" end
local parts = split_list(raw)
if #parts == 0 then return raw end
for i, part in ipairs(parts) do
local cat = lookup_occupation_category(part)
if cat then
-- Display singular label, link to plural category.
parts[i] = catlink(cat, part)
else
parts[i] = part
end
end
return table.concat(parts, ", ")
end
-- Formatter used by the infobox display for affiliation.
-- Converts any wikilinks into links to the corresponding CATEGORY page:
-- [[Cheer squad]] -> [[:Category:Cheer squad|Cheer squad]]
-- [[Cheer squad|Squad]] -> [[:Category:Cheer squad|Squad]]
-- Plain text remains unchanged.
function p.formatAffiliation(frame)
local raw = frame.args[1] or frame.args.value
raw = trim(raw)
if not raw then return "" end
-- Replace [[Target|Label]] first
raw = raw:gsub("%[%[([^%]|#]+)%|([^%]]+)%]%]", function(target, label)
target = trim(target)
label = trim(label)
if not target or not label then return "" end
return catlink(target, label)
end)
-- Replace [[Target]]
raw = raw:gsub("%[%[([^%]|#]+)%]%]", function(target)
target = trim(target)
if not target then return "" end
return catlink(target, target)
end)
return raw
end
-- Category emission used at the bottom of the infobox template.
function p.categories(frame)
local args = frame:getParent().args
local nocat = trim(args.nocat)
if nocat and (nocat == "yes" or nocat == "y" or nocat == "true" or nocat == "1") then
return ""
end
local cats = {}
-- Occupation categories (mapped)
local occ = trim(args.occupation)
if occ then
for _, part in ipairs(split_list(occ)) do
local cat = lookup_occupation_category(part)
if cat then
cats[#cats + 1] = ("[[Category:%s]]"):format(cat)
end
end
end
-- Affiliation categories (ONLY linked items)
local aff = trim(args.affiliation)
if aff then
for _, target in ipairs(extract_link_targets(aff)) do
cats[#cats + 1] = ("[[Category:%s]]"):format(target)
end
end
-- De-dupe
local seen, out = {}, {}
for _, c in ipairs(cats) do
if not seen[c] then
seen[c] = true
out[#out + 1] = c
end
end
return table.concat(out)
end
return p