Module:PageContext

Current answers. Practical procedures. Reliable reference.
Revision as of 21:16, 24 August 2026 by Sythan (talk | contribs) (Create centralized page context resolver for article eyebrows)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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

-- Module:PageContext
-- Centralized EDFM page section resolver for Article header eyebrows.
-- Keep page-specific overrides small; prefer structured datasets and family rules.

local p = {}
local config = mw.loadData('Module:Data/PageSections')

local cache = {}

local function trim(value)
	return mw.text.trim(tostring(value or ''))
end

local function isNonEmpty(value)
	return value ~= nil and trim(value) ~= ''
end

local function normalizeTitle(pageName)
	if isNonEmpty(pageName) then
		local t = mw.title.new(trim(pageName))
		return t and t.text or trim(pageName)
	end
	return mw.title.getCurrentTitle().text
end

local function loadLuaData(title)
	local ok, data = pcall(mw.loadData, title)
	if ok and type(data) == 'table' then return data end
	return nil
end

local function loadJsonPage(titleText)
	local title = mw.title.new(titleText)
	local content = title and title:getContent()
	if not content then return nil end
	local ok, data = pcall(mw.text.jsonDecode, content)
	if ok and type(data) == 'table' then return data end
	return nil
end

local function listContains(list, title)
	if type(list) ~= 'table' then return false end
	for _, value in ipairs(list) do
		if value == title then return true end
	end
	return false
end

local function pageInEngineers(title)
	local index = loadJsonPage('Module:Data/Engineers/index')
	return listContains(index, title)
end

local function pageInShipModules(title)
	local index = loadLuaData('Module:Data/ShipModules/index')
	return listContains(index, title)
end

local function pageInModulesJson(title)
	local index = loadJsonPage('Module:Data/Modules/index')
	if type(index) ~= 'table' or type(index.modules) ~= 'table' then return false end
	for _, record in pairs(index.modules) do
		if type(record) == 'table' and (record.page == title or record.name == title) then
			return true
		end
	end
	return false
end

local function pageInMiningDataset(title, dataTitle, field)
	local data = loadLuaData(dataTitle)
	if type(data) ~= 'table' then return false end
	for _, record in ipairs(data) do
		if type(record) == 'table' and (record[field or 'page'] == title or record.page == title or record.label == title or record.title == title) then
			return true
		end
	end
	return false
end

local function guardianLike(title)
	return title:find('Guardian', 1, true) ~= nil or title:find('Nanite Torpedo', 1, true) ~= nil
end

local function thargoidLike(title)
	return title:find('Thargoid', 1, true) ~= nil or title:find('Xeno', 1, true) ~= nil or title:find('AX ', 1, true) ~= nil or title:find('Caustic', 1, true) ~= nil
end

local function startsWith(value, prefix)
	return value:sub(1, #prefix) == prefix
end

local function typeToSection(pageType)
	return config.typeToSection and config.typeToSection[pageType]
end

function p.getPageTypeValue(pageName)
	local title = normalizeTitle(pageName)
	if cache['type:' .. title] then return cache['type:' .. title] end
	local pageType = nil

	if pageInEngineers(title) then
		pageType = 'engineer'
	elseif pageInMiningDataset(title, 'Module:Data/Mining/Methods') then
		pageType = 'mining_method'
	elseif pageInMiningDataset(title, 'Module:Data/Mining/Equipment') then
		pageType = 'mining_equipment'
	elseif pageInMiningDataset(title, 'Module:Data/Mining/Locations') then
		pageType = 'mining_location'
	elseif pageInMiningDataset(title, 'Module:Data/Mining/Commodities') then
		pageType = 'mining_commodity'
	elseif pageInMiningDataset(title, 'Module:Data/Procedures/Mining', 'page') then
		pageType = 'field_procedure'
	elseif pageInShipModules(title) or pageInModulesJson(title) then
		if guardianLike(title) then
			pageType = 'guardian_module'
		elseif thargoidLike(title) then
			pageType = 'thargoid_module'
		else
			pageType = 'ship_module'
		end
	end

	cache['type:' .. title] = pageType or ''
	return pageType
end

function p.getSectionValue(pageName, override)
	local title = normalizeTitle(pageName)
	if isNonEmpty(override) then return trim(override) end
	local key = 'section:' .. title
	if cache[key] then return cache[key] end

	local section = nil
	local exact = config.exactSections or {}
	if exact[title] then
		section = exact[title]
	else
		local pageType = p.getPageTypeValue(title)
		section = typeToSection(pageType)
	end

	if not section then
		for _, rule in ipairs(config.familyRules or {}) do
			if rule.prefix and startsWith(title, rule.prefix) then
				section = rule.section
				break
			end
		end
	end

	if not section then
		for _, rule in ipairs(config.titleContainsRules or {}) do
			if rule.text and title:find(rule.text, 1, true) then
				section = rule.section
				break
			end
		end
	end

	section = section or config.fallback or 'Reference'
	cache[key] = section
	return section
end

function p.getPageType(frame)
	local args = frame.args or {}
	return p.getPageTypeValue(args.page or args[1]) or ''
end

function p.getSection(frame)
	local args = frame.args or {}
	return p.getSectionValue(args.page or args[1], args.section or args.override)
end

function p.eyebrow(frame)
	local args = frame.args or {}
	return 'EDFM // ' .. p.getSectionValue(args.page or args[1], args.section or args.override)
end

return p