<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://the.satanic.wiki/index.php?action=history&amp;feed=atom&amp;title=Module%3AFrameTools</id>
	<title>Module:FrameTools - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://the.satanic.wiki/index.php?action=history&amp;feed=atom&amp;title=Module%3AFrameTools"/>
	<link rel="alternate" type="text/html" href="https://the.satanic.wiki/index.php?title=Module:FrameTools&amp;action=history"/>
	<updated>2026-04-20T00:17:53Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://the.satanic.wiki/index.php?title=Module:FrameTools&amp;diff=10908&amp;oldid=prev</id>
		<title>WikiGOD: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="https://the.satanic.wiki/index.php?title=Module:FrameTools&amp;diff=10908&amp;oldid=prev"/>
		<updated>2021-04-30T02:23:55Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported&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 02:23, 30 April 2021&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;4&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;!-- diff cache key zzegtzyr_mw19226-mwjf_:diff:1.41:old-10907:rev-10908 --&gt;
&lt;/table&gt;</summary>
		<author><name>WikiGOD</name></author>
	</entry>
	<entry>
		<id>https://the.satanic.wiki/index.php?title=Module:FrameTools&amp;diff=10907&amp;oldid=prev</id>
		<title>Mediawiki&gt;ExE Boss: Hoist type checks to function start</title>
		<link rel="alternate" type="text/html" href="https://the.satanic.wiki/index.php?title=Module:FrameTools&amp;diff=10907&amp;oldid=prev"/>
		<updated>2021-04-24T15:48:20Z</updated>

		<summary type="html">&lt;p&gt;Hoist type checks to function start&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;-- &amp;lt;nowiki&amp;gt;&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- This module contains helper functions for dealing with frame objects.&lt;br /&gt;
