このモジュールについての説明文ページを モジュール: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, strings_arrange, brass_arrange, horn_arrange, orchestra_arrange, remix, singer, extra, length = function() return '' end, function() return '' end, function() return '' end, function() return '' end, function() return '' end, function() return '' end, 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; 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.strings_arrange then
result = result .. '<th scope="col" style="width:' .. (args.strings_arrange_width or width.credits) .. ';">ストリングスアレンジ</th>'
-- ストリングスアレンジセル関数再定義
strings_arrange = function(x) return '<td>' .. (x.strings_arrange or ' ') .. '</td>' end
end
if credits.brass_arrange then
-- ブラスアレンジ列追加
result = result .. '<th scope="col" style="width:' .. (args.brass_arrange_width or width.credits) .. ';">ブラスアレンジ</th>'
-- ブラスアレンジセル関数再定義
brass_arrange = function(x) return '<td>' .. (x.brass_arrange or ' ') .. '</td>' end
end
if credits.horn_arrange then
-- ホーンアレンジ列追加
result = result .. '<th scope="col" style="width:' .. (args.horn_arrange_width or width.credits) .. ';">ホーンアレンジ</th>'
-- ホーンアレンジセル関数再定義
horn_arrange = function(x) return '<td>' .. (x.horn_arrange or ' ') .. '</td>' end
end
if credits.orchestra_arrange then
-- オーケストラアレンジ列追加
result = result .. '<th scope="col" style="width:' .. (args.orchestra_arrange_width or width.credits) .. ';">オーケストラアレンジ</th>'
-- オーケストラアレンジセル関数再定義
orchestra_arrange = function(x) return '<td>' .. (x.orchestra_arrange or ' ') .. '</td>' end
end
if credits.remix then
-- リミックス列追加
result = result .. '<th scope="col" style="width:' .. (args.remix_width or width.credits) .. ';">リミックス</th>'
-- オーケストラアレンジセル関数再定義
remix = function(x) return '<td>' .. (x.remix or ' ') .. '</td>' end
end
if credits.singer then
-- 歌列追加
result = result .. '<th scope="col" style="width:' .. (args.singer_width or width.credits) .. ';">歌</th>'
-- オーケストラアレンジセル関数再定義
singer = function(x) return '<td>' .. (x.singer 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 '' or '' --偶数/奇数で別色指定
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) .. strings_arrange(v) .. brass_arrange(v) .. horn_arrange(v) .. orchestra_arrange(v) .. remix(v) .. singer(v) .. extra(v) .. length(v) .. '</tr>'
end
else
for k, v in ipairs(trackA) do
local color = (v[1] % 2 == 0) and '' or ''
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) .. strings_arrange(v) .. brass_arrange(v) .. horn_arrange(v) .. orchestra_arrange(v) .. remix(v) .. singer(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;>合計時間:</div></th><td style="padding-right:0.5em;">'.. 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; vertical-align: middle;')
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
-- calc_columns 関数に新しい変数に関する表示可否判定のロジックを追加
local function calc_columns()
local col = 2 -- #, タイトル
-- ...
if credits.strings_arrange then col = col + 1 end
if credits.brass_arrange then col = col + 1 end
if credits.horn_arrange then col = col + 1 end
if credits.orchestra_arrange then col = col + 1 end
if credits.remix then col = col + 1 end
if credits.singer then col = col + 1 end
return col
end
-- ...
-- calc_width 関数に新しい変数に関する列幅の計算ロジックを追加
local function calc_width()
local width = {}
-- ...
if not credits.strings_arrange then col = col + 1 end
if not credits.brass_arrange then col = col + 1 end
if not credits.horn_arrange then col = col + 1 end
if not credits.orchestra_arrange then col = col + 1 end
if not credits.singer then col = col + 1 end
if not credits.remix then col = col + 1 end
return width
end
return p