Module:Section List

From Honkai: Nexus Anima Wiki
Jump to navigation Jump to search

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

local p = {}
local lib = require('Module:Feature')

function p.removeComments(pageContents)
	return pageContents
		:gsub('<!%-%-.-%-%->', '') -- remove comments
		:gsub('<%s*pre.-%s*>.-<%s*/%s*pre%s*>', '') -- remove <pre> tags
end

function p.listSections(pageContents, startLevel, maxLevel)
	local list = {}
	
	pageContents = p.removeComments(pageContents)
	
	startLevel = startLevel or 1
	maxLevel = maxLevel or 10
		
	local pattern = '\n(' .. string.rep('=', startLevel + 1) .. string.rep('=?', maxLevel - 2) .. ')([^=]+)%1'
	local parents = {}
	
	for levelString, sectName in pageContents:gmatch(pattern) do
		sectName = sectName
			:gsub('{{Icon.-}}', '') -- remove icon templates
			:gsub('%[%[File:.-%]%]', '') -- remove images
			:gsub('^%s+', '') -- remove leading whitespace
			:gsub('%s+$', '') -- remove trailing whitespace
			:gsub(' ([%?%.%!])', '&#32;%1') -- mediawiki parser forces nbsp before punctuation bc french or smth
		
		local level = #levelString - startLevel
		parents[level] = sectName
		for i = level + 1, #parents do
			parents[i] = nil
		end
		
		table.insert(list, copy(parents))
	end
	
	return list
end

function copy(tab)
	local new = {}
	for i,v in pairs(tab) do
		new[i] = v
	end
	return new
end

function p.listLoadingScreens(pageContents)
	local list = {}
	
	pageContents = p.removeComments(pageContents)
	
	for name in pageContents:gmatch("\n%*%s*'''(%[?%[?[^\n]+%]?%]?):'''") do
		name = name
			:gsub('{{LS|(.-)}}', '%1') -- remove {{LS}}
			:gsub('.+|', '') -- remove page and only keep label
			:gsub('[%[%]]', '') -- remove square brackets from links
			
		table.insert(list, name)
	end
	
	return list
end

function loadPage(pageTitle, fragment)
	local title = mw.title.makeTitle('', pageTitle, fragment)
	assert(title, 'Invalid or unknown page title')
	
	local pageContents = title:getContent()
	assert(pageContents, 'Specified page does not exist')
	
	return pageContents
end

function p.loadSections(pageTitle, fragment, startLevel, maxLevel)
	return p.listSections(loadPage(pageTitle, fragment), startLevel, maxLevel)
end

function p.loadLoadingScreens(pageTitle, fragment)
	return p.listLoadingScreens(loadPage(pageTitle, fragment))
end

function p.mapToLua(map)
	local out = mw.html.create('pre'):wikitext('return {\n')
	
	local keys = {}
	for k in pairs(map) do
		table.insert(keys, k)
	end
	
	table.sort(keys)
	
	for _, k in ipairs(keys) do
		local v = map[k]
		k = k:gsub('"', '\\"'):gsub('\n', '\\n')
		v = v:gsub('"', '\\"'):gsub('\n', '\\n')
		out:wikitext('\t["', k, '"] = "', v, '",\n')
	end
	
	out:wikitext('}')
	
	return out
end

function p.sectionMap(frame)
	local result = p._sectionMap(frame.args.pages or frame.args[1], frame.args.start_level, frame.args.max_level, frame.args.asLuaCode == '1' or frame.args.copy)
	
	if frame.args.copy then
		result = require('Module:CopyText')._main({ tostring(result), frame.args.copy, 'Copy Table' })
	end
	
	return result
end

function p.loadingScreenMap(frame)
	local result = p._loadingScreenMap(frame.args.pages or frame.args[1], frame.args.asLuaCode == '1' or frame.args.copy)
	
	if frame.args.copy then
		result = require('Module:CopyText')._main({ tostring(result), frame.args.copy, 'Copy Table' })
	end
	
	return result
end

function p._sectionMap(pageArray, startLevel, maxLevel, asLuaCode)
	if (type(pageArray) == 'string') then
		pageArray = lib.split(pageArray, '$$$', { removeEmpty = true })
	end
	
	local map = {}
	
	for _, pageTitle in ipairs(pageArray) do
		local overrideTitle, overrideStartLevel, overrideMaxLevel = pageTitle:match('^(.+)=(%d+):(%d+)$')
		
		overrideStartLevel = tonumber(overrideStartLevel)
		overrideMaxLevel = tonumber(overrideMaxLevel)
		pageTitle = (overrideStartLevel ~= nil and overrideTitle) or pageTitle
		
		local duplicates = {}
		
		for _, segments in ipairs(p.loadSections(pageTitle, nil, overrideStartLevel or startLevel, overrideMaxLevel or maxLevel)) do
			local hash = segments[#segments]
			local n = duplicates[hash]
			if n then
				duplicates[hash] = duplicates[hash] + 1
			end
			duplicates[hash] = (n or 1) + 1
			map[table.concat(segments, '/')] = pageTitle .. '#' .. hash .. (n and (' ' .. n) or '')
		end
	end
	
	if (asLuaCode) then
		return p.mapToLua(map)
	else
		return map
	end
end

function p._loadingScreenMap(pageArray, asLuaCode)
	if (type(pageArray) == 'string') then
		pageArray = lib.split(pageArray, '$$$', { removeEmpty = true })
	end
	
	local map = {}
	
	for _, pageTitle in ipairs(pageArray) do
		for _, section in ipairs(p.loadLoadingScreens(pageTitle)) do
			map[section] = pageTitle
		end
	end
	
	if (asLuaCode) then
		return p.mapToLua(map)
	else
		return map
	end
end

return p