local p = {}
local lib_arg = {}
local lib_va = require("Module:Va")
local function getTitle(title)
mw.log(title)
local success_call, template_obj = pcall(mw.title.new, title, "Template")
if not success_call then return nil end
if not template_obj then return nil end
success_call, template_obj = pcall(mw.title.new, lib_va.redirect_target(template_obj.fullText))
if not success_call then return nil end
if not template_obj then return nil end
return template_obj
end
local depth = 0
function p.build_template(frame)
depth = depth + 1
local args, working_frame
local inner_args
--參數和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})
inner_args = frame.args
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
inner_args = args
end
local template_name = args["@&$$~~!_template_name_!~~$$&@"] or 'void'
local template_obj = getTitle(template_name)
if template_obj and not template_obj.exists then
local blib_obj = getTitle("User:Bluedecklibrary/"..template_obj.fullText)
if blib_obj.exists then
local success_call, template_body = xpcall(function()return blib_obj:getContent()end,function(err)return err end)
if success_call and mw.text.trim(template_body or "") ~= "" then
template_body = mw.ustring.gsub(template_body, "%{%{%s*user%s*:%s*bluedeck%s*/%s*infr%s*/%s*library%.card","{{void|")
--關於noinclude、includeonly和onlyinclude的regexp
local re_noinclude_head = "<%s*[Nn][Oo][Ii][Nn][Cc][Ll][Uu][Dd][Ee]%s*>"
local re_noinclude_tail = "<%s*/%s*[Nn][Oo][Ii][Nn][Cc][Ll][Uu][Dd][Ee]%s*>"
local re_noinclude = "<%s*/?%s*[Nn][Oo][Ii][Nn][Cc][Ll][Uu][Dd][Ee]%s*/?%s*>"
local re_includeonly = "<%s*/?%s*[Ii][Nn][Cc][Ll][Uu][Dd][Ee][Oo][Nn][Ll][Yy]%s*/?%s*>"
local re_onlyinclude = "<%s*/?%s*[Oo][Nn][Ll][Yy][Ii][Nn][Cc][Ll][Uu][Dd][Ee]%s*/?%s*>"
local re_removes = {{"noinclude",re_noinclude}, {"includeonly",re_includeonly}, {"onlyinclude",re_onlyinclude}}
--摘除模板樣板中的noinclude與當中的內容
local noinclude, _i = mw.ustring.find(template_body, re_noinclude_head), 1
while noinclude do --如果找到<noinclude>
--尋找</noinclude>
local _, noinclude_end = mw.ustring.find(template_body, re_noinclude_tail)
--如無</noinclude>,視為noinclude到頁面結尾
noinclude_end = noinclude_end or -1
--去除掉<noinclude>...</noinclude>與其之間的內容
template_body = mw.ustring.sub(template_body, 1, noinclude-1) .. ((noinclude_end < 0) and "" or mw.ustring.sub(template_body, noinclude_end + 1, -1))
--尋找下一個<noinclude>
noinclude = mw.ustring.find(template_body, re_noinclude_head)
_i = _i + 1 --避免無窮迴圈
if _i > 100 then mw.addWarning(module_warn..'<noinclude>過多') break end
end --<noinclude></noinclude>內容移除完畢
--移除其他會影響解析功能的標籤
for _, to_remove in pairs(re_removes) do _i = 1
--處理巢狀引用
local remove_count = 1 --紀錄移除數量
while (tonumber(remove_count) or 0) > 0 do --如果還有殘留的相關標籤
--移除殘留的相關標籤,並記錄移除數量
template_body, remove_count = mw.ustring.gsub(template_body, to_remove[2], "")
_i = _i + 1 --避免無窮迴圈
if _i > 100 then mw.addWarning(module_warn..'<'..to_remove[1]..'>過多') break end
end --如果沒有殘留的相關標籤則結束迴圈
end
template_body = mw.ustring.gsub(template_body, "%{%{%s*user%s*:%s*bluedeck%s*/%s*infr%s*/%s*library%.card","{{void|")
template_body = mw.ustring.gsub(template_body, "%{%{%(%(%}%}","{{")
template_body = mw.ustring.gsub(template_body, "%[%[:?(分[類类]):","[[%1:")
template_body = mw.ustring.gsub(template_body, "%[%[:?([Cc][Aa][Tt]):","[[%1:")
template_body = mw.ustring.gsub(template_body, "%[%[:?([Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]):","[[%1:")
local child_frame = working_frame:newChild{ title = template_obj.fullText, args = args }
blib_result = child_frame:preprocess(template_body)
local target = nil
mw.ustring.gsub(blib_result, "^[%s\n\r]*#[^%[%]]+%[%[([^%[%]]+)%]%]", function(str) target = str end)
if type(target) ~= type(nil) then
if depth > 10 then return blib_result end
return p.build_template({["@%&$$~~!_template_name_!~~$$&%@"]=target})
end
return blib_result
end
end
end
return working_frame:expandTemplate{ title = ':'..template_obj.fullText, args = args }
end
return p