モジュール:Tracklist
表示
モジュールの解説[作成]
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