Redigerer
Modul:Sporliste
Hopp til navigering
Hopp til søk
Advarsel:
Du er ikke innlogget. IP-adressen din vil bli vist offentlig om du redigerer. Hvis du
logger inn
eller
oppretter en konto
vil redigeringene dine tilskrives brukernavnet ditt, og du vil få flere andre fordeler.
Antispamsjekk.
Ikke
fyll inn dette feltet!
-- This module implements [[Mal:Sporliste]] local yesno = require('Modul:Yesno') local checkType = require('libraryUtil').checkType local SHOW_WARNINGS = false local INPUT_ERROR_CATEGORY = 'Sporliste med input feil' -------------------------------------------------------------------------------- -- Helper functions -------------------------------------------------------------------------------- -- Add a mixin to a class. local function addMixin(class, mixin) for k, v in pairs(mixin) do if k ~= 'init' then class[k] = v end end end -------------------------------------------------------------------------------- -- Validation mixin -------------------------------------------------------------------------------- local Validation = {} function Validation.init(self) self.warnings = {} self.categories = {} end function Validation:addWarning(msg, category) table.insert(self.warnings, msg) table.insert(self.categories, category) end function Validation:addCategory(category) table.insert(self.categories, category) end function Validation:getWarnings() return self.warnings end function Validation:getCategories() return self.categories end -- Validate a track length. If a track length is invalid, a warning is added. -- A type error is raised if the length is not of type string or nil. function Validation:validateLengde(lengde) checkType('validateLength', 1, lengde, 'string', true) if lengde == nil then -- Do nothing if no length specified return nil end local hours, minutes, seconds -- Try to match times like "1:23:45". hours, minutes, seconds = lengde:match('^(%d+):(%d%d):(%d%d)$') if hours and hours:sub(1, 1) == '0' then -- Disallow times like "0:12:34" self:addWarning(string.format( "Ugyldig tid '%s' (tid-er i format 't:mm:ss' kan ikke starte med et null)", mw.text.nowiki(lengde) ), INPUT_ERROR_CATEGORY) return nil end if not seconds then -- The previous attempt didn't match. Try to match times like "1:23". minutes, seconds = lengde:match('^(%d?%d):(%d%d)$') if minutes and minutes:find('^0%d$') then -- Special case to disallow lengths like "01:23". This check has to -- be here so that lengths like "1:01:23" are still allowed. self:addWarning(string.format( "Ugyldig tid '%s' (tid-er i format 'mm:ss' kan ikke starte med et null)", mw.text.nowiki(lengde) ), INPUT_ERROR_CATEGORY) return nil end end -- Add a warning and return if we did not find a match. if not seconds then self:addWarning(string.format( "Ugyldig tid '%s' (tid-er må være i et av følgende format 'm:ss', 'mm:ss' eller 't:mm:ss')", mw.text.nowiki(lengde) ), INPUT_ERROR_CATEGORY) return nil end -- Check that the minutes are less than 60 if we have an hours field. if hours and tonumber(minutes) >= 60 then self:addWarning(string.format( "Ugyldig sporlengde '%s' (hvis timer er spesifisert, må antall minutter være mindre enn 60)", mw.text.nowiki(lengde) ), INPUT_ERROR_CATEGORY) return nil end -- Check that the seconds are less than 60 if tonumber(seconds) >= 60 then self:addWarning(string.format( "Ugyldig sporlengde '%s' (antall sekunder må være mindre enn 60)", mw.text.nowiki(lengde) ), INPUT_ERROR_CATEGORY) end return nil end -------------------------------------------------------------------------------- -- Track class -------------------------------------------------------------------------------- local Track = {} Track.__index = Track addMixin(Track, Validation) Track.fields = { nummer = true, tittel = true, notat = true, lengde = true, sangtekst = true, musikk = true, tekst = true, ekstra = true, } Track.cellMethods = { nummer = 'makeNummerCell', tittel = 'makeTittelCell', tekst = 'makeTekstCell', sangtekst = 'makeSangtekstCell', musikk = 'makeMusikkCell', ekstra = 'makeEkstraCell', lengde = 'makeLengdeCell', } function Track.new(data) local self = setmetatable({}, Track) Validation.init(self) for field in pairs(Track.fields) do self[field] = data[field] end self.nummer = assert(tonumber(self.nummer)) self:validateLengde(self.lengde) return self end function Track:getSangtekstCredit() return self.sangtekst end function Track:getMusikkCredit() return self.musikk end function Track:getTekstCredit() return self.tekst end function Track:getEkstraField() return self.ekstra end -- Note: called with single dot syntax function Track.makeSimpleCell(wikitext) return mw.html.create('td') :css('vertical-align', 'top') :wikitext(wikitext or ' ') end function Track:makeNummerCell() return mw.html.create('td') :css('padding-right', '10px') :css('text-align', 'right') :css('vertical-align', 'top') :wikitext(self.nummer .. '.') end function Track:makeTittelCell() local tittelCell = mw.html.create('td') tittelCell :css('vertical-align', 'top') :wikitext(self.tittel and string.format('«%s»', self.tittel) or 'Uten navn') if self.notat then tittelCell :wikitext(' ') :tag('span') :css('font-size', '85%') :wikitext(string.format('(%s)', self.notat)) end return tittelCell end function Track:makeTekstCell() return Track.makeSimpleCell(self.tekst) end function Track:makeSangtekstCell() return Track.makeSimpleCell(self.sangtekst) end function Track:makeMusikkCell() return Track.makeSimpleCell(self.musikk) end function Track:makeEkstraCell() return Track.makeSimpleCell(self.ekstra) end function Track:makeLengdeCell() return mw.html.create('td') :css('padding-right', '10px') :css('text-align', 'right') :css('vertical-align', 'top') :wikitext(self.lengde or ' ') end function Track:exportRow(options) options = options or {} local columns = options.columns or {} local row = mw.html.create('tr') row:css('background-color', options.color or '#fff') for i, column in ipairs(columns) do local method = Track.cellMethods[column] if method then row:node(self[method](self)) end end return row end -------------------------------------------------------------------------------- -- TrackListing class -------------------------------------------------------------------------------- local TrackListing = {} TrackListing.__index = TrackListing addMixin(TrackListing, Validation) TrackListing.fields = { alt_tekst = true, alt_sangtekst = true, alt_musikk = true, kollapset = true, overskrift = true, ekstra_kolonne = true, total_lengde = true, tittel_bredde = true, skriving_bredde = true, sangtekst_bredde = true, musikk_bredde = true, ekstra_bredde = true, category = true, } TrackListing.deprecatedFields = { skriving_kreditt = true, sangtekst_kreditt = true, musikk_kreditt = true, } function TrackListing.new(data) local self = setmetatable({}, TrackListing) Validation.init(self) -- Check for deprecated arguments for deprecatedField in pairs(TrackListing.deprecatedFields) do if data[deprecatedField] then self:addCategory('Sporliste med utdaterte parametere') break end end -- Validate total length if data.total_lengde then self:validateLengde(data.total_lengde) end -- Add properties for field in pairs(TrackListing.fields) do self[field] = data[field] end -- Evaluate boolean properties self.kollapset = yesno(self.kollapset, false) self.showCategories = yesno(self.category) ~= false self.category = nil -- Make track objects self.tracks = {} for i, trackData in ipairs(data.tracks or {}) do table.insert(self.tracks, Track.new(trackData)) end -- Find which of the optional columns we have. -- We could just check every column for every track object, but that would -- be no fun^H^H^H^H^H^H inefficient, so we use four different strategies -- to try and check only as many columns and track objects as necessary. do local optionalColumns = {} local columnMethods = { sangtekst = 'getSangtekstCredit', musikk = 'getMusikkCredit', tekst = 'getTekstCredit', ekstra = 'getEkstraField', } local doneTekstCheck = false for i, trackObj in ipairs(self.tracks) do for column, method in pairs(columnMethods) do if trackObj[method](trackObj) then optionalColumns[column] = true columnMethods[column] = nil end end if not doneTekstCheck and optionalColumns.tekst then doneTekstCheck = true optionalColumns.sangtekst = nil optionalColumns.musikk = nil columnMethods.sangtekst = nil columnMethods.musikk = nil end if not next(columnMethods) then break end end self.optionalColumns = optionalColumns end return self end function TrackListing:makeIntro() if self.alt_tekst then return string.format( 'Alle sporene er skrevet av %s.', self.alt_tekst ) elseif self.alt_sangtekst and self.alt_musikk then return string.format( 'Alle tekstene er skrevet av %s; all musikk er komponert av %s.', self.alt_sangtekst, self.alt_musikk ) elseif self.alt_sangtekst then return string.format( 'Alle tekstene er skrevet av %s.', self.alt_sangtekst ) elseif self.alt_musikk then return string.format( 'All musikk er komponert av %s.', self.alt_musikk ) else return '' end end function TrackListing:renderTrackingCategories() if not self.showCategories or mw.title.getCurrentTitle().namespace ~= 0 then return '' end local ret = '' local function addCategory(cat) ret = ret .. string.format('[[Category:%s]]', cat) end for i, category in ipairs(self:getCategories()) do addCategory(category) end for i, track in ipairs(self.tracks) do for j, category in ipairs(track:getCategories()) do addCategory(category) end end return ret end function TrackListing:renderWarnings() if not SHOW_WARNINGS then return '' end local ret = {} local function addWarning(msg) table.insert(ret, string.format( '<strong class="error">Sporliste feil: %s</strong>', msg )) end for i, warning in ipairs(self:getWarnings()) do addWarning(warning) end for i, track in ipairs(self.tracks) do for j, warning in ipairs(track:getWarnings()) do addWarning(warning) end end return table.concat(ret, '<br>') end function TrackListing:__tostring() -- Find columns to output local columns = {'nummer', 'tittel'} if self.optionalColumns.tekst then columns[#columns + 1] = 'tekst' else if self.optionalColumns.sangtekst then columns[#columns + 1] = 'sangtekst' end if self.optionalColumns.musikk then columns[#columns + 1] = 'musikk' end end if self.optionalColumns.ekstra then columns[#columns + 1] = 'ekstra' end columns[#columns + 1] = 'lengde' -- Find colspan and column width local nColumns = #columns local nOptionalColumns = nColumns - 3 local tittelColumnWidth if nColumns >= 5 then tittelColumnWidth = 40 elseif nColumns >= 4 then tittelColumnWidth = 60 else tittelColumnWidth = 100 end local optionalColumnWidth = (100 - tittelColumnWidth) / nOptionalColumns tittelColumnWidth = tittelColumnWidth .. '%' 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') :addClass(self.kollapset and 'collapsible kollapset' or nil) :css('display', 'block') :css('border-spacing', '0px') :css('border-collapse', 'collapse') :css('border', self.kollapset and '#aaa 1px solid' or nil) :css('padding', self.kollapset and '3px' or '4px') -- Header row if self.overskrift or self.kollapset then tableRoot:tag('tr'):tag('th') :addClass('tlheader mbox-text') :attr('colspan', nColumns) :css('text-align', 'left') :css('background-color', '#fff') :wikitext(self.overskrift or 'Sporliste') end -- Headers local headerRow = tableRoot:tag('tr') ---- Track nummer 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', 'Nummer') :wikitext('Nr.') ---- Tittel headerRow:tag('th') :addClass('tlheader') :attr('scope', 'col') :css('width', self.tittel_bredde or tittelColumnWidth) :css('text-align', 'left') :css('background-color', '#eee') :wikitext('Tittel') ---- Optional headers: writer, lyrics, music, and extra local function addOptionalHeader(field, headerText, width) if self.optionalColumns[field] then headerRow:tag('th') :addClass('tlheader') :attr('scope', 'col') :css('width', width or optionalColumnWidth) :css('text-align', 'left') :css('background-color', '#eee') :wikitext(headerText) end end addOptionalHeader('tekst', 'Låtskriver(e)', self.skriving_bredde) addOptionalHeader('sangtekst', 'Sangtekst', self.sangtekst_bredde) addOptionalHeader('musikk', 'Musikk', self.musikk_bredde) addOptionalHeader( 'ekstra', self.ekstra_kolonne or '{{{ekstra_kolonne}}}', self.ekstra_bredde ) ---- Track length headerRow:tag('th') :addClass('tlheader') :attr('scope', 'col') :css('width', '4em') :css('padding-right', '10px') :css('text-align', 'right') :css('background-color', '#eee') :wikitext('Lengde') -- Tracks for i, track in ipairs(self.tracks) do tableRoot:node(track:exportRow({ columns = columns, color = i % 2 == 0 and '#f7f7f7' or '#fff' })) end -- Total length if self.total_lengde then tableRoot :tag('tr') :tag('td') :attr('colspan', nColumns - 1) :css('padding', 0) :tag('span') :css('width', '7.5em') :css('float', 'right') :css('padding-left', '10px') :css('background-color', '#eee') :css('margin-right', '2px') :wikitext("'''Total lengde:'''") :done() :done() :tag('td') :css('padding', '0 10px 0 0') :css('text-align', 'right') :css('background-color', '#eee') :wikitext(string.format("'''%s'''", self.total_lengde)) end -- Warnings and tracking categories root:wikitext(self:renderWarnings()) root:wikitext(self:renderTrackingCategories()) return tostring(root) end -------------------------------------------------------------------------------- -- Exports -------------------------------------------------------------------------------- local p = {} function p._main(args) -- Process numerical args so that we can iterate through them. local data, tracks = {}, {} for k, v in pairs(args) do if type(k) == 'string' then local prefix, num = k:match('^(%D.-)(%d+)$') if prefix and Track.fields[prefix] and (num == '0' or num:sub(1, 1) ~= '0') then -- Allow numbers like 0, 1, 2 ..., but not 00, 01, 02..., -- 000, 001, 002... etc. num = tonumber(num) tracks[num] = tracks[num] or {} tracks[num][prefix] = v else data[k] = v end end end data.tracks = (function (t) -- Compress sparse array local ret = {} for num, trackData in pairs(t) do trackData.nummer = num table.insert(ret, trackData) end table.sort(ret, function (t1, t2) return t1.nummer < t2.nummer end) return ret end)(tracks) return tostring(TrackListing.new(data)) end function p.main(frame) local args = require('Modul:Arguments').getArgs(frame, { wrappers = 'Mal:Sporliste' }) return p._main(args) end return p
Redigeringsforklaring:
Merk at alle bidrag til Wikisida.no anses som frigitt under Creative Commons Navngivelse-DelPåSammeVilkår (se
Wikisida.no:Opphavsrett
for detaljer). Om du ikke vil at ditt materiale skal kunne redigeres og distribueres fritt må du ikke lagre det her.
Du lover oss også at du har skrevet teksten selv, eller kopiert den fra en kilde i offentlig eie eller en annen fri ressurs.
Ikke lagre opphavsrettsbeskyttet materiale uten tillatelse!
Avbryt
Redigeringshjelp
(åpnes i et nytt vindu)
Forhåndsvis en side som bruker denne malen
Mal som brukes på denne siden:
Modul:Sporliste/dok
(
rediger
)
Navigasjonsmeny
Personlige verktøy
Ikke logget inn
Brukerdiskusjon
Bidrag
Opprett konto
Logg inn
Navnerom
Modul
Diskusjon
English
Visninger
Les
Rediger kilde
Vis historikk
Mer
Navigasjon
Forside
Siste endringer
Tilfeldig side
Hjelp til MediaWiki
Verktøy
Lenker hit
Relaterte endringer
Spesialsider
Sideinformasjon