Jump to content

Module:Nested Lists

From The Petit Planet Wiki
Revision as of 11:32, 3 September 2026 by ReisuDesign (talk | contribs)
Module documentation

This module implements {{Nested Lists}}.

local p = {}

local exists = require('Module:Exists')

local levels = {
	[''] = 0,
	['//'] = 1,
	['$$'] = 2,
	['%%'] = 3,
	['&&'] = 4,
}

function p.main(frame)
	local args = require('Module:Arguments').getArgs(frame, {
		parentFirst = true,
		wrapper = {'Template:Nested Lists'}
	})

	return p._main(args)
end

function p._main(args)
	local input = args[1] or ''
	local link = args.link == '1'
	local iconFormat = args.icon
	local iconSize = args.icon_size or '25'

	-- Allow icon_size to be written as either 25 or 25px.
	iconSize = mw.text.trim(tostring(iconSize))
	iconSize = mw.ustring.gsub(iconSize, '[pP][xX]$', '')

	if iconSize == '' then
		iconSize = '25'
	end

	local output = {}

	-- Each semicolon separates an item.
	for item in mw.text.gsplit(input, ';', true) do
		item = mw.text.trim(item)

		if item ~= '' then
			local marker = ''
			local text = item

			-- Determine indentation marker.
			local prefix = mw.ustring.sub(item, 1, 2)

			if levels[prefix] ~= nil then
				marker = prefix
				text = mw.text.trim(mw.ustring.sub(item, 3))
			end

			local level = levels[marker] or 0

			-- [no] disables the icon for this individual item.
			local noIcon = false

			if mw.ustring.sub(text, 1, 4) == '[no]' then
				noIcon = true
				text = mw.text.trim(mw.ustring.sub(text, 5))
			end

			-- Separate page target and display label.
			--
			-- Example:
			-- Princess Peach|Peach
			--
			-- target = Princess Peach
			-- label  = Peach
			local target = text
			local label = text

			local separator = mw.ustring.find(text, '|', 1, true)

			if separator then
				target = mw.text.trim(mw.ustring.sub(text, 1, separator - 1))
				label = mw.text.trim(mw.ustring.sub(text, separator + 1))
			end

			-- Check whether the target page exists.
			local pageExists = false

			if link and target ~= '' then
				pageExists = exists.checkExists(target)
			end

			-- Generate the icon.
			local icon = ''

			if iconFormat and iconFormat ~= '' and not noIcon then
				-- {item} always uses the raw page target,
				-- never the generated wiki link or display label.
				local iconName = mw.ustring.gsub(
					iconFormat,
					'{item}',
					function()
						return target
					end
				)

				if pageExists then
					icon = string.format(
						'[[File:%s|%spx|link=%s]]',
						iconName,
						iconSize,
						target
					)
				else
					icon = string.format(
						'[[File:%s|%spx]]',
						iconName,
						iconSize
					)
				end
			end

			-- Generate the text.
			local displayText = label

			if pageExists then
				displayText = '[[' .. target .. '|' .. label .. ']]'
			end

			-- Combine icon and text.
			local content = displayText

			if icon ~= '' then
				content = icon .. ' ' .. displayText
			end

			table.insert(
				output,
				string.rep('*', level + 1) .. ' ' .. content
			)
		end
	end

	return table.concat(output, '\n')
end

return p