Module:Template porting

--[==[ /** * Template porting tools * Designed for testing and demonstrating alternative versions of templates * By User:FishTank / Isaac Fischer */ --]==]

local Porting = {}

-- Libraries of functions --

-- HF stands for High Frequency. -- This Module augments the built-in HF local HF = mw.InfoboxBuilderHF -- Parses invocation parameters, trims whitespace, and removes blanks local getArgs = require('Dev:Arguments').getArgs -- Generates lists local status_messages = { ['notapplicable'] = 'templateporting-status-notapplicable', ['identified'] = 'templateporting-status-identified', ['approved'] = 'templateporting-status-approved', ['ready'] = 'templateporting-status-ready', ['styling'] = 'templateporting-status-styling', ['coding'] = 'templateporting-status-coding', ['module'] = 'templateporting-status-module', ['unknown'] = 'templateporting-status-unknown', } local status_alias = { ['code'] = 'coding', ['aprobada'] = 'approved', ['listo'] = 'ready', ['aprobando'] = 'ready', ['css'] = 'styling', ['style'] = 'styling', ['estilo'] = 'styling', ['migrando'] = 'coding', ['codigo'] = 'coding', ['módulo'] = 'module', ['desconocido'] = 'unknown', } local status_colors = { ['notapplicable'] = 'darkgrey, black', ['identified'] = 'transparent, inherit', ['approved'] = '#00E029, white', ['ready'] = 'whitesmoke, #00E029', ['styling'] = 'transparent, #FF9900', ['coding'] = 'transparent, #FF0066', ['module'] = 'transparent, #0066FF', ['unknown'] = 'transparent, grey', } local messages = { ['en'] = { ['templateporting-label-template'] = 'Template', ['templateporting-label-comparison'] = 'Comparison', ['templateporting-label-status'] = 'Status', ['templateporting-label-documentation'] = 'doc', ['templateporting-label-raw'] = 'raw', ['templateporting-label-dependencies'] = 'Dependencies', ['templateporting-label-testcases'] = 'Test Cases', ['templateporting-error-notemplate'] = 'An entry with no template name was provided', ['templateporting-status-notapplicable'] = 'N/A', ['templateporting-status-identified'] = 'Identified', ['templateporting-status-approved'] = 'Approved', ['templateporting-status-ready'] = 'Ready', ['templateporting-status-styling'] = 'Styling', ['templateporting-status-coding'] = 'Coding', ['templateporting-status-module'] = 'Lua', ['templateporting-status-unknown'] = 'Unknown', ['templateporting-status-notapplicable-desc'] = 'Not suitable for porting', ['templateporting-status-identified-desc'] = 'Identified for porting, no work in progress', ['templateporting-status-approved-desc'] = 'Approved for use on community', ['templateporting-status-ready-desc'] = 'Ready for approval', ['templateporting-status-style-desc'] = 'CSS styling in progress', ['templateporting-status-code-desc'] = 'Template coding in progress', ['templateporting-status-module-desc'] = 'Lua Module coding in progress', ['templateporting-status-unknown-desc'] = 'Status unknown' },	['es'] = { ['templateporting-label-template'] = 'Plantilla', ['templateporting-label-comparison'] = 'Comparación', ['templateporting-label-status'] = 'Estado', ['templateporting-label-documentation'] = 'doc', ['templateporting-label-raw'] = 'raw', ['templateporting-label-dependencies'] = 'Familiares dependientes ', ['templateporting-label-testcases'] = 'Casos de prueba', ['templateporting-error-notemplate'] = 'Un parámetro fue dado sin un nombre de plantilla', ['templateporting-status-notapplicable'] = 'N/A', ['templateporting-status-identified'] = 'Identificado', ['templateporting-status-approved'] = 'Aprobada', ['templateporting-status-ready'] = 'Listo', ['templateporting-status-styling'] = 'Estilando', ['templateporting-status-coding'] = 'Migrando', ['templateporting-status-module'] = 'Lua', ['templateporting-status-unknown'] = 'Desconocido', ['templateporting-status-notapplicable-desc'] = 'No apto para portar', ['templateporting-status-identified-desc'] = 'Identificado para portar, sin trabajo en progreso', ['templateporting-status-approved-desc'] = 'Aprobado para usar en la comunidad', ['templateporting-status-ready-desc'] = 'Listo para aprobación', ['templateporting-status-styling-desc'] = 'Estilo CSS en progreso', ['templateporting-status-coding-desc'] = 'Codificación de la plantilla en progreso', ['templateporting-status-module-desc'] = 'Codificación del módulo Lua en progreso', ['templateporting-status-unknown-desc'] = 'Estado desconocido' } }

