モジュール:Tracklist
このモジュールについての説明文ページを モジュール:Tracklist/doc に作成できます
local p = {} --共通変数 local track = {} --トラックテーブル格納用テーブル local all = {} --全○○格納用テーブル local desc = {nil, nil} --コメント格納用テーブル local credits = {} --クレジット表示可否格納用テーブル local args = {} --その他引数格納用テーブル local col = 0 --列数 local width = {} --列幅格納用テーブル local collapsed = false --折りたたみ可否 local writer, lyrics, music, arranger, extra, length = function() return '' end, function() return '' end, function() return '' end, function() return '' end, function() return '' end, function() return '' end --基本セル関数 local md = true --microdata on/off --[[ 引数取得 ]] local function getArgs(frame) local t_info, t_num = '', 0 local func_credits = function(v) if v == 'yes' then return true end local alias = {'+arrangements', '+a', '+編曲', '・編曲'} for _k, _v in ipairs(alias) do if v == _v then return _v end end return false end for k, v in pairs(require('Module:Arguments').getArgs(frame, {parentOnly = true})) do if string.match(k, '^%D+%d+$') then --各トラック格納 t_info, t_num = string.match(k, '(%D+)(%d+)') if not track[t_num] then track[t_num] = {} end track[t_num][1] = tonumber(t_num) -- トラック番号はkey=1で記録 track[t_num][t_info] = v -- トラック情報はkey=引数で記録 elseif string.match(k, 'all_') then --全○○格納 local pattern = string.gsub(k, 'all_', '') if not all[pattern] then all[pattern] = {nil, v} end elseif string.match(k, '^%d$') then --コメント格納 desc[k] = string.gsub(v, '^([*#;:])', '\n%1') elseif string.match(k, '_credits') then --クレジット表示可否格納 credits[string.gsub(k, '_credits', '')] = func_credits(v) else -- その他格納 args[k] = v end end --allの整理 if all then local function isSame(a, b) --リンクを考慮して文字列を比較する if a and b then return (string.match(a[2], '%[%[.-%|(.-)]]') or string.match(a[2], '%[%[(.-)]]') or a[2]) == (string.match(b[2], '%[%[.-%|(.-)]]') or string.match(b[2], '%[%[(.-)]]') or b[2]) else return false end end if not all.writing and isSame(all.lyrics, all.music) then all.writing = {nil, all.lyrics[2]} end if all.writing then all.lyrics, all.music = nil, nil all.writing[1] = '全作詞・作曲: ' else if all.lyrics then all.lyrics[1] = '全作詞: ' end if all.music then all.music[1] = '全作曲: ' end end if isSame(all.writing, all.arrangements) then all.all = {'全作詞・作曲・編曲: ', all.writing[2]} all.writing, all.arrangements = nil, nil else if all.arrangements then all.arrangements[1] = '全編曲: ' end end if isSame(all.music, all.arrangements) then all.producing = {'全作曲・編曲: ', all.music[2]} all.music, all.arrangements = nil, nil end end credits.extra = args.extra_column if credits.writing then credits.lyrics, credits.music = false, false if credits.writing ~= true then credits.arrangements = false end end if credits.music and credits.music ~= true then credits.arrangements = false end collapsed = (args.collapsed == 'yes') md = (args.microdata == 'no') and false or args.id end --[[ 列数計算 ]] local function calc_columns() local col = 2 --#,タイトル for k, v in pairs(track) do if not v.length then credits.length = false else credits.length = true break end end for k, v in pairs(credits) do if v then col = col + 1 end end return col end --[[ 幅計算 ]] local function calc_width() local width = {} if not credits.length then col = col + 1 end if col < 4 then width.title, width.credits = '100%', 'auto' elseif col < 5 then width.title, width.credits = '60%', '40%' elseif col < 6 then width.title, width.credits = '40%', '30%' elseif col < 7 then width.title, width.credits = '40%', '20%' else width.title, width.credits = '40%', '15%' end return width end --[[ ヘッダ部 ]] local function header() --キャプション定義 local result = (args.headline or collapsed) and '<caption style="text-align:left; padding:0.25em 0.9em; font-weight:bold; line-height:1.4em; white-space:nowrap;">' .. (args.headline or 'トラックリスト') .. '</caption>' or '' if collapsed then --折りたたみ表示において[表示]ボタン行追加 result = result .. '<tr style="position:absolute; top:0.25em; right:0.9em; speak:none;"><th colspan="' .. col .. '"></th></tr>' end local newall = {} --全○○表示用テーブル if all then --全○○/コメント表示のとき if all.lyrics and not credits.lyrics then newall[1] = all.lyrics[1] .. all.lyrics[2] end if all.music and not credits.music then newall[#newall + 1] = all.music[1] .. all.music[2] end if all.all and not credits.writing and not credits.lyrics and not credits.music and not credits.arrangements then newall[1] = all.all[1] .. all.all[2] elseif all.writing and not credits.writing and not credits.lyrics and not credits.music then newall[1] = all.writing[1] .. all.writing[2] elseif all.producing and not credits.music and not credits.arrangements then newall[#newall + 1] = all.producing[1] .. all.producing[2] end if all.arrangements and not credits.arrangements then newall[#newall + 1] = all.arrangements[1] .. all.arrangements[2] end end if newall[1] or #desc > 0 then --全○○/コメント行追加 result = result .. '<tr><td colspan="' .. col .. '" style="padding-left:0.5em;"><small style="font-size:100%;">' .. (desc[1] or '') .. (newall[1] and (table.concat(newall, '、') .. '。') or '') .. (desc[2] or '') .. '</small></td></tr>' end --見出し行追加(#列・タイトル列追加) result = result .. '<tr style="text-align:left; background-color:#eee; font-size:111%;"><th scope="col" style="width:2em; padding-right:0.3em; text-align:right; white-space:nowrap;">#</th><th scope="col" style="width:' .. width.title .. '; padding-left:0.9em; white-space:nowrap;">タイトル</th>' if credits.writing then --作詞・作曲列追加 result = result .. '<th scope="col" style="width:' .. (args.writing_width or (credits.extra and '30%' or '40%')) .. ';">作詞・作曲' .. (credits.writing == true and '' or '・編曲') .. '</th>' --作詞・作曲セル関数再定義 if md then writer = function(x) return '<td itemprop="recordingOf" itemscope itemtype="http://schema.org/MusicComposition"><span itemprop="lyricist composer" itemscope itemtype="http://schema.org/Person"><span itemprop="name">' .. (x.writer or all.writer and all.writer[2] or all.all and all.all[2] or ' ') .. '</span></span></td>' end else writer = function(x) return '<td>' .. (x.writer or all.writer and all.writer[2] or all.all and all.all[2] or ' ') .. '</td>' end end else local disp = function(y) if y then return '' else return 'display:none;' end end --作詞列追加 result = result .. '<th scope="col" style="width:' .. (args.lyrics_width or width.credits) .. ';' .. disp(credits.lyrics) .. '">作詞</th>' --作詞セル関数再定義 if md then lyrics = function(x) return '<td itemprop="recordingOf" itemscope itemtype="http://schema.org/MusicComposition" style="' .. disp(credits.lyrics) .. '"><span itemprop="lyricist" itemscope itemtype="http://schema.org/Person"><span itemprop="name">' .. (x.lyrics or all.lyrics and all.lyrics[2] or x.writer or all.writing and all.writing[2] or all.all and all.all[2] or ' ') .. '</span></span></td>' end else lyrics = function(x) return '<td style="' .. disp(credits.lyrics) .. '">' .. (x.lyrics or all.lyrics and all.lyrics[2] or x.writer or all.writing and all.writing[2] or all.all and all.all[2] or ' ') .. '</td>' end end --作曲列追加 result = result .. '<th scope="col" style="width:' .. (args.music_width or width.credits) .. ';' .. disp(credits.music) .. '">作曲' .. (credits.music == true and '' or '・編曲') .. '</th>' --作曲セル関数再定義 if md then music = function(x) return '<td itemprop="recordingOf" itemscope itemtype="http://schema.org/MusicComposition" style="' .. disp(credits.music) .. '"><span itemprop="composer" itemscope itemtype="http://schema.org/Person"><span itemprop="name">' .. (x.music or all.music and all.music[2] or x.writer or all.writing and all.writing[2] or all.producing and all.producing[2] or all.all and all.all[2] or ' ') .. '</span></span></td>' end else music = function(x) return '<td style="' .. disp(credits.music) .. '">' .. (x.music or all.music and all.music[2] or x.writer or all.writing and all.writing[2] or all.producing and all.producing[2] or all.all and all.all[2] or ' ') .. '</td>' end end end if credits.arrangements then --編曲列追加 result = result .. '<th scope="col" style="width:' .. (args.arrangements_width or width.credits) .. ';">編曲</th>' --編曲セル関数再定義 arranger = function(x) return '<td>' .. (x.arranger or all.arrangements and all.arrangements[2] or all.producing and all.producing[2] or all.all and all.all[2] or ' ') .. '</td>' end end if credits.extra then --extra列追加 result = result .. '<th scope="col" style="width:' .. (args.extra_width or width.credits) .. ';">' .. credits.extra .. '</th>' --extraセル関数再定義 extra = function(x) return '<td>' .. (x.extra or ' ') .. '</td>' end end if credits.length then --時間列追加 result = result .. '<th scope="col" style="width:4em; padding-right:0.5em; text-align:right; white-space:nowrap;">時間</th>' --時間セル再定義 if md then length = function(x) return '<td style="padding-right:0.5em; text-align:right; white-space:nowrap;">' .. (x.length and ('<time itemprop="duration" datetime="'.. string.gsub(x.length, '^(%d+):(%d+)$', 'PT%1M%2S') ..'">' .. x.length .. '</time>') or ' ') .. '</td>' end else length = function(x) return '<td style="padding-right:0.5em; text-align:right; white-space:nowrap;">' .. (x.length and ('<time datetime="'.. string.gsub(x.length, '^(%d+):(%d+)$', 'PT%1M%2S') ..'">' .. x.length .. '</time>') or ' ') .. '</td>' end end end result = result .. '</tr>' return result end --[[ 本体部 ]] local function body() local result = '' local trackA = {} --ソート用テーブル for k, v in pairs(track) do trackA[#trackA + 1] = v end table.sort(trackA, function (a, b) return a[1] < b[1] end ) if md then for k, v in ipairs(trackA) do local color = (v[1] % 2 == 0) and '#f7f7f7' or '#fff' --偶数/奇数で別色指定 result = result .. '<tr itemprop="track" itemscope itemtype="http://schema.org/MusicRecording" style="background-color:' .. color .. '; vertical-align:top;"><td style="padding-left:0.5em; text-align:right;"><span itemprop="position">' .. (v['#'] or v[1]) .. '</span>.</td><td>' .. (v.title and ('「<span itemprop="name">' .. v.title .. '</span>」') or 'タイトルなし') .. (v.note and ('<small>(' .. v.note .. ')</small>') or '') .. '</td>' .. writer(v) .. lyrics(v) .. music(v) .. arranger(v) .. extra(v) .. length(v) .. '</tr>' end else for k, v in ipairs(trackA) do local color = (v[1] % 2 == 0) and '#f7f7f7' or '#fff' result = result .. '<tr style="background-color:' .. color .. '; vertical-align:top;"><td style="padding-left:0.5em; text-align:right;">' .. (v['#'] or v[1]) .. '.</td><td>' .. (v.title and ('「' .. v.title .. '」') or 'タイトルなし') .. (v.note and ('<small>(' .. v.note .. ')</small>') or '') .. '</td>' .. writer(v) .. lyrics(v) .. music(v) .. arranger(v) .. extra(v) .. length(v) .. '</tr>' end end return result end --[[ フッタ部(合計時間) ]] local function footer() local total = args.total_length local hour, min, sec = 0, 0, 0 if total == 'auto' then --合計時間計算 for k, v in pairs(track) do if not v.length then v.length = '0:00' end local _min, _sec = string.match(v.length, '(%d+):(%d+)') min, sec = min + _min, sec + _sec end while sec > 59 do min = min + 1 sec = sec - 60 end if sec < 10 then sec = '0' .. sec end total = min .. ':' .. sec end if total and total == string.match(total, '%d*:%d*') then --<time>タグ hour, min, sec = string.match(total, '(%d-):?(%d+):(%d+)') hour = (hour ~= '') and tonumber(hour) or 0 min = hour * 60 + tonumber(min) total = '<time datetime="PT' .. min .. 'M' .. sec .. 'S">'.. min .. ':' .. sec .. '</time>' --合計時間行追加 return '<tr style="text-align:right; font-size:111%;"><th colspan="' .. (col - 1) .. '"><div style="width:7.5em; text-align:left; margin:0 0 0 auto; padding-left:0.5em; white-space:nowrap; font-weight:bold; background-color:#eee; outline:1px solid #eee;">合計時間:</div></th><td style="padding-right:0.5em; background-color:#eee;">'.. total .. '</td></tr>' else return '' end end function p.main(frame) getArgs(frame) col = calc_columns() --number width = calc_width() --table --tableタグで囲んで出力 local table = mw.html.create('table') table :wikitext(header() .. body() .. footer()) --tableタグ内 :attr({class = 'tracklist', id = args.id or ''}) :cssText('display:block; max-width:100%; width:auto; border-spacing:0px; border-collapse:collapse; padding:0.2em; font-size:90%; text-align:left;') if collapsed then --折りたたみ表示追加指定 table :addClass('mw-collapsible mw-collapsed') :cssText('position:relative; overflow:hidden; outline:1px solid #aaa;') end if md then table:attr({itemtype = 'http://schema.org/MusicAlbum'}) end return tostring(table) end return p