Jump to content

Module:Data to Table: Difference between revisions

From The Petit Planet Wiki
ReisuDesign (talk | contribs)
No edit summary
ReisuDesign (talk | contribs)
No edit summary
Line 16: Line 16:
-- Escape characters
-- Escape characters
local function clean(txt)
local function clean(txt)
txt = txt:gsub('&(%a+;)', '&%1')
return txt
:gsub('\'', '\\'')
:gsub('\\', '\\\\')
:gsub('<', '&lt;')
:gsub('\'', '\\\'')
:gsub('\'', '\\\'')
return txt
end
end


Line 177: Line 175:


-- Wrap output in syntaxhighlight
-- Wrap output in syntaxhighlight
local luaText = tostring(result)
-- Decode HTML entities introduced by mw.html
luaText = mw.text.decode(luaText)
local output = frame:extensionTag(
local output = frame:extensionTag(
'syntaxhighlight',
'syntaxhighlight',
tostring(result),
luaText,
{
{
lang = 'lua',
lang = 'lua',
copy = ''
copy = ''
}
}
)
)





Revision as of 11:10, 8 September 2026

Module documentation

This module implements {{Data to Table}}.

local p = {}

local CleanTT = require('Module:tt').CleanTT
local lib = require('Module:Feature')
local ne = lib.isNotEmpty

local block = false

-- Check if the entry is the first on the level
local first = {true, true, true}

-- Check if the entry is right after the end of a deeper level
local previous = {false, false, false}


-- Escape characters
local function clean(txt)
	return txt
		:gsub('\\', '\\\\')
		:gsub('\'', '\\\'')
end


function p.main(frame)
	local info = {}
	local dataKeys = {}
	local rawKeys = {}

	-- Parse DPL data
	if frame.args.info then
		if ne(frame.args.cleanTT) then
			frame.args.info = CleanTT(frame.args.info)
		end

		info = lib.parseTemplateFormat(
			frame.args.info,
			';;',
			'$$$',
			'=='
		)
	else
		return ''
	end

	-- Parse keys
	if frame.args.keys then
		dataKeys = p.ParseKeys(frame.args.keys)
	end

	-- Parse unquoted/raw keys
	if frame.args.unquoted then
		rawKeys = p.ParseKeys(frame.args.unquoted)
	end

	-- Block formatting
	if ne(frame.args.block) then
		block = true
	end

	local sortkey = frame.args.sortkey or 'page'
	local subtable = frame.args.subtable


	-- Check whether a key should be output as raw Lua
	local function isUnquotedKey(key)
		for _, rawKey in ipairs(rawKeys) do
			if rawKey == key then
				return true
			end
		end

		return false
	end


	-- Build result
	local result = mw.html.create()
		:wikitext('return {\n')


	for _, entry in lib.spairs(
		info,
		function(tVal, a, b)
			if sortkey == 'INPUT' then
				return a < b
			else
				return (tVal[a][sortkey] or '') < (tVal[b][sortkey] or '')
			end
		end
	) do

		if ne(entry.page) then
			entry.page = clean(entry.page)

			-- No data keys: output page as a simple string
			if #dataKeys == 0 then

				result:wikitext(
					'\t\'',
					entry.page,
					'\',\n'
				)

			else

				-- Reset formatting state for every entry
				first = {true, true, true}
				previous = {false, false, false}

				local valid = false
				local values = mw.html.create()

				-- Entry name
				values:wikitext(
					'\t[\'',
					entry.page,
					'\'] = {'
				)

				-- Build entry
				local function parseLevels(K, level)
					level = level or 1

					if type(K) == 'string' then

						valid = true

						-- Use the value if present.
						-- BuildEntry handles missing values.
						values:node(
							p.BuildEntry(
								entry[K],
								K,
								level,
								subtable,
								isUnquotedKey(K)
							)
						)

					elseif type(K) == 'table' then

						level = level + 1

						for _, K2 in ipairs(K) do
							parseLevels(K2, level)
						end

						values:wikitext(
							'\n',
							string.rep('\t', level - 1),
							'},'
						)
					end
				end

				parseLevels(dataKeys, 1)

				-- Return table if there is valid data
				if valid then
					values:wikitext('\n')
					result:node(values)
				else
					result:wikitext(
						'\t\'',
						entry.page,
						'\',\n'
					)
				end
			end
		end
	end

	result:wikitext('}')


	-- Wrap output in syntaxhighlight
	local luaText = tostring(result)
	
	-- Decode HTML entities introduced by mw.html
	luaText = mw.text.decode(luaText)
	
	local output = frame:extensionTag(
		'syntaxhighlight',
		luaText,
		{
			lang = 'lua',
			copy = ''
		}
)


	-- Copy button
	if frame.args.copy then
		output = require('Module:CopyText')._main({
			output,
			frame.args.copy,
			'Copy Table'
		})
	end

	return output
end


-- Format data
function p.BuildEntry(value, key, level, subtable, unquoted)
	level = level or 1

	local container = mw.html.create()

	-- Default missing values
	if value == nil or value == '' then

		if key == 'number' then
			value = '0'
			unquoted = true
		else
			value = ''
			unquoted = false
		end
	end


	-- Format value
	if subtable and value ~= '' and value:find(subtable) then

		value = lib.split(
			clean(value),
			subtable
		)

		value = '{ \'' ..
			table.concat(value, '\', \'') ..
			' }'

	elseif unquoted and value ~= '' then

		-- Raw Lua value
		value = clean(value)

	else

		-- String value
		value = '\'' ..
			clean(value) ..
			'\''

	end


	-- Format key as ['key']
	local formattedKey =
		'[\'' .. clean(key) .. '\']'


	-- First item on this level
	if first[level] then

		container:wikitext(
			'\n',
			string.rep('\t', level),
			formattedKey,
			' = ',
			value,
			','
		)

		first[level] = false

		if level > 2 then
			first[2] = false
		end

		if level > 1 then
			first[1] = false
		end


	-- Subsequent item on this level
	else

		container:wikitext(
			'\n',
			string.rep('\t', level),
			formattedKey,
			' = ',
			value,
			','
		)

		previous[level] = false

	end

	return container
end


-- Parse data keys into specified levels
function p.ParseKeys(keys)
	keys = lib.split(keys, ';;')

	for i, key in pairs(keys) do

		if key:find('//') then

			local keys2 = lib.split(key, '//')

			for i2, key2 in pairs(keys2) do

				if key2:find('@@') then
					keys2[i2] = lib.split(key, '@@')
				end

			end

			keys[i] = keys2
		end
	end

	return keys
end


return p