Module:Track listing: Difference between revisions

rm non-working code related to the collapsed parameter; deprecated parameter checking can be implemented in the template easily
m (1 revision imported)
(rm non-working code related to the collapsed parameter; deprecated parameter checking can be implemented in the template easily)
Line 1: Line 1:
-- This module implements [[Template:Track listing]]
local yesno = require('Module:Yesno')
local yesno = require('Module:Yesno')
local checkType = require('libraryUtil').checkType
local checkType = require('libraryUtil').checkType
 
local cfg = mw.loadData('Module:Track listing/configuration')
local SHOW_WARNINGS = false
local INPUT_ERROR_CATEGORY = 'Track listings with input errors'
local COLLAPSED_PARAMETER_CATEGORY = 'Track listings that use the collapsed parameter '


--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
Line 64: Line 59:
if hours and hours:sub(1, 1) == '0' then
if hours and hours:sub(1, 1) == '0' then
-- Disallow times like "0:12:34"
-- Disallow times like "0:12:34"
self:addWarning(string.format(
self:addWarning(
"Invalid time '%s' (times in format 'h:mm:ss' cannot start with zero)",
string.format(cfg.leading_0_in_hours, mw.text.nowiki(length)),
mw.text.nowiki(length)
cfg.input_error_category
), INPUT_ERROR_CATEGORY)
)
return nil
return nil
end
end
Line 77: Line 72:
-- Special case to disallow lengths like "01:23". This check has to
-- Special case to disallow lengths like "01:23". This check has to
-- be here so that lengths like "1:01:23" are still allowed.
-- be here so that lengths like "1:01:23" are still allowed.
self:addWarning(string.format(
self:addWarning(
"Invalid time '%s' (times in format 'mm:ss' cannot start with zero)",
string.format(cfg.leading_0_in_minutes, mw.text.nowiki(length)),
mw.text.nowiki(length)
cfg.input_error_category
), INPUT_ERROR_CATEGORY)
)
return nil
return nil
end
end
Line 87: Line 82:
-- Add a warning and return if we did not find a match.
-- Add a warning and return if we did not find a match.
if not seconds then
if not seconds then
self:addWarning(string.format(
self:addWarning(
"Invalid time '%s' (times must be in a format of 'm:ss', 'mm:ss' or 'h:mm:ss')",
string.format(cfg.not_a_time, mw.text.nowiki(length)),
mw.text.nowiki(length)
cfg.input_error_category
), INPUT_ERROR_CATEGORY)
)
return nil
return nil
end
end
Line 96: Line 91:
-- Check that the minutes are less than 60 if we have an hours field.
-- Check that the minutes are less than 60 if we have an hours field.
if hours and tonumber(minutes) >= 60 then
if hours and tonumber(minutes) >= 60 then
self:addWarning(string.format(
self:addWarning(
"Invalid track length '%s' (if hours are specified, the number of minutes must be less than 60)",
string.format(cfg.more_than_60_minutes, mw.text.nowiki(length)),
mw.text.nowiki(length)
cfg.input_error_category
), INPUT_ERROR_CATEGORY)
)
return nil
return nil
end
end
Line 105: Line 100:
-- Check that the seconds are less than 60
-- Check that the seconds are less than 60
if tonumber(seconds) >= 60 then
if tonumber(seconds) >= 60 then
self:addWarning(string.format(
self:addWarning(
"Invalid track length '%s' (number of seconds must be less than 60)",
string.format(cfg.more_than_60_seconds, mw.text.nowiki(length)),
mw.text.nowiki(length)
cfg.input_error_category
), INPUT_ERROR_CATEGORY)
)
end
end


Line 122: Line 117:
addMixin(Track, Validation)
addMixin(Track, Validation)


Track.fields = {
Track.fields = cfg.track_field_names
number = true,
title = true,
note = true,
length = true,
lyrics = true,
music = true,
writer = true,
extra = true,
}


