Module:Unsubst: Difference between revisions
imported>Jeffersonkendric Created page with "local checkType = require('libraryUtil').checkType local p = {} local BODY_PARAM = '$B' local specialParams = { ['$params'] = 'parameter list', ['$aliases'] = 'parameter..." |
imported>Jeffersonkendric No edit summary |
||
Line 1: | Line 1: | ||
local checkType = require('libraryUtil').checkType |
|||
local p = {} |
local p = {} |
||
local BODY_PARAM = '$B' |
|||
local specialParams = { |
local specialParams = { |
||
['$N'] = 'template name', -- Deprecated, but keeping until it is removed from transcluding templates |
|||
['$params'] = 'parameter list', |
|||
['$ |
['$B'] = 'template content', |
||
['$flags'] = 'flags', |
|||
['$B'] = 'template content' |
|||
} |
} |
||
function |
p[''] = function ( frame ) |
||
if not frame:getParent() then |
|||
-- If we are substing, this function returns a template invocation, and if |
|||
error( '{{#invoke:Unsubst|}} makes no sense without a parent frame' ) |
|||
-- 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 |
end |
||
if not frame.args['$B'] then |
|||
error( '{{#invoke:Unsubst|}} requires parameter $B (template content)' ) |
|||
-- 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 |
end |
||
if mw.isSubsting() then |
|||
-- Find the invocation name. |
|||
---- substing |
|||
local mTemplateInvocation = require('Module:Template invocation') |
|||
-- Combine passed args with passed defaults |
|||
local name = mTemplateInvocation.name(frame:getParent():getTitle()) |
|||
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 75: | Line 29: | ||
args[k] = v |
args[k] = v |
||
end |
end |
||
end |
|||
-- Build an equivalent template invocation |
|||
-- Trim parameters, if not specified otherwise |
|||
-- First, find the title to use |
|||
if not string.find( ','..(frame.args['$flags'] or '')..',', ',%s*keep%-whitespace%s*,' ) then |
|||
local titleobj = mw.title.new(frame:getParent():getTitle()) |
|||
for k, v in pairs( args ) do args[k] = mw.ustring.match(v, '^%s*(.*)%s*$') or '' end |
|||
local title |
|||
end |
|||
if titleobj.namespace == 10 then -- NS_TEMPLATE |
|||
title = titleobj.text |
|||
-- Pull information from parameter aliases |
|||
elseif titleobj.namespace == 0 then -- NS_MAIN |
|||
local aliases = {} |
|||
title = ':' .. titleobj.text |
|||
if frame.args['$aliases'] then |
|||
else |
|||
local list = mw.text.split( frame.args['$aliases'], '%s*,%s*' ) |
|||
title = titleobj.prefixedText |
|||
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 |
||
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 |
|||
-- Build the invocation body with numbered args first, then named |
|||
-- Remove empty parameters, if specified |
|||
local ret = '{{' .. title |
|||
if string.find( ','..(frame.args['$flags'] or '')..',', ',%s*remove%-empty%s*,' ) then |
|||
local tmp = 0 |
|||
for k, v in ipairs( args ) do |
for k, v in ipairs( args ) do |
||
if string.find( v, '=', 1, true ) then |
|||
if v ~= '' or ( args[k+1] and args[k+1] ~= '' ) or ( args[k+2] and args[k+2] ~= '' ) then |
|||
-- likely something like 1=foo=bar, we need to do it as a named arg |
|||
tmp = k |
|||
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 |
||
ret = ret .. '|' .. k .. '=' .. v |
|||
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 |
Revision as of 07:45, 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 p = {}
local specialParams = {
['$N'] = 'template name', -- Deprecated, but keeping until it is removed from transcluding templates
['$B'] = 'template content',
}
p[''] = function ( frame )
if not frame:getParent() then
error( '{{#invoke:Unsubst|}} makes no sense without a parent frame' )
end
if not frame.args['$B'] then
error( '{{#invoke:Unsubst|}} requires parameter $B (template content)' )
end
if mw.isSubsting() then
---- substing
-- Combine passed args with passed defaults
local args = {}
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
-- Build an equivalent template invocation
-- First, find the title to use
local titleobj = mw.title.new(frame:getParent():getTitle())
local title
if titleobj.namespace == 10 then -- NS_TEMPLATE
title = titleobj.text
elseif titleobj.namespace == 0 then -- NS_MAIN
title = ':' .. titleobj.text
else
title = titleobj.prefixedText
end
-- Build the invocation body with numbered args first, then named
local ret = '{{' .. title
for k, v in ipairs( args ) do
if string.find( v, '=', 1, true ) then
-- likely something like 1=foo=bar, we need to do it as a named arg
break
end
ret = ret .. '|' .. v
args[k] = nil
end
for k, v in pairs( args ) do
ret = ret .. '|' .. k .. '=' .. v
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
return p