此模块作为模板{{Utawari}}的背后实现,主要用于简便地书写歌割り对齐的歌词。
在仅有不超过9句歌割り歌词时,建议使用模板{{Utawari}}。
根据2018年11月19日-2018年11月22日关于宽屏/窄屏缩进行为的讨论,目前的效果为:
使用格式:
{{#invoke:Utawari[|noLyric=][|lineSeparator=][|第1行歌词[|第2行歌词|...[|第n行歌词]]]}}
{{#invoke:Utawari[|noLyric=][|lineSeparator=][| 第1行歌词[| 第2行歌词[| ...[| 第n行歌词]]] }}
lyricMode
:是否开启歌词模式。歌词模式详见#歌词模式与#非歌词模式章节。
lineSeparator
:模块的自定义换行字符串。
此模块的功能与用法与模板{{Utawari}}基本相同。建议仅当歌割り中歌词超过9句时使用本模块。
更多详细用法请见:模板:Utawari/doc。
lineSeparator
参数。lyricMode
参数。Utawari
这个名称来使用模版了。local module = {}; local noLyric = false; local getArgs = require('Module:Arguments').getArgs function module.main(frame) local args = getArgs(frame) return module._main(args) end function module._main(args) local nodes = {} for i, v in ipairs(args) do table.insert(nodes, module.createNode()) end --初始化结果table。 -- 建立引用树。 for i, v in ipairs(args) do module.analyzeLine(i, v, nodes) end local lineSeparator = nil if args["noLyric"] == nil then --歌词模式 noLyric = false lineSeparator = "\r\n" --{{LyricsKai}}/{{LyricsKai/colors}}中的换行字符串。 else --非歌词模式 noLyric = true lineSeparator = args["lineSeparator"] if lineSeparator == nil then lineSeparator = "\r\n\r\n" --wiki的换行字符串。 end end return module.output(nodes, lineSeparator) end function module.analyzeLine(index, line, result) local currentNode = result[index] local r = module.stringSplitX(line, "##|#%d+", function(t, i, l) if (t == "##") then return "#" else local referenceNode = result[tonumber(string.sub(t, 2, l))] module.setParent(referenceNode, currentNode) return referenceNode end end ) for i,v in ipairs(r) do table.insert(currentNode.data, v) end end function module.output(nodes, lineSeparator) local result = {} local outputLine = function(node) local outputTabInternal = nil outputTabInternal = function(n, t) if (n.parent == nil) then return end outputTabInternal(n.parent, t) for _i, _d in ipairs(n.parent.data) do if _d == n then break elseif module.tableFind(nodes, _d) ~= nil then --Do nothing. else table.insert(t, _d) end end end local tabs = {} outputTabInternal(node, tabs) local datas = {} for i, d in ipairs(node.data) do if module.tableFind(nodes, d) == nil then table.insert(datas, d) end end if next(tabs) == nil then table.insert(result, table.concat(datas)) else local span = mw.html.create("span") -- span:attr("class", "mw-parser-output") local sub = mw.html.create("span") if noLyric then sub:attr("class", "Utawari-nolyric-tab") --非歌词模式使用的样式。 else sub:attr("class", "Utawari-lyric-tab") --歌词模式使用的样式。 end sub:node(table.concat(tabs)) span:node(sub) span:node(table.concat(datas)) table.insert(result, tostring(span)) end end for i, v in ipairs(nodes) do outputLine(v) end return table.concat(result, lineSeparator) end --判断node1是否为node2的上层节点。 function module.isAncestor(node1, node2) if node2.parent == nil then return false elseif node2.parent == mode1 then return true else return module.isAncestor(node1, node2.parent) end end --将node2设为node1的父节点。 function module.setParent(node1, node2) if node1.parent ~= nil then error("无法修改父节点。") elseif module.isAncestor(node1, node2) then error("循环设置父节点。") else node1.parent = node2 table.insert(node2.children, node1) end end --创建一个新节点。 function module.createNode() return { parent = nil, children = {}, data = {} } end function module.stringSplitX(s, pattern, func) local result = {} local localIndex = 1 while true do local text, index, length = module.stringMatchX(s, pattern, localIndex) if index == nil then break end if index > localIndex then table.insert(result, string.sub(s, localIndex, index - 1)) end table.insert(result, func(text, index, length)) localIndex = index + length end if localIndex <= string.len(s) then table.insert(result, string.sub(s, localIndex, string.len(s))) end return result; end function module.stringMatchX(s, pattern, init) local x, y = module.stringFindX(s, pattern, init) if x == nil or y == nil then return nil, nil, nil else local text = string.sub(s, x, y) local length = y - x + 1 return text, x, length end end function module.stringFindX(str, pattern, init) local va1, va2 = string.find(pattern, "|") local patterntable = {} if va1 ~= nil then table.insert(patterntable, string.sub(pattern, 1, va1 - 1)) table.insert(patterntable, string.sub(pattern, va1 + 1, string.len(pattern))) end va1, va2 = string.find(str, patterntable[1], init) if va1 == nil then return string.find(str, patterntable[2], init) else va3, va4 = string.find(str, patterntable[2], init) if va3 == nil then return va1, va2 end if va1 < va3 then return va1, va2 elseif va1 > va3 then return va3, va4 else if va2 <= va4 then return va1, va2 else return va3, va4 end end end return va1, va2 end function module.tableFind(t, item) for i,v in ipairs(t) do if v == item then return i end end return nil end return module