跳转到内容

模組:沙盒/a2569875/UserPageFunc

维基百科,自由的百科全书
--[[
<includeonly><onlyinclude>{{#invoke:沙盒/a2569875/UserPageFunc|getTemplateVar|:{{FULLPAGENAME}}|Polyhedronbox|Face}}</onlyinclude></includeonly>
]]
local p={}
local lib_arg={};
local lib_para = {}
p.SUBTable = {}
function p.getlest()
	--{{#invoke:沙盒/a2569875/UserPageFunc|getlest}}
	local frame = mw.getCurrentFrame()
	local body = ''
	local result = mw.text.split(frame.args[1] or frame.args['1'], frame.args[2] or frame.args['2'])
	if result then
		return result[#result]
	end
	return ''
end
function p.testParOrder()
	--{{#invoke:沙盒/a2569875/UserPageFunc|testParOrder}}
	local frame = mw.getCurrentFrame()
	local body = ''
	for v,k in frame:argumentPairs() do
		body = body .. '*參數' ..  v .. '值為' .. k .. '\n'
	end
	return body
end
function p.delUINQ(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_text = mw.text.trim(args["1"] or args[1] or "")
    return mw.ustring.gsub(input_text,"\127",'')
end

function _re_escape(input) return mw.ustring.gsub(input, "[%%%[%]|%(%)"..[[\]].."%{%}%.%^%$%*%+%-%?]", function(t) return (t==[[\]] and [[\]] or '%')..t end)end
function p._getSumm(article, useSub)
	local title = mw.title.new(article)
	local article_title = (title or {}).fullText or article
	local article_url = article_title
	local context = ""
	if (title or {}).isRedirect then
		title = title.redirectTarget or title
		article_url = (title or {}).fullText or article_url
	end
	if (title or {}).namespace == 0 then
		context = title.content or ''
	end
	local template_list = {}
	local link_list = {}
	local t01 = ''..context
	local nestrepl = ''..t01
	local old_repl = ''..t01
	
	local char_start, char_end = mw.ustring.find(nestrepl, "[\n\r]+%s*===*[^=]*[腳角人][色物][^=]*=*==%s*[\n\r]+")
	if useSub and char_start then
		local sub_data = {}
		
		if p.SUBTable[article_title] then sub_data = p.SUBTable[article_title] mw.log("use exist",article_title)
		else
			local eq=nil
			local find_text = mw.ustring.sub(nestrepl, char_start-1, #nestrepl-1)
			
			mw.ustring.gsub(mw.ustring.sub(nestrepl, char_start-1, char_end+1), "[\n\r]+%s*(===*)[^=]*[腳角人][色物][^=]*=*==%s*[\n\r]+", function(_eq)eq=eq or _eq return ''end)
			eq=eq or '='
			find_text = mw.ustring.sub(nestrepl, char_end+1, #nestrepl-1)
			char_end = mw.ustring.find(find_text, "[\n\r]+%s*"..eq.."[^=]+"..eq.."%s*[\n\r]+")
			find_text = '\n'..mw.ustring.sub(find_text, 1, char_end)
			char_end = 0
			repeat
				char_start, char_end = mw.ustring.find(find_text, "[\n\r]+;[^\n\r]+[\n\r]+", char_end + 1)
				if char_start == nil then break end
				char_start = char_start - 1
				if char_start < 1 then char_start = 1 end
				local c_start, c_end = mw.ustring.find(find_text, "[\n\r]+;[^\n\r]+[\n\r]+", char_end + 1)
				if c_start==nil then c_start=#find_text-1 end
				local char_title = mw.text.trim(mw.ustring.gsub('\n'..mw.ustring.sub(find_text, char_start + 1, char_end - 1), "[\n\r]+;", ""))
				local char_desc = mw.text.trim(mw.text.trim(mw.ustring.gsub('\n'..char_title, "[\n\r]+;", "")) .. '是' .. 
					mw.text.trim(mw.ustring.gsub('\n'..
					mw.ustring.gsub('\n'..mw.ustring.sub(find_text, char_end + 1, c_start), 
					"[\n\r]+=+[^=]+=+%s*[\n\r]+", "\n"), "[\n\r]+:?", " ")))
				local chat_name = nil
				char_title = mw.text.trim(mw.ustring.gsub(char_title, "[\n\r]+", " "))
				mw.ustring.gsub(char_title, "|%[*([^%[{|}%]]+)%]*[|}]", function(_name)chat_name = chat_name or _name end)
				if chat_name then
					sub_data[chat_name] = {name=chat_name, title=char_title, desc=char_desc}
				end
			until char_start == nil
			mw.log("create",article_title)
			p.SUBTable[article_title] = sub_data
		end
		local all_char = {}
		for _key,_val in pairs(sub_data) do if _val.title then all_char[#all_char + 1]=_key end end
		if #all_char > 1 then
			local newID = math.random(1,#all_char)
			nestrepl = sub_data[all_char[newID]].desc
			article_title = sub_data[all_char[newID]].name
			article_url = article_url..'#'..article_title
			local sent = mw.text.split(nestrepl,"。")
			nestrepl = ''
			for si = 1,6 do
				if si < #sent then
					nestrepl = nestrepl .. sent[si] .. '。'
				end
			end
			if mw.text.trim(mw.ustring.gsub(nestrepl,"[%s\n\r,./\\;'%[%]%{%},.;:<>=%%%?]+","")) == '' then
				nestrepl = "[["..article_url.."|"..article_title.."]]是"
			end
			return ('<span class=\"article-start\"></span>'..nestrepl), article_title, article_url
		end
	end
	
	repeat
		old_repl = nestrepl
		nestrepl = mw.ustring.gsub(nestrepl, "{{([^{}]*)}}", function(name)
			local src = "{{"..name.."}}"
			local template_name = mw.ustring.match(src, "{{([^{|}]*)[{|}]")
			template_list[#template_list + 1] = src
			return "╠├═"..#template_list.."═┤╣"
		end)
		nestrepl = mw.ustring.gsub(nestrepl, "%[%[([^%[%]]*)%]%]", function(name)
			local src = "[["..name.."]]"
			local template_name = mw.ustring.match(src, "%[%[([^%[|%]]*)[%[|%]]")
			link_list[#link_list + 1] = src
			return "╠├[═"..#link_list.."═]┤╣"
		end)
	until nestrepl == old_repl
	old_repl = ''..nestrepl
	repeat
		old_repl = nestrepl
		nestrepl = mw.ustring.gsub(nestrepl, "([%s \t]*)[\n\r]+", "%1\n")
		nestrepl = mw.ustring.gsub(nestrepl, "╠├═%d+═┤╣[%s \t]*\n", "\n")
		nestrepl = mw.ustring.gsub(nestrepl, "╠├%[═%d+═%]┤╣[%s \t]*\n", "\n")
	until nestrepl == old_repl
	local sent = mw.text.split(nestrepl,"。")
	nestrepl = ''
	for si = 1,6 do
		if si < #sent then
			nestrepl = nestrepl .. sent[si] .. '。'
		end
	end
	old_repl = ''..nestrepl
	repeat
		old_repl = nestrepl
		nestrepl = mw.ustring.gsub(nestrepl, "╠├═(%d+)═┤╣", function(tid)
			local id = tonumber(tid)
			if ({mw.ustring.gsub(mw.ustring.lower(''..(id or 'nan')), "[+-]*", "")})[1] ~= 'nan' and (template_list[id] or false) then
				return template_list[id]
			end
			return "╠├═"..tid.."═┤╣"
		end)
		nestrepl = mw.ustring.gsub(nestrepl, "╠├%[═(%d+)═%]┤╣", function(tid)
			local id = tonumber(tid)
			if ({mw.ustring.gsub(mw.ustring.lower(''..(id or 'nan')), "[+-]*", "")})[1] ~= 'nan' and (link_list[id] or false) then
				return link_list[id]
			end
			return "╠├[═"..tid.."═]┤╣"
		end)
	until nestrepl == old_repl

	nestrepl = mw.ustring.gsub(nestrepl, "([%s \t]*)[\n\r]+", "%1\n")
	nestrepl = mw.ustring.gsub(nestrepl, "<[%s \t\n\r]*ref[^<>]*/>", '')
	nestrepl = mw.ustring.gsub(nestrepl, "<[%s \t\n\r]*ref", '<span style="display:none; "')
	nestrepl = mw.ustring.gsub(nestrepl, "<[%s \t\n\r]*/[%s \t\n\r]*ref", '</span')
	nestrepl = mw.ustring.gsub(nestrepl, "{{[%s \t\n\r]*#tag[%s \t\n\r]*:[%s \t\n\r]*ref", '{{void|')
	nestrepl = mw.ustring.gsub(nestrepl, "{{[^{|}]*[Ii][Nn][Ff][Oo][%s \t\n\r]*[Bb][Oo][Xx]", "{{void|")
	nestrepl = mw.ustring.gsub(nestrepl, "{{[%s \t\n\r]*[Rr][Pp]", "{{void|")
	nestrepl = mw.ustring.gsub(nestrepl, "{{[%s \t\n\r]*[^|}]*[Bb][Oo][Xx]", "{{void|")
	nestrepl = mw.ustring.gsub(nestrepl, "{{[%s \t\n\r]*[Dd][Ee][Ll]", "{{void|")
	nestrepl = mw.ustring.gsub(nestrepl, "%{%{[^%{%}|:]*[Cc][Ii][Tt][AaEe][^%{%}|:]*[^%{%}|:]*([%{%}|:])", "{{void|%1")
	nestrepl = mw.ustring.gsub(' '..nestrepl, "([^{]){|", "%1{{void|")
	nestrepl = mw.ustring.gsub(nestrepl..' ', "|}([^}])", "}}%1")
	nestrepl = mw.ustring.gsub(nestrepl, "([,,。;;、][%s\n\r ]*)", "%1 ")
	
	nestrepl = mw.ustring.gsub(nestrepl, "%{%{[^%{%}|:]*[Pp][Aa][Gg][Ee][^%{%}|:]*[Nn][Aa][Mm][Ee][^%{%}|:]*([%{%}|:])", "{{p1|<b>[[".. article .. "]]</b>|%1")
	nestrepl = mw.ustring.gsub(nestrepl, "('''" .. _re_escape(article) .. "''')", "[[" .. article .. "|%1]]")
	if (title or {}).fullText ~= article then nestrepl = mw.ustring.gsub(nestrepl, "('''" .. _re_escape(title.fullText) .. "''')", "[[" .. article .. "|%1]]") end

	local f_end = mw.ustring.find('\n'..nestrepl , "[\n\r][%s \n\r\t]*=+[^=]+=+" )
	nestrepl = mw.text.trim(mw.ustring.gsub(mw.ustring.sub(nestrepl, 1, (f_end or 0) - 1),"[\n\r]*", ""))
	if #nestrepl < (#article + 4) or not mw.ustring.find(nestrepl, "[,,。;;、]") then nestrepl = p.pageWikidataGen(article) end
	local check_p = mw.getCurrentFrame():preprocess{ text = nestrepl }
	if #check_p < (#article + 4) or not mw.ustring.find(check_p, "[,,。;;、]") then nestrepl = p.pageWikidataGen(article) end
	nestrepl = '<span class=\"article-start\"></span>'..nestrepl
	local image = (title or {}).pageImage
	if image or false then
		local file_path = mw.ustring.gsub(image,"^%s*[^:]+:","File:")
		local is_comm = not (mw.title.new(file_path, "File") or {}).exists
		if is_comm then --只顯示共享資源圖像。本地圖像可能是合理使用圖像,不應於非條目之處顯示
			nestrepl = "[["..file_path.."|x140px|left|"..article.."]]"..nestrepl
		end
	end
	return nestrepl, article_title, article_url
end

function p.insertArticleStart(preview, insertText)
	local result = mw.ustring.gsub(preview or '', '(<%s*[Ss][Pp][Aa][Nn]%s+class="article%-start"%s*>)', '%1'..insertText)
	return result
end

function p.getSumm(frame)
	-- For calling from #invoke.
    local args
    local is_template
    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) --frame.args
        is_template = true
    else
        -- We're being called from another module or from the debug console, so assume
        -- the args are passed in directly.
        if type(frame) ~= type({}) then args = {frame}
        else args = frame end
    end
    local body = p._getSumm(args[1]or args['1'])
    if is_template then
    	return mw.getCurrentFrame():preprocess{ text = body }
    end
	return body
end

function p.pageAssessment(article)
	local flag, title = pcall(mw.title.new, article)
	if flag and title then
	flag, title = xpcall(function()
	for _,data in pairs((title or {}).pageAssessments or {}) do
	if mw.text.trim((data or {}).class or '') ~= '' then 
		if data.class ~= "未评" then return data.class end
	end end end,function() return '' end) end
	return title
end

function p.pageWikidataGen(article)
	local success, entid = pcall(mw.wikibase.getEntityIdForTitle, (article or {}).fullText or article or '')
	local title = (article or {}).fullText or article or ''
	local body = ""
	if success and mw.text.trim(entid or '')~='' then
		body = "[["..title.."|'''"..title.."''']]是"
		local wdItem = mw.wikibase.getEntity(entid)
		local desclang = {'zh','zh-hant','zh-hans','zh-cn','zh-hk','zh-sg','zh-mo','zh-tw'}
		if mw.ustring.lower((wdItem or {})["type"] or '') == "item" then
			local wikibase = mw.wikibase
			local label = ''
			for _,lang in ipairs(desclang) do
				success, label = pcall(function(lang)return wdItem:getLabelWithLang(lang)end, lang)
				if mw.text.trim(label or '')~='' then break end
			end
			if mw.text.trim(label or '')~='' then
				body = "[["..title.."|'''"..label.."''']]是"
			end
			local desc = ''
			for _,lang in ipairs(desclang) do
				local gotDesc = ''
				success, gotDesc = pcall(function(lang)return wdItem:getDescriptionWithLang(lang)end, lang)
				if #(mw.text.trim(gotDesc or '')) > #desc then desc = mw.text.trim(gotDesc or '') end
			end
			local getBestStatements = function(pid)return wdItem:getBestStatements(pid)end
			local pdata = {}
			local aType = {}
			success, pdata = pcall(getBestStatements, 'P360')
			if success and (pdata or {})[1] then
				for _, data in ipairs(pdata) do
					if (data or {}).mainsnak then
						local datavalue = data.mainsnak.datavalue or {}
						if (datavalue.value or {}).id then
							aType[#aType + 1] = "{{link-wd|"..datavalue.value.id.."}}的列表"
						end
					end
				end
			end
			if #aType <= 0 then
				success, pdata = pcall(getBestStatements, 'P279')
				if success and (pdata or {})[1] then
					for _, data in ipairs(pdata) do
						if (data or {}).mainsnak then
							local datavalue = data.mainsnak.datavalue or {}
							if (datavalue.value or {}).id then
								aType[#aType + 1] = "{{link-wd|"..datavalue.value.id.."}}"
							end
						end
					end
				end
			end
			if #aType <= 0 then
				success, pdata = pcall(getBestStatements, 'P31')
				if success and (pdata or {})[1] then
					for _, data in ipairs(pdata) do
						if (data or {}).mainsnak then
							local datavalue = data.mainsnak.datavalue or {}
							if (datavalue.value or {}).id then
								aType[#aType + 1] = "{{link-wd|"..datavalue.value.id.."}}"
							end
						end
					end
				end
			end
			if #aType > 0 then
				body=body..table.concat(aType, '也是')
			elseif mw.text.trim(desc or '')~='' then
				body=body..desc
			end
		end
	end
	return body
end
function _setRandomSeed()
	local seed = tonumber(mw.ustring.gsub(mw.getCurrentFrame():preprocess{ text = "{{NUMBEROFEDITS}}" },',',"")..'')
	while not seed do
		seed = tonumber(mw.ustring.gsub(mw.getCurrentFrame():preprocess{ text = "{{NUMBEROFEDITS}}" },',',"")..'')
	end
	math.randomseed( tonumber( mw.getContentLanguage():formatDate( "U" ) ) * 10000 + seed )
end

function p.randomDCA(frame)
	-- For calling from #invoke.
    local args
    local is_template
    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) --frame.args
        is_template = true
    else
        -- We're being called from another module or from the debug console, so assume
        -- the args are passed in directly.
        if type(frame) ~= type({}) then args = {frame}
        else args = frame end
    end
	local max_arctiles = tonumber(args['1'] or args[1]) or -1
	if mw.ustring.gsub(''..max_arctiles,"^[^\n\r]*[NnIi][AaNn][NnFf][^\n\r]*$", "nan") == "nan" or (tonumber(max_arctiles) or -1) <= 0 then 
		max_arctiles = 4
	end
	local count = max_arctiles
	_setRandomSeed()
	local dcsjson = mw.loadJsonData( "User:A2569875/DCs.json")
	local DCs = {}
	for __,item in ipairs(dcsjson) do DCs[1+#DCs]=item end
	local selectedDC = {}
	for i=1,count do
		local newID = math.random(1,1+#DCs)
		local isNew = true
		repeat
			isNew = true
			newID = math.random(1,1+#DCs)
			for j=1,#selectedDC do
				if selectedDC[j]==newID then
					isNew=false
					break
				end
			end
		until isNew == true and newID <= #DCs
		selectedDC[1+#selectedDC]=newID
	end
	local body = ""
	for i=1,count,2 do
		body = body .. '\n|-'
		for j=1,2 do
			local k=i+j-1
			if k<=count then
				body = body .. '\n|'
				local ass = p.pageAssessment(DCs[selectedDC[k]].name)
				local article, article_name, article_path = p._getSumm(DCs[selectedDC[k]].name, (math.random(3)==1)and 1 or nil)
				if ass then article = p.insertArticleStart(article, "{{Class/icon|"..ass.."}}") end
				--if #article > 320 then
				--	article = mw.ustring.sub(article,1,320)..'...\n[['..DCs[selectedDC[k]].name..'|閱讀更多]]'
				--end
				body = body .. article..'...\n[['..article_path..'|閱讀更多]]'
			end
		end
	end
    if is_template then
    	return mw.getCurrentFrame():preprocess{ text = body }
    end
	return body
end

function p.listRandomA(frame)
	-- For calling from #invoke.
    local args
    local is_template
    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) --frame.args
        is_template = true
    else
        -- We're being called from another module or from the debug console, so assume
        -- the args are passed in directly.
        if type(frame) ~= type({}) then args = {frame}
        else args = frame end
    end
	_setRandomSeed()
	local max_arctiles = tonumber(args['1'] or args[1]) or -1
	if mw.ustring.gsub(''..max_arctiles,"^[^\n\r]*[NnIi][AaNn][NnFf][^\n\r]*$", "nan") == "nan" or (tonumber(max_arctiles) or -1) <= 0 then 
		max_arctiles = 100
	end
	local maxID = tonumber(mw.ustring.gsub(mw.getCurrentFrame():preprocess{ text = "{{NUMBEROFPAGES}}" },',',"")..'')
	while not maxID do
		maxID = tonumber(mw.ustring.gsub(mw.getCurrentFrame():preprocess{ text = "{{NUMBEROFPAGES}}" },',',"")..'')
	end
	local total = tonumber(mw.ustring.gsub(mw.getCurrentFrame():preprocess{ text = "{{NUMBEROFARTICLES}}" },',',"")..'')
	while not total do
		total = tonumber(mw.ustring.gsub(mw.getCurrentFrame():preprocess{ text = "{{NUMBEROFARTICLES}}" },',',"")..'')
	end
	local id_pool = {}
	local nextArticle = function()
		repeat
			local find_id = math.random(1,maxID)
			local new_id = true
			repeat
				find_id = math.random(1,maxID)
				for j=1,#id_pool do
					if id_pool[j] == find_id then
						new_id = false
						break
					end
				end
			until new_id
			id_pool[#id_pool + 1] = find_id
			article = mw.title.new(find_id)
			if (article or {}).isRedirect then
				article = article.redirectTarget or article
			end
			if (article or {}).namespace == 1 then
				article = article.subjectPageTitle or article
				if (article or {}).isRedirect then
					article = article.redirectTarget or article
				end
			end
			mw.log(" - find",article)
		until (article or {}).namespace == 0 and not (article or {}).isDisambiguationPage
		return article
	end
	local body = ''
	for i=1,max_arctiles do
		local success, article = pcall(nextArticle)
		if not success then break end
		body = body .. '\n*[['..article.fullText..']]'
	end
	return body
end

function p.findAinP(article)
	local title = article
	if tonumber((title or {}).namespace) == nil then return article end
	if (title.namespace or 0) > 1 then
		local content = ''
		for i=1,2 do
			mw.log(" - check [["..(((title or {}).fullText or article) or '').."]]")
			content = mw.ustring.sub(title.content or '',1,10000)
			local finded, last_find = nil, nil
			mw.ustring.gsub(content, "%[%[([^%[|%]{:/\\#}]+)[{#|}%]]", function(_article)
				last_find = last_find or _article
				if math.random(3)==1 then
					finded = finded or _article
				end
			end)
			finded = finded or last_find
			if finded then
				mw.log(" - find [["..finded.."]] in "..(((article or {}).fullText or article) or ''))
				return finded
			end
			if title.isTalkPage then
				title = title.subjectPageTitle or title
				content = mw.ustring.sub(title.content or '',1,10000)
			else break
			end
		end
	end
	return article
end

function p.randomALLA(frame)
	-- For calling from #invoke.
    local args
    local is_template
    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) --frame.args
        is_template = true
    else
        -- We're being called from another module or from the debug console, so assume
        -- the args are passed in directly.
        if type(frame) ~= type({}) then args = {frame}
        else args = frame end
    end
	_setRandomSeed()
	local max_arctiles = tonumber(args['1'] or args[1]) or -1
	if mw.ustring.gsub(''..max_arctiles,"^[^\n\r]*[NnIi][AaNn][NnFf][^\n\r]*$", "nan") == "nan" or (tonumber(max_arctiles) or -1) <= 0 then 
		max_arctiles = 4
	end
	local selected_arctile = {}
	local article_checker = function(article)
		return true
	end
	local maxID = tonumber(mw.ustring.gsub(mw.getCurrentFrame():preprocess{ text = "{{NUMBEROFPAGES}}" },',',"")..'')
	while not maxID do
		maxID = tonumber(mw.ustring.gsub(mw.getCurrentFrame():preprocess{ text = "{{NUMBEROFPAGES}}" },',',"")..'')
	end
	local total = tonumber(mw.ustring.gsub(mw.getCurrentFrame():preprocess{ text = "{{NUMBEROFARTICLES}}" },',',"")..'')
	while not total do
		total = tonumber(mw.ustring.gsub(mw.getCurrentFrame():preprocess{ text = "{{NUMBEROFARTICLES}}" },',',"")..'')
	end
	local id_pool = {}
	maxID = total + maxID
	local article = nil
	for i=1,max_arctiles do
		repeat
			local find_id = math.random(1,maxID)
			local new_id = true
			repeat
				find_id = math.random(1,maxID)
				for j=1,#id_pool do
					if id_pool[j] == find_id then
						new_id = false
						break
					end
				end
			until new_id
			id_pool[#id_pool + 1] = find_id
			article = mw.title.new(find_id)
			article = p.findAinP(article)
			if (article or {}).isRedirect then
				article = article.redirectTarget or article
			end
			if (article or {}).namespace == 1 then
				article = article.subjectPageTitle or article
				if (article or {}).isRedirect then
					article = article.redirectTarget or article
				end
			end
			local vaild,success = pcall(article_checker, article)
			mw.log(" - find",article)
			if not(vaild and success) then article = nil end
		until (article or {}).namespace == 0 and not (article or {}).isDisambiguationPage and #(((article or {}).content) or '') > 2750
		selected_arctile[#selected_arctile + 1] = article.fullText
		mw.log("selected",article)
	end
	local body = ""
	for i=1,max_arctiles,2 do
		body = body .. '\n|-'
		for j=1,2 do
			local k=i+j-1
			if k<=max_arctiles then
				body = body .. '\n|'
				local ass = p.pageAssessment(selected_arctile[k])
				local article, article_name, article_path = p._getSumm(selected_arctile[k],(math.random(3)==1)and 1 or nil)
				if ass then article = p.insertArticleStart(article, "{{Class/icon|"..ass.."}}") end
				--if #article > 320 then
				--	article = mw.ustring.sub(article,1,320)..'...\n[['..selected_arctile[k]..'|閱讀更多]]'
				--end
				body = body .. article..'...\n[['..article_path..'|閱讀更多]]'
			end
		end
	end
    if is_template then
    	return mw.getCurrentFrame():preprocess{ text = body }
    end
	return body
end

function p.randomALLVa(frame)
	-- For calling from #invoke.
    local args
    local is_template
    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) --frame.args
        is_template = true
    else
        -- We're being called from another module or from the debug console, so assume
        -- the args are passed in directly.
        if type(frame) ~= type({}) then args = {frame}
        else args = frame end
    end
	_setRandomSeed()
	local max_arctiles = tonumber(args['1'] or args[1]) or -1
	if mw.ustring.gsub(''..max_arctiles,"^[^\n\r]*[NnIi][AaNn][NnFf][^\n\r]*$", "nan") == "nan" or (tonumber(max_arctiles) or -1) <= 0 then 
		max_arctiles = 4
	end
	local selected_arctile = {}
	
	local id_pool = {}
	local article = nil
	for i=1,max_arctiles do
		repeat
			local db = nil
			repeat db = mw.title.new("Wikipedia:基礎條目/資料/"..(function(id) if id <= 10 then return ''..(id-1) else return string.char(54+id) end end)(math.random(1,36))..".json", "Wikipedia") until (db or {}).exists
			db = mw.loadJsonData(db.fullText)
			local articles = {}
			for articleName,articleData in pairs(db) do articles[#articles + 1] = articleName end
			local find_id = nil
			local new_id = true
			repeat
				find_id = articles[math.random(1,#articles)]
				for j=1,#id_pool do
					if id_pool[j] == find_id then
						new_id = false
						break
					end
				end
			until new_id
			id_pool[#id_pool + 1] = find_id
			article = mw.title.new(find_id)
			if (article or {}).isRedirect then
				article = article.redirectTarget or article
			end
			mw.log(" - find",article)
		until (article or {}).namespace == 0 and not (article or {}).isDisambiguationPage and #(((article or {}).content) or '') > 2750
		selected_arctile[#selected_arctile + 1] = article.fullText
		mw.log("selected",article)
	end
	local body = ""
	for i=1,max_arctiles,2 do
		body = body .. '\n|-'
		for j=1,2 do
			local k=i+j-1
			if k<=max_arctiles then
				body = body .. '\n|'
				local ass = p.pageAssessment(selected_arctile[k])
				local article, article_name, article_path =p._getSumm(selected_arctile[k],(math.random(3)==1)and 1 or nil)
				if ass then article = p.insertArticleStart(article, "{{Class/icon|"..ass.."}}") end
				--if #article > 320 then
				--	article = mw.ustring.sub(article,1,320)..'...\n[['..selected_arctile[k]..'|閱讀更多]]'
				--end
				body = body .. article..'...\n[['..article_path..'|閱讀更多]]'
			end
		end
	end
    if is_template then
    	return mw.getCurrentFrame():preprocess{ text = body }
    end
	return body
end

function p.randomALLCVa(frame)
	-- For calling from #invoke.
    local args
    local is_template
    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) --frame.args
        is_template = true
    else
        -- We're being called from another module or from the debug console, so assume
        -- the args are passed in directly.
        if type(frame) ~= type({}) then args = {frame}
        else args = frame end
    end
	_setRandomSeed()
	local max_arctiles = tonumber(args['1'] or args[1]) or -1
	if mw.ustring.gsub(''..max_arctiles,"^[^\n\r]*[NnIi][AaNn][NnFf][^\n\r]*$", "nan") == "nan" or (tonumber(max_arctiles) or -1) <= 0 then 
		max_arctiles = 4
	end
	local selected_arctile = {}
	
	local id_pool = {}
	local article = nil
	for i=1,max_arctiles do
		local retrys = 20
		repeat
			local articles = {}
			local avoid_timeout = 20
			repeat
				local db = nil
				repeat db = mw.title.new("Wikipedia:基礎條目/資料/"..(function(id) if id <= 10 then return ''..(id-1) else return string.char(54+id) end end)(math.random(1,36))..".json", "Wikipedia") until (db or {}).exists
				db = mw.loadJsonData(db.fullText)
				for articleName,articleData in pairs(db) do 
					if (articleData.article_info_of_base_page or {})["Wikipedia:中文領域基礎條目"] then
						articles[#articles + 1] = articleName 
					end
				end
				avoid_timeout = avoid_timeout - 1
				if avoid_timeout < 0 then break end
			until #articles > 100
			local find_id = nil
			local new_id = true
			avoid_timeout = 20
			repeat
				find_id = articles[math.random(1,#articles)]
				for j=1,#id_pool do
					if id_pool[j] == find_id then
						new_id = false
						break
					end
				end
				avoid_timeout = avoid_timeout - 1
				if avoid_timeout < 0 then break end
			until new_id
			id_pool[#id_pool + 1] = find_id
			article = mw.title.new(find_id)
			if (article or {}).isRedirect then
				article = article.redirectTarget or article
			end
			mw.log(" - find",article)
			retrys = retrys - 1
			if retrys < 0 then
				mw.log(" - retry too many times... use=",article)
				break
			end
		until (article or {}).namespace == 0 and not (article or {}).isDisambiguationPage and #(((article or {}).content) or '') > 2750
		selected_arctile[#selected_arctile + 1] = article.fullText
		mw.log("selected",article)
	end
	local body = ""
	for i=1,max_arctiles,2 do
		body = body .. '\n|-'
		for j=1,2 do
			local k=i+j-1
			if k<=max_arctiles then
				body = body .. '\n|'
				local ass = p.pageAssessment(selected_arctile[k])
				local article, article_name, article_path =p._getSumm(selected_arctile[k],(math.random(3)==1)and 1 or nil)
				if ass then article = p.insertArticleStart(article, "{{Class/icon|"..ass.."}}") end
				--if #article > 320 then
				--	article = mw.ustring.sub(article,1,320)..'...\n[['..selected_arctile[k]..'|閱讀更多]]'
				--end
				body = body .. article..'...\n[['..article_path..'|閱讀更多]]'
			end
		end
	end
    if is_template then
    	return mw.getCurrentFrame():preprocess{ text = body }
    end
	return body
end

function p.randomACG(frame)
	local ACGList = {
		"在地下城尋求邂逅是否搞錯了什麼",
		"持續狩獵史萊姆三百年,不知不覺就練到LV_MAX",
		"輕鬆百合","NO_GAME_NO_LIFE_遊戲人生",
		"小林家的龍女僕",
	}
	-- For calling from #invoke.
    local args
    local is_template
    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) --frame.args
        is_template = true
    else
        -- We're being called from another module or from the debug console, so assume
        -- the args are passed in directly.
        if type(frame) ~= type({}) then args = {frame}
        else args = frame end
    end

	_setRandomSeed()
	local max_arctiles = tonumber(args['1'] or args[1]) or -1
	if mw.ustring.gsub(''..max_arctiles,"^[^\n\r]*[NnIi][AaNn][NnFf][^\n\r]*$", "nan") == "nan" or (tonumber(max_arctiles) or -1) <= 0 then 
		max_arctiles = 4
	end
	local selected_arctile = {}
	
	local id_pool = {}
	local article = nil

	local body = ""
	for i=1,max_arctiles,2 do
		body = body .. '\n|-'
		for j=1,2 do
			local k=i+j-1
			if k<=max_arctiles then
				body = body .. '\n|'
				local article, article_name, article_path
				repeat
					local select = ACGList[math.random(#ACGList)]
					local use_sub = (math.random(3)==1)and 1 or nil
					for _,oldId in ipairs(id_pool) do
						if oldId==select then
							use_sub = 1
							break
						end
					end
					article, article_name, article_path =p._getSumm(select, use_sub)
					mw.log(" = =  try select:",article_name, article_path)
					local newId = true
					for _,oldId in ipairs(id_pool) do
						if oldId==article_name then
							newId = false
							break
						end
					end
					if not newId then mw.log(" = = ",article_name, article_path, "EXIST!") end
				until newId
				mw.log(" = selectd:",article_name, article_path)
				id_pool[#id_pool+1] = article_name
				local ass = p.pageAssessment(article_path)
				if ass and (not mw.ustring.find(article_path, '#')) then article = p.insertArticleStart(article, "{{Class/icon|"..ass.."}}") end

				body = body .. article..'...\n[['..article_path..'|閱讀更多]]'
			end
		end
	end
    if is_template then
    	return mw.getCurrentFrame():preprocess{ text = body }
    end
	return body
end

function p.randomALLGFA(frame)
	-- For calling from #invoke.
    local args
    local is_template
    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) --frame.args
        is_template = true
    else
        -- We're being called from another module or from the debug console, so assume
        -- the args are passed in directly.
        if type(frame) ~= type({}) then args = {frame}
        else args = frame end
    end
	local max_arctiles = tonumber(args['1'] or args[1]) or -1
	if mw.ustring.gsub(''..max_arctiles,"^[^\n\r]*[NnIi][AaNn][NnFf][^\n\r]*$", "nan") == "nan" or (tonumber(max_arctiles) or -1) <= 0 then 
		max_arctiles = 4
	end
	local selected_arctile = {}
	_setRandomSeed()
	local GAs = {}
	local FAs = {}
	local FLs = {}
	mw.ustring.gsub((mw.title.new("Wikipedia:首頁/特色內容展示報告","Wikipedia") or {}).content or '',"|%-[\n\r %s]+|[^|]*|?[^|]+|[^|]*|[^|%[%]]*%[%[([^|%[%]]+)|?[^|]+|[^|]*|[^|]+|[ %s]+([^|%s]*)[ %s]*|[^|]*|[^|]+|[^|]*|[^|]+|[^|]*|[^\n\r%[]+%[%[([^%{%}%[%]|]+)", function(article,fl,desc)
		
		if mw.text.trim(fl) ~= '' then
			FLs[#FLs + 1] = {name=article, preview=desc}
		else
			FAs[#FAs + 1] = {name=article, preview=desc}
		end
	return ''end)
	mw.ustring.gsub((mw.title.new("Wikipedia:首頁/優良條目展示報告","Wikipedia") or {}).content or '',"|%-[\n\r %s]+|[^|]*|?[^|]+|[^|]*|[^|%[%]]*%[%[([^|%[%]]+)|?[^|]*|[^|]*|[^|]+|[^|]*|[^|]+|?[^|]*[^|]+[^%[]+%[%[([^|%[%]]+)", function(article,desc)
		GAs[#GAs + 1] = {name=article, preview=desc}
	return ''end)
	local id_pool = {}
	local GFs = {FAs, GAs, FAs, FLs}
	for i=1,max_arctiles do
		local DFid = -1
		local chkCount = #GFs * #GFs
		for _i = 1,chkCount do
			DFid = math.random(1,#GFs*#GFs)
			if GFs[DFid] or false then break end
		end
		if not (GFs[DFid] or false) then DFid = math.random(1,#GFs-1) end
		local find_id = nil
		local new_id = true
		repeat
			find_id = (GFs[DFid])[math.random(1,#(GFs[DFid]))]
			for j=1,#id_pool do
				if id_pool[j] == find_id.name then
					new_id = false
					break
				end
			end
		until new_id
		id_pool[#id_pool + 1] = find_id.name
		selected_arctile[#selected_arctile + 1] = find_id
	end
	local body = ""
	for i=1,max_arctiles,2 do
		body = body .. '\n|-'
		for j=1,2 do
			local k=i+j-1
			if k<=max_arctiles then
				body = body .. '\n|'
				body = body .. '{{:' .. selected_arctile[k].preview .. '}}...\n[['..selected_arctile[k].name..'|閱讀更多]]'
			end
		end
	end
    if is_template then
    	return mw.getCurrentFrame():preprocess{ text = body }
    end
	return body
end

function p.testStrip(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 mark_name = mw.text.trim(args["1"] or args[1] or "")
    if mark_name == '' then return '' end
    local mark_get_mart = frame:extensionTag( mark_name, mark_name )
    if mw.ustring.find(mark_get_mart,'\127') then
    	local max_id = ''
    	mw.ustring.gsub(mark_get_mart, mark_name .. '%-([0-9A-Za-z]+)%-', function(id)max_id = id end)
    	return max_id
    end
    return ''
end

function p.makeStrip(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 mark_name = mw.text.trim(args["1"] or args[1] or "")
    local mark_id = mw.text.trim(args["2"] or args[2] or "")
    if mark_name ~= '' and mark_id ~= '' then
    	return "\127'\"`UNIQ--" .. mark_name .. "-" .. mark_id .. "-QINU`\"'\127"
    end
    return ''
end

function p.countSaveTime(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 mTemplateInvocation = require('Module:Template invocation')
	local name = mTemplateInvocation.name(frame:getParent():getTitle())
	local get_text = args['1'] or args[1]
	local head, tail = mw.ustring.find(get_text, '%d+')
	local counts = tonumber(mw.ustring.sub(get_text, head, tail)) + 1
	return "{{subst:" .. name .. "|".. tostring(counts) .."}}" ;
end

function p.sb_func()
	p.append("  ")
	return 0
end

function p.append(frame, category) --fork from [[Module:If_empty]]
	if mw.isSubsting() then return '' end
	local cat = ''
	if type(frame) == type('string') then cat = frame end
	if type((frame or {}).args) ~= type({}) then frame = mw.getCurrentFrame() end
	cat = mw.text.trim(cat or category or frame.args['1'] or frame.args[1] or frame.args.cat or '')
	if cat ~= '' then
		frame:extensionTag('ref', string.format('[[Category:%s]]', cat), {group = 'TrackingCategory'})
		frame:extensionTag('references', '', {group = 'TrackingCategory'})
	end
	return ''
end

local num_map, num_str = {1,2,3,4,5,6,7,8,9,[0]=0,[',']=',',['’']=','}, {"0123456789","₀₁₂₃₄₅₆₇₈₉","⁰¹²³⁴⁵⁶⁷⁸⁹"}; for i=1,#num_str do for j=1,mw.ustring.len(num_str[i])do num_map[mw.ustring.sub(num_str[i],j,j)]=j-1 end end 

function p._getPolyItem(entity)
	local poly_item_property = {527,1012,1552,2670,4330}
	local propertyValues = {}
	for it=1,#poly_item_property do
		local temp_data = entity:getAllStatements( 'P' .. poly_item_property[it] )
		for key,value in pairs(temp_data) do
			propertyValues[key] = mw.clone( temp_data[key] )
		end
	end
	return propertyValues
end

function p.loadDimItem(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 input_title = args[1] or args['1']
    local input_dim = -1
    local entity
    input_title = mw.text.trim(mw.ustring.upper(input_title))
   
    if mw.ustring.find(input_title,"^Q%d+$") then
    	input_dim = tonumber(arg[2] or arg['2'] or '') or -2
    	entity = mw.wikibase.getEntity(input_title)
    elseif tonumber(input_title or '') then
    	input_dim = tonumber(input_title)
    	entity = mw.wikibase.getEntity()
    end
	local poly_item = {26382,3064117,2733626,4637223,18028552,18028565,18028567,18028569,18028571,
	[-1]={["item"]=27064338,["default"]=1},
	[0]={["item"]=26401},}
	local propertyValues = p._getPolyItem(entity)
	local body = ''
	local checkpoly = poly_item[tonumber(input_dim)or-2]
	local checkpoly_name = checkpoly
	local default_text = ''
	if type(checkpoly) == type({}) then
		checkpoly_name = checkpoly.item
		default_text = checkpoly.default or default_text
	end
    for it=1,#propertyValues do
    	local checker = ((propertyValues[it].mainsnak.datavalue or {}).value or {}).id
    	
    	if ('Q' .. tostring(checkpoly_name or '')) == (checker or '') then
			local getter = propertyValues[it].qualifiers["P1114"]
			if getter then
				body = body .. tonumber(getter[1].datavalue.value.amount)
			end
			break

    	end
    end
    if mw.text.trim(body) == '' then return default_text end
	return body
end

function p.loadSchlafli(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 input_title = args[1] or args['1']
    local input_format = args.format or '$'
    local input_split = args.split or '、'
    local entity = mw.wikibase.getEntity(input_title or '') or mw.wikibase.getEntity()
    local propertyValues = entity:getAllStatements( 'P3228' )
    local body = ''
    for it=1,#propertyValues do
    	if body ~= '' then body = body .. input_split end
    	local sstr = propertyValues[it].mainsnak.datavalue.value
		sstr = mw.ustring.gsub(sstr, '([^,%{%}/]+)/([^,%{%}/]+)', '<sup>%1</sup>/<sub>%2</sub>')
		sstr = mw.ustring.gsub(sstr,"[,₁₂₃₄₅₆₇₈₉₀]+",function(nstr)
			if mw.ustring.len(nstr) <= 1 and mw.ustring.sub(nstr,1,1) == ',' then return nstr end
			return "<sub>"..mw.ustring.gsub(nstr,".",function(c) return num_map[c] end).."</sub>"
		end)
		sstr = mw.ustring.gsub(sstr,"[’⁰¹²³⁴⁵⁶⁷⁸⁹]+",function(nstr)
			if mw.ustring.len(nstr) <= 1 and mw.ustring.sub(nstr,1,1) == ',' then return nstr end
			return "<sup>"..mw.ustring.gsub(nstr,".",function(c) return num_map[c] end).."</sup>"
		end)
    	body = body .. mw.ustring.gsub(input_format,'%$',sstr)
    end
	return body
end

function p.templateArgWarp(frame, warpargs)
	local args, new_name
    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.
        new_name = frame.args['1'] or frame.args[1] or frame.args.name or frame.args.Name
        local parent = frame:getParent() or {['args']={}}
        args = parent.args
    else
        -- We're being called from another module or from the debug console, so assume
        -- the args are passed in directly.
        if type(frame) == type('string') then new_name = frame
        elseif type(frame) == type({}) then new_name = frame['1'] or frame[1] or frame.name or frame.Name
        end
        args = warpargs or mw.getCurrentFrame().args
    end
    local mTemplateInvocation = require('Module:Template invocation')
	return require('Module:Template invocation').invocation(new_name, args)
end

function p.testFakeStrip()
	return mw.getCurrentFrame():preprocess( "{{{1\127'\"`UNIQ--item-00010000-QINU`\"'\127}}}\127'\"`UNIQ--item-00020000-QINU`\"'\127" )
end

function p.testBreakStrip()
	return mw.ustring.gsub(mw.getCurrentFrame():preprocess(mw.ustring.gsub(mw.getCurrentFrame().args[1] .. "<!--__UINQABCQNIU__-->",'\127','') ),'\127','')
end

local yesno = {}
function p.getJSON(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 input_title = args[1] or args['1']
    local key_alias = args['key alias'] or args.key_alias
    if (key_alias or '') ~= '' then
		if type(yesno) ~= type(tonumber) then yesno = require('Module:Yesno') end
		key_alias = yesno(key_alias or 'no')
	end
    local default = args["default"] or ''
    local fullText = mw.title.new( input_title, "Template" ):getContent()
    local jsonText = ''
    if fullText then
    	local checker, begin = mw.ustring.find(fullText, "<%s*source%s*lang%s*=%s*['\"]?[Jj][Ss][Oo][Nn]['\"]?%s*>")
    	local finish, __noop = mw.ustring.find(fullText, "<%s*/%s*source[^>]*>")
    	if checker then
    		jsonText = mw.ustring.sub(fullText,begin+1,finish-1)
    	end
    end

    local JSONobj = mw.text.jsonDecode( jsonText )
    local iterator = 2
	while args[iterator] ~= nil do
		if key_alias then
			local check_key = JSONobj[args[iterator]]
			if type(check_key) == type("string") then
				local check_key_str, find_key_str = mw.ustring.gsub(check_key,"<%s*target%s*>(.-)<%s*/%s*target%s*>", '%1')
				mw.log(args[iterator] .. ', find:' .. check_key_str)
				while find_key_str > 0 and mw.text.trim(check_key_str) ~= '' and JSONobj[check_key_str] ~= nil do
					check_key = JSONobj[check_key_str]
					if type(check_key) == type("string") then
						check_key_str, find_key_str = mw.ustring.gsub(check_key,"<%starget%s>(.-)<%s/%starget%s>", '%1')
						mw.log('   =>\"' .. check_key_str .. '\"')
					else break end
				end
			end
			JSONobj = check_key
		else JSONobj = JSONobj[args[iterator]] end
		if JSONobj == nil and default ~= nil then
			return default
		end
		iterator = iterator + 1
	end
	
	if type(JSONobj) == type({}) then
		return default
	end
	
	return JSONobj
end

function p.loadTemplateValue(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_title = args[1] or args['1']
	input_title = mw.text.trim(input_title or '')
	if input_title == '' then return '' end
	local input_template_name = args[2] or args['2']
	input_template_name = mw.text.trim(input_template_name or '')
	if input_template_name == '' then return '' end
    local title_obj = mw.title.new(input_title)
    local page_content = title_obj:getContent()
    if page_content then else return '' end
    local page_text = mw.text.decode(page_content)

	--store nowiki
	local nowikimap = {}
	page_text = mw.ustring.gsub(page_text, '<%s*([Nn][Oo][Ww][Ii][Kk][Ii][^>]*)>(.-)<%s*(/[Nn][Oo][Ww][Ii][Kk][Ii])%s*>', 
    	function(tag_head, tag_body, tag_tail)
    		nowikimap[#nowikimap + 1] = '<' .. tag_head .. '>' .. tag_body .. '<' .. tag_tail .. '>'
    		return '\127$__UINQ-NOWIKI-' .. #nowikimap ..'-QNIU__$\127'
    	end) 
	
	--store noinclude
	local noincludemap = {}
	local templatemap = {}
	local includemap = {}
    local paramap = {}

    local put_template_pattern, put_template_replacment = '%$__UINQ%-TEMP%-(%d+)%-QNIU__%$', function(map_id)
		local index = tonumber(map_id)
		return templatemap[index or ''] or ''
	end
    local put_noinclude_pattern, put_noinclude_replacment = '%$__UINQ%-NOINCLUDE%-(%d+)%-QNIU__%$', function(map_id)
		local index = tonumber(map_id)
		return noincludemap[index or ''] or ''
	end
    local put_include_pattern, put_include_replacment = '%$__UINQ%-INCLUDE%-(%d+)%-QNIU__%$', function(map_id)
		local index = tonumber(map_id)
		return includemap[index or ''] or ''
	end
    local put_para_pattern, put_para_replacment = '%$__UINQ%-PARA%-(%d+)%-QNIU__%$', function(map_id)
		local index = tonumber(map_id)
		return paramap[index or ''] or ''
	end
	
	page_text = mw.ustring.gsub(page_text, '<%s*([Nn][Oo][Ii][Nn][Cc][Ll][Uu][Dd][Ee][^>]*)>(.-)<%s*(/[Nn][Oo][Ii][Nn][Cc][Ll][Uu][Dd][Ee])%s*>', 
    	function(tag_head, tag_body, tag_tail)
    		noincludemap[#noincludemap + 1] = '<' .. tag_head .. '>' .. tag_body .. '<' .. tag_tail .. '>'
    		return '$__UINQ-NOINCLUDE-' .. #noincludemap ..'-QNIU__$'
    	end)
    --put back nowiki
	page_text = mw.ustring.gsub(page_text, '\127%$__UINQ%-NOWIKI%-(%d+)%-QNIU__%$\127', 
    	function(map_id)
    		local index = tonumber(map_id)
    		return nowikimap[index or ''] or ''
    	end)
    nowikimap = {}

    page_text = mw.ustring.gsub(page_text, '<%s*(/?)([a-zA-Z0-9_]-[Ii][Nn][Cc][Ll][Uu][Dd][Ee][a-zA-Z0-9_]-)([^>]*)>', 
    	function(end_tag,tag_name,tag_args)
    		includemap[#includemap + 1] = '<' .. end_tag .. tag_name .. tag_args .. '>'
    		return '$__UINQ-INCLUDE-' .. #includemap ..'-QNIU__$'
    	end)

    --使用自定義strip mark迴避subst階段完全無法unstrip的狀況
    local remap = {}
    local html_pattern, html_replacment = '<%s*(/?)([a-zA-Z0-9_]+)([^>]*)>',function(end_tag,tag_name,tag_args)
		remap[#remap + 1] = '<' .. end_tag .. tag_name .. tag_args .. '>'
		return '$__UINQ-HTML-' .. #remap ..'-QNIU__$'
	end
    page_text = mw.ustring.gsub(page_text, html_pattern, html_replacment)

	local deremap = {}
    local para_finder, para_replacment = '{{{[^{}]-}}}', function(paratext)
		paratext = mw.ustring.gsub(paratext, put_para_pattern, put_para_replacment)
		local check_name, check_name_end = mw.ustring.find(paratext, '{{{[^|}]-[|}]')
		if check_name then
			check_name = mw.ustring.sub(paratext, check_name+3, check_name_end-1)
			local check_org_name = mw.clone(check_name)
			local check_rep1,check_rep2 = 0,0
			check_org_name, check_rep1 = mw.ustring.gsub(check_name, put_include_pattern, put_include_replacment)
			check_org_name, check_rep2 = mw.ustring.gsub(check_org_name, put_noinclude_pattern, '')
			if (check_rep1+check_rep2) > 0 then
				deremap[check_name] = check_org_name
			end
		end
		paramap[#paramap + 1] = paratext
		return '$__UINQ-PARA-' .. #paramap ..'-QNIU__$'
	end
    for i=1,50 do
    	local replace_flag = 0
    	page_text, replace_flag = mw.ustring.gsub(page_text, para_finder,para_replacment)
    	if replace_flag <= 0 then break end
    end

    local template_finder, template_replacment = '{{[^{}]-}}', function(paratext)
    	--移除位於模板名稱中的include系列標籤,避免模板名稱錯誤
    	paratext = mw.ustring.gsub(paratext, '({{)([^|}]-)([|}])', function(template_head, template_name, template_tail)
    		local temp_name = mw.ustring.gsub(template_name, put_noinclude_pattern, '')
    		temp_name = mw.ustring.gsub(temp_name, put_include_pattern, '')
    		return template_head .. temp_name .. template_tail
    	end)
    	paratext = mw.ustring.gsub(paratext, put_para_pattern, put_para_replacment)
		paratext = mw.ustring.gsub(paratext, put_template_pattern, put_template_replacment)
		
		templatemap[#templatemap + 1] = paratext
		return '$__UINQ-TEMP-' .. #templatemap ..'-QNIU__$'
	end
    for i=1,50 do
    	local replace_flag = 0
    	page_text, replace_flag = mw.ustring.gsub(page_text, template_finder,template_replacment)
    	if replace_flag <= 0 then break end
    end

--			mw.log('deremap')
--			mw.logObject(deremap)
	
--    mw.log("paramap")
--mw.logObject(paramap)
--mw.log(table.concat( paramap,'\127'))
--mw.logObject(mw.text.split(table.concat( paramap,'\127'),'\127'))

--    mw.log("includemap")
--mw.logObject(includemap)

    mw.log("templatemap")
mw.logObject(templatemap)

--    mw.log("remap")
--mw.logObject(remap)
--    mw.log("noincludemap")
--mw.logObject(noincludemap)
	    		--mw.log("page_text")
	    		--mw.log(page_text)
	return ''
end

--{{#invoke:沙盒/a2569875/UserPageFunc|allSubst|subst|void}}
--失敗
function p.allSubst(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_data = args[1] or args['1']
    local input_title = mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(input_data, 'msgnw:',''), 'safesubst:',''), 'subst:','')
    local check_i, start = mw.ustring.find(input_data, "#invoke:")
    local offset = 1
    if check_i then
    	input_title = 'Module' .. mw.ustring.sub(input_data,start)
    	offset = 2
    end
    local title_obj = mw.title.new(input_title, 'Template' )
    local page_content = title_obj:getContent()
    if page_content then else return "&#123;&#123;[[Help:替换引用#safesubst|safesubst]]:[[Help:替换引用#msgnw|msgnw]]:[["..
    	title_obj.fullText .. '|' .. title_obj.text .. "]]&#125;&#125;" end
    local page_text = mw.text.decode(page_content)

	--store nowiki
	local nowikimap = {}
	page_text = mw.ustring.gsub(page_text, '<%s*([Nn][Oo][Ww][Ii][Kk][Ii][^>]*)>(.-)<%s*(/[Nn][Oo][Ww][Ii][Kk][Ii])%s*>', 
    	function(tag_head, tag_body, tag_tail)
    		nowikimap[#nowikimap + 1] = '<' .. tag_head .. '>' .. tag_body .. '<' .. tag_tail .. '>'
    		return '\127$__UINQ-NOWIKI-' .. #nowikimap ..'-QNIU__$\127'
    	end) 
	
	--store noinclude
	local noincludemap = {}
	local templatemap = {}
	local includemap = {}
    local paramap = {}

    local put_template_pattern, put_template_replacment = '%$__UINQ%-TEMP%-(%d+)%-QNIU__%$', function(map_id)
		local index = tonumber(map_id)
		return templatemap[index or ''] or ''
	end
    local put_noinclude_pattern, put_noinclude_replacment = '%$__UINQ%-NOINCLUDE%-(%d+)%-QNIU__%$', function(map_id)
		local index = tonumber(map_id)
		return noincludemap[index or ''] or ''
	end
    local put_include_pattern, put_include_replacment = '%$__UINQ%-INCLUDE%-(%d+)%-QNIU__%$', function(map_id)
		local index = tonumber(map_id)
		return includemap[index or ''] or ''
	end
    local put_para_pattern, put_para_replacment = '%$__UINQ%-PARA%-(%d+)%-QNIU__%$', function(map_id)
		local index = tonumber(map_id)
		return paramap[index or ''] or ''
	end
	
	page_text = mw.ustring.gsub(page_text, '<%s*([Nn][Oo][Ii][Nn][Cc][Ll][Uu][Dd][Ee][^>]*)>(.-)<%s*(/[Nn][Oo][Ii][Nn][Cc][Ll][Uu][Dd][Ee])%s*>', 
    	function(tag_head, tag_body, tag_tail)
    		noincludemap[#noincludemap + 1] = '<' .. tag_head .. '>' .. tag_body .. '<' .. tag_tail .. '>'
    		return '$__UINQ-NOINCLUDE-' .. #noincludemap ..'-QNIU__$'
    	end)
    --put back nowiki
	page_text = mw.ustring.gsub(page_text, '\127%$__UINQ%-NOWIKI%-(%d+)%-QNIU__%$\127', 
    	function(map_id)
    		local index = tonumber(map_id)
    		return nowikimap[index or ''] or ''
    	end)
    nowikimap = {}

    page_text = mw.ustring.gsub(page_text, '<%s*(/?)([a-zA-Z0-9_]-[Ii][Nn][Cc][Ll][Uu][Dd][Ee][a-zA-Z0-9_]-)([^>]*)>', 
    	function(end_tag,tag_name,tag_args)
    		includemap[#includemap + 1] = '<' .. end_tag .. tag_name .. tag_args .. '>'
    		return '$__UINQ-INCLUDE-' .. #includemap ..'-QNIU__$'
    	end)

    --使用自定義strip mark迴避subst階段完全無法unstrip的狀況
    local remap = {}
    local html_pattern, html_replacment = '<%s*(/?)([a-zA-Z0-9_]+)([^>]*)>',function(end_tag,tag_name,tag_args)
		remap[#remap + 1] = '<' .. end_tag .. tag_name .. tag_args .. '>'
		return '$__UINQ-HTML-' .. #remap ..'-QNIU__$'
	end
    page_text = mw.ustring.gsub(page_text, html_pattern, html_replacment)

	local deremap = {}
    local para_finder, para_replacment = '{{{[^{}]-}}}', function(paratext)
		paratext = mw.ustring.gsub(paratext, put_para_pattern, put_para_replacment)
		local check_name, check_name_end = mw.ustring.find(paratext, '{{{[^|}]-[|}]')
		if check_name then
			check_name = mw.ustring.sub(paratext, check_name+3, check_name_end-1)
			local check_org_name = mw.clone(check_name)
			local check_rep1,check_rep2 = 0,0
			check_org_name, check_rep1 = mw.ustring.gsub(check_name, put_include_pattern, put_include_replacment)
			check_org_name, check_rep2 = mw.ustring.gsub(check_org_name, put_noinclude_pattern, '')
			if (check_rep1+check_rep2) > 0 then
				deremap[check_name] = check_org_name
			end
		end
		paramap[#paramap + 1] = paratext
		return '$__UINQ-PARA-' .. #paramap ..'-QNIU__$'
	end
    for i=1,50 do
    	local replace_flag = 0
    	page_text, replace_flag = mw.ustring.gsub(page_text, para_finder,para_replacment)
    	if replace_flag <= 0 then break end
    end

    local template_finder, template_replacment = '{{[^{}]-}}', function(paratext)
    	--移除位於模板名稱中的include系列標籤,避免模板名稱錯誤
    	paratext = mw.ustring.gsub(paratext, '({{)([^|}]-)([|}])', function(template_head, template_name, template_tail)
    		local temp_name = mw.ustring.gsub(template_name, put_noinclude_pattern, '')
    		temp_name = mw.ustring.gsub(temp_name, put_include_pattern, '')
    		return template_head .. temp_name .. template_tail
    	end)
    	paratext = mw.ustring.gsub(paratext, put_para_pattern, put_para_replacment)
		paratext = mw.ustring.gsub(paratext, put_template_pattern, put_template_replacment)
		
		templatemap[#templatemap + 1] = paratext
		return '$__UINQ-TEMP-' .. #templatemap ..'-QNIU__$'
	end
    for i=1,50 do
    	local replace_flag = 0
    	page_text, replace_flag = mw.ustring.gsub(page_text, template_finder,template_replacment)
    	if replace_flag <= 0 then break end
    end
    
    --將自訂strip mark放回去
    page_text = mw.ustring.gsub(page_text, put_template_pattern, put_template_replacment)
    page_text = mw.ustring.gsub(page_text, put_para_pattern, put_para_replacment)
    page_text = mw.ustring.gsub(page_text, put_include_pattern, put_include_replacment)
	page_text = mw.ustring.gsub(page_text, put_noinclude_pattern, put_noinclude_replacment)
	page_text = mw.ustring.gsub(page_text, html_pattern, html_replacment)
	
			mw.log('deremap')
			mw.logObject(deremap)
	
    mw.log("paramap")
mw.logObject(paramap)
--mw.log(table.concat( paramap,'\127'))
--mw.logObject(mw.text.split(table.concat( paramap,'\127'),'\127'))

    mw.log("includemap")
mw.logObject(includemap)

    mw.log("templatemap")
mw.logObject(templatemap)

    mw.log("remap")
mw.logObject(remap)
    mw.log("noincludemap")
mw.logObject(noincludemap)
	    		mw.log("page_text")
	    		mw.log(page_text)

    local num_args = {}
	for key,value in pairs(args) do
		local num = tonumber(key) or 0
		if num then
			if num > offset then
				num_args[key - offset] = value
			end
		else
			num_args[key] = value
		end
	end
	for key,value in pairs(deremap) do
		if num_args[value] then
			num_args[key] = num_args[value]
		end
		local id_value = tonumber(value)
		if num_args[id_value] then
			num_args[key] = num_args[id_value]
		end
	end
    mw.log("num_args")
mw.logObject(num_args)
    local subst_frame = working_frame:newChild{ title = title_obj.fullText, args = num_args }
    local result = subst_frame:preprocess( page_text )

    result = mw.ustring.gsub(result, '%$__UINQ%-HTML%-(%d+)%-QNIU__%$', 
		function(map_id)
	    	local index = tonumber(map_id)
	    	if index then
	    		return remap[index] or ''
	    	end
	    	return ''
	    end)
	    mw.log('result')
	    mw.log(result)
	if mw.isSubsting() then return result end
	result = mw.ustring.gsub(result, '<%s*/?[^>]*include[^>]*>', '')
	return result
end



function p.unnowiki(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 input_n = args[1] or args['1']
	local input_data = "" .. mw.text.unstripNoWiki( input_n )
	if(mw.isSubsting())then 
		return mw.ustring.sub( input_n );
	end
	return working_frame:preprocess( input_data )
end

function p.getTemplateVar(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 finding_frame = working_frame:newChild{ title = working_frame:getTitle() .. "/FINDER", working_frame.args }
    local input_n = args[1] or args['1']
    local finder_template = args[2] or args['2'] or ''
    local finder = args[3] or args['3'] or ''
    local it_times = args['times'] or 3
	local src = ' ' .. (finding_frame:newParserValue{ text = "{{msgnw:" .. input_n .. "}}" }):expand()
	if mw.text.trim(finder_template) ~= '' then
		if lib_para._getEscapeString == nil then lib_para = require('Module:TemplateParameters') end
		local unstripped = ' ' .. mw.ustring.gsub(src ,'(&#123;&#123;)%s-(' .. lib_para._getEscapeString(finder_template) .. ')', '%1[[%2]]' );
		unstripped = mw.ustring.gsub(unstripped ,'ref', '[[ref]]' );
		local reexpand = '. ' .. (finding_frame:newParserValue{ text = mw.text.decode( unstripped ) }):expand() .. ' .'

		template_data = mw.ustring.gmatch(reexpand , "{{%s-%[%[.-}}[^}]")
		local result, iterator = '*', template_data()
		local replace_link = function(text)
			return mw.ustring.gsub(text ,'|', '{{!}}' )
		end
		while iterator do
			local pre_template_data = mw.ustring.gsub(iterator ,'%[%[.-%]%]', replace_link )
			local this_template = mw.text.split(pre_template_data, '|')  or { [1] = pre_template_data }
			local template_name = mw.text.trim(mw.ustring.gsub(this_template[1], '[%[%]{}\n\r\t]', ''))
			local arg_index = 0
			mw.log('pre_template_data',pre_template_data)
			mw.log('template_name',template_name)
			for arg_id, arg_full in pairs(this_template) do
				if arg_index == 0 then arg_index = 1 else
					local checker = mw.ustring.find( arg_full, "=")
					local arg_full_text = arg_full
					local arg_name = arg_index
					if checker then 
						arg_full_text = mw.text.trim(mw.ustring.sub(arg_full, checker+1, -1))
						arg_name = mw.text.trim(mw.ustring.sub(arg_full, 1, checker-1))
					else
						arg_index = arg_index + 1
					end 
					mw.log('arg_name='..arg_name..', '..'arg_value='..arg_full_text)
					
					local tmp_v = 'false';if(finder==arg_name)then tmp_v='true' end
					local tmp_t = 'false';if(finder_template==template_name)then tmp_t='true' end

					if mw.text.trim('' .. finder_template) == template_name and mw.text.trim('' .. finder) == arg_name then
						return mw.text.trim(arg_full_text or '')
					end
				end
			end
			--result = result .. iterator .. '\n*'
			iterator = template_data()
		end
		--return result
	end
	return ''
end
p['生成']=function()return 'jj生成' end
return p;