Module:Sandbox/DrMeepster/C yes yes explained

local p = -------------------------------------Code from other people-------------------------------------

TableTools = require("Module:TableTools")

--https://stackoverflow.com/a/1283608--All stack overflow code is CC BY-SA 3.0local function tableMerge(t1, t2) for k,v in pairs(t2) do if type(v)

"table" then if type(t1[k] or false)

"table" then _tableMerge(t1[k] or, t2[k] or) else t1[k] = v end else t1[k] = v end end return t1end

--This function is public domain. See http://lua-users.org/wiki/OrderedTable--Modified to be able to accept argslocal function Ordered(t) --nextkey and firstkey are used as markers; nextkey[firstkey] is --the first key in the table, and nextkey[nextkey] is the last key. --nextkey[nextkey[nextkey]] should always be nil.

local key2val, nextkey, firstkey =,, nextkey[nextkey] = firstkey local function onext(self, key) while key ~= nil do key = nextkey[key] local val = self[key] if val ~= nil then return key, val end end end -- To save on tables, we use firstkey for the (customised) -- metatable; this line is just for documentation local selfmeta = firstkey -- record the nextkey table, for routines lacking the closure selfmeta.__nextkey = nextkey -- setting a new key (might) require adding the key to the chain function selfmeta:__newindex(key, val) rawset(self, key, val) if nextkey[key]

nil then -- adding a new key nextkey[nextkey[nextkey]] = key nextkey[nextkey] = key end end out = setmetatable(key2val, selfmeta) if t then tableMerge(out, t) end return outend

p.Ordered = Ordered

------------------------------------------Code from me------------------------------------------

--metatable of mw.htmlp.htmlMeta = getmetatable(mw.html.create)

p.orderedMeta = getmetatable(p.Ordered)

function p.filter(tabl, typ) local typeCheck = (type(typ)

"string" and type) or (type(typ)

"table" and getmetatable) or error("Invalid type!") local out = for k,v in pairs(tabl) do if typeCheck(v)

typ then out[k] = v end end return outend

--------------------------------

--an HTML Elementlocal Element =

Element.__index = Element

--Create a new Elementfunction Element.new(type) o = setmetatable(Element) o.type = type o.children = o.style = Ordered o.classes = return oend

--Add Element or mw.html as childfunction Element:add(child) if getmetatable(child)

Element then child.parent = self elseif getmetatable(child) ~= htmlMeta then error("Inavlid child!") end table.insert(self.children, child) return childend

--Add string as childfunction Element:wikitext(child) if type(child) ~= "string" then error("Inavlid child!") end table.insert(self.children, child) return selfend

--create a new Element then add itfunction Element:tag(name) elem = Element.new(name) return self:add(elem)end

--add a newline (br)function Element:newline self:tag("br") return selfend

--add a css propertyfunction Element:css(k, v) if type(k)

"table" then for _,kv in ipairs(k) do self:css(kv[1], kv[2]) end elseif type(k)

"string" and type(v)

"string" then self.style[k] = v else error("CSS keys and values should be string!") end return selfend

--add classesfunction Element:class(class) if type(class)

"table" then tableMerge(self.classes, class) elseif type(class)

"string" then table.insert(self.classes, class) else error("Invalid class type!") end return selfend

--set the idfunction Element:setId(id) if type(id) ~= "string" then error("Id must be string!") end self.id = id return selfend

--returns parent. used for function chainingfunction Element:done return self.parent or selfend

--returns the root Elementfunction Element:allDone local parent = self.parent if parent

nil then return self end while parent.parent do parent = parent.parent end return parentend

--turn this Element into an mw.html objectfunction Element:bake local root = mw.html.create(self.type):css(self.style) for _,class in ipairs(self.classes) do root:addClass(class) end for _, child in ipairs(self.children) do if getmetatable(child)

Element then --must bake Element root:node(child:bake) elseif getmetatable(child)

htmlMeta then --do not need to bake mw.html root:node(child) elseif type(child)

"string" then --if string add as wikitext root:wikitext(child) else error("Unknown child of element!") end end return rootend

--bakes the root Elementfunction Element:bakeAll return self:allDone:bakeend

--wip dont usefunction Element:stylesheet(css) for _,c in ipairs(css) do for _,s in ipairs(c.selectors) do if s:check(self) then self:css(c.properties) break end end end for _,child in pairs(p.filter(self.children, Element)) do child:stylesheet(css) end return selfend

--------------------------------

local Selector = --selections ordered roughly by price, cheapest to most expensive --basic selections-- yes - Makes the selector always be true (*) id - Element must have this id (#id) type - Element must be of this type (type) class - Element must have all these classes (.class1.class2 etc) --combinator selections-- directParent- Element must have its parent element match this selector (parentElement > element) parent - Element must be inside an element matching this selector (parentElement element)

Selector.__index = Selector

function Selector.new(s) s = s or if type(s.class)

"string" then s.class = elseif type(s.class) ~= "table" then s.class = end return setmetatable(s, Selector)end

function Selector:check(e) if getmetatable(e) ~= Element then return false end -- all selector if self.yes then return true end -- id selector if self.id and e.id ~= self.id then return false end -- type selector if self.type and e.type ~= self.type then return false end -- class selector if #self.class > 0 then local class = true for _,v in pairs(self.class) do if not TableTools.inArray(e.classes, v) then class = false break end end if not class then return false end end -- direct parent check if self.directParent and not self.directParent:check(e.parent) then return false end -- parent check

if self.parent then local nextParent = e.parent while true do if nextParent

nil then return false end if self.parent:check(nextParent) then break end nextParent = nextParent.parent end end -- all selectors passed return trueend

--------------------------------p.Element = Elementp.Selector = Selectorreturn p