Module:Unsubst: Difference between revisions
imported>Jeffersonkendric No edit summary |
imported>Jeffersonkendric Undo revision 131863 by Jeffersonkendric (talk) |
||
Line 1: | Line 1: | ||
local checkType = require('libraryUtil').checkType |
|||
local p = {} |
local p = {} |
||
local BODY_PARAM = '$B' |
|||
local specialParams = { |
local specialParams = { |
||
['$params'] = 'parameter list', |
|||
['$N'] = 'template name', -- Deprecated, but keeping until it is removed from transcluding templates |
|||
['$ |
['$aliases'] = 'parameter aliases', |
||
['$flags'] = 'flags', |
|||
['$B'] = 'template content' |
|||
} |
} |
||
function p.main(frame, body) |
|||
-- If we are substing, this function returns a template invocation, and if |
|||
if not frame:getParent() then |
|||
-- not, it returns the template body. The template body can be specified in |
|||
error( '{{#invoke:Unsubst|}} makes no sense without a parent frame' ) |
|||
-- the body parameter, or in the template parameter defined in the |
|||
-- BODY_PARAM variable. This function can be called from Lua or from |
|||
-- #invoke. |
|||
-- Return the template body if we aren't substing. |
|||
if not mw.isSubsting() then |
|||
if body ~= nil then |
|||
return body |
|||
elseif frame.args[BODY_PARAM] ~= nil then |
|||
return frame.args[BODY_PARAM] |
|||
else |
|||
error(string.format( |
|||
"no template content specified (use parameter '%s' from #invoke)", |
|||
BODY_PARAM |
|||
), 2) |
|||
end |
|||
end |
end |
||
if not frame.args['$B'] then |
|||
-- Sanity check for the frame object. |
|||
error( '{{#invoke:Unsubst|}} requires parameter $B (template content)' ) |
|||
if type(frame) ~= 'table' |
|||
or type(frame.getParent) ~= 'function' |
|||
or not frame:getParent() |
|||
then |
|||
error( |
|||
"argument #1 to 'main' must be a frame object with a parent " .. |
|||
"frame available", |
|||
2 |
|||
) |
|||
end |
end |
||
-- Find the invocation name. |
|||
if mw.isSubsting() then |
|||
local mTemplateInvocation = require('Module:Template invocation') |
|||
---- substing |
|||
local name = mTemplateInvocation.name(frame:getParent():getTitle()) |
|||
-- Combine passed args with passed defaults |
|||
local args = {} |
|||
-- Combine passed args with passed defaults |
|||
local args = {} |
|||
if string.find( ','..(frame.args['$flags'] or '')..',', ',%s*override%s*,' ) then |
|||
for k, v in pairs( frame:getParent().args ) do |
|||
args[k] = v |
|||
end |
|||
for k, v in pairs( frame.args ) do |
|||
if not specialParams[k] then |
|||
if v == '__DATE__' then |
|||
v = mw.getContentLanguage():formatDate( 'F Y' ) |
|||
end |
|||
args[k] = v |
|||
end |
|||
end |
|||
else |
|||
for k, v in pairs( frame.args ) do |
for k, v in pairs( frame.args ) do |
||
if not specialParams[k] then |
if not specialParams[k] then |
||
Line 29: | Line 75: | ||
args[k] = v |
args[k] = v |
||
end |
end |
||
end |
|||
-- Trim parameters, if not specified otherwise |
|||
-- Build an equivalent template invocation |
|||
if not string.find( ','..(frame.args['$flags'] or '')..',', ',%s*keep%-whitespace%s*,' ) then |
|||
-- First, find the title to use |
|||
for k, v in pairs( args ) do args[k] = mw.ustring.match(v, '^%s*(.*)%s*$') or '' end |
|||
local titleobj = mw.title.new(frame:getParent():getTitle()) |
|||
end |
|||
local title |
|||
if titleobj.namespace == 10 then -- NS_TEMPLATE |
|||
-- Pull information from parameter aliases |
|||
title = titleobj.text |
|||
local aliases = {} |
|||
elseif titleobj.namespace == 0 then -- NS_MAIN |
|||
if frame.args['$aliases'] then |
|||
title = ':' .. titleobj.text |
|||
local list = mw.text.split( frame.args['$aliases'], '%s*,%s*' ) |
|||
else |
|||
for k, v in ipairs( list ) do |
|||
title = titleobj.prefixedText |
|||
local tmp = mw.text.split( v, '%s*>%s*' ) |
|||
aliases[tonumber(mw.ustring.match(tmp[1], '^[1-9][0-9]*$')) or tmp[1]] = ((tonumber(mw.ustring.match(tmp[2], '^[1-9][0-9]*$'))) or tmp[2]) |
|||
end |
end |
||
end |
|||
for k, v in pairs( aliases ) do |
|||
if args[k] and ( not args[v] or args[v] == '' ) then |
|||
args[v] = args[k] |
|||
end |
|||
args[k] = nil |
|||
end |
|||
-- Remove empty parameters, if specified |
|||
-- Build the invocation body with numbered args first, then named |
|||
if string.find( ','..(frame.args['$flags'] or '')..',', ',%s*remove%-empty%s*,' ) then |
|||
local ret = '{{' .. title |
|||
local tmp = 0 |
|||
for k, v in ipairs( args ) do |
for k, v in ipairs( args ) do |
||
if v ~= '' or ( args[k+1] and args[k+1] ~= '' ) or ( args[k+2] and args[k+2] ~= '' ) then |
|||
if string.find( v, '=', 1, true ) then |
|||
tmp = k |
|||
-- likely something like 1=foo=bar, we need to do it as a named arg |
|||
else |
|||
break |
break |
||
end |
end |
||
ret = ret .. '|' .. v |
|||
args[k] = nil |
|||
end |
end |
||
for k, v in pairs( args ) do |
for k, v in pairs( args ) do |
||
if v == '' then |
|||
if not (type(k) == 'number' and k < tmp) then args[k] = nil end |
|||
end |
|||
end |
end |
||
return ret .. '}}' |
|||
else |
|||
---- Not substing |
|||
-- Just return the "body" |
|||
return frame.args['$B'] .. (frame.args['$N'] and frame:getParent():getTitle() == mw.title.getCurrentTitle().prefixedText and '[[Category:Calls to Module:Unsubst that use $N]]' or '') |
|||
end |
end |
||
-- Order parameters |
|||
if frame.args['$params'] then |
|||
local params, tmp = mw.text.split( frame.args['$params'], '%s*,%s*' ), {} |
|||
for k, v in ipairs(params) do |
|||
v = tonumber(mw.ustring.match(v, '^[1-9][0-9]*$')) or v |
|||
if args[v] then tmp[v], args[v] = args[v], nil end |
|||
end |
|||
for k, v in pairs(args) do tmp[k], args[k] = args[k], nil end |
|||
args = tmp |
|||
end |
|||
return mTemplateInvocation.invocation(name, args) |
|||
end |
end |
||
p[''] = p.main -- For backwards compatibility |
|||
return p |
return p |
Latest revision as of 07:48, 19 September 2021
![]() | This Lua module is used on 5,050,000+ pages, or roughly 3257% of all pages. To avoid major disruption and server load, any changes should be tested in the You may want to test changes and make sure they are approved by site staff before submitting them.The tested changes can be added to this page in a single edit. Consider discussing changes on the talk page. |
Helper module to facilitate a substituted template transform into a template transclusion.
Maintenance templates, such as {{Citation needed}} or {{Refimprove}}, should never be substituted. A trick to avoid that is to make a template substitute to its transcluded form.
Usage
To turn a template into a self-substituting template, wrap the existing template code with:
{{ {{{|safesubst:}}}#invoke:Unsubst||$B= [ ... existing template code ... ] }}
The wikitext to display when not substed must be given as "$B". A parameter "$N" may also be seen in some templates; this was required in an older version of the module, but is no longer necessary and may be removed. Such templates are automatically placed in Category:Calls to Module:Unsubst that use $N (0).
All other parameters passed to the #invoke will be copied to the generated template invocation as default values. If the value of any of these default parameters is "__DATE__", that value in the generated template invocation will be the current month and year.
Some templates have a <noinclude> but no matching </noinclude> at the end of the template. In such cases the missing </noinclude> must be added before the ending }}
.
Example
Consider a template Template:Example containing the following code:
{{ {{{|safesubst:}}}#invoke:Unsubst||foo=bar |date=__DATE__ |$B= [ ... Template code goes here ... ] }}
Original | Result |
---|---|
{{subst:example}} | {{Example|foo=bar|date=October 2024}} |
{{subst:example|foo=X}} | {{Example|foo=X|date=October 2024}} |
{{subst:example|baz=X}} | {{Example|foo=bar|baz=X|date=October 2024}} |
{{subst:example|date=January 2001}} | {{Example|foo=bar|date=January 2001}} |
local checkType = require('libraryUtil').checkType
local p = {}
local BODY_PARAM = '$B'
local specialParams = {
['$params'] = 'parameter list',
['$aliases'] = 'parameter aliases',
['$flags'] = 'flags',
['$B'] = 'template content'
}
function p.main(frame, body)
-- If we are substing, this function returns a template invocation, and if
-- not, it returns the template body. The template body can be specified in
-- the body parameter, or in the template parameter defined in the
-- BODY_PARAM variable. This function can be called from Lua or from
-- #invoke.
-- Return the template body if we aren't substing.
if not mw.isSubsting() then
if body ~= nil then
return body
elseif frame.args[BODY_PARAM] ~= nil then
return frame.args[BODY_PARAM]
else
error(string.format(
"no template content specified (use parameter '%s' from #invoke)",
BODY_PARAM
), 2)
end
end
-- Sanity check for the frame object.
if type(frame) ~= 'table'
or type(frame.getParent) ~= 'function'
or not frame:getParent()
then
error(
"argument #1 to 'main' must be a frame object with a parent " ..
"frame available",
2
)
end
-- Find the invocation name.
local mTemplateInvocation = require('Module:Template invocation')
local name = mTemplateInvocation.name(frame:getParent():getTitle())
-- Combine passed args with passed defaults
local args = {}
if string.find( ','..(frame.args['$flags'] or '')..',', ',%s*override%s*,' ) then
for k, v in pairs( frame:getParent().args ) do
args[k] = v
end
for k, v in pairs( frame.args ) do
if not specialParams[k] then
if v == '__DATE__' then
v = mw.getContentLanguage():formatDate( 'F Y' )
end
args[k] = v
end
end
else
for k, v in pairs( frame.args ) do
if not specialParams[k] then
if v == '__DATE__' then
v = mw.getContentLanguage():formatDate( 'F Y' )
end
args[k] = v
end
end
for k, v in pairs( frame:getParent().args ) do
args[k] = v
end
end
-- Trim parameters, if not specified otherwise
if not string.find( ','..(frame.args['$flags'] or '')..',', ',%s*keep%-whitespace%s*,' ) then
for k, v in pairs( args ) do args[k] = mw.ustring.match(v, '^%s*(.*)%s*$') or '' end
end
-- Pull information from parameter aliases
local aliases = {}
if frame.args['$aliases'] then
local list = mw.text.split( frame.args['$aliases'], '%s*,%s*' )
for k, v in ipairs( list ) do
local tmp = mw.text.split( v, '%s*>%s*' )
aliases[tonumber(mw.ustring.match(tmp[1], '^[1-9][0-9]*$')) or tmp[1]] = ((tonumber(mw.ustring.match(tmp[2], '^[1-9][0-9]*$'))) or tmp[2])
end
end
for k, v in pairs( aliases ) do
if args[k] and ( not args[v] or args[v] == '' ) then
args[v] = args[k]
end
args[k] = nil
end
-- Remove empty parameters, if specified
if string.find( ','..(frame.args['$flags'] or '')..',', ',%s*remove%-empty%s*,' ) then
local tmp = 0
for k, v in ipairs( args ) do
if v ~= '' or ( args[k+1] and args[k+1] ~= '' ) or ( args[k+2] and args[k+2] ~= '' ) then
tmp = k
else
break
end
end
for k, v in pairs( args ) do
if v == '' then
if not (type(k) == 'number' and k < tmp) then args[k] = nil end
end
end
end
-- Order parameters
if frame.args['$params'] then
local params, tmp = mw.text.split( frame.args['$params'], '%s*,%s*' ), {}
for k, v in ipairs(params) do
v = tonumber(mw.ustring.match(v, '^[1-9][0-9]*$')) or v
if args[v] then tmp[v], args[v] = args[v], nil end
end
for k, v in pairs(args) do tmp[k], args[k] = args[k], nil end
args = tmp
end
return mTemplateInvocation.invocation(name, args)
end
p[''] = p.main -- For backwards compatibility
return p