Module:Data to Table: Difference between revisions
Appearance
ReisuDesign (talk | contribs) Created page with "local p = {} local CleanTT = require('Module:tt').CleanTT local lib = require('Module:Feature') local ne = lib.isNotEmpty local block = false --check for if the entry is the first on the level local first = {true, true, true} --check for if the entry is right after the end of a deeper level local previous = {false, false, false} --escape characters local function clean(txt) txt = txt:gsub('&(%a+;)','&%1'):gsub('\'','\\''):gsub('<', '<'):gsub('\'', '\\\'') r..." |
ReisuDesign (talk | contribs) No edit summary |
||
| 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 if the entry is the first on the level | |||
local first = {true, true, true} | local first = {true, true, true} | ||
-- | |||
-- 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 | |||
local function clean(txt) | local function clean(txt) | ||
txt = txt:gsub('&(%a+;)','&%1'):gsub('\'','\\''):gsub('<', '<'):gsub('\'', '\\\'') | txt = txt:gsub('&(%a+;)', '&%1') | ||
:gsub('\'', '\\'') | |||
:gsub('<', '<') | |||
:gsub('\'', '\\\'') | |||
return txt | return txt | ||
end | end | ||
function p.main(frame) | function p.main(frame) | ||
local info = {} | local info = {} | ||
local dataKeys = {} | local dataKeys = {} | ||
local rawKeys = {} | |||
-- 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 | if ne(frame.args.cleanTT) then | ||
info = lib.parseTemplateFormat(frame.args.info, ';;', '$$$', '==') | frame.args.info = CleanTT(frame.args.info) | ||
else return '' end | end | ||
if frame.args.keys then dataKeys = p.ParseKeys(frame.args.keys) end | |||
if ne(frame.args.block) then block = true 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 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') | |||
-- 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('pre') | |||
:css({ | |||
['min-height'] = '25px', | |||
['line-height'] = '16px' | |||
}) | |||
:wikitext('return {\n') | |||
local items = {} | local items = {} | ||
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 | |||
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) | ||
-- No data keys: output page as a simple string | |||
if #dataKeys == 0 then | if #dataKeys == 0 then | ||
result:wikitext('\t\'', entry.page, '\',\n') | |||
result:wikitext( | |||
'\t\'', | |||
entry.page, | |||
'\',\n' | |||
) | |||
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 | |||
-- | 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 | |||
if type(K) == 'string' and entry[K] ~= nil then | |||
valid = true | valid = true | ||
values:node(p.BuildEntry(entry[K], K, level, subtable)) | |||
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( | |||
values:wikitext( | |||
block | |||
and ('\n' .. string.rep('\t', level - 1)) | |||
or ' ', | |||
'},' | |||
) | |||
end | end | ||
end | end | ||
parseLevels(dataKeys, 1) | parseLevels(dataKeys, 1) | ||
-- | -- Return table if there is valid data, | ||
-- otherwise return the page as a plain string | |||
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 | ||
result:wikitext('}') | result:wikitext('}') | ||
-- Copy button | |||
if frame.args.copy then | if frame.args.copy then | ||
result = require('Module:CopyText')._main({ tostring(result), frame.args.copy, 'Copy Table' }) | result = require('Module:CopyText')._main({ | ||
tostring(result), | |||
frame.args.copy, | |||
'Copy Table' | |||
}) | |||
end | end | ||
return result | return result | ||
end | end | ||
-- | |||
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 | |||
-- Keep empty values | |||
if value ~= nil then | |||
-- Format value | |||
if subtable and value:find(subtable) then | if subtable and value:find(subtable) then | ||
value = lib.split(clean(value), subtable) | |||
value = '{ \'' .. table.concat(value, '\', \'') .. | value = lib.split( | ||
clean(value), | |||
subtable | |||
) | |||
value = '{ \'' .. | |||
table.concat(value, '\', \'') .. | |||
' }' | |||
elseif unquoted then | |||
-- Raw Lua value | |||
value = clean(value) | |||
else | else | ||
value = '\'' .. clean(value) .. '\'' | |||
-- String value | |||
value = '\'' .. | |||
clean(value) .. | |||
'\'' | |||
end | end | ||
-- Format key as ['key'] | |||
local formattedKey = | |||
'[\'' .. clean(key) .. '\']' | |||
-- First item on this level | |||
if first[level] then | if first[level] then | ||
container:wikitext( | |||
container:wikitext( | |||
'\n', | |||
string.rep('\t', level), | |||
formattedKey, | |||
' = ', | |||
value, | |||
',' | |||
) | |||
first[level] = false | first[level] = false | ||
if level > 2 then first[2] = false end | |||
if level > 1 then first[1] = false end | if level > 2 then | ||
first[2] = false | |||
container:wikitext( | 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 | previous[level] = false | ||
end | end | ||
end | end | ||
return container | return container | ||
end | end | ||
-- | |||
-- 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 | ||
Revision as of 17:08, 3 September 2026
| Main | Documentation | Usage |
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)
txt = txt:gsub('&(%a+;)', '&%1')
:gsub('\'', '\\'')
:gsub('<', '<')
:gsub('\'', '\\\'')
return txt
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('pre')
:css({
['min-height'] = '25px',
['line-height'] = '16px'
})
:wikitext('return {\n')
local items = {}
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' and entry[K] ~= nil then
valid = true
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(
block
and ('\n' .. string.rep('\t', level - 1))
or ' ',
'},'
)
end
end
parseLevels(dataKeys, 1)
-- Return table if there is valid data,
-- otherwise return the page as a plain string
if valid then
values:wikitext('\n')
result:node(values)
else
result:wikitext(
'\t\'',
entry.page,
'\',\n'
)
end
end
end
end
result:wikitext('}')
-- Copy button
if frame.args.copy then
result = require('Module:CopyText')._main({
tostring(result),
frame.args.copy,
'Copy Table'
})
end
return result
end
-- Format data
function p.BuildEntry(value, key, level, subtable, unquoted)
level = level or 1
local container = mw.html.create()
-- Keep empty values
if value ~= nil then
-- Format value
if subtable and value:find(subtable) then
value = lib.split(
clean(value),
subtable
)
value = '{ \'' ..
table.concat(value, '\', \'') ..
' }'
elseif unquoted 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
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