Track.cellMethods = {
Track.cellMethods = {
Line 173: Line 159:
function Track.makeSimpleCell(wikitext)
function Track.makeSimpleCell(wikitext)
return mw.html.create('td')
return mw.html.create('td')
:css('vertical-align', 'top')
:wikitext(wikitext or cfg.blank_cell)
:wikitext(wikitext or ' ')
end
end


function Track:makeNumberCell()
function Track:makeNumberCell()
return mw.html.create('td')
return mw.html.create('th')
:css('padding-right', '10px')
:attr('id', string.format(cfg.track_id, self.number))
:css('text-align', 'right')
:attr('scope', 'row')
:css('vertical-align', 'top')
:wikitext(string.format(cfg.number_terminated, self.number))
:wikitext(self.number .. '.')
end
end


function Track:makeTitleCell()
function Track:makeTitleCell()
local titleCell = mw.html.create('td')
local titleCell = mw.html.create('td')
titleCell
titleCell:wikitext(
:css('vertical-align', 'top')
self.title and string.format(cfg.track_title, self.title) or cfg.untitled
:wikitext(self.title and string.format('"%s"', self.title) or 'Untitled')
)
if self.note then
if self.note then
titleCell
titleCell:wikitext(string.format(cfg.note, self.note))
:wikitext(' ')
:tag('span')
:wikitext(string.format('(%s)', self.note))
end
end
return titleCell
return titleCell
Line 217: Line 198:
function Track:makeLengthCell()
function Track:makeLengthCell()
return mw.html.create('td')
return mw.html.create('td')
:css('padding-right', '10px')
:addClass('tracklist-length')
:css('text-align', 'right')
:wikitext(self.length or cfg.blank_cell)
:css('vertical-align', 'top')
:wikitext(self.length or ' ')
end
end


function Track:exportRow(options)
function Track:exportRow(columns)
options = options or {}
local columns = columns or {}
local columns = options.columns or {}
local row = mw.html.create('tr')
local row = mw.html.create('tr')
row:css('background-color', options.color or '#fff')
for i, column in ipairs(columns) do
for i, column in ipairs(columns) do
local method = Track.cellMethods[column]
local method = Track.cellMethods[column]
Line 244: Line 221:
TrackListing.__index = TrackListing
TrackListing.__index = TrackListing
addMixin(TrackListing, Validation)
addMixin(TrackListing, Validation)
 
TrackListing.fields = cfg.track_listing_field_names
TrackListing.fields = {
TrackListing.deprecatedFields = cfg.deprecated_track_listing_field_names
headline = true,
all_writing = true,
all_lyrics = true,
all_music = true,
extra_column = true,
total_length = true,
title_width = true,
writing_width = true,
lyrics_width = true,
music_width = true,
extra_width = true,
category = true,
}
 
TrackListing.deprecatedFields = {
writing_credits = true,
lyrics_credits = true,
music_credits = true,
}


function TrackListing.new(data)
function TrackListing.new(data)
Line 273: Line 231:
for deprecatedField in pairs(TrackListing.deprecatedFields) do
for deprecatedField in pairs(TrackListing.deprecatedFields) do
if data[deprecatedField] then
if data[deprecatedField] then
self:addCategory('Track listings with deprecated parameters')
self:addCategory(cfg.deprecated_parameter_category)
break
break
end
end
Line 337: Line 295:
function TrackListing:makeIntro()
function TrackListing:makeIntro()
if self.all_writing then
if self.all_writing then
return string.format(
return string.format(cfg.tracks_written, self.all_writing)
'All tracks are written by %s.',
self.all_writing
)
elseif self.all_lyrics and self.all_music then
elseif self.all_lyrics and self.all_music then
return string.format(
return mw.message.newRawMessage(
'All lyrics are written by %s; all music is composed by %s.',
cfg.lyrics_written_music_composed,
self.all_lyrics,
self.all_lyrics,
self.all_music
self.all_music
)
):plain()
elseif self.all_lyrics then
elseif self.all_lyrics then
return string.format(
return string.format(cfg.lyrics_written, self.all_lyrics)
'All lyrics are written by %s.',
self.all_lyrics
)
elseif self.all_music then
elseif self.all_music then
return string.format(
return string.format(cfg.music_composed, self.all_music)
'All music is composed by %s.',
self.all_music
)
else
else
return ''
return nil
end
end
end
end
Line 387: Line 336:


function TrackListing:renderWarnings()
function TrackListing:renderWarnings()
if not SHOW_WARNINGS then
if not cfg.show_warnings then
return ''
return ''
end
end
Line 394: Line 343:


local function addWarning(msg)
local function addWarning(msg)
table.insert(ret, string.format(
table.insert(ret, string.format(cfg.track_listing_error, msg))
'<strong class="error">Track listing error: %s</strong>',
msg
))
end
end


Line 414: Line 360:


function TrackListing:__tostring()
function TrackListing:__tostring()
-- Root of the output
local root = mw.html.create('div')
:addClass('track-listing')
local intro = self:makeIntro()
if intro then
root:tag('p')
:wikitext(intro)
:done()
end
-- Start of track listing table
local tableRoot = mw.html.create('table')
tableRoot
:addClass('tracklist')
-- Header row
if self.headline then
tableRoot:tag('caption')
:wikitext(self.headline or cfg.track_listing)
end
-- Headers
local headerRow = tableRoot:tag('tr')
---- Track number
headerRow
:tag('th')
:addClass('tracklist-number-header')
:attr('scope', 'col')
:tag('abbr')
:attr('title', cfg.number)
:wikitext(cfg.number_abbr)
-- Find columns to output
-- Find columns to output
local columns = {'number', 'title'}
local columns = {'number', 'title'}
Line 430: Line 410:
end
end
columns[#columns + 1] = 'length'
columns[#columns + 1] = 'length'
 
-- Find colspan and column width
-- Find column width
local nColumns = #columns
local nColumns = #columns
local nOptionalColumns = nColumns - 3
local nOptionalColumns = nColumns - 3
local titleColumnWidth
local titleColumnWidth = 100
if nColumns >= 5 then
if nColumns >= 5 then
titleColumnWidth = 40
titleColumnWidth = 40
elseif nColumns >= 4 then
elseif nColumns >= 4 then
titleColumnWidth = 60
titleColumnWidth = 60
else
titleColumnWidth = 100
end
end
local optionalColumnWidth = (100 - titleColumnWidth) / nOptionalColumns
local optionalColumnWidth = ((100 - titleColumnWidth) / nOptionalColumns) .. '%'
titleColumnWidth = titleColumnWidth .. '%'
titleColumnWidth = titleColumnWidth .. '%'
optionalColumnWidth = optionalColumnWidth .. '%'
-- Root of the output
local root = mw.html.create()
-- Intro
root:node(self:makeIntro())
-- Start of track listing table
local tableRoot = root:tag('table')
tableRoot
:addClass('tracklist')
:css('display', 'block')
:css('border-spacing', '0px')
-- Header row
if self.headline then
tableRoot:tag('caption')
:addClass('tlheader mbox-text')
:attr('colspan', nColumns)
:css('text-align', 'left')
:css('background-color', '#fff')
:css('font-weight', '700')
:wikitext(self.headline or 'Track listing')
end
-- Deprecated collapsed parameter
---- Title column
if self.collapsed then
self:addWarning("Deprecated collapsed parameter in use", COLLAPSED_PARAMETER_CATEGORY);
end
 
-- Headers
local headerRow = tableRoot:tag('tr')
 
---- Track number
headerRow
:tag('th')
:addClass('tlheader')
:attr('scope', 'col')
:css('width', '2em')
:css('padding-left', '10px')
:css('padding-right', '10px')
:css('text-align', 'right')
:css('background-color', '#eee')
:tag('abbr')
:attr('title', 'Number')
:wikitext('No.')
 
---- Title
headerRow:tag('th')
headerRow:tag('th')
:addClass('tlheader')
:attr('scope', 'col')
:attr('scope', 'col')
:css('width', self.title_width or titleColumnWidth)
:css('width', self.title_width or titleColumnWidth)
:css('text-align', 'left')
:wikitext(cfg.title)
:css('background-color', '#eee')
:wikitext('Title')


---- Optional headers: writer, lyrics, music, and extra
---- Optional headers: writer, lyrics, music, and extra
Line 505: Line 435:
if self.optionalColumns[field] then
if self.optionalColumns[field] then
headerRow:tag('th')
headerRow:tag('th')
:addClass('tlheader')
:attr('scope', 'col')
:attr('scope', 'col')
:css('width', width or optionalColumnWidth)
:css('width', width or optionalColumnWidth)
:css('text-align', 'left')
:css('background-color', '#eee')
:wikitext(headerText)
:wikitext(headerText)
end
end
end
end
addOptionalHeader('writer', 'Writer(s)', self.writing_width)
addOptionalHeader('writer', cfg.writer, self.writing_width)
addOptionalHeader('lyrics', 'Lyrics', self.lyrics_width)
addOptionalHeader('lyrics', cfg.lyrics, self.lyrics_width)
addOptionalHeader('music', 'Music', self.music_width)
addOptionalHeader('music', cfg.music, self.music_width)
addOptionalHeader(
addOptionalHeader(
'extra',
'extra',
self.extra_column or '{{{extra_column}}}',
self.extra_column or cfg.extra,
self.extra_width
self.extra_width
)
)
Line 524: Line 451:
---- Track length
---- Track length
headerRow:tag('th')
headerRow:tag('th')
:addClass('tlheader')
:addClass('tracklist-length-header')
:attr('scope', 'col')
:attr('scope', 'col')
:css('width', '4em')
:wikitext(cfg.length)
:css('padding-right', '10px')
:css('text-align', 'right')
:css('background-color', '#eee')
:wikitext('Length')


-- Tracks
-- Tracks
for i, track in ipairs(self.tracks) do
for i, track in ipairs(self.tracks) do
tableRoot:node(track:exportRow({
tableRoot:node(track:exportRow(columns))
columns = columns,
color = i % 2 == 0 and '#f7f7f7' or '#fff'
}))
end
end


Line 544: Line 464:
tableRoot
tableRoot
:tag('tr')
:tag('tr')
:tag('td')
:addClass('tracklist-total-length')
:tag('th')
:attr('colspan', nColumns - 1)
:attr('colspan', nColumns - 1)
:css('padding', 0)
:attr('scope', 'row')
:tag('span')
:tag('span')
:css('width', '7.5em')
:wikitext(cfg.total_length)
:css('float', 'right')
:css('padding-left', '10px')
:css('background-color', '#eee')
:css('margin-right', '2px')
:wikitext("'''Total length:'''")
:done()
:done()
:done()
:done()
:tag('td')
:tag('td')
:css('padding', '0 10px 0 0')
:wikitext(self.total_length)
:css('text-align', 'right')
:css('background-color', '#eee')
:wikitext(string.format("'''%s'''", self.total_length))
end
end
root:node(tableRoot)
-- Warnings and tracking categories
-- Warnings and tracking categories
root:wikitext(self:renderWarnings())
root:wikitext(self:renderWarnings())
root:wikitext(self:renderTrackingCategories())
root:wikitext(self:renderTrackingCategories())
 
return tostring(root)
return mw.getCurrentFrame():extensionTag{
name = 'templatestyles', args = { src = 'Module:Track listing/styles.css' }
} .. tostring(root)
end
end


Anonymous user