跳转到内容
打开/关闭搜索
搜索
打开/关闭菜单
389
文件
1
用户
6083
编辑
Gal中文百科
导航
首页
最近更改
随机页面
MediaWiki帮助
特殊页面
在其他项目中
打开/关闭外观设置菜单
无法加载偏好设置。请检查您的网络连接并重试。
重试
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。
user-interface-preferences
个人工具
讨论
贡献
创建账号
登录
编辑“︁
Module
:
Tracklist
”︁
来自Gal中文百科
查看
阅读
编辑源代码
查看历史
associated-pages
模块
讨论
更多操作
更多
工具
链入页面
相关更改
页面信息
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
-- This module implements [[Template:Tracklist]] local yesno = require('Module:Yesno') local checkType = require('libraryUtil').checkType local SHOW_WARNINGS = false local INPUT_ERROR_CATEGORY = '输入错误的曲目表' -------------------------------------------------------------------------------- -- 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:validateLength(length) checkType('validateLength', 1, length, 'string', true) if length == nil then -- Do nothing if no length specified return nil end --mw.log('>> length = ' .. length) length = length -- ugly hack: allow {{ref}} -- 在{{ref}}、[[模板:Citation Style documentation/cs1]]中的cs1模板等,前后包覆 span 可规避归入「Category:输入错误的曲目表」这个隐藏分类。 -- e.g., `length1 = 5:04<span class="ref"><ref name="通常盘"/></span>` @ [[春逝/marie]] :gsub("^([%d:]+)%s*<(%w+)([^<>]*)>[%s%S]*<%/%2>", "%1") -- ugly hack: allow <ref> --:gsub("\127\'\"\`UNIQ----ref--[%dA-F]+--QINU\`\"\'\127", "") -- trim :match "^%s*(.-)%s*$" --mw.log('>> length2 = ' .. length) local hours, minutes, seconds -- Try to match times like "1:23:45". hours, minutes, seconds = length: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( "无效时间'%s'(时间格式'h:mm:ss'不能以零开头)", mw.text.nowiki(length) ), 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 = length: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( "无效时间'%s'(时间格式'mm:ss'不能以零开头)", mw.text.nowiki(length) ), 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( "无效时间'%s'(时间格式必须为'm:ss'、'mm:ss'或'h:mm:ss')", mw.text.nowiki(length) ), 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( "无效时长'%s'(如果指定了小时数,则分钟数必须小于60)", mw.text.nowiki(length) ), INPUT_ERROR_CATEGORY) return nil end -- Check that the seconds are less than 60 if tonumber(seconds) >= 60 then self:addWarning(string.format( "无效时长'%s'(秒数必须小于60)", mw.text.nowiki(length) ), INPUT_ERROR_CATEGORY) end return nil end -------------------------------------------------------------------------------- -- Track class -------------------------------------------------------------------------------- local Track = {} Track.__index = Track addMixin(Track, Validation) Track.fields = { number = true, title = true, note = true, lyrics = true, music = true, writer = true, arranger = true, producer = true, ep = true, extra = true, longnote = true, length = true, } Track.cellMethods = { number = 'makeNumberCell', title = 'makeTitleCell', writer = 'makeWriterCell', lyrics = 'makeLyricsCell', music = 'makeMusicCell', arranger = 'makeArrangerCell', producer = 'makeProducerCell', ep = 'makeEpCell', extra = 'makeExtraCell', longnote = 'makeLongNoteCell', length = 'makeLengthCell', } function Track.new(data) local self = setmetatable({}, Track) Validation.init(self) for field in pairs(Track.fields) do self[field] = data[field] end self.number = assert(tonumber(self.number)) self:validateLength(self.length) return self end function Track:getLyricsCredit() return self.lyrics end function Track:getMusicCredit() return self.music end function Track:getWriterCredit() return self.writer end function Track:getArrangerCredit() return self.arranger end function Track:getProducerCredit() return self.producer end function Track:getEpCredit() return self.ep end function Track:getExtraField() return self.extra end function Track:getLongNoteField() return self.longnote end function Track:getLengthField() return self.length 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:makeNumberCell() return mw.html.create('td') :css('padding-right', '10px') :css('text-align', 'right') :css('vertical-align', 'top') :wikitext(self.number .. '.') end function Track:makeTitleCell() local titleCell = mw.html.create('td') titleCell :css('vertical-align', 'top') :wikitext(self.title and string.format('%s', self.title) or '-{zh-hans:《;zh-hant:〈;}-无题-{zh-hans:》;zh-hant:〉;}-') if self.note then titleCell :tag('span') :css('font-size', '85%') :wikitext(string.format('(%s)', self.note)) end return titleCell end function Track:makeWriterCell() return Track.makeSimpleCell(self.writer) end function Track:makeLyricsCell() return Track.makeSimpleCell(self.lyrics) end function Track:makeMusicCell() return Track.makeSimpleCell(self.music) end function Track:makeArrangerCell() return Track.makeSimpleCell(self.arranger) end function Track:makeProducerCell() return Track.makeSimpleCell(self.producer) end function Track:makeEpCell() return Track.makeSimpleCell(self.ep) end function Track:makeExtraCell() return Track.makeSimpleCell(self.extra) end function Track:makeLongNoteCell() local longnoteCell = mw.html.create('td') longnoteCell :css('vertical-align', 'top') :tag('span') :css('font-size', '85%') :wikitext(self.longnote or ' ') return longnoteCell end function Track:makeLengthCell() return mw.html.create('td') :addClass('tracklist-length') :css('text-align', 'right') :wikitext(self.length or ' ') end function Track:exportRow(options) options = options or {} local columns = options.columns or {} local row = mw.html.create('tr') 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 = { all_position = true, all_writing = true, all_lyrics = true, all_music = true, all_arranger = true, all_producer = true, all_ep = true, all_note = true, collapsed = true, headline = true, font_size = true, extra_column = true, total_length = true, title_width = true, writing_width = true, lyrics_width = true, music_width = true, arranger_width = true, producer_width = true, ep_width = true, extra_width = true, longnote_width = true, category = true, } TrackListing.deprecatedFields = { writing_credits = true, lyrics_credits = true, music_credits = true, arranger_credits = true, producer_credits = true, ep_credits = true, longnote_column = 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('使用废弃参数的曲目表') break end end -- Validate total length if data.total_length then self:validateLength(data.total_length) end -- Add properties for field in pairs(TrackListing.fields) do self[field] = data[field] end -- Evaluate boolean properties self.collapsed = yesno(self.collapsed, 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 = { lyrics = 'getLyricsCredit', music = 'getMusicCredit', writer = 'getWriterCredit', arranger = 'getArrangerCredit', producer = 'getProducerCredit', ep = 'getEpCredit', extra = 'getExtraField', longnote = 'getLongNoteField', length = 'getLengthField', } local doneWriterCheck = 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 doneWriterCheck and optionalColumns.writer then doneWriterCheck = true optionalColumns.lyrics = nil optionalColumns.music = nil columnMethods.lyrics = nil columnMethods.music = nil end if not next(columnMethods) then break end end self.optionalColumns = optionalColumns end return self end function TrackListing:makeIntro() local s = '' if self.all_writing then s = s .. string.format( '全碟词曲:%s ', self.all_writing ) elseif self.all_lyrics and self.all_music then s = s .. string.format( '全碟-{zh-cn:作词;zh-hk:填词;zh-tw:作词;}-:%s 全碟作曲:%s ', self.all_lyrics, self.all_music ) elseif self.all_lyrics then s = s .. string.format( '全碟-{zh-cn:作词;zh-hk:填词;zh-tw:作词;}-:%s ', self.all_lyrics ) elseif self.all_music then s = s .. string.format( '全碟作曲:%s ', self.all_music ) end if self.all_arranger then s = s .. string.format( '全碟编曲:%s ', self.all_arranger ) end if self.all_producer then s = s .. string.format( '全碟制作人:%s ', self.all_producer ) end if self.all_ep then s = s .. string.format( '全碟监制:%s ', self.all_ep ) end if self.all_note then if self.all_note == 'except' or yesno(self.all_note) == true then s = s .. string.format( '<small>(下面注明例外曲目)</small>' ) else s = s .. string.format( '%s', self.all_note ) end end return s 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">曲目表错误:%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 = {'number', 'title'} if self.optionalColumns.writer then columns[#columns + 1] = 'writer' else if self.optionalColumns.lyrics then columns[#columns + 1] = 'lyrics' end if self.optionalColumns.music then columns[#columns + 1] = 'music' end end if self.optionalColumns.arranger then columns[#columns + 1] = 'arranger' end if self.optionalColumns.producer then columns[#columns + 1] = 'producer' end if self.optionalColumns.ep then columns[#columns + 1] = 'ep' end if self.optionalColumns.extra then columns[#columns + 1] = 'extra' end if self.optionalColumns.longnote then columns[#columns + 1] = 'longnote' end if self.optionalColumns.length then columns[#columns + 1] = 'length' end -- Find colspan and column width local nColumns = #columns local c = #columns if self.optionalColumns.longnote then c = c - 1 end if self.optionalColumns.length then c = c - 1 end local nOptionalColumns = c - 2 local titleColumnWidth local longnoteColumnWidth if c >= 7 then if self.optionalColumns.longnote then titleColumnWidth = 20 longnoteColumnWidth = 20 else titleColumnWidth = 25 longnoteColumnWidth = 0 end elseif c >= 6 then if self.optionalColumns.longnote then titleColumnWidth = 20 longnoteColumnWidth = 20 else titleColumnWidth = 30 longnoteColumnWidth = 0 end elseif c >= 5 then if self.optionalColumns.longnote then titleColumnWidth = 25 longnoteColumnWidth = 24 else titleColumnWidth = 34 longnoteColumnWidth = 0 end elseif c >= 4 then if self.optionalColumns.longnote then titleColumnWidth = 25 longnoteColumnWidth = 30 else titleColumnWidth = 40 longnoteColumnWidth = 0 end elseif c >= 3 then if self.optionalColumns.longnote then titleColumnWidth = 30 longnoteColumnWidth = 40 else titleColumnWidth = 60 longnoteColumnWidth = 0 end else if self.optionalColumns.longnote then titleColumnWidth = 30 else titleColumnWidth = 100 end longnoteColumnWidth = 0 end local optionalColumnWidth = (100 - titleColumnWidth - longnoteColumnWidth) / nOptionalColumns titleColumnWidth = titleColumnWidth .. '%' if longnoteColumnWidth ~= 0 then longnoteColumnWidth = longnoteColumnWidth .. '%' else longnoteColumnWidth = '40em' end optionalColumnWidth = optionalColumnWidth .. '%' -- Find intros local nIntros = 0 if self.all_writing then nIntros = nIntros + 1 else if self.all_lyrics then nIntros = nIntros + 1 end if self.all_music then nIntros = nIntros + 1 end end if self.all_arranger then nIntros = nIntros + 1 end if self.all_producer then nIntros = nIntros + 1 end if self.all_ep then nIntros = nIntros + 1 end if self.all_note then nIntros = nIntros + 1 end -- Root of the output local root = mw.html.create() -- Intro (if above header) if nIntros ~= 0 and self.all_position ~= 'below' then root:tag('div') :css('padding-left', '1em') :node(self:makeIntro()) end -- Start of track listing table local tableRoot = root:tag('table') tableRoot :addClass('tracklist') :addClass(self.collapsed and 'mw-collapsible mw-collapsed' or nil) :css('display', 'block') :css('border-spacing', '0px') :css('border-collapse', 'collapse') :css('font-size', self.font_size or '100%') :css('border', self.collapsed and '#aaa 1px solid' or nil) :css('padding', self.collapsed and '3px' or '4px') -- Header row if self.headline or self.collapsed then tableRoot:tag('tr'):addClass('tlheadline'):tag('th') :addClass('mbox-text') :attr('colspan', nColumns) :css('text-align', 'left') :wikitext(self.headline or '曲目表') end -- Intro row (if below header) if nIntros ~= 0 and self.all_position == 'below' then tableRoot:tag('tr'):tag('th') :attr('colspan', nColumns) :css('padding-left', '2em') :css('text-align', 'left') :css('background-color', '#fff') :css('font-weight', 'normal') :node(self:makeIntro()) 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('white-space', 'nowrap') :wikitext('曲序') ---- Title headerRow:tag('th') :addClass('tlheader') :attr('scope', 'col') :css('width', self.title_width or titleColumnWidth) :css('white-space', 'nowrap') :wikitext('曲目') ---- Optional headers: writer, lyrics, music, arranger, producer, ep 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('white-space', 'nowrap') :wikitext(headerText) end end addOptionalHeader('writer', '词曲', self.writing_width) addOptionalHeader('lyrics', '-{zh-cn:作词;zh-hk:填词;zh-tw:作词;}-', self.lyrics_width) addOptionalHeader('music', '作曲', self.music_width) addOptionalHeader('arranger', '编曲', self.arranger_width) addOptionalHeader('producer', '制作人', self.producer_width) addOptionalHeader('ep', '监制', self.ep_width) addOptionalHeader( 'extra', self.extra_column or '{{{extra_column}}}', self.extra_width ) ---- Notes if self.optionalColumns['longnote'] then headerRow:tag('th') :addClass('tlheader') :attr('scope', 'col') :css('width', self.longnote_width or longnoteColumnWidth) :css('white-space', 'nowrap') :wikitext('备注') end ---- Track length if self.optionalColumns['length'] then headerRow:tag('th') :addClass('tlheader') :attr('scope', 'col') :css('width', '4em') :css('text-align', 'right') :css('white-space', 'nowrap') :wikitext('时长') end -- 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_length then tableRoot :tag('tr') :addClass('tracklist-total-length') :tag('th') :attr('colspan', nColumns - 1) :css('padding', 0) :tag('span') :css('width', '4em') :css('white-space', 'nowrap') :wikitext("总时长:") :done() :done() :tag('td') :css('padding', '0 10px 0 0') :css('text-align', 'right') :css('white-space', 'nowrap') :wikitext(string.format("%s", self.total_length)) end -- Warnings and tracking categories root:wikitext(self:renderWarnings()) root:wikitext(self:renderTrackingCategories()) return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Module:Tracklist/styles.css' } } .. 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.number = num table.insert(ret, trackData) end table.sort(ret, function (t1, t2) return t1.number < t2.number end) return ret end)(tracks) return tostring(TrackListing.new(data)) end function p.main(frame) local args = require('Module:Arguments').getArgs(frame, { wrappers = 'Template:Tracklist' }) return p._main(args) end return p
摘要:
请注意,所有对Gal中文百科的贡献均可能会被其他贡献者编辑、修改或删除。如果您不希望您的文字作品被随意编辑,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源(详情请见
Gal中文百科:著作权
)。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)
此页面嵌入的页面:
Module:Tracklist/doc
(
编辑
)
编辑“︁
Module
:
Tracklist
”︁
来自Gal中文百科