Module:TemplateDataDoc
Appearance
This module is rated as ready for general use. It has reached a mature form and is thought to be bug-free and ready for use wherever appropriate. It is ready to mention on help pages and other 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. |
Warning: | This page is shared between multiple wikis. All changes to this page will be automatically copied to all wikis listed in the left side bar. To avoid unnecessary page regeneration and server load, changes should be tested on the page's sandbox. |
Usage
[edit]This module automatically generates blocks of template documentation page using TemplateData.
{{#invoke:TemplateDataDoc|generateBlank}}
— generates blank template wikitext{{#invoke:TemplateDataDoc|generateExample}}
— generates template example wikitext and shows how a template with such parameters will be displayed
For correct order of parameters, TemplateData should contain paramOrder
block.
local docSubPage = mw.message.new( 'Templatedata-doc-subpage' ):plain();
local p = {};
function p.processJson( json )
local status, data = pcall( mw.text.jsonDecode, json );
if status == false then
return nil;
end
if not data[ 'paramOrder' ] then
data[ 'paramOrder' ] = {};
for paramName, paramData in pairs( data[ 'params' ] ) do
table.insert( data[ 'paramOrder' ], paramName );
end
end
local deprecatedParams = {
'nocat',
'nocoord',
'nocatcoord',
};
for _, param in ipairs( deprecatedParams ) do
if data[ 'params' ][ param ] ~= nil then
data[ 'params' ][ param ][ 'deprecated' ] = '-';
end
end
return data;
end
function p.getTemplateData( pageName )
local title = mw.title.makeTitle( 0, pageName );
if not title or not title.exists or not title:getContent() then
return nil;
end;
local json = mw.ustring.match( title:getContent(), '<templatedata%s*>(.*)</templatedata%s*>' );
if not json then
return nil;
end
return p.processJson( json )
end
-- See https://phabricator.wikimedia.org/diffusion/ETDA/browse/master/Specification.md?as=remarkup
-- We need a global format value for the 'block' and 'inline': [[phab:T205438]]
function p.convertFormatString( rawTemplateFormat )
local templateFormat = rawTemplateFormat or 'inline';
local isBlockFormatted = false;
if templateFormat == 'block' then
templateFormat = '{{_\n| _ = _\n}}';
isBlockFormatted = true;
elseif templateFormat == 'inline' then
templateFormat = '{{_|_=_}}';
end
return templateFormat, isBlockFormatted;
end
function p.getFormatParts( rawTemplateFormat, templateName )
local templateFormat, isBlockFormatted = p.convertFormatString( rawTemplateFormat );
local nameFormat = mw.ustring.match( templateFormat, '^[^|]+' );
local paramKeyFormat = mw.ustring.match( templateFormat, '%|[^=]+=' );
local paramValueFormat = mw.ustring.match( templateFormat, '=[^}]+' );
paramValueFormat = mw.ustring.sub( paramValueFormat, 2 );
local endFormat = mw.ustring.match( templateFormat, '%}%}.*$' );
local startFormat = mw.ustring.gsub( nameFormat, '_', templateName );
return isBlockFormatted, startFormat, endFormat, paramKeyFormat, paramValueFormat;
end
function p.generateBlankCode( templateData, templateName, args )
local paramaterLength = 0;
for i, parameterName in ipairs( templateData[ 'paramOrder' ] ) do
local parameterData = templateData[ 'params' ][ parameterName ] or {};
if not parameterData[ 'deprecated' ] then
local length = mw.ustring.len( parameterName );
if length > paramaterLength then
paramaterLength = length;
end
end
end
local isBlockFormatted, startFormat, endFormat, paramKeyFormat, paramValueFormat = p.getFormatParts( templateData[ 'format' ], templateName );
local out = startFormat;
local lastNumber = 0;
for i, parameterName in ipairs( templateData[ 'paramOrder' ] ) do
local parameterData = templateData[ 'params' ][ parameterName ] or {};
if parameterData[ 'inherits' ] then
parameterData = templateData[ 'params' ][ parameterData[ 'inherits' ] ] or {};
end
if not parameterData[ 'deprecated' ] then
local key = parameterName;
local nkey = tonumber(key);
if isBlockFormatted then
if nkey == nil or lastNumber ~= nkey - 1 then
while mw.ustring.len( key ) < paramaterLength do
key = key .. ' ';
end
end
end
if nkey ~= nil and lastNumber == nkey - 1 then
key = '';
lastNumber = nkey;
end
local value = '';
if args[ 'description' ] == '1' and parameterData[ 'description' ] then
value = parameterData[ 'description' ];
if value ~= '' then
value = '<!-- ' .. value .. ' -->';
end
elseif parameterData[ 'autovalue' ] then
value = parameterData[ 'autovalue' ];
end
if args[ '$' .. parameterName ] and args[ '$' .. parameterName ] ~= '' then
value = args[ '$' .. parameterName ];
end
local formattedKey = mw.ustring.gsub( paramKeyFormat, '_+', key, 1 );
if key == '' then
formattedKey = mw.ustring.gsub( formattedKey, '=', '' );
end
out = out .. formattedKey;
out = out .. mw.ustring.gsub( paramValueFormat, '_', value, 1 );
end
end
return out .. endFormat;
end
function p.generateBlank( frame )
local frame = mw.getCurrentFrame();
local getArgs = require( 'Module:Arguments' ).getArgs;
local args = getArgs( frame );
local templateName = frame.args[ 1 ];
table.remove( args, 1 );
local docPage = 'Template:' .. templateName .. '/' .. docSubPage;
local templateData = p.getTemplateData( docPage );
local out = p.generateBlankCode( templateData, templateName, args );
return frame:extensionTag{ name = 'pre', content = out };
end
function p.generateExampleCode( templateData, templateName, args )
local paramaterLength = 0;
for i, parameterName in ipairs( templateData[ 'paramOrder' ] ) do
local parameterData = templateData[ 'params' ][ parameterName ] or {};
if parameterData[ 'example' ] and not parameterData[ 'deprecated' ] then
local length = mw.ustring.len( parameterName );
if length > paramaterLength then
paramaterLength = length;
end
end
end
local isBlockFormatted, startFormat, endFormat, paramKeyFormat, paramValueFormat = p.getFormatParts( templateData[ 'format' ], templateName );
local out = startFormat;
local lastNumber = 0;
for i, parameterName in ipairs( templateData[ 'paramOrder' ] ) do
local parameterData = templateData[ 'params' ][ parameterName ] or {};
if parameterData[ 'inherits' ] then
parameterData = templateData[ 'params' ][ parameterData[ 'inherits' ] ] or {};
end
if parameterData[ 'example' ] and not parameterData[ 'deprecated' ] then
local key = parameterName;
local nkey = tonumber( key );
if isBlockFormatted then
if nkey == nil or lastNumber ~= nkey - 1 then
while mw.ustring.len( key ) < paramaterLength do
key = key .. ' ';
end
end
end
if nkey ~= nil and lastNumber == nkey - 1 then
key = '';
lastNumber = nkey;
end
local value = parameterData[ 'example' ];
local formattedKey = mw.ustring.gsub( paramKeyFormat, '_+', key, 1 );
if key == '' then
formattedKey = mw.ustring.gsub( formattedKey, '=', '' );
end
out = out .. formattedKey;
out = out .. mw.ustring.gsub( paramValueFormat, '_', value, 1 );
end
end
return out .. endFormat;
end
function p.generateExample( frame )
local frame = mw.getCurrentFrame();
local args = frame.args;
local templateName = frame.args[ 1 ];
local docPage = 'Template:' .. templateName .. '/' .. docSubPage;
local templateData = p.getTemplateData( docPage );
local out = p.generateExampleCode( templateData, templateName, args );
return frame:preprocess( out ) .. frame:extensionTag{ name = 'pre', content = out };
end
return p;