LLWiki正在建设中,欢迎加入我们

模块:Lyrics

来自LLWiki
跳转到导航 跳转到搜索
Template-info.png 模块文档
这个文档嵌入模块:Lyrics/doc

本页面含有来自萌娘百科的文本,以CC BY-NC-SA 3.0授权引入。经过双方的修改,内容可能已与来源有很大差异。

请使用{{lyrics}}调用模块。

--这是Lua语言。两个横线右侧的为注释,给看不懂的人(编者自己)用的。

--Lua快速入门:
--a..b表示字符串相连接。a+b表示转换为数字再相加。
--a.f(b,i)中的a.f表示类型a的函数f,函数对象为b,i是参数。a:f(i)等价于a.f(a,i)。
--table是array和dict的结合体。指定key时则为有key的dict;否则为key从1开始的array。
--只有false和nil为假;其他不管是不是空的,全都是真。
--字符串匹配和正则表达式很像,但有所不同。
--其他的和其他语言都差不多。

local module={} --模块的本质类似于函数库:下方定义的所有函数均放置在名为module的table中,最后返回module。
local getArgs = require('Module:Arguments').getArgs --调用其他模块中的函数。
--getArgs是一个函数,作用是获取传入的args。第二参数是options的table。

local data = mw.loadData( "module:lyrics/data" )
local colors = data.colors --角色名转换颜色的table
local fullnames = data.fullnames --角色名转换全名的table
local classnames = data.classnames --小队名转换角色名的table

function module.name2color(names,text,lang) --按角色名转换成的颜色给文字上色及加title和语言标识。
    if names=='' then
        return module.langWrap(text, lang)
    elseif names:find(',') then --如果颜色标识中有逗号,则说明有多位角色,使用渐变色。
        local errorFlag=nil
        names=mw.text.split(names, ',') --将角色列表全部转为小写后,在逗号处分割成table。
        local result='<span title="' --放置上色结果的span。title内放置角色全名
        for k,name in ipairs(names) do --将分割后的角色列表依次处理。k表示编号,从1开始。
            result=result..(fullnames[name] or '') --把每个角色名转换成全名,并加入到结果。如果角色不存在,则为空。
            if k<#names then --#表示求table的长度。如果当前不是最后一个,
                result=result..'、' --则加一个顿号。
            end --因为连接过程需要转换文字,所以不使用join或listToText。
        end
        result=result..'" class="'
        for k,name in ipairs(names) do
            result=result.." "..(classnames[name] or name)..'-lyrics' --与上面的类似,加入class
            if colors[name]==nil then
                errorFlag=(errorFlag and errorFlag..", " or '')..name
            end
        end
        result=result.." "..(errorFlag and "error" or "Lyrics_gradient")..'" style="background-image:-webkit-linear-gradient(left,'
        for k,name in ipairs(names) do
            result=result..(colors[name] or 'black') --与上面的类似,加入各颜色。如果颜色不存在,则为黑色。
            if k<#names then
                result=result..','
            end
        end
        return result..");"..(
            errorFlag and 'background:none;">[[category:Lyrics中出现错误颜色参数的页面]]Wrong color key: '..errorFlag
            or '">'..module.langQuote(text, lang)
        ).."</span>"
    else --如果颜色标识中没有逗号,则说明只有一位角色,直接上色。
        return '<span class="Lyrics_single '..(classnames[names] or names).."-lyrics"..(colors[names] and '' or " error")..
            '" title="'..(fullnames[names] or '')..'" style="color:'..(colors[names] or '')..';">'..
            (colors[names] and module.langQuote(text, lang) or "[[category:Lyrics中出现错误颜色参数的页面]]Wrong color key: "..names)
            .."</span>"
    end
end

function module.langQuote(text, lang) --改写自[[moegirl:Module:Lang]]的.quote。确定语言是否需要繁简转换。
    if lang == 'zh' then --中文则需要繁简转换。方法是不做改动,直接返回。
        return text
    else --其他语言则防止繁简转换。方法是在文字两侧加上防转换的-{ }-。
        return '-{' .. text .. '}-'
    end
end

function module.langWrap(text,lang) --改写自[[moegirl:Module:Lang]]的.wrap。给文字加上指定语言的attr。
    local span = mw.html.create('span') --创建HTML标签span用于设置语言。
        :wikitext( module.langQuote(text, lang) ) --给这个span加上内容,内容为langQuote确定的是否需要繁简转换的维基文本。
    return tostring(span)
end

function module.split(text)
    local result = {}
    for v in mw.ustring.gmatch(text..'\n', '([^\n]*)\n') do
        table.insert(result, v)
    end
    return result
end

