Sabtu, 26 September 2026
21:15 WIB
TERKINI
Bandar Lampung Semangat Anak Sawah: Harumkan Nama Lampung di Kancah Nasional Tanpa Dukungan Pemda Lampung Selatan Gunung Anak Krakatau Kembali Erupsi, Status Siaga Tetap Dipertahankan Bandar Lampung BPS Lampung Tuntaskan Sensus Ekonomi 2026, Hasilnya Siap Rilis Awal 2027 Bandar Lampung Inovasi Double Teaching: Guru Ahli Berbagi Ilmu Lintas Sekolah di Lampung Bandar Lampung Coki, Buaya Peliharaan Warga Panjang yang Bikin Haru Jelang Evakuasi KKP Lampung Tekuni Hobi Sejak Kuliah, Dani Tetap Bertahan Jual Ikan Hias di Tengah Tantangan Cuaca Prakiraan Cuaca Lampung 26 September 2026: Cerah Berawan dan Potensi Hujan Humaniora Perlindungan Anak Digital: MPR Desak Komitmen Global Terwujud Nyata di Tanah Air Regional Bupati Gowa Sitti Husniah Talenrang Tersangka Pemerasan Perizinan Bangunan dan TPPU Bandar Lampung Puluhan Siswa di Lampung Tengah Diduga Keracunan Makanan Program MBG Bandar Lampung Semangat Anak Sawah: Harumkan Nama Lampung di Kancah Nasional Tanpa Dukungan Pemda Lampung Selatan Gunung Anak Krakatau Kembali Erupsi, Status Siaga Tetap Dipertahankan Bandar Lampung BPS Lampung Tuntaskan Sensus Ekonomi 2026, Hasilnya Siap Rilis Awal 2027 Bandar Lampung Inovasi Double Teaching: Guru Ahli Berbagi Ilmu Lintas Sekolah di Lampung Bandar Lampung Coki, Buaya Peliharaan Warga Panjang yang Bikin Haru Jelang Evakuasi KKP Lampung Tekuni Hobi Sejak Kuliah, Dani Tetap Bertahan Jual Ikan Hias di Tengah Tantangan Cuaca Prakiraan Cuaca Lampung 26 September 2026: Cerah Berawan dan Potensi Hujan Humaniora Perlindungan Anak Digital: MPR Desak Komitmen Global Terwujud Nyata di Tanah Air Regional Bupati Gowa Sitti Husniah Talenrang Tersangka Pemerasan Perizinan Bangunan dan TPPU Bandar Lampung Puluhan Siswa di Lampung Tengah Diduga Keracunan Makanan Program MBG

Modul:Buffer

Wikimedia module

