Module:Demo/sandbox: Difference between revisions
Appearance
Content deleted Content added
BrandonXLF (talk | contribs) Add newline before output Tag: Reverted |
BrandonXLF (talk | contribs) Restored revision 1216257595 by Awesome Aasim (Restorer) |
||
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 |
|||
-- replaces all usages of \[, \], \<, \> \\, \{, and \} with [, ], <, >, \, {, and } |
|||
--creates a frame object that cannot access any of the parent's args |
|||
-- also replaces line breaks, carriage returns, and tabs with their appropriate character |
|||
--unless a table containing a list keys of not to inherit is provided |
|||
function |
function p._escapeAllCharacters(text) |
||
local |
local indices = p._getAllMatchIndices(text, "\\") |
||
local |
local splitText = mw.text.split(text, '') |
||
local skip = false |
|||
orphan.getParent = parent.getParent --returns nil |
|||
for k,v in ipairs(indices) do |
|||
orphan.args = {} |
|||
if not skip then |
|||
splitText[v] = '' |
|||
local family = {parent, frame} |
|||
local nc = splitText[v + 1] |
|||
splitText[v + 1] = ( |
|||
for k, v in pairs(family[f] and family[f].args or {}) do |
|||
nc == "e" and '=' or |
|||
orphan.args[k] = orphan.args[k] or v |
|||
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>&</nowiki>') or |
|||
splitText[v + 1] |
|||
) |
|||
mw.log(splitText[v + 1]) |
|||
if nc == '\\' then |
|||
skip = true |
|||
end |
end |
||
else |
|||
skip = false |
|||
end |
end |
||
end |
|||
parent.args = mw.clone(orphan.args) |
|||
return table.concat(splitText) |
|||
setmetatable(orphan.args, nil) |
|||
end |
|||
for _, k in ipairs(onlyTheseKeys) do |
|||
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 mw.ustring.gsub(str, "%&%S-;", replaceHTMLCharCodes) |
|||
return orphan, parent |
|||
end |
end |
||
function |
function p._removeAllLinks(text) |
||
-- find all [ and ] characters and remove them |
|||
local br = tonumber(args.br) and ('<br>'):rep(args.br) or args.br |
|||
local |
local splitText = mw.text.split(text, '') |
||
local numberOfBrackets = 0 |
|||
return #sep > 0 and ' ' .. sep .. ' ' or sep |
|||
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. |
function p._removeXML(text) |
||
-- finds all xml tags and remove them |
|||
local orphan, frame = disinherit(frame, passArgs and {arg or 1}) |
|||
local |
local splitText = mw.text.split(text, '') |
||
local numberOfBrackets = 0 |
|||
if code:match'UNIQ%-%-nowiki' then |
|||
local numberOfDoubleQuotes = 0 |
|||
code = mw.text.unstripNoWiki(code) |
|||
local numberOfSingleQuotes = 0 |
|||
:gsub('<', '<') |
|||
for k,v in ipairs(splitText) do |
|||
:gsub('>', '>') |
|||
if splitText[k] == '<' then |
|||
:gsub('"', '"') |
|||
numberOfBrackets = numberOfBrackets + 1 |
|||
-- Replace `}%-` with `}-` because of some server quirk leading to |
|||
if numberOfBrackets > 1 then numberOfBrackets = 1 else splitText[k] = '' end |
|||
-- =mw.text.unstripNoWiki(mw.getCurrentFrame():preprocess('<nowiki>}-</nowiki>')) |
|||
elseif splitText[k] == '>' then |
|||
-- outputting `}-` instead of `}-`, while it's ok with `<nowiki>} -</nowiki>` |
|||
numberOfBrackets = numberOfBrackets - 1 |
|||
:gsub('}%-', '}-') |
|||
if numberOfBrackets < 0 then numberOfBrackets = 0 else splitText[k] = '' end |
|||
-- The same with `-{` |
|||
else |
|||
:gsub('%-{', '-{') |
|||
if numberOfBrackets == 1 then |
|||
splitText[k] = '' |
|||
end |
|||
end |
|||
end |
end |
||
return table.concat(splitText) |
|||
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 |
end |
||
-- from Wikipedia |
|||
function p.main(frame, demoTable) |
|||
local function makeInvokeFunc(funcName) |
|||
local show = demoTable or p.get(frame) |
|||
return function (frame) |
|||
local args = getArgs(frame, { |
|||
if show[args.result_arg] then |
|||
valueFunc = function (key, value) |
|||
return show[args.result_arg] |
|||
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 .. '\n' .. show.output |
|||
end |
end |
||
p.main = makeInvokeFunc("_main") |
|||
-- Alternate function to return an inline result |
|||
function p. |
function p._main(args) |
||
local |
local nowiki = yn(args['nowiki']) or false |
||
local |
local format = args['format'] or 'block' |
||
local code = p._code(args) |
|||
if show[args.result_arg] then |
|||
local result = p._result(args) |
|||
return show[args.result_arg] |
|||
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 |
||
p.code = makeInvokeFunc("_code") |
|||
--passing of args into other module without preprocessing |
|||
function p. |
function p._code(args) |
||
local |
local nowiki = yn(args['nowiki']) or false |
||
local text = p._raw(args) |
|||
'demo_template', |
|||
local format = args['format'] or 'block' |
|||
'demo_module', |
|||
local syntaxhighlight = yn(args["syntaxhighlight"]) or false |
|||
'demo_module_func', |
|||
if not syntaxhighlight then |
|||
'demo_main', |
|||
local code = format == 'inline' |
|||
'demo_sep', |
|||
and mw.getCurrentFrame():preprocess("<code>" .. text .. "</code>") |
|||
'demo_br', |
|||
or mw.getCurrentFrame():preprocess("<code style=\"display:inline-block;\">" .. text .. "</code>") |
|||
'demo_result_arg', |
|||
return code |
|||
'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 |
else |
||
local code = format == "inline" |
|||
return "ERROR: Invalid module function: "..demoFunc |
|||
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:41, 14 August 2024
![]() | This is the module sandbox page for Module:Demo (diff). |
![]() | This module is rated as ready for general use. It has reached a mature form and is thought to be relatively bug-free and ready for use wherever appropriate. It is ready to mention on help pages and other Wikipedia resources as an option for new users to learn. To reduce server load and bad output, it should be improved by sandbox testing rather than repeated trial-and-error editing. |
![]() | This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
Usage
Usage via templates
This module supports {{Demo}}
{{#invoke:Demo|main}}
and {{Demo inline}}
{{#invoke:Demo|inline}}
The input must be wrapped in <nowiki>
tags or else it may be processed before the module can read it.
Usage in a module
If you want to use this in another module (such as to make the output prettier), you can get values like so:
require('Module:demo').get(frame)
Function get()
returns a table containing:
source
= the source code (without<syntaxhighlight>
wrappers, characters substituted with html entities)output
= the execution result of the source.frame
= the frame from which this template took the parameter.
By default, get()
takes the first parameter of frame. If the frame uses a different parameter name for the nowiki-wrapped source, then place that name (as a string) as the second parameter, like so require('Module:demo').get(frame, 'alternate_name')
Example:
local p = {}
function p.main(frame)
local parts = require('Module:demo').get(frame)
return '…Pretty HTML… <pre>' .. parts.source .. '</pre> …More pretty HTML… ' .. parts.output .. ' …Even more pretty HTML…'
end
return p
See also
- Template:Nowiki template demo which uses Module:Template test case
- Template:Automarkup which uses Module:Automarkup
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>&</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