Module:Demo/sandbox

From Wikipedia, the free encyclopedia
local p = {}
local yn = require('Module:Yesno')
local getArgs = require('Module:Arguments').getArgs
-- simple module that takes in an input and displays the input and output of a wikitext
-- helper function which gets all the locations of all the matches of a ustring
function p._getAllMatchIndices(text, pattern)
	local output = {}
	local i = 0
	while i ~= nil do
		i = mw.ustring.find(text, pattern, i + 1)
		if i ~= nil then table.insert(output, i) end
	end
	return output
end

-- replaces all usages of \[, \], \<, \> \\, \{, and \} with [, ], <, >, \, {,  and }
-- also replaces line breaks, carriage returns, and tabs with their appropriate character
function p._escapeAllCharacters(text)
	local indices = p._getAllMatchIndices(text, "\\")
	local splitText = mw.text.split(text, '')
	local skip = false
	for k,v in ipairs(indices) do
		if not skip then
			splitText[v] = ''
			local nc = splitText[v + 1]
			splitText[v + 1] = (
				nc == "e" and '=' or
				nc == "p" and '|' or
				nc == '[' and mw.getCurrentFrame():preprocess('<nowiki>[</nowiki>') or
				nc == ']' and mw.getCurrentFrame():preprocess('<nowiki>]</nowiki>') or
				nc == '{' and mw.getCurrentFrame():preprocess('<nowiki>{</nowiki>') or
				nc == '}' and mw.getCurrentFrame():preprocess('<nowiki>}</nowiki>') or
				nc == '<' and mw.getCurrentFrame():preprocess('<nowiki><</nowiki>') or
				nc == '>' and mw.getCurrentFrame():preprocess('<nowiki>></nowiki>') or
				nc == '&' and mw.getCurrentFrame():preprocess('<nowiki>&amp;</nowiki>') or
				splitText[v + 1]
			)
			mw.log(splitText[v + 1])
			if nc == '\\' then
				skip = true	
			end
		else
			skip = false	
		end
	end
	return table.concat(splitText)
end

function p._escapeHTMLCharCodes(str)
	local function replaceHTMLCharCodes(entity)
		mw.log(entity)
		local charCode = mw.ustring.match(entity, "%d+") and tonumber(mw.ustring.match(entity, "%d+")) or mw.ustring.match(entity, "%w+;")
		mw.log(charCode)
		if type(charCode) == 'number' then
			return mw.ustring.char(charCode)
		else
			local HTMLCharCodes = {
				["amp;"] = "&",
				["gt;"] = ">",
				["lt;"] = "<"
			}
			local replacementChar = HTMLCharCodes[charCode] or entity
			return replacementChar
		end
	end
	return mw.ustring.gsub(str, "%&%S-;", replaceHTMLCharCodes)
end

function p._removeAllLinks(text)
	-- find all [ and ] characters and remove them
	local splitText = mw.text.split(text, '')
	local numberOfBrackets = 0
	local endCharacter = false
	for k,v in ipairs(splitText) do
		if splitText[k] == '[' then
			numberOfBrackets = numberOfBrackets + 1
			endCharacter = false
			if numberOfBrackets > 2 then numberOfBrackets = 2 else splitText[k] = '' end
		elseif splitText[k] == ']' then
			numberOfBrackets = numberOfBrackets - 1
			endCharacter = false
			if numberOfBrackets < 0 then numberOfBrackets = 0 else splitText[k] = '' end
		else
			if numberOfBrackets == 2 then
				if not endCharacter then
					endCharacter = splitText[k] == '|'
					splitText[k] = ''
				end
			elseif numberOfBrackets == 1 then
				if not endCharacter then
					endCharacter = splitText[k] == ' '
					splitText[k] = ''
				end
			end
		end
	end
	return table.concat(splitText)
end

function p._removeXML(text)
	-- finds all xml tags and remove them
	local splitText = mw.text.split(text, '')
	local numberOfBrackets = 0
	local numberOfDoubleQuotes = 0
	local numberOfSingleQuotes = 0
	for k,v in ipairs(splitText) do
		if splitText[k] == '<' then
			numberOfBrackets = numberOfBrackets + 1
			if numberOfBrackets > 1 then numberOfBrackets = 1 else splitText[k] = '' end
		elseif splitText[k] == '>' then
			numberOfBrackets = numberOfBrackets - 1
			if numberOfBrackets < 0 then numberOfBrackets = 0 else splitText[k] = '' end
		else
			if numberOfBrackets == 1 then
				splitText[k] = ''
			end
		end
	end
	return table.concat(splitText)
end

-- from Wikipedia
local function makeInvokeFunc(funcName)
	return function (frame)
		local args = getArgs(frame, {
			valueFunc = function (key, value)
				if type(value) == 'string' then
					value = value:match('^%s*(.-)%s*$') -- Remove whitespace.
					if key == 'heading' or value ~= '' then
						return value
					else
						return nil
					end
				else
					return value
				end
			end
		})
		return p[funcName](args)
	end
end

p.main = makeInvokeFunc("_main")
function p._main(args)
	local nowiki = yn(args['nowiki']) or false
	local format = args['format'] or 'block'
	local code = p._code(args)
	local result = p._result(args)
	if format == 'inline' then
		return 'Using this code: ' .. code .. ' yields: ' .. result
	else
		return '<dl><dt>Using this code:</dt><dd>'
			.. code
			.. '</dd><dt>yields: </dt><dd>'
			.. result
			.. '</dd></dl>'--output the result
	end
end

p.code = makeInvokeFunc("_code")
function p._code(args)
	local nowiki = yn(args['nowiki']) or false
	local text = p._raw(args)
	local format = args['format'] or 'block'
	local syntaxhighlight = yn(args["syntaxhighlight"]) or false
	if not syntaxhighlight then
		local code = format == 'inline'
			and mw.getCurrentFrame():preprocess("<code>" .. text .. "</code>")
			or mw.getCurrentFrame():preprocess("<code style=\"display:inline-block;\">" .. text .. "</code>")
		return code
	else
		local code = format == "inline"
			and mw.getCurrentFrame():preprocess("<syntaxhighlight inline lang=\"wikitext\">" .. text .. "</syntaxhighlight>")
			or mw.getCurrentFrame():preprocess("<syntaxhighlight lang=\"wikitext\">" .. text .. "</syntaxhighlight>")
		return code
	end
end

p.raw = makeInvokeFunc("_raw")
function p._raw(args)
	local nowiki = yn(args['nowiki']) or false
	local syntaxhighlight = yn(args["syntaxhighlight"]) or false
	local text = (nowiki or syntaxhighlight) and args[1] or p._escapeAllCharacters(args[1])
	mw.log(text)
	return text
end

p.result = makeInvokeFunc("_result")
function p._result(args)
	local nowiki = yn(args['nowiki']) or false
	local text = p._raw(args)
	mw.log(p._removeXML(
		p._removeAllLinks(text)
	))
	local result = (yn(args['nowiki']) or yn(args['syntaxhighlight']))
		and mw.getCurrentFrame():preprocess(mw.text.unstripNoWiki(text))
			or mw.getCurrentFrame():preprocess(
				p._escapeHTMLCharCodes(
					mw.text.unstripNoWiki(
						p._removeXML(
							p._removeAllLinks(text)
						)
					)
				)
			)
		or ''
	mw.log(result)
	return result
end
return p