跳转到内容

模組:Hatnote only

维基百科,自由的百科全书
require("strict")

local getArgs = require("Module:Arguments").getArgs
local lc = require("Module:WikitextLC")

local BLANK = mw.getCurrentFrame():callParserFunction("#tag:nowiki")

local SHORT_VARIANTS = {
    cn = "zh-cn",
    hans = "zh-hans",
    hant = "zh-hant",
    hk = "zh-hk",
    mo = "zh-mo",
    my = "zh-my",
    sg = "zh-sg",
    tw = "zh-tw",
}

local VARIANT_FAMILY = {
    ["zh-cn"] = "hans",
    ["zh-hans"] = "hans",
    ["zh-my"] = "hans",
    ["zh-sg"] = "hans",
    ["zh-hant"] = "hant",
    ["zh-hk"] = "hant",
    ["zh-mo"] = "hant",
    ["zh-tw"] = "hant",
}

local OPPOSITE_FALLBACK = {
    hans = "zh-tw",
    hant = "zh-cn",
}

local SINGLE_MODE_KEYS = {
    [1] = true,
    [2] = true,
    hide = true,
    show = true,
}

local function normalize_variant(code)
    code = mw.text.trim(code):lower()

    if code == "" then
        return nil
    end

    return SHORT_VARIANTS[code] or code
end

local function parse_variants(value)
    if not value or mw.text.trim(value) == "" then
        return {}
    end

    local variants = {}
    local seen = {}

    for _, code in ipairs(mw.text.split(value, ",")) do
        local variant = normalize_variant(code)

        if variant and not seen[variant] then
            seen[variant] = true
            variants[#variants + 1] = variant
        end
    end

    return variants
end

local function all_in_family(variants, family)
    if #variants == 0 then
        return false
    end

    for _, variant in ipairs(variants) do
        if VARIANT_FAMILY[variant] ~= family then
            return false
        end
    end

    return true
end

local function is_single_mode(args)
    for key in pairs(args) do
        if not SINGLE_MODE_KEYS[key] then
            return false
        end
    end

    return true
end

local function normalize_args(args)
    if not is_single_mode(args) then
        return args
    end

    local show = args.show
    if not show or show == "" then
        show = args[2]
    end

    return {
        args[1],
        hide1 = args.hide,
        show1 = show,
    }
end

local function set_variant_content(variant_dict, variant, content)
    if variant == "zh" then
        variant_dict.zh = content
        return
    end

    variant_dict[variant] = lc.converted(content, variant)
end

local function parse_rule(content, show, hide, index)
    local shown_variants = parse_variants(show)

    if #shown_variants == 0 then
        error("Missing show" .. index .. " parameter.", 2)
    end

    local hidden_variants = parse_variants(hide)
    local variant_dict = {
        -- Show all hatnotes in the no-conversion maintenance mode.
        zh = content,
    }

    for _, variant in ipairs(shown_variants) do
        set_variant_content(variant_dict, variant, content)
    end

    local family
    if all_in_family(shown_variants, "hans") then
        family = "hans"
    elseif all_in_family(shown_variants, "hant") then
        family = "hant"
    end

    if family then
        hidden_variants[#hidden_variants + 1] =
            OPPOSITE_FALLBACK[family]
    end

    -- Apply hide rules last so explicit hiding overrides showing.
    for _, variant in ipairs(hidden_variants) do
        set_variant_content(variant_dict, variant, BLANK)
    end

    return lc.selective(variant_dict)
end

local function get_item_indices(args)
    local indices = {}

    for key, value in pairs(args) do
        if type(key) == "number" and value ~= nil then
            indices[#indices + 1] = key
        end
    end

    table.sort(indices)
    return indices
end

local function main(args)
    args = normalize_args(args)

    local items = {}

    for _, index in ipairs(get_item_indices(args)) do
        items[#items + 1] = parse_rule(
            args[index],
            args["show" .. index],
            args["hide" .. index],
            index
        )
    end

    return table.concat(items)
end

local p = {}

function p._main(args)
    return main(args)
end

function p.main(frame)
    return p._main(getArgs(frame))
end

return p