<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://horizonffxi.wiki/w/index.php?action=history&amp;feed=atom&amp;title=Module%3AArguments</id>
	<title>Module:Arguments - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://horizonffxi.wiki/w/index.php?action=history&amp;feed=atom&amp;title=Module%3AArguments"/>
	<link rel="alternate" type="text/html" href="https://horizonffxi.wiki/w/index.php?title=Module:Arguments&amp;action=history"/>
	<updated>2026-04-05T11:56:56Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.39.10</generator>
	<entry>
		<id>https://horizonffxi.wiki/w/index.php?title=Module:Arguments&amp;diff=10208&amp;oldid=prev</id>
		<title>Hugin at 19:04, 30 May 2023</title>
		<link rel="alternate" type="text/html" href="https://horizonffxi.wiki/w/index.php?title=Module:Arguments&amp;diff=10208&amp;oldid=prev"/>
		<updated>2023-05-30T19:04:15Z</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:04, 30 May 2023&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-l31&quot;&gt;Line 31:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 31:&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;br/&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;br/&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;--  Module dependencies.&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;--  Module dependencies.&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;local i18n = require(&amp;#039;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Dev&lt;/del&gt;:I18n&amp;#039;).loadMessages(&amp;#039;Arguments&amp;#039;)&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;local i18n = require(&amp;#039;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Module&lt;/ins&gt;:I18n&amp;#039;).loadMessages(&amp;#039;Arguments&amp;#039;)&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;local util = require(&amp;#039;libraryUtil&amp;#039;)&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;local util = require(&amp;#039;libraryUtil&amp;#039;)&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;local checkType = util.checkType&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;local checkType = util.checkType&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key horizon_wiki:diff::1.12:old-10207:rev-10208 --&gt;
&lt;/table&gt;</summary>
		<author><name>Hugin</name></author>
	</entry>
	<entry>
		<id>https://horizonffxi.wiki/w/index.php?title=Module:Arguments&amp;diff=10207&amp;oldid=prev</id>
		<title>Hugin: Created page with &quot;--- Arguments invocation argument extractor for Scribunto modules. --  It is intended for use by other Lua modules, and should not be --  called from an invocation (`#invoke`) directly. --   --  This module supports the following features: --   * Trimming and blank argument removal. --   * Argument inheritance between child and parent frames. --   * Argument extraction for external modules and console input. --   * Options to customise argument extraction behaviour. --...&quot;</title>
		<link rel="alternate" type="text/html" href="https://horizonffxi.wiki/w/index.php?title=Module:Arguments&amp;diff=10207&amp;oldid=prev"/>
		<updated>2023-05-30T19:03:24Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;--- Arguments invocation argument extractor for Scribunto modules. --  It is intended for use by other Lua modules, and should not be --  called from an invocation (`#invoke`) directly. --   --  This module supports the following features: --   * Trimming and blank argument removal. --   * Argument inheritance between child and parent frames. --   * Argument extraction for external modules and console input. --   * Options to customise argument extraction behaviour. --...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;--- Arguments invocation argument extractor for Scribunto modules.&lt;br /&gt;
--  It is intended for use by other Lua modules, and should not be&lt;br /&gt;
--  called from an invocation (`#invoke`) directly.&lt;br /&gt;
--  &lt;br /&gt;
--  This module supports the following features:&lt;br /&gt;
--   * Trimming and blank argument removal.&lt;br /&gt;
--   * Argument inheritance between child and parent frames.&lt;br /&gt;
--   * Argument extraction for external modules and console input.&lt;br /&gt;
--   * Options to customise argument extraction behaviour.&lt;br /&gt;
--  &lt;br /&gt;
--  @script             arguments&lt;br /&gt;
--  @release            stable&lt;br /&gt;
--  @note               The `args` table from the @{arguments.getArgs}&lt;br /&gt;
--                      function is a metatable for performance reasons.&lt;br /&gt;
--                      Thus, the table will not permit Lua table methods&lt;br /&gt;
--                      such as `#args`, @{next|next(args)}, and @{table}&lt;br /&gt;
--                      library functions.&lt;br /&gt;
--  @note               This module will eventually be adapted as a&lt;br /&gt;
--                      library in [[mw:gerrit:q/158323|MediaWiki&lt;br /&gt;
--                      core]], called as `require(&amp;#039;getArgs&amp;#039;)`. The core&lt;br /&gt;
--                      library will remove `options.parentOnly`.&lt;br /&gt;
--  @author             [[wikipedia:User:Mr. Stradivarius|Mr. Stradivarius]] (Wikipedia)&lt;br /&gt;
--  @author             [[wikipedia:User:Anomie|Anomie]] (Wikipedia)&lt;br /&gt;
--  @author             [[wikipedia:User:Jackmcbarn|Jackmcbarn]] (Wikipedia)&lt;br /&gt;
--  @author             [[User:Dessamator|Dessamator]]&lt;br /&gt;
--  @author             [[User:DarthKitty|DarthKitty]]&lt;br /&gt;
--  @attribution        [[wikipedia:Module:Arguments|Module:Arguments]] (Wikipedia)&lt;br /&gt;
--  @see                [[wikipedia:Module:Arguments|Original module on Wikipedia]]&lt;br /&gt;
--  @see                [[Module:Arguments/testcases|Test cases for this module]]&lt;br /&gt;
local arguments = {}&lt;br /&gt;
&lt;br /&gt;
--  Module dependencies.&lt;br /&gt;
local i18n = require(&amp;#039;Dev:I18n&amp;#039;).loadMessages(&amp;#039;Arguments&amp;#039;)&lt;br /&gt;
local util = require(&amp;#039;libraryUtil&amp;#039;)&lt;br /&gt;
local checkType = util.checkType&lt;br /&gt;
&lt;br /&gt;
-- Four different value tidying functions.&lt;br /&gt;
-- This way, we don&amp;#039;t have to check the options every time we call them.&lt;br /&gt;
&lt;br /&gt;
--- Default value tidying function.&lt;br /&gt;
--  Trims parameter values automatically if they are defined strings.&lt;br /&gt;
--  Treats blank strings as `nil`.&lt;br /&gt;
--  @function           tidyValDefault&lt;br /&gt;
--  @param              {string|number} key MediaWiki parameter key.&lt;br /&gt;
--  @param              {string|nil} val MediaWiki parameter value,&lt;br /&gt;
--                      or nil if `key` is an empty string or nil.&lt;br /&gt;
--  @local&lt;br /&gt;
local function tidyValDefault(key, val)&lt;br /&gt;
    if type(val) == &amp;#039;string&amp;#039; then&lt;br /&gt;
        val = val:match(&amp;#039;^%s*(.-)%s*$&amp;#039;)&lt;br /&gt;
        if val == &amp;#039;&amp;#039; then&lt;br /&gt;
            return nil&lt;br /&gt;
        else&lt;br /&gt;
            return val&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        return val&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Value tidying function that trims values.&lt;br /&gt;
--  Trims parameter values automatically if they are defined strings.&lt;br /&gt;
--  @function           tidyValTrimOnly&lt;br /&gt;
--  @param              {string|number} key MediaWiki parameter key.&lt;br /&gt;
--  @param              {string|nil} val MediaWiki parameter value.&lt;br /&gt;
--  @local&lt;br /&gt;
local function tidyValTrimOnly(key, val)&lt;br /&gt;
    if type(val) == &amp;#039;string&amp;#039; then&lt;br /&gt;
        return val:match(&amp;#039;^%s*(.-)%s*$&amp;#039;)&lt;br /&gt;
    else&lt;br /&gt;
        return val&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Value tidying function that removes blanks.&lt;br /&gt;
--  Removes blank values from the arguments table.&lt;br /&gt;
--  @function           tidyValRemoveBlanksOnly&lt;br /&gt;
--  @param              {string|number} key MediaWiki parameter key.&lt;br /&gt;
--  @param              {string|nil} val MediaWiki parameter value,&lt;br /&gt;
--                      or nil if `key` is whitespace or nil.&lt;br /&gt;
--  @local&lt;br /&gt;
local function tidyValRemoveBlanksOnly(key, val)&lt;br /&gt;
    if type(val) == &amp;#039;string&amp;#039; then&lt;br /&gt;
        if val:find(&amp;#039;%S&amp;#039;) then&lt;br /&gt;
            return val&lt;br /&gt;
        else&lt;br /&gt;
            return nil&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        return val&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Value tidying function that returns original value.&lt;br /&gt;
--  Effectively a NOOP function that does no value processing.&lt;br /&gt;
--  @function           tidyValNoChange&lt;br /&gt;
--  @param              {string|number} key MediaWiki parameter key.&lt;br /&gt;
--  @param              {string|nil} val MediaWiki parameter value.&lt;br /&gt;
--  @local&lt;br /&gt;
local function tidyValNoChange(key, val)&lt;br /&gt;
    return val&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Parent template title match checker.&lt;br /&gt;
--  @function           matchesTitle&lt;br /&gt;
--  @param              {string|number|nil} given Local prefixed page&lt;br /&gt;
--                      title, or MediaWiki article ID (`wgArticleId`).&lt;br /&gt;
--  @param              {string} title Title of parent template.&lt;br /&gt;
--  @return             {boolean} Whether the `given` ID/title matches&lt;br /&gt;
--                      the title of the parent template.&lt;br /&gt;
local function matchesTitle(given, title)&lt;br /&gt;
    local tp = type( given )&lt;br /&gt;
    return (tp == &amp;#039;string&amp;#039; or tp == &amp;#039;number&amp;#039;) and mw.title.new( given ).prefixedText == title&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Default argument translation metatable.&lt;br /&gt;
--  @table              translate_mt&lt;br /&gt;
--  @local&lt;br /&gt;
local translate_mt = { __index = function(t, k) return k end }&lt;br /&gt;
&lt;br /&gt;
--- Main argument extraction utility.&lt;br /&gt;
--  Arguments are memoized once fetched for optimal performance,&lt;br /&gt;
--  as with the `frame.args` metatable in Scribunto core.&lt;br /&gt;
--  &lt;br /&gt;
--  The default argument lookup behaviour uses the child frame arguments&lt;br /&gt;
--  first, then the parent frame arguments. There are numerous frame&lt;br /&gt;
--  options to change this behaviour.&lt;br /&gt;
--  &lt;br /&gt;
--  The default value tidying behaviour trims parameter values if they&lt;br /&gt;
--  are defined strings and treats blank strings as `nil`. This can be&lt;br /&gt;
--  customised in the `getArgs` options.&lt;br /&gt;
--  &lt;br /&gt;
--  @param              {frame|table} frame Scribunto frame object or&lt;br /&gt;
--                      Lua arguments table, passed from an invocation&lt;br /&gt;
--                      or Lua logic such as `frame:getParent()`.&lt;br /&gt;
--                      If this parameter does not have an `args` field&lt;br /&gt;
--                      and a `getParent` method, `frame` is assumed&lt;br /&gt;
--                      to be a Lua arguments table, such as the&lt;br /&gt;
--                      arguments from a named arguments call.&lt;br /&gt;
--  @param[opt]         {table} options Extraction/processing options.&lt;br /&gt;
--  @param[opt]         {boolean} options.trim&lt;br /&gt;
--                      Whether to trim the blank arguments present in&lt;br /&gt;
--                      the arguments table. Accepts `false` only.&lt;br /&gt;
--                      Default: `true`.&lt;br /&gt;
--  @param[opt]         {boolean} options.removeBlanks&lt;br /&gt;
--                      Whether to remove blank arguments from the&lt;br /&gt;
--                      arguments table. Does not shift sequential&lt;br /&gt;
--                      arguments removed by the processing stage.&lt;br /&gt;
--                      Accepts `false` only. Default: `true`.&lt;br /&gt;
--  @param[opt]         {function} options.valueFunc&lt;br /&gt;
--                      Custom value tidying function for use if the&lt;br /&gt;
--                      `trim` and `removeBlanks` options don&amp;#039;t cover&lt;br /&gt;
--                      the developer&amp;#039;s argument processing use case.&lt;br /&gt;
--  @param[opt]         {boolean} options.frameOnly&lt;br /&gt;
--                      Only read arguments from child frame (the&lt;br /&gt;
--                      `frame` parameter - usually invocation frame).&lt;br /&gt;
--  @param[opt]         {boolean} options.parentOnly&lt;br /&gt;
--                      Only read arguments from `frame` parent (the&lt;br /&gt;
--                      `frame` parameter - usually template frame).&lt;br /&gt;
--  @param[opt]         {boolean} options.parentFirst&lt;br /&gt;
--                      Argument lookup in the `frame` parent first,&lt;br /&gt;
--                      prioritised over the invocation frame arguments.&lt;br /&gt;
--  @param[opt]         {table} options.wrappers&lt;br /&gt;
--                      Individual value or array of values, listing&lt;br /&gt;
--                      wrapper title name(s) or article ID(s) to permit&lt;br /&gt;
--                      parent argument lookup from.&lt;br /&gt;
--  @param[opt]         {string|number} options.wrapper&lt;br /&gt;
--                      Alias of `options.wrappers` - contains title&lt;br /&gt;
--                      name or article ID to permit parent argument&lt;br /&gt;
--                      lookup from.&lt;br /&gt;
--  @param[opt]         {boolean} options.readOnly&lt;br /&gt;
--                      Whether to restrict write permissions to the&lt;br /&gt;
--                      arguments table. When set to a truthy value,&lt;br /&gt;
--                      an error will be thrown on any write attempt.&lt;br /&gt;
--  @param[opt]         {boolean} options.noOverwrite&lt;br /&gt;
--                      Whether to restrict overwrite attempts on&lt;br /&gt;
--                      existing argument keys in the arguments table.&lt;br /&gt;
--                      When set to a truthy value, an error will be&lt;br /&gt;
--                      thrown on any write attempt that would result&lt;br /&gt;
--                      in an existing argument being overwritten.&lt;br /&gt;
--  @param[opt]         {table} options.translate&lt;br /&gt;
--                      Map of parameter name aliases to their canonical&lt;br /&gt;
--                      argument parameter names.&lt;br /&gt;
--  @param[opt]         {table} options.backtranslate&lt;br /&gt;
--                      Map of canonical parameter names to their&lt;br /&gt;
--                      argument parameter aliases.&lt;br /&gt;
--                      Supersedes `options.translate` if both options&lt;br /&gt;
--                      are in use.&lt;br /&gt;
--  @error[opt,317]     &amp;#039;bad value assigned to option &amp;quot;valueFunc&amp;quot;&lt;br /&gt;
--                      (function expected, got $type)&amp;#039;&lt;br /&gt;
--  @error[opt,407]     &amp;#039;could not write to argument table key &amp;quot;$key&amp;quot;;&lt;br /&gt;
--                      the table is read-only&amp;#039;&lt;br /&gt;
--  @error[opt,409]     &amp;#039;could not write to argument table key &amp;quot;$key&amp;quot;;&lt;br /&gt;
--                      overwriting existing arguments is not permitted&amp;#039;&lt;br /&gt;
--  @return             {table} Arguments extracted from invocation.&lt;br /&gt;
--                      The argument data is embedded as a metatable in&lt;br /&gt;
--                      the exported table and cannot be accessed with&lt;br /&gt;
--                      the `#` operator or @{table} library methods.&lt;br /&gt;
--                      However, the exported table can be written to if&lt;br /&gt;
--                      the `options.readOnly` flag parameter is not&lt;br /&gt;
--                      truthy.&lt;br /&gt;
--  @usage&lt;br /&gt;
--      &lt;br /&gt;
--      local getArgs = require(&amp;#039;Module:Arguments&amp;#039;).getArgs&lt;br /&gt;
--      function p.main(frame)&lt;br /&gt;
--          local args = getArgs(frame, {&lt;br /&gt;
--              wrapper = &amp;#039;Template:&amp;lt;TEMPLATE&amp;gt;&amp;#039;&lt;br /&gt;
--          })&lt;br /&gt;
--          -- Use the args table here.&lt;br /&gt;
--          -- A common paradigm is `return p._main(args)`.&lt;br /&gt;
--          -- This allows other Lua modules to access the&lt;br /&gt;
--          -- main logic in a performant manner without a&lt;br /&gt;
--          -- frame object.&lt;br /&gt;
--      end&lt;br /&gt;
--      &lt;br /&gt;
--  @note               Reference tags in the form of `&amp;lt;ref&amp;gt;` will&lt;br /&gt;
--                      generate phantom references when calling the&lt;br /&gt;
--                      @{pairs} iterator on the arguments table,&lt;br /&gt;
--                      **IF** the `&amp;lt;ref&amp;gt;` tag does not appear in the&lt;br /&gt;
--                      dependent module&amp;#039;s wikitext output.&lt;br /&gt;
function arguments.getArgs(frame, options)&lt;br /&gt;
    checkType(&amp;#039;getArgs&amp;#039;, 1, frame, &amp;#039;table&amp;#039;, true)&lt;br /&gt;
    checkType(&amp;#039;getArgs&amp;#039;, 2, options, &amp;#039;table&amp;#039;, true)&lt;br /&gt;
    frame = frame or {}&lt;br /&gt;
    options = options or {}&lt;br /&gt;
&lt;br /&gt;
    -- Set up argument translation.&lt;br /&gt;
    options.translate = options.translate or {}&lt;br /&gt;
    if getmetatable(options.translate) == nil then&lt;br /&gt;
        setmetatable(options.translate, translate_mt)&lt;br /&gt;
    end&lt;br /&gt;
    if options.backtranslate == nil then&lt;br /&gt;
        options.backtranslate = {}&lt;br /&gt;
        for k,v in pairs(options.translate) do&lt;br /&gt;
            options.backtranslate[v] = k&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if options.backtranslate and getmetatable(options.backtranslate) == nil then&lt;br /&gt;
        setmetatable(options.backtranslate, {&lt;br /&gt;
            __index = function(t, k)&lt;br /&gt;
                if options.translate[k] ~= k then&lt;br /&gt;
                    return nil&lt;br /&gt;
                else&lt;br /&gt;
                    return k&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        })&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Get the argument tables. If we were passed a valid frame object,&lt;br /&gt;
    -- get the frame arguments (fargs) and the parent frame arguments&lt;br /&gt;
    -- (pargs), depending on the options set and on the parent frame&amp;#039;s&lt;br /&gt;
    -- availability. If we weren&amp;#039;t passed a valid frame object, we are&lt;br /&gt;
    -- being called from another Lua module or from the debug console,&lt;br /&gt;
    -- so assume that we were passed a table of args directly, and&lt;br /&gt;
    -- assign it to a new variable (luaArgs).&lt;br /&gt;
    local fargs, pargs, luaArgs&lt;br /&gt;
    options.wrappers = options.wrappers or options.wrapper&lt;br /&gt;
    if&lt;br /&gt;
        type(frame.args) == &amp;#039;table&amp;#039; and&lt;br /&gt;
        type(frame.getParent) == &amp;#039;function&amp;#039;&lt;br /&gt;
    then&lt;br /&gt;
        -- The wrappers option makes Module:Arguments look up&lt;br /&gt;
        -- arguments in either the frame argument table or the&lt;br /&gt;
        -- parent argument table, but not both. This means that&lt;br /&gt;
        -- users can use either the #invoke syntax or a wrapper&lt;br /&gt;
        -- template without the loss of performance associated&lt;br /&gt;
        -- with looking arguments up in both the frame and the&lt;br /&gt;
        -- parent frame.&lt;br /&gt;
        -- The arguments will be fetched from the parent frame if&lt;br /&gt;
        -- the parent frame&amp;#039;s title is present in options.wrapper;&lt;br /&gt;
        -- otherwise it will look up arguments in the frame object&lt;br /&gt;
        -- passed to getArgs.&lt;br /&gt;
        if options.wrappers then&lt;br /&gt;
            local parent = frame:getParent()&lt;br /&gt;
            if not parent then&lt;br /&gt;
                fargs = frame.args&lt;br /&gt;
            else&lt;br /&gt;
                local title = parent:getTitle():gsub(&amp;#039;/sandbox$&amp;#039;, &amp;#039;&amp;#039;)&lt;br /&gt;
                local found = false&lt;br /&gt;
                if matchesTitle(options.wrappers, title) then&lt;br /&gt;
                    found = true&lt;br /&gt;
                elseif type(options.wrappers) == &amp;#039;table&amp;#039; then&lt;br /&gt;
                    for _,v in pairs(options.wrappers) do&lt;br /&gt;
                        if matchesTitle(v, title) then&lt;br /&gt;
                            found = true&lt;br /&gt;
                            break&lt;br /&gt;
                        end&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
&lt;br /&gt;
                -- We test for false specifically here so that nil (the&lt;br /&gt;
                -- default) acts like true.&lt;br /&gt;
                if found or options.frameOnly == false then&lt;br /&gt;
                    pargs = parent.args&lt;br /&gt;
                end&lt;br /&gt;
                if not found or options.parentOnly == false then&lt;br /&gt;
                    fargs = frame.args&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        -- When options.wrapper isn&amp;#039;t set, check the other options.&lt;br /&gt;
        else&lt;br /&gt;
            if not options.parentOnly then&lt;br /&gt;
                fargs = frame.args&lt;br /&gt;
            end&lt;br /&gt;
            if not options.frameOnly then&lt;br /&gt;
                local parent = frame:getParent()&lt;br /&gt;
                pargs = parent and parent.args or nil&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        if options.parentFirst then&lt;br /&gt;
            fargs, pargs = pargs, fargs&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        luaArgs = frame&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Set the order of precedence of the argument tables. If the variables are&lt;br /&gt;
    -- nil, nothing will be added to the table, which is how we avoid clashes&lt;br /&gt;
    -- between the frame/parent args and the Lua args.&lt;br /&gt;
    local argTables = {fargs}&lt;br /&gt;
    argTables[#argTables + 1] = pargs&lt;br /&gt;
    argTables[#argTables + 1] = luaArgs&lt;br /&gt;
&lt;br /&gt;
    -- Generate the tidyVal function. If it has been specified by the user, we&lt;br /&gt;
    -- use that; if not, we choose one of four functions depending on the&lt;br /&gt;
    -- options chosen. This is so that we don&amp;#039;t have to call the options table&lt;br /&gt;
    -- every time the function is called.&lt;br /&gt;
    local tidyVal = options.valueFunc&lt;br /&gt;
    if tidyVal then&lt;br /&gt;
        if type(tidyVal) ~= &amp;#039;function&amp;#039; then&lt;br /&gt;
            error(i18n:msg(&amp;#039;error-value-func&amp;#039;, type(tidyVal)), 2)&lt;br /&gt;
        end&lt;br /&gt;
    elseif options.trim ~= false then&lt;br /&gt;
        if options.removeBlanks ~= false then&lt;br /&gt;
            tidyVal = tidyValDefault&lt;br /&gt;
        else&lt;br /&gt;
            tidyVal = tidyValTrimOnly&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        if options.removeBlanks ~= false then&lt;br /&gt;
            tidyVal = tidyValRemoveBlanksOnly&lt;br /&gt;
        else&lt;br /&gt;
            tidyVal = tidyValNoChange&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Set up the args, metaArgs and nilArgs tables. args will be the one&lt;br /&gt;
    -- accessed from functions, and metaArgs will hold the actual arguments. Nil&lt;br /&gt;
    -- arguments are memoized in nilArgs, and the metatable connects all of them&lt;br /&gt;
    -- together.&lt;br /&gt;
    local args, metaArgs, nilArgs, metatable = {}, {}, {}, {}&lt;br /&gt;
    setmetatable(args, metatable)&lt;br /&gt;
&lt;br /&gt;
    -- Accepts multiple tables as input and merges their keys and values&lt;br /&gt;
    -- into one table. If a value is already present it is not overwritten;&lt;br /&gt;
    -- tables listed earlier have precedence. We are also memoizing nil&lt;br /&gt;
    -- values, which can be overwritten if they are &amp;#039;s&amp;#039; (soft).&lt;br /&gt;
    local function mergeArgs(tables)&lt;br /&gt;
        for _, t in ipairs(tables) do&lt;br /&gt;
            for key, val in pairs(t) do&lt;br /&gt;
                if metaArgs[key] == nil and nilArgs[key] ~= &amp;#039;h&amp;#039; then&lt;br /&gt;
                    local tidiedVal = tidyVal(key, val)&lt;br /&gt;
                    if tidiedVal == nil then&lt;br /&gt;
                        nilArgs[key] = &amp;#039;s&amp;#039;&lt;br /&gt;
                    else&lt;br /&gt;
                        metaArgs[key] = tidiedVal&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;
    -- Define metatable behaviour. Arguments are memoized in the metaArgs table,&lt;br /&gt;
    -- and are only fetched from the argument tables once. Fetching arguments&lt;br /&gt;
    -- from the argument tables is the most resource-intensive step in this&lt;br /&gt;
    -- module, so we try and avoid it where possible. For this reason, nil&lt;br /&gt;
    -- arguments are also memoized, in the nilArgs table. Also, we keep a record&lt;br /&gt;
    -- in the metatable of when pairs and ipairs have been called, so we do not&lt;br /&gt;
    -- run pairs and ipairs on the argument tables more than once. We also do&lt;br /&gt;
    -- not run ipairs on fargs and pargs if pairs has already been run, as all&lt;br /&gt;
    -- the arguments will already have been copied over.&lt;br /&gt;
&lt;br /&gt;
    -- Fetches an argument when the args table is indexed. First we check&lt;br /&gt;
    -- to see if the value is memoized, and if not we try and fetch it from&lt;br /&gt;
    -- the argument tables. When we check memoization, we need to check&lt;br /&gt;
    -- metaArgs before nilArgs, as both can be non-nil at the same time.&lt;br /&gt;
    -- If the argument is not present in metaArgs, we also check whether&lt;br /&gt;
    -- pairs has been run yet. If pairs has already been run, we return nil.&lt;br /&gt;
    -- This is because all the arguments will have already been copied into&lt;br /&gt;
    -- metaArgs by the mergeArgs function, meaning that any other arguments&lt;br /&gt;
    -- must be nil.&lt;br /&gt;
    metatable.__index = function (t, key)&lt;br /&gt;
        if type(key) == &amp;#039;string&amp;#039; then&lt;br /&gt;
            key = options.translate[key]&lt;br /&gt;
        end&lt;br /&gt;
        local val = metaArgs[key]&lt;br /&gt;
        if val ~= nil then&lt;br /&gt;
            return val&lt;br /&gt;
        elseif metatable.donePairs or nilArgs[key] then&lt;br /&gt;
            return nil&lt;br /&gt;
        end&lt;br /&gt;
        for _, argTable in ipairs(argTables) do&lt;br /&gt;
            local argTableVal = tidyVal(key, argTable[key])&lt;br /&gt;
            if argTableVal ~= nil then&lt;br /&gt;
                metaArgs[key] = argTableVal&lt;br /&gt;
                return argTableVal&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        nilArgs[key] = &amp;#039;h&amp;#039;&lt;br /&gt;
        return nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    metatable.__newindex = function (t, key, val)&lt;br /&gt;
        -- This function is called when a module tries to add a new&lt;br /&gt;
        -- value to the args table, or tries to change an existing&lt;br /&gt;
        -- value.&lt;br /&gt;
        if type(key) == &amp;#039;string&amp;#039; then&lt;br /&gt;
            key = options.translate[key]&lt;br /&gt;
        end&lt;br /&gt;
        if options.readOnly then&lt;br /&gt;
            error(i18n:msg(&amp;#039;error-write-permission&amp;#039;, tostring(key)), 2)&lt;br /&gt;
        elseif options.noOverwrite and args[key] ~= nil then&lt;br /&gt;
            error(i18n:msg(&amp;#039;error-overwrite-permission&amp;#039;, tostring(key)), 2)&lt;br /&gt;
        elseif val == nil then&lt;br /&gt;
            -- If the argument is to be overwritten with nil, we need to erase&lt;br /&gt;
            -- the value in metaArgs, so that __index, __pairs and __ipairs do&lt;br /&gt;
            -- not use a previous existing value, if present; and we also need&lt;br /&gt;
            -- to memoize the nil in nilArgs, so that the value isn&amp;#039;t looked&lt;br /&gt;
            -- up in the argument tables if it is accessed again.&lt;br /&gt;
            metaArgs[key] = nil&lt;br /&gt;
            nilArgs[key] = &amp;#039;h&amp;#039;&lt;br /&gt;
        else&lt;br /&gt;
            metaArgs[key] = val&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local function translatenext(invariant)&lt;br /&gt;
        local k, v = next(invariant.t, invariant.k)&lt;br /&gt;
        invariant.k = k&lt;br /&gt;
        if k == nil then&lt;br /&gt;
            return nil&lt;br /&gt;
        elseif type(k) ~= &amp;#039;string&amp;#039; or not options.backtranslate then&lt;br /&gt;
            return k, v&lt;br /&gt;
        else&lt;br /&gt;
            local backtranslate = options.backtranslate[k]&lt;br /&gt;
            if backtranslate == nil then&lt;br /&gt;
                -- Skip this one. This is a tail call, so this&lt;br /&gt;
                -- won&amp;#039;t cause stack overflow.&lt;br /&gt;
                return translatenext(invariant)&lt;br /&gt;
            else&lt;br /&gt;
                return backtranslate, v&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- This metamethod is called when pairs is run on the args table.&lt;br /&gt;
    metatable.__pairs = function ()&lt;br /&gt;
        if not metatable.donePairs then&lt;br /&gt;
            mergeArgs(argTables)&lt;br /&gt;
            metatable.donePairs = true&lt;br /&gt;
        end&lt;br /&gt;
        return translatenext, { t = metaArgs }&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- This custom `ipairs`-style iterator uses our __index metamethod.&lt;br /&gt;
    local function inext(t, i)&lt;br /&gt;
        local v = t[i + 1]&lt;br /&gt;
        if v ~= nil then&lt;br /&gt;
            return i + 1, v&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- This metamethod is called when ipairs is run on the args table.&lt;br /&gt;
    metatable.__ipairs = function (t)&lt;br /&gt;
        return inext, t, 0&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return args&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return arguments&lt;/div&gt;</summary>
		<author><name>Hugin</name></author>
	</entry>
</feed>