Module:Dev/Entrypoint
Jump to navigation
Jump to search
Documentation for this module may be created at Module:Dev/Entrypoint/doc
--- Entrypoint templating wrapper for Scribunto packages. -- The module generates an entrypoint function that can execute Scribunto -- package calls in the template context. This allows a package to support -- both direct and template invocations. -- -- @script entrypoint -- @release stable -- @author [[User:8nml|8nml]] -- @param {table} package Scribunto package. -- @error[85] {string} 'you must specify a function to call' -- @error[91] {string} 'the function you specified did not exist' -- @error[opt,95] {string} '$2 is not a function' -- @return {function} Template entrypoint - @{main}. -- @note Parent frames are not available in Entrypoint's -- `frame`. This is because recursive (grandparent) -- frame access is impossible in legacy Scribunto -- due to [[mw:Manual:Parser#Empty-argument expansion -- cache|empty-argument expansion cache]] limitations. -- @note As Entrypoint enables template access rather than -- a new extension hook, it does not work with named -- numeric parameters such as `1=` or `2=`. This may -- result in unexpected behaviour such as Entrypoint -- and module errors. --- Stateless, sequential Lua iterator. -- @function inext -- @param {table} t Invariant state to loop over. -- @param {number} i Control variable (current index). -- @return[opt] {number} Next index. -- @return[opt] {number|string|table|boolean} Next value. -- @see [[github:lua/lua/blob/v5.1.1/lbaselib.c#L247]] local inext = select(1, ipairs{}) --- Check for MediaWiki version 1.25. -- The concurrent Scribunto release adds a type check for package functions. -- @variable {boolean} func_check -- @see [[mw:MediaWiki 1.24/wmf7#Scribunto]] local func_check = tonumber(mw.site.currentVersion:match('^%d+.%d+')) >= 1.25 --- MediaWiki error message getter. -- Mimics Scribunto error formatting for script errors. -- @function msg -- @param {string} key MediaWiki i18n message key. -- @param[opt] {string} fn_name Name of package function. -- @return {string} Formatted lowercase message. -- @local local function msg(key, fn_name) return select(1, mw.message.new(key) :plain() :match(':%s*(.-)[.۔。෴։።]?$') :gsub('^.', mw.ustring.lower) :gsub('$2', fn_name or '$2') ) end --- Template entrypoint function generated by this module. -- @function main -- @param {Frame} frame Scribunto frame in module context. -- @return {string} Module output in template context. return function(package) return function(f) local frame = f:getParent() local args_mt = {} local arg_cache = {} args_mt.__pairs = function() return next, arg_cache, nil end args_mt.__ipairs = function() return inext, arg_cache, 0 end args_mt.__index = function(t, k) return arg_cache[k] end for key, val in pairs(frame.args) do arg_cache[key] = val end local fn_name = table.remove(arg_cache, 1) f.args = setmetatable({}, args_mt) frame.args = setmetatable({}, args_mt) if not fn_name then error(msg('scribunto-common-nofunction')) end fn_name = mw.text.trim(fn_name) if not package[fn_name] then error(msg('scribunto-common-nosuchfunction', fn_name)) end if func_check and type(package[fn_name]) ~= 'function' then error(msg('scribunto-common-notafunction', fn_name)) end return package[fn_name](frame) end end