模块:Lyrics/multi
此模块的文档可以在模块:Lyrics/multi/doc创建
local p = {}
local getArgs = require("Module:Arguments").getArgs
local lang = require("Module:Lang")
local errmsg = require("Module:Error")
local lrcmod = require("Module:Lyrics/colors")
local getCharaBlock = require("Module:Lyrics/colors/sub")._charaBlock
local showErrorMessage = function(msg, args)
if args.errMsg ~= "off" then
return errmsg.error{ message = msg }
end
end
local ce_cache = {}
local apply_ce = function(text)
text = mw.ustring.gsub(text, '%$([%d%$%[@])', function(s)
if not ce_cache[s] then ce_cache[s] = mw.getCurrentFrame():expandTemplate{ title = 'ce', args = {s} } end
return ce_cache[s]
end)
text = mw.ustring.gsub(text, '@%[([^%[]-)%]', function(match) return '@' .. (customArgs.map_aliases[match] and customArgs.map_aliases[match] or '['..match..']') end)
return text
end
function p._lyrics(args)
------------------------ 处理参数 ------------------------
local colorsMode = args.colorsMode == "on" -- 是否开启彩色显示开关。
local colors, map_aliases, charas = lrcmod.parseArgs(args.colors or '', args.charas or '', args.charaBlock)
local versions = {}
for k, v in pairs(args) do
if type(k) == "number" then
local def = mw.text.trim(mw.ustring.gsub(v or "", "\n", "")) -- 删除名称定义语句中的所有换行及首尾空白字符。
local key, aliases = mw.ustring.match(def, "^([^%[]*)%[([^%]]*)%]$") -- 匹配名称和缩写列表。
if key == nil then
if mw.ustring.find(def, "[%[%]]") then -- 有意定义缩写列表,因此为格式错误。
if args.errMsg ~= "off" then
return errmsg.error{ message = mw.ustring.format("格式错误:第%d个名称定义语句“%s”中括号“[”和“]”不配对。", k, v) }
end
else
key = def -- 无意定义缩写列表,将整个字符串视为名称。
end
end
key = mw.text.trim(key) -- 去除首尾空白字符。
if key == "" then
if args.errMsg ~= "off" then
return errmsg.error{ message = mw.ustring.format("格式错误:在第%d个名称定义语句“%s”中未找到名称或者全部为空白字符。", k, v) }
end
else
-- 获取所有缩写名称
local inter = mw.text.gsplit(aliases or "", ",")
aliases = {}
for alias in inter do
alias = mw.text.trim(alias)
if alias ~= "" and aliases[alias] == nil then
table.insert(aliases, alias)
aliases[alias] = true
end
end
-- 获取名称及缩写对应参数值的通用函数。
local getParam = function(postfix)
local temp = args[key..postfix] -- 以名称优先。
if mw.text.trim(temp or "") == "" then -- 名称对应参数不存在,则按顺序检查缩写对应参数。
temp = nil
for _, alias in ipairs(aliases) do
if mw.text.trim(args[alias..postfix] or "") ~= "" then -- 这个缩写对应的参数符合条件。
if temp ~= nil then -- 已有符合条件的对应参数。
if args.errMsg ~= "off" then
return false, errmsg.error{ message = mw.ustring.format("检测到重复的参数“%s”和“%s”,它们使用的名称缩写“%s”和“%s”都表示“%s”。", temp..postfix, alias..postfix, temp, alias, key) }
end
--temp = alias -- 顺序后的覆盖顺序前的。
end
temp = alias
end
end
if temp ~= nil then
temp = args[temp..postfix]
end
end
return true, temp
end
local success, result
-- 获取语言代码。
success, result = getParam("lang")
if not success then
return result
end
local lang = result
-- 获取自定义样式。
success, result = getParam("style")
if not success then
return result
end
local style = result
-- 获取歌词的所有行。
local lines = mw.text.split(apply_ce(args[key] or ""):match("^(.-)%s*$"), "\n")
if colorsMode then -- 开启颜色模式。
-- 检查该列是否需要颜色处理。
success, result = getParam("Colors")
if not success then
return result
end
-- 默认第一列需要颜色处理。
if #versions == 0 then
result = result or "on"
lines = lrcmod.parse(colors, charas, args.chorusName or '', lines)
elseif result == "on" then
-- 解析颜色歌词。
lines = lrcmod.parse(colors, charas, args.chorusName or '', lines)
end
end
-- 将每一个翻译版本创建成项。
if args[key] ~= nil then
table.insert(versions, key)
local entry = {
lines = lines,
lang = lang,
style = style
}
if #versions == 1 then entry.lang = entry.lang or "ja" -- 默认第一列时日文。
else entry.lang = entry.lang or "zh" -- 默认第二列时中文。
end
versions[key] = entry
end
end
end
end
------------------------ 核心代码 ------------------------
local html = mw.html.create("div")
:addClass("Lyrics")
:css("width", args.width)
:cssText(args.containerstyle)
-- 检查任何一列歌词是否包含ruby。
if mw.text.trim(args.hasRuby or "") ~= "" then
html:addClass("Lyrics-has-ruby")
else
local hasRuby = false
for i = 1, #versions do
if args[versions[i]]:find("<ruby") then
hasRuby = true
break
end
end
if hasRuby then
html:addClass("Lyrics-has-ruby")
else
html:addClass("Lyrics-no-ruby")
end
end
-- 创建charaBlock。
if args.charaBlock == "on" then
html:tag("p"):node(getCharaBlock{
colors = args.colors,
charas = args.charas,
groupName = args.groupName,
groupColor = versions[versions[1]].style -- 默认为第1列的样式
})
end
local len = 0 -- 行数的最大值
for i = 1, #versions do
len = math.max(len, #(versions[versions[i]].lines))
end
for line = 1, len do
local div = html:tag("div"):addClass("Lyrics-line")
local emptyline = true -- 是否为空行。
for i = 1, #versions do
if (versions[versions[i]].lines[line] or "") ~= "" then
emptyline = false
end
end
if emptyline then
div:tag("div")
:attr("data-column", 1) -- 当前的列编号。
:attr("data-column-count", 1) -- 列的总数。
:addClass("Lyrics-column") -- 通用列样式。
:newline()
else
for i = 1, #versions do
local entry = versions[versions[i]]
local nlang = lang.wrap(entry.lines[line] or "", entry.lang)
div:tag("div")
:attr("data-column", i) -- 当前的列编号。
:attr("data-column-count", #versions) -- 列的总数。
:addClass("Lyrics-column") -- 通用列样式。
:addClass("Lyrics-column-"..entry.lang) -- 针对语言的样式。
:addClass("Lyrics-col"..tostring(i)) -- 针对特定列的样式。
:addClass("Lyrics-column-suppressed") -- 宽屏时压缩在一行内的列的样式。
:cssText(entry.style)
:css("width", "calc(95% / "..tostring(#versions)..")") -- 在一行内放下所有列。
:node(nlang)
div:tag("div")
:attr("data-column", i) -- 当前的列编号。
:attr("data-column-count", #versions) -- 列的总数。
:addClass("Lyrics-column") -- 通用列样式。
:addClass("Lyrics-column-"..entry.lang) -- 针对语言的样式。
:addClass("Lyrics-col"..tostring(i)) -- 针对特定列的样式。
:addClass("Lyrics-column-wrapped") -- 窄屏时拆分为多行的列的样式。
:cssText(entry.style)
:node(nlang)
end
end
end
-- Clear the floating
html:tag("div"):css("clear", "both")
local css = mw.getCurrentFrame():extensionTag{ name = "templatestyles", args = { src = "Template:LyricsKai/multi/styles.css" } }
return css .. tostring(html)
end
function p.lyrics(frame)
local args = getArgs(frame, { wrappers = "Template:LyricsKai/multi" })
return p._lyrics(args)
end
return p