From 891d790aa1dafff5340c181e3dce3332526e4834 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Mon, 13 Aug 2012 22:41:51 +0000 Subject: new luatex package luaxml (13aug12) git-svn-id: svn://tug.org/texlive/trunk@27394 c570f23f-e606-0410-a88d-b1316a301751 --- .../tex/luatex/luaxml/luaxml-mod-handler.lua | 338 +++++++++++++ .../tex/luatex/luaxml/luaxml-mod-xml.lua | 547 +++++++++++++++++++++ .../tex/luatex/luaxml/luaxml-selectors.lua | 42 ++ .../texmf-dist/tex/luatex/luaxml/luaxml-stack.lua | 63 +++ 4 files changed, 990 insertions(+) create mode 100644 Master/texmf-dist/tex/luatex/luaxml/luaxml-mod-handler.lua create mode 100644 Master/texmf-dist/tex/luatex/luaxml/luaxml-mod-xml.lua create mode 100644 Master/texmf-dist/tex/luatex/luaxml/luaxml-selectors.lua create mode 100644 Master/texmf-dist/tex/luatex/luaxml/luaxml-stack.lua (limited to 'Master/texmf-dist/tex') diff --git a/Master/texmf-dist/tex/luatex/luaxml/luaxml-mod-handler.lua b/Master/texmf-dist/tex/luatex/luaxml/luaxml-mod-handler.lua new file mode 100644 index 00000000000..bc4d8ea9120 --- /dev/null +++ b/Master/texmf-dist/tex/luatex/luaxml/luaxml-mod-handler.lua @@ -0,0 +1,338 @@ +module(...,package.seeall) +-- +-- Overview: +-- ========= +-- Standard XML event handler(s) for XML parser module (xml.lua) +-- +-- Features: +-- ========= +-- printHandler - Generate XML event trace +-- domHandler - Generate DOM-like node tree +-- simpleTreeHandler - Generate 'simple' node tree +-- simpleTeXhandler - SAX like handler with support for CSS selectros +-- +-- API: +-- ==== +-- Must be called as handler function from xmlParser +-- and implement XML event callbacks (see xmlParser.lua +-- for callback API definition) +-- +-- printHandler: +-- ------------- +-- +-- printHandler prints event trace for debugging +-- +-- domHandler: +-- ----------- +-- +-- domHandler generates a DOM-like node tree structure with +-- a single ROOT node parent - each node is a table comprising +-- fields below. +-- +-- node = { _name = , +-- _type = ROOT|ELEMENT|TEXT|COMMENT|PI|DECL|DTD, +-- _attr = { Node attributes - see callback API }, +-- _parent = +-- _children = { List of child nodes - ROOT/NODE only } +-- } +-- +-- The dom structure is capable of representing any valid XML document +-- +-- simpleTreeHandler +-- ----------------- +-- +-- simpleTreeHandler is a simplified handler which attempts +-- to generate a more 'natural' table based structure which +-- supports many common XML formats. +-- +-- The XML tree structure is mapped directly into a recursive +-- table structure with node names as keys and child elements +-- as either a table of values or directly as a string value +-- for text. Where there is only a single child element this +-- is inserted as a named key - if there are multiple +-- elements these are inserted as a vector (in some cases it +-- may be preferable to always insert elements as a vector +-- which can be specified on a per element basis in the +-- options). Attributes are inserted as a child element with +-- a key of '_attr'. +-- +-- Only Tag/Text & CDATA elements are processed - all others +-- are ignored. +-- +-- This format has some limitations - primarily +-- +-- * Mixed-Content behaves unpredictably - the relationship +-- between text elements and embedded tags is lost and +-- multiple levels of mixed content does not work +-- * If a leaf element has both a text element and attributes +-- then the text must be accessed through a vector (to +-- provide a container for the attribute) +-- +-- In general however this format is relatively useful. +-- +-- It is much easier to understand by running some test +-- data through 'textxml.lua -simpletree' than to read this) +-- +-- Options +-- ======= +-- simpleTreeHandler.options.noReduce = { = bool,.. } +-- +-- - Nodes not to reduce children vector even if only +-- one child +-- +-- domHandler.options.(comment|pi|dtd|decl)Node = bool +-- +-- - Include/exclude given node types +-- +-- Usage +-- ===== +-- Pased as delegate in xmlParser constructor and called +-- as callback by xmlParser:parse(xml) method. +-- +-- See textxml.lua for examples +-- License: +-- ======== +-- +-- This code is freely distributable under the terms of the Lua license +-- (http://www.lua.org/copyright.html) +-- +-- History +-- ======= +-- $Id: handler.lua,v 1.1.1.1 2001/11/28 06:11:33 paulc Exp $ +-- +-- $Log: handler.lua,v $ +-- Revision 1.1.1.1 2001/11/28 06:11:33 paulc +-- Initial Import +--@author Paul Chakravarti (paulc@passtheaardvark.com)

