<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.cern.ch/index.php?action=history&amp;feed=atom&amp;title=Module%3ABuffer</id>
	<title>Module:Buffer - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.cern.ch/index.php?action=history&amp;feed=atom&amp;title=Module%3ABuffer"/>
	<link rel="alternate" type="text/html" href="https://wiki.cern.ch/index.php?title=Module:Buffer&amp;action=history"/>
	<updated>2026-04-04T04:46:13Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.44.0</generator>
	<entry>
		<id>https://wiki.cern.ch/index.php?title=Module:Buffer&amp;diff=11299&amp;oldid=prev</id>
		<title>Vigen: 1 revision imported from :wikipedia:Module:Buffer</title>
		<link rel="alternate" type="text/html" href="https://wiki.cern.ch/index.php?title=Module:Buffer&amp;diff=11299&amp;oldid=prev"/>
		<updated>2026-03-31T21:29:30Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported from &lt;a href=&quot;https://en.wikipedia.org/wiki/Module:Buffer&quot; class=&quot;extiw&quot; title=&quot;wikipedia:Module:Buffer&quot;&gt;wikipedia:Module:Buffer&lt;/a&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 21:29, 31 March 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Vigen</name></author>
	</entry>
	<entry>
		<id>https://wiki.cern.ch/index.php?title=Module:Buffer&amp;diff=11298&amp;oldid=prev</id>
		<title>wikipedia&gt;Phuzion: Fix typos per edit request</title>
		<link rel="alternate" type="text/html" href="https://wiki.cern.ch/index.php?title=Module:Buffer&amp;diff=11298&amp;oldid=prev"/>
		<updated>2025-12-18T13:25:54Z</updated>

		<summary type="html">&lt;p&gt;Fix typos per &lt;a href=&quot;/index.php?title=Module_talk:Buffer&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Module talk:Buffer (page does not exist)&quot;&gt;edit request&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;--[[=============================&lt;br /&gt;
This Module was written by Alexander Zhikun He, also known as User:Codehydro on the English Wikipedia&lt;br /&gt;
&lt;br /&gt;
All methods were developed independently and any resemblance to other string buffer libraries would be coincidental.&lt;br /&gt;
Furthermore, many methods will not work when compiled by standard Lua libraries as they depend on behaviors unique to&lt;br /&gt;
the MediaWiki Scribunto mod, which, for example, has a getmetatable() method that always returns nil on non-tables.&lt;br /&gt;
https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual&lt;br /&gt;
&lt;br /&gt;
Source code comments may be thin at some points because they are intended to be supplemented by the documentation page:&lt;br /&gt;
https://en.wikipedia.org/wiki/Module:Buffer/doc&lt;br /&gt;
&lt;br /&gt;
Licensed under Creative Commons Attribution-ShareAlike 3.0 Unported License&lt;br /&gt;
https://en.wikipedia.org/wiki/Wikipedia:Text_of_Creative_Commons_Attribution-ShareAlike_3.0_Unported_License&lt;br /&gt;
&lt;br /&gt;
https://en.wikipedia.org/wiki/Module:Buffer&lt;br /&gt;
https://en.wikipedia.org/wiki/User:Codehydro&lt;br /&gt;
=============================--]]&lt;br /&gt;
local function Valid(v)--type validation&lt;br /&gt;
	if v and v~=true then--reject nil/boolean; faster than 2 type() comparisons&lt;br /&gt;
		local str = tostring(v)--functions not filtered since unlikely passed by accident (Scribunto does not have userdata/thread types)&lt;br /&gt;
		if str~=v and str==&amp;#039;table&amp;#039; then return rawget(v, 1) and table.concat(v) end--tostring(string-type) returns same ref; same refs compare faster than type()&lt;br /&gt;
		if str~=&amp;#039;&amp;#039; then return str end--numbers are coerced to string per table.concat op; appending in string form saves ops on repeat concat&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