--- -- Local functions (used inside this module) -- --- -- This creates an external link. function HF.ExternalLink( target, label, plain ) local output = string.format('[%s %s]', target, label) if plain == true then output = string.format(' %s ', output) end return output end

-- Adds an internal link -- `label` is optional function HF.Link( link, text ) if not HF.isempty( text ) then return string.format('%s'..'%s|%s]]', '[[', link, text) else return string.format('%s'..'%s]]', '[[', link) end end

local function makeButton ( label, args ) local button = mw.html.create( 'span' ) :addClass('wds-button'):addClass('wds-is-squished') if args.role == 'secondary' then button:addClass('wds-is-secondary') end if args.role == 'text' then button:addClass('wds-is-text') end if args.background then button:css('background', args.background) end if args.color then button:css('color', args.color):css('border-color', args.color) end if args.tooltip then button:attr('title', args.tooltip) end if args.width then button:css('width', args.width) end if args.min_width then button:css('min-width', args.min_width) end if args.max_width then button:css('max-width', args.max_width) end button:wikitext( label ):allDone return tostring( button ) end

local function message ( messagename ) assert( messagename, 'function «message» was called with no message key' ) if mw.message.new( messagename ):exists == true then return mw.message.new( messagename ):plain elseif messages[mw.getContentLanguage:getCode] then return messages[mw.getContentLanguage:getCode][messagename] or mw.message.new( messagename ):plain else return messages['en'][messagename] end end

local function button_template ( template ) local args = { ['role'] = 'text' } if template.exists == false then args['color'] = 'red' else args['color'] = 'black' end return HF.Link(			template.fullText,			makeButton( template.fullText, args)	) end

local function button_raw ( template ) return HF.ExternalLink(		template:fullUrl( 'action=raw' ),		makeButton( message('templateporting-label-raw'), {} )	) end

local function button_doc ( template ) return HF.Link(		template:subPageTitle('doc').fullText,		makeButton( message('templateporting-label-documentation'), template:subPageTitle('doc').exists and {} or { ['role'] = 'secondary' } )	) end

local function dptclist( entries ) local dptc_ul = mw.html.create('ul'):addClass('wds-list') for _,v in ipairs(entries) do		dptc_ul:tag('li'):wikitext(v):done end dptc_ul:allDone return dptc_ul end

local function button_dependencies ( dependencies ) if dependencies then local dp = mw.html.create('span') :addClass('wds-button'):addClass('wds-is-squished') :addClass('wds-dropdown') :attr('title', message('templateporting-label-dependencies')) :tag('span'):addClass('wds-dropdown__toggle') :wikitext('⌵') :done :tag('div'):addClass('wds-dropdown__content') :node( dptclist( dependencies ) ) :done :allDone return tostring(dp) else return nil end end

local function button_testcases ( template, test_cases ) local testcases_group = mw.html.create('div') :addClass('wds-button-group') :wikitext(			HF.Link( template:subPageTitle( 'testcases' ).fullText, makeButton(message('templateporting-label-testcases'), {}) )		)	if test_cases then testcases_group:tag('span') :addClass('wds-button'):addClass('wds-is-squished') :addClass('wds-dropdown') :tag('span'):addClass('wds-dropdown__toggle') :wikitext('⌵') :done :tag('div'):addClass('wds-dropdown__content') :node( dptclist( test_cases ) ) :done :done end testcases_group:allDone return tostring(testcases_group) end

