<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.roatpkz.com/index.php?action=history&amp;feed=atom&amp;title=Module%3ADependencyList</id>
	<title>Module:DependencyList - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.roatpkz.com/index.php?action=history&amp;feed=atom&amp;title=Module%3ADependencyList"/>
	<link rel="alternate" type="text/html" href="https://wiki.roatpkz.com/index.php?title=Module:DependencyList&amp;action=history"/>
	<updated>2026-04-28T16:26:52Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.roatpkz.com/index.php?title=Module:DependencyList&amp;diff=22745&amp;oldid=prev</id>
		<title>Hefner at 19:26, 12 May 2024</title>
		<link rel="alternate" type="text/html" href="https://wiki.roatpkz.com/index.php?title=Module:DependencyList&amp;diff=22745&amp;oldid=prev"/>
		<updated>2024-05-12T19:26:12Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 19:26, 12 May 2024&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l358&quot;&gt;Line 358:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 358:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     for _, item in ipairs( invokeList ) do&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     for _, item in ipairs( invokeList ) do&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         table.insert( res, string.format(&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         table.insert( res, string.format(&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;             &quot;&amp;lt;div class=&#039;seealso&#039;&amp;gt;&#039;&#039;&#039;%s&#039;&#039;&#039; invokes function &#039;&#039;&#039;%s&#039;&#039;&#039; in [[%s]] using &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[[RuneScape:&lt;/del&gt;Lua&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;|Lua]]&lt;/del&gt;.&amp;lt;/div&amp;gt;&quot;,&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;             &quot;&amp;lt;div class=&#039;seealso&#039;&amp;gt;&#039;&#039;&#039;%s&#039;&#039;&#039; invokes function &#039;&#039;&#039;%s&#039;&#039;&#039; in [[%s]] using Lua.&amp;lt;/div&amp;gt;&quot;,&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;             templateName,&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;             templateName,&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;             item.funcName,&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;             item.funcName,&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Hefner</name></author>
	</entry>
	<entry>
		<id>https://wiki.roatpkz.com/index.php?title=Module:DependencyList&amp;diff=1653&amp;oldid=prev</id>
		<title>Fantastic: Created page with &quot;local p = {} local libraryUtil = require( &#039;libraryUtil&#039; ) local arr = require( &#039;Module:Array&#039; ) local yn = require( &#039;Module:Yesno&#039; ) local param = require( &#039;Module:Paramtest&#039; ) local dpl = require( &#039;Module:DPLlua&#039; ) local tooltip = require( &#039;Module:Tooltip&#039; ) local moduleIsUsed = false local COLLAPSE_LIST_LENGTH_THRESHOLD = 5 local MAX_DYNAMIC_REQUIRE_LIST_LENGTH = 30 local dynamicRequireListQueryCache = {}  local builtins = {     [&quot;libraryUtil&quot;] = {         link = &quot;mw:S...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.roatpkz.com/index.php?title=Module:DependencyList&amp;diff=1653&amp;oldid=prev"/>
		<updated>2024-03-29T21:36:21Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;local p = {} local libraryUtil = require( &amp;#039;libraryUtil&amp;#039; ) local arr = require( &amp;#039;Module:Array&amp;#039; ) local yn = require( &amp;#039;Module:Yesno&amp;#039; ) local param = require( &amp;#039;Module:Paramtest&amp;#039; ) local dpl = require( &amp;#039;Module:DPLlua&amp;#039; ) local tooltip = require( &amp;#039;Module:Tooltip&amp;#039; ) local moduleIsUsed = false local COLLAPSE_LIST_LENGTH_THRESHOLD = 5 local MAX_DYNAMIC_REQUIRE_LIST_LENGTH = 30 local dynamicRequireListQueryCache = {}  local builtins = {     [&amp;quot;libraryUtil&amp;quot;] = {         link = &amp;quot;mw:S...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local p = {}&lt;br /&gt;
local libraryUtil = require( &amp;#039;libraryUtil&amp;#039; )&lt;br /&gt;
local arr = require( &amp;#039;Module:Array&amp;#039; )&lt;br /&gt;
local yn = require( &amp;#039;Module:Yesno&amp;#039; )&lt;br /&gt;
local param = require( &amp;#039;Module:Paramtest&amp;#039; )&lt;br /&gt;
local dpl = require( &amp;#039;Module:DPLlua&amp;#039; )&lt;br /&gt;
local tooltip = require( &amp;#039;Module:Tooltip&amp;#039; )&lt;br /&gt;
local moduleIsUsed = false&lt;br /&gt;
local COLLAPSE_LIST_LENGTH_THRESHOLD = 5&lt;br /&gt;
local MAX_DYNAMIC_REQUIRE_LIST_LENGTH = 30&lt;br /&gt;
local dynamicRequireListQueryCache = {}&lt;br /&gt;
&lt;br /&gt;
local builtins = {&lt;br /&gt;
    [&amp;quot;libraryUtil&amp;quot;] = {&lt;br /&gt;
        link = &amp;quot;mw:Special:MyLanguage/Extension:Scribunto/Lua reference manual#libraryUtil&amp;quot;,&lt;br /&gt;
        categories = {},&lt;br /&gt;
    },&lt;br /&gt;
    [&amp;quot;strict&amp;quot;] = {&lt;br /&gt;
        link = &amp;quot;mw:Special:MyLanguage/Extension:Scribunto/Lua reference manual#strict&amp;quot;,&lt;br /&gt;
        categories = { &amp;quot;Strict mode modules&amp;quot; },&lt;br /&gt;
    },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
--- Used in case &amp;#039;require( varName )&amp;#039; is found. Attempts to find a string value stored in &amp;#039;varName&amp;#039;.&lt;br /&gt;
---@param content string    The content of the module to search in&lt;br /&gt;
---@param varName string&lt;br /&gt;
---@return string&lt;br /&gt;
local function substVarValue( content, varName )&lt;br /&gt;
    local res = content:match( varName .. &amp;#039;%s*=%s*(%b&amp;quot;&amp;quot;%s-%.*)&amp;#039; ) or content:match( varName .. &amp;quot;%s*=%s*(%b&amp;#039;&amp;#039;%s-%.*)&amp;quot; ) or &amp;#039;&amp;#039;&lt;br /&gt;
    if res:find( &amp;#039;^([&amp;quot;\&amp;#039;])[Mm]odule:[%S]+%1&amp;#039; ) and not res:find( &amp;#039;%.%.&amp;#039; ) and not res:find( &amp;#039;%%%a&amp;#039; ) then&lt;br /&gt;
        return mw.text.trim( res )&lt;br /&gt;
    else&lt;br /&gt;
        return &amp;#039;&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---@param capture string&lt;br /&gt;
---@param content string    The content of the module to search in&lt;br /&gt;
---@return string&lt;br /&gt;
local function extractModuleName( capture, content )&lt;br /&gt;
    capture = capture:gsub( &amp;#039;^%(%s*(.-)%s*%)$&amp;#039;, &amp;#039;%1&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
    if capture:find( &amp;#039;^([&amp;quot;\&amp;#039;]).-%1$&amp;#039; ) then -- Check if it is already a pure string&lt;br /&gt;
        return capture&lt;br /&gt;
    elseif capture:find( &amp;#039;^[%a_][%w_]*$&amp;#039; ) then -- Check if if is a single variable&lt;br /&gt;
        return substVarValue( content, capture )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return capture&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---@param str string&lt;br /&gt;
---@return string&lt;br /&gt;
local function formatPageName( str )&lt;br /&gt;
    local name = mw.text.trim(str)&lt;br /&gt;
        :gsub( &amp;#039;^([\&amp;#039;\&amp;quot;])(.-)%1$&amp;#039;, &amp;#039;%2&amp;#039; ) -- Only remove quotes at start and end of string if both are the same type&lt;br /&gt;
        :gsub( &amp;#039;_&amp;#039;, &amp;#039; &amp;#039; )&lt;br /&gt;
        :gsub( &amp;#039;^.&amp;#039;, string.upper )&lt;br /&gt;
        :gsub( &amp;#039;:.&amp;#039;, string.upper )&lt;br /&gt;
&lt;br /&gt;
    return name&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---@param str string&lt;br /&gt;
---@param allowBuiltins? boolean&lt;br /&gt;
---@return string&lt;br /&gt;
local function formatModuleName( str, allowBuiltins )&lt;br /&gt;
    if allowBuiltins then&lt;br /&gt;
        local name = mw.text.trim(str)&lt;br /&gt;
            -- Only remove quotes at start and end of string if both are the same type&lt;br /&gt;
            :gsub([[^([&amp;#039;&amp;quot;])(.-)%1$]], &amp;#039;%2&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
        if builtins[name] then&lt;br /&gt;
            return name&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local module = formatPageName( str )&lt;br /&gt;
&lt;br /&gt;
    if not string.find( module, &amp;#039;^[Mm]odule:&amp;#039; ) then&lt;br /&gt;
        module = &amp;#039;Module:&amp;#039; .. module&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return module&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function dualGmatch( str, pat1, pat2 )&lt;br /&gt;
    local f1 = string.gmatch( str, pat1 )&lt;br /&gt;
    if pat2 then&lt;br /&gt;
        local f2 = string.gmatch( str, pat2 )&lt;br /&gt;
        return function()&lt;br /&gt;
            return f1() or f2()&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        return f1&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function isDynamicPath( str )&lt;br /&gt;
    return string.find( str, &amp;#039;%.%.&amp;#039; ) or string.find( str, &amp;#039;%%%a&amp;#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Used in case a construct like &amp;#039;require( &amp;quot;Module:wowee/&amp;quot; .. isTheBest )&amp;#039; is found.&lt;br /&gt;
--- Will return a list of pages which satisfy this pattern where &amp;#039;isTheBest&amp;#039; can take any value.&lt;br /&gt;
---@param query string&lt;br /&gt;
---@return string[]&lt;br /&gt;
local function getDynamicRequireList( query )&lt;br /&gt;
    if query:find( &amp;#039;%.%.&amp;#039; ) then&lt;br /&gt;
        query = mw.text.split( query, &amp;#039;..&amp;#039;, true )&lt;br /&gt;
        query = arr.map( query, function(x) return mw.text.trim(x) end )&lt;br /&gt;
        query = arr.map( query, function(x) return (x:match(&amp;#039;^[\&amp;#039;\&amp;quot;](.-)[\&amp;#039;\&amp;quot;]$&amp;#039;) or &amp;#039;%&amp;#039;) end )&lt;br /&gt;
        query = table.concat( query )&lt;br /&gt;
    else&lt;br /&gt;
        local _, _query = query:match( &amp;#039;([&amp;quot;\&amp;#039;])(.-)%1&amp;#039; )&lt;br /&gt;
        query = _query:gsub( &amp;#039;%%%a&amp;#039;, &amp;#039;%%&amp;#039; )&lt;br /&gt;
    end&lt;br /&gt;
    query = query:gsub( &amp;#039;^[Mm]odule:&amp;#039;, &amp;#039;&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
    if query:find( &amp;#039;^[Ee]xchange/&amp;#039; ) or query:find( &amp;#039;^[Dd]ata/&amp;#039; ) then&lt;br /&gt;
        return { &amp;#039;Module:&amp;#039; .. query }   -- This format will later be used by formatDynamicQueryLink()&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if dynamicRequireListQueryCache[ query ] then&lt;br /&gt;
        return dynamicRequireListQueryCache[ query ]&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local list = dpl.ask{&lt;br /&gt;
        namespace = &amp;#039;Module&amp;#039;,&lt;br /&gt;
        titlematch = query,&lt;br /&gt;
        nottitlematch = &amp;#039;%/doc|&amp;#039;..query..&amp;#039;/%&amp;#039;,&lt;br /&gt;
        distinct = &amp;#039;strict&amp;#039;,&lt;br /&gt;
        ignorecase = true,&lt;br /&gt;
        ordermethod = &amp;#039;title&amp;#039;,&lt;br /&gt;
        count = MAX_DYNAMIC_REQUIRE_LIST_LENGTH + 1,&lt;br /&gt;
        skipthispage = &amp;#039;no&amp;#039;,&lt;br /&gt;
        allowcachedresults = true,&lt;br /&gt;
        cacheperiod = 604800 -- One week&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if #list &amp;gt; MAX_DYNAMIC_REQUIRE_LIST_LENGTH then&lt;br /&gt;
        list = { &amp;#039;Module:&amp;#039; .. query }&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    dynamicRequireListQueryCache[ query ] = list&lt;br /&gt;
&lt;br /&gt;
    return list&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Returns a list of modules loaded and required by module &amp;#039;moduleName&amp;#039;.&lt;br /&gt;
---@param moduleName string&lt;br /&gt;
---@param searchForUsedTemplates? boolean&lt;br /&gt;
---@return table&amp;lt;string, string[]&amp;gt;&lt;br /&gt;
local function getRequireList( moduleName, searchForUsedTemplates )&lt;br /&gt;
    local content = mw.title.new( moduleName ):getContent()&lt;br /&gt;
    local requireList = arr{}&lt;br /&gt;
    local loadDataList = arr{}&lt;br /&gt;
    local loadJsonDataList = arr{}&lt;br /&gt;
    local usedTemplateList = arr{}&lt;br /&gt;
    local dynamicRequirelist = arr{}&lt;br /&gt;
    local dynamicLoadDataList = arr{}&lt;br /&gt;
    local dynamicLoadJsonDataList = arr{}&lt;br /&gt;
    local extraCategories = arr{}&lt;br /&gt;
&lt;br /&gt;
    assert( content ~= nil, string.format( &amp;#039;%s does not exist&amp;#039;, moduleName ) )&lt;br /&gt;
&lt;br /&gt;
    content = content:gsub( &amp;#039;%-%-%[(=-)%[.-%]%1%]&amp;#039;, &amp;#039;&amp;#039; ):gsub( &amp;#039;%-%-[^\n]*&amp;#039;, &amp;#039;&amp;#039; ) -- Strip comments&lt;br /&gt;
&lt;br /&gt;
    local function getList( pat1, pat2, list, dynList )&lt;br /&gt;
        for match in dualGmatch( content, pat1, pat2 ) do&lt;br /&gt;
            match = mw.text.trim( match )&lt;br /&gt;
            local name = extractModuleName( match, content )&lt;br /&gt;
&lt;br /&gt;
            if isDynamicPath( name ) then&lt;br /&gt;
                dynList:insert( getDynamicRequireList( name ), true )&lt;br /&gt;
            elseif name ~= &amp;#039;&amp;#039; then&lt;br /&gt;
                name = formatModuleName( name, true )&lt;br /&gt;
                table.insert( list, name )&lt;br /&gt;
&lt;br /&gt;
                if builtins[name] then&lt;br /&gt;
                    extraCategories = extraCategories:insert( builtins[name].categories, true )&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    getList( &amp;#039;require%s*(%b())&amp;#039;, &amp;#039;require%s*(([&amp;quot;\&amp;#039;])%s*[Mm]odule:.-%2)&amp;#039;, requireList, dynamicRequirelist )&lt;br /&gt;
    getList( &amp;#039;mw%.loadData%s*(%b())&amp;#039;, &amp;#039;mw%.loadData%s*(([&amp;quot;\&amp;#039;])%s*[Mm]odule:.-%2)&amp;#039;, loadDataList, dynamicLoadDataList )&lt;br /&gt;
    getList( &amp;#039;mw%.loadJsonData%s*(%b())&amp;#039;, &amp;#039;mw%.loadJsonData%s*(([&amp;quot;\&amp;#039;])%s*[Mm]odule:.-%2)&amp;#039;, loadJsonDataList, dynamicLoadJsonDataList )&lt;br /&gt;
    getList( &amp;#039;pcall%s*%(%s*require%s*,([^%),]+)&amp;#039;, nil, requireList, dynamicRequirelist )&lt;br /&gt;
    getList( &amp;#039;pcall%s*%(%s*mw%.loadData%s*,([^%),]+)&amp;#039;, nil, loadDataList, dynamicLoadDataList )&lt;br /&gt;
    getList( &amp;#039;pcall%s*%(%s*mw%.loadJsonData%s*,([^%),]+)&amp;#039;, nil, loadJsonDataList, dynamicLoadJsonDataList )&lt;br /&gt;
&lt;br /&gt;
    if searchForUsedTemplates then&lt;br /&gt;
        for preprocess in string.gmatch( content, &amp;#039;:preprocess%s*(%b())&amp;#039; ) do&lt;br /&gt;
            local function recursiveGMatch( str, pat )&lt;br /&gt;
                local list = {}&lt;br /&gt;
                local i = 0&lt;br /&gt;
                repeat&lt;br /&gt;
                    for match in string.gmatch( list[i] or str, pat ) do&lt;br /&gt;
                        table.insert( list, match )&lt;br /&gt;
                    end&lt;br /&gt;
                    i =  i + 1&lt;br /&gt;
                until i &amp;gt; #list or i &amp;gt; 100&lt;br /&gt;
&lt;br /&gt;
                i = 0&lt;br /&gt;
                return function()&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
                    return list[i]&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
&lt;br /&gt;
            for template in recursiveGMatch( preprocess, &amp;#039;{(%b{})}&amp;#039; ) do&lt;br /&gt;
                local name = string.match( template, &amp;#039;{(.-)[|{}]&amp;#039; )&lt;br /&gt;
                if name ~= &amp;#039;&amp;#039; then&lt;br /&gt;
                    if name:find( &amp;#039;:&amp;#039; ) then&lt;br /&gt;
                        local ns = name:match( &amp;#039;^(.-):&amp;#039; )&lt;br /&gt;
                        if arr.contains( {&amp;#039;&amp;#039;, &amp;#039;template&amp;#039;, &amp;#039;calculator&amp;#039;, &amp;#039;user&amp;#039;}, ns:lower() ) then&lt;br /&gt;
                            table.insert( usedTemplateList, name )&lt;br /&gt;
                        elseif ns == ns:upper() then&lt;br /&gt;
                            table.insert( usedTemplateList, ns ) -- Probably a magic word&lt;br /&gt;
                        end&lt;br /&gt;
                    else&lt;br /&gt;
                        if name:match( &amp;#039;^%u+$&amp;#039; ) or name == &amp;#039;!&amp;#039; then&lt;br /&gt;
                            table.insert( usedTemplateList, name ) -- Probably a magic word&lt;br /&gt;
                        else&lt;br /&gt;
                            table.insert( usedTemplateList, &amp;#039;Template:&amp;#039;..name )&lt;br /&gt;
                        end&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    requireList = requireList .. dynamicRequirelist&lt;br /&gt;
    requireList = requireList:unique()&lt;br /&gt;
    loadDataList = loadDataList .. dynamicLoadDataList&lt;br /&gt;
    loadDataList = loadDataList:unique()&lt;br /&gt;
    loadJsonDataList = loadJsonDataList .. dynamicLoadJsonDataList&lt;br /&gt;
    usedTemplateList = usedTemplateList:unique()&lt;br /&gt;
    extraCategories = extraCategories:unique()&lt;br /&gt;
    table.sort( requireList )&lt;br /&gt;
    table.sort( loadDataList )&lt;br /&gt;
    table.sort( loadJsonDataList )&lt;br /&gt;
    table.sort( usedTemplateList )&lt;br /&gt;
    table.sort( extraCategories )&lt;br /&gt;
&lt;br /&gt;
    return {&lt;br /&gt;
        requireList = requireList,&lt;br /&gt;
        loadDataList = loadDataList,&lt;br /&gt;
        loadJsonDataList = loadJsonDataList,&lt;br /&gt;
        usedTemplateList = usedTemplateList,&lt;br /&gt;
        extraCategories = extraCategories&lt;br /&gt;
    }&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Returns a list with module and function names used in all &amp;#039;{{#Invoke:moduleName|funcName}}&amp;#039; found on page &amp;#039;templateName&amp;#039;.&lt;br /&gt;
---@param templateName string&lt;br /&gt;
---@return table&amp;lt;string, string&amp;gt;[]&lt;br /&gt;
local function getInvokeCallList( templateName )&lt;br /&gt;
    local content = mw.title.new( templateName ):getContent()&lt;br /&gt;
    local invokeList = {}&lt;br /&gt;
&lt;br /&gt;
    assert( content ~= nil, string.format( &amp;#039;%s does not exist&amp;#039;, templateName ) )&lt;br /&gt;
&lt;br /&gt;
    for moduleName, funcName in string.gmatch( content, &amp;#039;{{[{|safeubt:}]-#[Ii]nvoke:([^|]+)|([^}|]+)[^}]*}}&amp;#039; ) do&lt;br /&gt;
        moduleName = formatModuleName( moduleName )&lt;br /&gt;
        funcName = mw.text.trim( funcName )&lt;br /&gt;
        if string.find( funcName, &amp;#039;^{{{&amp;#039; ) then&lt;br /&gt;
            funcName = funcName ..  &amp;#039;}}}&amp;#039;&lt;br /&gt;
        end&lt;br /&gt;
        table.insert( invokeList, {moduleName=moduleName, funcName=funcName} )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- For form calcs invoking the module directly&lt;br /&gt;
    for config in dualGmatch( content, &amp;#039;&amp;lt;pre%s+class%s*=%s*[&amp;quot;\&amp;#039;]jcConfig[&amp;quot;\&amp;#039;](.-)&amp;lt;/pre&amp;gt;&amp;#039;, &amp;#039;{{[Ff]orm calculator%s*|(.+)}}&amp;#039; ) do&lt;br /&gt;
        local moduleName = string.match( config, &amp;#039;module%s*=%s*(.-)[\n|]&amp;#039; )&lt;br /&gt;
        if param.has_content( moduleName ) then&lt;br /&gt;
            moduleName = formatModuleName( moduleName )&lt;br /&gt;
            local funcName = string.match( config, &amp;#039;modulefunc%s*=%s*(.-)[\n|]&amp;#039; ) or &amp;#039;main&amp;#039;&lt;br /&gt;
            table.insert( invokeList, {moduleName=moduleName, funcName=funcName} )&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    invokeList = arr.unique( invokeList, function(x) return x.moduleName..x.funcName end )&lt;br /&gt;
    table.sort( invokeList, function(x, y) return x.moduleName..x.funcName &amp;lt; y.moduleName..y.funcName end )&lt;br /&gt;
&lt;br /&gt;
    return invokeList&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---@param pageName string&lt;br /&gt;
---@param addCategories boolean&lt;br /&gt;
---@return string&lt;br /&gt;
local function messageBoxUnused( pageName, addCategories )&lt;br /&gt;
    local html = mw.html.create( &amp;#039;table&amp;#039; ):addClass( &amp;#039;messagebox obsolete plainlinks&amp;#039; )&lt;br /&gt;
    html:tag( &amp;#039;td&amp;#039; )&lt;br /&gt;
        :attr( &amp;#039;width&amp;#039;, &amp;#039;40xp&amp;#039; )&lt;br /&gt;
        :wikitext( &amp;#039;[[File:Willow logs (historical).png|center|30px|link=]]&amp;#039; )&lt;br /&gt;
    :done()&lt;br /&gt;
    :tag( &amp;#039;td&amp;#039; )&lt;br /&gt;
        :wikitext( &amp;quot;&amp;#039;&amp;#039;&amp;#039;This module is unused.&amp;#039;&amp;#039;&amp;#039;&amp;quot; )&lt;br /&gt;
        :tag( &amp;#039;div&amp;#039; )&lt;br /&gt;
            :css{ [&amp;#039;font-size&amp;#039;]=&amp;#039;0.85em&amp;#039;, [&amp;#039;line-height&amp;#039;]=&amp;#039;1.45em&amp;#039; }&lt;br /&gt;
            :wikitext( string.format( &amp;#039;This module is neither invoked by a template nor required/loaded by another module. If this is in error, make sure to add &amp;lt;code&amp;gt;{{[[Template:Documentation|Documentation]]}}&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;{{[[Template:No documentation|No&amp;amp;nbsp;documentation]]}}&amp;lt;/code&amp;gt; to the calling template\&amp;#039;s or parent\&amp;#039;s module documentation.&amp;#039;, pageName ) )&lt;br /&gt;
            :wikitext( addCategories and &amp;#039;[[Category:Unused modules]]&amp;#039; or &amp;#039;&amp;#039; )&lt;br /&gt;
        :done()&lt;br /&gt;
    :done()&lt;br /&gt;
&lt;br /&gt;
    return tostring( html )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function collapseList( list, id, listType )&lt;br /&gt;
    local text = string.format( &amp;#039;%d %s&amp;#039;, #list, listType )&lt;br /&gt;
    local button = tooltip._span{ name=id, alt=text }&lt;br /&gt;
    list = arr.map( list, function(x) return &amp;#039;\n# &amp;#039;..x end )&lt;br /&gt;
    local content = tooltip._div{ name=id, content=&amp;#039;\n&amp;#039;..table.concat( list )..&amp;#039;\n\n&amp;#039; }&lt;br /&gt;
&lt;br /&gt;
    return { tostring( button ) .. tostring( content ) }&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Creates a link to [[Special:Search]] showing all pages found by getDynamicRequireList() in case it found more than MAX_DYNAMIC_REQUIRE_LIST_LENGTH pages.&lt;br /&gt;
---@param query string      @This will be in a format like &amp;#039;Module:Wowee/%&amp;#039; or &amp;#039;Module:Wowee/%/data&amp;#039;&lt;br /&gt;
---@return string&lt;br /&gt;
local function formatDynamicQueryLink( query )&lt;br /&gt;
    local prefix = query:match( &amp;#039;^([^/]+)&amp;#039; )&lt;br /&gt;
    local linkText = query:gsub( &amp;#039;%%&amp;#039;, &amp;#039;&amp;amp;lt; ... &amp;amp;gt;&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
    query = query:gsub( &amp;#039;^Module:&amp;#039;,  &amp;#039;&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
    query = query:gsub( &amp;#039;([^/]+)/?&amp;#039;, function ( match )&lt;br /&gt;
        if match == &amp;#039;%&amp;#039; then&lt;br /&gt;
            return &amp;#039;\\/[^\\/]+&amp;#039;&lt;br /&gt;
        else&lt;br /&gt;
            return &amp;#039;\\/&amp;quot;&amp;#039; .. match .. &amp;#039;&amp;quot;&amp;#039;&lt;br /&gt;
        end&lt;br /&gt;
    end )&lt;br /&gt;
&lt;br /&gt;
    query = query:gsub( &amp;#039;^\\/&amp;#039;, &amp;#039;&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
    query = string.format(&lt;br /&gt;
        &amp;#039;intitle:/%s%s/i -intitle:/%s\\/&amp;quot;&amp;quot;/i -intitle:doc prefix:&amp;quot;%s&amp;quot;&amp;#039;,&lt;br /&gt;
        query,&lt;br /&gt;
        query:find( &amp;#039;&amp;quot;$&amp;#039; ) and &amp;#039;&amp;#039; or &amp;#039;&amp;quot;&amp;quot;&amp;#039;,&lt;br /&gt;
        query,&lt;br /&gt;
        prefix&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    return string.format( &amp;#039;&amp;lt;span class=&amp;quot;plainlinks&amp;quot;&amp;gt;[%s %s]&amp;lt;/span&amp;gt;&amp;#039;, tostring( mw.uri.fullUrl( &amp;#039;Special:Search&amp;#039;, { search = query } ) ), linkText )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---@param templateName string&lt;br /&gt;
---@param addCategories boolean&lt;br /&gt;
---@param invokeList table&amp;lt;string, string&amp;gt;[]    @This is the list returned by getInvokeCallList()&lt;br /&gt;
---@return string&lt;br /&gt;
local function formatInvokeCallList( templateName, addCategories, invokeList )&lt;br /&gt;
    local category = addCategories and &amp;#039;[[Category:Lua-based templates]]&amp;#039; or &amp;#039;&amp;#039;&lt;br /&gt;
    local res = {}&lt;br /&gt;
&lt;br /&gt;
    for _, item in ipairs( invokeList ) do&lt;br /&gt;
        table.insert( res, string.format(&lt;br /&gt;
            &amp;quot;&amp;lt;div class=&amp;#039;seealso&amp;#039;&amp;gt;&amp;#039;&amp;#039;&amp;#039;%s&amp;#039;&amp;#039;&amp;#039; invokes function &amp;#039;&amp;#039;&amp;#039;%s&amp;#039;&amp;#039;&amp;#039; in [[%s]] using [[RuneScape:Lua|Lua]].&amp;lt;/div&amp;gt;&amp;quot;,&lt;br /&gt;
            templateName,&lt;br /&gt;
            item.funcName,&lt;br /&gt;
            item.moduleName&lt;br /&gt;
        ) )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if #invokeList &amp;gt; 0 then&lt;br /&gt;
        table.insert( res, category )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return table.concat( res )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---@param moduleName string&lt;br /&gt;
---@param addCategories boolean&lt;br /&gt;
---@param whatLinksHere string    @A list generated by a dpl of pages in the Template or Calculator namespace which link to moduleName.&lt;br /&gt;
---@return string&lt;br /&gt;
local function formatInvokedByList( moduleName, addCategories, whatLinksHere )&lt;br /&gt;
    local function lcfirst( str )&lt;br /&gt;
        return string.gsub( str, &amp;#039;^[Mm]odule:.&amp;#039;, string.lower )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local templateData = arr.map( whatLinksHere, function(x) return {templateName=x, invokeList=getInvokeCallList(x)} end )&lt;br /&gt;
    templateData = arr.filter( templateData, function(x)&lt;br /&gt;
        return arr.any( x.invokeList, function(y)&lt;br /&gt;
            return lcfirst(y.moduleName) == lcfirst(moduleName)&lt;br /&gt;
        end )&lt;br /&gt;
    end )&lt;br /&gt;
&lt;br /&gt;
    local invokedByList = {}&lt;br /&gt;
&lt;br /&gt;
    for _, template in ipairs( templateData ) do&lt;br /&gt;
        for _, invoke in ipairs( template.invokeList ) do&lt;br /&gt;
            table.insert( invokedByList, string.format( &amp;quot;function &amp;#039;&amp;#039;&amp;#039;%s&amp;#039;&amp;#039;&amp;#039; is invoked by [[%s]]&amp;quot;, invoke.funcName, template.templateName ) )&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    table.sort( invokedByList)&lt;br /&gt;
&lt;br /&gt;
    local res = {}&lt;br /&gt;
&lt;br /&gt;
    if #invokedByList &amp;gt; COLLAPSE_LIST_LENGTH_THRESHOLD then&lt;br /&gt;
        table.insert( res, string.format(&lt;br /&gt;
            &amp;quot;&amp;lt;div class=&amp;#039;seealso&amp;#039;&amp;gt;&amp;#039;&amp;#039;&amp;#039;%s&amp;#039;&amp;#039;&amp;#039; is invoked by %s.&amp;lt;/div&amp;gt;&amp;quot;,&lt;br /&gt;
            moduleName,&lt;br /&gt;
            collapseList( invokedByList, &amp;#039;invokedBy&amp;#039;, &amp;#039;templates&amp;#039; )[1]&lt;br /&gt;
        ) )&lt;br /&gt;
    else&lt;br /&gt;
        for _, item in ipairs( invokedByList ) do&lt;br /&gt;
            table.insert( res, string.format(&lt;br /&gt;
                &amp;quot;&amp;lt;div class=&amp;#039;seealso&amp;#039;&amp;gt;&amp;#039;&amp;#039;&amp;#039;%s&amp;#039;s&amp;#039;&amp;#039;&amp;#039; %s.&amp;lt;/div&amp;gt;&amp;quot;,&lt;br /&gt;
                moduleName,&lt;br /&gt;
                item&lt;br /&gt;
            ) )&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if #templateData &amp;gt; 0 then&lt;br /&gt;
        moduleIsUsed = true&lt;br /&gt;
        table.insert( res, (addCategories and &amp;#039;[[Category:Template invoked modules]]&amp;#039; or &amp;#039;&amp;#039;) )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return table.concat( res )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---@param moduleName string&lt;br /&gt;
---@param addCategories boolean&lt;br /&gt;
---@param whatLinksHere string      @A list generated by a dpl of pages in the Module namespace which link to moduleName.&lt;br /&gt;
---@return string&lt;br /&gt;
local function formatRequiredByList( moduleName, addCategories, whatLinksHere )&lt;br /&gt;
    local childModuleData = arr.map( whatLinksHere, function ( title )&lt;br /&gt;
        local lists = getRequireList( title )&lt;br /&gt;
        return {name=title, requireList=lists.requireList, loadDataList=lists.loadDataList .. lists.loadJsonDataList}&lt;br /&gt;
    end )&lt;br /&gt;
&lt;br /&gt;
    local requiredByList = arr.map( childModuleData, function ( item )&lt;br /&gt;
        if arr.any( item.requireList, function(x) return x:lower()==moduleName:lower() end ) then&lt;br /&gt;
            if item.name:find( &amp;#039;%%&amp;#039; ) then&lt;br /&gt;
                return formatDynamicQueryLink( item.name )&lt;br /&gt;
            else&lt;br /&gt;
                return &amp;#039;[[&amp;#039; .. item.name .. &amp;#039;]]&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end )&lt;br /&gt;
&lt;br /&gt;
    local loadedByList = arr.map( childModuleData, function ( item )&lt;br /&gt;
        if arr.any( item.loadDataList, function(x) return x:lower()==moduleName:lower() end ) then&lt;br /&gt;
            if item.name:find( &amp;#039;%%&amp;#039; ) then&lt;br /&gt;
                return formatDynamicQueryLink( item.name )&lt;br /&gt;
            else&lt;br /&gt;
                return &amp;#039;[[&amp;#039; .. item.name .. &amp;#039;]]&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end )&lt;br /&gt;
&lt;br /&gt;
    if #requiredByList &amp;gt; 0 or #loadedByList &amp;gt; 0 then&lt;br /&gt;
        moduleIsUsed  = true&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if #requiredByList &amp;gt; COLLAPSE_LIST_LENGTH_THRESHOLD then&lt;br /&gt;
        requiredByList = collapseList( requiredByList, &amp;#039;requiredBy&amp;#039;, &amp;#039;modules&amp;#039; )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if #loadedByList &amp;gt; COLLAPSE_LIST_LENGTH_THRESHOLD then&lt;br /&gt;
        loadedByList = collapseList( loadedByList, &amp;#039;loadedBy&amp;#039;, &amp;#039;modules&amp;#039; )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local res = {}&lt;br /&gt;
&lt;br /&gt;
    for _, requiredByModuleName in ipairs( requiredByList ) do&lt;br /&gt;
        table.insert( res, string.format(&lt;br /&gt;
            &amp;quot;&amp;lt;div class=&amp;#039;seealso&amp;#039;&amp;gt;&amp;#039;&amp;#039;&amp;#039;%s&amp;#039;&amp;#039;&amp;#039; is required by %s.&amp;lt;/div&amp;gt;&amp;quot;,&lt;br /&gt;
            moduleName,&lt;br /&gt;
            requiredByModuleName&lt;br /&gt;
        ) )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if #requiredByList &amp;gt; 0 then&lt;br /&gt;
        table.insert( res, (addCategories and &amp;#039;[[Category:Modules required by modules]]&amp;#039; or &amp;#039;&amp;#039;) )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    for _, loadedByModuleName in ipairs( loadedByList ) do&lt;br /&gt;
        table.insert( res, string.format(&lt;br /&gt;
            &amp;quot;&amp;lt;div class=&amp;#039;seealso&amp;#039;&amp;gt;&amp;#039;&amp;#039;&amp;#039;%s&amp;#039;&amp;#039;&amp;#039; is loaded by %s.&amp;lt;/div&amp;gt;&amp;quot;,&lt;br /&gt;
            moduleName,&lt;br /&gt;
            loadedByModuleName&lt;br /&gt;
        ) )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if #loadedByList &amp;gt; 0 then&lt;br /&gt;
        table.insert( res, (addCategories and &amp;#039;[[Category:Module data]]&amp;#039; or &amp;#039;&amp;#039;) )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return table.concat( res )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function formatImportList( currentPageName, moduleList, id, message, category )&lt;br /&gt;
    if #moduleList &amp;gt; COLLAPSE_LIST_LENGTH_THRESHOLD then&lt;br /&gt;
        moduleList = collapseList( moduleList, id, &amp;#039;modules&amp;#039; )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local res = arr.map( moduleList, function( moduleName )&lt;br /&gt;
        return &amp;#039;&amp;lt;div class=&amp;quot;seealso&amp;quot;&amp;gt;&amp;#039; .. string.format( message, currentPageName, moduleName ) .. &amp;#039;&amp;lt;/div&amp;gt;&amp;#039;&lt;br /&gt;
    end )&lt;br /&gt;
&lt;br /&gt;
    if #moduleList &amp;gt; 0 and category then&lt;br /&gt;
        table.insert( res, string.format( &amp;#039;[[Category:%s]]&amp;#039;, category ) )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return table.concat( res )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function formatUsedTemplatesList( currentPageName, addCategories, usedTemplateList )&lt;br /&gt;
    local res = {}&lt;br /&gt;
&lt;br /&gt;
    if #usedTemplateList &amp;gt; COLLAPSE_LIST_LENGTH_THRESHOLD then&lt;br /&gt;
        usedTemplateList = collapseList( usedTemplateList, &amp;#039;usedTemplates&amp;#039;, &amp;#039;templates&amp;#039; )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    for _, templateName in ipairs( usedTemplateList ) do&lt;br /&gt;
        table.insert( res, string.format(&lt;br /&gt;
            &amp;quot;&amp;lt;div class=&amp;#039;seealso&amp;#039;&amp;gt;&amp;#039;&amp;#039;&amp;#039;%s&amp;#039;&amp;#039;&amp;#039; transcludes %s using &amp;lt;samp&amp;gt;frame:preprocess()&amp;lt;/samp&amp;gt;.&amp;lt;/div&amp;gt;&amp;quot;,&lt;br /&gt;
            currentPageName,&lt;br /&gt;
            templateName&lt;br /&gt;
        ) )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return table.concat( res )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main( frame )&lt;br /&gt;
    local args = frame:getParent().args&lt;br /&gt;
    return p._main( args[1], args.category, args.isUsed )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---@param currentPageName string|nil&lt;br /&gt;
---@param addCategories boolean|string|nil&lt;br /&gt;
---@return string&lt;br /&gt;
function p._main( currentPageName, addCategories, isUsed )&lt;br /&gt;
    libraryUtil.checkType( &amp;#039;Module:RequireList._main&amp;#039;, 1, currentPageName, &amp;#039;string&amp;#039;, true )&lt;br /&gt;
    libraryUtil.checkTypeMulti( &amp;#039;Module:RequireList._main&amp;#039;, 2, addCategories, {&amp;#039;boolean&amp;#039;, &amp;#039;string&amp;#039;, &amp;#039;nil&amp;#039;} )&lt;br /&gt;
    libraryUtil.checkTypeMulti( &amp;#039;Module:RequireList._main&amp;#039;, 3, isUsed, {&amp;#039;boolean&amp;#039;, &amp;#039;string&amp;#039;, &amp;#039;nil&amp;#039;} )&lt;br /&gt;
&lt;br /&gt;
    local title = mw.title.getCurrentTitle()&lt;br /&gt;
&lt;br /&gt;
    -- Leave early if not in module, template or calculator namespace or if module is part of exchange or data groups&lt;br /&gt;
    if param.is_empty( currentPageName ) and (&lt;br /&gt;
        ( not arr.contains( {&amp;#039;Module&amp;#039;, &amp;#039;Template&amp;#039;, &amp;#039;Calculator&amp;#039;}, title.nsText ) ) or&lt;br /&gt;
        ( title.nsText == &amp;#039;Module&amp;#039; and ( arr.contains( {&amp;#039;Exchange&amp;#039;, &amp;#039;Exchange historical&amp;#039;, &amp;#039;Data&amp;#039;}, title.text:match( &amp;#039;^(.-)/&amp;#039; ) ) ) )&lt;br /&gt;
    ) then&lt;br /&gt;
        return &amp;#039;&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    currentPageName = param.default_to( currentPageName, title.fullText )&lt;br /&gt;
    currentPageName = string.gsub( currentPageName, &amp;#039;/[Dd]oc$&amp;#039;, &amp;#039;&amp;#039; )&lt;br /&gt;
    currentPageName = formatPageName( currentPageName )&lt;br /&gt;
    addCategories = yn( param.default_to( addCategories, title.subpageText~=&amp;#039;doc&amp;#039; ) )&lt;br /&gt;
    moduleIsUsed = yn( param.default_to( isUsed, false ) )&lt;br /&gt;
&lt;br /&gt;
    if title.text:lower():find( &amp;#039;sandbox&amp;#039; ) then&lt;br /&gt;
        moduleIsUsed = true -- Don&amp;#039;t show sandbox modules as unused&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if currentPageName:find( &amp;#039;^Template:&amp;#039; ) or currentPageName:find( &amp;#039;^Calculator:&amp;#039; ) then&lt;br /&gt;
        local invokeList = getInvokeCallList( currentPageName )&lt;br /&gt;
        return formatInvokeCallList(currentPageName, addCategories, invokeList)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local whatTemplatesLinkHere, whatModulesLinkHere = dpl.ask( {&lt;br /&gt;
        namespace = &amp;#039;Template|Calculator&amp;#039;,&lt;br /&gt;
        linksto = currentPageName,&lt;br /&gt;
        distinct = &amp;#039;strict&amp;#039;,&lt;br /&gt;
        ignorecase = true,&lt;br /&gt;
        ordermethod = &amp;#039;title&amp;#039;,&lt;br /&gt;
        allowcachedresults = true,&lt;br /&gt;
        cacheperiod = 604800 -- One week&lt;br /&gt;
    }, {&lt;br /&gt;
        namespace = &amp;#039;Module&amp;#039;,&lt;br /&gt;
        linksto = currentPageName,&lt;br /&gt;
        nottitlematch = &amp;#039;%/doc|Exchange/%|Exchange historical/%|Data/%|&amp;#039; .. currentPageName:gsub( &amp;#039;Module:&amp;#039;, &amp;#039;&amp;#039; ),&lt;br /&gt;
        distinct = &amp;#039;strict&amp;#039;,&lt;br /&gt;
        ignorecase = true,&lt;br /&gt;
        ordermethod = &amp;#039;title&amp;#039;,&lt;br /&gt;
        allowcachedresults = true,&lt;br /&gt;
        cacheperiod = 604800 -- One week&lt;br /&gt;
    } )&lt;br /&gt;
&lt;br /&gt;
    local lists = getRequireList( currentPageName, true )&lt;br /&gt;
&lt;br /&gt;
    local requireList = arr.map( lists.requireList, function ( moduleName )&lt;br /&gt;
        if moduleName:find( &amp;#039;%%&amp;#039; ) then&lt;br /&gt;
            return formatDynamicQueryLink( moduleName )&lt;br /&gt;
        elseif builtins[moduleName] then&lt;br /&gt;
            return &amp;#039;[[&amp;#039; .. builtins[moduleName].link .. &amp;#039;|&amp;#039; .. moduleName .. &amp;#039;]]&amp;#039;&lt;br /&gt;
        else&lt;br /&gt;
            return &amp;#039;[[&amp;#039; .. moduleName .. &amp;#039;]]&amp;#039;&lt;br /&gt;
        end&lt;br /&gt;
    end )&lt;br /&gt;
&lt;br /&gt;
    local loadDataList = arr.map( lists.loadDataList, function ( moduleName )&lt;br /&gt;
        if moduleName:find( &amp;#039;%%&amp;#039; ) then&lt;br /&gt;
            return formatDynamicQueryLink( moduleName )&lt;br /&gt;
        else&lt;br /&gt;
            return &amp;#039;[[&amp;#039; .. moduleName .. &amp;#039;]]&amp;#039;&lt;br /&gt;
        end&lt;br /&gt;
    end )&lt;br /&gt;
&lt;br /&gt;
    local loadJsonDataList = arr.map( lists.loadJsonDataList, function ( moduleName )&lt;br /&gt;
        if moduleName:find( &amp;#039;%%&amp;#039; ) then&lt;br /&gt;
            return formatDynamicQueryLink( moduleName )&lt;br /&gt;
        else&lt;br /&gt;
            return &amp;#039;[[&amp;#039; .. moduleName .. &amp;#039;]]&amp;#039;&lt;br /&gt;
        end&lt;br /&gt;
    end )&lt;br /&gt;
&lt;br /&gt;
    local usedTemplateList = arr.map( lists.usedTemplateList, function( templateName )&lt;br /&gt;
        if string.find( templateName, &amp;#039;:&amp;#039; ) then -- Real templates are prefixed by a namespace, magic words are not&lt;br /&gt;
            return &amp;#039;[[&amp;#039;..templateName..&amp;#039;]]&amp;#039;&lt;br /&gt;
        else&lt;br /&gt;
            return &amp;quot;&amp;#039;&amp;#039;&amp;#039;&amp;amp;#123;&amp;amp;#123;&amp;quot;..templateName..&amp;quot;&amp;amp;#125;&amp;amp;#125;&amp;#039;&amp;#039;&amp;#039;&amp;quot; -- Magic words don&amp;#039;t have a page so make them bold instead&lt;br /&gt;
        end&lt;br /&gt;
    end )&lt;br /&gt;
&lt;br /&gt;
    local res = {}&lt;br /&gt;
&lt;br /&gt;
    table.insert( res, formatInvokedByList( currentPageName, addCategories, whatTemplatesLinkHere ) )&lt;br /&gt;
    table.insert( res, formatImportList( currentPageName, requireList, &amp;#039;require&amp;#039;, &amp;quot;&amp;#039;&amp;#039;&amp;#039;%s&amp;#039;&amp;#039;&amp;#039; requires %s.&amp;quot;, addCategories and &amp;#039;Modules requiring modules&amp;#039; ) )&lt;br /&gt;
    table.insert( res, formatImportList( currentPageName, loadDataList, &amp;#039;loadData&amp;#039;, &amp;quot;&amp;#039;&amp;#039;&amp;#039;%s&amp;#039;&amp;#039;&amp;#039; loads data from %s.&amp;quot;, addCategories and &amp;#039;Modules using data&amp;#039; ) )&lt;br /&gt;
    table.insert( res, formatImportList( currentPageName, loadJsonDataList, &amp;#039;loadJsonData&amp;#039;, &amp;quot;&amp;#039;&amp;#039;&amp;#039;%s&amp;#039;&amp;#039;&amp;#039; loads data from %s.&amp;quot;, addCategories and &amp;#039;Modules using data&amp;#039; ) )&lt;br /&gt;
    table.insert( res, formatUsedTemplatesList( currentPageName, addCategories, usedTemplateList ) )&lt;br /&gt;
    table.insert( res, formatRequiredByList( currentPageName, addCategories, whatModulesLinkHere ) )&lt;br /&gt;
&lt;br /&gt;
    if addCategories then&lt;br /&gt;
        local extraCategories = arr.map( lists.extraCategories, function( categoryName )&lt;br /&gt;
            return &amp;quot;[[Category:&amp;quot; .. categoryName .. &amp;quot;]]&amp;quot;&lt;br /&gt;
        end )&lt;br /&gt;
&lt;br /&gt;
        table.insert( res, table.concat( extraCategories ) )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if not moduleIsUsed then&lt;br /&gt;
        table.insert( res, 1, messageBoxUnused( currentPageName:gsub( &amp;#039;Module:&amp;#039;, &amp;#039;&amp;#039; ), addCategories ) )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return table.concat( res )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Fantastic</name></author>
	</entry>
</feed>