跳转到内容

模組:Vgname/sandbox

维基百科,自由的百科全书
--- For supplementing {{vgname}}. Under construction, see [[Template:Vgname/testcases]].

require("strict")

local str = mw.ustring

local getArgs = require("Module:Arguments").getArgs
local yesno = require("Module:Yesno")

local language_data = mw.loadData("Module:Vgname/languages")

--- @alias TemplateParameterKey string | number
--- @alias Args table<TemplateParameterKey, string> The arguments pre-handled by getArgs.

--[==[
********** UTILITIES **********
]==]

--- Call a MediaWiki template and expand it.
---
--- This function takes a template name and a table of arguments, then returns the parsed result of the template call.
---
--- @param title string The name of the MediaWiki template to call.
--- @param args table<TemplateParameterKey, any> A table containing the arguments to pass to the template.
--- @return string # The parsed result of the template call.
local function template(title, args)
    return mw.getCurrentFrame():expandTemplate {title = title, args = args}
end

--- Simulating Python's `bool()` function, converts a given object to a boolean value.
--- The following values are regarded as empty: false, nil, '', 0, and {}.
---
--- @param object any The object to be converted to a boolean.
--- @return boolean # The boolean value of the object.
local function isempty(object)
    local object_type = type(object)
    if object_type == "boolean" then
        return object
    end
    if object_type == "nil" then
        return false
    end
    if object_type == "string" then
        return object ~= ""
    end
    if object_type == "number" then
        return object ~= 0
    end
    if object_type == "table" then
        for _, _ in pairs(object) do
            return true
        end
        return false
    end
    return true
end

--- Applies bold markup to the text according to the flag.
--- * If the flag is falsy, the text is returned as is.
--- * Otherwise (including nil), the text is wrapped in bold wikicode.
---
--- @param text string The text to be processed.
--- @param flag string | boolean | nil The flag that determines whether to apply bold markup.
--- @return string # The processed text with or without bold markup.
local function with_bold(text, flag)
    if yesno(flag) == false then
        return text
    end
    return "'''" .. text .. "'''"
end

--- Applies italic markup to the text according to the flag.
--- * If the flag is truly, the text is wrapped in italic wikicode.
--- * Otherwise, the text is returned as is.
---
--- @param text string The text to be processed.
--- @param flag string | boolean | nil The flag that determines whether to apply italic markup.
--- @return string # The processed text with or without italic markup.
local function with_italic(text, flag)
    if yesno(flag) then
        return text
    end
    return "''" .. text .. "''"
end

--- Applies bracket pair to the text according to the flag.
--- * If the flag is truly or nil, the text is wrapped in double book title marks (《...》).
--- * If the flag is falsy, the text is returned as is.
--- * If the flag is 'q', the text is wrapped in quotation marks (「...」).
--- * If the flag is a comma-separated pair, the text is wrapped in this pair.
--- * Otherwise, the Mediawiki template named after the flag is called, with the text as unnamed parameter 1 (e.g., {{單雙書名號轉換}}).
---
--- @param text string The text to be processed.
--- @param flag string | boolean | nil The flag that determines what the kind of mark to apply.
--- @return string # The processed text with or without the marks pair.
local function with_bracket(text, flag)
    if yesno(flag) == true then
        return "《" .. text .. "》"
    end
    if flag == nil then
        return "《" .. text .. "》"
    end
    if yesno(flag) == false then
        return text
    end
    if flag == "q" then
        return "「" .. text .. "」"
    end
    local _, _, open, close = str.find(flag, "^([^|]+),%s-(.+)$")
    if open then
        return open .. text .. close
    end
    return template(flag, {text})
end

--- Applies an inline content conversion tag to the text according to the flag.
--- * If the flag is falsy, the text is returned as is (i.e., allowed to be automatical converted).
--- * If the flag is 'strict', the text is wrapped in no convertion tag (-{...}-).
--- * Otherwise, the text is wrapped in character-based convention tag (-{zh-hans; zh-hant;|...}-).
---
--- @param text string The text to be processed.
--- @param flag string | boolean | nil The flag that determines the type of conversion label to apply.
--- @return string # The processed text with or without the conversion tag.
local function with_conversion_tag(text, flag)
    if yesno(flag) == false then
        return text
    end
    if flag == "strict" then
        return "-{" .. text .. "}-"
    end
    return "-{zh-hans; zh-hant;|" .. text .. "}-"
end

--- Splits the given wikicode into two parts: the text and the suffix reference tags.
---
--- @param text string The wikicode to be split.
--- @return string # The text before the reference tag.
--- @return string | nil # The reference tag, or nil if no reference tag is found.
local function split_refs(text)
    local ref_ptn = '\127\'"`UNIQ%-%-[Rr][Ee][Ff]%-%x+%-QINU`$"\'\127' -- [[:en:WP:UNIQ]]
    local pos = string.find(text, ref_ptn)
    if pos then
        return str.sub(text, 1, pos - 1), str.sub(text, pos)
    end
    return text, nil
end

--[==[
********** COMPONOENT BUILDERS **********
]==]

--- Builds the head part with bold and bracket markup.
---
--- @param args Args Template arguments.
--- @return string #The formatted head part.
local function build_head(args)
    local text, refs = split_refs(args[1])
    text = with_bold(text, args.bold)
    text = with_bracket(text, args.bracket)

    local result = text
    if isempty(refs) then
        result = result .. refs
    end
    return result
end

-- TODO: the original name section
-- TODO: [[Talk:土豆兄弟#Infobox写法]]

--- Retrieves the foreign definition based on an optional language code.
--- * If the `code` is given: First, it returns the definition if the code exists as a
--- key in the configuration table. Otherwise, it iterates through the list part of the
--- table to find a matching `langcode`.
--- * If the `code` is not given: It iterates through the list part of the table and
--- returns the definition if there is a parameter that matches the langcode of the
--- definition.
---
--- @param args Args
--- @param code string | nil The optional language code to look for.
--- @return table | nil # The matched foreign language definition table or nil.
local function get_foreign_definition(args, code)
    if code ~= nil then
        if language_data[code] then
            return language_data[code]
        end
        for _, v in ipairs(language_data) do
            if code == v.langcode then
                return v
            end
        end
        return nil
    end
    for _, v in ipairs(language_data) do
        for param in pairs(args) do
            if param == v.langcode then
                return v
            end
        end
    end
    return nil
end

--- Evaluates whether there is a definition indicating a difference in meaning between
--- the original foreign name and its English version.
--- * If `|diff=` has been assigned, it returns a boolean value depending on that.
--- * If either `|na=` or `|eu=` has been set, it returns true.
--- * Otherwise, it returns false.
---
--- @param args Args The arguments table to be evaluated.
--- @return boolean # The result of the evaluation.
local function get_diff_flag(args)
    local yesno_diff_arg = yesno(args)
    if yesno_diff_arg ~= nil then
        return yesno_diff_arg
    end
    if isempty(args.na) or isempty(args.eu) then
        return true
    end
    return false
end

-- TODO: the translation name section
-- TODO: the extend translation name section
-- TODO: the note section
-- TODO: the footnote function

---------- MAIN FUNCTION ----------

local p = {}

function p.vgname(frame)
    local args = getArgs(frame)
    return p._vgname(args)
end

function p._vgname(args)
    local result = ""
    local head = build_head(args)
    local foreign_definition = get_foreign_definition(args)
    local label = foreign_definition and foreign_definition.langcode or ""
    result = head .. label
    return result
end

return p