Module:TemplateDataDoc

Module documentation
warning 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.

UsageEdit

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 = '&lt;!-- ' .. value .. ' --&gt;';
				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;