Module:Demo/sandbox: Difference between revisions
Appearance
Content deleted Content added
No edit summary Tag: Reverted |
BrandonXLF (talk | contribs) Syncing sandbox code with main template (sync-template-sandbox.js) Tags: Manual revert Reverted |
||
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 |
function disinherit(frame, onlyTheseKeys) |
||
local |
local parent = frame:getParent() or frame |
||
local |
local orphan = parent:newChild{} |
||
orphan.getParent = parent.getParent --returns nil |
|||
local skip = false |
|||
orphan.args = {} |
|||
for k,v in ipairs(indices) do |
|||
if onlyTheseKeys then |
|||
local family = {parent, frame} |
|||
splitText[v] = '' |
|||
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>&</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 |
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 |
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. |
function p.get(frame, arg, passArgs) |
||
local orphan, frame = disinherit(frame, passArgs and {arg or 1}) |
|||
-- finds all xml tags and remove them |
|||
local |
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('<', '<') |
|||
local numberOfSingleQuotes = 0 |
|||
:gsub('>', '>') |
|||
for k,v in ipairs(splitText) do |
|||
:gsub('"', '"') |
|||
if splitText[k] == '<' then |
|||
-- Replace `}%-` 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 `}-` instead of `}-`, while it's ok with `<nowiki>} -</nowiki>` |
|||
elseif splitText[k] == '>' then |
|||
:gsub('}%-', '}-') |
|||
numberOfBrackets = numberOfBrackets - 1 |
|||
-- The same with `-{` |
|||
if numberOfBrackets < 0 then numberOfBrackets = 0 else splitText[k] = '' end |
|||
:gsub('%-{', '-{') |
|||
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) |
|||
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. |
function p.inline(frame, demoTable) |
||
local |
local show = demoTable or p.get(frame) |
||
local |
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. |
function p.module(frame) |
||
local |
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
![]() | 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 = {}
--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('<', '<')
:gsub('>', '>')
:gsub('"', '"')
-- Replace `}%-` with `}-` because of some server quirk leading to
-- =mw.text.unstripNoWiki(mw.getCurrentFrame():preprocess('<nowiki>}-</nowiki>'))
-- outputting `}-` instead of `}-`, while it's ok with `<nowiki>} -</nowiki>`
:gsub('}%-', '}-')
-- The same with `-{`
:gsub('%-{', '-{')
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