--&lt;br /&gt;
-- @script frameTools&lt;br /&gt;
-- @alias p&lt;br /&gt;
-- @author [[User:DarthKitty]]&lt;br /&gt;
-- @author [[User:Dessamator]]&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
local p = {}&lt;br /&gt;
local util = require &amp;quot;libraryUtil&amp;quot;&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Frame methods are protected by a `checkSelf` function, which makes them more&lt;br /&gt;
-- difficult to copy.&lt;br /&gt;
--&lt;br /&gt;
-- @param {Frame|PseudoFrame} frame&lt;br /&gt;
--        The frame of pseudo-frame to copy.&lt;br /&gt;
-- @return {PseudoFrame}&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
function p.copy(frame)&lt;br /&gt;
    util.checkType(&amp;quot;frameTools.copy&amp;quot;, 1, frame, &amp;quot;table&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    local copy = mw.clone(frame)&lt;br /&gt;
&lt;br /&gt;
    -- Point methods on `copy` to their `frame` counterparts&lt;br /&gt;
    for methodName, method in pairs(frame) do&lt;br /&gt;
        if type(method) == &amp;quot;function&amp;quot; and methodName ~= &amp;quot;getParent&amp;quot; then&lt;br /&gt;
            copy[methodName] = function (copy, ...)&lt;br /&gt;
                return method(frame, ...)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- This method needs special treatment&lt;br /&gt;
    function copy:getParent()&lt;br /&gt;
        local parent = frame:getParent()&lt;br /&gt;
&lt;br /&gt;
        if parent then&lt;br /&gt;
            return p.copy(parent)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return copy&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Creates a pseudo frame with some useful functions available in&lt;br /&gt;
-- [[mw:Extension:Scribunto]], e.g. `newChild`.&lt;br /&gt;
--&lt;br /&gt;
-- @param[opt] {Frame} frame&lt;br /&gt;
--             The frame that provides implementatinos for the `preprocess` method.&lt;br /&gt;
-- @param[opt] {table} parentArgs&lt;br /&gt;
--             The parameters available on `pseudoFrame:getParent().args`&lt;br /&gt;
-- @param[opt] {table} childArgs&lt;br /&gt;
--             The parameters available on `pseudoFrame.args`&lt;br /&gt;
-- @return {PseudoFrame}&lt;br /&gt;
--         The new pseudo-Frame&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
function p.makePseudoFrame(frame, parentArgs, childArgs)&lt;br /&gt;
    util.checkType(&amp;quot;frameTools.makePseudoFrame&amp;quot;, 1, frame, &amp;quot;table&amp;quot;, true)&lt;br /&gt;
    util.checkType(&amp;quot;frameTools.makePseudoFrame&amp;quot;, 2, parentArgs, &amp;quot;table&amp;quot;, true)&lt;br /&gt;
    util.checkType(&amp;quot;frameTools.makePseudoFrame&amp;quot;, 3, childArgs, &amp;quot;table&amp;quot;, true)&lt;br /&gt;
&lt;br /&gt;
    local pseudoFrame = {parent = {}}&lt;br /&gt;
    local checkSelf = util.makeCheckSelfFunction(&amp;quot;pseudoFrame&amp;quot;, &amp;quot;frame&amp;quot;, pseudoFrame, &amp;quot;PseudoFrame object&amp;quot;)&lt;br /&gt;
    local parentFrame = pseudoFrame.parent&lt;br /&gt;
    local checkSelfParent = util.makeCheckSelfFunction(&amp;quot;pseudoFrame&amp;quot;, &amp;quot;frame&amp;quot;, parentFrame, &amp;quot;parent PseudoFrame object&amp;quot;)&lt;br /&gt;
    local pArgs = {}&lt;br /&gt;
    local pTitle&lt;br /&gt;
    local args = {}&lt;br /&gt;
&lt;br /&gt;
    if frame then&lt;br /&gt;
        args = frame.args&lt;br /&gt;
&lt;br /&gt;
        for name in pairs(frame) do&lt;br /&gt;
            pseudoFrame[name] = function (pseudoFrame, ...)&lt;br /&gt;
                return frame[name](frame, ...)&lt;br /&gt;
            end&lt;br /&gt;
&lt;br /&gt;
            parentFrame[name] = function (parent, ...)&lt;br /&gt;
                return pseudoFrame[name](frame, ...)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        if type(frame.getParent) == &amp;quot;function&amp;quot; and frame:getParent() then&lt;br /&gt;
            pArgs = frame:getParent().args&lt;br /&gt;
            pTitle = frame:getParent():getTitle()&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    parentFrame.args = mw.clone(parentArgs or pArgs)&lt;br /&gt;
    pseudoFrame.args = mw.clone(childArgs or args)&lt;br /&gt;
    pseudoFrame.title = mw.title.getCurrentTitle().text&lt;br /&gt;
    parentFrame.title = pTitle or &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    function pseudoFrame:getTitle()&lt;br /&gt;
        checkSelf(self, &amp;quot;getTitle&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        return self.title&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    function parentFrame:getTitle()&lt;br /&gt;
        checkSelfParent(self, &amp;quot;getTitle&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        return self.title&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    function pseudoFrame:getParent()&lt;br /&gt;
        checkSelf(self, &amp;quot;getParent&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        return self.parent&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    function parentFrame:getParent()&lt;br /&gt;
        checkSelfParent(self, &amp;quot;getParent&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        return self.parent&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Creates a new Frame object that is a child of the current frame, optional&lt;br /&gt;
    -- arguments and title.&lt;br /&gt;
    -- Syntax: frame:newChild{title = title, args = table}&lt;br /&gt;
    function pseudoFrame:newChild(attributes)&lt;br /&gt;
        checkSelf(self, &amp;quot;newChild&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        local tmpTable = p.makePseudoFrame(frame, self.args, attributes.args)&lt;br /&gt;
&lt;br /&gt;
        tmpTable.parent.title = self.title&lt;br /&gt;
        tmpTable.title = attributes.title&lt;br /&gt;
&lt;br /&gt;
        return tmpTable&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    function pseudoFrame:showargs()&lt;br /&gt;
        checkSelf(self, &amp;quot;showargs&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        local childParams = &amp;quot;Child parameters:\nKey \t Value&amp;quot;&lt;br /&gt;
        local parentParams = &amp;quot;Parent parameters:\nKey \t Value&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        if self.args then&lt;br /&gt;
            for k, v in pairs(self.args) do&lt;br /&gt;
                childParams = childParams .. &amp;quot;\n&amp;quot; .. k .. &amp;quot;\t&amp;quot; .. v&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        if self.parent.args then&lt;br /&gt;
            for k, v in pairs(self.parent.args) do&lt;br /&gt;
                parentParams = parentParams .. &amp;quot;\n&amp;quot; .. k .. &amp;quot;\t&amp;quot; .. v&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        return childParams .. &amp;quot;\n\n&amp;quot; .. parentParams&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    function pseudoFrame:setArgs(childArgs, parentArgs)&lt;br /&gt;
        checkSelf(self, &amp;quot;setArgs&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        if childArgs then&lt;br /&gt;
            self.args = childArgs or {}&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        if parentArgs then&lt;br /&gt;
           self.parent.args = parentArgs&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local function preprocessMock(parent) return function(self, opt)&lt;br /&gt;
        if parent then&lt;br /&gt;
            checkSelfParent(self, &amp;quot;expandTemplate&amp;quot;)&lt;br /&gt;
        else&lt;br /&gt;
            checkSelf(self, &amp;quot;expandTemplate&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        local text&lt;br /&gt;
        if type(opt) == &amp;quot;table&amp;quot; then&lt;br /&gt;
            text = opt.text&lt;br /&gt;
        else&lt;br /&gt;
            text = opt&lt;br /&gt;
        end&lt;br /&gt;
        text = tostring(text)&lt;br /&gt;
&lt;br /&gt;
        return text&lt;br /&gt;
    end end&lt;br /&gt;
    if not pseudoFrame.preprocess then&lt;br /&gt;
        pseudoFrame.preprocess = preprocessMock()&lt;br /&gt;
    end&lt;br /&gt;
    if not pseudoFrame.parent.preprocess then&lt;br /&gt;
        pseudoFrame.parent.preprocess = preprocessMock(&amp;quot;parent&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local function expandTemplateMock(parent) return function(self, opt)&lt;br /&gt;
        if parent then&lt;br /&gt;
            checkSelfParent(self, &amp;quot;expandTemplate&amp;quot;)&lt;br /&gt;
        else&lt;br /&gt;
            checkSelf(self, &amp;quot;expandTemplate&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        if type(opt) ~= &amp;quot;table&amp;quot; then&lt;br /&gt;
            error(&amp;quot;frame:expandTemplate: the first parameter must be a table&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        local title&lt;br /&gt;
        if opt.title == nil then&lt;br /&gt;
            error(&amp;quot;frame:expandTemplate: a title is required&amp;quot;)&lt;br /&gt;
        else&lt;br /&gt;
            title = tostring(opt.title)&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        local args&lt;br /&gt;
        if opt.args == nil then&lt;br /&gt;
            args = {}&lt;br /&gt;
        elseif type(opt.args) == &amp;quot;table&amp;quot; then&lt;br /&gt;
            args = opt.args&lt;br /&gt;
        else&lt;br /&gt;
            error(&amp;quot;frame:expandTitle: args must be a table&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        local keys = {}&lt;br /&gt;
        for k in pairs(args) do&lt;br /&gt;
            table.insert(keys, k)&lt;br /&gt;
        end&lt;br /&gt;
        table.sort(keys)&lt;br /&gt;
&lt;br /&gt;
        local text = {}&lt;br /&gt;
        table.insert(text, &amp;quot;{{&amp;quot; .. title)&lt;br /&gt;
        local anonymous_index = 0&lt;br /&gt;
        for _, k in ipairs(keys) do&lt;br /&gt;
            table.insert(text, &amp;quot;|&amp;quot; .. (tonumber(k) == (anonymous_index + 1) and &amp;quot;&amp;quot; or (&amp;quot; &amp;quot; .. k .. &amp;quot; = &amp;quot;)) .. args[k])&lt;br /&gt;
            if tonumber(k) == (anonymous_index + 1) then anonymous_index = anonymous_index + 1 end&lt;br /&gt;
        end&lt;br /&gt;
        table.insert(text, &amp;quot;}}&amp;quot;)&lt;br /&gt;
        text = table.concat(text, &amp;#039;\n&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
        return text&lt;br /&gt;
    end end&lt;br /&gt;
&lt;br /&gt;
    if not pseudoFrame.expandTemplate then&lt;br /&gt;
        pseudoFrame.expandTemplate = expandTemplateMock()&lt;br /&gt;
    end&lt;br /&gt;
    if not parentFrame.expandTemplate then&lt;br /&gt;
        parentFrame.expandTemplate = expandTemplateMock(&amp;quot;parent&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if mw.getCurrentFrame() == nil then&lt;br /&gt;
        _G.mw.getCurrentFrame = function() return pseudoFrame end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return pseudoFrame&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Returns a frame-like object with the given arguments removed.&lt;br /&gt;
--&lt;br /&gt;
-- @param {Frame|PseudoFrame} frame&lt;br /&gt;
--        The Frame to copy&lt;br /&gt;
-- @param[opt] ...&lt;br /&gt;
--             The arguments to omit from the new `Frame`&amp;#039;s `args` property&lt;br /&gt;
-- @return {PseudoFrame}&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
function p.removeArgs(frame, ...)&lt;br /&gt;
    util.checkType(&amp;quot;frameTools.removeArgs&amp;quot;, 1, frame, &amp;quot;table&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    local pseudoFrame = p.copy(frame)&lt;br /&gt;
    local args = pseudoFrame.args&lt;br /&gt;
    local metatable = getmetatable(args)&lt;br /&gt;
&lt;br /&gt;
    -- disable arg caching&lt;br /&gt;
    metatable.__index = nil&lt;br /&gt;
    metatable.__pairs = nil&lt;br /&gt;
&lt;br /&gt;
    -- remove args&lt;br /&gt;
    for _, arg in ipairs{...} do&lt;br /&gt;
        args[arg] = nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return pseudoFrame&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- A frame-like object that provides mock implementations for the most common&lt;br /&gt;
-- @{Frame|mw.frame} instance methods and properties&lt;br /&gt;
--&lt;br /&gt;
-- @type {Frame} PseudoFrame&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
return p&lt;br /&gt;
&lt;br /&gt;
-- &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
-- (Add categories here.)&lt;/div&gt;</summary>
		<author><name>Mediawiki&gt;ExE Boss</name></author>
	</entry>
</feed>