function module._lyrics(args) --改写自[[moegirl:Module:Lyrics]]的._lyrics。args为传入参数的table。
    local orig = module.split(args[1] or args.original or '')
    local tran = module.split(args[2] or args.translated or '')
   
    --对传入的字符串进行初步处理。
    --1. 如果没有传入字符串,则默认为空字符串。
    --2. 在所有换行处分割字符串,结果为一个table。
    local llang = args.llang or 'ja'
    local rlang = args.rlang --传入的语言,没有传入则默认分别为日文与中文。
    local lcolor = colors[string.lower(args.lcolor or '')] or colors[string.lower(args.color or '')] or args.lcolor or args.color or ''
    local rcolor = colors[string.lower(args.rcolor or '')] or args.rcolor or '' --传入的默认颜色,没有传入则默认为空字符串。
    local lstyle = '' --准备处理传入的style。
    if lcolor ~= '' then --如果传入了color,
        lstyle = 'color:'..lcolor..';'..(args.lstyle or '') --则把color放在传入的style前;
    else --否则,
        lstyle = args.lstyle or '' --只有传入的style。
    end
    --如果没有传入style则默认为空字符串。style中如果包括color则会覆盖传入的color。
    local rstyle = '' --与上面的类似,处理译文的style。
    if rcolor ~='' then
        rstyle = 'color:'..rcolor..';'..(args.rstyle or '')
    else
        rstyle = args.rstyle or ''
    end
    
    local html = mw.html.create('div') --创建HTML标签div用于放置内容,此div为全部内容的最外层容器。
        :addClass('Lyrics_box') --给这个div添加Lyrics_box的class。
        :cssText(args.containerstyle or '') --设置容器的其他style。

    if (args[2] or args.translated or '') == '' then
        html:addClass('Lyrics_no_translation') --如果歌詞沒有添加譯文,則添加Lyrics_no_translation的class。
    end

    if (args[1] or args.original or ''):find('<ruby') or (args[2] or args.translated or ''):find('<ruby') or (args.hasRuby or '') ~= '' then
        html:addClass('Lyrics_has_ruby') --如果歌词中有ruby,或者手动设置的hasRuby不为空,则添加Lyrics_has_ruby的class;
    else
        html:addClass('Lyrics_no_ruby') --否则,添加Lyrics_no_ruby的class。
    end

    local len = math.max(#orig, #tran) --歌词行数。#表示求table的长度。原文和译文较长的即为总行数。

    for i=1,len do --为每一行进行一次。
        local orig_line=orig[i] --准备转换颜色标识。
        if orig_line:find('@') then --如果有颜色标识,
            orig_line=orig_line:gsub("^([^@]+)", function(n) return module.langWrap(n,llang) end) --则把开头没有颜色标识的文字加上语言标识,
            orig_line=orig_line:gsub("@([^@]*)@([^@]+)", function(n1,n2) return module.name2color(n1,n2,llang) end) --并把颜色标识替换成有语言标识的颜色span。
        else --如果没有颜色标识,
            orig_line=module.langWrap(orig_line,llang) --则直接添加语言标识。
        end 
        html:tag('div') --在容器中创建一个div,代表一行歌词。
            :addClass('Lyrics_line') --添加Lyrics_line的class。(这个class实际上未设置。)
                :tag('div') --在div中创建一个div,用于放置歌词原文。
                    :addClass('Lyrics_original') --添加Lyrics_original的class。
                    :attr('lang', llang)
                    :cssText(lstyle) --添加设置的style。
                    :node(orig_line or '') --添加歌词文字。语言已在添加颜色时设定。
                    :done() --完成这个div。
                :tag('div') --与上面的类似,用于放置歌词译文。
                    :addClass('Lyrics_translated')
                    :cssText(rstyle)
                    :node(rlang and module.langQuote(tran[i] or '', rlang) or tran[i])
                    :done()
    end

    html:tag('div'):cssText('clear:both;') --在容器最后添加一个div,用于与下文间clear开。

    return tostring(html) --将全部HTML转换成字符串并返回。这里是全部程序的输出结果。
end

function module.lyrics(frame) --改写自[[moegirl:Module:Lyrics]]的.lyrics。取用参数并进行计算。
    --将取用参数的步骤单独列成函数,是为了让模块可以直接取用模板的参数,而使用其他方法取用参数不受此影响。
    local args = getArgs(frame, {wrappers='Template:Lyrics'}) --获取传入参数。
    --wrappers意味着会优先在此部分中查找参数;如果找不到,再使用frame提供的参数。
    --在此例中,这可以使模块直接取用模板参数。
    return module._lyrics(args)
end

return module --返回module,也就是返回模块中定义的所有函数的库。
--使用#invoke调用模块时,第一参数为调用模块中的哪个函数。在此模块中为lyrics。