--- **LIBEZT-1.0** Is a simple library for importing/rendering EZT templates -- @class file -- @name LIBEZT-1.0 --[[ LIBEZT-1.0 Revision: $Rev$ Author(s): Humbedooh Description: EZT import library License: Apache License, v/2.0 ]] local LIBEZT_MAJOR = "LibEZT-1.0" -- version number of this file (automatically generated by SVN) local LIBEZT_MINOR = tonumber(("$Rev$"):match("(%d+)")) or 10000; local LIBEZT = false; if LibStub then LIBEZT = LibStub:NewLibrary(LIBEZT_MAJOR, LIBEZT_MINOR) _G.LIBEZT = LIBEZT; else if not _G.LIBEZT or (type(_G.LIBEZT) == "table" and _G.LIBEZT.rev < LIBEZT_MINOR) then _G.LIBEZT = {rev = LIBEZT_MINOR}; end LIBEZT = _G.LIBEZT; end if not LIBEZT then return end function LIBEZT:version() return LIBEZT_MINOR end function LIBEZT.parseargs(s) local arg = {}; for w in s:gmatch("([%w:%-]+)") do table.insert(arg,w) end return arg; end function LIBEZT.at(s,e) local l = 1; for n = 1, e do if s:sub(n,n)=="\n" then l=l+1 end end return l end function LIBEZT:import(s, loose) local tremove, parseargs,tinsert = table.remove, LIBEZT.parseargs,table.insert; local stack = {}; local top = {}; tinsert(stack, top); local ni,c,class,args; local i, j = 1, 1; local ci, cj -- start and end of HTML comment (if any) local searchComment = true -- whether there are comments still to find while true do -- class: (alpha | '_') (alphanum | '_' | '-')* -- args = anything afterwards ni,j,class,args = s:find("%[([%l%u_][%w%-_]*)([^%]]*)%]", i); if not ni then break end --[[ HTML comments may contain constructs that look like ezt sytnax, e.g. In order to support HTML comments, we need to scan for either a comment or an EZT command However Lua does not support RE alternation, so this needs to be done as a separate search. Also Lua does not support a "continue" clause so we need to use a nested if ]] if searchComment then ci, cj = s:find("", i) end -- find next HTML comment (if any) if not ci then searchComment = False end -- no comment found; there cannot be any more if searchComment and ci < ni then -- the comment starts before the ezt command top[#top+1]=s:sub(i, cj); i = cj + 1 -- skip the comment -- and continue to look for next ezt command else -- found an ezt command outside an HTML comment local text = s:sub(i, ni-1); if text:find("%S") then top[#top+1]=text; end if (class ~= "ezt" and class ~= "end" and class ~= "if" and class~= "is" and class~= "if-any" and class ~= "define" and class~= "for") then -- empty element top[#top+1] ={class=class, args=parseargs(args), empty=true, ni=ni}; elseif class ~= "end" then -- start tag -- print("open " .. class) top = {class=class, args=parseargs(args), ni=ni}; stack[#stack+1] = top; -- new level elseif class == "end" then -- end tag local toclose = tremove(stack); -- pop the top and get the opening tag --print("close " .. toclose.class) top = stack[#stack]; if #stack < 1 then -- print( ("%s: No opening tag found for <%s> (at line %u)!"):format("LibEZT", class, LIBEZT.at(s,ni))) return nil, ("%s: No opening tag found for <%s> (at line %u)!"):format("LibEZT", class, LIBEZT.at(s,ni)); end top[#top+1] = toclose; end i = j+1; end end local text = s:sub(i); if not text:find("^%s*$") then local st = stack[#stack]; st[#st+1] = text; end if #stack > 1 then local l = LIBEZT.at(s, (stack[#stack].ni or 0)) print(("%s: EZT data ended without closing [%s] (at line %u)!"):format("LibEZT", stack[#stack].class, l)) return nil, ("%s: EZT data ended without closing <%s> (at line %u)!"):format("LibEZT", stack[#stack].class, l); end return stack[1]; end function LIBEZT.construct(self, child, defs) if type(child) == "string" then return child or "" elseif type(child) == "table" and #table > 0 then -- print("got a root") local rv = "" for k, v in pairs(child) do print(k) -- TODO this looks like a debug statement, should it still be enabled? rv = rv .. LIBEZT.construct(self, v, defs) end return rv elseif child.class then if child.class == "ezt" then -- print("Starting EZT...") local rv = "" for k, v in ipairs(child) do rv = rv .. LIBEZT.construct(self, v, defs) end return rv elseif child.class == "define" then -- print("got a define") local key = child.args[1] defs.strings[key] = child[1] -- print("set", key, child[1]) return "" elseif child.class == "for" then local rv = "" -- print("Doing for...") if child.args[1] and defs.arrays[child.args[1]] then for x,y in pairs(defs.arrays[child.args[1]]) do defs.strings[child.args[1]] = y for k, v in ipairs(child) do --print(k) rv = rv .. LIBEZT.construct(self, v, defs) end end end return rv elseif child.class == "if-any" then local rv = "" -- print("Doing if..") if child.args[1] then if defs.strings[child.args[1]] or defs.arrays[child.args[1]] then for k, v in ipairs(child) do rv = rv .. LIBEZT.construct(self, v, defs) end end end return rv elseif child.class == "is" then local rv = "" -- print("Doing is..") rv = "" if #child.args == 2 then local a = defs.strings[child.args[1]] or nil local b = defs.strings[child.args[2]] or nil if a == b then for k, v in ipairs(child) do rv = rv .. LIBEZT.construct(self, v, defs) end end end return rv elseif child.empty then --print(child.class) return tostring(defs.strings[child.class] or "") end else local rv = "" for k, v in pairs(child) do rv = rv .. LIBEZT.construct(self, v, defs) end return rv end end return LIBEZT