模組:Special wikitext

local p={
	--會被抓取wikitext的關鍵字,此處請設定為與[[Module:Module wikitext]]一致
	wikiTextKey = '_addText'
}

function p.displayWikitext()
	local body = ''
	local title = mw.title.getCurrentTitle()
	local this_frame = mw.getCurrentFrame()
	
	local pagename = title.nsText..':'..title.rootText
	local pagesubname = mw.ustring.gsub(title.fullText,"[^:\/]*:[^\/]+",'')

	--[[en:mediawiki:clearyourcache]] --[[en:special:diff/332947732]]
	local notice = this_frame:preprocess('{{#invoke:Special wikitext/Template|getNotices|'..pagename..'|'..pagesubname..'}}') or ''
	body = body .. '<div class="mw-editnotice-content">'..notice..'</div>'

	--將原有函數結果外邊以div包裹
	local wikitext = p.check() or ''
	body = body .. '<div class="mw-_addText-content">'..wikitext..'</div>'

	return body
end

function p.check()
	--使用頁面內容模型來判斷格式
	local content_model = mw.ustring.lower(mw.title.getCurrentTitle().contentModel)
	--根據文檔格式選用適當的解析模式
	if content_model == 'json' then
		return _getJSONwikitext()
	elseif content_model == 'js' or content_model == 'javascript' or content_model == 'text' then
		return _getJSwikitext()
	elseif content_model == 'css' or content_model == 'sanitized-css' then
		return _getCSSwikitext()
	end
	--若不是json、js、css則返回空字串
	return ''
end

--//合併多個wikitext字串,並以換行分隔
local TemplateParameters = {}
function _addText(input_str,new_str,escape)
	if not TemplateParameters._get_escape then TemplateParameters = require('Module:TemplateParameters') end
	if new_str~='' then
		if input_str~='' then input_str = input_str .. '\n' end
		local text = new_str
		if escape then text = TemplateParameters._get_escape(new_str) end
		input_str = input_str .. text
	end
	return input_str
end

--//讀取wikitext字串,並忽略註解尾部
function _getString(str)
	local test_str = mw.ustring.match(str, "[^\n]*%*/")
	if test_str then test_str = mw.ustring.sub(test_str,1,-3) 
	else test_str = str end
	local trim_check = mw.text.trim(test_str)
	local first_char = mw.ustring.sub(trim_check,1,1)
	if first_char == mw.ustring.sub(trim_check,-1,-1) and (first_char == "'" or first_char == '"') then
		return mw.ustring.sub(trim_check,2,-2)
	else
		return test_str
	end
end

--//讀取CSS之 _addText { content:"XXX" } 模式的字串
function _getContentText(str)
	local wikitext = ''
	xpcall( function()
		local it=mw.ustring.gmatch(str, p.wikiTextKey .. "%s*%{[^c%}]*content%s*:%s*[^\n]*")
		local text=it()
		while text do
			local temp_text = mw.ustring.gsub(mw.text.trim(
				mw.ustring.match(text,"content%s*:%s*[^\n]*"), "\t\r\n\f ;}"
			),"%s*content%s*:%s*","")
			if wikitext ~= '' then wikitext = wikitext .. '\n' end
			wikitext = wikitext .. _getString(temp_text)
			text=it()
		end
	end, function()end )
	return wikitext
end

--//讀取物件定義模式為 _addText=XXX 或 _addText:XXX 模式的字串
function _getObjText(str)
	local wikitext = ''
	xpcall( function()
		local it=mw.ustring.gmatch(str, p.wikiTextKey .. "%s*[%=:]%s*[^\n]*")
		local text=it()
		while text do
			local temp_text = mw.ustring.gsub(
				mw.text.trim(text, "\t\r\n\f ;}"),
			p.wikiTextKey .. "%s*[%=:]%s*","")
			if wikitext ~= '' then wikitext = wikitext .. '\n' end
			wikitext = wikitext .. _getString(temp_text)
			text=it()
		end
	end, function()end )
	return wikitext
end

--//分析CSS中符合條件的wikitext
function _getCSSwikitext(input_string)
	local this_frame = mw.getCurrentFrame()
	local wikitext = ''
	local css_text = input_string or mw.title.getCurrentTitle():getContent()
	--匹配 _addText { content:"XXX" } 模式
	wikitext = _addText(wikitext, _getContentText(css_text), true)
	--同時亦匹配 /* _addText:XXX */ 模式
	wikitext = _addText(wikitext, _getObjText(css_text), true)
	--若讀到有效字串,則呼叫解析器
	if wikitext ~= '' then wikitext = this_frame:preprocess(wikitext) end
	return wikitext
end

--//分析JavaScript中符合條件的wikitext
function _getJSwikitext(input_string)
	local this_frame = mw.getCurrentFrame()
	local wikitext = ''
	local js_text = input_string or mw.title.getCurrentTitle():getContent()
	wikitext = _addText(wikitext, _getObjText(js_text), true)
	--若讀到有效字串,則呼叫解析器
	if wikitext ~= '' then wikitext = this_frame:preprocess(wikitext) end
	return wikitext
end

--//分析JSON中符合條件的wikitext
function _getJSONwikitext(input_string)
	local this_frame = mw.getCurrentFrame()
	local wikitext = ''
	xpcall( function()
		local json_data = mw.text.jsonDecode(input_string or mw.title.getCurrentTitle():getContent())
		for k,v in pairs(json_data) do 
			if mw.ustring.match(k,p.wikiTextKey) and type(v) == type('')then
				wikitext = _addText(wikitext, v)
			end
			--//如果是陣列物件會多包一層
			if type(v) == type({}) then
				for testArr_k,testArr_v in pairs(v) do 
					if mw.ustring.match(testArr_k,p.wikiTextKey) and type(testArr_v) == type('')then
						wikitext = _addText(wikitext, testArr_v)
					end
				end
			end
		end
	end, function()end )
	if wikitext ~= '' then wikitext = this_frame:preprocess(wikitext) end
	return wikitext
end

--除錯模式 : 使用 #invoke 或 console 除錯的呼叫方式 (預設模式會直接讀取頁面內容)
local lib_arg = {}
function _getTestFromFrame(frame)
	-- For calling from #invoke.
    local str = ''
    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
        local args = lib_arg.getArgs(frame) --frame
        str = args[1] or args['1'] or args.str
    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 str = frame[1] or frame['1'] or frame.str
        else str = tostring(frame) end
    end
    if mw.text.trim(str or '') == '' then str = mw.title.getCurrentTitle():getContent() end
    return str
end
function p.getCSSwikitext(frame) return _getCSSwikitext(_getTestFromFrame(frame)) end
function p.getJSwikitext(frame) return _getJSwikitext(_getTestFromFrame(frame)) end
function p.getJSONwikitext(frame) return _getJSONwikitext(_getTestFromFrame(frame)) end
return p