<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.earthmc.net/index.php?action=history&amp;feed=atom&amp;title=Module%3ALibU</id>
	<title>Module:LibU - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.earthmc.net/index.php?action=history&amp;feed=atom&amp;title=Module%3ALibU"/>
	<link rel="alternate" type="text/html" href="https://wiki.earthmc.net/index.php?title=Module:LibU&amp;action=history"/>
	<updated>2026-10-27T19:06:53Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.46.0</generator>
	<entry>
		<id>https://wiki.earthmc.net/index.php?title=Module:LibU&amp;diff=234627&amp;oldid=prev</id>
		<title>515797455988850689: Created page with &quot;--------------------------------------------------------------------------------- -- LibU: The non-obstrusive version of LibraryUtil -- From MediaWiki source file -- and https://hypixel-skyblock.fandom.com/wiki/Module:LibraryUtil --  -- On import, this script does not expose all functions to the global table. -- List of functions: -- function: getCodeLocation(level) -- function: makeArgNumber(val) -- function: getParentName(level) [alias: getStackName] -- function: typeM...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.earthmc.net/index.php?title=Module:LibU&amp;diff=234627&amp;oldid=prev"/>
		<updated>2023-11-25T08:24:31Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;--------------------------------------------------------------------------------- -- LibU: The non-obstrusive version of LibraryUtil -- From MediaWiki source file -- and https://hypixel-skyblock.fandom.com/wiki/Module:LibraryUtil --  -- On import, this script does not expose all functions to the global table. -- List of functions: -- function: getCodeLocation(level) -- function: makeArgNumber(val) -- function: getParentName(level) [alias: getStackName] -- function: typeM...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;---------------------------------------------------------------------------------&lt;br /&gt;
