Module:ListUtils
Documentation for this module may be created at Module:ListUtils/doc
-- Module:ListUtils
local p = {}
-- Helper: trim whitespace
local function trim(s)
if not s then return '' end
return (mw.ustring.gsub(s, '^%s*(.-)%s*$', '%1'))
end
-- Helper: is already a wikilink like [[Foo]] or [[Foo|Bar]]
local function isLinked(s)
return mw.ustring.match(s, '%[%[') ~= nil
end
-- Helper: strip existing [[...]] to normalize before relinking
local function stripLinks(s)
s = mw.ustring.gsub(s, '%[%[', '')
s = mw.ustring.gsub(s, '%]%]', '')
return s
end
-- Public: turn "A, B , [[C|X]] , D" into "[[A]], [[B]], [[C|X]], [[D]]"
function p.linkifyCommaList(frame)
local raw = frame.args[1] or ''
raw = trim(raw)
if raw == '' then return '' end
-- Split on commas (allowing messy spacing)
local parts = mw.text.split(raw, ',')
local out = {}
local seen = {}
for _, part in ipairs(parts) do
local s = trim(part)
if s ~= '' then
-- Keep already-linked entries as-is
if isLinked(s) then
if not seen[s] then
table.insert(out, s)
seen[s] = true
end
else
-- Normalize any accidental brackets then relink
local plain = stripLinks(s)
plain = trim(plain)
-- Deduplicate by plain text
if not seen[plain] then
table.insert(out, '[[' .. plain .. ']]')
seen[plain] = true
end
end
end
end
return table.concat(out, ', ')
end
--------------------------------------------------------------------
-- Generic helper for comma lists → categories + SMW properties
--------------------------------------------------------------------
-- Internal helper: works on raw strings
local function catsAndPropsFromList(list, property, catNs)
list = trim(list or '')
if list == '' then
return ''
end
catNs = catNs or 'Category'
local parts = mw.text.split(list, ',')
local out = {}
local seen = {}
for _, part in ipairs(parts) do
local s = trim(part)
if s ~= '' then
-- Normalize to plain page name
local plain = stripLinks(s)
-- Handle links like [[Foo|Label]]
plain = mw.ustring.match(plain, '([^|]+)') or plain
plain = trim(plain)
if plain ~= '' and not seen[plain] then
-- Category link (optional if catNs ~= '')
if catNs ~= '' then
table.insert(out, '[[' .. catNs .. ':' .. plain .. ']]')
end
-- Property annotation (hidden label so nothing shows)
if property and property ~= '' then
table.insert(out, '[[' .. property .. '::' .. plain .. '| ]]')
end
seen[plain] = true
end
end
end
return table.concat(out, ' ')
end
-- Internal: props only
local function propsFromList(list, property)
list = trim(list or '')
if list == '' or not property or property == '' then
return ''
end
local parts = mw.text.split(list, ',')
local out = {}
local seen = {}
for _, part in ipairs(parts) do
local s = trim(part)
if s ~= '' then
local plain = stripLinks(s)
plain = mw.ustring.match(plain, '([^|]+)') or plain
plain = trim(plain)
if plain ~= '' and not seen[plain] then
table.insert(out, '[[' .. property .. '::' .. plain .. '| ]]')
seen[plain] = true
end
end
end
return table.concat(out, ' ')
end
-- Public: generic #invoke entry point
-- Examples:
-- {{#invoke:ListUtils|catsAndProps|Environment, Energy|HasVertical}}
-- {{#invoke:ListUtils|catsAndProps
-- | list = Environment, Energy
-- | property = HasVertical
-- | catns = Category
-- }}
function p.catsAndProps(frame)
local list = frame.args.list or frame.args[1] or ''
local property = frame.args.property or frame.args[2] or ''
local catNs = frame.args.catns or frame.args.categoryNamespace or frame.args[3] or 'Category'
return catsAndPropsFromList(list, property, catNs)
end
-- Public: props-only entry point
-- {{#invoke:ListUtils|propsOnly|A, B, C|HasThing}}
-- {{#invoke:ListUtils|propsOnly|list=A, B, C|property=HasThing}}
function p.propsOnly(frame)
local list = frame.args.list or frame.args[1] or ''
local property = frame.args.property or frame.args[2] or ''
return propsFromList(list, property)
end
return p