Модуль:TemplateDataDoc
Модуль для работы с TemplateData и автоматической генерации заготовок для копирования и примеров использования шаблонов на основе её.
Для корректной сортировки параметров в TemplateData должен содержаться массив paramOrder
. При редактировании через визуальный интерфейс он добавляется в момент перетаскивания параметров вверх-вниз в списке.
Методы
Внешние
- generateBlank( frame ) — вывод заготовки для вставки шаблона в статью (см. {{Заготовка шаблона}})
- generateExample( frame ) — вывод примера использования шаблона (см. {{Пример шаблона}})
Внутренние
- getTemplateData( pageName ) — парсинг TemplateData с указанной страницы
local docSubPage = mw.message.new( 'Templatedata-doc-subpage' ):plain(); local p = {}; local lastNumber = 0; -- Enable/disable additional spacing for block-formatted templates local formatBlockSpaces = true; local noDocNote = 'TemplateDataDoc: Запишите страницу для отображения заполненного шаблона.'; 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', 'from', '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 false; end; local json = mw.ustring.match( title:getContent(), '<[Tt]emplate[Dd]ata%s*>(.*)</[Tt]emplate[Dd]ata%s*>' ); if not json then return nil; end return p.processJson( json ) end function p.getValue( data, key ) if data[ key ] then return data[ key ]; end -- Numbered keys return as numbers local nkey = tonumber( key ); if nkey ~= nil and data[ nkey ] then return data[ nkey ]; end return {}; 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.formatKeyValue( key, parameterData, formatData ) if parameterData[ 'deprecated' ] then return ''; end local args = formatData.args; local parameterName = key; local nkey = tonumber( key ); -- Add additional spacing to string keys if formatData.parameterLength and ( nkey == nil or lastNumber ~= nkey - 1 ) then while mw.ustring.len( key ) < formatData.parameterLength do key = key .. ' '; end end -- Remove numbering for adjacent numbered keys if nkey ~= nil and lastNumber == nkey - 1 then key = ''; lastNumber = nkey; end local value = ''; if formatData.valueKey == 'example' and parameterData[ 'example' ] then -- Example value = parameterData[ 'example' ]; else if formatData.valueKey == 'description' and parameterData[ 'description' ] then -- Description value = parameterData[ 'description' ]; if value ~= '' then value = '<!-- ' .. value .. ' -->'; end elseif parameterData[ 'autovalue' ] then -- Autovalue value = parameterData[ 'autovalue' ]; end if args[ '$' .. parameterName ] and args[ '$' .. parameterName ] ~= '' then -- Custom values from template call value = args[ '$' .. parameterName ]; end end local formattedKey = mw.ustring.gsub( formatData.paramKeyFormat, '_+', key, 1 ); if key == '' then formattedKey = mw.ustring.gsub( formattedKey, '=', '' ); end return formattedKey .. mw.ustring.gsub( formatData.paramValueFormat, '_', value, 1 ); end function p.generateBlankCode( templateData, templateName, args ) if templateData == false then return '{{' .. templateName .. '}}'; end local parameterLength = 0; for i, parameterName in ipairs( templateData[ 'paramOrder' ] ) do local parameterData = p.getValue( templateData[ 'params' ], parameterName ); if not parameterData[ 'deprecated' ] then local length = mw.ustring.len( parameterName ); if length > parameterLength then parameterLength = length; end end end local isBlockFormatted, startFormat, endFormat, paramKeyFormat, paramValueFormat = p.getFormatParts( templateData[ 'format' ], templateName ); local out = startFormat; lastNumber = 0; for i, parameterName in ipairs( templateData[ 'paramOrder' ] ) do local parameterData = p.getValue( templateData[ 'params' ], parameterName ); if parameterData[ 'inherits' ] then parameterData = p.getValue( templateData[ 'params' ], parameterData[ 'inherits' ] ); end out = out .. p.formatKeyValue( parameterName, parameterData, { args = args, valueKey = ( args[ 'description' ] and 'description' or nil ), isBlockFormatted = isBlockFormatted, parameterLength = parameterLength, paramKeyFormat = paramKeyFormat, paramValueFormat = paramValueFormat, } ); 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 ); local previewNote = '' if templateData == false and frame:preprocess('{{REVISIONID}}') == '' then previewNote = '<div class="warningbox">' .. noDocNote .. '</div>'; end return previewNote .. frame:extensionTag{ name = 'pre', content = out }; end function p.generateExampleCode( templateData, templateName, args ) if templateData == false then return '{{' .. templateName .. '}}'; end local parameterLength = 0; for i, parameterName in ipairs( templateData[ 'paramOrder' ] ) do local parameterData = p.getValue( templateData[ 'params' ], parameterName ); if parameterData[ 'example' ] and not parameterData[ 'deprecated' ] then local length = mw.ustring.len( parameterName ); if length > parameterLength then parameterLength = length; end end end local isBlockFormatted, startFormat, endFormat, paramKeyFormat, paramValueFormat = p.getFormatParts( templateData[ 'format' ], templateName ); local out = startFormat; lastNumber = 0; for i, parameterName in ipairs( templateData[ 'paramOrder' ] ) do local parameterData = p.getValue( templateData[ 'params' ], parameterName ); if parameterData[ 'inherits' ] then parameterData = p.getValue( templateData[ 'params' ], parameterData[ 'inherits' ] ); end if parameterData[ 'example' ] then out = out .. p.formatKeyValue( parameterName, parameterData, { args = args, valueKey = 'example', isBlockFormatted = isBlockFormatted, parameterLength = parameterLength, paramKeyFormat = paramKeyFormat, paramValueFormat = paramValueFormat, } ); 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 ); local previewNote = '' if templateData == false and frame:preprocess('{{REVISIONID}}') == '' then previewNote = '<div class="warningbox">' .. noDocNote .. '</div>'; end return previewNote .. frame:preprocess( out ) .. frame:extensionTag{ name = 'pre', content = out }; end return p;