Output Lua Table To Html File |
|
-- dontspamme_samlie@yahoo.com
-- Converts Lua table to HTML output in table.html file function tohtml(x) ret = tohtml_table(x,1) writefile("table.html", ret) os.execute("table.html") return(ret) end -- Saves a string to file function writefile(filename, value) if (value) then local file = io.open(filename,"w+") file:write(value) file:close() end end -- Flattens a table to html output function tohtml_table(x, table_level) local k, s, tcolor local html_colors = { "#339900","#33CC00","#669900","#666600","#FF3300", "#FFCC00","#FFFF00","#CCFFCC","#CCCCFF","#CC66FF", "#339900","#33CC00","#669900","#666600","#FF3300", "#FFCC00","#FFFF00","#CCFFCC","#CCCCFF","#CC66FF" } local lineout = {} local tablefound = false if type(x) == "table" then s = "" k = 1 local i, v = next(x) while i do if (type(v) == "table") then if (table_level<10) then lineout[k] = "<b>" .. flat(i) .. "</b>".. tohtml_table(v, table_level + 1) else lineout[k] = "<b>MAXIMUM LEVEL BREACHED</b>" end tablefound = true else lineout[k] = flat(i) .. "=" .. tohtml_table(v) end k = k + 1 i, v = next(x, i) end for k,line in ipairs(lineout) do if (tablefound) then s = s .. "<tr><td>" .. line .. "</td></tr>\n" else s = s .. "<td>" .. line .. "</td>\n" end end if not (tablefound) then s = "<table border='1' bgcolor='#FFFFCC' cellpadding='5' cellspacing='0'>" .. "<tr>" .. s .. "</tr></table>\n" else tcolor = html_colors[table_level] s = "<table border='3' bgcolor='"..tcolor.."' cellpadding='10' cellspacing='0'>" .. s .. "</table>\n" end return s end if type(x) == "function" then return "FUNC" end if type(x) == "file" then return "FILE" end return tostring(x) end -- Flattens a table to string function flat(x) return toflat(x,1) end -- Flattens a table to string function toflat(x, tlevel) local s tlevel = tlevel + 1 if type(x) == "table" then s = "{" local i, v = next(x) while i do if (tlevel < 15) then s = s .. i .. "=" .. toflat(v, tlevel) else s = s .. i .. "={#}" end i, v = next(x, i) if i then s = s .. ", " end end return s .. "}\n" end if type(x) == "function" then return "FUNC" end if type(x) == "file" then return "FILE" end return tostring(x) end
Here is a more advanced implementation, with expand/collapsing and handling cycles. (See warning in comments before use.)
-- Example dumping Lua tables to HTML for debugging. -- -- Warning: not complete or well tested. This is only intended -- as an example/starting point. Clean it up if used in production. -- -- (c) 2008 David Manura (2008-12) -- Licensed under the same terms as Lua (MIT license). local ids = {} local current_id = 0 local count = {} local from = {} local format = string.format local function htmlize(s) --FIX: improve? s = s:gsub('&', '&') s = s:gsub('<', '<') s = s:gsub('>', '>') return s end local function output(s) io.stdout:write(s) end local function analyze_tree(o) if type(o) == 'table' then if count[o] then count[o] = count[o] + 1 else count[o] = 1 current_id = current_id + 1 ids[o] = current_id local this_id = current_id for k,v in pairs(o) do analyze_tree(k) analyze_tree(v) if type(k) == 'table' then from[k] = from[k] or {}; from[k][o] = this_id .. '.' .. ids[k] end if type(v) == 'table' then from[v] = from[v] or {}; from[v][o] = this_id .. '.' .. (ids[k] or tostring(k)) end end end end end local function output_html(o) if type(o) == 'table' then local is_empty = next(o) == nil output( format('<a name="%d"></a>', ids[o]) .. '<div class="table">' .. (is_empty and '(empty)' or ('<a href="javascript:toggle(' .. ids[o] .. ')">[toggle]</a>')) .. format([[Table ID %d]], ids[o]) .. (type(o.tag) == 'string' and ('[Tag=' .. o.tag .. ']') or '') .. format('<div style="display:none" id="%d">\n', ids[o])) if from[o] and not next(from[o]) then output('<div>Referenced from: ') for _,from_id in pairs(from[o]) do output(format([[ <a onlick="show(%s)" href="#%s">%s</a> ]], from_id, from_id, from_id)) end output('</div>') end for k,v in pairs(o) do local knew, vnew if count[k] then knew = format([[<a onclick="show(%s)" href="#%s">(see %s)</a>]], ids[k],ids[k],ids[k]) elseif type(k) ~= 'table' then knew = htmlize(tostring(k)) end if count[v] then vnew = format([[<a onclick="show(%s)" href="#%s">(see %s)</a>]], ids[v],ids[v],ids[v]) elseif type(v) ~= 'table' then vnew = htmlize(tostring(v)) end local kname = format([[<a name="%s"></a>]], ids[o] .. '.' .. (ids[k] or tostring(k))) if knew and vnew then output(kname .. '<div class="table_row">' .. knew .. '=' .. vnew .. '</div>') else output('<div class="table_row">\n') output(kname) if knew then output(knew) else output_html(k) end output('=') if vnew then output(vnew) else output_html(v) end output('</div>\n') end end output('</div></div>\n') else output('<div>' .. htmlize(tostring(o)) .. '</div>\n') end end local function dump(o) analyze_tree(o) for k,v in pairs(count) do if v == 1 then count[k] = nil end end output [[ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> <head> <title>FIX</title> <style type="text/css"> .table {margin:1em; border: 1px solid black} .table_row { margin-left:1em; border: 1px solid black} </style> <script> function toggle(id) { if (document.getElementById) { var ele = document.getElementById(id); if (ele && ele.style) { ele.style.display = ele.style.display == 'none' ? '' : 'none'; } } } function show_node(ele) { if (ele.style) { ele.style.display = ''; if (ele.parentNode) show(ele.parentNode); } } function show(id) { if (document.getElementById) { var ele = document.getElementById(id); if (ele) show_node(ele); } } </script> </head> <body> ]] output_html(o) for oo in pairs(count) do output_html(oo) end output [[</body></html>]] end dump(_G) -- metalua example --[=[ package.path = package.path .. ';/u/work/luawork/luaanalyze/lib/?.lua' require "lexer" require "gg" require "mlp_lexer" require "mlp_misc" require "mlp_table" require "mlp_meta" require "mlp_expr" require "mlp_stat" require "mlp_ext" mlc = {} -- make gg happy local mlp = assert(_G.mlp) local function string_to_ast(src, filename) filename = filename or '(string)' local lx = mlp.lexer:newstream (src, filename) local ast = mlp.chunk(lx) return ast end local src_file = assert(io.open ('mydump.lua', 'r')) local src = src_file:read '*a'; src_file:close() local ast = string_to_ast(src, src_filename) local function remove_lineinfo(o) if type(o) == 'table' then o.lineinfo = nil for k,v in pairs(o) do remove_lineinfo(k) remove_lineinfo(v) end end end remove_lineinfo(ast) dump(ast) --]=]