Ir para o conteúdo

Módulo:Tabela de episódios

Permanently protected module
Origem: Wikipédia, a enciclopédia livre.

-- Este módulo implementa {{Tabela de episódios}} e {{Tabela de episódios/parte}}.

local HTMLcolor = mw.loadData( 'Módulo:Color contrast/colors' )

--------------------------------------------------------------------------------
-- EpisodeTable class
-- The main class.
--------------------------------------------------------------------------------

local contrast_ratio = require('Módulo:Color contrast')._ratio
local EpisodeTable = {}

function EpisodeTable.cell(background, width, text, reference, textColor)
	local cell = mw.html.create('th')
	
	-- Width
	local cell_width
	if width == 'auto' then
		cell_width = 'auto'
	elseif tonumber(width) ~= nil then
		cell_width = width .. '%'
	else
		cell_width = nil
	end
	
	-- Cell
	cell:attr('scope','col')
		:css('background',background or '#CCCCFF')
		:css('width',cell_width)
		:css('color',textColor)
		:wikitext(text)
	
	-- Reference
	if reference and reference ~= '' then
		cell:wikitext(" " .. EpisodeTable.reference(reference, background))
	end
	
	return cell
end

function EpisodeTable.reference(reference, background)
	local link1_cr = contrast_ratio{'#0645AD', background or '#CCCCFF', ['error'] = 0}
	local link2_cr = contrast_ratio{'#0B0080', background or '#CCCCFF', ['error'] = 0}
	
	local refspan = mw.html.create('span')
		:wikitext(reference)
	
	if link1_cr < 7 or link2_cr < 7 then
		refspan
			:css('color','black')
			:css('background-color','white')
			:css('padding','1px')
			:css('display','inline-block')
			:css('line-height','50%')
	end
	
	return tostring(refspan)
end

function EpisodeTable.abbr(text,title)
	local abbr = mw.html.create('abbr')
		:attr('title',title)
		:wikitext(text)
	return tostring(abbr)
end

function EpisodeTable.part(frame, args)
    local row = mw.html.create('tr')
    
    -- Handle color contrast (kept from old version)
    args.c = args.c or '#CCCCFF'  -- Default color if not specified
    local black_cr = contrast_ratio{args.c, 'black', ['error'] = 0}
    local white_cr = contrast_ratio{'white', args.c, ['error'] = 0}
    
    -- New part type handling with fallback to old version
    local displaytext = ''
    local foundPart = false
    
    -- First try new partTypes system
    local partTypes = {
        {params = {'act', 'ato', 'acto'}, displays = {act = 'Ato', ato = 'Ato', acto = 'Acto'}},
        {params = {'chapter', 'capítulo'}, display = 'Capítulo'},
        {params = {'part', 'parte'}, display = 'Parte'},
        {params = {'volume'}, display = 'Volume'},
        {params = {'week', 'semana'}, display = 'Semana'}
    }
    
    for _, partType in ipairs(partTypes) do
        for _, param in ipairs(partType.params) do
            if args[param] then
                foundPart = true
                local display = partType.display or (partType.displays and partType.displays[param]) or 'Parte'
                displaytext = display .. ' ' .. args[param]
                break
            end
        end
        if foundPart then break end
    end
    
    -- Fallback to old version if no new-style part was found
    if not foundPart and args.p then
        displaytext = (not args.nopart and 'Parte ' or '') .. args.p
    end
    
    -- Add subtitle if exists
    local subtitleText = args.subtitle or args['subtítulo']
    if subtitleText then
        if displaytext ~= '' then
            displaytext = displaytext .. ': ' .. subtitleText
        else
            displaytext = subtitleText
        end
    end
    
    -- Handle anchor/visible template (compatible with both versions)
    local plainText = require('Módulo:Texto simples')._main
    local displayTextAnchor = plainText(displaytext)
    
    row:tag('td')
        :attr('colspan', 13)
        :attr('id', args.id or displayTextAnchor)
        :css('text-align', 'center')
        :css('background-color', args.c)
        :css('color', black_cr > white_cr and 'black' or 'white')
        :wikitext((args.nobold or args.sem_negrito and displaytext or "'''" .. displaytext .. "'''") .. 
                 (args.r and "&#8202;" .. EpisodeTable.reference(args.r, args.c) or ''))
    
    return tostring(row)
