模組:Arguments/doc

这是Module:Arguments的文档页面
![]() | 此頁面是Module:Arguments的模块文档。 此頁面可能包含了模板的使用說明、分類和其他内容。 |
![]() | 此模块文档被引用於4,180,000+個頁面,佔全部頁面的52%。 為了避免造成大規模的影響,所有對此模块文档的編輯應先於沙盒或測試樣例上測試。 測試後無誤的版本可以一次性地加入此模块文档中,但是修改前請務必於討論頁發起討論。 模板引用數量會自動更新。 |
![]() | 此模块的文档不存在、不全面或不能详细描述其功能及/或其代码中的参数。请帮助扩充并改进其文档。 |
![]() | 此條目可参照外語維基百科相應條目来扩充。 (2018年9月21日) |
此模块提供了对通过{{#invoke:}}
(以下简称#invoke)传递参数的简单处理。它是一个元模块,只能被其他模块所使用,而不应被#invoke直接调用。其特性如下:
- 对参数的简易修整,移除空白参数。
- 参数可以在当前框架或父框架中同时传递。(具体见下)
- 参数可以直接通过其他Lua模块或调试控制台传递。
- 参数按需获取,这样可以避免一些
<ref>...</ref>
标签的问题。 - 可自定义更多特性。
基本用法
首先,您需要通过require函数加载这个模块。这个模块包含了一个名为getArgs
的函数。
local getArgs = require('Module:Arguments').getArgs
最简单的方法是在使用getArgs函数。变量args
是包含#invoke参数的表(table)。(详情见下文)
local getArgs = require('Module:Arguments').getArgs
local p = {}
function p.main(frame)
local args = getArgs(frame)
-- 主模块放这儿。
end
return p
但实践中,最好先用专门的函数(指变量p
的一个域值,如下文中的p._main)来处理一个特定的参数表(lua的表,与#invoke无关),然后用另一个函数(如下文中的p.main)调用这个函数,并将调用#invoke时传用的参数(即下文中的getArgs(frame))作为调用这个函数时的参数。这样,其他Lua模块直接调用该模块时,就无需再调用frame对象,从而提升性能,减小开销。
local getArgs = require('Module:Arguments').getArgs
local p = {}
function p.main(frame)
local args = getArgs(frame) -- 从#invoke中获得的参数
return p._main(args)
end
function p._main(args)
-- 主模块放这儿,这里的args是一个纯粹的表
end
return p
如果你需要多个函数使用这些参数,而且你希望这些函数可用于#invoke,你可以使用包装函数(wrapper function)。
local getArgs = require('Module:Arguments').getArgs
local function makeInvokeFunc(funcName)
return function (frame)
local args = getArgs(frame)
return p[funcName](args)
end
end
local p = {}
p.func1 = makeInvokeFunc('_func1')
function p._func1(args)
-- 第一个函数的代码。
end
p.func2 = makeInvokeFunc('_func2')
function p._func2(args)
-- 第二个函数的代码。
end
return p
选项
你可以使用如下面这段代码所示的选项。这些选项会在下文中介绍。
local args = getArgs(frame, {
trim = false,
removeBlanks = false,
valueFunc = function (key, value)
-- 用于处理一个参数的函数的代码。
end,
frameOnly = true,
parentOnly = true,
parentFirst = true,
wrappers = {
'Template:A wrapper template',
'Template:Another wrapper template'
},
readOnly = true,
noOverwrite = true
})
移除参数空格和移除空白的参数
Blank arguments often trip up coders new to converting MediaWiki templates to Lua. 在模板中,空白字符串和仅包含空白字符(whitespace,空格、换行等)的字符串被视为假值(false)。然而,在Lua,空白字符串和只包含空白字符的字符串则会被视为真值(true)。这就是说,如果你在写Lua模块时,不注意这些参数,你可能会把本想视为假值的东西视为真值。为了避免这种情况,这个模块默认会移除所有的空白参数。
与之类似,空白字符在处理位置参数(positional arguments)时会发生问题。虽然来自#invoke的命了名的参数的空白字符会被剔除(trim),但是对一些位置参数仍然保留。大多数时候,多余的空白字符是不需要的,所以这个模块默认剔除这些空白字符。
然而,有时输入时又需要使用这些空白字符,或者空白参数。This can be necessary to convert some templates exactly as they were written. 如果你需要不剔除空白字符或移除空白参数,你可以(在调用getArgs函数时)将trim
和removeBlanks
参数设为false
。
local args = getArgs(frame, {
trim = false,
removeBlanks = false
})
Custom formatting of arguments
Sometimes you want to remove some blank arguments but not others, or perhaps you might want to put all of the positional arguments in lower case. To do things like this you can use the valueFunc
option. The input to this option must be a function that takes two parameters, key
and value
, and returns a single value. This value is what you will get when you access the field key
in the args
table.
Example 1: this function preserves whitespace for the first positional argument, but trims all other arguments and removes all other blank arguments.
local args = getArgs(frame, {
valueFunc = function (key, value)
if key == 1 then
return value
elseif value then
value = mw.text.trim(value)
if value ~= '' then
return value
end
end
return nil
end
})
Example 2: this function removes blank arguments and converts all arguments to lower case, but doesn't trim whitespace from positional parameters.
local args = getArgs(frame, {
valueFunc = function (key, value)
if not value then
return nil
end
value = mw.ustring.lower(value)
if mw.ustring.find(value, '%S') then
return value
end
return nil
end
})
Note: the above functions will fail if passed input that is not of type string
or nil
. This might be the case if you use the getArgs
function in the main function of your module, and that function is called by another Lua module. In this case, you will need to check the type of your input. This is not a problem if you are using a function specially for arguments from #invoke (i.e. you have p.main
and p._main
functions, or something similar).
Examples 1 and 2 with type checking
|
---|
Example 1: local args = getArgs(frame, {
valueFunc = function (key, value)
if key == 1 then
return value
elseif type(value) == 'string' then
value = mw.text.trim(value)
if value ~= '' then
return value
else
return nil
end
else
return value
end
end
})
Example 2: local args = getArgs(frame, {
valueFunc = function (key, value)
if type(value) == 'string' then
value = mw.ustring.lower(value)
if mw.ustring.find(value, '%S') then
return value
else
return nil
end
else
return value
end
end
})
|
Also, please note that the valueFunc
function is called more or less every time an argument is requested from the args
table, so if you care about performance you should make sure you aren't doing anything inefficient with your code.
Frames and parent frames
Arguments in the args
table can be passed from the current frame or from its parent frame at the same time. To understand what this means, it is easiest to give an example. Let's say that we have a module called Module:ExampleArgs
. This module prints the first two positional arguments that it is passed.
Module:ExampleArgs code
|
---|
local getArgs = require('Module:Arguments').getArgs
local p = {}
function p.main(frame)
local args = getArgs(frame)
return p._main(args)
end
function p._main(args)
local first = args[1] or ''
local second = args[2] or ''
return first .. ' ' .. second
end
return p
|
Module:ExampleArgs
is then called by Template:ExampleArgs
, which contains the code {{#invoke:ExampleArgs|main|firstInvokeArg}}
. This produces the result "firstInvokeArg".
Now if we were to call Template:ExampleArgs
, the following would happen:
Code | Result |
---|---|
{{ExampleArgs}}
|
firstInvokeArg |
{{ExampleArgs|firstTemplateArg}}
|
firstInvokeArg |
{{ExampleArgs|firstTemplateArg|secondTemplateArg}}
|
firstInvokeArg secondTemplateArg |
There are three options you can set to change this behaviour: frameOnly
, parentOnly
and parentFirst
. If you set frameOnly
then only arguments passed from the current frame will be accepted; if you set parentOnly
then only arguments passed from the parent frame will be accepted; and if you set parentFirst
then arguments will be passed from both the current and parent frames, but the parent frame will have priority over the current frame. Here are the results in terms of Template:ExampleArgs
:
- frameOnly
Code | Result |
---|---|
{{ExampleArgs}}
|
firstInvokeArg |
{{ExampleArgs|firstTemplateArg}}
|
firstInvokeArg |
{{ExampleArgs|firstTemplateArg|secondTemplateArg}}
|
firstInvokeArg |
- parentOnly
Code | Result |
---|---|
{{ExampleArgs}}
|
|
{{ExampleArgs|firstTemplateArg}}
|
firstTemplateArg |
{{ExampleArgs|firstTemplateArg|secondTemplateArg}}
|
firstTemplateArg secondTemplateArg |
- parentFirst
Code | Result |
---|---|
{{ExampleArgs}}
|
firstInvokeArg |
{{ExampleArgs|firstTemplateArg}}
|
firstTemplateArg |
{{ExampleArgs|firstTemplateArg|secondTemplateArg}}
|
firstTemplateArg secondTemplateArg |
Notes:
- If you set both the
frameOnly
andparentOnly
options, the module won't fetch any arguments at all from #invoke. This is probably not what you want. - In some situations a parent frame may not be available, e.g. if getArgs is passed the parent frame rather than the current frame. In this case, only the frame arguments will be used (unless parentOnly is set, in which case no arguments will be used) and the
parentFirst
andframeOnly
options will have no effect.
Wrappers
The wrappers option is used to specify a limited number of templates as wrapper templates, that is, templates whose only purpose is to call a module. If the module detects that it is being called from a wrapper template, it will only check for arguments in the parent frame; otherwise it will only check for arguments in the frame passed to getArgs. This allows modules to be called by either #invoke or through a wrapper template without the loss of performance associated with having to check both the frame and the parent frame for each argument lookup.
For example, the only content of Template:Side box (excluding content in <noinclude>...</noinclude>
tags) is {{#invoke:Side box|main}}
. There is no point in checking the arguments passed directly to the #invoke statement for this template, as no arguments will ever be specified there. We can avoid checking arguments passed to #invoke by using the parentOnly option, but if we do this then #invoke will not work from other pages either. If this were the case, the |text=Some text
in the code {{#invoke:Side box|main|text=Some text}}
would be ignored completely, no matter what page it was used from. By using the wrappers
option to specify 'Template:Side box' as a wrapper, we can make {{#invoke:Side box|main|text=Some text}}
work from most pages, while still not requiring that the module check for arguments on the Template:Side box page itself.
Wrappers can be specified either as a string, or as an array of strings.
local args = getArgs(frame, {
wrappers = 'Template:Wrapper template'
})
local args = getArgs(frame, {
wrappers = {
'Template:Wrapper 1',
'Template:Wrapper 2',
-- Any number of wrapper templates can be added here.
}
})
Notes:
- The module will automatically detect if it is being called from a wrapper template's /sandbox subpage, so there is no need to specify sandbox pages explicitly.
- The wrappers option effectively changes the default of the frameOnly and parentOnly options. If, for example, parentOnly were explicitly set to false with wrappers set, calls via wrapper templates would result in both frame and parent arguments being loaded, though calls not via wrapper templates would result in only frame arguments being loaded.
- If the wrappers option is set and no parent frame is available, the module will always get the arguments from the frame passed to
getArgs
.
Writing to the args table
Sometimes it can be useful to write new values to the args table. This is possible with the default settings of this module. (However, bear in mind that it is usually better coding style to create a new table with your new values and copy arguments from the args table as needed.)
args.foo = 'some value'
It is possible to alter this behaviour with the readOnly
and noOverwrite
options. If readOnly
is set then it is not possible to write any values to the args table at all. If noOverwrite
is set, then it is possible to add new values to the table, but it is not possible to add a value if it would overwrite any arguments that are passed from #invoke.
Ref tags
This module uses metatables to fetch arguments from #invoke. This allows access to both the frame arguments and the parent frame arguments without using the pairs()
function. This can help if your module might be passed <ref>...</ref>
tags as input.
As soon as <ref>...</ref>
tags are accessed from Lua, they are processed by the MediaWiki software and the reference will appear in the reference list at the bottom of the article. If your module proceeds to omit the reference tag from the output, you will end up with a phantom reference - a reference that appears in the reference list, but no number that links to it. This has been a problem with modules that use pairs()
to detect whether to use the arguments from the frame or the parent frame, as those modules automatically process every available argument.
This module solves this problem by allowing access to both frame and parent frame arguments, while still only fetching those arguments when it is necessary. The problem will still occur if you use pairs(args)
elsewhere in your module, however.
Known limitations
The use of metatables also has its downsides. Most of the normal Lua table tools won't work properly on the args table, including the #
operator, the next()
function, and the functions in the table library. If using these is important for your module, you should use your own argument processing function instead of this module.