模組:沙盒/Artoria2e5/Infobox artist/doc

此頁面為 Module:沙盒/Artoria2e5/Infobox artist 的說明文件

本模塊用於執行{{藝人}}和{{Infobox artist}}模板,請到模板頁閱讀具體用法。

貢獻指南

目前這個模板最重要的事情就是要抄參數填參數。常用的語法和翻譯結果如下所列:

-- 帮手函数
local function _(str)
    if str ~= nil and str ~= '' then
        return str
    else
        return nil
    end
end

-- 这里演示给定参数调用模板 func 的方法,也是给下面 {{func}} 铺垫
local function func(args)
    return frame:expandTemplate{title = 'func', args = args}
end

--[[
Lua                        -- MediaWiki
]]--
_(a) or _(b) or _(c) or '' -- {{{a|{{{b|{{{c|}}}}}}}}}
_(foo) or '{{{foo}}}'      -- {{{foo}}}
_(foo) and 'a' or 'b'      -- {{#if:{{{foo|}}}|a|b}}
_(foo):lower()             -- {{lc:{{{foo|}}}}}
func({                     -- {{func
    ["1"] = 'anon_1',      --   | anon_1
    ["k"] = 'v',           --   | k = v
    ["2"] = 'anon_2'       --   | anon_2 <!-- | 2 = anon_2 -->
})                         -- }}

當然,由於我們處理的是實際傳來的參數,其實還是要用args['a']獲取參數,而不是處理現有的變量a。像ifeq這樣的解析器函數其實也不難,看手冊就好了。至於Lua語言的語法,這個官方自有教程,也不難。

arg_aliases

如果表格key部分的參數查找args找不到,那麼會按照接下來key指向的備選列表一個個尋找候選內容。也就是說:

    ["foo"] = {"某", "baaar", "baz"}, -- 对应于 {{{foo|{{{某|{{{baaar|{{{baz|}}}}}}}}}}}}

多換幾處,是不是整潔多了?

只可在模板中的所有對某變量的引用都以同種順序出現時在arg_aliases加入內容。按照前面對此功能的描述,你很容易就會想通一件事——以後取這套變量,只能用頭上作為key的那個字串的名字取,否則就得不到後備查找的加成。

實現上,這個模塊用Lua metatable(元表)在args上面多玩了一層,實現了按照arg_aliases一個個順序找候選參數。Lua允許給表格添加一個元表屬性,決定特定函數的行為。例如,__index(table, key)這個函數,會在查找不到table[key]的時候蹦出來繼續嘗試查找。

現在我們一步步把註釋為「magic」的地方拆開看:

    local oldArgsMeta = getmetatable(args) or {}         -- 保留旧 metatable。MediaWiki 传入的参数列表据说是用了 metatable。
    local newArgsMeta = {}                               -- 准备一个新的。
    for k, v in ipairs(oldArgsMeta) do                   -- 把旧的都复制过去。之所以不用旧的是因为担心可能只读。
        newArgsMeta[k] = v
    end
    newArgsMeta.__index = function (t, k)                -- 开始定义新的 __index 函数。
    	if oldArgsMeta.__index ~= nil then                 -- 如果旧的里面有 __index(这里旧的能在这个函数里面用到是因为 Lua 的闭包(closure))
    	    local val = oldArgsMeta.__index(t, k)            -- 我们试着用一下
    	    if val ~= nil then                               -- 如果取到了
                return val                                     -- 那就是它了,返回(return)就好
            end
        end
        for _, v in ipairs(arg_aliases[k] or {}) do        -- 对于每个在 arg_aliases 里面查到的 k 的后备 v
            if t[v] ~= nil and t[v] ~= '' then               -- 如果取到了 t[v] 且非空字符串(后者是 MediaWiki 模板参数的要求)
                return t[v]                                    -- 就是它了
            end
        end
        return nil                                         -- 没找着
    end
    setmetatable(args, newArgsMeta)                      -- 把新的 metatable 套上去,完事儿

這個實現有趣的地方在於t[v]這裏本身還有可能再回到__index函數,也就是說之前的arg_aliases可以有遞歸查找的結構。