Dokumentasi modullihatsuntingriwayatsegarkan
Siap digunakanModul ini dinilai siap digunakan secara umum. Modul ini sudah matang dan diperkirakan bebas dari bug dan siap digunakan pada tempat yang tepat di manapun. Modul ini siap disinggung di halaman-halaman bantuan dan sumber informasi Wikipedia lainnya sebagai pilihan untuk dipelajari para pengguna baru. Untuk mengurangi beban server dan output yang tidak diharapkan, modul ini harus diperlengkapi dengan halaman bak pasir dan kasus uji daripada harus melakukan suntingan coba-dan-salah berulang-ulang.
WarningModul Lua ini digunakan pada sekitar 411.000 halaman, atau sekira 10% dari keseluruhan halaman.
Untuk mencegah suntingan mengganggu skala besar dan beban peladen, setiap perubahan harus diuji di subhalaman /bak pasir atau /kasus uji Modul:Buffer, atau bak pasir modul Anda. Perubahan yang telah diuji kemudian dapat ditambahkan ke halaman ini dalam satu suntingan. Pertimbangkan untuk mendiskusikan perubahan di halaman pembicaraan sebelum mengimplementasikannya.
DiproteksiModul ini dilindungi. Modul ini sangat mencolok yang digunakan oleh banyak halaman, atau sangat sering disubstitusikan. Karena vandalisme atau kesalahan akan mempengaruhi banyak halaman, dan suntingan kecil dapat memberi beban besar pada server, modul ini dilindungi dari penyuntingan.
Dokumentasi di atas ditransklusikan dari Modul:Buffer/doc. (sunting | riwayat)
Penyunting dapat melakukan uji coba pada halaman bak pasir (buat | cermin) dan kasus uji (buat) modul ini.
Subhalaman modul ini.
--[[=============================
This Module was written by Alexander Zhikun He, also known as, User:Codehydro on the English Wikipedia
All methods were developed independently and any resemblance to other string buffer libraries would be coincidental.
Furthermore, many methods will not work when compiled by standard Lua libraries as they depend on behaviors unique to
the MediaMiki Scribunto mod, which, for example, has a getmetatable() method that always returns nil on non-tables.
https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual
Source code comments may be thin at some points because they are intended to be supplemented by the documentation page:
https://en.wikipedia.org/wiki/Module:Buffer/doc
Licensed under Creative Commons Attribution-ShareAlike 3.0 Unported License
https://en.wikipedia.org/wiki/Wikipedia:Text_of_Creative_Commons_Attribution-ShareAlike_3.0_Unported_License
https://en.wikipedia.org/wiki/Module:Buffer
https://en.wikipedia.org/wiki/User:Codehydro
=============================--]]
localfunctionValid(v)--type validation
ifvandv~=truethen--reject nil/boolean; faster than 2 type() comparisons
localstr=tostring(v)--functions not filtered since unlikely passed by accident (Scribunto does not have userdata/thread types)
ifstr~=vandstr=='table'thenreturnrawget(v,1)andtable.concat(v)end--tostring(string-type) returns same ref; same refs compare faster than type()
ifstr~=''thenreturnstrend--numbers are coerced to string per table.concat op; appending in string form saves ops on repeat concat
end
end
localnoOp,MBpairs=function()enddolocaliMap,vMap,oMap,pIter,pOther,pFast,Next--Map
localfunctioninit()--init = noOp after first run
functionNext(t)returnnext,tend--slightly faster to do this than to use select()
functionpIter(t,k)k=(iMap[t]orMBpairs(t,true)andiMap[t])[notkand1orvMap[t][k]]returnk,t[k]end--don't use rawget; accepting unmapped tables does not measurably affect performance.
functionpOther(t,k)k=(oMap[t]orMBpairs(t,true)andoMap[t])[nil==kand1orvMap[t][k]]returnk,t[k]end--comparison to nil because false is a valid key
functionpFast(t,k)k=notkand1ork<(vMap[t]or#t)andk+1ornilreturnk,t[k]end--mapless iterator; almost as fast as native ipairs; slight performance penalty when length not cached
--k and k < (vMap[t] or #t) and k + 1 or not k and 1 or nil return k, t[k] end--mapless iterator; almost as fast as native ipairs; slight performance penalty when length not cached
localmk={__mode='k'}--use mode 'k'; found that mode 'kv' sometimes garbage collects maps mid-loop (may not error because iterators auto re-map, but that's expensive)
init,iMap,vMap,oMap=noOp,setmetatable({},mk),setmetatable({},mk),setmetatable({},mk)--iMap is numeric keys, oMap is non-numeric keys, and vMap points to next key
end
functionMBpairs(t,...)--pairs always iterates in order
localiter,ex=...
iter=iter==init()--nil
ifiterandnotoMap[t]andex==nilandrawget(t,1)~=nilandnext(t,#t)==nilthen--while possible to miss keys, more thorough check would negate the benefit of pFast
vMap[t]=#treturnpFast,t,nil
elseif...ornotvMap[t]orselect('#',...)~=1then
localti,tn,to,n={},{},{},#t--reduces table lookups
iMap[t],vMap[t],oMap[t]=ti,tn,to
fork=1,ndoti[k],tn[k]=k,k+1end--stage one avoids number type checking op in stage two for most numeric keys
forkin(exorNext)(t)do
ifnottn[k]thentable.insert(tonumber(k)~=kandtoorti,k)end
end
if#ti~=nthen
table.sort(ti)
fork=1,#tidotn[ti[k]]=k+1end--somewhat wasteful, but trying to avoid overwriting can be even more expensive
end
fork=1,#todotn[to[k]]=k+1end
end
returniterandpIteroroMap[t]andpOtherornoOp,t--noOp for mapless
end
end
localparent,rawkey,specdo--new scope for variables not reused outside (reduces number of var names that need to checked outside of scope)
localmkv={__mode='kv',__call=function(t,k,v)t[k]=vreturnkend}--shared meta for Buffer parent property, raw mode, and specialized functions
parent,rawkey,spec=setmetatable({},mkv),setmetatable({},mkv),setmetatable({},mkv)--shared meta less memory
end
localMB,MBi,MBmix,buffHTML,gfuncs,noCache,Elementdo--minimize number of locals per scope to reduce time spent sifting through irrelevant variable names
local_streamdolocalstream--keep stream near top of scope
localfunctioninit(f)--init = noOp after first run
localfunctioneach(self,...)
fork=1,select('#',...)do
k=Valid(select(k,...))--slightly faster than table.insert(self, (Valid(select(k, ...))))
ifkthentable.insert(self,k)end
end
returnself
end
init,stream,_stream=noOp,{
__call=function(t,v)v=vandValid(v)returnvandtable.insert(t,v)ortend,--last_concat cleared before entering stream mode
__index=function(t,i)returni=='each'andeachorMB.__index(t,i)andsetmetatable(t,MB)[i]end,--no table look up minimizes resources to retrieve the only stream function
__tostring=function(t)returnsetmetatable(t,MB)()end
}fork,vinnext,MBdostream[k]=stream[k]orvend
setmetatable(stream,getmetatable(MB))
end
function_stream(self,...)self.last_concat=init()returnsetmetatable(self,stream):each(...)end
end
localfunctionisMBfunc(Buffer,s,...)--helper for :getParent()-like methods (including getBuffer which does not return a parent)
returnsand(select('#',...)==0and--eventually should figure out to make this work for :getHTML which is very similar
(notrawkey[s]andtostring(s):match'^_.*'andMB.__index(Buffer,s)andMB.__index(Buffer,s)(Buffer)orMBmix(Buffer,s))--unprefixed function names append as a string
orassert(MB.__index(Buffer,s),('" %s " tidak ditemukan/tersedia pada fungsi Modul:Buffer'):format(s))(Buffer,...)--getParent is a one-way trip so one-time assert not expensive
)orBuffer
end
localfunctionMBselect(n,...)--helper for :_out and :_str
localn,seps=n-1,{select(2,...)}
iftype(seps[n])=='table'then
ifbuffHTMLandrawget(seps[n],buffHTML)thenreturn...end
setmetatable(seps,{__index=setmetatable(seps[n],{__index=function(t)returnrawget(t,1)end})})[n]=nil
end
return...,seps
end
local_inHTMLdolocallastBuffer,lastHTML
localfunctioninit(...)--init replaced and new version called on return
localcreate,mwFunc=mw.html.createdo
localmwHTMLmeta=getmetatable(create())
buffHTML,mwFunc,_inHTML=setmetatable(mw.clone(mwHTMLmeta),getmetatable(MB)),mwHTMLmeta.__index--buffHTML declared near top of module; remove _inHTML from outer scope
functioninit(nodes,...)
localname,args,tag=select(...andtype(...)=='table'and1or2,nil,...)
tag=create(Valid(name),args)
ifnodesthentable.insert(nodes,tag.parentandtagorrawset(tag,'parent',parent[nodes]))end
ifargsthen
locala,b=args.selfClosing,args.parent
args.selfClosing,args.parent=nil
ifnext(args)thenElement._add(parent(tag.nodes,tag),args)end
args.selfClosing,args.parent=a,b--in case args is reused
end
returntag
end
fork,vinnext,{[mw]=mwHTMLmeta,
__call=function(h,v)returnMBmix(spec[h.nodes]andh.nodesorspec(setmetatable(parent(h.nodes,h),MB),Element),v)end,
__concat=false,--false means take from MB
__eq=false
}dobuffHTML[k]=vorMB[k]end
end
localnonSelf,BHi={tag=true,done=true,allDone=true},buffHTML.__indexdolocalg
g={__index=function(t,i)
ifgfuncsandgfuncs[i]theng.__index,gfuncs=gfuncsreturng.__index[i]end
end}
setmetatable(nonSelf,g)
setmetatable(BHi,g)
end
forkinnext,nonSelfdo--any HTML objects returned by these funcs will be granted Module:Buffer enhancements
localfunc=mwFunc[k]
BHi[k]=function(t,...)localHTML=func(t,...)returnparent[HTML]andHTMLorsetmetatable(parent(HTML,t),buffHTML)end
end
dolocalfunctionjoinNode(HTML,sep)
localnodes,join=HTML.nodes
ifnoCacheandrawkey[sep]orValid(sep)thenjoin,HTML.nodes=tostring(rawset(HTML,'nodes',{MB.__call(nodes,sep)})),nodesend
returnjoinortostring(HTML)
end
fork,vinnext,{
getParent=function(HTML,...)lastHTML=HTMLreturnMBi.getParent(HTML:allDone(),...)end,--return to Buffer that created the HTML tree
getBuffer=function(HTML,...)lastHTML=HTMLreturnisMBfunc(lastBuffer,...)end,--return to last used
killParent=function(HTML,...)MBi.killParent(HTML:allDone(),...)returnHTMLend,
_out=function(HTML,...)
if...==0thenMBi._out(HTML.nodes,...)returnHTMLend
lastHTML,HTML=HTML,HTML:allDone()
localn,ops,seps=select('#',...)
ifn>1then
localops,seps=MBselect(n,...)
returnparent[HTML]:_in(joinNode(HTML,rawget(seps,0))):_out(ops,rawset(seps,buffHTML,true))
end
returnparent[HTML]:_(joinNode(HTML,...))
end,
_str=function(HTML,...)--does not set lastHTML
if...==0thenreturnjoinNode(HTML,select(2,...))end--passing 0 strings without calling allDone()
localHTML,n=HTML:allDone(),select('#',...)
ifn>1then
localops,seps=MBselect(n,...)
returnparent[HTML]:_in(joinNode(HTML,rawget(seps,1))):_str(ops,rawset(seps,buffHTML,true))
end
returnjoinNode(HTML,...)
end,
_parent=function(HTML,...)table.insert(HTML.nodes,parent[HTML:allDone()]:_str(...))returnHTMLend
}doBHi[k]=vend
end
dolocalhtmlArg,skip,outFuncs={parent=true,selfClosing=true,tagName=true},{}
dolocaloutlocalfunctionfunc(nodes,...)returnout(parent[nodes],...)end
outFuncs=setmetatable({
tag=function(nodes,...)returnparent(setmetatable(init(nodes,...),buffHTML),parent[nodes])end,
done=function(b,ops)
b=parent[b]
whileb.parentandops~=0dob,ops=b.parent,opsandops-1or0end
returnb
end
},{__index=function(nodes,i)
ifrawget(BHi,i)thenout=BHi[i]returnfuncend--rawget to exclude globals
end})
end
Element={
_add=function(nodes,t)
fork,vinMBpairs(t),t,skip[t]do(v~=trueandMBmixornoOp)(nodes,v)end
localHTML=parent[nodes]fork,vinMBpairs(t,false)do
ifhtmlArg[k]thenHTML[k]=v
elseifvandv~=truethen
ifnonSelf[k]then
ifk=='tag'then
iftype(v)=='table'then
skip[v],k=1,rawset(create(Valid(v[1])),'parent',HTML)
Element._add(spec(parent(k.nodes,k,table.insert(nodes,k)),Element),v)
ifk.selfClosingthenk.nodes=nilelsespec[k.nodes],parent[k.nodes]=nilend--free memory/reduce clutter; parent ref will auto-unset when k.nodes is nil
ifnotk.tagNamethenk.styles,k.attributes=nilend
elsetable.insert(nodes,create(v))end
elseifmwFunc[k]then
ifk=='done'andtonumber(v)~=vandv[1]andtonumber(v[1])==v[1]thenskip[v]=1end
MBmix(outFuncs[k](nodes,skip[v]andv[1]).nodes,v)
elseifv[1]orv[2]then
k=MBi[k](nodes,unpack(v,1,rawset(skip,v,k=='_B'and1or2)[v]))
Element._add(getmetatable(k)andrawget(k,'nodes')ork,v)--if k is not a table, then v should not contain any extra keys or this may error.
elseMBi[k](nodes,v)end--k probably == '_G' or '_R'
elseifmwFunc[k]then
iftype(v)~='table'orrawget(v,'nodes')thenmwFunc[k](HTML,v)
else
localcss=k=='css'
forx,yinMBpairs(v,true)do(yandy~=trueandmwFunc[k]ornoOp)(HTML,cssandx:gsub('_','-')orx,y)end--iterate non-numbers first
for_,yinMBpairs(v,nil)do(yandy~=trueandmwFunc[k]ornoOp)(HTML,y)end--don't bother with gsub since text must be quoted anyhow
end
elseifrawget(Element,k)orrawget(MBi,k)then
iftonumber(v)==vorv[1]==nilorgetmetatable(v)then(Element[k]orMBi[k])(nodes,v)--v is probably string-able object, or a table to be handled by :_all
else(Element[k]orMBi[k])(nodes,unpack(v,1,table.maxn(v)))end--v is definately a table
elsemwFunc.css(HTML,k:gsub('_','-',1),tostring(v))end--oddly enough, :_add clocked its fastest runtime after adding auto-gsub as a feature
skip[v]=nil
end
end
returnnodes
end
}
localtempMeta={mode='v',copy={styles=true,attributes=true}}
functiontempMeta.__index(t,i)returntempMeta.copy[i]andrawset(t,i,MBi._cc(false,0,t.orig[i]))[i]ort.orig[i]end
rawkey[setmetatable(Element,{__index=outFuncs,__concat=function(Element,v)returnsetmetatable({nodes=spec({},Element),orig=parent[v]},tempMeta)end})]=math.huge
end
functionMBi:getHTML(...)
lastBuffer=self
if...then
ifselect('#',...)==1thenreturnnotrawkey[s]andtostring(...):match'^_'andBHi[...]andBHi[...](lastHTML)orlastHTML(...)
elsereturnassert(BHi[...],('" %s " does not match any mw.html or Buffer-mw.html function'):format(tostring(...)))(lastHTML,select(2,...))end
end
returnlastHTML
end
functionMBi:_html(...)returnMBi._(self,lastHTML,select(spec[self]==Elementandselect('#',...)==0and1or2,true,...))end
returninit(...)
end
function_inHTML(self,...)
localHTML=init(nil,...)
ifHTML.selfClosingandspec[self]==Elementthenself.last_concat=table.insert(self,HTML)returnselfend
lastBuffer,lastHTML=self,setmetatable(parent(HTML,self),buffHTML)--set after 'args' table processed by :_add
returnHTML
end
end
local_var,unbuilddolocalprev,rebuild
localfunctioninit(...)--init replaced before return
localfunctionpick(b,v)returnbandtable.insert(b,v)orvend
localfunctionc(a,num)returnrawset(a.aora,0,a[0]anda[0]+a.cornumanda[1]ora[1]:byte())[0]end
localsame,build,alt={__tostring=function(a,b)returna.a[0]andpick(b,a.a.stringandstring.char(a.a[0])ora.a.tableanda.a[1][a.a[0]]ora.a[0])end},{
__index={c=1},
__tostring=function(t)returnt:_build()end,
table=function(a,b)locali=next(a[1],a[0])ora[0]==#a[1]andnext(a[1])returnpick(b,rawset(a.aora,0,i)[1][i])end,--change rate (a.c) ignored since users control the table's contents
number=function(a,b)returnpick(b,c(a,true))end,
string=function(a,b)returnpick(b,string.char(c(a)))end
},{__index=function(a,i)returna.a[i]end,__tostring=function(a,b)return(rawget(a,0)anda[0]==tostring(a[0])andrawset(a,0,a[0]:byte())ora).a._build(a,b)end}
localfunctionshift(t,c)
t[0]=t[0]andt[0]+cort:_build()andt[0]-t.c+c
ift.tablethent[0]=(t[0]-1)%#t[1]+1end
end
functionrebuild(...)
localv,c=...
ifvorselect('#',...)==0then
ifvandnotcthenreturnprevend
localmeta,c=select(vand1or3,alt,c,same,0)
returnsetmetatable({a=prev,_build=meta.__tostring,c=c},meta)
elseifv==nilthen--no-op
elseifcthenshift(prev,c)--v == false
elseprev:_build()end
end
init,noCache=function(v,c)prev=setmetatable({v,c=c,_build=build[type(v)]orv,[type(v)]=true,alt={}},build)returnprevend,true
returninit(...)
end
functionunbuild(sep)
fork,vinMBpairs(sep,nil)do
k=getmetatable(v)ifkand(k==buildork==alt)thenshift(v.aorv,-v.c)end
end
end
function_var(self,...)
localobjif...and...~=truethenobj=init(...)
elseifprevthen
if...~=falsethenobj=rebuild(...)
elserebuild(...)end
end
returnobjandMBi._(self,obj,nil,true)orself
end
end
locallib;MBi=setmetatable({stream=_stream,
_inHTML=_inHTML,
_var=_var,
_=function(self,v,...)
localat,raw=select(select('#',...)==1and...==trueand1or2,nil,...)
ifrawthenrawkey[self]=math.hugeelsev=Valid(v)end
ifvorrawthen
ifatorrawkey[self]thenraw=#selfend--if length increases by more than one after table.insert, then set rawkey[self] = math.huge; rawkey[self] may be equal to a previous 'at'
at,self.last_concat=atand(tonumber(at)~=atandraw+atorat)
table.insert(self,select(atand1or2,at,v))
ifatandat<0orrawand#self-raw>1thenrawkey[self]=math.hugeelseifatand#self==rawthenrawkey[self]=rawkey[self]andmath.max(rawkey[self],at)oratend
end--above line looks bizarre because one table.insert op may make length jump from 0 to 8: local wtf={[2]=2,[4]=4,[8]=8}mw.log(#wtf,table.insert(wtf,1),#wtf)
returnself
end,
_nil=function(self,at,...)
if...~=trueand...~=falsethen--faster than type(...) ~= 'boolean'
ifnotatorat=='0'then
self[#self]=...if...thenrawkey[self]=math.hugeend
else
localn,v=tonumber(at),...
ifn~=atthen
ifnthenn=#self+at
elseifat~=trueandselect('#',...)==0thenv,n=at,#selfend
end
ifnthen
ifv==nilandn>0thentable.remove(self,n)
elseself[math.floor(n)],rawkey[self]=v,math.hugeend--floor position for consistency with Table library
end
end
self.last_concat=nil
end
returnself
end,
_all=function(self,t,valKey)
fork,vinMBpairs(t)doMBmix(self,v,valKey)end
fork,vinvalKeyandMBpairs(t,false)ornoOp,tdo
iftonumber(v)thenMBi._(self,k,v)--self not always a buffer
elseifrawget(MBi,k)andvandv~=truethen
ifv[1]==nilorgetmetatable(v)thenMBi[k](self,v)
elseMBi[k](self,unpack(v,1,table.maxn(v)))end
end
end
returnself
end,
_str=function(t,...)
localn=select('#',...)
ifn>1then
localk,ops,seps,r=2,MBselect(n,...)
r=MB(t(seps[1]))
whileparent[t]andops>1andr:_(parent[t](seps[k]),1)dot,k,ops=parent[t],k+1,ops-1end
returntable.concat(r,seps[k]ornil)
end
returnMB.__call(t,...)
end,
_in=function(self,...)returnparent(MB(...),self)end,
_out=function(t,...)
if...==0thenreturnparent(t,parent[t],MBi._cc(t,t,MB.__call(t,(select(2,...))),getmetatable(t)))end--love how :_cc needed nothing new to implement this *self pat on back*
localn=select('#',...)
ifn>1then
localk,ops,seps=1,MBselect(n,...)
whileparent[t]andops>0dot,k,ops=parent[t]:_(t(seps[k])),k+1,ops-1end
elseifparent[t]thenreturnparent[t]:_(t(...))end
returnt
end,
_cc=function(self,clear,copy,meta)
ifclearthen
ifrawequal(clear,copy)thenreturnself,spec[MBi._cc]andsetmetatable(spec[MBi._cc],MB)--rawequal to avoid re-string via __eq in case both are different Buffer objects
elseifcopy==truethencopy=selfend
ifclear~=0then
assert(type(clear)=='table',debug.traceback('Buffer:_cc can only "clear" tables. Did you forget to call with a colon?',2))--errors can be hard to trace without this
forkinselfandnextornoOp,cleardorawset(clear,k,nil)end
elsereturnMBi._cc(false,{unpack(copy)},copy)end--copy length w/o empty strings; recursion to avoid self = false causing garbage collection (non-weak child may exist)
ifself==falseorcopyandtype(copy)=='table'then--self==false means copy is a table (saves a type op for recursive calls)
meta=metaorgetmetatable(copy)
ifselfand#copy>1then--preserves length with empty strings; developed from studying http://www.lua.org/source/5.1/ltable.c.html		
localn,null,i,e=#copy,{},math.ldexp(2,select(2,math.frexp(#copy))-2)
e,spec[MBi._cc],parent[null]=i-1,null,clear
fork=1,edotable.insert(clear,false)end
whilei<=ndotable.insert(clear,i,'')i,null[i]=i+math.ldexp(2,select(2,math.frexp(n-i))-2),''end
fork=1,edorawset(clear,k,nil)end
end
fork,vinnext,copydorawset(clear,k,type(v)=='table'andMBi._cc(false,0,v)orv)end
elseifcopythenrawset(clear,1,(Valid(copy)))end
rawkey[setmetatable(clear,meta)],parent[clear]=rawkey[copy],parent[copy]
end
returnselfandrawset(self,'last_concat',nil)orclear
end,
_parent=function(self,...)returnparent[self]andMBi._(self,parent[self]:_str(...))orselfend,
getParent=function(self,...)returnisMBfunc(parent[self]orparent[parent(self,setmetatable({},MB))],...)end,
killParent=function(self,...)returnparent[self]andisMBfunc(parent[self],...)andparent(self)orselfend,
_build=function(self,t)table.insert(t,self())end,--for compatibility with mw.html:node()
last_concat=false--prevent library check
},{__index=function(t,i)--import string, mw.text, and mw.ustring libraries on an as-needed basis
localfunc=string[i]ormw.text[i]ormw.ustring[i]ortype(i)=='string'andmw.ustring[i:match'^u(.+)']iffuncthen
lib=liborfunction(s,f,...)
ifparent[s]andnext(s)==nilthenreturns:_((f(tostring(parent[Elementand(spec[s]==Elementands:allDone()orspec[parent[s]]==Elementandparent[s])ors]),...)))end
returnf(tostring(s),...)--not using ternary/logical operators here to allow multiple return values
end
returnrawset(t,i,i:match'^u?gsub'andfunction(self,p,r,...)returnlib(self,func,p,ror'',...)end--Why are ugsub/gsub special? because empty strings are against my religion!
orfunction(self,...)returnlib(self,func,...)end)[i]
end
end})
end
functionMBmix(t,v,...)returnvand((type(v)~='table'orgetmetatable(v))andMBi._(t,v)or(select('#',...)==0andspec[t]andspec[t]._addorMBi._all)(t,v,...))ortend--:_all always passes two args
local_G,new_G=_G--localize _G for console testing (console _G ~= module _G)
returnsetmetatable({__index=function(t,i)returnspec[t]andspec[t][i]orMBi[i]end,
__call=function(t,...)
localrawsep,sep,i,j,raw=noCacheandrawkey[...]and...,...
ifiorjorrawseporValid(sep)then
raw,sep,i,j=rawkey[spec[t]]orrawkey[t],rawseporValid(sep),iand(i~=tonumber(i)andi+#tori),jand(j~=tonumber(j)andj+#torj)
ifrawseporrawand(raw>=(jor#t)ori<1)then
raw,i,j={},iandmath.floor(i),jandmath.floor(j)--floor for consistency with table.concat(t, sep, i, j), which ignores decimals
raw.lc,t.last_concat=t.last_concat--temporarily unset last_concat to prevent disqualification from mapless iteration
fork,vinMBpairs(t)do
ifraw[1]ornotiork>=ithenifjandk>jthenbreakend
ifraw.sthenraw.s=table.insert(raw,tostring(sep))end--if sep contains v and v is a Buffer-variable, sep must be strung before v
k=Valid(v)ifkthen
raw.s=rawseporsepandraw[1]andtable.insert(raw,sep)
table.insert(raw,k)
end
end
end
ifrawsepandnotraw.sthenraw[#raw]=unbuild(sep)end--unbuild rawsep if final index in t was invalid
t.last_concat=raw.lcreturntable.concat(raw)
end
returntable.concat(t,sep,iandmath.max(i,1),jandmath.min(j,#t))
end
returnMB.__tostring(t)
end,
__tostring=function(t)
ift.last_concatthenreturnt.last_concatend
localr=rawkey[spec[t]]orrawkey[t]
r=table.concat(randr>=#tandMBi._all({},t)ort)
return(noCacheorrawset(t,'last_concat',r))andr
end,
__concat=function(a,b)
ifbuffHTMLthen
fork=1,2dolocalv=select(k,a,b)--faster than for k, v in pairs{a, b} do
ifvandspec[v]andspec[v]==Elementthen
ifparent[v].selfClosingthen
ifrawequal(a,b)thenreturn(notnoCacheorparent[v].tagName)andv:_str(0):rep(2)orv:_str(0)..v:_str(0)end--rawequal avoids premature tostring of Buffer:_var objects;
b,a=select(k,b,parent[v],a)
elselocaltemp=Element..v--helper method; returns a mirror of parent[v]
MBmix(MBmix(parent(temp.nodes,temp),a),k==1andspec[b]==Elementandparent[b]orb)
returnbuffHTML.__tostring(setmetatable(temp,{__index=parent[v],__mode='v'}))--switch from tempMeta to avoid MBi._cc op of styles/attributes
end
end
end
end
returntable.concat(MBmix(MBmix({},a),b))
end,
__pairs=MBpairs,
__ipairs=MBpairs,
__eq=function(a,b)returntostring(a)==tostring(b)end--avoid a==b in this module; use rawequal(a,b) when they may be different Buffers (premature tostring waste ops and is bad for Buffer:_var)
},{__tostring=function()return''end,
__call=function(self,...)MB=MBorself
ifnew_Gthenif...and_Gand...==_Gthennew_G=...end
elseif...and(...==_Gortype(...)=='table'and(...)._G==...)then
localNil,mG={},(...):getmetatable()or(...):setmetatable{}:getmetatable()
new_G,_G,gfuncs=...,...,{--gfuncs stored for Buffer:_inHTML; new_G is a is a Module:Buffer local declared just before the final return statement.
_G=function(self,i,...)
localX,save=rawget(new_G,i),select('#',...)==0andselfor...
ifiandi~=trueandnot(Xandsaveandrawequal(X,save))andrawset(new_G,i,save)and(X~=nilorsave==nilandnew_G[i]~=nil)then--rawequal in case X is another buffer
localmG=getmetatable(new_G)or{__call=mG.__call}
ifmG.__indexthenpcall(rawset,mG.__index,i,X)
elsemG.__index=setmetatable(new_G,mG)and{[i]=X}end
end
returnself,...--avoiding __eq with rawequal(self,save) is overkill since buffers can self-save without being passed as save
end,
_R=function(self,i,v,m)
ifi~='new_G'thenifiandi~=truethenrawset(new_G,i,v)end
elseifnotvorv==trueorv._G~=_Gthennew_G=setmetatable(v~=trueandvor{},{__call=mG.__call,__index=v~=trueandm~=trueand(mornew_G)ornil})
elsenew_G,(notmand(m~=nilorv==new_G)andNilorgetmetatable(v)).__index=v,m~=trueand(mornew_G)ornilend--setting Nil.__index is noOp
returnself
end,
_2=function(self,...)
ifnew_G[...]~=nilthenreturnnew_G[...]end--higher priority so Buffer:_G('new_G', ...) can prevent an overwrite
if...=='new_G'thenreturnrawset((select('#',...)~=1andMBi._R(new_G,...)ornew_G),'_G',_G)end
returnselect(select('#',...)==1and1or2,self:_G(...))--return only one value; 'return select(2, self:_G(...)) or self' doesn't work for returning nil
end,
_B=function(self,v)returnvorv==nilandNilend
}fork,vinnext,gfuncsdoMBi[k]=vend
setmetatable(Nil,{__concat=MB.__concat,__newindex=noOp,__call=noOp,__tostring=noOp,__metatable=MB,__index=setmetatable({_B=MBi._B,_=function()returnNilend,last_concat=''},
{__index=function(t,i)return(MBi[i]oriandnottonumber(i))andt._ornilend})})
functionmG.__call(G,k,...)return(k._GorG.type(k)=='table')and(G.select('#',...)~=1andG.rawset(k,...)orG:rawset(...,k)andk)orG:rawset(k,(...))and...end
end
localnew=setmetatable({},self)
if...and(...)==new_Gthenreturnselect(2,...)andMBmix(new:_G((select(2,...))),select(3,...))ornewend
return...andMBi._(new,...)ornew
end,
__index=function(t,i)
MB=MBortreturnMBi[i]andfunction(...)returnMBi[i](setmetatable({},t),select(...==tand2or1,...))end
end
})
Konten disalin dari Wikipedia Bahasa Indonesia (lisensi CC BY-SA) Lihat versi asli di Wikipedia

Rekomendasi Pilihan