+ + +---Handler to generate a string prepresentation of a table +--Convenience function for printHandler (Does not support recursive tables). +--@param t Table to be parsed +--@returns Returns a string representation of table + +local stack = require("luaxml-stack") + +function showTable(t) + local sep = '' + local res = '' + if type(t) ~= 'table' then + return t + end + for k,v in pairs(t) do + if type(v) == 'table' then + v = showTable(v) + end + res = res .. sep .. string.format("%s=%s",k,v) + sep = ',' + end + res = '{'..res..'}' + return res +end + +---Handler to generate a simple event trace +printHandler = function() + local obj = {} + obj.starttag = function(self,t,a,s,e) + io.write("Start : "..t.."\n") + if a then + for k,v in pairs(a) do + io.write(string.format(" + %s='%s'\n",k,v)) + end + end + end + obj.endtag = function(self,t,s,e) + io.write("End : "..t.."\n") + end + obj.text = function(self,t,s,e) + io.write("Text : "..t.."\n") + end + obj.cdata = function(self,t,s,e) + io.write("CDATA : "..t.."\n") + end + obj.comment = function(self,t,s,e) + io.write("Comment : "..t.."\n") + end + obj.dtd = function(self,t,a,s,e) + io.write("DTD : "..t.."\n") + if a then + for k,v in pairs(a) do + io.write(string.format(" + %s='%s'\n",k,v)) + end + end + end + obj.pi = function(self,t,a,s,e) + io.write("PI : "..t.."\n") + if a then + for k,v in pairs(a) do + io. write(string.format(" + %s='%s'\n",k,v)) + end + end + end + obj.decl = function(self,t,a,s,e) + io.write("XML Decl : "..t.."\n") + if a then + for k,v in pairs(a) do + io.write(string.format(" + %s='%s'\n",k,v)) + end + end + end + return obj +end + +---Handler to generate a lua table from a XML content string +function simpleTreeHandler() + local obj = {} + + obj.root = {} + obj.stack = {obj.root;n=1} + obj.options = {noreduce = {}} + + obj.reduce = function(self,node,key,parent) + -- Recursively remove redundant vectors for nodes + -- with single child elements + for k,v in pairs(node) do + if type(v) == 'table' then + self:reduce(v,k,node) + end + end + if table.getn(node) == 1 and not self.options.noreduce[key] and + node._attr == nil then + parent[key] = node[1] + else + node.n = nil + end + end + + obj.starttag = function(self,t,a) + local node = {} + if self.parseAttributes == true then + node._attr=a + end + + local current = self.stack[table.getn(self.stack)] + if current[t] then + table.insert(current[t],node) + else + current[t] = {node;n=1} + end + table.insert(self.stack,node) + end + + obj.endtag = function(self,t,s) + local current = self.stack[table.getn(self.stack)] + local prev = self.stack[table.getn(self.stack)-1] + if not prev[t] then + error("XML Error - Unmatched Tag ["..s..":"..t.."]\n") + end + if prev == self.root then + -- Once parsing complete recursively reduce tree + self:reduce(prev,nil,nil) + end + table.remove(self.stack) + end + + obj.text = function(self,t) + local current = self.stack[table.getn(self.stack)] + table.insert(current,t) + end + + obj.cdata = obj.text + + return obj +end + + + +--- domHandler +function domHandler() + local obj = {} + obj.options = {commentNode=1,piNode=1,dtdNode=1,declNode=1} + obj.root = { _children = {n=0}, _type = "ROOT" } + obj.current = obj.root + obj.starttag = function(self,t,a) + local node = { _type = 'ELEMENT', + _name = t, + _attr = a, + _parent = self.current, + _children = {n=0} } + table.insert(self.current._children,node) + self.current = node + end + obj.endtag = function(self,t,s) + if t ~= self.current._name then + error("XML Error - Unmatched Tag ["..s..":"..t.."]\n") + end + self.current = self.current._parent + end + obj.text = function(self,t) + local node = { _type = "TEXT", + _parent = self.current, + _text = t } + table.insert(self.current._children,node) + end + obj.comment = function(self,t) + if self.options.commentNode then + local node = { _type = "COMMENT", + _parent = self.current, + _text = t } + table.insert(self.current._children,node) + end + end + obj.pi = function(self,t,a) + if self.options.piNode then + local node = { _type = "PI", + _name = t, + _attr = a, + _parent = self.current } + table.insert(self.current._children,node) + end + end + obj.decl = function(self,t,a) + if self.options.declNode then + local node = { _type = "DECL", + _name = t, + _attr = a, + _parent = self.current } + table.insert(self.current._children,node) + end + end + obj.dtd = function(self,t,a) + if self.options.dtdNode then + local node = { _type = "DTD", + _name = t, + _attr = a, + _parent = self.current } + table.insert(self.current._children,node) + end + end + obj.cdata = obj.text + return obj +end + +-- +simpleTeXhandler=function() + local obj={} + local _stack=stack.Stack:Create() + obj.starttag = function(self,t,a,s,e) + local tag = {t} + local getAtt = function(att) + if a[att] then + return att.."="..a[att] + end + return nil + end + if type(a) == "table" then + table.insert(tag,getAtt("id")) + table.insert(tag,getAtt("class")) + end + _stack:push("<"..table.concat(tag," ")..">") + io.write(_stack:join("").."\n") +-- io.write("Start "..t.."\n" ) + end + obj.endtag = function(self,t,s,e) + _stack:pop() + -- io.write("End : "..t.."\n") + end + return obj +end diff --git a/Master/texmf-dist/tex/luatex/luaxml/luaxml-mod-xml.lua b/Master/texmf-dist/tex/luatex/luaxml/luaxml-mod-xml.lua new file mode 100644 index 00000000000..f3ebb0445e8 --- /dev/null +++ b/Master/texmf-dist/tex/luatex/luaxml/luaxml-mod-xml.lua @@ -0,0 +1,547 @@ +module(...,package.seeall) +--- +-- Overview: +-- ========= +-- +-- This module provides a non-validating XML stream parser in Lua. +-- +-- Features: +-- ========= +-- +-- * Tokenises well-formed XML (relatively robustly) +-- * Flexible handler based event api (see below) +-- * Parses all XML Infoset elements - ie. +-- - Tags +-- - Text +-- - Comments +-- - CDATA +-- - XML Decl +-- - Processing Instructions +-- - DOCTYPE declarations +-- * Provides limited well-formedness checking +-- (checks for basic syntax & balanced tags only) +-- * Flexible whitespace handling (selectable) +-- * Entity Handling (selectable) +-- +-- Limitations: +-- ============ +-- +-- * Non-validating +-- * No charset handling +-- * No namespace support +-- * Shallow well-formedness checking only (fails +-- to detect most semantic errors) +-- +-- API: +-- ==== +-- +-- The parser provides a partially object-oriented API with +-- functionality split into tokeniser and hanlder components. +-- +-- The handler instance is passed to the tokeniser and receives +-- callbacks for each XML element processed (if a suitable handler +-- function is defined). The API is conceptually similar to the +-- SAX API but implemented differently. +-- +-- The following events are generated by the tokeniser +-- +-- handler:start - Start Tag +-- handler:end - End Tag +-- handler:text - Text +-- handler:decl - XML Declaration +-- handler:pi - Processing Instruction +-- handler:comment - Comment +-- handler:dtd - DOCTYPE definition +-- handler:cdata - CDATA +-- +-- The function prototype for all the callback functions is +-- +-- callback(val,attrs,start,end) +-- +-- where attrs is a table and val/attrs are overloaded for +-- specific callbacks - ie. +-- +-- Callback val attrs (table) +-- -------- --- ------------- +-- start name { attributes (name=val).. } +-- end name nil +-- text nil +-- cdata nil +-- decl "xml" { attributes (name=val).. } +-- pi pi name { attributes (if present).. +-- _text = +-- } +-- comment nil +-- dtd root element { _root = , +-- _type = SYSTEM|PUBLIC, +-- _name = , +-- _uri = , +-- _internal = +-- } +-- +-- (start & end provide the character positions of the start/end +-- of the element) +-- +-- XML data is passed to the parser instance through the 'parse' +-- method (Nore: must be passed a single string currently) +-- +-- Options +-- ======= +-- +-- Parser options are controlled through the 'self.options' table. +-- Available options are - +-- +-- * stripWS +-- +-- Strip non-significant whitespace (leading/trailing) +-- and do not generate events for empty text elements +-- +-- * expandEntities +-- +-- Expand entities (standard entities + single char +-- numeric entities only currently - could be extended +-- at runtime if suitable DTD parser added elements +-- to table (see obj._ENTITIES). May also be possible +-- to expand multibyre entities for UTF-8 only +-- +-- * errorHandler +-- +-- Custom error handler function +-- +-- NOTE: Boolean options must be set to 'nil' not '0' +-- +-- Usage +-- ===== +-- +-- Create a handler instance - +-- +-- h = { start = function(t,a,s,e) .... end, +-- end = function(t,a,s,e) .... end, +-- text = function(t,a,s,e) .... end, +-- cdata = text } +-- +-- (or use predefined handler - see handler.lua) +-- +-- Create parser instance - +-- +-- p = xmlParser(h) +-- +-- Set options - +-- +-- p.options.xxxx = nil +-- +-- Parse XML data - +-- +-- xmlParser:parse(" + +local format= string.format +---Parses a XML string +--@param handler Handler object to be used to convert the XML string +--to another formats. @see handler.lua +xmlParser = function(handler) + local obj = {} + -- Public attributes + + obj.options = { + stripWS = 1, + expandEntities = 1, + errorHandler = function(err,pos) + error(format("%s [char=%d]\n", + err or "Parse Error",pos)) + end, + } + + -- Public methods + + obj.parse = function(self, str, parseAttributes) + if parseAttributes == nil then + parseAttributes = true + end + self._handler.parseAttributes = parseAttributes + + local match,endmatch,pos = 0,0,1 + local text,endt1,endt2,tagstr,tagname,attrs,starttext,endtext + local errstart,errend,extstart,extend + while match do + -- Get next tag (first pass - fix exceptions below) + match,endmatch,text,endt1,tagstr,endt2 = string.find(str,self._XML,pos) + if not match then + if string.find(str,self._WS,pos) then + -- No more text - check document complete + if table.getn(self._stack) ~= 0 then + self:_err(self._errstr.incompleteXmlErr,pos) + else + break + end + else + -- Unparsable text + self:_err(self._errstr.xmlErr,pos) + end + end + -- Handle leading text + starttext = match + endtext = match + string.len(text) - 1 + match = match + string.len(text) + text = self:_parseEntities(self:_stripWS(text)) + if text ~= "" and self._handler.text then + self._handler:text(text,nil,match,endtext) + end + -- Test for tag type + if string.find(string.sub(tagstr,1,5),"?xml%s") then + -- XML Declaration + match,endmatch,text = string.find(str,self._PI,pos) + if not match then + self:_err(self._errstr.declErr,pos) + end + if match ~= 1 then + -- Must be at start of doc if present + self:_err(self._errstr.declStartErr,pos) + end + tagname,attrs = self:_parseTag(text) + -- TODO: Check attributes are valid + -- Check for version (mandatory) + if attrs.version == nil then + self:_err(self._errstr.declAttrErr,pos) + end + if self._handler.decl then + self._handler:decl(tagname,attrs,match,endmatch) + end + elseif string.sub(tagstr,1,1) == "?" then + -- Processing Instruction + match,endmatch,text = string.find(str,self._PI,pos) + if not match then + self:_err(self._errstr.piErr,pos) + end + if self._handler.pi then + -- Parse PI attributes & text + tagname,attrs = self:_parseTag(text) + local pi = string.sub(text,string.len(tagname)+1) + if pi ~= "" then + if attrs then + attrs._text = pi + else + attrs = { _text = pi } + end + end + self._handler:pi(tagname,attrs,match,endmatch) + end + elseif string.sub(tagstr,1,3) == "!--" then + -- Comment + match,endmatch,text = string.find(str,self._COMMENT,pos) + if not match then + self:_err(self._errstr.commentErr,pos) + end + if self._handler.comment then + text = self:_parseEntities(self:_stripWS(text)) + self._handler:comment(text,next,match,endmatch) + end + elseif string.sub(tagstr,1,8) == "!DOCTYPE" then + -- DTD + --match,endmatch,attrs = self:_parseDTD(string,pos) + match,endmatch,attrs = self:_parseDTD(str,pos) + if not match then + self:_err(self._errstr.dtdErr,pos) + end + if self._handler.dtd then + self._handler:dtd(attrs._root,attrs,match,endmatch) + end + elseif string.sub(tagstr,1,8) == "![CDATA[" then + -- CDATA + match,endmatch,text = string.find(str,self._CDATA,pos) + if not match then + self:_err(self._errstr.cdataErr,pos) + end + if self._handler.cdata then + self._handler:cdata(text,nil,match,endmatch) + end + else + -- Normal tag + + -- Need theck for embedded '>' in attribute value and extend + -- match recursively if necessary eg. + + while 1 do + errstart,errend = string.find(tagstr,self._ATTRERR1) + if errend == nil then + errstart,errend = string.find(tagstr,self._ATTRERR2) + if errend == nil then + break + end + end + extstart,extend,endt2 = string.find(str,self._TAGEXT,endmatch+1) + tagstr = tagstr .. string.sub(string,endmatch,extend-1) + if not match then + self:_err(self._errstr.xmlErr,pos) + end + endmatch = extend + end + + -- Extract tagname/attrs + + tagname,attrs = self:_parseTag(tagstr) + + if (endt1=="/") then + -- End tag + if self._handler.endtag then + if attrs then + -- Shouldnt have any attributes in endtag + self:_err(format("%s (/%s)", + self._errstr.endTagErr, + tagname) + ,pos) + end + if table.remove(self._stack) ~= tagname then + self:_err(format("%s (/%s)", + self._errstr.unmatchedTagErr, + tagname) + ,pos) + end + self._handler:endtag(tagname,nil,match,endmatch) + end + else + -- Start Tag + table.insert(self._stack,tagname) + if self._handler.starttag then + self._handler:starttag(tagname,attrs,match,endmatch) + end + -- Self-Closing Tag + if (endt2=="/") then + table.remove(self._stack) + if self._handler.endtag then + self._handler:endtag(tagname,nil,match,endmatch) + end + end + end + end + pos = endmatch + 1 + end + end + + -- Private attrobures/functions + + obj._handler = handler + obj._stack = {} + + obj._XML = '^([^<]*)<(%/?)([^>]-)(%/?)>' + obj._ATTR1 = '([%w-:_]+)%s*=%s*"(.-)"' + obj._ATTR2 = '([%w-:_]+)%s*=%s*\'(.-)\'' + obj._CDATA = '<%!%[CDATA%[(.-)%]%]>' + obj._PI = '<%?(.-)%?>' + obj._COMMENT = '' + obj._TAG = '^(.-)%s.*' + obj._LEADINGWS = '^%s+' + obj._TRAILINGWS = '%s+$' + obj._WS = '^%s*$' + obj._DTD1 = '' + obj._DTD2 = '' + obj._DTD3 = '' + obj._DTD4 = '' + obj._DTD5 = '' + --obj._DTD6 = "" + + obj._ATTRERR1 = '=%s*"[^"]*$' + obj._ATTRERR2 = '=%s*\'[^\']*$' + obj._TAGEXT = '(%/?)>' + + obj._ENTITIES = { ["<"] = "<", + [">"] = ">", + ["&"] = "&", + ["""] = '"', + ["'"] = "'", + ["&#(%d+);"] = function (x) + local d = tonumber(x) + if d >= 0 and d < 256 then + return string.char(d) + else + return "&#"..d..";" + end + end, + ["&#x(%x+);"] = function (x) + local d = tonumber(x,16) + if d >= 0 and d < 256 then + return string.char(d) + else + return "&#x"..x..";" + end + end, + } + + obj._err = function(self,err,pos) + if self.options.errorHandler then + self.options.errorHandler(err,pos) + end + end + + obj._errstr = { xmlErr = "Error Parsing XML", + declErr = "Error Parsing XMLDecl", + declStartErr = "XMLDecl not at start of document", + declAttrErr = "Invalid XMLDecl attributes", + piErr = "Error Parsing Processing Instruction", + commentErr = "Error Parsing Comment", + cdataErr = "Error Parsing CDATA", + dtdErr = "Error Parsing DTD", + endTagErr = "End Tag Attributes Invalid", + unmatchedTagErr = "Unbalanced Tag", + incompleteXmlErr = "Incomplete XML Document", + } + + obj._stripWS = function(self,s) + if self.options.stripWS then + s = string.gsub(s,'^%s+','') + s = string.gsub(s,'%s+$','') + end + return s + end + + obj._parseEntities = function(self,s) + if self.options.expandEntities then + --for k,v in self._ENTITIES do + for k,v in pairs(self._ENTITIES) do + --print (k, v) + s = string.gsub(s,k,v) + end + end + return s + end + + obj._parseDTD = function(self,s,pos) + -- match,endmatch,root,type,name,uri,internal + --print(s.." : "..pos) + local m,e,r,t,n,u,i + m,e,r,t,n,u = string.find(s,self._DTD5,pos) + if m then + return m,e,{_root=r,_type=t,_name=n,_uri=u} + end + m,e,r,t,u,i = string.find(s,self._DTD1,pos) + if m then + return m,e,{_root=r,_type=t,_uri=u,_internal=i} + end + m,e,r,t,n,u,i = string.find(s,self._DTD2,pos) + if m then + return m,e,{_root=r,_type=t,_name=n,_uri=u,_internal=i} + end + m,e,r,i = string.find(s,self._DTD3,pos) + if m then + return m,e,{_root=r,_internal=i} + end + m,e,r,t,u = string.find(s,self._DTD4,pos) + if m then + return m,e,{_root=r,_type=t,_uri=u} + end + return nil + end + + obj._parseTag = function(self,s) + local attrs = {} + local tagname = string.gsub(s,self._TAG,'%1') + string.gsub(s,self._ATTR1,function (k,v) + attrs[string.lower(k)]=self:_parseEntities(v) + attrs._ = 1 + end) + string.gsub(s,self._ATTR2,function (k,v) + attrs[string.lower(k)]=self:_parseEntities(v) + attrs._ = 1 + end) + if attrs._ then + attrs._ = nil + else + attrs = nil + end + return tagname,attrs + end + + return obj + +end + +function xmlEscape(s) + local t = {['"']=""",["'"]="'",["&"]="&",["<"]="<",[">"]=">"} + return string.gsub(s,"([\"'<>&])",t) +end + + + +function serialize(tb) +local function getAttributes(k,v) + local i = "" + if(type(v["_attr"])=="table") then + -- texio.write_nl("attr") + for p,n in pairs(v["_attr"]) do + i = i ..' '.. p .. '="'..xmlEscape(n)..'"' + end + --table.remove(v,"_attr") + end + return i +end + local function printable(tb, level,currTag) + local r ={} + local currTag = currTag or "" + level = level or 0 + local spaces = string.rep(' ', level*2) + for k,v in pairs(tb) do + if type(v) ~= "table" then + local ct = k + if type(k)=="number" then + ct = currTag + end + if ct == "" then + table.insert(r,spaces .. xmlEscape(v).."\n") + else + local i = getAttributes(k,v) + table.insert(r,spaces .. '<'..ct..i..'>'..xmlEscape(v)..''.."\n") + end + else + if k == "_attr" then + --table.insert(r,printable(v, level)) + else + if type(k)=="string" then + --currTag = k + if type(k)=="numeric" then + k = currTag + end + if #v > 1 then + table.insert(r,printable(v, level+1,k)) + else + local i = getAttributes(k,v) + table.insert(r,spaces.."<"..k..i..">\n") + table.insert(r,printable(v, level+1,k)) + table.insert(r,spaces.."\n") + end + else + local i = getAttributes(k,v) + table.insert(r,spaces .. "<"..currTag..i..">\n") + --level = level + 1 + table.insert(r,printable(v, level+1)) + table.insert(r,spaces .. "\n") + end + end + end + end + return table.concat(r,"") + end + return table.concat({'',printable(tb)},"\n") +end diff --git a/Master/texmf-dist/tex/luatex/luaxml/luaxml-selectors.lua b/Master/texmf-dist/tex/luatex/luaxml/luaxml-selectors.lua new file mode 100644 index 00000000000..921f971eb2e --- /dev/null +++ b/Master/texmf-dist/tex/luatex/luaxml/luaxml-selectors.lua @@ -0,0 +1,42 @@ +module(...,package.seeall) + + +function makeTag(s) + return "<"..s.."[^>]*>" +end +function matchTag(tg) + return makeTag(tg) +end + +function matchDescendand(a,b) + return makeTag(a)..makeTag(b) +end + +function matchChild(a,b) + return makeTag(a)..".*"..makeTag(b) +end + +function matchSibling(a,b) + return makeTag(a .. "[^>]*".."@%("..b.."[^>]*%)") +end + +function matchClass(tg,class) + return makeTag(tg.."[^>]*class=[|]*[^>]*|"..class.."[^>]*|") +end +matcher = {} +function matcher.new() + local self = {} + local selectors={} + function self:addSelector(sel,val) + selectors[sel.."$"] = val + end + function self:testPath(path,fn) + for k, v in pairs(selectors) do + if path:match(k) then + fn(v) + end + end + end + return self +end + diff --git a/Master/texmf-dist/tex/luatex/luaxml/luaxml-stack.lua b/Master/texmf-dist/tex/luatex/luaxml/luaxml-stack.lua new file mode 100644 index 00000000000..54386ff84d3 --- /dev/null +++ b/Master/texmf-dist/tex/luatex/luaxml/luaxml-stack.lua @@ -0,0 +1,63 @@ +-- Code from http://lua-users.org/wiki/SimpleStack +module(...,package.seeall) +Stack = {} + +-- Create a Table with stack functions +function Stack:Create() + + -- stack table + local t = {} + -- entry table + t._et = {} + + -- push a value on to the stack + function t:push(...) + if ... then + local targs = {...} + -- add values + for _,v in pairs(targs) do + table.insert(self._et, v) + end + end + end + + -- pop a value from the stack + function t:pop(num) + + -- get num values from stack + local num = num or 1 + + -- return table + local entries = {} + + -- get values into entries + for i = 1, num do + -- get last entry + if #self._et ~= 0 then + table.insert(entries, self._et[#self._et]) + -- remove last value + table.remove(self._et) + else + break + end + end + -- return unpacked entries + return unpack(entries) + end + + -- get entries + function t:getn() + return #self._et + end + + -- list values + function t:list() + for i,v in pairs(self._et) do + print(i, v) + end + end + function t:join(s) + return table.concat(self._et,s) + end + return t +end -- cgit v1.2.3