Module:曲包列表

Admin​(留言 | 贡献)2026年8月16日 (日) 23:50的版本 (JSON 流水线更新曲包渲染模块)
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)

此模块的文档可以在Module:曲包列表/doc创建

local p = {}

-- 数据页: 曲包列表 (json 内容模型)
local DATA_TITLE = '模板:曲包列表.json'
-- lang 标注单一来源: 曲目列表数据页的 lang 字段
local SONG_DATA_TITLE = '模板:曲目列表.json'

local function esc(s)
	return (s:gsub('|', '|'))
end

local function loadData(title)
	local t = mw.title.new(title)
	if not t or not t.exists then
		return nil, '数据页不存在: [[' .. title .. ']]'
	end
	local ok, data = pcall(mw.text.jsonDecode, t:getContent())
	if not ok or type(data) ~= 'table' then
		return nil, '数据页 JSON 解析失败: [[' .. title .. ']]'
	end
	return data
end

local function buildLangMap()
	local langBy = {}
	local songData = loadData(SONG_DATA_TITLE)
	if songData then
		for _, s in ipairs(songData.songs or {}) do
			if s['lang'] then langBy[s['曲名']] = s['lang'] end
		end
		for _, s in ipairs(songData.special or {}) do
			if s['lang'] then langBy[s['曲名']] = s['lang'] end
		end
	end
	return langBy
end

function p.render(frame)
	local demomode = frame and frame.args['demo']
	local data, err = loadData(DATA_TITLE)
	if not data then
		return '<span class="error">' .. tostring(err) .. '</span>'
	end

	local langBy = buildLangMap()

	local function disp(name)
		local lang = langBy[name]
		if lang == 'ja' then
			return '{{lang|ja|' .. esc(name) .. '}}'
		elseif lang == 'zh-Hant' then
			return '{{lang|zh-Hant|' .. esc(name) .. '}}'
		end
		return esc(name)
	end

	local out = {}
	table.insert(out, '{| class="wikitable sortable" style="width:100%"')
	table.insert(out, '! 图片 !! 曲包 !! 曲目数 !! 包含曲目')
	for _, pack in ipairs(data.packs or {}) do
		local img = pack['图片']
		local imgCell = img and ('[[文件:' .. esc(img) .. '|80px]]') or '—'
		local songs = {}
		for _, name in ipairs(pack['包含曲目'] or {}) do
			table.insert(songs, '[[' .. '曲目:' .. esc(name) .. '|' .. disp(name) .. ']]')
		end
		table.insert(out, '|-\n| ' .. imgCell .. ' || ' .. esc(pack['曲包'] or '')
			.. ' || ' .. tostring(pack['曲目数'] or '')
			.. ' || ' .. table.concat(songs, ' / '))
	end
	table.insert(out, '|}')

	if not demomode then
		table.insert(out, '\n[[Category:曲包]]')
	end
	-- Scribunto 返回文本中的 {{模板}} 不会被自动展开, 必须显式 preprocess
	return frame:preprocess(table.concat(out, '\n'))
end

return p