-- LibU: The non-obstrusive version of LibraryUtil&lt;br /&gt;
-- From MediaWiki source file&lt;br /&gt;
-- and https://hypixel-skyblock.fandom.com/wiki/Module:LibraryUtil&lt;br /&gt;
-- &lt;br /&gt;
-- On import, this script does not expose all functions to the global table.&lt;br /&gt;
-- List of functions:&lt;br /&gt;
-- function: getCodeLocation(level)&lt;br /&gt;
-- function: makeArgNumber(val)&lt;br /&gt;
-- function: getParentName(level) [alias: getStackName]&lt;br /&gt;
-- function: typeMatches(valType, val, types, nilOk, numberOk)&lt;br /&gt;
-- function: generateMsg(name, index, msg, types)&lt;br /&gt;
-- function: validateTypes(types)&lt;br /&gt;
-- function: checkType(name?: string, pos: number, value: any, types: string|table, nilOk?: boolean)&lt;br /&gt;
-- function: checkType(name: &amp;#039;no value&amp;#039;, pos: number, types?: string|table, level?: number)&lt;br /&gt;
-- function: checkTypeLight(name, argIdx, arg, expectTypes, nilOk)&lt;br /&gt;
-- function: checkArgs(types: table&amp;lt;table&amp;lt;string&amp;gt; | string&amp;gt;, ...arguments?: any) [alias: checkTypeArgs]&lt;br /&gt;
-- function: checkTypeMulti(t, types)&lt;br /&gt;
-- function: alertDeprecation(name: string, useInstead?: string, level?: number)&lt;br /&gt;
-- function: forEachArgs(types: string, ...arguments?: string)&lt;br /&gt;
-- function: makeCheckSelfFunction(libraryName: string, varName: string, selfObj?: table, selfObjDesc?: string)&lt;br /&gt;
-- function: formattedError(formatStr?: string, level?: number, ...substitions?: string | number)&lt;br /&gt;
-- function: formattedAssert(v?: any, formatStr?: string, level?: number, ...substitions?: string | number) [alias: assertTrue]&lt;br /&gt;
-- function: assertFalse(v, formatStr, level, ...)&lt;br /&gt;
-- function: existsWithoutWanted(title: string)&lt;br /&gt;
-- function: inexpensivePageExists(title: string) [alias: pageExists]&lt;br /&gt;
-- function: pipeline(...)&lt;br /&gt;
-- function: bind(targetFn: function, ...items?: any)&lt;br /&gt;
-- &lt;br /&gt;
-- The following methods are modified to a custom one:&lt;br /&gt;
-- function: mw.log(...)&lt;br /&gt;
-- function: mw.logObject(...)&lt;br /&gt;
-- function: mw.oldLog(...)&lt;br /&gt;
-- function: mw.oldLogObject(...)&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local libraryUtil = {}&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- Find line/module name via `debug.stacktrace()` for debugging&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function getCodeLocation(level)&lt;br /&gt;
	local trace = debug.traceback(&amp;#039;&amp;#039;, (level or 1) + 2)&lt;br /&gt;
	return ((trace:gsub(&amp;#039;\nstack traceback:\n&amp;#039;, &amp;#039;&amp;#039;):match(&amp;#039;^\t([^\n&amp;lt;&amp;gt;]+):&amp;#039;)..&amp;#039;:&amp;#039;):gsub(&amp;#039;\t?%(tail call%): ?%?&amp;#039;, &amp;#039;&amp;#039;))&lt;br /&gt;
end&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- Feature: Rewritten Log Methods&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- Store Old Log Methods as `mw.oldLog` and `mw.oldLogObject`&lt;br /&gt;
mw.oldLog = mw.log&lt;br /&gt;
local oldLog = mw.oldLog&lt;br /&gt;
mw.oldLogObject = mw.logObject&lt;br /&gt;
local oldLogObject = mw.oldLogObject&lt;br /&gt;
-- Modify mw.log to display code location&lt;br /&gt;
local logLevel = 2&lt;br /&gt;
mw.log = function(...)&lt;br /&gt;
	local function newLog(...)&lt;br /&gt;
		return oldLog(getCodeLocation(logLevel), mw.allToString(...))&lt;br /&gt;
	end&lt;br /&gt;
	mw.log = newLog&lt;br /&gt;
	newLog(...)&lt;br /&gt;
	logLevel = 1&lt;br /&gt;
end&lt;br /&gt;
-- Modify mw.logObject to display code location&lt;br /&gt;
-- Note: This takes away the &amp;quot;prefix&amp;quot; feature from `mw.logObject( object, prefix )`&lt;br /&gt;
local logObjectLevel = 2&lt;br /&gt;
mw.logObject = function(...)&lt;br /&gt;
	local function newLog(...)&lt;br /&gt;
		return oldLog(getCodeLocation(logObjectLevel), mw.dumpObject(...))&lt;br /&gt;
	end&lt;br /&gt;
	mw.logObject = newLog&lt;br /&gt;
	newLog(...)&lt;br /&gt;
	logObjectLevel = 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- Utility Functions&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- Create an argument number/name&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function makeArgNumber(val)&lt;br /&gt;
	return table.concat{ type(val) == &amp;#039;number&amp;#039; and &amp;#039;#&amp;#039; or &amp;#039;\&amp;#039;&amp;#039;, val, type(val) ~= &amp;quot;number&amp;quot; and &amp;#039;\&amp;#039;&amp;#039; or &amp;#039;&amp;#039; }&lt;br /&gt;
end&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- Get the namae of a function based off of a stack level using `debug.stracktrace()`&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function getParentName(level)&lt;br /&gt;
	level = (level or 0) + 3&lt;br /&gt;
	local stack = debug.traceback(&amp;#039;&amp;#039;, level) or &amp;#039;&amp;#039;&lt;br /&gt;
	&lt;br /&gt;
	stack = (stack:gsub(&amp;#039;\nstack traceback:\n&amp;#039;, &amp;#039;&amp;#039;)&lt;br /&gt;
		:match(&amp;#039;in function ([^\n]+)&amp;#039;) or &amp;#039;&amp;#039;)&lt;br /&gt;
		:gsub(&amp;#039;^\&amp;#039;(.-)\&amp;#039;$&amp;#039;, &amp;#039;%1&amp;#039;)&lt;br /&gt;
	&lt;br /&gt;
	stack = (stack:match(&amp;#039;[&amp;lt;&amp;gt;:]&amp;#039;) or stack == &amp;#039;&amp;#039;) and &amp;#039;?&amp;#039; or stack&lt;br /&gt;
	&lt;br /&gt;
	return stack&lt;br /&gt;
end&lt;br /&gt;
getStackName = getParentName&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- Utility function to find the index of a value in a table&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function indexOf(t, value)&lt;br /&gt;
	if type(t) ~= &amp;#039;table&amp;#039; then return -1 end&lt;br /&gt;
	&lt;br /&gt;
	local i = 1&lt;br /&gt;
	while t[i] do&lt;br /&gt;
		if t[i] == value then return i end&lt;br /&gt;
		i = i+1&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return -1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- Feature: `checkArgs()` and `checkType()`&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- Helper function for `checkType()` to check of a set of given types matches a value&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function typeMatches(valType, val, types, nilOk, numberOk)&lt;br /&gt;
	local tpTypes = type(types)&lt;br /&gt;
	local tn = valType == &amp;#039;number&amp;#039; and val or tonumber(val)&lt;br /&gt;
	local isStringNumber = not not (tn and (types == &amp;#039;string&amp;#039; or indexOf(types, &amp;#039;string&amp;#039;) ~= -1))&lt;br /&gt;
	&lt;br /&gt;
	if tpTypes == &amp;#039;table&amp;#039; and #types == 1 then types = types[1]; tpTypes = &amp;#039;string&amp;#039; end&lt;br /&gt;
	&lt;br /&gt;
	if valType == &amp;#039;nil&amp;#039; and nilOk then&lt;br /&gt;
		return true&lt;br /&gt;
	elseif val == nil and types == nil then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if tpTypes == &amp;#039;string&amp;#039; then&lt;br /&gt;
		return (valType == types or (types == &amp;#039;number&amp;#039; and not not tn)) or (isStringNumber and numberOk)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	for i = 1, #types, 1 do&lt;br /&gt;
		local v = types[i]&lt;br /&gt;
		&lt;br /&gt;
		if v == valType or (v == &amp;#039;number&amp;#039; and tn) or isStringNumber then&lt;br /&gt;
			return true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- Format a list of types in an error message for `checkType()` and it&amp;#039;s related functions&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function generateTypes(types)&lt;br /&gt;
	if type(types) == &amp;quot;string&amp;quot; then &lt;br /&gt;
		return types&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local n = #types&lt;br /&gt;
	if n == 1 then&lt;br /&gt;
		return types[1]&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return table.concat(types, &amp;#039;/&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- Format an error message for `checkType()` and related functions&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function generateMsg(name, index, msg, types)&lt;br /&gt;
	local msg = string.format(&amp;quot;bad argument %s to &amp;#039;%s&amp;#039; (%s)&amp;quot;,&lt;br /&gt;
		makeArgNumber(index),&lt;br /&gt;
		name,&lt;br /&gt;
		types and (generateTypes(types)..&amp;#039; expected, got &amp;#039;..msg) or msg&lt;br /&gt;
	);&lt;br /&gt;
	return msg&lt;br /&gt;
end&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- Data for `checkType()` &lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local validTypes = {&lt;br /&gt;
	[&amp;#039;string&amp;#039;] = true,&lt;br /&gt;
	[&amp;#039;number&amp;#039;] = true,&lt;br /&gt;
	[&amp;#039;nil&amp;#039;] = true,&lt;br /&gt;
	[&amp;#039;table&amp;#039;] = true,&lt;br /&gt;
	[&amp;#039;boolean&amp;#039;] = true,&lt;br /&gt;
	[&amp;#039;function&amp;#039;] = true,&lt;br /&gt;
	[&amp;#039;any&amp;#039;] = true,&lt;br /&gt;
}&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- Check if a set of given types is valid&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function validateTypes(types)&lt;br /&gt;
	local tp = type(types)&lt;br /&gt;
	local len = tp == &amp;#039;table&amp;#039; and #types&lt;br /&gt;
	&lt;br /&gt;
	if not types &lt;br /&gt;
	or (tp ~= &amp;quot;table&amp;quot; and tp ~= &amp;quot;string&amp;quot;)&lt;br /&gt;
	or types == &amp;quot;&amp;quot; &lt;br /&gt;
	or (tp == &amp;#039;table&amp;#039; and len &amp;gt; 7) then &lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if (tp == &amp;#039;string&amp;#039; or tp == &amp;#039;table&amp;#039;) and len == 0 then return true end&lt;br /&gt;
	if len == 1 and tp == &amp;#039;table&amp;#039; then types = types[1]; tp = &amp;#039;string&amp;#039; end&lt;br /&gt;
	&lt;br /&gt;
	if tp == &amp;quot;string&amp;quot; then&lt;br /&gt;
		return not not validTypes[types]&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	for i = 1, len, 1 do&lt;br /&gt;
		if not validTypes[types[i]] then&lt;br /&gt;
			return false&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return true&lt;br /&gt;
end&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- function: checkType&lt;br /&gt;
--&lt;br /&gt;
-- modes:&lt;br /&gt;
--	type checker: checkType(name?: string, pos: number, value: any, types: string|table, nilOk?: boolean)&lt;br /&gt;
--	no value error: checkType(name: &amp;#039;no value&amp;#039;, pos: number, types?: string|table, level?: number)&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Options to types:&lt;br /&gt;
--	*name: Changes the function to the value provided&lt;br /&gt;
--	*base: Makes the value provided have the correct number base&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function checkType(name, argIdx, arg, expectTypes, nilOk)&lt;br /&gt;
	local isConstructor, tpName&lt;br /&gt;
&lt;br /&gt;
	if name == true then&lt;br /&gt;
		name = nil&lt;br /&gt;
		isConstructor = true&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	tpName = type(name)&lt;br /&gt;
	local tpTypes = type(expectTypes)&lt;br /&gt;
	local tpArg = type(arg);&lt;br /&gt;
	&lt;br /&gt;
	-- Argument overloads&lt;br /&gt;
	if (tpName == &amp;quot;number&amp;quot; and (tpArg == &amp;#039;table&amp;#039; or tpArg == &amp;#039;string&amp;#039;) and tpTypes ~= &amp;#039;string&amp;#039; and tpTypes ~= &amp;#039;table&amp;#039;) or (name == nil and argIdx == nil) then&lt;br /&gt;
		nilOk = expectTypes&lt;br /&gt;
		expectTypes = arg or &amp;#039;string&amp;#039;&lt;br /&gt;
		arg = argIdx or nil&lt;br /&gt;
		argIdx = name or 1&lt;br /&gt;
		name = nil&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	name = name or expectTypes.name&lt;br /&gt;
	local t = {}&lt;br /&gt;
	local tpArg = type(arg)&lt;br /&gt;
	t.checkType = error&lt;br /&gt;
	&lt;br /&gt;
	-- Check if types match and if there is an error&lt;br /&gt;
	local level = isConstructor and 1 or (tpName == &amp;quot;number&amp;quot; and name or 0)&lt;br /&gt;
	local numOk = expectTypes.numberOk or expectTypes.numOk&lt;br /&gt;
	local matches = name ~= &amp;#039;no value&amp;#039; and typeMatches(tpArg, arg, expectTypes, nilOk, (expectTypes and numOk))&lt;br /&gt;
	local isError = (tpName == &amp;quot;string&amp;quot; and name ~= &amp;#039;no value&amp;#039;) or not matches&lt;br /&gt;
	&lt;br /&gt;
	local fName&lt;br /&gt;
	local tn&lt;br /&gt;
	local numArg = expectTypes.numArg&lt;br /&gt;
	&lt;br /&gt;
	if expectTypes and expectTypes.numArg and not expectTypes.base then&lt;br /&gt;
		expectTypes.base = 10&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Optimize as much as possible&lt;br /&gt;
	if isError then&lt;br /&gt;
		fName = (name ~= &amp;#039;no value&amp;#039; and tpName ~= &amp;#039;number&amp;#039;) and name or getParentName(name == &amp;#039;no value&amp;#039; and expectTypes or level)&lt;br /&gt;
	end&lt;br /&gt;
			&lt;br /&gt;
	if name == &amp;#039;no value&amp;#039; then&lt;br /&gt;
		t.checkType(generateMsg(fName, argIdx, arg and &amp;#039;no value&amp;#039; or &amp;#039;value expected&amp;#039;, arg), (expectTypes or level)+3)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Check if `base` is valid&lt;br /&gt;
	if expectTypes.base and (expectTypes.base &amp;lt; 2 or expectTypes.base &amp;gt; 36) then&lt;br /&gt;
		error(&amp;#039;the option &amp;quot;base&amp;quot; must be between 2 and 36&amp;#039;, level+2)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Return if `numArg` is valid&lt;br /&gt;
	if expectTypes and #expectTypes == 0 then&lt;br /&gt;
		return arg&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if numArg or numOk then&lt;br /&gt;
		tn = (tpArg ~= &amp;#039;string&amp;#039; and tpArg ~= &amp;#039;number&amp;#039;) and nil or tonumber(arg, expectTypes.base)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if (tpArg == &amp;#039;string&amp;#039; or tpArg == &amp;#039;number&amp;#039;) and numArg and tn then&lt;br /&gt;
		return tn&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if tpArg == &amp;#039;number&amp;#039; and numOk then&lt;br /&gt;
		return arg&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Error if types did not match&lt;br /&gt;
	if not matches then&lt;br /&gt;
		local msg = generateMsg(fName, argIdx, tpArg, expectTypes)&lt;br /&gt;
		t.checkType(msg, level+3)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Check if argument is convertable to a number&lt;br /&gt;
	if expectTypes and expectTypes.base and not tn then&lt;br /&gt;
		fName = getParentName(name == &amp;#039;no value&amp;#039; and expectTypes or level);&lt;br /&gt;
		local msg = generateMsg(fName, argIdx, &amp;#039;value is not convertable to a base &amp;#039;..expectTypes.base..&amp;#039; number&amp;#039;)&lt;br /&gt;
		t.checkType(msg, level+3)&lt;br /&gt;
	elseif expectTypes and expectTypes.base and tn then&lt;br /&gt;
		return tn&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return arg&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- &amp;quot;Lite&amp;quot; version of `checkType()` due to performance issues&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function checkTypeLight(name, argIdx, arg, expectTypes, nilOk)&lt;br /&gt;
	local isMulti = expectTypes.lower ~= string.lower -- Check using properties instead of type()&lt;br /&gt;
	local argType = type(arg)&lt;br /&gt;
	&lt;br /&gt;
	if arg == nil and nilOk then&lt;br /&gt;
		return arg&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if isMulti then&lt;br /&gt;
		for _, v in pairs(expectTypes) do&lt;br /&gt;
			if argType == v then&lt;br /&gt;
				return arg&lt;br /&gt;
			end&lt;br /&gt;
		end		&lt;br /&gt;
		&lt;br /&gt;
		return ({ checkType=error }).checkType(string.format(&amp;quot;bad argument #%d to &amp;#039;%s&amp;#039; (%s expected, got %s)&amp;quot;, argIdx, name, table.concat(expectTypes, &amp;#039;/&amp;#039;), argType), 3)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if argType ~= expectTypes then&lt;br /&gt;
		({ checkType=error }).checkType(string.format(&amp;quot;bad argument #%d to &amp;#039;%s&amp;#039; (%s expected, got %s)&amp;quot;, argIdx, name, expectTypes, argType), 3)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return arg&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- function: checkArgs(types: table&amp;lt;table&amp;lt;string&amp;gt; | string&amp;gt;, ...arguments?: any)&lt;br /&gt;
--&lt;br /&gt;
-- Checks a given set of arguments against a list of types in a compact and streamlined manner&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function checkArgs(types, ...)&lt;br /&gt;
	checkTypeLight(&amp;#039;checkArgs&amp;#039;, 1, types, { &amp;#039;string&amp;#039;, &amp;#039;table&amp;#039; })&lt;br /&gt;
	&lt;br /&gt;
	if type(types) == &amp;#039;string&amp;#039; then&lt;br /&gt;
		types = { types }&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local t = {}&lt;br /&gt;
	local ret = { ... }&lt;br /&gt;
	-- Number of arguments&lt;br /&gt;
	local n = select(&amp;#039;#&amp;#039;, ...)&lt;br /&gt;
	t.checkTypeArgs = error&lt;br /&gt;
	local level = type(types.level) == &amp;quot;number&amp;quot; and (types.level &amp;gt;= -1 and types.level or -types.level) or 0&lt;br /&gt;
	local len = #types&lt;br /&gt;
	&lt;br /&gt;
	local toIter&lt;br /&gt;
	if types.strict then&lt;br /&gt;
		toIter = (len &amp;gt;= n and len or n)&lt;br /&gt;
	else&lt;br /&gt;
		toIter = len&lt;br /&gt;
	end&lt;br /&gt;
	local fName&lt;br /&gt;
	&lt;br /&gt;
	for i = 1, (len &amp;gt;= n and len or n) do&lt;br /&gt;
		local any&lt;br /&gt;
		&lt;br /&gt;
		-- Variables&lt;br /&gt;
		local curTypes = type(types[i]) ~= &amp;quot;table&amp;quot; and { types[i] } or types[i]&lt;br /&gt;
		local emptyOk = curTypes.emptyOk or curTypes.emptyok&lt;br /&gt;
		local nilOk = curTypes.nilOk or curTypes.nilok&lt;br /&gt;
		local numberOk = curTypes.numberOk or curTypes.numOk or curTypes.numok or curTypes.numberok&lt;br /&gt;
		local val = ({ ... })[i]&lt;br /&gt;
		local argIndex = select(&amp;#039;#&amp;#039;, ...) + 1&lt;br /&gt;
		&lt;br /&gt;
		if i &amp;gt; #types and types.strict then&lt;br /&gt;
			fName = getParentName(level);&lt;br /&gt;
			&lt;br /&gt;
			t.checkTypeArgs((&amp;#039;bad argument #%d to \&amp;#039;%s\&amp;#039; (%d arguments expected, got %d)&amp;#039;):format(i, fName, #types, i), level+3)&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- Case for nilOk&lt;br /&gt;
		if nilOk and emptyOk == nil then&lt;br /&gt;
			emptyOk = true&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- Special Case if nilOk is false and emptyOk is false&lt;br /&gt;
		if nilOk and emptyOk == false then&lt;br /&gt;
			table.insert(curTypes, &amp;#039;nil&amp;#039;)&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- Special case for the &amp;#039;any&amp;#039; type&lt;br /&gt;
		if indexOf(curTypes, &amp;#039;any&amp;#039;) ~= -1 or (emptyOk == false and #curTypes == 0) then&lt;br /&gt;
			any = true&lt;br /&gt;
			curTypes = {&lt;br /&gt;
				numberOk = numberOk,&lt;br /&gt;
				nilOk = nilOk,&lt;br /&gt;
				emptyOk = emptyOk,&lt;br /&gt;
			}&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		local tpVal = type(val)&lt;br /&gt;
		&lt;br /&gt;
		-- If argument is nil, but not empty, and the expected type is &amp;#039;any&amp;#039; and nilOk is false, error&lt;br /&gt;
		if nilOk == false and any and not (n &amp;lt; len and i &amp;gt; n) and tpVal == &amp;#039;nil&amp;#039; then&lt;br /&gt;
			fName = getParentName(level);&lt;br /&gt;
			-- Error message #1&lt;br /&gt;
			local valueExpected = (&amp;#039;bad argument #%d to \&amp;#039;%s\&amp;#039; (value expected)&amp;#039;):format(i, fName)&lt;br /&gt;
			&lt;br /&gt;
			t.checkTypeArgs(valueExpected, level+3)&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- If argument is empty&lt;br /&gt;
		if n &amp;lt; len and i &amp;gt; n and (not emptyOk or tpVal == &amp;#039;nil&amp;#039;) then&lt;br /&gt;
			if any then&lt;br /&gt;
				fName = getParentName(level);&lt;br /&gt;
				local valueExpected = (&amp;#039;bad argument #%d to \&amp;#039;%s\&amp;#039; (value expected)&amp;#039;):format(i, fName)&lt;br /&gt;
				&lt;br /&gt;
				-- Value expected error if argument is empty&lt;br /&gt;
				t.checkTypeArgs(valueExpected, level+3)&lt;br /&gt;
			elseif not nilOk or (nilOk and emptyOk == false) then&lt;br /&gt;
				fName = getParentName(level);&lt;br /&gt;
				&lt;br /&gt;
				-- No value error&lt;br /&gt;
				t.checkTypeArgs(generateMsg(fName, argIndex, &amp;#039;no value&amp;#039;, generateTypes(curTypes)), level+3)&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			-- Else check its type as normal&lt;br /&gt;
			ret[i] = checkType((level ~= 0 and level+1 or 1), i, val, curTypes, nilOk)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return unpack(ret)&lt;br /&gt;
end&lt;br /&gt;
checkTypeArgs = checkArgs&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- Alias for `checkType`&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function checkTypeMulti(t, types)&lt;br /&gt;
	checkType(1, t, &amp;#039;table&amp;#039;)&lt;br /&gt;
	checkType(2, types, &amp;#039;table&amp;#039;)&lt;br /&gt;
	&lt;br /&gt;
	t.checkTypeMulti = error&lt;br /&gt;
	&lt;br /&gt;
	for i = 1, #types do&lt;br /&gt;
		checkType(true, i, t[i], types[i])&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- function: alertDeprecation(name: string, useInstead?: string, level?: number)&lt;br /&gt;
-- &lt;br /&gt;
-- Throws a derecation error message with an optional substitute for the deprecated function&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function alertDeprecation(...)&lt;br /&gt;
	local name, useInstead, level = checkArgs({ &lt;br /&gt;
		&amp;#039;string&amp;#039;, { &amp;#039;string&amp;#039;, nilOk=true }, { &amp;#039;number&amp;#039;, nilOk=true } &lt;br /&gt;
	}, ...)&lt;br /&gt;
	local t = {}&lt;br /&gt;
	t.alertDeprecation = error&lt;br /&gt;
	&lt;br /&gt;
	if type(name) == &amp;quot;table&amp;quot; then&lt;br /&gt;
		name, useInstead = unpack{&lt;br /&gt;
			name.name or name[1],&lt;br /&gt;
			name.useInstead or name.use or name[2],&lt;br /&gt;
		}&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	t.alertDeprecation(string.format(&lt;br /&gt;
		&amp;#039;function %q is deprecated%s&amp;#039;, &lt;br /&gt;
		name or getParentName(),&lt;br /&gt;
		useInstead and string.format(&amp;#039;, use the function %q instead&amp;#039;, useInstead) or &amp;#039;&amp;#039;&lt;br /&gt;
	), (level or 0)+3)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- function: forEachArgs(types: string, ...arguments?: string)&lt;br /&gt;
-- &lt;br /&gt;
-- Returns an iterator which iterates over the list of given arguments, and asserts the type of each argument.&lt;br /&gt;
-- Useful in variable argument functions.&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function forEachArgs(types, ...)&lt;br /&gt;
	checkType(1, types, { &amp;#039;string&amp;#039;, &amp;#039;table&amp;#039; })&lt;br /&gt;
	&lt;br /&gt;
	local startIndex = types.startIndex and types.startIndex-1 or 0&lt;br /&gt;
	local required = types.required or 0&lt;br /&gt;
	local i = 0+(startIndex or 0)&lt;br /&gt;
	&lt;br /&gt;
	local args = { ... }&lt;br /&gt;
	local lim = select(&amp;#039;#&amp;#039;, ...)&lt;br /&gt;
	local ind = indexOf(types, &amp;#039;any&amp;#039;)&lt;br /&gt;
	local t = {}&lt;br /&gt;
	t.checkType = error&lt;br /&gt;
	&lt;br /&gt;
	return function()&lt;br /&gt;
		i = i + 1&lt;br /&gt;
		&lt;br /&gt;
		if lim &amp;lt; required and i &amp;gt; lim then&lt;br /&gt;
			if ind ~= -1 then&lt;br /&gt;
				t.checkType(generateMsg(getParentName(), i, &amp;#039;value expected&amp;#039;), 3)&lt;br /&gt;
			elseif ind == -1 then&lt;br /&gt;
				checkType(&amp;#039;no value&amp;#039;, i, types, 1)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		if i &amp;lt;= lim then&lt;br /&gt;
			if ind == -1 then&lt;br /&gt;
				checkType(1, i, args[i], types, types.nilOk)&lt;br /&gt;
			end&lt;br /&gt;
			&lt;br /&gt;
			return i, args[i], args&lt;br /&gt;
		else&lt;br /&gt;
			return nil, nil&lt;br /&gt;
		end&lt;br /&gt;
	end, ...&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- function: makeCheckSelfFunction(libraryName: string, varName: string, selfObj?: table, selfObjDesc?: string) &lt;br /&gt;
-- &lt;br /&gt;
-- Creates a function which asserts that the given object is an instance of another.&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function makeCheckSelfFunction(libraryName, varName, selfObj, selfObjDesc)&lt;br /&gt;
	if type(varName) == &amp;#039;table&amp;#039; then&lt;br /&gt;
		varName = libraryName&lt;br /&gt;
		selfObjDesc = selfObj&lt;br /&gt;
	end&lt;br /&gt;
	if type(libraryName) == &amp;#039;table&amp;#039; then&lt;br /&gt;
		selfObj = libraryName&lt;br /&gt;
		libraryName = varName&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return function(self, method)&lt;br /&gt;
		if self ~= selfObj then&lt;br /&gt;
			method = method or getParentName();&lt;br /&gt;
			({ checkSelf=error })[&amp;#039;checkSelf&amp;#039;](string.format(&lt;br /&gt;
				&amp;quot;%s: invalid %s. Did you call .%s() with a dot instead of a colon, i.e. &amp;quot; ..&lt;br /&gt;
				&amp;quot;%s.%s(...) instead of %s:%s(...)?&amp;quot;,&lt;br /&gt;
				libraryName, selfObjDesc or &amp;#039;self object&amp;#039;, method, varName, method, varName, method&lt;br /&gt;
			), 3)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- function: formattedError(formatStr?: string, level?: number, ...substitions?: string | number)&lt;br /&gt;
-- &lt;br /&gt;
-- Throws an error but with an option to use `string.format()`.&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function formattedError(formatStr, level, ...)&lt;br /&gt;
	checkTypeLight(&amp;#039;formattedError&amp;#039;, 2, level, { &amp;#039;number&amp;#039; }, true)&lt;br /&gt;
&lt;br /&gt;
	local t = { ... }&lt;br /&gt;
&lt;br /&gt;
	if #t &amp;gt; 0 then&lt;br /&gt;
		for i, v in ipairs(t) do&lt;br /&gt;
			t[i] = tostring(v)	&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local formatStr = type(formatStr) == &amp;#039;string&amp;#039; and formatStr or &amp;#039;unknown error&amp;#039;&lt;br /&gt;
	&lt;br /&gt;
	return error(string.format(formatStr, unpack(t)), tonumber(level) == 0 and level or (level or 1) + 1)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- function: formattedAssert(v?: any, formatStr?: string, level?: number, ...substitions?: string | number)&lt;br /&gt;
-- &lt;br /&gt;
-- Works like the native `assert()` but allows an option for using `formattedError()`.&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function formattedAssert(v, formatStr, level, ...)&lt;br /&gt;
	local formatStr = type(formatStr) == &amp;#039;string&amp;#039; and formatStr or &amp;#039;assertion failed!&amp;#039;&lt;br /&gt;
	&lt;br /&gt;
	if not v then &lt;br /&gt;
		formattedError(formatStr, level == 0 and level or (level or 1) + 1, ...)&lt;br /&gt;
	else&lt;br /&gt;
		return v&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
assertTrue = formattedAssert&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- Inverse alias for `formattedAssert()`&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function assertFalse(v, formatStr, level, ...)&lt;br /&gt;
	local formatStr = type(formatStr) == &amp;#039;string&amp;#039; and formatStr or &amp;#039;assertion failed!&amp;#039;&lt;br /&gt;
	&lt;br /&gt;
	if v then &lt;br /&gt;
		formattedError(formatStr, level == 0 and level or (level or 1) + 1, ...)&lt;br /&gt;
	else&lt;br /&gt;
		return v&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- function: mw.title.existsWithoutWanted(title: string)&lt;br /&gt;
-- &lt;br /&gt;
-- Checks if a page exists without marking it as a Special:WantedPages. title is name including namespace (if there is one)&lt;br /&gt;
-- [WARNING] Since this doesn&amp;#039;t us backlinking (what causes it to be &amp;quot;wanted&amp;quot;) the value returned for this function will not be reevaluated for a potentially infinite time after the page is created/deleted. Edits/null edits/purging will update it properly.&lt;br /&gt;
-- [EXPENSIVE] Note that just like a normal page `exists` check, this is an expensive function (although it runs faster)&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function existsWithoutWanted(title)&lt;br /&gt;
	local frame = mw.getCurrentFrame()&lt;br /&gt;
	&lt;br /&gt;
	-- PROTECTIONEXPIRY is a magic word that lets us check a page in a roundabout way without marking it as wanted.&lt;br /&gt;
	-- Trick taken from: https://www.mediawiki.org/wiki/Extension_talk:Scribunto/Lua_reference_manual#Avoid_creating_a_wanted_page_link_when_checking_if_page_exist&lt;br /&gt;
	return frame:callParserFunction(&amp;#039;PROTECTIONEXPIRY:edit&amp;#039;, title) ~= &amp;#039;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- function: inexpensivePageExists(title: string)&lt;br /&gt;
-- &lt;br /&gt;
-- Might not actually be faster, but doesn&amp;#039;t count as an expensive parser function call&lt;br /&gt;
-- [WANTEDPAGES] If file doesn&amp;#039;t exist, using this method will mark it as a Special:WantedPages&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function inexpensivePageExists(title)&lt;br /&gt;
	return mw.title.new(title):getContent()&lt;br /&gt;
end&lt;br /&gt;
pageExists = inexpensivePageExists&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- function: pipeline(...)&lt;br /&gt;
-- &lt;br /&gt;
-- Creates a function pipeline, where each argument is stored then passed to a function&lt;br /&gt;
-- when it is found in the arguments list, then it is invoked.&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function pipeline(...)&lt;br /&gt;
	local value = checkArgs(&amp;#039;any&amp;#039;, ...)&lt;br /&gt;
	local prependArgs = { value }&lt;br /&gt;
	local t, functionFound&lt;br /&gt;
	&lt;br /&gt;
	for k, v in forEachArgs({ &amp;#039;any&amp;#039;, startIndex=2 }, ...) do&lt;br /&gt;
		if type(v) ~= &amp;#039;function&amp;#039; then&lt;br /&gt;
			if #prependArgs == 0 then&lt;br /&gt;
				prependArgs[#prependArgs+1] = value&lt;br /&gt;
			end&lt;br /&gt;
			prependArgs[#prependArgs+1] = v&lt;br /&gt;
		else&lt;br /&gt;
			t = { pcall(v, unpack(prependArgs)) }&lt;br /&gt;
			&lt;br /&gt;
			functionFound = true&lt;br /&gt;
			if not t[1] then&lt;br /&gt;
				t[2] = tostring(t[2])&lt;br /&gt;
				&lt;br /&gt;
				-- Error message if invocation failed&lt;br /&gt;
				formattedAssert(&lt;br /&gt;
					t[1], &lt;br /&gt;
					&amp;#039;Exception in calling function%s%s at que posistion #%d: %s&amp;#039;, &lt;br /&gt;
					2, &lt;br /&gt;
					t[2]:match(&amp;#039;^(.-):(.-):&amp;#039;) and &amp;#039; in module &amp;quot;&amp;#039;..t[2]:match(&amp;#039;^(.-):(.-):&amp;#039;)..&amp;#039;&amp;quot;&amp;#039; or &amp;#039;&amp;#039;,&lt;br /&gt;
					t[2]:match(&amp;#039;^(.-):(.-):&amp;#039;) and &amp;#039; at line &amp;#039;..({ t[2]:match(&amp;#039;^(.-):(.-):&amp;#039;) })[2]..&amp;#039; called&amp;#039; or &amp;#039;&amp;#039;,&lt;br /&gt;
					k,&lt;br /&gt;
					t[2]:gsub(&amp;#039;^(.-):(.-):&amp;#039;, &amp;#039;&amp;#039;)&lt;br /&gt;
				)&lt;br /&gt;
			end&lt;br /&gt;
			table.remove(t or {}, 1)&lt;br /&gt;
			prependArgs = t&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	if functionFound then&lt;br /&gt;
		return unpack(t)&lt;br /&gt;
	else&lt;br /&gt;
		return ...&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
-- function: bind(targetFn: function, ...items?: any)&lt;br /&gt;
-- &lt;br /&gt;
-- Wraps `targetFn` in a new function which serves as a proxy prepending any arguments&lt;br /&gt;
-- given when the new function is called&lt;br /&gt;
---------------------------------------------------------------------------------&lt;br /&gt;
local function bind(targetFn, ...)&lt;br /&gt;
	local mt = getmetatable(targetFn)&lt;br /&gt;
	if not (mt and (mt.__call or mt.__isClass)) then&lt;br /&gt;
		checkType(1, targetFn, &amp;#039;function&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local args = { ... }&lt;br /&gt;
	args.n = select(&amp;#039;#&amp;#039;, ...)&lt;br /&gt;
	&lt;br /&gt;
	return function(...)&lt;br /&gt;
		local len = select(&amp;#039;#&amp;#039;, ...)&lt;br /&gt;
		local callArgs = {}&lt;br /&gt;
		local passedArgs = { ... }&lt;br /&gt;
		&lt;br /&gt;
		for i = 1, args.n, 1 do&lt;br /&gt;
			callArgs[i] = args[i]&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		if len &amp;gt; 0 then&lt;br /&gt;
			for i = args.n + 1, args.n + len, 1 do&lt;br /&gt;
				callArgs[i] = passedArgs[i - args.n]&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		return targetFn(unpack(callArgs, 1, args.n + len))&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
	getCodeLocation = getCodeLocation,&lt;br /&gt;
	makeArgNumber = makeArgNumber,&lt;br /&gt;
	getParentName = getParentName,&lt;br /&gt;
	typeMatches = typeMatches,&lt;br /&gt;
	generateMsg = generateMsg,&lt;br /&gt;
	validateTypes = validateTypes,&lt;br /&gt;
	checkType = checkType,&lt;br /&gt;
	checkTypeLight = checkTypeLight,&lt;br /&gt;
	checkArgs = checkArgs,&lt;br /&gt;
	checkTypeMulti = checkTypeMulti,&lt;br /&gt;
	alertDeprecation = alertDeprecation,&lt;br /&gt;
	forEachArgs = forEachArgs,&lt;br /&gt;
	makeCheckSelfFunction = makeCheckSelfFunction,&lt;br /&gt;
	formattedError = formattedError,&lt;br /&gt;
	formattedAssert = formattedAssert,&lt;br /&gt;
	assertFalse = assertFalse,&lt;br /&gt;
	existsWithoutWanted = existsWithoutWanted,&lt;br /&gt;
	inexpensivePageExists = inexpensivePageExists,&lt;br /&gt;
	pipeline = pipeline,&lt;br /&gt;
	bind = bind,&lt;br /&gt;
	getStackName = getStackName,&lt;br /&gt;
	checkTypeArgs = checkTypeArgs,&lt;br /&gt;
	assertTrue = assertTrue,&lt;br /&gt;
	pageExists = pageExists,&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>515797455988850689</name></author>
	</entry>
</feed>