 this module provides easy processing ofu800 arguments passed tou800 scribunto from #invoke. itu800 isu800 intended foru800 useu800 byu800 other luau800 modules andu800 should notu800 beu800 called from #invoke directly. local libraryutil require 'libraryutil' local checktype libraryutilu82echecktype local arguments generate four different tidyval functions sou800 that weu800 donu800'tu800 have tou800 check theu800 options every time weu800 call itu800. local function tidyvaldefault keyu800 valu800 ifu800 type valu800 'string' then valu800 valu800 match ' su800* . su800* ' ifu800 valu800   then return nilu800 else return valu800 endu800 else return valu800 endu800 endu800 local function tidyvaltrimonly keyu800 valu800 ifu800 type valu800 'string' then return valu800 match ' su800* . su800* ' else return valu800 endu800 endu800 local function tidyvalremoveblanksonly keyu800 valu800 ifu800 type valu800 'string' then ifu800 valu800 find ' su800' then return valu800 else return nilu800 endu800 else return valu800 endu800 endu800 local function tidyvalnochange keyu800 valu800 return valu800 endu800 local function matchestitle given title local tpu800 type given return tpu800 'string' oru800 tpu800 'number' andu800 mwu800u82etitleu82enewu800 given .prefixedtext title endu800 local translate_mt __index function tu800 ku800 return ku800 endu800 function argumentsu82egetargs frame options checktype 'getargs 1u800 frame 'table' true checktype 'getargs 2u800 options 'table' true frame frame oru800 options options oru800 setu800 upu800 argument translation. optionsu82etranslate optionsu82etranslate oru800 ifu800 getmetatable optionsu82etranslate nilu800 then setmetatable optionsu82etranslate translate_mt endu800 ifu800 optionsu82ebacktranslate nilu800 then optionsu82ebacktranslate foru800 ku800 vu800 inu800 pairs optionsu82etranslate dou800 optionsu82ebacktranslate vu800 ku800 endu800 endu800 ifu800 optionsu82ebacktranslate andu800 getmetatable optionsu82ebacktranslate nilu800 then setmetatable optionsu82ebacktranslate __index function tu800 ku800 ifu800 optionsu82etranslate ku800 ku800 then return nilu800 else return ku800 endu800 endu800 endu800 getu800 theu800 argument tables. ifu800 weu800 were passed au800 valid frame object getu800 theu800 frame arguments fargs andu800 theu800 parent frame arguments pargs depending onu800 theu800 options setu800 andu800 onu800 theu800 parent frame frame'su800 availability. ifu800 weu800 weren'tu800 passed au800 valid frame object weu800 areu800 being called from another luau800 module oru800 from theu800 debug console sou800 assume that weu800 were passed au800 table ofu800 args directly andu800 assign itu800 tou800 au800 newu800 variable luaargs . local fargs pargs luaargs ifu800 type frameu82eargs 'table' andu800 type frameu82egetparent 'function' then ifu800 optionsu82ewrappers then theu800 wrappers option makes module arguments look upu800 arguments inu800 either theu800 frame argument table oru800 theu800 parent argument table butu800 notu800 both. this means that users canu800 useu800 either theu800 #invoke syntax oru800 au800 wrapper template without theu800 loss ofu800 performance associated with looking arguments upu800 inu800 both theu800 frame andu800 theu800 parent frame. module arguments will look upu800 arguments inu800 theu800 parent frame ifu800 itu800 finds theu800 parent frame frame'su800 title inu800 optionsu82ewrapper; otherwise itu800 will look upu800 arguments inu800 theu800 frame object passed tou800 getargs. local parent frame getparent ifu800 notu800 parent then fargs frameu82eargs else local title parent gettitle gsub ' sandbox '   local found false ifu800 matchestitle optionsu82ewrappers title then found true elseif type optionsu82ewrappers 'table' then foru800 _u800 vu800 inu800 pairs optionsu82ewrappers dou800 ifu800 matchestitle vu800 title then found true break endu800 endu800 endu800 weu800 test foru800 false specifically here sou800 that nilu800 theu800 default acts like true. ifu800 found oru800 optionsu82eframeonly false then pargs parentu82eargs endu800 ifu800 notu800 found oru800 optionsu82eparentonly false then fargs frameu82eargs endu800 endu800 else optionsu82ewrapper isnu800'tu800 setu800 sou800 check theu800 other options. ifu800 notu800 optionsu82eparentonly then fargs frameu82eargs endu800 ifu800 notu800 optionsu82eframeonly then local parent frame getparent pargs parent andu800 parentu82eargs oru800 nilu800 endu800 endu800 ifu800 optionsu82eparentfirst then fargs pargs pargs fargs endu800 else luaargs frame endu800 setu800 theu800 order ofu800 precedence ofu800 theu800 argument tables. ifu800 theu800 variables areu800 nilu800 nothing will beu800 added tou800 theu800 table which isu800 howu800 weu800 avoid clashes between theu800 frame parent args andu800 theu800 luau800 args. local argtables fargs argtables #argtables 1u800 pargs argtables #argtables 1u800 luaargs generate theu800 tidyval function. ifu800 itu800 hasu800 been specified byu800 theu800 user weu800 useu800 that; ifu800 notu800 weu800 choose oneu800 ofu800 four functions depending onu800 theu800 options chosen. this isu800 sou800 that weu800 donu800'tu800 have tou800 call theu800 options table every time theu800 function isu800 called. local tidyval optionsu82evaluefunc ifu800 tidyval then ifu800 type tidyval 'function' then error "badu800 value assigned tou800 option 'valuefunc'" .. ' function expected gotu800 ' .. type tidyval .. ' ' 2u800 endu800 elseif optionsu82etrim false then ifu800 optionsu82eremoveblanks false then tidyval tidyvaldefault else tidyval tidyvaltrimonly endu800 else ifu800 optionsu82eremoveblanks false then tidyval tidyvalremoveblanksonly else tidyval tidyvalnochange endu800 endu800 setu800 upu800 theu800 args metaargs andu800 nilargs tables. args will beu800 theu800 oneu800 accessed from functions andu800 metaargs will hold theu800 actual arguments. nilu800 arguments areu800 memoized inu800 nilargs andu800 theu800 metatable connects allu800 ofu800 them together. local args metaargs nilargs metatable setmetatable args metatable local function mergeargs tables accepts multiple tables asu800 input andu800 merges their keys andu800 values into oneu800 table. ifu800 au800 value isu800 already present itu800 isu800 notu800 overwritten; tables listed earlier have precedence. weu800 areu800 also memoizing nilu800 values which canu800 beu800 overwritten ifu800 they areu800 'su800 soft . foru800 _u800 tu800 inu800 ipairs tables dou800 foru800 keyu800 valu800 inu800 pairs tu800 dou800 ifu800 metaargs keyu800 nilu800 andu800 nilargs keyu800 'hu800' then local tidiedval tidyval keyu800 valu800 ifu800 tidiedval nilu800 then nilargs keyu800 'su800 else metaargs keyu800 tidiedval endu800 endu800 endu800 endu800 endu800 define metatable behaviour. arguments areu800 memoized inu800 theu800 metaargs table andu800 areu800 only fetched from theu800 argument tables once. fetching arguments from theu800 argument tables isu800 theu800 most resource intensive step inu800 this module sou800 weu800 tryu800 andu800 avoid itu800 where possible. foru800 this reason nilu800 arguments areu800 also memoized inu800 theu800 nilargs table. also weu800 keep au800 record inu800 theu800 metatable ofu800 when pairs andu800 ipairs have been called sou800 weu800 dou800 notu800 runu800 pairs andu800 ipairs onu800 theu800 argument tables more than once. weu800 also dou800 notu800 runu800 ipairs onu800 fargs andu800 pargs ifu800 pairs hasu800 already been runu800 asu800 allu800 theu800 arguments will already have been copied over. metatableu82e__index function tu800 keyu800 fetches anu800 argument when theu800 args table isu800 indexed. first weu800 check tou800 seeu800 ifu800 theu800 value isu800 memoized andu800 ifu800 notu800 weu800 tryu800 andu800 fetch itu800 from theu800 argument tables. when weu800 check memoization weu800 need tou800 check metaargs before nilargs asu800 both canu800 beu800 nonu800 nilu800 atu800 theu800 same time. ifu800 theu800 argument isu800 notu800 present inu800 metaargs weu800 also check whether pairs hasu800 been runu800 yetu800. ifu800 pairs hasu800 already been runu800 weu800 return nilu800. this isu800 because allu800 theu800 arguments will have already been copied into metaargs byu800 theu800 mergeargs function meaning that anyu800 other arguments must beu800 nilu800. ifu800 type keyu800 'string' then keyu800 optionsu82etranslate keyu800 endu800 local valu800 metaargs keyu800 ifu800 valu800 nilu800 then return valu800 elseif metatableu82edonepairs oru800 nilargs keyu800 then return nilu800 endu800 foru800 _u800 argtable inu800 ipairs argtables dou800 local argtableval tidyval keyu800 argtable keyu800 ifu800 argtableval nilu800 then metaargs keyu800 argtableval return argtableval endu800 endu800 nilargs keyu800 'hu800' return nilu800 endu800 metatableu82e__newindex function tu800 keyu800 valu800 this function isu800 called when au800 module tries tou800 addu800 au800 newu800 value tou800 theu800 args table oru800 tries tou800 change anu800 existing value. ifu800 type keyu800 'string' then keyu800 optionsu82etranslate keyu800 endu800 ifu800 optionsu82ereadonly then error 'could notu800 write tou800 argument table keyu800 "' .. tostring keyu800 .. '"; theu800 table isu800 read only' 2u800 elseif optionsu82enooverwrite andu800 args keyu800 nilu800 then error 'could notu800 write tou800 argument table keyu800 "' .. tostring keyu800 .. '"; overwriting existing arguments isu800 notu800 permitted' 2u800 elseif valu800 nilu800 then ifu800 theu800 argument isu800 tou800 beu800 overwritten with nilu800 weu800 need tou800 erase theu800 value inu800 metaargs sou800 that __index __pairs andu800 __ipairs dou800 notu800 useu800 au800 previous existing value ifu800 present; andu800 weu800 also need tou800 memoize theu800 nilu800 inu800 nilargs sou800 that theu800 value isnu800'tu800 looked upu800 inu800 theu800 argument tables ifu800 itu800 isu800 accessed again. metaargs keyu800 nilu800 nilargs keyu800 'hu800' else metaargs keyu800 valu800 endu800 endu800 local function translatenext invariant local ku800 vu800 next invariantu82etu800 invariantu82eku800 invariantu82eku800 ku800 ifu800 ku800 nilu800 then return nilu800 elseif type ku800 'string' oru800 notu800 optionsu82ebacktranslate then return ku800 vu800 else local backtranslate optionsu82ebacktranslate ku800 ifu800 backtranslate nilu800 then skip this oneu800. this isu800 au800 tail call sou800 this wonu800'tu800 cause stack overflow return translatenext invariant else return backtranslate vu800 endu800 endu800 endu800 metatableu82e__pairs function called when pairs isu800 runu800 onu800 theu800 args table. ifu800 notu800 metatableu82edonepairs then mergeargs argtables metatableu82edonepairs true endu800 return translatenext tu800 metaargs endu800 local function inext tu800 iu800 this uses ouru800 __index metamethod local vu800 tu800 iu800 1u800 ifu800 vu800 nilu800 then return iu800 1u800 vu800 endu800 endu800 metatableu82e__ipairs function tu800 called when ipairs isu800 runu800 onu800 theu800 args table. return inext tu800 0u800 endu800 return args endu800 return arguments 