local function button_draft ( draft ) if draft.exists then return HF.Link (			draft.fullText,			makeButton( message('insights-altaction-seedraft'), { ['min_width'] = '75px' } )		)	else return HF.ExternalLink (			draft:fullUrl( 'action=edit&conversion=1' ),			makeButton( message('insights-altaction-convert'), {					['role'] = 'secondary', ['min_width'] = '75px' }			)		)	end end

local function button_status ( status ) local status_canonical = status_messages[status] and status or assert( status_alias[status], '«'..status..'» is not a recognized status' ) assert(		status_messages[status_canonical],		'No message exists in «status_messages» for «'..status_canonical..'»'	) local button_color = status_colors[status_canonical] and mw.text.split( status_colors[status_canonical], ',%s?' )[1] local button_text_color = status_colors[status_canonical] and mw.text.split( status_colors[status_canonical], ',%s?' )[2] return makeButton(		message( status_messages[status_canonical] ),		{			['background'] = button_color,			['color'] = button_text_color,			['min_width'] = '75px',			['tooltip'] = message(status_messages[status_canonical]..'-desc')		}	) end

--- -- Public functions (used by templates and articles) -- --- function Porting.project_table (frame) local args = getArgs(frame) return Porting._project_table( args ) end

- -- Internal functions (used by this and other modules) -- - function Porting._project_table ( args ) -- local base_community = args.base_community -- local inexpensive = args.inexpensive local T = mw.html.create( 'table' ) :attr('border', '0'):attr('cellpadding', '1'):attr('cellspacing', '1') :addClass('article-table'):addClass('sortable'):css('width','100%') if args.collapsible then T:addClass('mw-collapsible') if args.collapsible == 'collapsed' or args.collapsible == 'closed' then T:addClass('mw-collapsed') end end if args.caption then T:tag('caption'):wikitext(args.caption):done end T:tag('tr') :tag('th'):wikitext(message('templateporting-label-template')):done :tag('th'):wikitext(message('templateporting-label-comparison')):done :tag('th'):css('width', '190px'):wikitext(message('templateporting-label-status')):done :done

for _,v in ipairs( args ) do			local template_name = assert(					v:match('^%s*([^%|]+)'),					message('templateporting-error-notemplate')				) template_name = mw.text.trim( template_name ) local template = mw.title.new( template_name, 10 ) local status = mw.ustring.match( v, '^%s*[^%|]+%|([%w%s]*)') or 'unknown' status = mw.text.trim( status ) local draft = template:subPageTitle( message('templatedraft-subpage') ) local dependencies = (					type(mw.text.split( v, '|')[3]) == 'string'					and #mw.text.split( v, '|')[3] > 2				) and mw.text.split(					mw.text.trim ( mw.text.split( v, '|')[3] ),					',%s'				) local test_cases = (					type(mw.text.split( v, '|')[4]) == 'string'					and #mw.text.split( v, '|')[4] > 2				) and mw.text.split(					mw.text.trim ( mw.text.split( v, '|')[4] ),					',%s'				)

T:tag('tr') :tag('td') :wikitext( button_template( template ) ) :tag('div'):addClass('wds-button-group'):css('float', 'right') :wikitext(button_dependencies (dependencies)) :wikitext(button_raw (template)) :wikitext(button_doc (template)) :done :done :tag('td') :wikitext( button_testcases( template, test_cases ) ) :done :tag('td') :tag('div'):addClass('wds-button-group') :wikitext( button_status(status) ) :wikitext( button_draft(draft) ) :done :done :done end T:allDone return tostring(T) end

-- Output --

return Porting