Module:Input parser

From Yugipedia
Revision as of 19:43, 1 April 2024 by Deltaneos (talk | contribs) (`coalesce` isn't defined here.)
Jump to: navigation, search
--[[
Common functions for helping with extracting data from wikitext input
]]--


local inputParser = {}

-- Convert an unordered list (bulleted list) to an array (i.e. table)
-- e.g. `'\n* A\n* B\n* C'` -> `{ 'A', 'B', 'C' }`
--
-- @param text string unordered list in wikitext
-- @return table
function inputParser.ulToArray(text)
	-- No text, return empty table
	if (not text) then return {} end

	-- remove initial `*` and spacing
	local trimmedText = mw.text.trim(text, '* \n')

	-- If the text is empty or only contained whitespace, return empty table 
	if (trimmedText == '') then return {} end

	-- Split by `*`, surrounded in optional spaces
	return mw.text.split(trimmedText, '%s*\*%s*')
end

-- Parse data from a wikitext link
-- e.g. `'[[Metal Fiend Token (manga)|Metal Devil]]'` -> `{ link = 'Metal Fiend Token (manga)', text = 'Metal Devil' }`
-- @param linkInput string
-- @return table
function inputParser.parseLink(linkInput)
	if (not linkInput) then
		return { link = nil, text = nil }
	end

	--[[
	Pattern for a link in wikitext
	- two opening square brackets
	- any number of non-`|` non-`]` characters <-- first capture group
	- optional pipe character
	- optional amount of any characters <-- second capture group
	- two closing square brackets
	]]--
	local pattern = '%[%[([^|%]]*)|?(.-)%]%]'

	-- Store the first capture group as the link
	-- And the second as the display text
	local link, text = linkInput:match(pattern)

	-- If the text doesn't match the pattern, assume there's no link, only text
	if (not link) then
		return { link = nil, text = linkInput }
	end

	-- Use the first capture group a the link
	-- Use the second as the text, or fallback to the first
	return {
		link = link,
		text = (text ~= nil and text ~= '') and text or link
	}
end

--[[
A number of modules accept input formatted like this:
List item 1; // arg1::value1; arg2; arg3::value3
List Item 2; // arg1::value1; arg2; arg3::value3

This function gets the arguments after the double forward slash.

e.g.
Mystical Moon; 800 // debut; mentioned; dub; qty::2
becomes
{ ['debut'] = true, ['mentioned'] = true, ['dub'] = true, ['qty'] = 2 }
]]--
--
-- @param lineText string
-- @return table
function inputParser.getLineArgs(lineText)
	-- Get text after the `//`
	local argsText = mw.text.split(lineText, '%s*//%s*')[2] or ''

	-- Split by semicolons surrounded by any amount of spaces
	-- e.g. `'[[Mystical Moon]] // debut; mentioned; dub; qty::2'`
	-- becomes `{ 'debut', 'mentioned', 'dub', 'qty::2' }`
	local argsArr = mw.text.split(argsText, '%s*;%s*')

	-- Pattern for matching two pieces of text separated by a double semicolon
	local pattern = '(.*)::(.*)'
	
	local args = {}

	-- Parse the named variables in the list
	-- e.g. `{ 'debut', 'mentioned', 'dub', 'qty::2' }`
	-- becomes `{ 'debut', 'mentioned', 'dub', ['qty'] = 2 }
	for _, arg in pairs(argsArr) do
		local param, value = arg:match(pattern)
		
		if (not param) then
			-- table.insert(args, arg)
			args[arg] = true
		else
			args[param] = value
		end
	end

	return args
end

return inputParser