Jump to content

Module:Demo/sandbox: Difference between revisions

From Wikipedia, the free encyclopedia
Content deleted Content added
No edit summary
Tag: Reverted
Syncing sandbox code with main template (sync-template-sandbox.js)
Line 1: Line 1:
local p = {}
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


--creates a frame object that cannot access any of the parent's args
-- replaces all usages of \[, \], \<, \> \\, \{, and \} with [, ], <, >, \, {, and }
--unless a table containing a list keys of not to inherit is provided
-- also replaces line breaks, carriage returns, and tabs with their appropriate character
function p._escapeAllCharacters(text)
function disinherit(frame, onlyTheseKeys)
local indices = p._getAllMatchIndices(text, "\\")
local parent = frame:getParent() or frame
local splitText = mw.text.split(text, '')
local orphan = parent:newChild{}
orphan.getParent = parent.getParent --returns nil
local skip = false
orphan.args = {}
for k,v in ipairs(indices) do
if not skip then
if onlyTheseKeys then
local family = {parent, frame}
splitText[v] = ''
local nc = splitText[v + 1]
for f = 1, 2 do
for k, v in pairs(family[f] and family[f].args or {}) do
splitText[v + 1] = (
orphan.args[k] = orphan.args[k] or v
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
end
else
skip = false
end
end
parent.args = mw.clone(orphan.args)
end
setmetatable(orphan.args, nil)
return table.concat(splitText)
for _, k in ipairs(onlyTheseKeys) do
end
rawset(orphan.args, k, nil)

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
end
end
return orphan, parent
return mw.ustring.gsub(str, "%&%S-;", replaceHTMLCharCodes)
end
end


function p._removeAllLinks(text)
function getSeparator(args, default)
local br = tonumber(args.br) and ('<br>'):rep(args.br) or args.br
-- find all [ and ] characters and remove them
local splitText = mw.text.split(text, '')
local sep = args.sep or br or default
return #sep > 0 and ' ' .. sep .. ' ' or sep
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
end


function p._removeXML(text)
function p.get(frame, arg, passArgs)
local orphan, frame = disinherit(frame, passArgs and {arg or 1})
-- finds all xml tags and remove them
local splitText = mw.text.split(text, '')
local code = frame.args[arg or 1] or ''
if code:match'UNIQ%-%-nowiki' then
local numberOfBrackets = 0
code = mw.text.unstripNoWiki(code)
local numberOfDoubleQuotes = 0
:gsub('&lt;', '<')
local numberOfSingleQuotes = 0
:gsub('&gt;', '>')
for k,v in ipairs(splitText) do
:gsub('&quot;', '"')
if splitText[k] == '<' then
-- Replace `&#125;%-` with `}-` because of some server quirk leading to
numberOfBrackets = numberOfBrackets + 1
-- =mw.text.unstripNoWiki(mw.getCurrentFrame():preprocess('<nowiki>}-</nowiki>'))
if numberOfBrackets > 1 then numberOfBrackets = 1 else splitText[k] = '' end
-- outputting `&#125;-` instead of `}-`, while it's ok with `<nowiki>} -</nowiki>`
elseif splitText[k] == '>' then
:gsub('&#125;%-', '}-')
numberOfBrackets = numberOfBrackets - 1
-- The same with `-&#123;`
if numberOfBrackets < 0 then numberOfBrackets = 0 else splitText[k] = '' end
:gsub('%-&#123;', '-{')
else
if numberOfBrackets == 1 then
splitText[k] = ''
end
end
end
end
local kill_categories = frame.args.demo_kill_categories or frame.args.nocat
return table.concat(splitText)
return {
source = code,
output = orphan:preprocess(code):gsub(kill_categories and '%[%[Category.-%]%]' or '', ''),
frame = frame
}
end
end


function p.main(frame, demoTable)
-- from Wikipedia
local show = demoTable or p.get(frame)
local function makeInvokeFunc(funcName)
return function (frame)
local args = show.frame.args
if show[args.result_arg] then
local args = getArgs(frame, {
return show[args.result_arg]
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
local yesno = require('Module:Yesno')
args.reverse = yesno(args.reverse, false)
args.sep = getSeparator(args, '')
local source = frame:extensionTag{
name = 'syntaxhighlight',
args = {
lang = 'wikitext',
style = args.style
},
content = show.source
}
return args.reverse and
show.output .. args.sep .. source or
source .. args.sep .. show.output
end
end


-- Alternate function to return an inline result
p.main = makeInvokeFunc("_main")
function p._main(args)
function p.inline(frame, demoTable)
local nowiki = yn(args['nowiki']) or false
local show = demoTable or p.get(frame)
local format = args['format'] or 'block'
local args = show.frame.args
if show[args.result_arg] then
local code = p._code(args)
return show[args.result_arg]
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
local yesno = require('Module:Yesno')
args.reverse = yesno(args.reverse, false)
args.sep = getSeparator(args, args.reverse and '←' or '→')
local source = frame:extensionTag{
name = 'syntaxhighlight',
args = {
lang = 'wikitext',
inline = true,
style = args.style
},
content = show.source
}
return args.reverse and
show.output .. args.sep .. source or
source .. args.sep .. show.output
end
end


--passing of args into other module without preprocessing
p.code = makeInvokeFunc("_code")
function p._code(args)
function p.module(frame)
local nowiki = yn(args['nowiki']) or false
local orphan, frame = disinherit(frame, {
'demo_template',
local text = p._raw(args)
'demo_module',
local format = args['format'] or 'block'
'demo_module_func',
local syntaxhighlight = yn(args["syntaxhighlight"]) or false
'demo_main',
if not syntaxhighlight then
'demo_sep',
local code = format == 'inline'
'demo_br',
and mw.getCurrentFrame():preprocess("<code>" .. text .. "</code>")
'demo_result_arg',
or mw.getCurrentFrame():preprocess("<code style=\"display:inline-block;\">" .. text .. "</code>")
'demo_kill_categories',
return code
'nocat'
})
local template = frame.args.demo_template and 'Template:'..frame.args.demo_template
local demoFunc = frame.args.demo_module_func or 'main\n'
local demoModule = require('Module:' .. frame.args.demo_module)[demoFunc:match('^%s*(.-)%s*$')]
frame.args.br, frame.args.result_arg = frame.args.demo_sep or frame.args.demo_br, frame.args.demo_result_arg
local kill_categories = frame.args.demo_kill_categories or frame.args.nocat
if demoModule then
local named = {insert = function(self, ...) table.insert(self, ...) return self end}
local source = {insert = named.insert, '{{', frame.args.demo_template or frame.args.demo_module, '\n'}
if not template then
source:insert(2, '#invoke:'):insert(4, '|'):insert(5, demoFunc)
end
local insertNamed = #source + 1
for k, v in pairs(orphan.args) do
local nan, insert = type(k) ~= 'number', {v}
local target = nan and named or source
target:insert'|'
if nan then
target:insert(k):insert'=':insert'\n'
table.insert(insert, 1, #target)
end
target:insert(unpack(insert))
local nowiki = v:match('nowiki')
if nowiki or v:match('{{.-}}') then
orphan.args[k] = frame:preprocess(nowiki and mw.text.unstripNoWiki(v) or v)
end
end
source:insert'}}'
table.insert(source, insertNamed, table.concat(named))
return p.main(orphan, {
source = table.concat(source), "<>'|=~",
output = tostring(demoModule(orphan)):gsub(kill_categories and '%[%[Category.-%]%]' or '', ''),
frame = frame
})
else
else
return "ERROR: Invalid module function: "..demoFunc
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
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
return p

Revision as of 02:31, 14 August 2024

local p = {}

--creates a frame object that cannot access any of the parent's args
--unless a table containing a list keys of not to inherit is provided
function disinherit(frame, onlyTheseKeys)
	local parent = frame:getParent() or frame
	local orphan = parent:newChild{}
	orphan.getParent = parent.getParent --returns nil
	orphan.args = {}
	if onlyTheseKeys then
		local family = {parent, frame}
		for f = 1, 2 do
			for k, v in pairs(family[f] and family[f].args or {}) do
				orphan.args[k] = orphan.args[k] or v
			end
		end
		parent.args = mw.clone(orphan.args)
		setmetatable(orphan.args, nil)
		for _, k in ipairs(onlyTheseKeys) do
			rawset(orphan.args, k, nil)
		end
	end
	return orphan, parent
end

function getSeparator(args, default)
	local br = tonumber(args.br) and ('<br>'):rep(args.br) or args.br
	local sep = args.sep or br or default
	return #sep > 0 and ' ' .. sep .. ' ' or sep
end

function p.get(frame, arg, passArgs)
	local orphan, frame = disinherit(frame, passArgs and {arg or 1})
	local code = frame.args[arg or 1] or ''
	if code:match'UNIQ%-%-nowiki' then
		code = mw.text.unstripNoWiki(code)
			:gsub('&lt;', '<')
			:gsub('&gt;', '>')
			:gsub('&quot;', '"')
			-- Replace `&#125;%-` with `}-` because of some server quirk leading to
			-- =mw.text.unstripNoWiki(mw.getCurrentFrame():preprocess('<nowiki>}-</nowiki>'))
			-- outputting `&#125;-` instead of `}-`, while it's ok with `<nowiki>} -</nowiki>`
			:gsub('&#125;%-', '}-')
			-- The same with `-&#123;`
			:gsub('%-&#123;', '-{')
	end
	local kill_categories = frame.args.demo_kill_categories or frame.args.nocat
	return {
		source = code,
		output = orphan:preprocess(code):gsub(kill_categories and '%[%[Category.-%]%]' or '', ''),
		frame = frame
	}
end

function p.main(frame, demoTable)
	local show = demoTable or p.get(frame)
	local args = show.frame.args
	if show[args.result_arg] then
		return show[args.result_arg]
	end
	local yesno = require('Module:Yesno')
	args.reverse = yesno(args.reverse, false)
	args.sep = getSeparator(args, '')
	local source = frame:extensionTag{
		name = 'syntaxhighlight',
		args = {
			lang = 'wikitext',
			style = args.style
		},
		content = show.source
	}
	return args.reverse and
		show.output .. args.sep .. source or
		source .. args.sep .. show.output
end

-- Alternate function to return an inline result
function p.inline(frame, demoTable)
	local show = demoTable or p.get(frame)
	local args = show.frame.args
	if show[args.result_arg] then
		return show[args.result_arg]
	end
	local yesno = require('Module:Yesno')
	args.reverse = yesno(args.reverse, false)
	args.sep = getSeparator(args, args.reverse and '←' or '→')
	local source =  frame:extensionTag{
		name = 'syntaxhighlight',
		args = {
			lang = 'wikitext',
			inline = true,
			style = args.style
		},
		content = show.source
	}
	return args.reverse and
		show.output .. args.sep .. source or
		source .. args.sep .. show.output
end

--passing of args into other module without preprocessing
function p.module(frame)
	local orphan, frame = disinherit(frame, {
		'demo_template',
		'demo_module',
		'demo_module_func',
		'demo_main',
		'demo_sep',
		'demo_br',
		'demo_result_arg',
		'demo_kill_categories',
		'nocat'
	})
	local template = frame.args.demo_template and 'Template:'..frame.args.demo_template
	local demoFunc = frame.args.demo_module_func or 'main\n'
	local demoModule = require('Module:' .. frame.args.demo_module)[demoFunc:match('^%s*(.-)%s*$')]
	frame.args.br, frame.args.result_arg = frame.args.demo_sep or frame.args.demo_br, frame.args.demo_result_arg
	local kill_categories = frame.args.demo_kill_categories or frame.args.nocat
	if demoModule then
		local named = {insert = function(self, ...) table.insert(self, ...) return self end}
		local source = {insert = named.insert, '{{', frame.args.demo_template or frame.args.demo_module, '\n'}
		if not template then
			source:insert(2, '#invoke:'):insert(4, '|'):insert(5, demoFunc)
		end
		local insertNamed = #source + 1
		for k, v in pairs(orphan.args) do
			local nan, insert = type(k) ~= 'number', {v}
			local target = nan and named or source
			target:insert'|'
			if nan then
				target:insert(k):insert'=':insert'\n'
				table.insert(insert, 1, #target)
			end
			target:insert(unpack(insert))
			local nowiki = v:match('nowiki')
			if nowiki or v:match('{{.-}}') then
				orphan.args[k] = frame:preprocess(nowiki and mw.text.unstripNoWiki(v) or v)
			end
		end
		source:insert'}}'
		table.insert(source, insertNamed, table.concat(named))
		return p.main(orphan, {
			source = table.concat(source), "<>'|=~",
			output = tostring(demoModule(orphan)):gsub(kill_categories and '%[%[Category.-%]%]' or '', ''),
			frame = frame
		})
	else
		return "ERROR: Invalid module function: "..demoFunc
	end
end

return p