Editing Module:Data to Table

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision Your text
Line 1: Line 1:
local p = {}
local p = {}
local CleanTT = require('Module:tt').CleanTT
local CleanTT = require('Module:tt').CleanTT
local lib = require('Module:Feature')
local lib = require('Module:Feature')
local ne = lib.isNotEmpty
local ne = lib.isNotEmpty
local block = false
local block = false
 
--check for if the entry is the first on the level
-- Check if the entry is the first on the level
local first = {true, true, true}
local first = {true, true, true}
 
--check for if the entry is right after the end of a deeper level
-- Check if the entry is right after the end of a deeper level
local previous = {false, false, false}
local previous = {false, false, false}


 
--escape characters
-- Escape characters for Lua strings
local function clean(txt)
local function clean(txt)
txt = txt:gsub('&(%a+;)','&amp;%1'):gsub('\'','\\&#39;'):gsub('<', '&lt;'):gsub('\'', '\\\'')
return txt
return txt
:gsub('\\', '\\\\')
:gsub('\'', '\\\'')
end
end
-- Parse DPL data
local function parseInfo(info, frame)
if not info then
return {}
end
if ne(frame.args.cleanTT) then
info = CleanTT(info)
end
return lib.parseTemplateFormat(
info,
';;',
'$$$',
'=='
)
end
-- Get grouped JSON data
local function getJsonGroups(frame)
local groups = {}
local i = 1
while true do
local groupName = frame.args['group' .. i]
local groupInfo = frame.args['group' .. i .. '_info']
-- Stop when neither argument exists.
if groupName == nil and groupInfo == nil then
break
end
if ne(groupName) and groupInfo ~= nil then
local info = parseInfo(groupInfo, frame)
local entries = {}
-- Collect entries
for _, entry in lib.spairs(
info,
function(tVal, a, b)
local aPage = tostring(tVal[a].page or a)
local bPage = tostring(tVal[b].page or b)
return aPage < bPage
end
) do
if ne(entry.page) then
entries[#entries + 1] = entry.page
end
end
-- Only add the group if it actually contains entries.
if #entries > 0 then
groups[groupName] = entries
end
end
i = i + 1
end
return groups
end
-- Format grouped data as readable JSON
function p.FormatJSONGroups(groups)
local result = {}
table.insert(result, '{')
-- Get group names
local groupNames = {}
for name in pairs(groups) do
groupNames[#groupNames + 1] = name
end
table.sort(groupNames)
-- Build each group
for i, name in ipairs(groupNames) do
local entries = groups[name]
local groupComma = (i < #groupNames) and ',' or ''
table.insert(
result,
'\t' ..
mw.text.jsonEncode(name) ..
': ['
)
for j, entry in ipairs(entries) do
local entryComma = (j < #entries) and ',' or ''
table.insert(
result,
'\t\t' ..
mw.text.jsonEncode(entry) ..
entryComma
)
end
table.insert(
result,
'\t]' .. groupComma
)
end
table.insert(result, '}')
return table.concat(result, '\n')
end


function p.main(frame)
function p.main(frame)
local info = {}
local info = {}
local dataKeys = {}
local dataKeys = {}
local rawKeys = {}
-- ============================================================
-- JSON MODE
-- ============================================================
if tostring(frame.args.json) == '1' then
-- --------------------------------------------------------
-- Grouped JSON mode
-- --------------------------------------------------------
local groups = getJsonGroups(frame)
-- If groups were supplied, output the complete JSON object.
if next(groups) ~= nil then
local jsonText = p.FormatJSONGroups(groups)
return frame:extensionTag(
'syntaxhighlight',
jsonText,
{
lang = 'json',
copy = ''
}
)
end
-- --------------------------------------------------------
-- Simple JSON array mode
-- --------------------------------------------------------
if frame.args.info then
info = parseInfo(frame.args.info, frame)
local jsonEntries = {}
for _, entry in lib.spairs(
info,
function(tVal, a, b)
local aPage = tostring(tVal[a].page or a)
local bPage = tostring(tVal[b].page or b)
return aPage < bPage
end
) do
if ne(entry.page) then
jsonEntries[#jsonEntries + 1] = entry.page
end
end
local jsonText = mw.text.jsonEncode(jsonEntries)
return frame:extensionTag(
'syntaxhighlight',
jsonText,
{
lang = 'json',
copy = ''
}
)
end
return ''
end
-- ============================================================
-- NORMAL LUA MODE
-- ============================================================
-- Parse DPL data
if frame.args.info then
if frame.args.info then
 
if ne(frame.args.cleanTT) then frame.args.info = CleanTT(frame.args.info) end -- remove TTs
info = parseInfo(frame.args.info, frame)
info = lib.parseTemplateFormat(frame.args.info, ';;', '$$$', '==')
 
else return '' end
else
if frame.args.keys then dataKeys = p.ParseKeys(frame.args.keys) end
return ''
if ne(frame.args.block) then block = true end
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 sortkey = frame.args.sortkey or 'page'
local subtable = frame.args.subtable
local subtable = frame.args.subtable
 
 
local result = mw.html.create('pre'):css({['min-height'] = '25px',['line-height'] = '16px'}):wikitext('return {\n')
-- Constant value mode
local items = {}
-- If |value=day is supplied, every page gets that value.
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
local constantValue = frame.args.value
local valueUnquoted = false
 
if constantValue ~= nil then
 
for _, rawKey in ipairs(rawKeys) do
 
if rawKey == 'value' then
valueUnquoted = true
break
end
 
end
 
end
 
 
-- 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
if ne(entry.page) then
entry.page = clean(entry.page)
entry.page = clean(entry.page)
 
if #dataKeys == 0 then
 
result:wikitext('\t\'', entry.page, '\',\n')
-- ----------------------------------------------------
-- Constant value mode
-- ----------------------------------------------------
 
if constantValue ~= nil and #dataKeys == 0 then
 
local value
 
if valueUnquoted then
value = clean(constantValue)
else
value = '\'' ..
clean(constantValue) ..
'\''
end
 
result:wikitext(
'\t[\'',
entry.page,
'\'] = ',
value,
',\n'
)
 
 
-- ----------------------------------------------------
-- No data keys
-- ----------------------------------------------------
 
elseif #dataKeys == 0 then
 
result:wikitext(
'\t\'',
entry.page,
'\',\n'
)
 
 
-- ----------------------------------------------------
-- Normal nested table mode
-- ----------------------------------------------------
 
else
else
-- Reset formatting state for every entry
first = {true, true, true}
first = {true, true, true}
previous = {false, false, false}
previous = {false, false, false}
local valid = false
local valid = false
local values = mw.html.create()
local values = mw.html.create()
 
values:wikitext('\t[\'', entry.page, '\']')
 
-- Entry name
--build entry
values:wikitext(
'\t[\'',
entry.page,
'\'] = {'
)
 
 
-- Build entry
local function parseLevels(K, level)
local function parseLevels(K, level)
level = level or 1
level = level or 1
 
if type(K) == 'string' and ne(entry[K]) then
if type(K) == 'string' then
 
valid = true
valid = true
 
values:node(p.BuildEntry(entry[K], K, level, subtable))
-- 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
elseif type(K) == 'table' then
level = level + 1
level = level + 1
for _, K2 in ipairs(K) do
for _, K2 in ipairs(K) do
parseLevels(K2, level)
parseLevels(K2, level)
end
end
 
values:wikitext((block and ('\n' .. string.rep('\t', level-1)) or ' '),'},\n')
values:wikitext(
'\n',
string.rep('\t', level - 1),
'},'
)
 
end
end
end
end
parseLevels(dataKeys, 1)
parseLevels(dataKeys, 1)
 
 
--return table is any valid data, return plain string otherwise
-- Return table if there is valid data
if valid then
if valid then
values:wikitext('\n')
result:node(values)
result:node(values)
else
else
 
result:wikitext('\t\'', entry.page, '\',\n')
result:wikitext(
'\t\'',
entry.page,
'\',\n'
)
 
end
end
end
end
end
    end
end
end
result:wikitext('}')
result:wikitext('}')
 
 
-- ============================================================
-- LUA SYNTAX HIGHLIGHT
-- ============================================================
 
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
-- ============================================================
 
-- Keep Module:CopyText for normal Lua output.
if frame.args.copy then
if frame.args.copy then
 
result = require('Module:CopyText')._main({ tostring(result), frame.args.copy, 'Copy Table' })
output = require('Module:CopyText')._main({
output,
frame.args.copy,
'Copy Table'
})
 
end
end
 
 
return result
return output
end
end


 
--format data
-- ================================================================
function p.BuildEntry(value, key, level, subtable)
-- FORMAT DATA
-- ================================================================
 
function p.BuildEntry(value, key, level, subtable, unquoted)
 
level = level or 1
level = level or 1
local container = mw.html.create()
local container = mw.html.create()
 
if ne(value) then
 
if subtable and value:find(subtable) then
-- Default missing values
value = lib.split(clean(value), subtable)
if value == nil or value == '' then
value = '{ \'' .. table.concat(value, '\', \'') .. '\' }'
 
if key == 'number' then
 
value = '0'
unquoted = true
 
else
else
 
value = '\'' .. clean(value) .. '\''
value = ''
unquoted = false
 
end
end
end
if first[level] then
 
container:wikitext(' = {', (block and ('\n' .. string.rep('\t', level)) or ' '), clean(key), ' = ', value)
 
first[level] = false
-- Format value
if level > 2 then first[2] = false end
if subtable and value ~= '' and value:find(subtable) then
if level > 1 then first[1] = false end
 
elseif (not first[level]) then
value = lib.split(
container:wikitext((block and (',\n' .. string.rep('\t', level)) or ', '), clean(key), ' = ', value)
clean(value),
previous[level] = false
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
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
end
return container
return container
end
end


 
--parse data keys into specified levels
-- ================================================================
-- PARSE DATA KEYS INTO SPECIFIED LEVELS
-- ================================================================
 
function p.ParseKeys(keys)
function p.ParseKeys(keys)
keys = lib.split(keys, ';;')
keys = lib.split(keys, ';;')
for i, key in pairs(keys) do
for i, key in pairs(keys) do
if key:find('//') then
if key:find('//') then
local keys2 = lib.split(key, '//')
local keys2 = lib.split(key, '//')
for i2, key2 in pairs(keys2) do
for i2, key2 in pairs(keys2) do
if key2:find('@@') then
if key2:find('@@') then
keys2[i2] = lib.split(key, '@@')
keys2[i2] = lib.split(key, '@@')
end
end
end
end
keys[i] = keys2
keys[i] = keys2
end
end
end
end
return keys
return keys
end
end


return p
return p
Please note that all contributions to The Petit Planet Wiki are considered to be released under the Creative Commons Attribution-ShareAlike (see Petit Planet Wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!
Cancel Editing help (opens in new window)
Preview page with this template
Below are commonly used wikitext from MediaWiki:Edittools. Click on any to insert them in the edit box.
File Pages==Summary====Licensing=={{Fairuse}}{{File|}}
Dynamic Page List¦²«»²{¦}²«»«/»«!----»
Array in DPL¹^2{}^2^2{¹}^2
Parser Functions{{#if:||}}
{{#ifeq:|||}}
{{#expr:}}
{{#switch:||#default=}}
{{#replace:||}}
{{#titleparts:}}
{{#tag:|}}
Markup{{}}|[][[]][[Category:]]#REDIRECT [[]] [[Category:Redirect Pages]]<code></code><includeonly></includeonly><noinclude></noinclude><nowiki></nowiki><!----><br>§
Notices{{Stub|}}{{Stub Dialogue}}{{Upcoming}}{{Under Construction}}{{Placeholder|}}
Magic Words{{!}}{{formatnum:}}{{lc:}}{{uc:}}{{PAGENAME}}{{FULLPAGENAME}}{{ROOTPAGENAME}}{{BASEPAGENAME}}{{SUBPAGENAME}}{{DISPLAYTITLE:|noreplace}}__TOC____NOTOC____EXPECTUNUSEDCATEGORY____HIDDENCAT__
HTML Entities&mdash;&nbsp;&comma;&shy;