<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.americanmusicclub.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=98.230.192.179</id>
	<title>The Official Website for Mark Eitzel &amp; American Music Club - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.americanmusicclub.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=98.230.192.179"/>
	<link rel="alternate" type="text/html" href="https://wiki.americanmusicclub.com/wiki/Special:Contributions/98.230.192.179"/>
	<updated>2026-04-28T00:29:19Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://wiki.americanmusicclub.com/index.php?title=Module:Buffer/doc&amp;diff=19215</id>
		<title>Module:Buffer/doc</title>
		<link rel="alternate" type="text/html" href="https://wiki.americanmusicclub.com/index.php?title=Module:Buffer/doc&amp;diff=19215"/>
		<updated>2015-04-11T00:00:36Z</updated>

		<summary type="html">&lt;p&gt;98.230.192.179: duplicate template arguments&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Tmbox|image=[[File:Stop_hand_nuvola.svg|40px]]|text=Do not &amp;quot;beautify&amp;quot; the source of this metamodule. Its unconventional syntax was developed using the [[scientific method]] for performance. For example, {{code|1=v2~=true and v2~=false}}, though longer than {{code|1=type(v2)~=&#039;boolean&#039;|lang=lua}}, is about 8 times faster per op. Though the {{luaref|type}} op is normally trivial, the way this is used could cause any inefficiency to be multiplied by over a &#039;&#039;&#039;b&#039;&#039;&#039;illion.&lt;br /&gt;
&amp;lt;ref group=note&amp;gt;For instance, [[Module:Asbox]] is transcluded on about 2 million pages, which each have Asbox using Buffer functions on 10-30 variables, some of which may be strings generated by other Modules that may eventually use Module:Buffer several times. Finally, throw in the fact that many pages transclude Asbox multiple times, and you can see how a few microseconds per op could translate to hours for the [[Help:Job queue|job queue]].&amp;lt;/ref&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Module rating |release&amp;lt;!-- Values:  pre-alpha • alpha • beta • release • protected  --  If a rating not needed/relevant, delete this template call --&amp;gt;}}&lt;br /&gt;
&amp;lt;!-- Please place categories where indicated at the bottom of this page and interwikis at Wikidata (see [[Wikipedia:Wikidata]]) --&amp;gt;&lt;br /&gt;
{{TOC right}}&lt;br /&gt;
This was originally developed to optimize string concatenation as a helper method within [[Module:Asbox]], but has been generalized for all modules.&lt;br /&gt;
&lt;br /&gt;
The interface for [[#Buffer object|Module:Buffer objects]] is similar to that of {{Luaref|HTML_library|mw.html}} objects in that you may build complex strings with independent child nodes. In most cases, you may use Buffer objects like a normal string, including using {{code|..}} operator (though {{luaself|:_}} has the same role, but potentially [[#performance|over 10 times faster than {{code|..}}]]). See also: [[#String, mw.ustring, and mw.text libraries]]&lt;br /&gt;
&lt;br /&gt;
Additionally, there are several specialized forms and extended objects, described further in their respective sections: &lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;div style=&amp;quot;margin:0; column-width: 15em; -moz-column-width: 15em; -webkit-column-width: 15em; width:49em&amp;quot;&amp;gt;&lt;br /&gt;
*{{luaself|:stream|plain=y}}&lt;br /&gt;
*{{luaself|\-HTML|plain=y}}&lt;br /&gt;
*{{luaself|pre=Element-|\|plain=y}}&lt;br /&gt;
*{{luaself|\-variable|plain=y}}&lt;br /&gt;
*{{luaself|\-nil|plain=y}}&lt;br /&gt;
*[[#_G object|_G (callable)]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Last but not least, this module has an ordered [[#require&#039;Module:Buffer&#039;.__pairs|__pairs]] which can be more thorough than {{luaref|ipairs||y}} and {{luaref|pairs||y}}. (Even reads nil keys!) &lt;br /&gt;
The &amp;lt;span title=&#039;This is a bad Star Trek joke&#039;&amp;gt;logical uniqueness&amp;lt;/span&amp;gt; of this iterator may be reason enough to {{luaref|require|assimilate|y}} Module:Buffer.&lt;br /&gt;
&lt;br /&gt;
==Usage==&lt;br /&gt;
{{anchor|module|initialize}}&lt;br /&gt;
===require&#039;Module:Buffer&#039;===&lt;br /&gt;
 &lt;br /&gt;
{{luaself|Buffer|\|require&#039;Module:***&#039;|subpage= |args=...|args2=_G, name, ...}}&lt;br /&gt;
&lt;br /&gt;
Creates a new Module:Buffer object when the module returned by {{luaref|require||y}} is called as a function{{--}}i.e., there is no &#039;main&#039;.&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;span title=&#039;i.e. never accept arguments&#039;&amp;gt;{{luaref|mw.html:done|public methods with useless parenthesis|y}}&amp;lt;/span&amp;gt; are a [[pet peeve]] of this developer, this forwards arguments to {{luaself|:_}}; &lt;br /&gt;
if that op is not desired, you may chain a Buffer object function directly to the module and the self-action will be redirected to a new Buffer object{{--}}&lt;br /&gt;
i.e [[#Buffer:_inHTML|{{code|lang=lua|require&#039;Module:Buffer&#039;:_inHTML&#039;table&#039;}}]] is equivalent to {{code|lang=lua|require&#039;Module:Buffer&#039;():_inHTML&#039;table&#039;}}.&amp;lt;ref group=note&amp;gt;For your convience, the self operator {{code|:}} and {{code|.}} are interchangable when used on the Module directly, though the self-op is required for nearly all other interactions with objects created by the Module.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The global variable {{luaref|_G}} is &amp;quot;magic&amp;quot; when passed as the first arg. Such enables the [[#Global functions|global functions]] and, &lt;br /&gt;
if followed by a &amp;lt;code&amp;gt;name&amp;lt;code&amp;gt; string, will declare the new Buffer with that name in the global scope. If the argument following &#039;&#039;name&#039;&#039; is a table with no metatable, &lt;br /&gt;
it and any other {{luaref|varargs||y}} are forwarded to {{luaself|:_all}}; otherwise, as long as the first vararg is not nil or false, this passes them to {{luaself|:_}}.&amp;lt;ref group=note&amp;gt;&lt;br /&gt;
Passing arguments after &#039;&#039;name&#039;&#039; is primary used when {{luaself|:_in}} is indirectly called by {{luaself|:_all}} or {{luaself|pre=Element-|:_add}}. For example:&amp;lt;br /&amp;gt;&lt;br /&gt;
{{code|1=require&#039;Module:Buffer&#039;(_G,&#039;arg&#039;):_all({&#039;arg&#039;,arg and {&#039; was saved:&#039; ,_in={_G, &#039;t&#039;, &#039; awesome&#039;}{{))}}, true):_(t and {t(), t..&#039;r&#039;, t..&#039;st&#039;})|lang=lua}}&amp;lt;br /&amp;gt;&lt;br /&gt;
produces: {{code|arg was saved: awesome awesomer awesomest|lang=lua}}&amp;lt;/ref&amp;gt; The _G passed may also gain a __call {{luaref|Metatables|metamethod|y}} (details at [[#G object|_G object]]).&lt;br /&gt;
&lt;br /&gt;
{{anchor|recycling}}&lt;br /&gt;
As a final note, if you {{luaref|require|plain=y}} text from a module which returns a Buffer object, it may be more efficient to create a new Buffer via chaining {{luaself|Buffer|:_in|:_in|args=()}} &lt;br /&gt;
after a require statement for the other module and use {{luaself|:_parent|args=()}} at the point where you would append the required text. (Best add {{code|lang=lua|--:_in == indirect require Module:Buffer}} &lt;br /&gt;
so future editors won&#039;t hunt for {{code|lang=lua|function ...:_in}} at the other module)&lt;br /&gt;
&lt;br /&gt;
===Basic functions===&lt;br /&gt;
{{anchor|Buffer}}&lt;br /&gt;
====Buffer object====&lt;br /&gt;
&lt;br /&gt;
{{luaself|\|args=sep, i, j}}&lt;br /&gt;
:&#039;&#039;See also {{luaself|:_str|plain=y}} for advanced string conversion.&lt;br /&gt;
&lt;br /&gt;
Get a Buffer as a {{luaref|string||y}} via a function call on the Buffer &#039;&#039;object&#039;&#039; (as opposed to [[#require&#039;Module:Buffer&#039;|a call on the &#039;&#039;module&#039;&#039;]]). &lt;br /&gt;
This is basically shorthand for {{luaref|table.concat|args=Buffer, ...}}, or, with no args, {{luaref|tostring|args=Buffer}}. &lt;br /&gt;
However, if this Buffer holds [[#raw|raw values]]&amp;lt;ref group=note name=raw /&amp;gt; or {{luaref|sequence|non-sequential values|y}}, &lt;br /&gt;
then the return is built from an iteration of its values through &amp;lt;code&amp;gt;new-{{luaself|:_all|plain=yes|args=Buffer}}&amp;lt;/code&amp;gt; (or a similar process).&lt;br /&gt;
{{anchor|relative}}&lt;br /&gt;
&lt;br /&gt;
Unconventionally, any &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;j&amp;lt;code&amp;gt; of type {{luaref|string|plain=y}} would be treated as &#039;&#039;relative to length&#039;&#039;; &lt;br /&gt;
that is, {{luaself|\|args=&#039;-&#039;, -1, &#039;-3&#039;}} is equivalent to {{luaself|\|args=&#039;-&#039;, -1, #Buffer - 3}} &lt;br /&gt;
(obviating the need to set a {{luaref|Local variable declarations|local|y}} Buffer to use the {{luaref|Length operator|length operator|y}}).&lt;br /&gt;
&lt;br /&gt;
Note you may append a Buffer object without tostring coercion to an {{luaref|HTML library|mw.html|y}} object via {{luaref|mw.html:node}} (though not mw.html:wikitext because of type checking).&lt;br /&gt;
&lt;br /&gt;
=====Buffer.last_concat=====&lt;br /&gt;
&lt;br /&gt;
When strung without a ([[#valid|valid]]) &amp;lt;code&amp;gt;sep&amp;lt;/code&amp;gt;, the result is cached at &amp;lt;code&amp;gt;Buffer.last_concat&amp;lt;/code&amp;gt;. &lt;br /&gt;
Until purged, future calls to return that Buffer as a string will return this index instead.&amp;lt;ref group=note&amp;gt;&lt;br /&gt;
Using {{luaself|:_var|plain=y}} prevents future caching on all Buffers, though Buffers which already &lt;br /&gt;
unmodified Buffers will continue to return their cached version&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should clear automatically whenever a Buffer object function changes the contents of a Buffer. &lt;br /&gt;
You may manually purge the cache by setting this key to nil, as well as by passing nothing to {{luaself|:_cc|args=()}}. &lt;br /&gt;
&lt;br /&gt;
====Buffer:_====&lt;br /&gt;
&lt;br /&gt;
{{luaself|:_|args=&#039;string&#039;|args2=value, pos, raw|args3=value, raw}}&lt;br /&gt;
:&#039;&#039;See also {{luaself|:stream|plain=y}} for a faster, simpler version of this op.&lt;br /&gt;
&lt;br /&gt;
Appends a value to the Buffer. In rough terms, {{code|lang=lua|Buffer:_&#039;string1&#039;:_&#039;string2&#039;}} is the same as {{code|lang=lua|Buffer {{=}} Buffer..&#039;string1&#039;..&#039;string2&#039;}}. &lt;br /&gt;
(It may help to imagine {{code|:_}} as a {{code|..}} that has stood up and is now casting a shadow.)&lt;br /&gt;
{{anchor|valid|invalid|no-op}}&lt;br /&gt;
&lt;br /&gt;
If passed an &#039;&#039;invalid&#039;&#039; {{code|value}} listed below, this is a no-op:&lt;br /&gt;
* {{luaref|boolean||y}}&lt;br /&gt;
* {{luaref|nil||y}}&lt;br /&gt;
* empty {{luaref|string||y}}, or any table such that {{luaref|tostring|args=table}} returns an empty string (or nil/false)&lt;br /&gt;
* {{luaref|table||y}} without a __tostring metamethod and which {{code|table[1]|lang=lua}} is nil or false&lt;br /&gt;
&lt;br /&gt;
A table with no __tostring will pass through {{luaref|table.concat}} before insertion. An {{luaref|error|plain=y}} may be thrown if the table would cause table.concat to error. &lt;br /&gt;
(Use {{luaself|:_all}} instead for such tables.)&lt;br /&gt;
&lt;br /&gt;
When passed {{code|pos}} of type {{luaref|number|plain=y}}, the argument is identical to &#039;&#039;pos&#039;&#039; for {{luaref|table.insert|args=table, pos, value}}. &lt;br /&gt;
In fact, assuming a [[#valid|valid value]], {{luaself|:_|args=&#039;string&#039;, 1}} is exactly the same as {{luaref|table.insert|args=Buffer, 1, &#039;string&#039;}}.&lt;br /&gt;
&lt;br /&gt;
Just like with the position arguments of [[#Buffer|Buffer()]], any &#039;&#039;pos&#039;&#039; of type {{luaref|string|plain=y}} would be treated as relative to length.&lt;br /&gt;
{{anchor|raw}}&lt;br /&gt;
&lt;br /&gt;
Set {{code|raw}} to true to force append a &#039;&#039;value&#039;&#039; without tostring coercion, including [[#no-op|invalid]] values.&amp;lt;ref group=note name=raw&amp;gt;&lt;br /&gt;
Appending a value &amp;quot;raw&amp;quot;{{--}}i.e. without string type coercion{{--}} sets &amp;quot;raw mode&amp;quot;, which incurs a [[#performance|performance]] penalty &lt;br /&gt;
because future tostring ops would have to [[#valid|re-validate]] every value in the Buffer via {{luaself|:_all}} to insert them in a new table before passing that to table.concat (vs. passing itself directly). &lt;br /&gt;
That said, re-stringing a raw Buffer is still usually several times faster than using the {{luaref|Concatenation operator|..}} op to join an equivalent number of strings. &lt;br /&gt;
(See [[#Tips]] for ways to avoid  using raw)&amp;lt;/ref&amp;gt; &lt;br /&gt;
If given only two (non-self) arguments with the second being a boolean, then the second is read as &#039;&#039;raw&#039;&#039; instead.&lt;br /&gt;
&lt;br /&gt;
====Buffer:_nil====&lt;br /&gt;
&lt;br /&gt;
{{luaself|:_nil|args=pos, replacement|args2=replacement}}&lt;br /&gt;
&lt;br /&gt;
Removes the value buffered at {{code|pos}}. As with {{luaself|:_}}, a string &#039;&#039;pos&#039;&#039; string is treated as {{code|lang=lua|#Buffer + pos}}.&lt;br /&gt;
&lt;br /&gt;
If a non-boolean {{code|replacement}} is provided, then it will replace the value indexed at &#039;&#039;pos&#039;&#039;. Passing a boolean as the second argument is a no-op.&lt;br /&gt;
&lt;br /&gt;
When &#039;&#039;replacement&#039;&#039; is nil, the op is basically {{luaref|table.remove|args=Buffer, pos}}. As with the positional arguments of other Buffer methods, &lt;br /&gt;
any numerical string &#039;&#039;pos&#039;&#039; is added to length, such that {{luaself|:_nil&#039;0&#039;}} removes the last item. &lt;br /&gt;
Note the only type check on replacement is a direct comparison to both booleans (nil is implied). &lt;br /&gt;
Any other type, including strings, sets the Buffer to [[#raw|raw mode]].&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;pos&#039;&#039; that is omitted, nil, or false has the same effect as though &amp;lt;code&amp;gt;&#039;0&#039;&amp;lt;/code&amp;gt; (or {{luaself|pre=#|\}}) were passed. &lt;br /&gt;
Given only one non-numerical argument which evaluates true but {{luaref|tonumber||y}} would return it as nil , this treats it as though it were passed as the second.&lt;br /&gt;
If passed a non-numerical &#039;&#039;pos&#039;&#039; with any other argument, including nil, this is effectively a no op (though may still purge the [[#Buffer.last_concat|cache]]).&lt;br /&gt;
&lt;br /&gt;
====Buffer:_all====&lt;br /&gt;
&lt;br /&gt;
{{luaself|:_all|args={ value, ... }|args2={ ..., value = pos, functionName = args, ... }, nanKeys}}&lt;br /&gt;
&lt;br /&gt;
Takes a table {{code|value}}, iterates through all number keys {{luaref|table.sort|in order|plain=yes}}, appending each [[#valid|valid]] value to the end of the Buffer. &lt;br /&gt;
In contrast to {{luaref|ipairs}}, this starts at the most negative key (down to {{luaref|math.huge|-inf|y}}) and ends at the most positive index, &lt;br /&gt;
continuing through any nil keys and includes [[Double-precision floating-point format|non-integer number keys]]. (Note: despite more thorough iteration, &lt;br /&gt;
the runtime of Module:Buffer.__pairs is almost statisically indistinguishable from that of ipairs in most cases. Details at [[#Performance|Performance]] and [[#MBpairs|require&#039;Module:Buffer&#039;.__pairs]].)&lt;br /&gt;
&lt;br /&gt;
A table &#039;&#039;value&#039;&#039; that has no metatable will have its contents iterated by this function before moving on to the next value. All other data types are processed by {{luaself|:_}}.&lt;br /&gt;
{{anchor|nanKeys}}&lt;br /&gt;
&lt;br /&gt;
By default, this ignores non-number keys unless {{code|nanKeys}} evaluates true. If so, non-number keys are processed after number keys. &lt;br /&gt;
Keep in mind such keys are iterated in {{luaref|next|no particular|y}} order, though an order may be imposed by wrapping each pair in a table indexed at a number key.&lt;br /&gt;
&lt;br /&gt;
If given a &amp;lt;code&amp;gt;&#039;&#039;value&#039;&#039; = &#039;&#039;pos&#039;&#039;&amp;lt;/code&amp;gt; pair, defined as a number or number string indexed at a non-number key, &lt;br /&gt;
then they will be passed as the {{code|value}} and {{code|pos}} arguments for {{luaself|:_|plain=y}}. Thus, &lt;br /&gt;
:{{luaself|:_all|args=({1,2,3,&#039;... done&#039;,[3.5]=variable and 4 or {four=&#039;1&#039;,zero=1{{))}},true)}}&lt;br /&gt;
&lt;br /&gt;
produces the same result as:&lt;br /&gt;
:{|&lt;br /&gt;
|{{#tag:syntaxhighlight|Buffer:_(1):_(2):_(3)&lt;br /&gt;
if variable then&lt;br /&gt;
	Buffer:_(4)&lt;br /&gt;
else&lt;br /&gt;
	Buffer:_&#039;four&#039;:_(&#039;zero&#039;,1)--vs :_all{four=&#039;1&#039;,zero=1}; less redundant would be&lt;br /&gt;
end                           --   :_all{&#039;four&#039;,zero=1}, but that doesn&#039;t demo string numbers&lt;br /&gt;
Buffer:_&#039;... done&#039;&lt;br /&gt;
--returns &amp;quot;1234... done&amp;quot; if variable evaluates true or &amp;quot;zero123four... done&amp;quot; if false|lang=lua}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a non-number key points to a value that cannot be coerced into a {{luaref|tonumber|coerced into a number|y}} then the pair may be treated as &amp;lt;code&amp;gt;&#039;&#039;functionName&#039;&#039; = &#039;&#039;args&#039;&#039;&amp;lt;/code&amp;gt;, &lt;br /&gt;
when &#039;&#039;functionName&#039;&#039; matches a Buffer object function and &#039;&#039;args&#039;&#039; is not boolean. &lt;br /&gt;
If &#039;&#039;args&#039;&#039; is such that {{code|value[1]|lang=lua}} evaluates true, then this will pass the return of {{luaref|unpack|args=value, 1, table.maxn(value)}} to the named function; otherwise, the value is passed as is.&lt;br /&gt;
&amp;lt;ref group=note&amp;gt;In other words, if &#039;&#039;args&#039;&#039; is a string or a table without [1] set, it will be passed as the only argument. &lt;br /&gt;
Further note it is not possible to pass a &amp;lt;code&amp;gt;&#039;&#039;functionName&#039;&#039; = &#039;&#039;args&#039;&#039;&amp;lt;/code&amp;gt; pair where &#039;&#039;args&#039;&#039; is numerical since such would be read as &amp;lt;code&amp;gt;&#039;&#039;value&#039;&#039; = &#039;&#039;pos&#039;&#039;&amp;lt;/code&amp;gt;. &lt;br /&gt;
Finally, passing a function type as &#039;&#039;args&#039;&#039; will throw an error message.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Buffer:_in====&lt;br /&gt;
&lt;br /&gt;
{{luaself|:_in|args=...|args2=_G, name, save, ...}}&lt;br /&gt;
&lt;br /&gt;
Passes any arguments to [[#require&#039;Module:Buffer&#039;|Module:Buffer]] to create a new Buffer object, sets an external reference to the parent Buffer and returns the child.&amp;lt;ref group=&#039;note&#039; name=&#039;in-dependents&#039;&amp;gt;&lt;br /&gt;
There is no &#039;getChild&#039; method. If a child needed after returning to the parent, set it {{luaref|Local_variable_declarations|locally|y}} &lt;br /&gt;
or use {{luaself|:_G}} prior to returning or it may become irretrievable. (No, {{u|Codehydro}} did not get lazy. &lt;br /&gt;
Rather, this allows {{luaref|Garbage collection|garbage collection|y}} on children with no further purpose.)&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
This does &amp;lt;u&amp;gt;not&amp;lt;/u&amp;gt; append the child to the parent. (See {{luaself|:_out|plain=y}})&lt;br /&gt;
&lt;br /&gt;
Also, be aware that Buffer parent references are {{luaref|weak tables|weak|y}}. Thus, if you were to (re-)set a local variable that is currently set to the parent, such could trigger immediate garbage collection on the parent.&lt;br /&gt;
&lt;br /&gt;
====Buffer:_out====&lt;br /&gt;
&lt;br /&gt;
{{luaself|:_out|args=sep|args2=ops, sep{{ndash}}list, { default{{ndash}}sep, ..., [#] = sep }|args3=0, sep}}&lt;br /&gt;
&lt;br /&gt;
[[#Buffer object|Joins a Buffer]] with {{code|sep}} and appends result to its parent, which is returned. &lt;br /&gt;
If no parent is found, this is a no-op and returns the same Buffer.&lt;br /&gt;
&lt;br /&gt;
When given two or more arguments, this reads the first as {{code|ops}}{{--}}the number of :_out() operations to perform.&amp;lt;ref group=note&amp;gt;&lt;br /&gt;
For [[#performance]], the first arg is not type checked but read as &#039;&#039;ops&#039;&#039; only when multiple args are present (or if it is the number 0); &lt;br /&gt;
i.e., &amp;lt;code&amp;gt;Buffer:_out(2)&amp;lt;/code&amp;gt; uses &amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; as a separator. To append to the &#039;&#039;N&#039;&#039;th ancestor with no separator, &lt;br /&gt;
use &amp;lt;code&amp;gt;Buffer:_outs(&#039;&#039;N&#039;&#039;, nil)&amp;lt;/code&amp;gt;.&amp;lt;/ref&amp;gt; This applies the first &#039;&#039;sep&#039;&#039; in {{code|sep-list}} for the current Buffer, &lt;br /&gt;
the second for its parent, the third for its grandparent, and so on.&lt;br /&gt;
&lt;br /&gt;
If the last item is a {{luaref|table||y}}, then any &#039;&#039;nil&#039;&#039; in &#039;&#039;sep-list&#039;&#039; default to &amp;lt;code&amp;gt;&#039;&#039;table&#039;&#039;[1]&amp;lt;/code&amp;gt;; &lt;br /&gt;
any &#039;&#039;false&#039;&#039; mean &amp;quot;no-sep&amp;quot;.&amp;lt;ref group=note&amp;gt;Empty strings would produce the same output as false, however,&lt;br /&gt;
Lua string literals create objects that take up memory until garbage collected.&amp;lt;/ref&amp;gt; The table may be the second arg (i.e. &#039;&#039;sep-list&#039;&#039; may be omitted). &lt;br /&gt;
If it has other keys, then &#039;&#039;table[n]&#039;&#039; would apply instead of &#039;&#039;table[1]&#039;&#039;, making these synonymous:&amp;lt;br /&amp;gt;&lt;br /&gt;
{{luaself|:_out|args=4, nil, nil, nil, &#039; and &#039;, {&#039;, &#039;} }} and {{luaself|:_out|args=4, {&#039;, &#039;, [4] = &#039; and &#039;} }}.&lt;br /&gt;
&lt;br /&gt;
The number {{code|lang=lua|0}} is &amp;quot;magic&amp;quot; when passed as the first arg (even by itself), &lt;br /&gt;
joining and appending to the same Buffer &#039;&#039;after&#039;&#039; it has been {{luaself|Buffer|:_cc|emptied|y}}. &lt;br /&gt;
This is the only method by which a Buffer in [[#raw|raw mode]] may lose that status. Parent references are preserved.&lt;br /&gt;
&lt;br /&gt;
====Buffer:_str====&lt;br /&gt;
&lt;br /&gt;
{{luaself|:_str|args=sep|args2=ops, sep{{ndash}}list, { default{{ndash}}sep, ..., [#] = sep } }}&lt;br /&gt;
&lt;br /&gt;
Joins a Buffer with {{code|sep}} and returns the string.&lt;br /&gt;
&lt;br /&gt;
This uses the same helper method as {{luaself|:_out}} to handle multiple arguments, with which, if provided, this creates a new temporary Buffer to which this appends the results of the number of generations specified by &amp;lt;code&amp;gt;ops&amp;lt;/code&amp;gt;, with each ancestor in front of its descendants. This then performs one additional concat op using the &#039;&#039;sep&#039;&#039; at {{code|ops + 1|lang=lua}} and returns the result. If a parent-less Buffer is reached before &#039;&#039;ops&#039;&#039;, then the sep that follows its op number will separate the generations.&lt;br /&gt;
&lt;br /&gt;
When no [[#valid|valid]] &#039;&#039;sep&#039;&#039; is given, this returns a string identical to what would append to the next ancestor, if those arguments were passed to Buffer:_out instead and one additional :_out() op performed.&lt;br /&gt;
&lt;br /&gt;
However, because this does not actually append child Buffers to their parent, the result may differ where this would insert the sep at &#039;&#039;ops + 1&#039;&#039; and Buffer:_out would place the parent&#039;s sep between it and its child instead.&lt;br /&gt;
&lt;br /&gt;
====Buffer:_cc====&lt;br /&gt;
&lt;br /&gt;
{{luaself|:_cc|DUPLICATE-args=clear|args=clear, copy, meta|args2=0, true}}&lt;br /&gt;
&lt;br /&gt;
Nils all keys of the table referenced by {{code|clear}} and unsets its metatable. If &#039;&#039;clear&#039;&#039; evaluates false, this simply purges the cache at {{luaself|.last_concat}}.&lt;br /&gt;
&lt;br /&gt;
If given a table to {{code|copy}}, this will duplicate all key-value pairs of &#039;&#039;copy&#039;&#039; into &#039;&#039;clear&#039;&#039;, cloning any table value recursively via {{code|lang=lua|Buffer:_cc(0, value)}}. This returns the Buffer unless passed the number {{code|lang=lua|0}} as &#039;&#039;clear&#039;&#039;, which causes this to create a new table and return that instead. Passing {{code|lang=lua|true}} as &#039;&#039;copy&#039;&#039; is equivalent to passing the Buffer itself. If &#039;&#039;copy&#039;&#039; is not a table, then it will be set as the first item in &#039;&#039;clear&#039;&#039; as long as it is not &#039;&#039;false&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
While this may resemble {{luaref|mw.clone}}, there are several differences, namely that this:&lt;br /&gt;
* Gives &#039;&#039;clear&#039;&#039; the same metatable as &#039;&#039;copy&#039;&#039; (or sets &amp;lt;code&amp;gt;meta&amp;lt;/code&amp;gt;, if given) as opposed to a &amp;quot;clone&amp;quot; of the metatable.&lt;br /&gt;
* Conserves {{luaref|Length operator|Length|y}} attribute (though empty strings may replace some nil keys&amp;lt;ref group=note&amp;gt;&lt;br /&gt;
For example, given {{code|lang=lua|{nil, &#039;string&#039;} }} as &#039;&#039;copy&#039;&#039;, {{code|lang=lua|Buffer:_cc(clear, copy)}} makes {{code|lang=lua|#clear}} equal &amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;, &lt;br /&gt;
whereas {{code|lang=lua|#mw.clone{nil, &#039;string&#039;} }} equals &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; (as of March 2015). &lt;br /&gt;
This replicates length by filling clear halfway to the length of copy (the minimum needed to &#039;trick&#039; Lua) and then setting nil every key that would not trigger recalculation.&lt;br /&gt;
As a result, keys that would resize &#039;&#039;clear&#039;&#039; when set nil are left as empty strings. Such should be fairly rare;&lt;br /&gt;
given tables representing every possible way to position a single nil key for all lengths between 2 and 32 (inclusive), only 8.39 percent of such tables would have its nil copied as an empty string instead.&lt;br /&gt;
Also note that tables returned from {{code|lang=lua|Buffer:_(0, copy)}} have length declared on creation instead, and thus won&#039;t have extra strings attached. &lt;br /&gt;
The odds can be estimated using &amp;lt;math&amp;gt;y {{=}} 0.5 / \sqrt{x}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; is the upper limit that an arbitrary nil key from &#039;&#039;copy&#039;&#039; of length ranging from 1 to &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; is imaged as an empty string.&amp;lt;/ref&amp;gt;)&lt;br /&gt;
* {{luaref|Rawset||y}}s values and iterates without invoking any __pairs {{luaref|Metatables|metamethod|y}}.&lt;br /&gt;
* Includes Buffer parent and [[#raw|raw]] attributes (stored externally)&lt;br /&gt;
&lt;br /&gt;
To obtain the key-value pairs left as empty strings in the previous copy op in a table, simply call this again such with value such that &amp;lt;code&amp;gt;rawequal(clear, copy)&amp;lt;/code&amp;gt; is true; call :getParent() on this table returns &#039;&#039;clear&#039;&#039; (useful after leeaving the local scope which referenced &#039;&#039;clear&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
====Buffer:_parent====&lt;br /&gt;
&lt;br /&gt;
{{luaself|:_parent|args=sep|args2=ops, sep{{ndash}}list, { default{{ndash}}sep, ..., [#] = sep } }}&lt;br /&gt;
:&#039;&#039;To skip generations without breaking the Buffer chain, see [[#global functions]].&lt;br /&gt;
&lt;br /&gt;
Resembling the reverse of {{luaself|:_out}}, this calls {{luaself|:_str}} on the Buffer&#039;s parent with the arguments given and appends the strung ancestor(s) to the current Buffer, which is returned.&lt;br /&gt;
&lt;br /&gt;
The parent is unaffected by this operation and may still be retrieved via {{luaself|:_out}} or re-appended again with this function.&lt;br /&gt;
&lt;br /&gt;
====Buffer:getParent====&lt;br /&gt;
&lt;br /&gt;
{{luaself|:getParent|args=value|args2=functionName, ...}}&lt;br /&gt;
:&#039;&#039;Note that there is no &#039;getChild&#039; method&amp;lt;ref group=&#039;note&#039; name=&#039;in-dependents&#039;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns parent Buffer, or, if none exists, creates a new Buffer and returns it as the adopted parent. As with {{luaself|:_in}}, this does not automatically append the adoptive child to the new parent.&lt;br /&gt;
&lt;br /&gt;
If the first argument is a string matching the name of a Buffer object (or [[#library]]) function, this calls the function on the parent and forwards any additional {{luaself|varargs|plain=yes}}.&lt;br /&gt;
&lt;br /&gt;
When passed exactly one argument that is not a Buffer function name that starts with {{code|_}}, this calls {{luaself|:_|args=value}} on the parent.&lt;br /&gt;
&lt;br /&gt;
====Buffer:killParent====&lt;br /&gt;
&lt;br /&gt;
{{luaself|:killParent|args=...}}&lt;br /&gt;
&lt;br /&gt;
Unsets Buffer parent reference.&lt;br /&gt;
&lt;br /&gt;
If passed any args, they are forwarded to the current parent, if one exists, via Buffer:getParent as a &amp;quot;parting gift&amp;quot;. In either case, returns the current Buffer.&lt;br /&gt;
&lt;br /&gt;
This is not necessary for {{luaref|garbage collection||y}} since Buffer parent references are weak. Rather, use this when it is desirable to assign a new parent via Buffer:getParent or, for example, to prevent the inclusion of an ancestor when passing {{luaref|math.huge}} as &#039;&#039;ops&#039;&#039; for functions such as {{luaself|:_out|plain=y}} (more useful when [[#recycling|recycling Module:Buffer]] from another Module).&lt;br /&gt;
&lt;br /&gt;
===Stream mode===&lt;br /&gt;
====Buffer:stream====&lt;br /&gt;
&lt;br /&gt;
{{luaself|:stream|args=...}}&lt;br /&gt;
&lt;br /&gt;
Switches a Buffer to [[#Stream-Buffer|stream mode]]. While streaming, the __call metamethod will append values to the end of the Buffer &lt;br /&gt;
instead of the [[#Buffer object|usual op]].&lt;br /&gt;
&lt;br /&gt;
Aside from that, there is only one other function: {{luaself|pre=Stream{{ndash}}|:each}}. &lt;br /&gt;
Any args passed to Buffer:stream are forwarded to that function for a reason that should be evident when you finish reading this very short section.&lt;br /&gt;
&lt;br /&gt;
No special action is needed to exit this mode. The normal call to string op is restored upon the use of any regular Buffer function &lt;br /&gt;
or any operation which coerces the Buffer into a string (e.g. the &amp;lt;code&amp;gt;..&amp;lt;/code&amp;gt; operator).&lt;br /&gt;
&lt;br /&gt;
{{anchor|Stream-Buffer}}&lt;br /&gt;
====Stream-Buffer object====&lt;br /&gt;
&lt;br /&gt;
{{luaself|pre=Stream-|\|args=&#039;string&#039;|args2={concat{{ndash}}list}|args3=(var)}}{{anchor|streaming|calling a Buffer:stream}}&lt;br /&gt;
&lt;br /&gt;
Stream-Buffer objects accept only one argument which they append if [[#valid|valid]]. That is, the op is a streamlined version of {{luaself|:_}} &lt;br /&gt;
sans the &#039;&#039;pos&#039;&#039; and &#039;&#039;raw&#039;&#039; args, improving [[#performance|performance]] by about 50 percent (or, in one test versus &amp;lt;code&amp;gt;..&amp;lt;/code&amp;gt;, over 2000 percent).&lt;br /&gt;
&lt;br /&gt;
This also exploits {{luaref|named arguments|the syntactic sugar of function calls|y}} to append a series of string literals (and tables) with nothing between them &lt;br /&gt;
(or only {{luaref|Character class|ASCII space chars|y}} if desired).&lt;br /&gt;
&lt;br /&gt;
For example, both A and B will produce identical strings:&lt;br /&gt;
:{|&lt;br /&gt;
|{{#tag:syntaxhighlight|local A = require&#039;Module:Buffer&#039;:stream&#039;A string of text may flow&#039;&#039;with nothing between each string&#039; &#039;or perhaps only a space&#039;&lt;br /&gt;
	&#039;or even tab and line-break characters&#039;&#039;and continue to append individually&#039;&#039;for use with a joiner&#039;&lt;br /&gt;
local B = require&#039;Module:Buffer&#039;:_&#039;A string of text may flow&#039;:_&#039;with nothing between each string&#039; :_ &#039;or perhaps only a space&#039;&lt;br /&gt;
	:_&#039;or even tab and line-break characters&#039;:_&#039;and continue to append individually&#039;:_&#039;for use with a joiner&#039;&lt;br /&gt;
mw.log(A==B, A:_str&#039; &#039;)&lt;br /&gt;
true	A string of text may flow with nothing between each string or perhaps only a space or even tab and line-break characters and continue to append individually for use with a joiner&lt;br /&gt;
|lang=lua}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Stream-Buffer:each====&lt;br /&gt;
&lt;br /&gt;
{{luaself|pre=Stream-|:each|args=...}}&lt;br /&gt;
&lt;br /&gt;
Appends an undetermined number of [[#valid|valid]] values to the Buffer object.&amp;lt;ref group=note&amp;gt;This is no different than calling the Stream-Buffer object directly &lt;br /&gt;
with each item in the {{luaref|expression list}}; however, after noting how numbers and variables (too shy to [[skinny dip]] without parenthesis) &lt;br /&gt;
could look rather odd swimming fully clothed in a stream of naked strings, this was made for those whose aesthetics prefer &lt;br /&gt;
{{luaself|pre=Stream-|:each|args=(&#039;A&#039;,arg,&#039;B&#039;,arg2)}} over {{code|lang=lua|Stream{{ndash}}Buffer&#039;A&#039;(arg)&#039;B&#039;(arg2)}}.&lt;br /&gt;
As a side note, it is best practice to pass number &#039;&#039;strings&#039;&#039; instead of number literals (i.e. {{code|lang=lua|Buffer:stream&#039;1&#039;}} instead of {{code|lang=lua|Buffer:stream(1)}}) &lt;br /&gt;
as such improves performance and is perhaps more aesthetically pleasing in this mode.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the above line gives you [[Déjà vu]], that is because it is drawn from {{luaref|mw.html:wikitext|plain=y}}. &lt;br /&gt;
However, unlike mw.html:wikitext, this does &#039;&#039;not&#039;&#039; stop at the first &#039;&#039;nil&#039;&#039; value.&amp;lt;ref group=note&amp;gt;&lt;br /&gt;
If you want something like {{code|lang=lua|:wikitext(&#039;string1&#039;, varName, &#039;string2&#039;)}} such that &#039;&#039;varName&#039;&#039; is shorthand for an {{code|lang=lua|if}} statement that &lt;br /&gt;
appends &#039;&#039;varName&#039;&#039; and &#039;string2&#039; when the former is not nil, use {{code|lang=lua|:each(&#039;string1&#039;, {varName, &#039;string2&#039;})}} instead.&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Also, despite a more nuanced handling of non-string objects, this is [[#performance|over twice as fast]] as its mw.html analog and should be preferred &lt;br /&gt;
for appending multiple strings to (Stream-)[[#Element-Buffer|Element-Buffers]].&lt;br /&gt;
&lt;br /&gt;
==HTML library extension==&lt;br /&gt;
&lt;br /&gt;
Upon the first call to {{luaself|:_inHTML}}, Module:Buffer clones the {{luaref|HTML library|mw.html object metatable|y}}, adding Module:Buffer&#039;s __eq and __concat metamethods along with a few additional functions.&lt;br /&gt;
&lt;br /&gt;
Objects with this modified metatable are referred to as &#039;&#039;&#039;Buffer-HTML objects&#039;&#039;&#039;. Yet, though dressed in bells and whistles, they are only named with &#039;&#039;Buffer&#039;&#039; as an adjective since they lack most Buffer object functions.&lt;br /&gt;
&lt;br /&gt;
In contrast, the &#039;&#039;&#039;Element-Buffer&#039;&#039;&#039; (returned by [[#Buffer-HTML|the function call on a Buffer-HTML object]]) is a true Buffer object with specialized &amp;quot;tricks&amp;quot; allowing complex structures to be built via both mw.html and Buffer object methods as well as through a [[#Element-Buffer:_add|builder that perhaps marries the best of both worlds]].&lt;br /&gt;
&lt;br /&gt;
===Buffer functions for HTML===&lt;br /&gt;
&lt;br /&gt;
====Buffer:_inHTML====&lt;br /&gt;
&lt;br /&gt;
{{luaself|:_inHTML|args=tagName, args|args2={ args{{ndash}}list } }}&lt;br /&gt;
&lt;br /&gt;
Accepts the same parameters as {{luaref|mw.html.create||y}} to create and return a [[#Buffer-HTML|modified mw.html object]]. As with {{luaself|:_in}}, this does &#039;&#039;not&#039;&#039; append the child object to the parent Buffer and instead sets a Buffer-style parent reference.&lt;br /&gt;
&lt;br /&gt;
An exception to the above is when chaining this to an [[#Element-Buffer|&#039;&#039;Element-&#039;&#039;Buffer]] and such produces a &#039;&#039;selfClosing&#039;&#039; tag; when both conditions are met, this appends the tag and returns to the same Buffer.&amp;lt;ref group=note&amp;gt;That is, Element-Buffer{{code|lang=lua|:_inHTML&#039;br&#039;}} may be shorthand for {{code|lang=lua|:tag&#039;br&#039;:done()()}} when planning to continue using Buffer object functions. This &amp;quot;auto-done and back&amp;quot; for selfClosing tags does not apply to non-element Buffers in order not to encourage the use of Buffer:_inHTML for simple tags as per [[#Tips and style recommendations]].&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unlike mw.html.create, if {{code|args}} has keys other than &amp;lt;code&amp;gt;args.parent&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;args.selfClosing&amp;lt;/code&amp;gt;, it will pass for further processing through {{luaself|pre=Element-Buffer|:_add|plain=y}} (a cousin of {{luaself|:_all|plain=y}} that handles mw.html functions). Moreover, if passed a table where mw.html.create expects &#039;&#039;tagName&#039;&#039;, this treats it as &#039;&#039;args&#039;&#039; instead.&lt;br /&gt;
&lt;br /&gt;
Finally, this does not automatically set the &amp;lt;code&amp;gt;mw.html.parent&amp;lt;/code&amp;gt; reference, making this an alternative to mw.html:tag &lt;br /&gt;
&lt;br /&gt;
====Buffer:getHTML====&lt;br /&gt;
&lt;br /&gt;
{{luaself|:getHTML|args=value|args2=functionName, ...}}&lt;br /&gt;
&lt;br /&gt;
Available only after {{luaself|:_inHTML}} is used the first time.&lt;br /&gt;
{{anchor|lastHTML}}&lt;br /&gt;
&lt;br /&gt;
Accepts the same arguments as {{luaself|:getParent}}, however this instead return the last Buffer-HTML object (&amp;quot;lastHTML&amp;quot;) created, or, if available, the lastHTML passed to any of the following functions:&lt;br /&gt;
* {{luaself|\-HTML:getParent|plain=y}}&lt;br /&gt;
* {{luaself|\-HTML:getBuffer|plain=y}}&lt;br /&gt;
* {{luaself|\-HTML:_out|plain=y}} (except when passed {{code|lang=lua|0}})&lt;br /&gt;
&lt;br /&gt;
====Buffer:_html====&lt;br /&gt;
&lt;br /&gt;
{{luaself|:_html|args = at, raw|args2 = raw}}&lt;br /&gt;
&lt;br /&gt;
Available only after {{luaself|:_inHTML}} is used the first time.&lt;br /&gt;
&lt;br /&gt;
This (re-)appends the [[#lastHTML|last Buffer-HTML object]] to the current Buffer object. The &amp;lt;code&amp;gt;raw&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;pos&amp;lt;/code&amp;gt; args are generally the same as those in {{luaself|:_}}.&lt;br /&gt;
&lt;br /&gt;
When called with no arguments on an &#039;&#039;Element-&#039;&#039;Buffer, this appends lastHTML without [[#raw|string coercion]]. Be warned however that if the Element-Buffer belongs to lastHTML or one of its tags, such will cause an [[infinite loop]], which can be avoided by passing an explicit nil to append lastHTML as a string.&amp;lt;ref group=note&amp;gt;{{luaself|\-HTML:_parent}} serves a similar role, but appends Buffer objects rather than HTML objects. Also Buffer-HTML:_parent only appends the string form of its ancestor object(s).&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===HTML object functions===&lt;br /&gt;
&lt;br /&gt;
Buffer-HTML objects may be used like any mw.html object. (In fact, merely replacing {{code|mw.html.create}} with {{code|require&#039;Module:Buffer&#039;:_inHTML}} in an existing Module should produce the same output.)&lt;br /&gt;
&lt;br /&gt;
{{anchor|wrapper}}&lt;br /&gt;
Most mw.html functions are unchanged, except {{luaref|mw.html:tag|:tag}}, {{luaref|mw.html:done|:done}}, and {{luaref|mw.html:allDone|:allDone}} are embedded in a wrapper function that checks whether they return a normal mw.html object. If so, switches the metatable to convert it to a Buffer-HTML object and sets a parent reference.&lt;br /&gt;
&amp;lt;ref group=note&amp;gt;Buffer(-HTML) objects reference their parent differently from mw.html objects. Passing a normal mw.html object to Buffer:_inHTML as {{code|args.parent}} and then calling {{luaref|mw.html:done|:done}} the object created, followed by {{luaself|:getParent}} on the adopted parent, may return the &amp;quot;child.&amp;quot; This is a feature rather than a bug.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a side bonus, the {{code|..}} may be used on Buffer-mw.html objects directly (no {{luaref|tostring}} needed).&lt;br /&gt;
&lt;br /&gt;
{{anchor|Buffer-HTML}}&lt;br /&gt;
====Buffer-HTML object====&lt;br /&gt;
&lt;br /&gt;
{{luaself|\-HTML|args=&#039;string&#039;|args2={ args{{ndash}}list } }}&lt;br /&gt;
&lt;br /&gt;
Call this object as a function to return its {{code|lang=lua|.nodes}} index&amp;lt;ref group=note&amp;gt;{{--}}the internal table which holds elements appended via {{luaref|mw.html:wikitext||y}}, {{luaref|mw.html:tag||y}}, and {{luaref|mw.html:node||y}}&amp;lt;/ref&amp;gt;, which this converts to an {{luaself|pre=Element-|\|plain=y}} object, granting it the same metatable as regular Module:Buffer objects (as well as several additional &amp;quot;tricks&amp;quot;) and assigning the Buffer-HTML as its parent Buffer.&amp;lt;ref group=note&amp;gt;Passing arguments for {{luaself|pre=Element-|:_add}} via the &#039;&#039;args&#039;&#039; parameter of {{luaself|:_inHTML}} and {{luaself|\-HTML:tag}} during the creation of a new Buffer-HTML object is the only way to use most Buffer object functions on the new HTML object without converting its &amp;lt;code&amp;gt;.nodes&amp;lt;/code&amp;gt; into an Element-Buffer.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This takes one argument which is forwarded to its Element-Buffer. Tables pass to the specialized HTML builder {{luaself|pre=Element-|:_add}}. All other [[#valid]] values are appended to its Element-Buffer via {{luaself|:_}}.&lt;br /&gt;
&lt;br /&gt;
{|style=&#039;float:right&#039;&lt;br /&gt;
|{{TOC tab|{{TOC tab|{{TOC tab|{{TOC tab|{{TOC tab||Buffer-HTML:_parent|depth=2}}|Buffer-HTML:_str|depth=2}}|Buffer-HTML:_out|depth=2}}|Buffer-HTML:killParent|depth=2}}|Buffer-HTML:getParent|depth=2}}&lt;br /&gt;
|}{{anchor|HTML version}}&lt;br /&gt;
You cannot chain call regular Buffer functions on a Buffer-HTML object; however, since mw.html functions cannot read Buffer-style parent references, modified versions of methods that return [[#Buffer:_inHTML|the parent Buffer]] are available to Buffer-HTML without having to call into the Element-Buffer. For convenience, {{luaref|mw.html:allDone}} is called automatically prior to the op, though after the &amp;lt;code&amp;gt;lastHTML&amp;lt;/code&amp;gt; reference has been set for {{luaself|:getHTML}}.&amp;lt;ref group=note&amp;gt;That is, Buffer:getHTML may be used to return to the child node, though the trade off is that you may still need to call mw.html:allDone before using these methods in order to append the full HTML tree via [[#Buffer:_html|Buffer:_html]].&amp;lt;/ref&amp;gt;&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;div style=&amp;quot;margin:0; column-width: 15em; -moz-column-width: 15em; -webkit-column-width: 15em; width:49em&amp;quot;&amp;gt;&lt;br /&gt;
*{{replace|&#039;&#039;&#039;[[#Buffer:${{!}}:$]]&#039;&#039;&#039;|$|getParent}}&lt;br /&gt;
*{{replace|&#039;&#039;&#039;[[#Buffer:${{!}}:$]]&#039;&#039;&#039;|$|killParent}}&lt;br /&gt;
*{{replace|&#039;&#039;&#039;[[#Buffer:${{!}}:$]]&#039;&#039;&#039;|$|_out}} {{ref label|html-0-out|0}}{{ref label|html-ops-out|$}}&lt;br /&gt;
*{{replace|&#039;&#039;&#039;[[#Buffer:${{!}}:$]]&#039;&#039;&#039;|$|_str}} {{ref label|html-0-str|0}}{{ref label|html-ops-str|$}}&lt;br /&gt;
*{{replace|&#039;&#039;&#039;[[#Buffer:${{!}}:$]]&#039;&#039;&#039;|$|_parent}} {{ref label|html-parent|^}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&#039;font-size:smaller&#039;&amp;gt;&lt;br /&gt;
{{note label|html-0-out|||{{note label|html-0-str|0||&amp;amp;nbsp;if passed {{code|lang=lua|0}} as the first argument, these do not redirect the self-action via &amp;lt;code&amp;gt;:allDone()&amp;lt;/code&amp;gt;, however, these always return a Buffer-HTML object (think &amp;lt;code&amp;gt;{{luaself|pre=Element-|:done|args=(0)|plain=y}}&amp;lt;/code&amp;gt;). {{note label|html-0-out-perm|||For :_out only, the &amp;quot;magic&amp;quot; number zero &#039;&#039;permanently&#039;&#039; consolidates &amp;lt;code&amp;gt;Buffer-HTML.nodes&amp;lt;/code&amp;gt; (whether or not converted)}} just like &amp;lt;code&amp;gt;:_out(0)&amp;lt;/code&amp;gt; on a normal Buffer except it would not unset raw mode on an Element-Buffer.}}}}&lt;br /&gt;
&lt;br /&gt;
{{note label|html-ops-out|||{{note label|html-ops-str|$||&amp;amp;nbsp;When passed a [[#valid|valid]] sep for the first op, these temporarily{{ref label||0|html-0-out-perm}} switch the Element-Buffer (or unconverted .nodes) with a table containing only the concatenated string before stringing the Buffer-HTML in the first op. As with the non-HTML versions, only :_out appends the string to the parent Buffer.}}}}&lt;br /&gt;
&lt;br /&gt;
{{note label|html-parent|^||&amp;amp;nbsp;This takes arguments for {{luaself|:_str}} and calls it on the [[#Buffer:_inHTML|parent Buffer of the HTML tree]], returning and appending the result to the same Buffer-HTML object. In other words, the &amp;quot;auto-allDone&amp;quot; doesn&#039;t really apply here, or at least not in the same sense as with the other functions. (As a reminder, Buffer:_inHTML does not append to the parent Buffer those Buffer-HTML objects which it returns.)}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In addition to the above, [[#gfuncs|global functions]] may be available to Buffer-HTML if enabled; these functions are the same for all Module:Buffer objects{{--}}i.e. the self action is never redirected.&lt;br /&gt;
&lt;br /&gt;
===Element-Buffer functions===&lt;br /&gt;
{{anchor|Element-Buffer}}&lt;br /&gt;
====Element-Buffer object====&lt;br /&gt;
&lt;br /&gt;
{{luaself|pre=Element-|\|args=sep, i , j}}&lt;br /&gt;
&lt;br /&gt;
Sharing the same metatable as with regular Buffer objects, Element-Buffers concatenate the same way when [[#Buffer object|called]] &lt;br /&gt;
to produce a string analogous to the [[JavaScript]] DOM [http://www.w3schools.com/jsref/prop_html_innerhtml.asp &amp;quot;innerHTML&amp;quot;] property. &lt;br /&gt;
In other words, when strung, it is generally the contents of the Buffer-HTML object without the &amp;quot;outerHTML&amp;quot; or tag.&lt;br /&gt;
&lt;br /&gt;
There are exceptions to this &amp;quot;innerHTML&amp;quot; behavior. For instance, as appended to another object via {{luaref|mw.html:node}}, an Element-Buffer and its Buffer-HTML &lt;br /&gt;
are interchangeable (though appending the former via {{luaself|:_}} only includes the inner result).&lt;br /&gt;
&lt;br /&gt;
Also, using the concatenation operator {{code|lang=lua|..}} on an Element-Buffer includes its tag in a manner depending on if it is selfClosing:&lt;br /&gt;
*For most tags, the conjoined string is placed inside the tag, e.g. {{code|lang=lua|Buffer:_inHTML&#039;p&#039; &#039;inner text&#039; .. 1}} returns {{code|lang=lua|&#039;&amp;lt;p&amp;gt;inner text1&amp;lt;/p&amp;gt;&#039;}}. &lt;br /&gt;
*For selfClosers, the {{code|lang=lua|..}} op redirects to its Buffer-HTML, e.g. insert [[#Element-Buffer:_add|{{code|lang=lua|1=:_add{selfClosing=true} }}]] in the above example before {{code|lang=lua|.. 1}} to produce {{code|lang=lua|&#039;&amp;lt;p /&amp;gt;1&#039;}}.&lt;br /&gt;
:{{see|#Modified .. operator}}&lt;br /&gt;
&lt;br /&gt;
You may use most Buffer object functions normally, however if there is a [[#HTML version|Buffer-HTML version]], &lt;br /&gt;
it instead behaves as though chained on the [[#Buffer-HTML|outer HTML object]].&amp;lt;ref group=note&amp;gt;While Buffer-HTML objects may use [[#global functions]], &lt;br /&gt;
there is no separate Buffer-HTML version. In other words, the self-action of a global function on an Element-Buffer is &amp;lt;u&amp;gt;not&amp;lt;/u&amp;gt; redirected.&amp;lt;/ref&amp;gt; &lt;br /&gt;
You may also chain any mw.html object function. Unless otherwise indicated, such returns a [[#wrapper|wrapper]] method that merely redirects the self-action to the outside Buffer-HTML.&amp;lt;ref group=note&amp;gt;&lt;br /&gt;
{{luaref|mw.html:allDone}} is doubly wrapped for Element-Buffers, with the other wrapper setting a Buffer parent reference as described at {{luaself|:_inHTML}}. &lt;br /&gt;
Furthermore, {{luaself|pre=Element-|:tag}} and {{luaself|pre=Element-|:done}} do not call their mw.html namesakes at all, as detailed in their respective sections.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a final note, Element-Buffers are in permanent [[#raw|raw mode]] since it is expected that some mw.html method (e.g. :tag and :node) may or will append non-string elements.&amp;lt;ref group=note&amp;gt;However, &lt;br /&gt;
since the mw.html __tostring method never calls the Element-Buffer as a function, raw mode is not expected to reduce performance when appending the Buffer-HTML (or Element-Buffer via mw.html:node) &lt;br /&gt;
to another object.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Element-Buffer:done====&lt;br /&gt;
&lt;br /&gt;
{{luaself|pre=Element-|\|args=ops}}&lt;br /&gt;
&lt;br /&gt;
When passed nothing, this should behave just like {{luaref|mw.html:done}} as called the &amp;quot;outer&amp;quot; HTML object{{--}}returning &lt;br /&gt;
&amp;lt;code&amp;gt;Buffer-HTML.parent&amp;lt;/code&amp;gt;, if available, or Buffer-HTML if not.&lt;br /&gt;
&lt;br /&gt;
However, this has been re-designed to accept {{code|ops}}, the number of :done() operations to perform. Thus, &lt;br /&gt;
{{code|Element{{ndash}}Buffer:done(4)|lang=lua}} is equivalent to {{code|Buffer{{ndash}}HTML:done():done():done():done()|lang=lua}}.&lt;br /&gt;
&lt;br /&gt;
Pass {{code|lang=lua|0}} (zero) as &#039;&#039;dones&#039;&#039; to return to the Element-Buffer&#039;s direct HTML container.&lt;br /&gt;
&lt;br /&gt;
Finally, keep in mind that Buffer-HTML objects use the original mw.html:done (albeit in a light [[#wrapper|wrapper]]).&lt;br /&gt;
&lt;br /&gt;
====Element-Buffer:tag====&lt;br /&gt;
&lt;br /&gt;
{{luaself|pre=Element-|:tag|args=tagName, args|args2={ args{{ndash}}list } }}&lt;br /&gt;
&lt;br /&gt;
This uses the same helper method as {{luaself|:_inHTML|plain=y}} to handle arguments and produce new Buffer-HTML objects, &lt;br /&gt;
selectively passing &#039;&#039;args&#039;&#039; to {{luaself|:_add|plain=y}} when it contains keys not used by {{luaref|mw.html.create||y}}. &lt;br /&gt;
&lt;br /&gt;
As may be expected, this differs from Buffer:_inHTML in that this actually appends the tag and will set a mw.html-style parent reference. &lt;br /&gt;
This also lacks the other function&#039;s &amp;quot;auto-done&amp;quot; feature for selfClosing tags.&lt;br /&gt;
&lt;br /&gt;
As with the other Element-Buffer remake of an mw.html method, the features described here do not apply to the version used by Buffer-HTML objects.&lt;br /&gt;
&lt;br /&gt;
====Element-Buffer:_add====&lt;br /&gt;
&lt;br /&gt;
{{luaself|pre=Element-|:_add|args=args|args2={ wikitext{{ndash}}list, { args{{ndash}}list }, ..., arg {{=}} value, functionName {{=}} args } }}&lt;br /&gt;
&lt;br /&gt;
Takes a table as its only argument. This then thoroughly iterates all number keys from lowest&amp;lt;sup&amp;gt;[[#endnote_skip1|†]]&amp;lt;/sup&amp;gt; to highest using [[#MBpairs|this module&#039;s custom __pairs]] method. &lt;br /&gt;
Most values append as wikitext if [[#valid|valid]]. If a table is indexed at a number key, this [[Recursion (computer science)|recursively]] iterates the table before moving on to the next key.&lt;br /&gt;
&lt;br /&gt;
After processing all number key-value pairs, this then iterates the other (non-number) keys. For those naming a [[#Basic functions|core Buffer object function]], &lt;br /&gt;
this selectively unpacks {{code|args}} in a manner described at {{luaself|:_all}} when that function is passed the &#039;&#039;nanKey&#039;&#039; parameter (excepting that this does not read&lt;br /&gt;
numbers as &#039;&#039;pos&#039;&#039;, i.e. treats them the same way as strings).&lt;br /&gt;
 &lt;br /&gt;
This also accepts keys naming [[#HTML object functions|HTML]] and [[#Global functions|global functions]] as well as mw.html arguments. &lt;br /&gt;
Thus, {{code|lang=lua|Element{{ndash}}Buffer:_add{ tag {{=}} &#039;br&#039;, &#039;text&#039;} }} appends a BR tag &#039;&#039;after&#039;&#039; the text and &lt;br /&gt;
{{code|lang=lua|Element{{ndash}}Buffer:_add{ {tag {{=}} &#039;br&#039; }, &#039;text&#039;} }} appends the BR before the text. &lt;br /&gt;
Note however that how this handles &#039;&#039;args&#039;&#039; for such keys depends on the particular function or argument named:&lt;br /&gt;
:{|&lt;br /&gt;
|&lt;br /&gt;
======args.&#039;&#039;argName&#039;&#039;======&lt;br /&gt;
{{code|lang=lua|1=Element{{ndash}}Buffer:_add{ arg = value } }}&amp;lt;br /&amp;gt;&lt;br /&gt;
The effect of passing &#039;&#039;args&#039;&#039; with keys such as &amp;lt;code&amp;gt;args.selfClosing&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;args.parent&amp;lt;/code&amp;gt; is the same as though &#039;&#039;args&#039;&#039; were passed to {{luaref|mw.html.create}}. &lt;br /&gt;
This also takes one additional &#039;&#039;arg&#039;&#039;, i.e. &amp;lt;code&amp;gt;args.tagName&amp;lt;/code&amp;gt;, which value replaces the original &#039;&#039;tagName&#039;&#039; of the HTML object (or, if false, removes the tag).&lt;br /&gt;
&lt;br /&gt;
Note that these are the only keys for which a boolean &#039;&#039;arg&#039;&#039; would result in a op. (For Buffer object functions that do not no-op when passed only a boolean, place the boolean in an &#039;&#039;args&#039;&#039; table for unpacking.)&lt;br /&gt;
&lt;br /&gt;
======args.&#039;&#039;cssName&#039;&#039;======&lt;br /&gt;
{{code|lang=lua|1=Element{{ndash}}Buffer:_add{ cssName = cssValue } }}&amp;lt;br /&amp;gt;&lt;br /&gt;
A non-number &#039;&#039;key&#039;&#039; and &#039;&#039;value&#039;&#039; pair may default as the &amp;lt;code&amp;gt;cssName&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;cssValue&amp;lt;/code&amp;gt; parameters for {{luaref|mw.html:css}} when&lt;br /&gt;
the key matches none of the three [[#args.argsName|argName]] keys nor the name of any available function for Buffer and mw.html objects.&lt;br /&gt;
&lt;br /&gt;
This sends non-boolean &#039;&#039;cssValue&#039;&#039; though {{luaref|tostring||y}} prior to forwarding it to mw.html:css. Because this is the default, &lt;br /&gt;
any typoed or non-string key goes to mw.html:css as &#039;&#039;cssName&#039;&#039; (without string coercion). Functions not yet [[#loadable|loaded]] also end up there.&lt;br /&gt;
&lt;br /&gt;
The form {{code|lang=lua|1=Element-Buffer:_add{ css = { cssName = cssValue } } }} also works if sacrificing performance to reduce ambiguity is your thing (or if clearing a previously set value; &lt;br /&gt;
see example at [[#args.htmlFunction]] for more details).&lt;br /&gt;
&lt;br /&gt;
======args.tag&amp;lt;sup&amp;gt;[[#endnote_skip1|†]]&amp;lt;/sup&amp;gt;======&lt;br /&gt;
{{code|lang=lua|1=Element{{ndash}}Buffer:_add{ tag = tagName } }}&amp;lt;br /&amp;gt;&lt;br /&gt;
{{code|lang=lua|1=Element{{ndash}}Buffer:_add{ tag = { tagName, args{{ndash}}list } } }}&amp;lt;br /&amp;gt;&lt;br /&gt;
Set the key &amp;lt;code&amp;gt;args.tag&amp;lt;/code&amp;gt; to a string and this calls {{luaref|mw.html.create||y}} with it as the &#039;&#039;tagName&#039;&#039; argument. &lt;br /&gt;
This then raw inserts the returned mw.html object (&amp;quot;tag&amp;quot;), emulating the effect of {{luaref|mw.html:tag||y}} minus parent references, which are unnecessary.&lt;br /&gt;
&lt;br /&gt;
Pair the &#039;&#039;args.tag&#039;&#039; key with a table value and this calls mw.html.create with {{code|lang=lua|table[1]}} as &#039;&#039;tagName&#039;&#039; (or nil if [[#invalid]]), appending it as described above for string values, &lt;br /&gt;
but also pointing &amp;lt;code&amp;gt;tag.parent&amp;lt;/code&amp;gt; to the [[#Buffer-HTML|Element-Buffer&#039;s parent]] as well as temporarily setting the tag as the parent Buffer of &amp;lt;code&amp;gt;tag.nodes&amp;lt;/code&amp;gt;. &lt;br /&gt;
This then treats tag.nodes as a &#039;&#039;[[pseudo]]-&#039;&#039;Element-Buffer, [[Recursion (computer science)|recursing]] tag.nodes as &amp;quot;self&amp;quot; and the table as &#039;&#039;args&#039;&#039;, &lt;br /&gt;
though only iterating keys not equal to {{code|lang=lua|1}} (or less).[[#endnote_skip1-tag|&amp;lt;sup&amp;gt;[*]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Note this appends normal mw.html objects. That said, most Buffer functions named in &#039;&#039;args-list&#039;&#039; should still work as though the tag and &amp;lt;code&amp;gt;tag.nodes&amp;lt;/code&amp;gt; were Buffer objects.&amp;lt;ref group=note&amp;gt;However, &lt;br /&gt;
some Buffer methods may not work properly after appending objects via mw.html functions to the psuedo-Buffer.&amp;lt;br /&amp;gt;&lt;br /&gt;
For example, {{code|lang=lua|1={ tag = {&#039;div&#039;, &#039;List:&#039;, foo1, foo2, foo3, _out = { 0, &#039;\n*&#039; } } } }} could produce a div with each &#039;&#039;foo&#039;&#039; as [[Bullet_(typography)|bulleted]] item. &lt;br /&gt;
But, if &#039;&#039;foo1&#039;&#039; were {{code|lang=lua|1={ tag = { &#039;b&#039;, &#039;text&#039; } } }}, then {{luaself|:_out|plain=y}} may fail when appending {{luaref|table.concat||y}} with the non-string/number element.&lt;br /&gt;
A workaround is to add the pair {{code|lang=lua|1=_ = {true, true} }} to set [[#raw|raw mode]] on the div&#039;s tag.nodes; another is to replace &#039;&#039;foo1&#039;&#039; with {{code|lang=lua|mw.html.create&#039;b&#039;:wikitext&#039;text&#039;}}, &lt;br /&gt;
which appends in string form.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upon completing a recursive iteration for args.tag, this checks if the tag is selfClosing, in which case, this saves memory (which can improve performance) by setting tag.nodes to nil. &lt;br /&gt;
Likewise, if its tagName property evaluates false, this nils tag.styles and tag.attributes. Such presumes those properties will not be modified afterwards, &lt;br /&gt;
so use mw.html:tag outside of Element-Buffer:_add if such is not the case.&lt;br /&gt;
&lt;br /&gt;
======args.done&amp;lt;sup&amp;gt;[[#endnote_skip1|†]]&amp;lt;/sup&amp;gt;======&lt;br /&gt;
{{code|lang=lua|1=Element{{ndash}}Buffer:_add{ done = wikitext } }}&amp;lt;br /&amp;gt;&lt;br /&gt;
{{code|lang=lua|1=Element{{ndash}}Buffer:_add{ done = { ops, args{{ndash}}list } } }}&amp;lt;br /&amp;gt;&lt;br /&gt;
Similar to args.tag, this treats the first index of the table as the &#039;&#039;ops&#039;&#039; argument of {{luaself|pre=Element-|:done}}. &lt;br /&gt;
After calling that function, this then iterates all subsequent keys in a recursive call on the Element-Buffer of the Buffer-HTML object returned.&lt;br /&gt;
&lt;br /&gt;
======args.allDone======&lt;br /&gt;
{{code|lang=lua|1=Element{{ndash}}Buffer:_add{ allDone = wikitext } }}&amp;lt;br /&amp;gt;&lt;br /&gt;
{{code|lang=lua|1=Element{{ndash}}Buffer:_add{ allDone = { args{{ndash}}list } } }}&amp;lt;br /&amp;gt;&lt;br /&gt;
Similar to the previous two, except that the first index is not used as an argument; thus, the entire table is iterated.&lt;br /&gt;
&lt;br /&gt;
{{anchor|args.globalFunction}}&lt;br /&gt;
======args.&#039;&#039;globalFunction&#039;&#039;&amp;lt;sup&amp;gt;[[#endnote_skip2|‡]]&amp;lt;/sup&amp;gt;======&lt;br /&gt;
{{code|lang=lua|1=Element{{ndash}}Buffer:_add{ globalFunction = name } }}&amp;lt;br /&amp;gt;&lt;br /&gt;
{{code|lang=lua|1=Element{{ndash}}Buffer:_add{ globalFunction = { name, save, args{{ndash}}list } } }}&amp;lt;br /&amp;gt;&lt;br /&gt;
{{code|lang=lua|1=Element{{ndash}}Buffer:_add{ _B = { var, args{{ndash}}list } } }}&amp;lt;br /&amp;gt;&lt;br /&gt;
If the [[#gfuncs|global functions]] have been loaded and a key matches one, this calls the function with the first two arguments {{luaref|unpack||y}}ed from the paired &#039;&#039;args-list&#039;&#039; table. &lt;br /&gt;
This then recursively iterates the list, excluding keys less than or equal to {{code|lang=lua|2}}, with whatever object is returned as &#039;&#039;self&#039;&#039;. &lt;br /&gt;
However, if the returned object has a metatable and &amp;lt;code&amp;gt;object.nodes&amp;lt;/code&amp;gt; exists, the &#039;&#039;self&#039;&#039; will be object.nodes instead.&lt;br /&gt;
&lt;br /&gt;
Because {{luaself|:_B}} takes only one argument, args._B only unpacks the first index and starts the iteration after that key. &lt;br /&gt;
&lt;br /&gt;
If neither of the first two keys evaluate true, this assumes the paired value is a string for use as the &#039;&#039;name&#039;&#039; argument for the function matching its key.&amp;lt;ref group=note&amp;gt;&lt;br /&gt;
A caveat of this unconventional type checking is that pairing an args.globalFunction with a number value will throw an error &lt;br /&gt;
(which shouldn&#039;t be a problem since numbers make poor names for global variables).&amp;lt;/ref&amp;gt; In that case, the current call stack&#039;s &#039;&#039;self&#039;&#039;&lt;br /&gt;
(an Element-Buffer or [[#args.tag|tag.nodes]] if this was called indirectly) is &#039;&#039;self&#039; for the global function.&lt;br /&gt;
&lt;br /&gt;
======args.&#039;&#039;htmlFunction&#039;&#039;======&lt;br /&gt;
{{code|lang=lua|1=Element{{ndash}}Buffer:_add{ htmlFunction = object } }}&amp;lt;br /&amp;gt;&lt;br /&gt;
{{code|lang=lua|1=Element{{ndash}}Buffer:_add{ htmlFunction = { arg-list, name = value } } }}&amp;lt;br /&amp;gt;&lt;br /&gt;
If args.&#039;&#039;key&#039;&#039; matches an {{luaref|HTML library|mw.html object function|y}} that does not have its own args section, &lt;br /&gt;
this checks if the associated &#039;&#039;object&#039;&#039; is table. If not a table, or if &amp;lt;code&amp;gt;object.nodes&amp;lt;/code&amp;gt; evaluates true, &lt;br /&gt;
this calls the mw.html function with the object as the only argument.&lt;br /&gt;
&lt;br /&gt;
For table objects without an object.nodes, this iterates the table (non-recursively), repeatedly calling the named mw.html function &lt;br /&gt;
with one or two arguments depending on key&#039;s type in each loop. Non-number key-value pairs are both passed as arguments. &lt;br /&gt;
For number indicies, only the value is passed. Boolean values are a no-op.&lt;br /&gt;
&lt;br /&gt;
Unlike with most implementions of [[#MBpairs|Module:Buffer&#039;s __pairs]], this first loops through &#039;&#039;non-&#039;&#039;number keys, &lt;br /&gt;
followed by number keys (still ordered from lowest to highest). Thus, something like {{code|lang=lua|1=Element{{ndash}}Buffer:_add{ css = { &#039;width&#039;, width = &#039;1em&#039; } } }} is equivalent to &lt;br /&gt;
{{code|lang=lua|Element{{ndash}}Buffer:css( &#039;width&#039;, &#039;1em&#039; ):css( &#039;width&#039; )()}}, setting the width attribute, then unsetting it for a net no-op, and returning the Element-Buffer &lt;br /&gt;
(though the practical purpose of such is a mystery for this developer).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--//redundant?&lt;br /&gt;
======args.&#039;&#039;bufferFunction&#039;&#039;======&lt;br /&gt;
{{code|lang=lua|1=Element{{ndash}}Buffer:_add{ bufferFunction = object } }}&amp;lt;br /&amp;gt;&lt;br /&gt;
{{code|lang=lua|1=Element{{ndash}}Buffer:_add{ bufferFunction = { expression{{ndash}}list } } }}&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If passed a table object that has no metatable such that {{code|lang=lua|object[1]}} exists, this {{luaref|unpack}}s the table from {{code|lang=lua|1}} and {{luaref|table.maxn|args=table}} &lt;br /&gt;
for use as arguments for the Buffer object function named. Other objects are passed as the only argument to the designated function.&lt;br /&gt;
//!--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&#039;font-size:smaller&#039;&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
{{note label|skip1|†||&amp;amp;nbsp;Unlike with tables passed directly, [[Recursion (computer science)|recursive]] iterations &lt;br /&gt;
for functions marked with &amp;lt;sup&amp;gt;†&amp;lt;/sup&amp;gt; start at the smallest number greater than {{code|lang=lua|1}} instead of negative infinity. &lt;br /&gt;
Such was decided for performance and coding simplicity on the reasoning that any practical purpose for indexing at a key less than one may be accomplished &lt;br /&gt;
by instead indexing it at any of the trillion or so [[floating point]] values between one and two{{--}}e.g. {{code|lang=lua|1.01}}.}}&lt;br /&gt;
&lt;br /&gt;
{{note label|skip2|‡||&amp;amp;nbsp;The iteration may start after {{code|lang=lua|2}} for some global functions.}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{anchor|loadable}}&lt;br /&gt;
==Loadable convenience extensions==&lt;br /&gt;
The methods here are loaded on demand or depend on subroutines which need initialization.&lt;br /&gt;
&lt;br /&gt;
Whereas most Module:Buffer methods are built for performance, these methods perform tasks &lt;br /&gt;
which generally require less CPU usage if handled outside of Module:Buffer (i.e. via local variable declarations).&lt;br /&gt;
That said, they can greatly simplify the structure of the modules which employ them by doing, in a fluent manner, &lt;br /&gt;
many tasks which may otherwise force an awkward interruption in Buffer call chains.&lt;br /&gt;
&lt;br /&gt;
{{anchor|gfuncs}}&lt;br /&gt;
===Global functions===&lt;br /&gt;
The nodes of many chainable constructors are  traversed by methods such as {{luaref|HTML library||y}}&#039;s {{luaref|mw.html:done}} &lt;br /&gt;
or this module&#039;s {{luaself|getParent}} which only go in one direction. While fine for returning to an ancestor, &lt;br /&gt;
such functions are unable to navigate to nodes which are a child, sibling, or cousin. &lt;br /&gt;
When multiple variables may each affect multiple nodes, a common solution is to assign a local variable &lt;br /&gt;
to each node and then break out of call chain to switch objects; the alternative being a convoluted series of {{luaref|Logical operators|logical operators|y}}.&amp;lt;ref group=note&amp;gt;&lt;br /&gt;
For example, mw.html objects may append a node that isn&#039;t actually &amp;quot;done&amp;quot; if a condition which affects the node also appends text after the node;&lt;br /&gt;
i.e. the node must be appended prematurely so that it appears before the text. Occasionally, this can get confusing for future editors &lt;br /&gt;
when a node is several generations removed from the declaration statement:&lt;br /&gt;
&lt;br /&gt;
{{code|lang=lua|local x {{=}} mw.html.create():tag ...  :tag&#039;td&#039; ... :tag&#039;p&#039;:wikitext( ... ):tag&#039;br&#039;:done():done() }}{{--}}i.e. is &#039;&#039;x&#039;&#039; the TD, or did I miss an element in the [[ellipsis]]?&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The global functions, as described further below, were developed to simplify the construction and maintenance &lt;br /&gt;
of multi-conditional structures by providing in-chain variable declaration and navigation. &lt;br /&gt;
These methods are enabled when your global variable is passed to the module{{--}}either in the initial call to [[#initialize|require&#039;Module:Buffer&#039;]] &lt;br /&gt;
(further instructions in that section) or to {{luaself|:_in}} which calls the Module:Buffer metatable to produce a new Buffer object.&amp;lt;ref group=note&amp;gt;&lt;br /&gt;
Global function are not enabled by default for various reasons:&lt;br /&gt;
* Relatively few modules would benefit from these methods since most templates are one-dimensional (i.e. contain few if any nested conditional statements).&lt;br /&gt;
* Loading them to the Module:Buffer meta index means more items that must be sifted through each time a specific function has to be retrieved for execution.&lt;br /&gt;
* Lua checks the global scope last; thus retrieving values from that scope takes longer than it would if they were stored in the local scope.&lt;br /&gt;
* If used to excess, the global scope may get so cluttered as to slow the retrieval of basic Lua functions (e.g. {{luaref|type}} or {{luaref|pairs}}) even after Buffer functions are no longer used.&lt;br /&gt;
&lt;br /&gt;
It should be mentioned however that variable retrieval even even in a relatively cluttered global scope is fairly trivial. In fact, early versions of Module:Buffer &lt;br /&gt;
used globals extensively (and actually had no locals declared before the final return, or rather the entire module was just one long return statement). &lt;br /&gt;
In contrast, the current version nests many {{code|lang=lua|do ... end}} blocks to limit scope size. &lt;br /&gt;
Yet, {{luaself|:_}}, a core function which has changed little, is only a modest 10 percent faster than itself in the last unscoped version (not published);&lt;br /&gt;
then again, perhaps the benefit of scope dieting has been masked by much greater total number of variables required by new features?&amp;lt;/ref&amp;gt;&lt;br /&gt;
Initializing this extension also adds a [[#_G object|__call metamethod to the global _G]].&lt;br /&gt;
&lt;br /&gt;
====Buffer:_G====&lt;br /&gt;
&lt;br /&gt;
{{luaself|:_G|args=name, save}}&lt;br /&gt;
{{Distinguish2|the [[#G object|&amp;amp;sect; _G object]], which chain call looks the same but may behave differently.}}&lt;br /&gt;
&lt;br /&gt;
Pass &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;save&amp;lt;/code&amp;gt; to assign the object passed as &#039;&#039;save&#039;&#039; to a global variable via {{luaref|rawset|args=_G, name, save}}.&amp;lt;ref group=note&amp;gt;&lt;br /&gt;
Actually, the first argument to rawset is a local variable &amp;lt;code&amp;gt;[[#new_G|new_G]]&amp;lt;/code&amp;gt; which generally equals _G but not always, to be detailed in a later section.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pass only &#039;&#039;name&#039;&#039; and this substitutes &#039;&#039;self&#039;&#039; for &#039;&#039;save&#039;&#039; to assign the Buffer object to &amp;lt;code&amp;gt;_G[name]&amp;lt;/code&amp;gt; instead. &lt;br /&gt;
Give an explicit nil as &#039;&#039;save&#039;&#039; to unset a global. This returns the Buffer object as well as any argument given after &#039;&#039;name&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
This is a no-op when &#039;&#039;name&#039;&#039; is nil or a boolean, or, when &#039;&#039;save&#039;&#039; (eventually) evaluates true and {{luaref|rawequal|args=save, rawget(new_G, name)}} also returns true.&lt;br /&gt;
{{anchor|metaglobal}}&lt;br /&gt;
&lt;br /&gt;
If the named global already exists, this &amp;quot;backs up&amp;quot; the old value by moving it to the meta __index of the global table, &lt;br /&gt;
setting a new metatable if none exists.&amp;lt;ref group=note&amp;gt;If the meta global has an __index which is a function (as is the case after requiring [[Module:No globals]]), &lt;br /&gt;
the back-up op aborts without throwing an error.&amp;lt;/ref&amp;gt; Retrieving the old value requires unsetting the new one via {{luaself|:_R}} (more details in that section). &lt;br /&gt;
If overwritten a third time, the first value is discarded and the second takes its place in the back up. &lt;br /&gt;
&lt;br /&gt;
If a metaglobal variable exists but the global is nil, this sets the global without unsetting the metaglobal (i.e. does not back up a nil global).&lt;br /&gt;
An exception is when this is given an explicit nil as &#039;&#039;save&#039;&#039; and only the metaglobal exists; &lt;br /&gt;
thus, passing nil twice for the same &#039;&#039;name&#039;&#039;, unsets the key in both the global table and its metaindex.&lt;br /&gt;
&lt;br /&gt;
====Buffer:_R====&lt;br /&gt;
&lt;br /&gt;
{{luaself|:_R|args=name, save|args2=&#039;new_G&#039;, var, metaindex}}&lt;br /&gt;
&lt;br /&gt;
This {{luaref|rawset||y}} with the global table as the first argument and &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;save&amp;lt;/code&amp;gt; as the second and third, respectively,&lt;br /&gt;
returning the Buffer object for call chaining.&amp;lt;ref group=example&amp;gt;&lt;br /&gt;
The following demonstates how, by combining Buffer:_R and Buffer:_G, the global variable &#039;&#039;v&#039;&#039; can be declared, backed-up and replaced, replaced without back-up, restored from back-up, and removed completely:&lt;br /&gt;
:{|&lt;br /&gt;
|{{#tag:syntaxhighlight|require&#039;Module:Buffer&#039;&lt;br /&gt;
   (_G,&#039;v&#039;)           -- call module with global functions enabled and declare new buffer as v&lt;br /&gt;
   :_&#039;A&#039;              -- append &#039;A&#039; to the returned buffer&lt;br /&gt;
   :_G(&#039;v&#039;, 1):_(v)   -- _G.v = 1, shift old value (the buffer) to metaglobal.__index&lt;br /&gt;
   :_R(&#039;v&#039;, 2):_(v)   -- _G.v = 2, discard old value (1) without back-up&lt;br /&gt;
   :_R&#039;v&#039;:_(v)        -- unset _G.v, which now defaults to metaglobal.__index.v (the buffer)&lt;br /&gt;
   :_G(&#039;v&#039;, nil)&amp;quot;, &amp;quot;  -- remove back-up and join the buffer with a separator&lt;br /&gt;
..&#039; and &#039;..tostring(v)-- returns &#039;A, 1, 2, A12 and nil&#039;|lang=lua}}&lt;br /&gt;
|}&amp;lt;/ref&amp;gt; This is a no-op if &#039;&#039;name&#039;&#039; is nil or a boolean.&lt;br /&gt;
&lt;br /&gt;
{{anchor|new_G}}&lt;br /&gt;
{{see|#new_G object}}&lt;br /&gt;
Note that Buffer methods use a local variable &amp;lt;code&amp;gt;new_G&amp;lt;/code&amp;gt; as a proxy for the global table _G; &lt;br /&gt;
though not a global index, the string {{code|lang=lua|&#039;new_G&#039;}} is a &amp;quot;magic word&amp;quot; &lt;br /&gt;
that changes the destination for future &#039;&#039;save&#039;&#039; for this and Buffer:_G.&lt;br /&gt;
&lt;br /&gt;
Pass a table as &amp;lt;code&amp;gt;var&amp;lt;/code&amp;gt; (same place as &#039;&#039;save&#039;&#039;) to set as the &#039;&#039;new&#039;&#039; new_G. &lt;br /&gt;
Any table such that {{code|lang=lua|1=var._G == _G}} is treated as a (former) new_G object. &lt;br /&gt;
This {{luaref|getmetatable|gets the metatable|y}} of former proxies and {{luaref|setmetatable|sets a new table|y}} &lt;br /&gt;
with the {{luaself|_G object|plain=y}} __call method on non-new_G tables. Then, this, if third parameter &amp;lt;code&amp;gt;metaindex&amp;lt;/code&amp;gt; equals:&lt;br /&gt;
* nil {{--}} backs up the current proxy as the metaindex of the next (though this no-ops if &#039;&#039;var&#039;&#039; equals new_G to avoid cyclical indexing).&lt;br /&gt;
* false {{--}} leaves the metaindex intact (replacing the current proxy without back-up)&lt;br /&gt;
* true {{--}} unsets the metaindex of the next proxy&lt;br /&gt;
* any other value {{--}} sets that value as the metaindex of the next proxy. (Note new_G._G is not set until it is returned by {{luaself|:_2}})&lt;br /&gt;
&lt;br /&gt;
To omit or to pass nil/false as &#039;&#039;var&#039;&#039; has the same effect as {{luaself|:_R|args=&#039;new_G&#039;, {} }}.&lt;br /&gt;
Pass true instead and this treats it as though passed as &#039;&#039;metaindex&#039;&#039;, creating a new proxy without backing up the incumbent.&lt;br /&gt;
&lt;br /&gt;
====Buffer:_2====&lt;br /&gt;
&lt;br /&gt;
{{luaself|:_2|args=name, save|args2=&#039;new_G&#039;, ...}}&lt;br /&gt;
&lt;br /&gt;
This returns the value indexed at key &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; in the global table. If it does not exist, this forwards both arguments to {{luaself|:_G}} and returns the saved value (which may be itself).&lt;br /&gt;
&lt;br /&gt;
In other words, {{luaself|:_2|args=name, save}} is roughly equivalent to {{code|lang=lua|1=_G[name] = _G[name] or save or save==nil and Buffer}}.&lt;br /&gt;
&lt;br /&gt;
The string {{code|lang=lua|&#039;new_G&#039;}} will return the Module:Buffer local variable &amp;lt;code&amp;gt;[[#new_G|new_G]]&amp;lt;/code&amp;gt;, &lt;br /&gt;
used as a proxy for the global variable _G. Given more than one argument, this forwards arguments to {{luaself|:_R}} &lt;br /&gt;
to assign another proxy global before returning the (newly-deposed) proxy. This then sets &amp;lt;code&amp;gt;new_G._G&amp;lt;/code&amp;gt; to the &lt;br /&gt;
original _G object for call chaining. (See &amp;amp;sect; chain call in [[#G object|_G object]]).&lt;br /&gt;
&lt;br /&gt;
====Buffer:_B====&lt;br /&gt;
&lt;br /&gt;
{{luaself|:_B|args=var}}&lt;br /&gt;
&lt;br /&gt;
Takes only one argument and returns that argument.&lt;br /&gt;
 &lt;br /&gt;
Assuming the only &#039;&#039;X&#039;&#039; declared is {{luaref|_G|_G.X}} and new_G equals _G, then {{luaself|:_B|args=(X)}} and {{luaself|:_2|args=&#039;X&#039;}} are equivalent.&amp;lt;ref group=note&amp;gt;&lt;br /&gt;
Dubbing this a &amp;quot;global function&amp;quot; is bit of a misnomer since this never retrieves anything from the global table. &lt;br /&gt;
While designed for in-chain navigation to Buffer objects that were [[#Buffer:_G|self-declared as globals]], &lt;br /&gt;
this returns any local reference or literal passed as well (allowing {{luaself|pre=Element-|:_add}} to execute Buffer methods on non-Buffer objects &amp;lt;code&amp;gt;[[#args.globalFunction|args._B]]&amp;lt;/code&amp;gt;).&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When passed a variable that does not exist, this returns the Buffer nil object:&lt;br /&gt;
&lt;br /&gt;
=====Buffer-nil object=====&lt;br /&gt;
&lt;br /&gt;
{{luaself|\-nil()}}&amp;lt;br /&amp;gt;&lt;br /&gt;
{{luaself|\-nil:anyName|args=():_B( var )}}&lt;br /&gt;
&lt;br /&gt;
The Buffer nil object is unique. Calling this as a function returns nothing (in contrast, calling an empty Buffer object returns an empty string). &lt;br /&gt;
This does however have the Module:Buffer __concat metamethod, which treats this the same way as any [[#invalid|invalid]] object (i.e. ignores it).&lt;br /&gt;
&lt;br /&gt;
Appending this via {{luaref|mw.html:node}} or {{luaself|:_}} has the same effect as appending nil. &lt;br /&gt;
Passing this to {{luaref|tostring||y}} returns nil instead of the string &#039;nil&#039;.&lt;br /&gt;
&lt;br /&gt;
The only real Buffer method in its meta __index is {{luaself|:_B}}, however, any non-numerical key string retrieves a function that only returns the Buffer nil object for call chaining. &lt;br /&gt;
In a sense, you can think of {{code|lang=lua|Buffer:_B(var):...}} as an {{code|lang=lua|1=if var~=nil then var:...}} block around the following chain that ends in the the next :_B().&lt;br /&gt;
&lt;br /&gt;
If {{luaref|mw.clone|cloned|y}}, the clone will be a normal Buffer object.&lt;br /&gt;
&lt;br /&gt;
{{anchor|_G object}}&amp;lt;!--anchor below excludes the _ --&amp;gt;&lt;br /&gt;
====_G object====&lt;br /&gt;
&lt;br /&gt;
The first _G variable [[#initialize|passed to this module]] is given a __call metamethod that self-{{luaref|rawset||y}}s and returns in a manner &lt;br /&gt;
that depends on whether it was called directly or from a chain.&amp;lt;ref group=example&amp;gt;Saving a new_G object globally via a chain call&lt;br /&gt;
can prevent conflict. The follow example has a hypothetical &amp;quot;Module:X&amp;quot; that may overwrite globals declared by your module or&lt;br /&gt;
unwittingly discard your new_G when it passes _G to Module:Buffer (passing _G to this module resets new_G to the global table &lt;br /&gt;
even when the global functions are already enabled):&lt;br /&gt;
:{|&lt;br /&gt;
|{{#tag:syntaxhighlight|&lt;br /&gt;
return require&#039;Module:Buffer&#039;(_G)--Return before require to show intent to return a Buffer object; chain cannot be broken&lt;br /&gt;
	:_R(frame.args.title and     --store values outside global scope if invoked with title parameter&lt;br /&gt;
		&#039;new_G&#039;)&lt;br /&gt;
	:_G&#039;myBuff&#039;                  --save current Buffer in new_G&lt;br /&gt;
		:_2&#039;new_G&#039;               --retrieve new_G&lt;br /&gt;
			:_G&#039;my_G&#039;            --save new_G as global my_G&lt;br /&gt;
			:_G(&#039;t&#039;,             --save title object as my_G.t for later re-use&lt;br /&gt;
				mw.title.new(frame.args.title or frame.args.page)&lt;br /&gt;
			).myBuff             --go to my_G.myBuff (my_G lacks the Buffer:_2 method, but doesn&#039;t need it)&lt;br /&gt;
	:stream(my_G.t.exists        --just arbitrary code to show how in-line storage may be used without breaking the chain&lt;br /&gt;
			or warning(my_G.t),  --local function warning() declared before return&lt;br /&gt;
		require&#039;Module:X&#039;.main(my_G.t),&lt;br /&gt;
		my_G.t.isSubpage and subpage(my_G.t),&lt;br /&gt;
		... )&lt;br /&gt;
	:_R(&#039;new_G&#039;, my_G)           --set my_G as new_G again and have the new_G from Module:X as its metaindex&lt;br /&gt;
	:_(frame.args.detail and &lt;br /&gt;
		my_G.info&lt;br /&gt;
			:_(frame.args.detail)--append Buffer object from Module:X&#039;s new_G.info if args.details and it exists; append detail param to result&lt;br /&gt;
		or my_G.summary)         --just append summary from Module:X if not invoked with detail param.&lt;br /&gt;
	:_B(t and					 --use global t as a shorthand for &amp;quot;if not frame.args.title then&amp;quot; (t only declared a global in line 2 if no title given)&lt;br /&gt;
		myBuff&lt;br /&gt;
			:stream(frame.args.page,&lt;br /&gt;
				frame.args.details2,&lt;br /&gt;
				mw.html.create&#039;br&#039;,&lt;br /&gt;
				require&#039;Module:Y&#039;.main(frame))&lt;br /&gt;
		or my_G.myBuff           --place results in a table if invoked with title param (alternative chain call branches within Buffer:_B)&lt;br /&gt;
			:_inHTML&#039;table&#039;(_addArgs)&lt;br /&gt;
			:_parent()&lt;br /&gt;
	)&lt;br /&gt;
|lang=lua}}&lt;br /&gt;
|}&amp;lt;/ref&amp;gt; This module conserves any pre-existing metatable and alters no metamethod other than __call.&lt;br /&gt;
&lt;br /&gt;
:{|&lt;br /&gt;
|&lt;br /&gt;
=====direct call=====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;_G( k, v )&amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;_G&#039;string&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When called, the _G object self-sets any string passed as &amp;lt;code&amp;gt;k&amp;lt;/code&amp;gt; with whatever is passed as &amp;lt;code&amp;gt;v&amp;lt;/code&amp;gt;. &lt;br /&gt;
This returns &#039;&#039;v&#039;&#039;, or nil if omitted (unlike with rawset, an explicit nil is not necessary to unset a variable with direct calls).&lt;br /&gt;
&lt;br /&gt;
Note that &#039;&#039;k&#039;&#039; must be a string to declare or unset a global in this op. &lt;br /&gt;
Tables passed as the first argument are treated as though this were executed via a call chain (discussed shortly). &lt;br /&gt;
Passing &#039;&#039;k&#039;&#039; which is not one of those two types will throw an error. &lt;br /&gt;
&lt;br /&gt;
=====chain call=====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;chained-object:_G( k, v )&amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;chained-object:_G&#039;string&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Distinguish2|[[#Buffer:_G|&amp;amp;sect; Buffer:_G]], the Buffer object function, which differences are noted in the final paragraph of this section.}}&lt;br /&gt;
&lt;br /&gt;
When used in a call chain, this rawsets the &#039;&#039;k&#039;&#039;ey-&#039;&#039;v&#039;&#039;alue pair in the chained object and returns that object. &lt;br /&gt;
The _G object may chain itself when returning _G is desired for another op instead of &#039;&#039;v&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
In contrast to the direct op, the in-chain op will index non-string &#039;&#039;k&#039;&#039; values. Moreover, this only unsets object[k] when passed an explicitly nil &#039;&#039;v&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
If &#039;&#039;v&#039;&#039; is omitted in-chain, this uses the chained object as the missing argument; thus, (chained) &amp;lt;code&amp;gt;object:_G&#039;string&#039;&amp;lt;/code&amp;gt; &lt;br /&gt;
has identical effect and return to &amp;lt;code&amp;gt;_G(&#039;string&#039;, object)&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The same __call method is given to [[#new_G|new_G]] objects created by Buffer:_R, however the direct call only works if its metaindex is the _G object.&lt;br /&gt;
Any table such that &amp;lt;code&amp;gt;table._G&amp;lt;/code&amp;gt; points to the _G object may chain save to itself regardless of metaindex.&lt;br /&gt;
&lt;br /&gt;
Though the behavior of the chain op when &#039;&#039;v&#039;&#039; is omitted may be a [[Dead ringer (idiom)|dead ringer]] to that of [[#Buffer:_G|Buffer:_G]]&lt;br /&gt;
when &#039;&#039;save&#039;&#039; is omitted and [[#new_G|new_G]] is the chained object, mind that the Buffer object function sets keys in new_G variable &lt;br /&gt;
rather than the chained (Buffer) object; in other words, this is unaffected by Buffer:_R re-assigning new_G to another table. &lt;br /&gt;
Also, this does not have the back up behavior of Buffer:_G.&lt;br /&gt;
&lt;br /&gt;
{{anchor|Buffer-variable}}&lt;br /&gt;
===Buffer-variable object===&lt;br /&gt;
&lt;br /&gt;
====Buffer:_var====&lt;br /&gt;
&lt;br /&gt;
{{luaself|:_var|args=var, change|args2={ ... }|args3=()}}&lt;br /&gt;
&lt;br /&gt;
Raw appends a Buffer-variable object, which may appear as a different value each time the object is converted to a string.&amp;lt;ref group=example&amp;gt;&lt;br /&gt;
The following contrived example demonstrates most features of {{luaself|:_var|plain=y}}:&lt;br /&gt;
:{|&lt;br /&gt;
|{{#tag:syntaxhighlight|local H, sep = require&#039;Module:Buffer&#039;:_inHTML(&#039;div&#039;,{&#039;Heading &#039;,_var={nil,&#039;odd&#039;,&#039;even&#039;},color=&#039;blue&#039;,[&#039;text-decoration&#039;]=&#039;underline&#039;})&lt;br /&gt;
	:_out():_html(true):_html(true):_html(true)&lt;br /&gt;
sep = H:_in&#039;This is &#039;:_var():_&#039; - &#039;:_var&#039;A&#039;:_var(3,-1):_&#039;\n&#039;&lt;br /&gt;
return H:_in(H(sep)):_(sep)&lt;br /&gt;
	:_&#039;math:&#039;:_var():_&#039;+ 5 =&#039;:_var(true,5):_&#039;;&#039;:_var():_out(0,&#039; &#039;):_var(false):_&#039;- 1 = &#039;:_var()&lt;br /&gt;
--[[ produces:&lt;br /&gt;
&amp;lt;div style=&amp;quot;color:blue;text-decoration:underline&amp;quot;&amp;gt;Heading odd&amp;lt;/div&amp;gt;This is odd - A3&lt;br /&gt;
&amp;lt;div style=&amp;quot;color:blue;text-decoration:underline&amp;quot;&amp;gt;Heading even&amp;lt;/div&amp;gt;This is even - B2&lt;br /&gt;
&amp;lt;div style=&amp;quot;color:blue;text-decoration:underline&amp;quot;&amp;gt;Heading odd&amp;lt;/div&amp;gt;This is odd - C1&lt;br /&gt;
&amp;lt;div style=&amp;quot;color:blue;text-decoration:underline&amp;quot;&amp;gt;Heading even&amp;lt;/div&amp;gt; This is even - D0&lt;br /&gt;
 math: 0 + 5 = 5 ; 5 - 1 = 4   --]]|lang=lua}}&lt;br /&gt;
 |}&amp;lt;/ref&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Initialize a Buffer-variable object by passing as &amp;lt;code&amp;gt;var&amp;lt;/code&amp;gt; a:&lt;br /&gt;
* number - which, when strung the first time, appears as that number and reappears as &amp;lt;code&amp;gt;var + change&amp;lt;/code&amp;gt; the next time it is strung. &lt;br /&gt;
* string - that transforms into the next [[ASCII]] character via {{luaref|string.char||args=var:byte() + change}}.&lt;br /&gt;
* table - to return the first (non-nil) item, then the second, and so on as determined by {{luaref|next|args=table}}, looping back to the first item after reaching the last. (Note the &#039;&#039;change&#039;&#039; argument does not apply to table-based Buffer-variables.)&lt;br /&gt;
* custom function - to be set as the _build and __tostring method of a variable-object, though instructions for coding such functions are beyond the scope of this manual.&lt;br /&gt;
&lt;br /&gt;
Re-append the same variable object by passing {{code|lang=lua|true}} as the first argument. &lt;br /&gt;
For non-table-based variables, you may specify &#039;&#039;change&#039;&#039; to append a sister version &lt;br /&gt;
which transforms the value at the rate specified. Sister changes are cumulative. Thus, &lt;br /&gt;
if the original is re-strung after a sister, its value will differ from that of its last appearance &lt;br /&gt;
by the sum of the original and sister rates.&lt;br /&gt;
&lt;br /&gt;
Apply a &#039;&#039;change&#039;&#039; without appending a new variable object to the Buffer by passing {{code|lang=lua|false}}. &lt;br /&gt;
The shift is effective immediately and may affect previously appended variable objects not yet [[#Buffer:_out|finalized]]. &lt;br /&gt;
Pass only false (i.e., omit &#039;&#039;change&#039;&#039;) to produce the same effect as stringing the original once. &lt;br /&gt;
Note that the false-change is the only &#039;&#039;change&#039;&#039; table-based Buffer variables will honor.&amp;lt;ref group=note&amp;gt;&lt;br /&gt;
False cycles tables based on {{luaref|Length operator|#|y}} instead of {{luaref|next}}, which may diverge or error if the table contains nil items.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pass nothing to append a version which simply repeats the result of the last stringing. While generally identical in effect to &lt;br /&gt;
the object generated by &amp;lt;code&amp;gt;:_var(true, 0)&amp;lt;code&amp;gt;, the Buffer-variable will return nothing if strung before any of its sisters.&lt;br /&gt;
&lt;br /&gt;
If passed an explicit nil as the first argument, this is no-op. If passed a boolean before any Buffer-variable has been initialized, &lt;br /&gt;
this is also a no-op. Note that any op disables future caching at {{luaself|.last_concat|plain=y}} for all Buffer objects &lt;br /&gt;
in your module (and in any module which may require it).&lt;br /&gt;
&lt;br /&gt;
{{anchor|library}}&lt;br /&gt;
===String, mw.ustring, and mw.text libraries===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Modified {{code|..}} operator==&lt;br /&gt;
{{code|Buffer .. value}}&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&#039;&#039;Buffer-HTML&#039;&#039; .. value&amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
This is akin to {{luaref|self=Buffer/doc|:_all|&#039;&#039;&#039;new-buffer&#039;&#039;:_all|args={ Buffer, value} }} or &amp;lt;code&amp;gt;{{luaref|tostring||p|args=Buffer}} .. value&amp;lt;/code&amp;gt;. HTML objects created by a Buffer may also be concatenated in this manner.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&#039;&#039;Buffer-HTML&#039;&#039; .. value&amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;value .. &#039;&#039;Element-Buffer&#039;&#039;&amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Concatenate an Element-Buffer to another value  to return the result inside the tag, such that:&lt;br /&gt;
{{#tag:syntaxhighlight|&lt;br /&gt;
local Buff = require&#039;Module:Buffer&#039;:_inHTML&#039;div&#039;{&#039;Section &#039;,color=&#039;red&#039;}&lt;br /&gt;
return {Buff..1,Buff..2,Buff..3}&lt;br /&gt;
|lang=lua}}&lt;br /&gt;
&lt;br /&gt;
Can be a rapid way of generating:&lt;br /&gt;
{{#tag:syntaxhighlight|&lt;br /&gt;
local section = {}&lt;br /&gt;
for k = 1, 3 do&lt;br /&gt;
	table.insert(section, tostring(mw.html.create&#039;div&#039;:css{color=&#039;red&#039;}:wikitext(&#039;Section &#039;, k)))&lt;br /&gt;
end&lt;br /&gt;
return section&lt;br /&gt;
|lang=lua}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{anchor|MBpairs}}&lt;br /&gt;
==require&#039;Module:Buffer&#039;.__pairs==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{anchor|tips|Tips}}&lt;br /&gt;
==Tips and style recommendations==&lt;br /&gt;
* If [[#Buffer|joining Buffer]] with a string immediately after &amp;lt;code&amp;gt;:_&#039;&amp;lt;i&amp;gt;text&amp;lt;/i&amp;gt;&#039;&amp;lt;/code&amp;gt;, place a space between &#039;string&#039; and the [[#Buffer|separator]] and use double/single quote marks to . (i.e. &amp;lt;code&amp;gt;:_&#039;&amp;lt;i&amp;gt;text&amp;lt;/i&amp;gt;&#039; &amp;quot; &amp;quot;&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;:_&#039;&amp;lt;i&amp;gt;text&amp;lt;/i&amp;gt;&#039;{{`}} &#039;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;:_&#039;&amp;lt;i&amp;gt;text&amp;lt;/i&amp;gt;&#039;(&#039; &#039;)&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Saving Module:Buffer locally, e.g. &amp;lt;code&amp;gt;local Buffer = {{luaref|require|args=&#039;Module:Buffer&#039;|plain=y}}&amp;lt;/code&amp;gt;, though fine, is often unnecessary since all Buffer objects can create new buffers via {{luaself|:_in}}.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For {{luaself|:_}}&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Treat {{code|:_}} as though it were a {{code|..}} op. Wrapping strings with unnecessary {{code|()}} is akin to {{code|( &#039;string1&#039; ) .. ( &#039;string2&#039; ) .. ( &#039;string3&#039; )}}.&lt;br /&gt;
* Most uses of {{code|raw}} can be avoided through careful planning with the {{code|pos}} argument. That said, the performance decrease from &#039;&#039;raw&#039;&#039; is unlikely to be significant for modules transcluded on less 100,000 pages. In short, reduction in server load from avoiding &#039;&#039;raw&#039;&#039; may not be worth it if such makes the code harder to maintain.&lt;br /&gt;
* To insert an empty string as a placeholder for a [[#Buffer|separator]] without setting {{code|raw}}, pass a table containing only a empty string, like so: {{luaself|:_|args={&#039;&#039;} }}.&lt;br /&gt;
* Raw appending a non-table is pointless since no other Scribunto type can tostring differently afterwards. However, this developer believes you are smart enough that {{code|lang=lua|1=raw and type(v)==&#039;table&#039;}} is a waste of server resources. (Such checks are why {{luaref|mw.html:wikitext||y}} takes twice as much time to append a list of strings as {{luaself|pre=Stream-|:each|plain=y}} despite their near-identical roles in an Element-Stream-Buffer).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For {{luaself|:_out}} and {{luaself|:_str}}&#039;&#039;&#039;&lt;br /&gt;
* Something like {{code|lang=lua|Buffer_str(2, false, A, false, {C, B})}} will use variable &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt; as the parent&#039;s separator, or &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; instead if &#039;&#039;A&#039;&#039; is nil, or &amp;lt;code&amp;gt;C&amp;lt;/code&amp;gt; if both A and B are nil.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For {{luaself|:_all}}&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Appending values in multiple locations is one of the primary reasons why the [[#nanKeys|nanKeys]] argument exists. While passing a boolean directly will cause an error, you can do something like...&lt;br /&gt;
::this:{{sp|3}}{{code|1=Buffer:_all({condition and {_nil={&#039;0&#039;, &#039;replacement&#039;},Front=1,getParent=&#039;from child&#039;{{))}}}, true)|lang=lua}}&lt;br /&gt;
::versus: {{code|lang=lua|Buffer:_nil(&#039;0&#039;, condition and &#039;replacement&#039; or false):_(condition and &#039;Front&#039;, 1):getParent(condition and &#039;from child&#039;):_B(child)}}.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For {{luaself|:_cc}}&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* If the table reference passed as {{code|clear}} was appended [[#raw|raw]] in multiple positions, this is akin to performing {{luaself|:_nil}} at all positions simultaneously. (May be easier than trying to come up with a {{luaref|string.gsub}} pattern)&lt;br /&gt;
* Inserting a [[#Buffer:_G|named]] empty table is raw as a placeholder to be populated later via this function may be easier than calculating &#039;&#039;pos&#039;&#039; argument of {{luaself|:_}}.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For {{luaself|:_inHTML}} &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* When appending simple HTML structures, something like {{luaself|:_|args=mw.html.create&#039;br&#039;}} is roughly 6 times more efficient than &amp;lt;code&amp;gt;{{luaself|:_inHTML|plain=y}}&amp;lt;syntaxhighlight lang=lua enclose=none&amp;gt;&#039;br&#039;:_out()&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/code&amp;gt;, at least in terms of server CPU usage. (Though {{code|lang=lua|Buffer:_&#039;&amp;lt;br /&amp;gt;&#039;}} is 25 and 4 times more efficient than both examples, respectively.)&lt;br /&gt;
:Buffer:_inHTML is slower on the first run due to initialization. After the first run, the efficiency of Buffer:_inHTML improves by a factor of 4 (though not quite as fast as the other two).&lt;br /&gt;
&lt;br /&gt;
{{anchor|performance}}&lt;br /&gt;
==Performance==&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
&lt;br /&gt;
{{reflist|group=example}}&lt;br /&gt;
&lt;br /&gt;
==Notes==&lt;br /&gt;
Non-literal interpretations of the source code (that is, more opinion than fact) are provided here to offer additional clarity. &lt;br /&gt;
Overly technical details may be found here as well when including such caveats appears more likely to confuse than help those advanced-but-not-quite-fluent in Lua.&lt;br /&gt;
&lt;br /&gt;
Though commentary was deemed unneccessary for the {{Scribunto}}, Scribunto methods are &amp;quot;safe&amp;quot; for beginners and &lt;br /&gt;
offer extensive in-code help in the form of {{luaref|error||y}} messages. In contrast, Module:Buffer methods, &lt;br /&gt;
intended for intermediate-advanced coders, are built with &amp;quot;safeties off&amp;quot;{{--}}i.e., minimal type filtering and custom error warnings{{--}}to maximize performance &lt;br /&gt;
(though the rare {{luaref|assert}} may be found in methods which seldom need to be used more than once and where the default error message &lt;br /&gt;
seemed exceptionally vague or difficult to trace).&lt;br /&gt;
&lt;br /&gt;
{{reflist|group=note}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;includeonly&amp;gt;{{#ifeq:{{SUBPAGENAME}}|sandbox | |&lt;br /&gt;
&amp;lt;!-- Categories below this line, please; interwikis at Wikidata --&amp;gt;&lt;br /&gt;
[[Category:Lua metamodules]]&lt;br /&gt;
}}&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>98.230.192.179</name></author>
	</entry>
</feed>