local noOp, MBpairs = function()end do local iMap, vMap, oMap, pIter, pOther, pFast, Next--Map&lt;br /&gt;
	local function init()--init = noOp after first run&lt;br /&gt;
		function Next(t) return next, t end--slightly faster to do this than to use select()&lt;br /&gt;
		function pIter(t, k) k = (iMap[t] or MBpairs(t, true) and iMap[t])[not k and 1 or vMap[t][k]] return k, t[k] end--don&amp;#039;t use rawget; accepting unmapped tables does not measurably affect performance.&lt;br /&gt;
		function pOther(t, k) k = (oMap[t] or MBpairs(t, true) and oMap[t])[nil==k and 1 or vMap[t][k]] return k, t[k] end--comparison to nil because false is a valid key&lt;br /&gt;
		function pFast(t, k) k = not k and 1 or k &amp;lt; (vMap[t] or #t) and k + 1 or nil return k, t[k] end--mapless iterator; almost as fast as native ipairs; slight performance penalty when length not cached&lt;br /&gt;
							   --k and k &amp;lt; (vMap[t] or #t) and k + 1 or not k and 1 or nil return k, t[k] end--mapless iterator; almost as fast as native ipairs; slight performance penalty when length not cached&lt;br /&gt;
		local mk = {__mode = &amp;#039;k&amp;#039;}--use mode &amp;#039;k&amp;#039;; found that mode &amp;#039;kv&amp;#039; sometimes garbage collects maps mid-loop (may not error because iterators auto re-map, but that&amp;#039;s expensive)&lt;br /&gt;
		init, iMap, vMap, oMap = noOp, setmetatable({}, mk), setmetatable({}, mk), setmetatable({}, mk)--iMap is numeric keys, oMap is non-numeric keys, and vMap points to next key&lt;br /&gt;
	end&lt;br /&gt;
	function MBpairs(t, ...)--pairs always iterates in order&lt;br /&gt;
		local iter, ex = ...&lt;br /&gt;
		iter = iter==init()--nil&lt;br /&gt;
		if iter and not oMap[t] and ex==nil and rawget(t, 1)~=nil and next(t, #t)==nil then--while possible to miss keys, more thorough check would negate the benefit of pFast&lt;br /&gt;
			vMap[t] = #t return pFast, t, nil&lt;br /&gt;
		elseif ... or not vMap[t] or select(&amp;#039;#&amp;#039;, ...)~=1 then&lt;br /&gt;
			local ti, tn, to, n = {}, {}, {}, #t--reduces table lookups&lt;br /&gt;
			iMap[t], vMap[t], oMap[t] = ti, tn, to&lt;br /&gt;
			for k = 1, n do ti[k], tn[k] = k, k + 1 end--stage one avoids number type checking op in stage two for most numeric keys&lt;br /&gt;
			for k in (ex or Next)(t) do&lt;br /&gt;
				if not tn[k] then table.insert(tonumber(k)~=k and to or ti, k) end&lt;br /&gt;
			end&lt;br /&gt;
			if #ti~=n then&lt;br /&gt;
				table.sort(ti)&lt;br /&gt;
				for k = 1, #ti do tn[ti[k]] = k + 1 end--somewhat wasteful, but trying to avoid overwriting can be even more expensive&lt;br /&gt;
			end&lt;br /&gt;
			for k = 1, #to do tn[to[k]] = k + 1 end&lt;br /&gt;
		end&lt;br /&gt;
		return iter and pIter or oMap[t] and pOther or noOp, t--noOp for mapless&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
local parent, rawkey, spec do--new scope for variables not reused outside (reduces number of var names that need to checked outside of scope)&lt;br /&gt;
	local mkv = {__mode=&amp;#039;kv&amp;#039;, __call=function(t,k,v)t[k]=v return k end}--shared meta for Buffer parent property, raw mode, and specialized functions&lt;br /&gt;
	parent, rawkey, spec = setmetatable({}, mkv), setmetatable({}, mkv), setmetatable({}, mkv)--shared meta less memory&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local MB, MBi, MBmix, buffHTML, gfuncs, noCache, Element do--minimize number of locals per scope to reduce time spent sifting through irrelevant variable names&lt;br /&gt;
	local _stream do local stream--keep stream near top of scope&lt;br /&gt;
		local function init(f)--init = noOp after first run&lt;br /&gt;
			local function each(self, ...)&lt;br /&gt;
				for k = 1, select(&amp;#039;#&amp;#039;, ...) do&lt;br /&gt;
					k = Valid(select(k, ...))--slightly faster than table.insert(self, (Valid(select(k, ...))))&lt;br /&gt;
					if k then table.insert(self, k) end&lt;br /&gt;
				end&lt;br /&gt;
				return self&lt;br /&gt;
			end&lt;br /&gt;
			init, stream, _stream = noOp, {&lt;br /&gt;
				__call = function(t, v) v = v and Valid(v) return v and table.insert(t, v) or t end,--last_concat cleared before entering stream mode&lt;br /&gt;
				__index = function(t, i) return i==&amp;#039;each&amp;#039; and each or MB.__index(t, i) and setmetatable(t, MB)[i] end,--no table look up minimizes resources to retrieve the only stream function&lt;br /&gt;
				__tostring = function(t) return setmetatable(t, MB)() end&lt;br /&gt;
			} for k, v in next, MB do stream[k] = stream[k] or v end&lt;br /&gt;
			setmetatable(stream, getmetatable(MB))&lt;br /&gt;
		end&lt;br /&gt;
		function _stream(self, ...) self.last_concat = init() return setmetatable(self, stream):each(...) end&lt;br /&gt;
	end&lt;br /&gt;
	local function isMBfunc(Buffer, s, ...)--helper for :getParent()-like methods (including getBuffer which does not return a parent)&lt;br /&gt;
		return s and (select(&amp;#039;#&amp;#039;, ...)==0 and--eventually should figure out to make this work for :getHTML which is very similar&lt;br /&gt;
				(not rawkey[s] and tostring(s):match&amp;#039;^_.*&amp;#039; and MB.__index(Buffer, s) and MB.__index(Buffer, s)(Buffer) or MBmix(Buffer, s))--unprefixed function names append as a string&lt;br /&gt;
				or assert(MB.__index(Buffer, s), (&amp;#039;&amp;quot; %s &amp;quot; does not match any available Module:Buffer function&amp;#039;):format(s))(Buffer, ...)--getParent is a one-way trip so one-time assert not expensive&lt;br /&gt;
			) or Buffer&lt;br /&gt;
	end&lt;br /&gt;
	local function MBselect(n, ...)--helper for :_out and :_str&lt;br /&gt;
		local n, seps = n - 1, {select(2, ...)}&lt;br /&gt;
		if type(seps[n])==&amp;#039;table&amp;#039; then &lt;br /&gt;
			if buffHTML and rawget(seps[n], buffHTML) then return ... end&lt;br /&gt;
			setmetatable(seps, {__index = setmetatable(seps[n], {__index = function(t) return rawget(t, 1) end})})[n] = nil&lt;br /&gt;
		end&lt;br /&gt;
		return ..., seps&lt;br /&gt;
	end&lt;br /&gt;
	local _inHTML do local lastBuffer, lastHTML&lt;br /&gt;
		local function init(...)--init replaced and new version called on return&lt;br /&gt;
			local create, mwFunc = mw.html.create do&lt;br /&gt;
				local mwHTMLmeta = getmetatable(create())&lt;br /&gt;
				buffHTML, mwFunc, _inHTML = setmetatable(mw.clone(mwHTMLmeta), getmetatable(MB)), mwHTMLmeta.__index--buffHTML declared near top of module; remove _inHTML from outer scope&lt;br /&gt;
				function init(nodes, ...)&lt;br /&gt;
					local name, args, tag = select(... and type(...)==&amp;#039;table&amp;#039; and 1 or 2, nil, ...)&lt;br /&gt;
					tag = create(Valid(name), args)&lt;br /&gt;
					if nodes then table.insert(nodes, tag.parent and tag or rawset(tag, &amp;#039;parent&amp;#039;, parent[nodes])) end&lt;br /&gt;
					if args then&lt;br /&gt;
						local a, b = args.selfClosing, args.parent&lt;br /&gt;
						args.selfClosing, args.parent = nil&lt;br /&gt;
						if next(args) then Element._add(parent(tag.nodes, tag), args) end&lt;br /&gt;
						args.selfClosing, args.parent = a, b--in case args is reused&lt;br /&gt;
					end&lt;br /&gt;
					return tag&lt;br /&gt;
				end&lt;br /&gt;
				for k, v in next, {[mw] = mwHTMLmeta,&lt;br /&gt;
					__call = function(h, v) return MBmix(spec[h.nodes] and h.nodes or spec(setmetatable(parent(h.nodes, h), MB), Element), v) end,&lt;br /&gt;
					__concat = false,--false means take from MB&lt;br /&gt;
					__eq = false&lt;br /&gt;
				} do buffHTML[k] = v or MB[k] end&lt;br /&gt;
			end&lt;br /&gt;
			local nonSelf, BHi = {tag=true,done=true,allDone=true}, buffHTML.__index do local g&lt;br /&gt;
				g = {__index = function(t, i)&lt;br /&gt;
					if gfuncs and gfuncs[i] then g.__index, gfuncs = gfuncs return g.__index[i] end&lt;br /&gt;
				end}&lt;br /&gt;
				setmetatable(nonSelf, g)&lt;br /&gt;
				setmetatable(BHi, g)&lt;br /&gt;
			end&lt;br /&gt;
			for k in next, nonSelf do--any HTML objects returned by these funcs will be granted Module:Buffer enhancements&lt;br /&gt;
				local func = mwFunc[k]&lt;br /&gt;
				BHi[k] = function(t, ...) local HTML = func(t, ...) return parent[HTML] and HTML or setmetatable(parent(HTML, t), buffHTML) end&lt;br /&gt;
			end&lt;br /&gt;
			do local function joinNode(HTML, sep)&lt;br /&gt;
					local nodes, join = HTML.nodes&lt;br /&gt;
					if noCache and rawkey[sep] or Valid(sep) then join, HTML.nodes = tostring(rawset(HTML, &amp;#039;nodes&amp;#039;, {MB.__call(nodes, sep)})), nodes end&lt;br /&gt;
					return join or tostring(HTML)&lt;br /&gt;
				end&lt;br /&gt;
				for k, v in next, {&lt;br /&gt;
					getParent = function(HTML, ...) lastHTML = HTML return MBi.getParent(HTML:allDone(), ...) end,--return to Buffer that created the HTML tree&lt;br /&gt;
					getBuffer = function(HTML, ...) lastHTML = HTML return isMBfunc(lastBuffer, ...) end,--return to last used&lt;br /&gt;
					killParent = function(HTML, ...) MBi.killParent(HTML:allDone(), ...) return HTML end,&lt;br /&gt;
					_out = function(HTML, ...)&lt;br /&gt;
						if ...==0 then MBi._out(HTML.nodes, ...) return HTML end&lt;br /&gt;
						lastHTML, HTML = HTML, HTML:allDone()&lt;br /&gt;
						local n, ops, seps = select(&amp;#039;#&amp;#039;, ...)&lt;br /&gt;
						if n &amp;gt; 1 then&lt;br /&gt;
							local ops, seps = MBselect(n, ...)&lt;br /&gt;
							return parent[HTML]:_in(joinNode(HTML, rawget(seps, 0))):_out(ops, rawset(seps, buffHTML, true))&lt;br /&gt;
						end&lt;br /&gt;
						return parent[HTML]:_(joinNode(HTML, ...))&lt;br /&gt;
					end,&lt;br /&gt;
					_str = function(HTML, ...)--does not set lastHTML&lt;br /&gt;
						if ...==0 then return joinNode(HTML, select(2, ...)) end--passing 0 strings without calling allDone()&lt;br /&gt;
						local HTML, n = HTML:allDone(), select(&amp;#039;#&amp;#039;, ...)&lt;br /&gt;
						if n &amp;gt; 1 then&lt;br /&gt;
							local ops, seps = MBselect(n, ...)&lt;br /&gt;
							return parent[HTML]:_in(joinNode(HTML, rawget(seps, 1))):_str(ops, rawset(seps, buffHTML, true))&lt;br /&gt;
						end&lt;br /&gt;
						return joinNode(HTML, ...)&lt;br /&gt;
					end,&lt;br /&gt;
					_parent = function(HTML, ...) table.insert(HTML.nodes, parent[HTML:allDone()]:_str(...)) return HTML end&lt;br /&gt;
				} do BHi[k] = v end&lt;br /&gt;
			end&lt;br /&gt;
			do local htmlArg, skip, outFuncs = {parent=true,selfClosing=true,tagName=true}, {}&lt;br /&gt;
				do local out local function func(nodes, ...) return out(parent[nodes], ...) end&lt;br /&gt;
					outFuncs = setmetatable({&lt;br /&gt;
						tag = function(nodes, ...) return parent(setmetatable(init(nodes, ...), buffHTML), parent[nodes]) end,&lt;br /&gt;
						done = function(b, ops)&lt;br /&gt;
							b = parent[b] &lt;br /&gt;
							while b.parent and ops~=0 do b, ops = b.parent, ops and ops - 1 or 0 end&lt;br /&gt;
							return b&lt;br /&gt;
						end&lt;br /&gt;
					}, {__index = function(nodes, i)&lt;br /&gt;
						if rawget(BHi, i) then out = BHi[i] return func end--rawget to exclude globals&lt;br /&gt;
					end})&lt;br /&gt;
				end&lt;br /&gt;
				Element = {&lt;br /&gt;
					_add = function(nodes, t)&lt;br /&gt;
						for k, v in MBpairs(t), t, skip[t] do (v~=true and MBmix or noOp)(nodes, v) end&lt;br /&gt;
						local HTML = parent[nodes] for k, v in MBpairs(t, false) do&lt;br /&gt;
							if htmlArg[k] then HTML[k] = v&lt;br /&gt;
							elseif v and v~=true then&lt;br /&gt;
								if nonSelf[k] then&lt;br /&gt;
									if k==&amp;#039;tag&amp;#039; then&lt;br /&gt;
										if type(v)==&amp;#039;table&amp;#039; then&lt;br /&gt;
											skip[v], k = 1, rawset(create(Valid(v[1])), &amp;#039;parent&amp;#039;, HTML)&lt;br /&gt;
											Element._add(spec(parent(k.nodes, k, table.insert(nodes, k)), Element), v)&lt;br /&gt;
											if k.selfClosing then k.nodes = nil else spec[k.nodes], parent[k.nodes] = nil end--free memory/reduce clutter; parent ref will auto-unset when k.nodes is nil&lt;br /&gt;
											if not k.tagName then k.styles, k.attributes = nil end&lt;br /&gt;
										else table.insert(nodes, create(v)) end&lt;br /&gt;
									elseif mwFunc[k] then&lt;br /&gt;
										if k==&amp;#039;done&amp;#039; and tonumber(v)~=v and v[1] and tonumber(v[1])==v[1] then skip[v] = 1 end&lt;br /&gt;
										MBmix(outFuncs[k](nodes, skip[v] and v[1]).nodes, v)&lt;br /&gt;
									elseif v[1] or v[2] then&lt;br /&gt;
										k = MBi[k](nodes, unpack(v, 1, rawset(skip, v, k==&amp;#039;_B&amp;#039; and 1 or 2)[v]))&lt;br /&gt;
										Element._add(getmetatable(k) and rawget(k, &amp;#039;nodes&amp;#039;) or k, v)--if k is not a table, then v should not contain any extra keys or this may error.&lt;br /&gt;
									else MBi[k](nodes, v) end--k probably == &amp;#039;_G&amp;#039; or &amp;#039;_R&amp;#039;&lt;br /&gt;
								elseif mwFunc[k] then&lt;br /&gt;
									if type(v)~=&amp;#039;table&amp;#039; or rawget(v, &amp;#039;nodes&amp;#039;) then mwFunc[k](HTML, v)&lt;br /&gt;
									else&lt;br /&gt;
										local css = k==&amp;#039;css&amp;#039;&lt;br /&gt;
										for x, y in MBpairs(v, true) do (y and y~=true and mwFunc[k] or noOp)(HTML, css and x:gsub(&amp;#039;_&amp;#039;, &amp;#039;-&amp;#039;) or x, y) end--iterate non-numbers first&lt;br /&gt;
										for _, y in MBpairs(v, nil) do (y and y~=true and mwFunc[k] or noOp)(HTML, y) end--don&amp;#039;t bother with gsub since text must be quoted anyhow&lt;br /&gt;
									end&lt;br /&gt;
								elseif rawget(Element, k) or rawget(MBi, k) then&lt;br /&gt;
									if tonumber(v)==v or v[1]==nil or getmetatable(v) then (Element[k] or MBi[k])(nodes, v)--v is probably string-able object, or a table to be handled by :_all&lt;br /&gt;
									else (Element[k] or MBi[k])(nodes, unpack(v, 1, table.maxn(v))) end--v is definately a table&lt;br /&gt;
								else mwFunc.css(HTML, k:gsub(&amp;#039;_&amp;#039;, &amp;#039;-&amp;#039;, 1), tostring(v)) end--oddly enough, :_add clocked its fastest runtime after adding auto-gsub as a feature&lt;br /&gt;
								skip[v] = nil&lt;br /&gt;
							end&lt;br /&gt;
						end&lt;br /&gt;
						return nodes&lt;br /&gt;
					end&lt;br /&gt;
				}&lt;br /&gt;
				local tempMeta = {mode=&amp;#039;v&amp;#039;, copy={styles=true,attributes=true}}&lt;br /&gt;
				function tempMeta.__index(t, i) return tempMeta.copy[i] and rawset(t, i, MBi._cc(false, 0, t.orig[i]))[i] or t.orig[i] end&lt;br /&gt;
				rawkey[setmetatable(Element, {__index = outFuncs, __concat=function(Element, v) return setmetatable({nodes=spec({}, Element),orig=parent[v]}, tempMeta) end})] = math.huge&lt;br /&gt;
			end&lt;br /&gt;
			function MBi:getHTML(...)&lt;br /&gt;
				lastBuffer = self&lt;br /&gt;
				if ... then&lt;br /&gt;
					if select(&amp;#039;#&amp;#039;, ...)==1 then return not rawkey[s] and tostring(...):match&amp;#039;^_&amp;#039; and BHi[...] and BHi[...](lastHTML) or lastHTML(...)&lt;br /&gt;
					else return assert(BHi[...], (&amp;#039;&amp;quot; %s &amp;quot; does not match any mw.html or Buffer-mw.html function&amp;#039;):format(tostring(...)))(lastHTML, select(2, ...)) end&lt;br /&gt;
				end&lt;br /&gt;
				return lastHTML&lt;br /&gt;
			end&lt;br /&gt;
			function MBi:_html(...) return MBi._(self, lastHTML, select(spec[self]==Element and select(&amp;#039;#&amp;#039;, ...)==0 and 1 or 2, true, ...)) end&lt;br /&gt;
			return init(...)&lt;br /&gt;
		end&lt;br /&gt;
		function _inHTML(self, ...)&lt;br /&gt;
			local HTML = init(nil, ...)&lt;br /&gt;
			if HTML.selfClosing and spec[self]==Element then self.last_concat = table.insert(self, HTML) return self end&lt;br /&gt;
			lastBuffer, lastHTML = self, setmetatable(parent(HTML, self), buffHTML)--set after &amp;#039;args&amp;#039; table processed by :_add&lt;br /&gt;
			return HTML&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local _var, unbuild do local prev, rebuild&lt;br /&gt;
		local function init(...)--init replaced before return&lt;br /&gt;
			local function pick(b, v) return b and table.insert(b, v) or v end&lt;br /&gt;
			local function c(a, num) return rawset(a.a or a, 0, a[0] and a[0] + a.c or num and a[1] or a[1]:byte())[0] end&lt;br /&gt;
			local same, build, alt = {__tostring = function(a, b) return a.a[0] and pick(b, a.a.string and string.char(a.a[0]) or a.a.table and a.a[1][a.a[0]] or a.a[0]) end}, {&lt;br /&gt;
				__index = {c = 1},&lt;br /&gt;
				__tostring = function(t) return t:_build() end,&lt;br /&gt;
				table = function(a, b) local i = next(a[1], a[0]) or a[0]==#a[1] and next(a[1]) return pick(b, rawset(a.a or a, 0, i)[1][i]) end,--change rate (a.c) ignored since users control the table&amp;#039;s contents&lt;br /&gt;
				number = function(a, b) return pick(b, c(a, true)) end,&lt;br /&gt;
				string = function(a, b) return pick(b, string.char(c(a))) end&lt;br /&gt;
			}, {__index = function(a, i) return a.a[i] end, __tostring = function(a, b) return (rawget(a, 0) and a[0]==tostring(a[0]) and rawset(a, 0, a[0]:byte()) or a).a._build(a, b) end}&lt;br /&gt;
			local function shift(t, c)&lt;br /&gt;
				t[0] = t[0] and t[0] + c or t:_build() and t[0] - t.c + c&lt;br /&gt;
				if t.table then t[0] = (t[0] - 1) % #t[1] + 1 end&lt;br /&gt;
			end&lt;br /&gt;
			function rebuild(...)&lt;br /&gt;
				local v, c = ...&lt;br /&gt;
				if v or select(&amp;#039;#&amp;#039;, ...)==0 then&lt;br /&gt;
					if v and not c then return prev end&lt;br /&gt;
					local meta, c = select(v and 1 or 3, alt, c, same, 0)&lt;br /&gt;
					return setmetatable({a = prev, _build = meta.__tostring, c = c}, meta)&lt;br /&gt;
				elseif v==nil then--no-op&lt;br /&gt;
				elseif c then shift(prev, c)--v == false&lt;br /&gt;
				else prev:_build() end&lt;br /&gt;
			end&lt;br /&gt;
			init, noCache = function(v, c) prev = setmetatable({v, c = c, _build = build[type(v)] or v, [type(v)] = true, alt = {}}, build) return prev end, true&lt;br /&gt;
			return init(...)&lt;br /&gt;
		end&lt;br /&gt;
		function unbuild(sep)&lt;br /&gt;
			for k, v in MBpairs(sep, nil) do&lt;br /&gt;
				k = getmetatable(v) if k and (k==build or k==alt) then shift(v.a or v, -v.c) end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		function _var(self, ...)&lt;br /&gt;
			local obj if ... and ...~=true then obj = init(...)&lt;br /&gt;
			elseif prev then&lt;br /&gt;
				if ...~=false then obj = rebuild(...)&lt;br /&gt;
				else rebuild(...) end&lt;br /&gt;
			end&lt;br /&gt;
			return obj and MBi._(self, obj, nil, true) or self&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local lib; MBi = setmetatable({stream = _stream,&lt;br /&gt;
		_inHTML = _inHTML,&lt;br /&gt;
		_var = _var,&lt;br /&gt;
		_ = function(self, v, ...)&lt;br /&gt;
			local at, raw = select(select(&amp;#039;#&amp;#039;, ...)==1 and ...==true and 1 or 2, nil, ...)&lt;br /&gt;
			if raw then rawkey[self] = math.huge else v = Valid(v) end&lt;br /&gt;
			if v or raw then&lt;br /&gt;
				if at or rawkey[self] then raw = #self end--if length increases by more than one after table.insert, then set rawkey[self] = math.huge; rawkey[self] may be equal to a previous &amp;#039;at&amp;#039;&lt;br /&gt;
				at, self.last_concat = at and (tonumber(at)~=at and raw + at or at)&lt;br /&gt;
				table.insert(self, select(at and 1 or 2, at, v))&lt;br /&gt;
				if at and at &amp;lt; 0 or raw and #self - raw &amp;gt; 1 then rawkey[self] = math.huge elseif at and #self==raw then rawkey[self] = rawkey[self] and math.max(rawkey[self], at) or at end&lt;br /&gt;
			end--above line looks bizarre because one table.insert op may make length jump from 0 to 8: local wtf={[2]=2,[4]=4,[8]=8}mw.log(#wtf,table.insert(wtf,1),#wtf)&lt;br /&gt;
			return self&lt;br /&gt;
		end,&lt;br /&gt;
		_nil = function(self, at, ...)&lt;br /&gt;
			if ...~=true and ...~=false then--faster than type(...) ~= &amp;#039;boolean&amp;#039;&lt;br /&gt;
				if not at or at==&amp;#039;0&amp;#039; then&lt;br /&gt;
					self[#self] = ... if ... then rawkey[self] = math.huge end&lt;br /&gt;
				else&lt;br /&gt;
					local n, v = tonumber(at), ...&lt;br /&gt;
					if n~=at then &lt;br /&gt;
						if n then n = #self + at&lt;br /&gt;
						elseif at~=true and select(&amp;#039;#&amp;#039;, ...)==0 then v, n = at, #self end&lt;br /&gt;
					end&lt;br /&gt;
					if n then &lt;br /&gt;
						if v==nil and n &amp;gt; 0 then table.remove(self, n)&lt;br /&gt;
						else self[math.floor(n)], rawkey[self] = v, math.huge end--floor position for consistency with Table library&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
				self.last_concat = nil&lt;br /&gt;
			end&lt;br /&gt;
			return self&lt;br /&gt;
		end,&lt;br /&gt;
		_all = function(self, t, valKey)&lt;br /&gt;
			for k, v in MBpairs(t) do MBmix(self, v, valKey) end&lt;br /&gt;
			for k, v in valKey and MBpairs(t, false) or noOp, t do&lt;br /&gt;
				if tonumber(v) then MBi._(self, k, v)--self not always a buffer&lt;br /&gt;
				elseif rawget(MBi, k) and v and v~=true then&lt;br /&gt;
					if v[1]==nil or getmetatable(v) then MBi[k](self, v)&lt;br /&gt;
					else MBi[k](self, unpack(v, 1, table.maxn(v))) end&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			return self&lt;br /&gt;
		end,&lt;br /&gt;
		_str = function(t, ...)&lt;br /&gt;
			local n = select(&amp;#039;#&amp;#039;, ...)&lt;br /&gt;
			if n &amp;gt; 1 then&lt;br /&gt;
				local k, ops, seps, r = 2, MBselect(n, ...)&lt;br /&gt;
				r = MB(t(seps[1]))&lt;br /&gt;
				while parent[t] and ops &amp;gt; 1 and r:_(parent[t](seps[k]), 1) do t, k, ops = parent[t], k + 1, ops - 1 end&lt;br /&gt;
				return table.concat(r, seps[k] or nil)&lt;br /&gt;
			end&lt;br /&gt;
			return MB.__call(t, ...)&lt;br /&gt;
		end,&lt;br /&gt;
		_in = function (self, ...) return parent(MB(...), self) end,&lt;br /&gt;
		_out = function(t, ...)&lt;br /&gt;
			if ...==0 then return parent(t, parent[t], MBi._cc(t, t, MB.__call(t, (select(2, ...))), getmetatable(t))) end--love how :_cc needed nothing new to implement this *self pat on back*&lt;br /&gt;
			local n = select(&amp;#039;#&amp;#039;, ...)&lt;br /&gt;
			if n &amp;gt; 1 then&lt;br /&gt;
				local k, ops, seps = 1, MBselect(n, ...)&lt;br /&gt;
				while parent[t] and ops &amp;gt; 0 do t, k, ops = parent[t]:_(t(seps[k])), k + 1, ops - 1 end&lt;br /&gt;
			elseif parent[t] then return parent[t]:_(t(...)) end&lt;br /&gt;
			return t&lt;br /&gt;
		end,&lt;br /&gt;
		_cc = function(self, clear, copy, meta)&lt;br /&gt;
			if clear then&lt;br /&gt;
				if rawequal(clear, copy) then return self, spec[MBi._cc] and setmetatable(spec[MBi._cc], MB)--rawequal to avoid re-string via __eq in case both are different Buffer objects&lt;br /&gt;
				elseif copy==true then copy = self end&lt;br /&gt;
				if clear~=0 then&lt;br /&gt;
					assert(type(clear)==&amp;#039;table&amp;#039;, debug.traceback(&amp;#039;Buffer:_cc can only &amp;quot;clear&amp;quot; tables. Did you forget to call with a colon?&amp;#039;, 2))--errors can be hard to trace without this&lt;br /&gt;
					for k in self and next or noOp, clear do rawset(clear, k, nil) end&lt;br /&gt;
				else return MBi._cc(false, {unpack(copy)}, copy) end--copy length w/o empty strings; recursion to avoid self = false causing garbage collection (non-weak child may exist)&lt;br /&gt;
				if self==false or copy and type(copy)==&amp;#039;table&amp;#039; then--self==false means copy is a table (saves a type op for recursive calls)&lt;br /&gt;
					meta = meta or getmetatable(copy)&lt;br /&gt;
					if self and #copy &amp;gt; 1 then--preserves length with empty strings; developed from studying http://www.lua.org/source/5.1/ltable.c.html		&lt;br /&gt;
						local n, null, i, e = #copy, {}, math.ldexp(2, select(2, math.frexp(#copy)) - 2)&lt;br /&gt;
						e, spec[MBi._cc], parent[null] = i - 1, null, clear&lt;br /&gt;
						for k = 1, e do table.insert(clear, false) end&lt;br /&gt;
						while i&amp;lt;=n do table.insert(clear, i, &amp;#039;&amp;#039;) i, null[i] = i + math.ldexp(2, select(2, math.frexp(n - i)) - 2), &amp;#039;&amp;#039; end&lt;br /&gt;
						for k = 1, e do rawset(clear, k, nil) end&lt;br /&gt;
					end&lt;br /&gt;
					for k, v in next, copy do rawset(clear, k, type(v)==&amp;#039;table&amp;#039; and MBi._cc(false, 0, v) or v) end&lt;br /&gt;
				elseif copy then rawset(clear, 1, (Valid(copy))) end&lt;br /&gt;
				rawkey[setmetatable(clear, meta)], parent[clear] = rawkey[copy], parent[copy]&lt;br /&gt;
			end&lt;br /&gt;
			return self and rawset(self, &amp;#039;last_concat&amp;#039;, nil) or clear&lt;br /&gt;
		end,&lt;br /&gt;
		_parent = function(self, ...) return parent[self] and MBi._(self, parent[self]:_str(...)) or self end,&lt;br /&gt;
		getParent = function(self, ...) return isMBfunc(parent[self] or parent[parent(self, setmetatable({}, MB))], ...) end,&lt;br /&gt;
		killParent = function(self, ...) return parent[self] and isMBfunc(parent[self], ...) and parent(self) or self end,&lt;br /&gt;
		_build = function(self, t) table.insert(t, self()) end,--for compatibility with mw.html:node()&lt;br /&gt;
		last_concat = false--prevent library check&lt;br /&gt;
	}, {__index = function(t, i)--import string, mw.text, and mw.ustring libraries on an as-needed basis&lt;br /&gt;
		local func = string[i] or mw.text[i] or mw.ustring[i] or type(i)==&amp;#039;string&amp;#039; and mw.ustring[i:match&amp;#039;^u(.+)&amp;#039;] if func then&lt;br /&gt;
			lib	= lib or function (s, f, ...)&lt;br /&gt;
				if parent[s] and next(s)==nil then return s:_((f(tostring(parent[Element and (spec[s]==Element and s:allDone() or spec[parent[s]]==Element and parent[s]) or s]), ...))) end&lt;br /&gt;
				return f(tostring(s), ...)--not using ternary/logical operators here to allow multiple return values&lt;br /&gt;
			end&lt;br /&gt;
			return rawset(t, i, i:match&amp;#039;^u?gsub&amp;#039; and function(self, p, r, ...)return lib(self, func, p, r or &amp;#039;&amp;#039;, ...)end--Why are ugsub/gsub special? because empty strings are against my religion!&lt;br /&gt;
				or function(self, ...)return lib(self, func, ...)end)[i]&lt;br /&gt;
		end&lt;br /&gt;
	end})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function MBmix(t, v, ...) return v and ((type(v)~=&amp;#039;table&amp;#039; or getmetatable(v)) and MBi._(t, v) or (select(&amp;#039;#&amp;#039;, ...)==0 and spec[t] and spec[t]._add or MBi._all)(t, v, ...)) or t end--:_all always passes two args&lt;br /&gt;
&lt;br /&gt;
local _G, new_G = _G--localize _G for console testing (console _G ~= module _G)&lt;br /&gt;
return setmetatable({__index = function(t, i) return spec[t] and spec[t][i] or MBi[i] end,&lt;br /&gt;
	__call = function(t, ...)&lt;br /&gt;
		local rawsep, sep, i, j, raw = noCache and rawkey[...] and ..., ...&lt;br /&gt;
		if i or j or rawsep or Valid(sep) then&lt;br /&gt;
			raw, sep, i, j = rawkey[spec[t]] or rawkey[t], rawsep or Valid(sep), i and (i~=tonumber(i) and i + #t or i), j and (j~=tonumber(j) and j + #t or j)&lt;br /&gt;
			if rawsep or raw and (raw&amp;gt;=(j or #t) or i &amp;lt; 1) then&lt;br /&gt;
				raw, i, j = {}, i and math.floor(i), j and math.floor(j)--floor for consistency with table.concat(t, sep, i, j), which ignores decimals&lt;br /&gt;
				raw.lc, t.last_concat = t.last_concat--temporarily unset last_concat to prevent disqualification from mapless iteration&lt;br /&gt;
				for k, v in MBpairs(t) do&lt;br /&gt;
					if raw[1] or not i or k&amp;gt;=i then if j and k &amp;gt; j then break end&lt;br /&gt;
						if raw.s then raw.s = table.insert(raw, tostring(sep)) end--if sep contains v and v is a Buffer-variable, sep must be strung before v&lt;br /&gt;
						k = Valid(v) if k then&lt;br /&gt;
							raw.s = rawsep or sep and raw[1] and table.insert(raw, sep)&lt;br /&gt;
							table.insert(raw, k)&lt;br /&gt;
						end&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
				if rawsep and not raw.s then raw[#raw] = unbuild(sep) end--unbuild rawsep if final index in t was invalid&lt;br /&gt;
				t.last_concat = raw.lc return table.concat(raw)&lt;br /&gt;
			end&lt;br /&gt;
			return table.concat(t, sep, i and math.max(i, 1), j and math.min(j, #t))&lt;br /&gt;
		end&lt;br /&gt;
		return MB.__tostring(t)&lt;br /&gt;
	end,&lt;br /&gt;
	__tostring = function(t)&lt;br /&gt;
		if t.last_concat then return t.last_concat end&lt;br /&gt;
		local r = rawkey[spec[t]] or rawkey[t]&lt;br /&gt;
		r = table.concat(r and r&amp;gt;=#t and MBi._all({}, t) or t)&lt;br /&gt;
		return (noCache or rawset(t, &amp;#039;last_concat&amp;#039;, r)) and r&lt;br /&gt;
	end,&lt;br /&gt;
	__concat = function(a, b)&lt;br /&gt;
		if buffHTML then&lt;br /&gt;
			for k = 1, 2 do local v = select(k, a, b)--faster than for k, v in pairs{a, b} do&lt;br /&gt;
				if v and spec[v] and spec[v]==Element then&lt;br /&gt;
					if parent[v].selfClosing then&lt;br /&gt;
						if rawequal(a, b) then return (not noCache or parent[v].tagName) and v:_str(0):rep(2) or v:_str(0)..v:_str(0) end--rawequal avoids premature tostring of Buffer:_var objects;&lt;br /&gt;
						b, a = select(k, b, parent[v], a)&lt;br /&gt;
					else local temp = Element .. v --helper method; returns a mirror of parent[v]&lt;br /&gt;
						MBmix(MBmix(parent(temp.nodes, temp), a), k==1 and spec[b]==Element and parent[b] or b)&lt;br /&gt;
						return buffHTML.__tostring(setmetatable(temp, {__index=parent[v], __mode=&amp;#039;v&amp;#039;}))--switch from tempMeta to avoid MBi._cc op of styles/attributes&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		return table.concat(MBmix(MBmix({}, a), b))&lt;br /&gt;
	end,&lt;br /&gt;
	__pairs = MBpairs,&lt;br /&gt;
	__ipairs = MBpairs,&lt;br /&gt;
	__eq = function(a, b) return tostring(a)==tostring(b) end--avoid a==b in this module; use rawequal(a,b) when they may be different Buffers (premature tostring waste ops and is bad for Buffer:_var)&lt;br /&gt;
}, {__tostring = function()return&amp;#039;&amp;#039;end,&lt;br /&gt;
	__call = function(self, ...) MB = MB or self&lt;br /&gt;
		if new_G then if ... and _G and ...==_G then new_G = ... end&lt;br /&gt;
		elseif ... and (...==_G or type(...)==&amp;#039;table&amp;#039; and (...)._G==...) then&lt;br /&gt;
			local Nil, mG = {}, (...):getmetatable() or (...):setmetatable{}:getmetatable()&lt;br /&gt;
			new_G, _G, gfuncs = ..., ..., {--gfuncs stored for Buffer:_inHTML; new_G is a is a Module:Buffer local declared just before the final return statement.&lt;br /&gt;
				_G = function(self, i, ...)&lt;br /&gt;
					local X, save = rawget(new_G, i), select(&amp;#039;#&amp;#039;, ...)==0 and self or ...&lt;br /&gt;
					if i and i~=true and not (X and save and rawequal(X, save)) and rawset(new_G, i, save) and (X~=nil or save==nil and new_G[i]~=nil) then--rawequal in case X is another buffer&lt;br /&gt;
						local mG = getmetatable(new_G) or {__call=mG.__call}&lt;br /&gt;
						if mG.__index then pcall(rawset, mG.__index, i, X)&lt;br /&gt;
						else mG.__index = setmetatable(new_G, mG) and {[i] = X} end&lt;br /&gt;
					end&lt;br /&gt;
					return self, ...--avoiding __eq with rawequal(self,save) is overkill since buffers can self-save without being passed as save&lt;br /&gt;
				end,&lt;br /&gt;
				_R = function(self, i, v, m)&lt;br /&gt;
					if i~=&amp;#039;new_G&amp;#039; then if i and i~=true then rawset(new_G, i , v) end&lt;br /&gt;
					elseif not v or v==true or v._G~=_G then new_G = setmetatable(v~=true and v or {}, {__call = mG.__call, __index = v~=true and m~=true and (m or new_G) or nil})&lt;br /&gt;
					else new_G, (not m and (m~=nil or v==new_G) and Nil or getmetatable(v)).__index = v, m~=true and (m or new_G) or nil end--setting Nil.__index is noOp&lt;br /&gt;
					return self&lt;br /&gt;
				end,&lt;br /&gt;
				_2 = function(self, ...)&lt;br /&gt;
					if new_G[...]~=nil then return new_G[...] end--higher priority so Buffer:_G(&amp;#039;new_G&amp;#039;, ...) can prevent an overwrite&lt;br /&gt;
					if ...==&amp;#039;new_G&amp;#039; then return rawset((select(&amp;#039;#&amp;#039;, ...)~=1 and MBi._R(new_G, ...) or new_G), &amp;#039;_G&amp;#039;, _G) end&lt;br /&gt;
					return select(select(&amp;#039;#&amp;#039;, ...)==1 and 1 or 2, self:_G(...))--return only one value; &amp;#039;return select(2, self:_G(...)) or self&amp;#039; doesn&amp;#039;t work for returning nil&lt;br /&gt;
				end,&lt;br /&gt;
				_B = function(self, v) return v or v==nil and Nil end&lt;br /&gt;
			} for k, v in next, gfuncs do MBi[k] = v end &lt;br /&gt;
			setmetatable(Nil,{__concat=MB.__concat,__newindex=noOp,__call=noOp,__tostring=noOp,__metatable=MB,__index=setmetatable({_B=MBi._B,_=function()return Nil end,last_concat=&amp;#039;&amp;#039;},&lt;br /&gt;
				{__index=function(t,i)return (MBi[i] or i and not tonumber(i)) and t._ or nil end})})&lt;br /&gt;
			function mG.__call(G, k, ...) return (k._G or G.type(k)==&amp;#039;table&amp;#039;) and (G.select(&amp;#039;#&amp;#039;, ...)~=1 and G.rawset(k, ...) or G:rawset(..., k) and k) or G:rawset(k, (...)) and ... end&lt;br /&gt;
		end&lt;br /&gt;
		local new = setmetatable({}, self)&lt;br /&gt;
		if ... and (...)==new_G then return select(2, ...) and MBmix(new:_G((select(2, ...))), select(3, ...)) or new end&lt;br /&gt;
		return ... and MBi._(new, ...) or new&lt;br /&gt;
	end,&lt;br /&gt;
	__index = function(t, i)&lt;br /&gt;
		MB = MB or t return MBi[i] and function(...) return MBi[i](setmetatable({}, t), select(...==t and 2 or 1,...)) end&lt;br /&gt;
	end&lt;br /&gt;
})&lt;/div&gt;</summary>
		<author><name>wikipedia&gt;Phuzion</name></author>
	</entry>
</feed>