模块:文本切换显示

来自维阿百科
霓虹灯鱼讨论 | 贡献2022年7月8日 (五) 21:16的版本 (导入1个版本)
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳转至: 导航搜索

此模块的文档可以在模块:文本切换显示/doc创建

-- luacheck: globals mw
local module = {}

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

--[[
    对分支进行排序。
    -----
    branches: 所有要排序的参数,其中部分是分支参数。
    sortProvider: 其中仅以"@#"开头后紧跟数字的值键对作为排序参考。
--]]
local sortBranches = function(branches, sortProvider)
    sortProvider = sortProvider or branches -- 参数和排序参考写在同一个表的情况。

    local sortKeys = {}
    local result = {}
    for k, v in pairs(sortProvider) do
        v = mw.text.trim(v)
        if type(k) == 'string' and v ~= '' then -- 初步筛选k和v。
            local index = tonumber(mw.ustring.match(k, '^@#(%d+)$'))
            if index ~= nil and index >= 1 then -- 最终筛选k。
                result[index] = {v, branches[v]} -- 赋值明确指定位置的参数。
                sortKeys[v] = true -- 记录已排序的参数。
                sortProvider[k] = nil -- 清除排序记录。
            end
        end
    end

    local index = 1
    for k, v in pairs(branches) do
        if not sortKeys[k] then
            while result[index] do
                index = index + 1
            end -- 找到下一个可用的位置。
            result[index] = {k, v} -- 按照默认顺序赋值
        end
    end

    return ipairs(result)
end

local initSpan = function(className, templateName, frame)
    local span = mw.html.create('span')
    span:attr('class', className)

    local sortedBranchProvider = {
        sortBranches(
            getArgs(
                frame,
                {
                    wrappers = 'Template:' .. templateName
                }
            )
        )
    }

    if className == 'textToggleDisplayButtons' then -- 自Template:切换显示调用。
        local operators = {} -- 操作参数。
        local contentlist = {} --[[内容表列。结构为:
                                                {
                                                    strcode = 字符串代号,
                                                    on = @on后缀的内容,
                                                    off = @off后缀的内容,
                                                    default = 没有@on或@off后缀的内容,
                                                }
                                            ]]
        for _, pair in unpack(sortedBranchProvider) do
            local k, v = unpack(pair)
            k = tostring(k) -- 数字类型的字符串代号。
            if v ~= nil then
                if mw.ustring.sub(k, 1, 1) == '@' then
                    operators[k] = v
                else
                    local strcode
                    local onoff = nil
                    -- 获取字符串代号和开关类型。
                    if mw.ustring.sub(k, -3) == '@on' then
                        strcode = mw.ustring.sub(k, 1, mw.ustring.len(k) - 3)
                        onoff = 'on'
                    elseif mw.ustring.sub(k, -4) == '@off' then
                        strcode = mw.ustring.sub(k, 1, mw.ustring.len(k) - 4)
                        onoff = 'off'
                    else
                        strcode = k
                    end
                    onoff = onoff or 'default' -- 没有开关类型就是默认值。

                    if not contentlist[strcode] then
                        table.insert(contentlist, {strcode = strcode}) -- 增加空的内容表。
                        contentlist[strcode] = #contentlist -- 定位新增加的索引,绑定到参数k。
                    end
                    contentlist[contentlist[strcode]][onoff] = v -- 替换内容。
                end
            end
        end

        local counter = 0 -- 计数器。
        for k_operators, v_operators in pairs(operators) do
            span:attr('data-key-' .. counter, k_operators):attr('data-value-' .. counter, v_operators)
            counter = counter + 1
        end

        for index, content in ipairs(contentlist) do
            span:tag('span'):attr('data-order', index - 1):attr('data-key', content.strcode):tag('span'):addClass(
                'textToggleDisplayButtonLabelText on'
            ):wikitext(frame:preprocess(content.on or content.default)):done():tag('span'):addClass(
                'textToggleDisplayButtonLabelText off'
            ):wikitext(frame:preprocess(content.off or content.default))
            -- counter = index + 1 -- 获取最新的下一个索引。
        end
    else
        local counter = 0 -- 计数器
        for _, pair in unpack(sortedBranchProvider) do
            local k, v = unpack(pair) -- 拆包
            if v ~= nil then
                span:attr('data-key-' .. counter, k):attr('data-value-' .. counter, v)
                counter = counter + 1
            end
        end
    end

    return tostring(span)
end

function module.template(frame)
    local args =
        getArgs(
        frame,
        {
            wrappers = 'Template:切换显示/模板'
        }
    )

    local tTitle = args['@'] or ''
    if tTitle == '' then
        return nil
    end
    local tag = args['@tag']

    local branches = {}
    local params = {}
    for k, v in pairs(args) do
        k = tostring(k)
        if not mw.ustring.match(k, '^@[^@]') then
            local i = 1
            while true do
                local _, j, flag = mw.ustring.find(k, '@(.)', i)
                if j == nil then
                    i = mw.ustring.len(k)
                    break
                elseif flag == '@' then
                    i = j + 1
                else
                    i = j - 2
                    break
                end
            end

            local param = mw.text.trim(mw.ustring.gsub(mw.ustring.sub(k, 1, i), '@@', '@'))
            local branch = mw.ustring.sub(k, i + 2)
            if mw.text.trim(param) ~= '' then
                if params[param] == nil then
                    params[param] = {}
                end
                if branch ~= '' and branches[branch] == nil then
                    branches[branch] = #branches + 1
                    table.insert(branches, branch)
                end
                if branch == '' then
                    params[param][0] = v
                else
                    params[param][branch] = v
                end
            end
        end
    end

    local result = {}
    for _, pair in sortBranches(branches, args) do
        local branch, _ = unpack(pair)
        if type(branch) == 'string' then
            local tArgs = {}
            for param, bValue in pairs(params) do
                tArgs[param] = bValue[branch] or bValue[0]
            end

            table.insert(
                result,
                frame:expandTemplate {
                    title = '切换显示',
                    args = {
                        [1] = branch,
                        [2] = frame:expandTemplate {title = tTitle, args = tArgs},
                        [3] = tag
                    }
                }
            )
        end
    end

    return table.concat(result)
end

function module.button(frame)
    return initSpan('textToggleDisplayButtons', '切换显示按钮', frame)
end

function module.style(frame)
    return initSpan('textToggleDisplayStyle', '切换显示样式', frame)
end

function module.buttonStyle(frame)
    return initSpan('textToggleDisplayButtonsStyle', '切换显示按钮样式', frame)
end

return module