local p = {}
local lib_arg={}
--if (x<!--y){printf(y)};
function p.passEscapeArgs(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})
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 template_name = '' .. (args.template_name or 'void')
local module_name, function_name = nil,nil
if mw.ustring.find(template_name, "#[Ii][Nn][Vv][Oo][Kk][Ee]:.+%|.+") then
mw.ustring.gsub(template_name, "#[Ii][Nn][Vv][Oo][Kk][Ee]:(.+)%|(.+)", function(str, fun)module_name, function_name = str, fun return str end)
end
local escape_args = {}
for key, value in pairs(args) do
local arg_value = value
if mw.isSubsting() then
arg_value = mw.ustring.gsub(value, "[=%|%{%}]", function(esc_str)
local mapping = {} mapping['|']='!' mapping['=']='=' mapping['{']='(' mapping['}']=')'
if mapping[esc_str] then
return "{{" .. mapping[esc_str] .. "}}"
end
return esc_str
end)
end
escape_args[key] = mw.text.encode(arg_value)
end
local body_frame = working_frame:newChild{ title = module_name or template_name, args = escape_args }
if module_name ~= nil then
module_body = require("Module:"..module_name)
if module_body ~= nil then
func_body = module_body[function_name]
if func_body ~= nil then
return func_body(body_frame)
end
end
return ''
end
return body_frame:expandTemplate{ title = template_name, args = escape_args }
end
function p.passNArgs(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})
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 template_name = args.template_name or 'void'
local skip_args = tonumber(args.skip) or 1
local numberic_args = {}
local text_args = {}
local min_args, max_args = tonumber("inf"), tonumber("-inf")
for key, value in pairs(args) do
local i = tonumber(key)
local check = mw.text.trim(key):lower()
local arg_value = mw.ustring.gsub(value, "[=%|%{%}]", function(esc_str)
local mapping = {} mapping['|']='!' mapping['=']='=' mapping['{']='(' mapping['}']=')'
if mapping[esc_str] then
return "{{" .. mapping[esc_str] .. "}}"
end
return esc_str
end)
if i ~= nil and check~='inf' and check~='-inf' and check~='nan' and check~='-nan' then
numberic_args[i] = arg_value
if i > max_args then max_args = i end
if i < min_args then min_args = i end
else
text_args[key] = arg_value
end
end
if mw.isSubsting() then
template_name = mw.ustring.gsub(template_name, "%{%{!%}%}", "|")
end
local body = "{{" .. template_name
local continuous = true
for i = min_args, max_args do
if numberic_args[i] ~= nil then
if i <= 0 or i > skip_args then
local value = numberic_args[i]
body = body .. '|'
if i <= 0 or not continuous then
body = body .. (i - ((i > 0) and skip_args or 0)) .. '='
end
body = body .. value
end
else
if i > skip_args then continuous = false end
end
end
for key, value in pairs(text_args) do
body = body .. '|' .. key .. '=' .. value
end
body = body .. '}}'
return frame:callParserFunction( '#tag', { 'nowiki', body } )..working_frame:preprocess(body)
end
function p.printArgs(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})
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
body = ''
local function _escape(str)
return frame:extensionTag( 'code', mw.ustring.gsub(str,"%{","{"):gsub("%|","|"):gsub("%}","}") )
end
if mw.isSubsting() then
body = body .. '*1='.._escape(args[1]or 'nil')..'\n'
body = body .. '*2='.._escape(args[2]or 'nil')..'\n'
body = body .. '*3='.._escape(args[3]or 'nil')..'\n'
body = body .. '*4='.._escape(args[4]or 'nil')..'\n'
body = body .. '*(1==2)='..(((args[1]or 'nil')==(args[2]or 'nil'))and'true'or'false')..'\n'
else
body = body .. '*1='.._escape(args[1]or 'nil')..'\n'
body = body .. '*2='.._escape(args[2]or 'nil')..'\n'
body = body .. '*3='.._escape(args[3]or 'nil')..'\n'
body = body .. '*4='.._escape(args[4]or 'nil')..'\n'
body = body .. '*(1==2)='..(((args[1]or 'nil')==(args[2]or 'nil'))and'true'or'false')..'\n'
end
return body
end
function p.getPageCode(frame, args)
local input_obj, iargs
if frame == mw.getCurrentFrame() then
local pframe = iframe:getParent()
local title = iframe.args["$"] or pframe.args["$"] or ''
iargs={}
for k,v in pairs(iframe.args) do iargs[k] = v end
elseif type(frame) == type({}) then
if frame.isTypeObj == true then
input_obj = frame
end
end
end
function p.include(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})
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 keep_title
local pagename
local full_include = false
local new_args = { args["\\1"] or '' }
for arg_name, arg_value in pairs( args ) do
if arg_name == 1 or arg_name == '1' then
pagename = arg_value
elseif arg_name == "keep" or arg_name == "keep_title" or arg_name == "keep title" then
keep_title = mw.ustring.lower(arg_value)
elseif arg_name == "full_include" or arg_name == "full include" or arg_name == "full" then
if yesno == nil then yesno = require('Module:Yesno') end
full_include = yesno(mw.ustring.lower(arg_value) or 'no')
elseif arg_name == "\\1" then new_args["1"] = arg_value
else new_args[arg_name] = arg_value end
end
local titleObj = p.checkTemplateTitle(pagename)
if titleObj and titleObj.func then
return titleObj.func(mw.getCurrentFrame(),titleObj.pagename, new_args)
end
end
function p.extMagicWord(iframe,ititle,iargs)
if iframe == mw.getCurrentFrame() and ititle==nil and iargs==nil then
local pframe = iframe:getParent()
ititle = iframe.args[1] or iframe.args["1"] or iframe.args["ititle"] or iframe.args["title"] or
pframe.args[1] or pframe.args["1"] or pframe.args["ititle"] or pframe.args["title"] or ''
iargs = iframe.args
end
return iframe:callParserFunction{ name = ititle, args = iargs }
end
function p.copytable(input_table,layer)
local lyr = layer or 1
local output_table
if type(input_table) == type({}) then
output_table = {}
for k,v in pairs(input_table) do
local temp
if type(input_table) == type({}) then
if lyr<5 then
temp = mw.clone(p.copytable(v, lyr+1))
end
elseif type(input_table) == type(tonumber) then
else
temp = mw.copy(v)
end
output_table[k]=temp
end
elseif type(input_table) == type(tonumber) then
--do nothing
else
output_table = mw.clone(input_table)
end
return output_table
end
function p.checkTemplateTitle(inputTitle)
local input_title = ''
local is_invoke = false
if type(inputTitle) == type({}) then
local get_arg = (inputTitle.args or inputTitle)
if get_arg[1] or get_arg["1"] then
is_invoke = true
input_title = get_arg[1] or get_arg["1"]
else xpcall(function()
input_title = mw.dumpObject(inputTitle)
end, function(exception)end) end
else
input_title = inputTitle
end
local frame = mw.getCurrentFrame()
pagename = tostring(input_title)
if mw.text.trim(pagename or '') == '' then return end
local chaptername = ''
local input_fullpagename = tostring(pagename)
local InIsSubst, InIsSSubst, InIsMsgnw, InIsInt
pagename, InIsSubst = mw.ustring.gsub(pagename, "^subst:","")
pagename, InIsMsgnw = mw.ustring.gsub(pagename, "^msgnw:","")
pagename, InIsSSubst = mw.ustring.gsub(pagename, "^safesubst:","")
pagename, InIsInt = mw.ustring.gsub(pagename, "^int:","MediaWiki:")
pagename = mw.ustring.gsub(pagename, "^raw:","")
InIsSubst, InIsMsgnw, InIsInt = (InIsSubst > 0 or InIsMsgnw > 0), InIsMsgnw > 0, InIsInt > 0
local magic_word_check = mw.ustring.match(pagename, "^#[^#:]+:[^%|]*") --魔術字(#XX)
local output_obj = {}
local is_magic_word = false
if magic_word_check then
local function checkInArr(str,arr)for _,arrstr in ipairs(arr) do if arrstr==str then return true end end return false end
local magic_words = {"language","special","speciale"}
local ParserFunctions_data = {"expr", "if", "ifeq", "iferror", "ifexpr", "ifexist", "rel2abs", "switch", "time", "timel", "titleparts","tag"}
local ParserFunctions = {
["cexpr"] = {func=function(iframe,ititle,iargs)
local calc = require("Module:Complex_Number/Calculate")
local magic_word_title = mw.ustring.gsub(ititle, "^#[^#:]+:([^%|]*)", "%1")
return calc.calculate({magic_word_title, class="cmath"},-1)
end},
["ifcexpr"] = {func=function(iframe,ititle,iargs)
local calc = require("Module:Complex_Number/Calculate")
local magic_word_title = mw.ustring.gsub(ititle, "^#[^#:]+:([^%|]*)", "%1")
if comp_number == nil then comp_number = require("Module:Complex Number") end
local cmath = comp_number.cmath.init()
local result = calc.calc(magic_word_title, cmath, cmath.toComplexNumber)
if cmath.abs(result) <= 1e-12 then
return iargs[2] or iargs['2'] or ''
else
return iargs[1] or iargs['1'] or ''
end
end},
["ifreal"] = {func=function(iframe,ititle,iargs)
local calc = require("Module:Complex_Number/Calculate")
local magic_word_title = mw.ustring.gsub(ititle, "^#[^#:]+:([^%|]*)", "%1")
if comp_number == nil then comp_number = require("Module:Complex Number") end
local cmath = comp_number.cmath.init()
local result = calc.calc(magic_word_title, cmath, cmath.toComplexNumber)
if cmath.abs(result.imag) <= 1e-12 then
return iargs[1] or iargs['1'] or ''
else
return iargs[2] or iargs['2'] or ''
end
end},
["ifredirect"] = {func=function(iframe,ititle,iargs)
local magic_word_title = mw.ustring.gsub(ititle, "^#[^#:]+:([^%|]*)", "%1")
local check = mw.title.new(magic_word_title)
if check and check.isRedirect then
return iargs[1] or iargs['1'] or ''
else
return iargs[2] or iargs['2'] or ''
end
end},
["mw"] = {func=function(iframe,ititle,iargs)
local magic_word_title = mw.ustring.gsub(ititle, "^#[^#:]+:([^%|]*)", "%1")
magic_word_title = mw.text.trim(magic_word_title)
local magic_word_title_sp = mw.text.split(magic_word_title, '%.')
local to_exe = mw
if magic_word_title~='' then
for i=1,#magic_word_title_sp do
if to_exe[magic_word_title_sp[i]] then
to_exe = to_exe[magic_word_title_sp[i]]
else
return ''
end
end
end
local result
if type(to_exe) == type(tonumber) then
result = { to_exe(unpack(iargs)) }
elseif to_exe then
result = to_exe
else
return ''
end
local body = ''
for _,val in ipairs(result) do
if type(val) == type({}) then
body = body .. mw.text.jsonEncode(p.copytable(val)) .. ' '
elseif val then
if mw.text.trim(tostring(val)) ~= '' then
body = body .. tostring(val) .. ''
end
end
end
return body
end},
}
for _, psit in ipairs(ParserFunctions_data) do
ParserFunctions[psit] = {func=p.extMagicWord}
end
local magic_word_name = mw.ustring.gsub(magic_word_check, "^#([^#:]+):[^%|]*", "%1")
local magic_word_title = mw.ustring.gsub(magic_word_check, "^#[^#:]+:([^%|]*)", "%1")
if magic_word_name=="invoke" then
output_obj = {pagename="Module:" .. magic_word_title,magic_word=true,invoke=true}
is_magic_word=true
elseif ParserFunctions[magic_word_name] then
output_obj = {pagename=magic_word_check,functionname=magic_word_name, func=ParserFunctions[magic_word_name].func, magic_word=true}
is_magic_word=true
elseif checkInArr(magic_word_name, magic_words) then
output_obj = {pagename=magic_word_check,magic_word=true}
is_magic_word=true
end
end
if is_magic_word and not output_obj.invoke then
output_obj.isTypeObj = true
if is_invoke then return mw.dumpObject(output_obj) end
return output_obj
elseif output_obj.pagename then
pagename = output_obj.pagename
end
local mark_pos,_ = mw.ustring.find(pagename, '%#') --分析章節語法(#)
if mark_pos then
chaptername = mw.ustring.sub(pagename,mark_pos+1,#pagename)
pagename = mw.ustring.sub(pagename,1,mark_pos-1)
end
local chapterfullname = tostring(chaptername)
local chapterid = 1
mark_pos = mw.ustring.find(chapterfullname, "%_%d+$") --分析章節語法(_)
if mark_pos then
chaptername = mw.ustring.sub(chapterfullname,1,mark_pos-1)
chapterid = tonumber(mw.ustring.sub(chapterfullname,mark_pos+1,#chapterfullname)) or 1
end
local chapterothername = tostring(chaptername)
local body = ''
if mw.text.trim(pagename) == '' then return end
--取得引用頁名稱
local check_includetitle, is_namespace0 = mw.text.trim(pagename), 0
check_includetitle, is_namespace0 = mw.ustring.gsub(check_includetitle, "^%s-:+","")
local check_includetitle_obj = (mw.title.new( check_includetitle ) or {})
local check_includetitle_namespace = check_includetitle_obj.namespace or 10
local check_isExternal = check_includetitle_obj.isExternal
if check_isExternal == nil then check_isExternal = false end
if check_includetitle_namespace == 0 and is_namespace0 > 0 and not check_isExternal then --有冒號表示指名名字空間(預設是 Template )
check_includetitle = mw.title.new( check_includetitle )
elseif check_includetitle_namespace == 0 and not check_isExternal then --沒有冒號表示預設是 Template
check_includetitle = mw.title.new( "Template:" .. check_includetitle )
else --其餘情況就用解析到的名字空間
check_includetitle = mw.title.new( check_includetitle )
end
if check_includetitle == nil then check_includetitle = check_includetitle or {
fullText = mw.text.trim(pagename) , text = mw.text.trim(pagename), isErrorTitle=true
} end
output_obj.orginalpagename = pagename
pagename=check_includetitle.fullText
if mw.text.trim(chapterfullname) ~= '' then output_obj.fullpagename = pagename.. '#' .. chapterfullname
else output_obj.fullpagename = pagename end
local redirectTarget = check_includetitle.redirectTarget
if redirectTarget ~= false and redirectTarget ~= nil then check_includetitle = redirectTarget end
output_obj.titleObj = check_includetitle
pagename=check_includetitle.fullText
if check_includetitle.namespace == mw.title.new( "Template:1" ).namespace then
output_obj.includePagename = mw.ustring.gsub(pagename, "^Template:", "")
elseif check_includetitle.namespace == mw.title.new( "MediaWiki:1" ).namespace then
output_obj.includePagename = mw.ustring.gsub(pagename, "^MediaWiki:", "int:")
elseif check_includetitle.namespace == mw.title.new( "1" ).namespace then
output_obj.includePagename = mw.ustring.gsub(pagename, "^:*", ":")
end
output_obj.chapterfullname = chapterfullname
output_obj.chaptername = chaptername
output_obj.isTypeObj = true
if is_invoke then return mw.dumpObject(output_obj) end
return output_obj
end
return p