end

function EpisodeTable.new(frame,args)
	args = args or {}
	local categories = ''
	local background = ((args.background and args.background ~= '' and args.background ~= '#') or (args['cor_fundo'] and args['cor_fundo'] ~= '' and args['cor_fundo'] ~= '#')) and (args.background or args['cor_fundo']) or nil
	
	-- Add # to background if necessary
	if background ~= nil and HTMLcolor[background] == nil then
		background = '#'..(mw.ustring.match(background, '^[%s#]*([a-fA-F0-9]*)[%s]*$') or '')
	end
	
	-- Default widths noted by local consensus
	local defaultwidths = {};
	defaultwidths.overall = 5;
	defaultwidths.overall2 = 5;
	defaultwidths.season = 5;
	defaultwidths.series = 5;
	defaultwidths.prodcode = 7;
	defaultwidths.viewers = 10;
	
	-- Create episode table
	local root = mw.html.create('table')
	
	-- Table width
	local table_width = string.gsub(args.total_width or args['largura_total'] or '','%%','')
	if args.total_width == 'auto' or args['largura_total'] == 'auto' or args.total_width == '' or args['largura_total'] == '' then
		table_width = 'auto'
	elseif tonumber(table_width) ~= nil then
		table_width = table_width .. '%'
	else
		table_width = '100%'
	end
	
	root
		:addClass('wikitable')
		:addClass('plainrowheaders')
		:addClass('wikiepisodetable')
		:css('width', table_width)
	
	-- Caption
	if args.show_caption or args.mostrar_legenda then
		-- Visible caption option, with a tracking category
		root:tag('caption'):wikitext(args.caption or args['legenda'])
		categories = categories .. '[[Categoria:!Artigos usando Predefinição:Tabela de episódios com legenda visível]]'
	elseif args.caption or args['legenda'] then
		-- If a visible caption isn't defined, then default to the screenreader-only caption
		root:tag('caption'):wikitext(frame:expandTemplate{title='Sronly',args={args.caption or args['legenda']}})
	end
	
	-- Colour contrast; add to category only if it's in the mainspace
	local title = mw.title.getCurrentTitle()
	local black_cr = contrast_ratio{background, 'black', ['error'] = 0}
	local white_cr = contrast_ratio{'white', background, ['error'] = 0}

	if title.namespace == 0 and ((args.background and args.background ~= '' and args.background ~= '#') or (args['cor_fundo'] and args['cor_fundo'] ~= '' and args['cor_fundo'] ~= '#')) and black_cr < 7 and white_cr < 7 then
		categories = categories .. '[[Categoria:!Artigos usando Predefinição:Tabela de episódios com combinações de cores inválidas]]'
	end
	
	-- Main row
	local textColor = background and (black_cr > white_cr and 'black' or 'white') or 'black'
	local mainRow = root:tag('tr')
	mainRow
		:css('color', textColor)
		:css('text-align', 'center')
	
	-- Cells
	do
		local used_season = false
		local country = (args.country or args['país']) ~= '' and (args.country or args['país']) ~= nil
		local viewers = (country and 'A' or 'A') .. 'udiência' .. ' ' .. (country and (args.country or args['país']) or '') ..
			((not args.viewers_type or not args['audiência_tipo'] or args.viewers_type ~= '' or args['audiência_tipo'] ~= '') and '<br />(' .. (args.viewers_type or args['audiência_tipo'] or 'milhões') .. ')' or '')
		
	local cellNames = {
    {'overall', 'geral', 'EpisodeNumber', 'NúmeroEpisódio', EpisodeTable.abbr('N.º','Número') ..
        ((args.season or args['temporada'] or args.series or args['série'] or args.EpisodeNumber2 or args['NúmeroEpisódio2'] or args.EpisodeNumber2Series or args['NúmeroEpisódio2Série'] or args.forceoverall or args['forçar_geral']) and '<br />' ..(args.overall_type or args.geral_tipo or 'geral') or '')
    },
    {'overall2', 'geral2', '*', ''},
    {'season', 'temporada', 'EpisodeNumber2', 'NúmeroEpisódio2', EpisodeTable.abbr('N.º','Número') .. ' na<br />' .. (args['temporada_tipo'] or EpisodeTable.abbr('temp.', 'temporada'))},
	{'series', 'série', 'EpisodeNumber2Series', 'NúmeroEpisódio2Série', EpisodeTable.abbr('N.º','Número') .. ' na<br />' .. (args['série_tipo'] or EpisodeTable.abbr('temp.', 'temporada'))},
    {'title', 'título', 'Title', 'Título', 'Título'},
    {'aux1', 'Aux1', ''},
    {'director', 'diretor', 'DirectedBy', 'Dirigido', 'Dirigido por'},
    {'writer', 'escritor', 'WrittenBy', 'Escrito','Escrito por'},
    {'aux2', 'Aux2', ''},
    {'aux3', 'Aux3', ''},
    {'airdate', 'data_exibição', 'OriginalAirDate', 'DataTransmissãoOriginal', (args.released ~= nil and args.released ~= '' or args['lançamento'] ~= nil and args['lançamento'] ~= '') and 'Lançamento' or 'Exibição original'},
    {'altdate', 'data_alter', 'AltDate', 'DataAlter', ''},
    {'guests', 'convidados', 'Guests', 'Convidados', 'Convidado(s)'},
    {'musicalguests', 'convidados_musicais', 'MusicalGuests', 'ConvidadosMusicais', 'Convidado(s) musicais'},
    {'prodcode', 'códprod', 'ProdCode', 'CódigoProd', EpisodeTable.abbr('Cód.','Código') .. ' de<br />produção'},
    {'viewers', 'audiência', 'Audiência', 'Viewers',viewers},
    {'aux4', 'Aux4', ''}
	}
	
		for k,v in pairs(cellNames) do
			local thisCell = args[v[1]] or args[v[2]] or args[v[3]]
			if thisCell and (v[1] ~= 'series' or (v[1] == 'series' and used_season == false)) then
				if v[1] == 'season' then used_season = true end
				if (k <= 3 and thisCell == '') then thisCell = '5' end
				if (thisCell == '' and defaultwidths[v[1]]) then thisCell = defaultwidths[v[1]] end

				local thisCellT = args[v[1] .. 'T'] or args[v[2] .. 'T'] or args[v[3] .. 'T']
				local thisCellR = args[v[1] .. 'R'] or args[v[2] .. 'R'] or args[v[3] .. 'R']
				mainRow:node(EpisodeTable.cell(background, thisCell, thisCellT or v[5], thisCellR, textColor))
		end
