Jump to content
Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Module:Subject index

From Calima Saga Wiki
Revision as of 06:09, 29 October 2026 by WikiAdmin (talk | contribs) (World pages as dictionaries grouped by letter)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Documentation for this module may be created at Module:Subject index/doc

-- Module:Subject index
-- Every subject of one kind (from the Cargo table Subjects, filled by
-- {{Appears in}}), as a dictionary grouped under the initial letter of its
-- name in the page's language. A leading article is ignored for sorting and
-- grouping, so "The Old Warrior" files under O and "La Cábala" under C.
--
--   {{#invoke:Subject index|main|kind=faction|lang=es}}
--   kind: character, faction, place, belief or force
--   lang: es or ca for a translation; empty for English
--   work: optional, only subjects appearing in that work

local p = {}

local ARTICLES = {
	en = { 'The ' },
	es = { 'El ', 'La ', 'Los ', 'Las ' },
	ca = { 'El ', 'La ', 'Els ', 'Les ', "L'", 'En ', 'Na ' },
}
local PLAIN = {
	['Á'] = 'A', ['À'] = 'A', ['É'] = 'E', ['È'] = 'E', ['Í'] = 'I', ['Ï'] = 'I',
	['Ó'] = 'O', ['Ò'] = 'O', ['Ú'] = 'U', ['Ü'] = 'U', ['Ç'] = 'C', ['Ñ'] = 'N',
	['á'] = 'a', ['à'] = 'a', ['é'] = 'e', ['è'] = 'e', ['í'] = 'i', ['ï'] = 'i',
	['ó'] = 'o', ['ò'] = 'o', ['ú'] = 'u', ['ü'] = 'u', ['ç'] = 'c', ['ñ'] = 'n',
}
local NONE = { en = "''None yet.''", es = "''Ninguno todavía.''", ca = "''Encara cap.''" }

local function plain(s)
	return (mw.ustring.gsub(s, '.', PLAIN))
end

-- The name without its leading article: what the dictionary sorts on.
local function sortName(name, lang)
	for _, article in ipairs(ARTICLES[lang] or ARTICLES.en) do
		local n = mw.ustring.len(article)
		if mw.ustring.sub(name, 1, n) == article and mw.ustring.len(name) > n then
			return mw.ustring.sub(name, n + 1)
		end
	end
	return name
end

function p.main(frame)
	local args = frame.args
	local kind = mw.text.trim(args.kind or '')
	local lang = mw.text.trim(args.lang or '')
	if lang == '' then
		lang = 'en'
	end
	local where = "kind='" .. kind:gsub("'", '') .. "'"
	local work = mw.text.trim(args.work or '')
	if work ~= '' then
		where = where .. " AND works HOLDS '" .. work:gsub("'", '') .. "'"
	end
	local rows = mw.ext.cargo.query('Subjects', '_pageName=page,name_es=name_es,name_ca=name_ca',
		{ where = where, limit = 5000 })

	local items = {}
	for _, row in ipairs(rows) do
		local name = row.page
		local target = row.page
		if lang ~= 'en' then
			local translated = row['name_' .. lang]
			if translated and translated ~= '' then
				name = translated
			end
			local t = mw.title.new(row.page .. '/' .. lang)
			if t and t.exists then
				target = row.page .. '/' .. lang
			end
		end
		local key = plain(sortName(name, lang))
		local letter = mw.ustring.upper(mw.ustring.sub(key, 1, 1))
		if not letter:match('^%u$') then
			letter = '#'
		end
		table.insert(items, { name = name, target = target, key = mw.ustring.lower(key), letter = letter })
	end
	if #items == 0 then
		return NONE[lang] or NONE.en
	end
	table.sort(items, function(a, b)
		return a.key < b.key
	end)

	local groups, letters = {}, {}
	for _, item in ipairs(items) do
		if not groups[item.letter] then
			groups[item.letter] = {}
			table.insert(letters, item.letter)
		end
		table.insert(groups[item.letter], item)
	end

	local anchor = function(letter)
		return 'letter-' .. (letter == '#' and 'other' or letter)
	end
	local out, bar = {}, {}
	for _, letter in ipairs(letters) do
		table.insert(bar, '[[#' .. anchor(letter) .. '|' .. letter .. ']]')
	end
	table.insert(out, '<div class="calima-letters">' .. table.concat(bar, ' ') .. '</div>')
	table.insert(out, '<div class="calima-dict">')
	for _, letter in ipairs(letters) do
		table.insert(out, '<div class="calima-dict__group">')
		table.insert(out, '<div class="calima-dict__letter" id="' .. anchor(letter) .. '">' .. letter .. '</div>')
		for _, item in ipairs(groups[letter]) do
			table.insert(out, '<div class="calima-dict__item">[[' .. item.target .. '|' .. item.name .. ']]</div>')
		end
		table.insert(out, '</div>')
	end
	table.insert(out, '</div>')
	return table.concat(out, '\n')
end

return p