Module:Rainbow

From Moegirlpedia
Revision as of 16:03, 18 November 2023 by LiaMinina (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
Template-info.svg Module Documentation  [Create] [Refresh]
local module = {}

local getArgs = require('Module:Arguments').getArgs

function module._main(colors, material)
    local rubySave = {}
    material = mw.ustring.gsub(material, '(<ruby[^>]*>.-</ruby>)', function(str)
        rubySave[#rubySave + 1] = str
        return 'Ÿ'
    end)
    
    local htmlEscapeSave = {}
    local htmlEscapeSaveFunc = function(str)
        htmlEscapeSave[#htmlEscapeSave + 1] = str
        return 'Æ'
    end
    material = mw.ustring.gsub(material, '&#%d+;', htmlEscapeSaveFunc)
    material = mw.ustring.gsub(material, '&[A-Za-z]+;', htmlEscapeSaveFunc)
    
    function lang(ptns)
        for i, v in ipairs(ptns) do
            material = mw.ustring.gsub(material, '(.*%-{)ῧ?(.-)(;?%s-'..v..':)(.-}%-)', function(str0, str1, str2, str3)
                -- Use the ῧ instruction to keep the current color
                -- Use Ῥ to indicate that this is the start of the next language variant, reading colors
                return str0..'ῧ'..str1..mw.ustring.gsub(str2, '(.)', '‡%1')..'Ῥ'..str3
            end)
        end
    end

    lang({
        'zh%-hans', 'zh%-hant', 'zh%-cn', 'zh%-tw', 'zh%-hk', 'zh%-sg', 'zh%-mo', 'zh%-my', 'zh'
    })

    function flee(ptns)
        for i, v in ipairs(ptns) do
            material = mw.ustring.gsub(material, '('..v..')', function(str)
                return mw.ustring.gsub(str, '(.)', '‡%1')
            end)
        end
    end

    flee({
        -- the html tag or mw markup should be treated as a whole, no separate color change
        '<.->', '%-{', '}%-', '\'\"\`UNIQ%-.-%-QINU\`\"\''
    })

    local flag = 1            -- Color change count
    local ZhConverter_old_flag = 1    -- 字词转换中上一个语言变种的flag
    local ruby = 1            -- ruby count
    local htmlEscape = 1      -- HTML escape character count
    local mark = false        -- Mark skip
    local rainbow = mw.ustring.gsub(material, '[^%s]', function(str1)
        if str1 == 'ῧ' then
            ZhConverter_old_flag = flag
            return ''
        end
        if str1 == 'Ῥ' then
            flag = ZhConverter_old_flag
            return ''
        end
        if str1 == '‡' then
            mark = true
            return ''
        end
        if str1 == 'Æ' then
            htmlEscape = htmlEscape + 1
            return htmlEscapeSave[htmlEscape - 1]
        end
        if mark then
            mark = false
            return str1
        end

        local colour = ''
        if str1 ~= 'Ÿ' then
            colour = '<span style="color:'..colors[flag]..'">'..str1..'</span>'
        else
            colour = string.gsub(rubySave[ruby], '<ruby([^>]*)>', function(str2)
                if string.find(str2, 'style=".-"') then
                    return '<ruby '..string.gsub(str2, 'style="(.-)"', function(str3)
                        return 'style="'..str3..'; color:'..colors[flag]..'"'
                    end)..'>'
                else
                    return '<ruby'..str2..' style="color:'..colors[flag]..'">'
                end
            end)
            ruby = ruby + 1
        end

        if flag < #colors then
            flag = flag + 1
        else
            flag = 1
        end

        return colour
    end)

    return rainbow
end

function module.main(frame)
    local args = getArgs(frame, {wrappers='Template:CrosscolorF'})
    local colorStr = args.c or args[1]
    local material = args.s or args[2]
    local colors = mw.text.split(colorStr, ',')
    return module._main(colors, material)
end

return module