模块:IfUtil
此模块被引用于约168,000个页面。 为了避免造成大规模的影响,所有对此模块的编辑应先于沙盒或测试样例上测试。 测试后无误的版本可以一次性地加入此模块中,但是修改前请务必于讨论页发起讨论。 模板引用数量会自动更新。 |
ifnewhtmlline
判断输入字符串中是否存在HTML的换行标签
noTrim
由于默认的解析器函数(如{{#if:}}
、{{#ifexpr:}}
)会自动将输入的参数做去除头尾空白或断行字符的操作
这对部分需要使替换引用结果出现换行又要避免出现尾部占位符(如在换行后加入<!---->
或{{void}}
等作法避免trim)是不可行的,或者需要较复杂的语法书写方式(参见mw:Manual:Newlines_and_spaces#Trimming_on_expansion),这将使的模板代码的可读性和可维护性变得十分的差,并且增加模板展开调用甚至可能增加维基媒体服务器的运作负担。
因此为了解决{{#if:}}
、{{#ifexpr:}}
和{{if}}
会自动将参数trim掉的问题,因此这个模块通过Module:Arguments将关闭参数trim功能提供了一个解决方案。
基本用法
{{#invoke:ifUtil
|noTrim|命令|判斷參數|成立時返回|不成立時返回}}
- 简易用法
- 高级用法
{{yesno}}
- 参数顺序:
{{#invoke:ifUtil|noTrim|yesno|布林值|為真時(yes)|為假時(no)|空白時(blank)|非法輸入時(def)|未定義時(¬)}}
- 参数顺序:
- if...elseif...else
{{#invoke:ifUtil|noTrim|expr|判斷式1|式1為真時|式1為假時}}
{{#invoke:ifUtil|noTrim|expr|判斷式1|式1為真時|elseif判斷式2|式2為真時}}
{{#invoke:ifUtil|noTrim|expr|判斷式1|式1為真時|elseif判斷式2|式2為真時|皆為假時}}
{{#invoke:ifUtil|noTrim|expr|判斷式1|式1為真時|elseif判斷式2|式2為真時|elseif判斷式3|式3為真時}}
{{#invoke:ifUtil|noTrim|expr|判斷式1|式1為真時|elseif判斷式2|式2為真時|elseif判斷式3|式3為真時|皆為假時}}
- 以此类推,参数长度没有上限 (除了WP:模板限制)
- 比较
注意留意“文字”与“Yse/No”模板间的空格状况
项目 | 使用Module:IfUtil#noTrim | 使用Help:解析器函数 | ||
---|---|---|---|---|
您所输入的 | 您所看到的 | 您所输入的 | 您所看到的 | |
#ifexpr: |
文字{{#invoke:IfUtil|noTrim|expr|5>3|
Yes
|
No
}}文字
|
文字
Yes 文字 |
文字{{#ifexpr:5>3|
Yes
|
No
}}文字
|
文字Yes文字 |
#ifexpr: |
文字{{#invoke:IfUtil|noTrim|expr|5<3|
Yes
|
No
}}文字
|
文字
No 文字 |
文字{{#ifexpr:5<3|
Yes
|
No
}}文字
|
文字No文字 |
#ifeq: |
文字{{#invoke:IfUtil|noTrim|eq|A|A|
Yes
|
No
}}文字
|
文字
Yes 文字 |
文字{{#ifeq:A|A|
Yes
|
No
}}文字
|
文字Yes文字 |
#ifeq: |
文字{{#invoke:IfUtil|noTrim|eq|A|B|
Yes
|
No
}}文字
|
文字
No 文字 |
文字{{#ifeq:A|B|
Yes
|
No
}}文字
|
文字No文字 |
yesno:是 | 文字{{#invoke:IfUtil|noTrim|yesno|是|
Yes
|
No
}}文字
|
文字
Yes 文字 |
文字{{yesno|是|yes=
Yes
|no=
No
}}文字
|
文字Yes文字 |
#ifexist: 无此条目!! |
文字{{#invoke:IfUtil|noTrim|exist|無此條目!!|
Yes
|
No
}}文字
|
文字
No 文字 |
文字{{#ifexist:無此條目!!|
Yes
|
No
}}文字
|
文字No文字 |
#ifexist: WP:条目 |
文字{{#invoke:IfUtil|noTrim|exist|WP:條目|
Yes
|
No
}}文字
|
文字
Yes 文字 |
文字{{#ifexist:WP:條目|
Yes
|
No
}}文字
|
文字Yes文字 |
所有命令
命令 | 基本用法 | 描述 | ||
---|---|---|---|---|
常规判断 | ||||
if
|
{{#invoke:ifUtil|noTrim|if|判斷的字串|字串有值時返回|字串為空時返回}}
|
{{#if:}} 的不trim版本。
| ||
expr
|
{{#invoke:ifUtil|noTrim|expr|expr表達式|表達式為真時返回|表達式為假時返回}}
|
{{#ifexpr:}} 的不trim版本。
| ||
内容比对 | ||||
eq
|
{{#invoke:ifUtil|noTrim|eq|判斷的字串|字串有值時返回|字串為空時返回}}
|
{{#ifeq:}} 的不trim版本。
| ||
eq|選項=Y/N
|
{{#invoke:ifUtil|noTrim|eq|選項1=Y/N|選項2=Y/N|判斷的字串|字串有值時返回|字串為空時返回}}
|
特殊选项的{{#ifeq:}} 。目前的选项有:
可叠加多个选项。 | ||
eq|trim=no
|
{{#invoke:ifUtil|noTrim|eq|trim=no|比對的字串1|比對的字串2|字串相等時返回|字串不同時返回}}
|
连输入欲比对之字符串都不trim的{{#ifeq:}} 。其会将“foo ”与“foo ”视为相异。
| ||
eq|i=yes
|
{{#invoke:ifUtil|noTrim|eq|i=yes|比對的字串1|比對的字串2|字串相等時返回|字串不同時返回}}
|
忽略大小写的trim的{{#ifeq:}} 。其会将“FOO ”与“foo ”视为相同。
| ||
内容判断 | ||||
error
|
{{#invoke:ifUtil|noTrim|error|欲除錯的內容|內容有錯誤時返回|內容沒有問題時返回}}
|
{{#iferror:}} 的不trim版本。
| ||
exist
|
{{#invoke:ifUtil|noTrim|exist|要判斷是否存在的頁面標題|頁面存在時返回|頁面不存在時返回}}
|
{{#ifexist:}} 的不trim版本。
| ||
工具 | ||||
yesno
|
{{#invoke:ifUtil|noTrim|yesno|可代表布林值的字串|布林值為真時返回|布林值為假時返回}}
|
{{yesno}} 的不trim版本[a],同时也支援{{yesno}}的。|yes= 、|no= 、|def= 、|¬= 和|blank= 等参数。(参见#高级用法#yesno)
| ||
其他if-else類模板
|
{{#invoke:ifUtil|noTrim|<其他if-else類模板>|判斷用參數|成立時返回|不成立時返回}}
|
其他if-else类模板的不trim版本[a]。 | ||
其他模板 [b]
|
{{#invoke:ifUtil|noTrim|<模板名稱>|參數1|參數2|參數3....}}
|
对于不支援或非if-else类的模板会有类似一般地调用模板的效果。 | ||
参数
下表按固定顺序显示了可用的位置参数(参数*
)。对于每个命令,都会标记适用的参数集。例如,如果已给出命令 eq
,那么至少应给出 判斷式①
和比對式
两个参数。
(必要) | (必要) | (ifeq必填) | (可选) | (可选) | (可选) | (可选) | ||||
{{#invoke:ifUtil|noTrim
|
命令
|
判斷式①
|
比对式
|
①成立时
|
否则
|
判断式②
|
②成立时
|
判断式③...
|
}}
| |
---|---|---|---|---|---|---|---|---|---|---|
其他参数
|
其他参数2
|
其他参数3...
| ||||||||
if , expr ,eq ,error ,exist ,yesno ,其他if-else类模板, 其他模板 |
||||||||||
eq
|
||||||||||
if , expr ,eq ,error ,exist ,yesno (yes参数),其他if-else类模板
|
||||||||||
if , expr , eq ,error ,exist ,yesno (no参数), 其他if-else类模板
|
||||||||||
expr , yesno (blank参数), 其他模板
|
||||||||||
expr , yesno (def参数), 其他模板 (可选 2nd, 3rd 等)
|
||||||||||
expr (可选 2nd, 3rd 等), yesno (¬参数), 其他模板
| ||||||||||
if2number
local p={}
local lib_arg={}
local yesno = require('Module:Yesno')
function p.noTrim(frame)--{{#invoke:IfUtil|noTrim|expr|5>3|Yes|No}}
local args, working_frame
if frame == mw.getCurrentFrame() then
-- We're being called via #invoke. The args are passed through to the module
-- from the template page, so use the args that were passed into the template.
if lib_arg.getArgs == nil then lib_arg = require('Module:Arguments') end
args = lib_arg.getArgs(frame, {
parentFirst=true,
trim = false,
removeBlanks = false
})
working_frame = frame
else
-- We're being called from another module or from the debug console, so assume
-- the args are passed in directly.
args = frame
working_frame = mw.getCurrentFrame()
if type(args) ~= type({}) then args = {frame} end
end
local command = mw.ustring.lower(mw.text.trim(args['1'] or args[1] or ''))
local if_table = require('Module:Var')._seek_arg(args,1)
if command == 'if' or command == '' or command == '#if' then
return p.ifnoTrim(if_table)
elseif command == 'ifexpr' or command == 'expr' or command == '#ifexpr' then
return p.ifexprnoTrim(if_table)
elseif command == 'ifeq' or command == 'eq' or command == '#ifeq' then
local strcmpi, unstrip, preprocess = yesno(mw.text.trim(args.i or 'no')), yesno(mw.text.trim(args.unstrip or 'no')), yesno(mw.text.trim(args.preprocess or 'no'))
local pre_str = function(in_str)
local result = in_str
if preprocess == true then result = working_frame:preprocess(result) end
if unstrip == true then result = mw.text.unstrip(result) end
if strcmpi == true then result = mw.ustring.lower(result) end
return result
end
if yesno(mw.text.trim(args.trim or 'yes')) then
if mw.text.trim(pre_str(args['2'] or args[2] or '')) == mw.text.trim(pre_str(args['3'] or args[3] or '')) then return args['4'] or args[4] or ''
else return args['5'] or args[5] or '' end
else
if pre_str(args['2'] or args[2] or '') == pre_str(args['3'] or args[3] or '') then return args['4'] or args[4] or ''
else return args['5'] or args[5] or '' end
end
elseif command == 'iferror' or command == 'error' or command == '#iferror' then
local output_error = args['3'] or args[3] or ''
local output_success = args['4'] or args[4]
if not output_success then output_success = args['2'] or args[2] or '' end
local result = working_frame:callParserFunction{ name = '#iferror:' .. mw.text.trim(args['2'] or args[2] or ''), args = {'error', 'success'} }
result = mw.ustring.lower(result)
if result == 'success' then return output_success end
return output_error
elseif command == 'ifexist' or command == 'exist' or command == '#ifexist' then
local output_exist = args['3'] or args[3]
local output_no = args['4'] or args[4] or ''
if not output_exist then output_exist = args['2'] or args[2] or '' end
local result = working_frame:callParserFunction{ name = '#ifexist:' .. mw.text.trim(args['2'] or args[2] or ''), args = {'1', '0'} }
result = mw.ustring.lower(result)
if result == '1' then return output_exist end
return output_no
elseif command == 'yesno' then
--1=yesno | 2=test | 3=yes | 4=no | 5=blank | 6=def | 7=¬
local checker = mw.ustring.lower(mw.text.trim(args['2'] or args[2]or''))
if (not (args['2'] or args[2])) or checker == '¬' then return args['¬'] or args['7'] or args[7] or ''end
if checker=='' then return (args.blank or args['5'] or args[5]) or (args.no or args['4'] or args[4]) or '' end
checker = yesno(checker)
if checker == true then
return args.yes or args['3'] or args[3] or 'yes'
elseif checker == false then
return args.no or args['4'] or args[4] or ''
end
return args.def or args['6'] or args[6] or ''
else
local yes_arg, no_arg = args['yes arg'] or args.yes_arg or '2', args['no arg'] or args.no_arg or '3'
local if_check_table_input = require('Module:Var')._seek_arg(args,1)
if_check_table_input[yes_arg], if_check_table_input.yes = "yes", "yes"
if_check_table_input[no_arg], if_check_table_input.no = "no", "no"
local if_check_table = {}
for key, value in pairs(if_check_table_input) do
local num_key = tonumber(key)
if type(num_key) ~= type(nil) then --是數字參數 (匿名參數)
if_check_table[num_key] = value --避免數字參數重複以清理[[:Category:调用重复模板参数的页面]]
else
if_check_table[key] = value
end
end
local tester = mw.ustring.gsub(mw.text.unstrip(mw.ustring.lower(mw.text.trim(working_frame:preprocess(require('Module:Template invocation').invocation( 'safesubst:' .. (args['1'] or args[1] or 'void'), if_check_table))))), "<[^>]+>", '')
local checker = yesno(mw.ustring.sub(tester, mw.ustring.find(tester,'%a+')))
if checker == true then return args['3'] or args[3] or ''
elseif checker == false then return args['4'] or args[4] or ''end
return working_frame:preprocess(require('Module:Template invocation').invocation( 'safesubst:' .. (args['1'] or args[1] or 'void'), if_table))
end
return ''
end
function p.ifexprnoTrim(frame)--{{#invoke:IfUtil|ifexprnoTrim|5>3|Yes|No}}
local args, working_frame
if frame == mw.getCurrentFrame() then
-- We're being called via #invoke. The args are passed through to the module
-- from the template page, so use the args that were passed into the template.
if lib_arg.getArgs == nil then lib_arg = require('Module:Arguments') end
args = lib_arg.getArgs(frame, {
parentFirst=true,
trim = false,
removeBlanks = false
})
working_frame = frame
else
-- We're being called from another module or from the debug console, so assume
-- the args are passed in directly.
args = frame
working_frame = mw.getCurrentFrame()
if type(args) ~= type({}) then args = {frame} end
end
local input_str = args['1'] or args[1] or '0'
local output_if = args['2'] or args[2] or ''
local check_max_arg = 2
local ifexpr_table = {}
for k,v in pairs(args) do
local check_num = tonumber(mw.text.trim(k))
if check_num and check_num > check_max_arg then
check_max_arg = check_num
end
ifexpr_table[k] = v
end
ifexpr_table['1'] = input_str
ifexpr_table['2'] = output_if
local tail = check_max_arg - check_max_arg % 2
local output_else = (check_max_arg % 2 == 1) and (args[tostring(check_max_arg)] or args[check_max_arg]) or ''
for i=1,tail,2 do
local expr = ifexpr_table[tostring(i)] or ifexpr_table[i] or '0'
local true_result = args[tostring(i+1)] or args[i+1] or ''
local flag,ifexpr = xpcall(function() return mw.ext.ParserFunctions.expr(expr)end,function()end)
--use original #ifexpr: to print original error
if flag~=true then return working_frame:preprocess("{{safesubst:#ifexpr:" .. expr .. '|' .. true_result .. '|' .. output_else .."}}") end
if (tonumber(ifexpr or'0') or 0) ~= 0 then return true_result end
end
return output_else
end
function p.ifnoTrim(frame)
local args, working_frame
if frame == mw.getCurrentFrame() then
-- We're being called via #invoke. The args are passed through to the module
-- from the template page, so use the args that were passed into the template.
if lib_arg.getArgs == nil then lib_arg = require('Module:Arguments') end
args = lib_arg.getArgs(frame, {
parentFirst=true,
trim = false,
removeBlanks = false
})
working_frame = frame
else
-- We're being called from another module or from the debug console, so assume
-- the args are passed in directly.
args = frame
working_frame = mw.getCurrentFrame()
if type(args) ~= type({}) then args = {frame} end
end
local input_str = args['1'] or args[1] or ''
local output_if = args['2'] or args[2] or ''
local output_else = args['3'] or args[3] or ''
if mw.text.trim(input_str) ~= '' then
return output_if
end
return output_else
end
function p.ifnewhtmlline(frame)
local args, working_frame
if frame == mw.getCurrentFrame() then
-- We're being called via #invoke. The args are passed through to the module
-- from the template page, so use the args that were passed into the template.
if lib_arg.getArgs == nil then lib_arg = require('Module:Arguments') end
args = lib_arg.getArgs(frame, {
parentFirst=true,
trim = false,
removeBlanks = false
})
working_frame = frame
else
-- We're being called from another module or from the debug console, so assume
-- the args are passed in directly.
args = frame
working_frame = mw.getCurrentFrame()
if type(args) ~= type({}) then args = {frame} end
end
local input_str = args['1'] or args[1] or ''
local output_if = args['2'] or args[2] or ''
local output_else = args['3'] or args[3] or ''
if mw.ustring.find(input_str, '<%s*/?%s*[Bb][Rr]%s*/?%s*>') then
return output_if
end
return output_else
end
function p.ifnoAddTail(frame) --{{#invoke:IfUtil|ifnoAddTail|text|unit|pattern}}
local args, working_frame
if frame == mw.getCurrentFrame() then
-- We're being called via #invoke. The args are passed through to the module
-- from the template page, so use the args that were passed into the template.
if lib_arg.getArgs == nil then lib_arg = require('Module:Arguments') end
args = lib_arg.getArgs(frame, {
trim = false,
removeBlanks = false
})
working_frame = frame
else
-- We're being called from another module or from the debug console, so assume
-- the args are passed in directly.
args = frame
working_frame = mw.getCurrentFrame()
if type(args) ~= type({}) then args = {frame} end
end
local input_str = args['1'] or args[1] or ''
local uint = args['2'] or args[2] or ''
local uint_pattern = args['3'] or args[3] or ''
if mw.text.trim(uint_pattern) == '' then uint_pattern = mw.ustring.gsub(mw.text.trim(uint), '([%\\%^%$%(%)%%%.%{%}%[%]%*%+%-%?])','%%%1')end
if mw.ustring.find(input_str, uint_pattern) then
return input_str
end
return input_str .. uint
end
function p.if2number(frame)
local args, working_frame
if frame == mw.getCurrentFrame() then
-- We're being called via #invoke. The args are passed through to the module
-- from the template page, so use the args that were passed into the template.
if lib_arg.getArgs == nil then lib_arg = require('Module:Arguments') end
args = lib_arg.getArgs(frame, {
parentFirst=true,
trim = false,
removeBlanks = false
})
working_frame = frame
else
-- We're being called from another module or from the debug console, so assume
-- the args are passed in directly.
args = frame
working_frame = mw.getCurrentFrame()
if type(args) ~= type({}) then args = {frame} end
end
local input_str = args['1'] or args[1] or ''
local output_hasTwo = args['2'] or args[2] or '1'
local output_otherwise = args['3'] or args[3] or ''
local check_split = args['4'] or args[4] or '~'
local local_check = mw.text.trim(require('Module:TemplateParameters').containsNumber({input_str}))
if local_check ~= '' then
local split_end, split2_first = mw.ustring.find(input_str,check_split)
local first_num_str, second_num_str = '', ''
if split_end then first_num_str = mw.ustring.sub(input_str,1,split_end-1) end
if split2_first then second_num_str = mw.ustring.sub(input_str,split2_first+1,-1) end
local first_num_check, second_num_check = mw.text.trim(require('Module:TemplateParameters').containsNumber({first_num_str})),
mw.text.trim(require('Module:TemplateParameters').containsNumber({second_num_str}))
if first_num_check ~= '' and second_num_check ~= '' then
first_num_check, second_num_check = require('Module:TemplateParameters').getNumberValue({first_num_str}),
require('Module:TemplateParameters').getNumberValue({second_num_str})
local first_num, second_num = tonumber(first_num_check), tonumber(second_num_check)
if first_num and second_num then
if first_num ~= second_num then
return output_hasTwo
else return output_otherwise end
else return output_otherwise end
else return output_otherwise end
else return output_otherwise end
end
function p.findArgs(frame)
-- For calling from #invoke.
local args
--是否存在有效的frame可供呼叫
local can_call_parse = false
if frame == mw.getCurrentFrame() then
-- We're being called via #invoke. The args are passed through to the module
-- from the template page, so use the args that were passed into the template.
args = frame.args
can_call_parse = true
else
-- We're being called from another module or from the debug console, so assume
-- the args are passed in directly.
args = frame
end
local out_frame = mw.getCurrentFrame():getParent() --模板外層
local out_args = {} --紀錄來自模板外層提供的參數
local body = ''
local to_find={}
local default=''
if out_frame then out_args = out_frame.args or out_args end
for key,val in pairs(args) do
local parse_name=tonumber(key)
if parse_name then to_find[#to_find+1]=val end
end
default = args.default or default
local find_result={}
local is_find=false
for key,val in pairs(out_args) do
for i=1,#to_find do
if mw.ustring.lower(mw.text.trim(val)) == mw.ustring.lower(mw.text.trim(to_find[i])) then
is_find=true
find_result[mw.text.trim(key)]=is_find;
end
end
end
if is_find then
local body = ''
for key,val in pairs(find_result) do
if body~='' then body=body..','end
body=body..key
end
return body
else
return default
end
end
return p