end
	
		-- Episodes
		if args.episodes or args['episódios'] then
			if args.anchor or args['âncora'] then 
				local anchor = args.anchor or args['âncora']
				args.episodes = args.episodes or args['episódios']
				args.episodes = string.gsub(args.episodes, "(id=\")(ep%w+\")", "%1" .. anchor .. "%2")
			end
			
			root:node(args.episodes or args['episódios'])
		end
	end
	

    local templateStyles = mw.getCurrentFrame():extensionTag{
		name = 'templatestyles', args = { src = 'Módulo:Tabela de episódios/styles.css' }
	}
	return (((args.dontclose or args['não_fechar'] or '') ~= '') and mw.ustring.gsub(tostring(root), "</table>", "") or tostring(root)) .. categories .. templateStyles
end

--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------

local p = {}

function p.main(frame)
	local args = require('Módulo:Arguments').getArgs(frame, {
		removeBlanks = false,
		wrappers = 'Predefinição:Tabela de episódios'
	})
	local check = require('Módulo:Check for unknown parameters')._check
	local tracking = ''
	local title = mw.title.getCurrentTitle()
	if title.namespace == 0 then
		tracking = check({
			['unknown']='[[Categoria:!Páginas usando tabela de episódios com parâmetros desconhecidos|_VALUE_'..title.text..']]',
			['preview']='Página usando [[Predefinição:Tabela de episódios]] com o parâmetro desconhecido "_VALUE_"',
			['showblankpositional']='y',
			['regexp1']='[%w_]+NULL',
			'airdate', 'airdateR', 'airdateT', 'altdate', 'AltDate', 'altdateR', 'AltDateR',
			'altdateT', 'AltDateT', 'anchor', 'aux1', 'Aux1', 'aux1R', 'Aux1R', 'aux1T',
			'Aux1T', 'aux2', 'Aux2', 'aux2R', 'Aux2R', 'aux2T', 'Aux2T', 'aux3', 'Aux3',
			'aux3R', 'Aux3R', 'aux3T', 'Aux3T', 'aux4', 'Aux4', 'aux4R', 'Aux4R', 'aux4T',
			'Aux4T', 'b', 'background', 'c', 'caption', 'country', 'DirectedBy', 'DirectedByR',
			'DirectedByT', 'director', 'directorR', 'directorT', 'dontclose', 'EpisodeNumber',
			'EpisodeNumber2', 'EpisodeNumber2R', 'EpisodeNumber2Series', 'EpisodeNumber2SeriesR',
			'EpisodeNumber2SeriesT', 'EpisodeNumber2T', 'EpisodeNumberR', 'EpisodeNumberT',
			'episodes', 'forceoverall', 'guests', 'Guests', 'guestsR', 'GuestsR', 'guestsT',
			'GuestsT', 'id', 'musicalguests', 'MusicalGuests', 'musicalguestsR', 'MusicalGuestsR',
			'musicalguestsT', 'MusicalGuestsT', 'OriginalAirDate', 'OriginalAirDateR',
			'OriginalAirDateT', 'overall', 'overall_type', 'overall2', 'overall2R',
			'overall2T', 'overallR', 'overallT', 'prodcode', 'ProdCode', 'prodcodeR',
			'ProdCodeR', 'prodcodeT', 'ProdCodeT', 'r', 'released', 'season', 'season_type', 'seasonR',
			'seasonT', 'series', 'series_type', 'seriesR', 'seriesT', 'show_caption',
			'subtitle', 'title', 'Title', 'titleR', 'TitleR', 'titleT', 'TitleT', 'total_width',
			'viewers', 'Viewers', 'viewers_type', 'viewersR', 'ViewersR', 'viewersT',
			'ViewersT', 'writer', 'writerR', 'writerT', 'WrittenBy', 'WrittenByR', 'WrittenByT',
			'âncora', 'audiência', 'Audiência', 'audiênciaR', 'AudiênciaR', 'audiênciaT',
			'AudiênciaT', 'audiência_tipo', 'convidados', 'Convidados', 'convidadosR', 'ConvidadosR',
			'convidadosT', 'ConvidadosT', 'convidados_musicais', 'ConvidadosMusicais',
			'convidados_musicaisR', 'ConvidadosMusicaisR', 'convidados_musicaisT', 'ConvidadosMusicaisT',
			'cor_fundo', 'códprod', 'CódigoProd', 'códprodR', 'CódigoProdR', 'códprodT',
			'CódigoProdT', 'DataTransmissãoOriginal', 'DataTransmissãoOriginalR', 'DataTransmissãoOriginalT',
			'data_alter', 'data_alterR', 'data_alterT', 'data_exibição', 'data_exibiçãoR',
			'data_exibiçãoT', 'diretor', 'diretorR', 'diretorT', 'Dirigido', 'DirigidoR',
			'DirigidoT', 'episódios', 'escritor', 'escritorR', 'escritorT', 'Escrito',
			'EscritoR', 'EscritoT', 'forçar_geral', 'geral', 'geralR', 'geralT', 'geral_tipo',
			'geral2', 'geral2R', 'geral2T', 'lançamento', 'largura_total', 'legenda', 'mostrar_legenda',
			'não_fechar', 'NúmeroEpisódio', 'NúmeroEpisódio2', 'NúmeroEpisódio2Série', 'NúmeroEpisódioR',
			'NúmeroEpisódio2R', 'NúmeroEpisódio2SérieR', 'NúmeroEpisódioT', 'NúmeroEpisódio2T',
			'NúmeroEpisódio2SérieT','país', 'série', 'sérieR', 'sérieT', 'série_tipo', 'temporada', 'temporadaR',
			'temporada_tipo', 'subtítulo', 'título', 'Título', 'títuloR', 'TítuloR', 'títuloT', 'TítuloT'
		}, args)
	end
	return EpisodeTable.new(frame,args) .. tracking
end

function p.part(frame)
	local args = require('Módulo:Arguments').getArgs(frame, {
		removeBlanks = false,
		wrappers = 'Predefinição:Tabela de episódios/parte'
	})
	return EpisodeTable.part(frame,args)
end

function p.ref(frame)
	local args = require('Módulo:Arguments').getArgs(frame, {
		removeBlanks = false,
	})
	return EpisodeTable.reference(args.r,args.b)
end

return p