Module:Lua
From Liquipedia Commons Wiki
Some functions for checking the existence of modules and loading them.
API[edit]
- Programmatic name: Lua
- moduleExists(name: string) → boolean
Checks if a Module with the name exists.
- requireIfExists(name: string, options: table) → Module require or default
Requires the Module if it exists and returns the default otherwise.
- loadDataIfExists(name: string) → Module data or default
Loads the Module data if the Module exists and returns the default otherwise.
- import(name: string, options: table?) → Module
Imports a module by name.
See all our documentation here.
The above documentation is transcluded from Module:Lua/doc. (edit | history) Editors can experiment in this module's sandbox (create | mirror) and testcases (edit | run) pages. Subpages of this module. |
--- -- @Liquipedia -- wiki=commons -- page=Module:Lua -- -- Please see https://github.com/Liquipedia/Lua-Modules to contribute -- local FeatureFlag = require('Module:FeatureFlag') local Logic = require('Module:Logic') local StringUtils = require('Module:StringUtils') local Lua = {} ---Checks for the existence of a Lua module ---@param name string ---@return boolean function Lua.moduleExists(name) if package.loaded[name] then return true else -- Package.Searchers was renamed from Loaders in lua5.2, have support for both ---@diagnostic disable-next-line: deprecated for _, searcher in ipairs(package.searchers or package.loaders) do local loader = searcher(name) if type(loader) == 'function' then -- luacheck: ignore -- luacheck complains about package.preload being read-only package.preload[name] = loader return true end end return false end end ---Imports a module if it exists by its name. --- ---By default it will include the /dev module if in dev mode activated. This can be turned off by setting --- the requireDevIfEnabled option to false. ---@param name string ---@param options {requireDevIfEnabled: boolean, loadData: boolean?}? ---@return unknown? function Lua.requireIfExists(name, options) if Lua.moduleExists(name) then return Lua.import(name, options) end end ---Loads (mw.loadData) a data module if it exists by its name. ---@deprecated use `Lua.requireIfExists` with `loadData` option instead ---@param name string ---@return unknown? function Lua.loadDataIfExists(name) mw.ext.TeamLiquidIntegration.add_category('Pages using deprecated Lua.loadDataIfExists function') return Lua.requireIfExists(name, {loadData = true}) end ---Imports a module by its name. ---By default it will include the /dev module if in dev mode activated. This can be turned off by setting --- the requireDevIfEnabled option to false. --- Optionally mw.loaddata can be used instead of require by passing the loadData option. ---@param name string ---@param options {requireDevIfEnabled: boolean?, loadData: boolean?}? ---@return unknown function Lua.import(name, options) options = options or {} local importFunction = options.loadData and mw.loadData or require if options.requireDevIfEnabled ~= false then if StringUtils.endsWith(name, '/dev') then error('Lua.import: Module name should not end in \'/dev\'') end local devFlag = FeatureFlag.get('dev') if not devFlag then return importFunction(name) end local devName = name .. '/dev' .. (type(devFlag) == 'string' and ('/' .. devFlag) or '') if require('Module:Namespace').isMain() then mw.ext.TeamLiquidIntegration.add_category('Pages using dev modules') end if Lua.moduleExists(devName) then return importFunction(devName) else return importFunction(name) end else return importFunction(name) end end --[[ This function intended to be #invoke'd from wikicode. Invokes a function inside a module or a dev module depending on the dev feature flag. Can also set the dev feature flag inside the function scope by passing dev=1. The following 3 code snippets are equivalent, assuming that Module:Magpie/dev exists and that feature_dev is unset previously. {{#invoke:Lua|invoke|module=Magpie|fn=theive|foo=3|dev=1}} {{#vardefine:feature_dev|1}} {{#invoke:Magpie/dev|theive|foo=3}} {{#vardefine:feature_dev|}} require('Module:FeatureFlag').set('dev', true) require('Module:Magpie/dev').theive({args = {foo = 3}}) require('Module:FeatureFlag').set('dev', nil) ]] ---@param frame Frame ---@return unknown function Lua.invoke(frame) local moduleName = frame.args.module local fnName = frame.args.fn assert(moduleName, 'Lua.invoke: args.module is missing') assert(fnName, 'Lua.invoke: args.fn is missing') assert( not StringUtils.endsWith(moduleName, '/dev'), 'Lua.invoke: Module name should not end in \'/dev\'' ) assert( not StringUtils.startsWith(moduleName, 'Module:'), 'Lua.invoke: Module name should not begin with \'Module:\'' ) frame.args.module = nil frame.args.fn = nil local getDevFlag = function(startFrame) local currentFrame = startFrame while currentFrame do if currentFrame.args.dev ~= nil then if Logic.readBoolOrNil(currentFrame.args.dev) ~= nil then return Logic.readBool(currentFrame.args.dev) else return currentFrame.args.dev end end currentFrame = currentFrame:getParent() end end local devFlag = getDevFlag(frame) local flags = {dev = devFlag} return FeatureFlag.with(flags, function() local module = Lua.import('Module:' .. moduleName) local context = {baseModuleName = 'Module:' .. moduleName, module = module} return Lua.withPerfSetup(context, function() return Lua.callAndDisplayErrors(module[fnName], frame, devFlag) end) end) end ---@param fn function ---@param frame Frame ---@param hardErrors boolean|string? ---@return string function Lua.callAndDisplayErrors(fn, frame, hardErrors) local ErrorDisplay = require('Module:Error/Display') local ErrorExt = require('Module:Error/Ext') local result = Logic.tryOrElseLog(function() return fn(frame) end) local parts = result and {tostring(result)} or {} local errors = ErrorExt.Stash.retrieve() if #errors > 0 then if hardErrors then for _, error in ipairs(errors) do table.insert(parts, tostring(ErrorDisplay.ClassicError(error))) end else table.insert(parts, tostring(ErrorDisplay.ErrorList{errors = errors})) end if mw.title.getCurrentTitle().namespace == 2 then mw.ext.TeamLiquidIntegration.add_category('User pages with script errors') else mw.ext.TeamLiquidIntegration.add_category('Pages with script errors') end end return table.concat(parts) end ---Automatically sets up performance instrumentation if using Lua.invoke ---@param context {baseModuleName: string, module: unknown} ---@param f fun(): ... ---@return ... function Lua.withPerfSetup(context, f) if FeatureFlag.get('perf') then require('Module:Performance/Util').startFromInvoke(context) end local function post(...) if FeatureFlag.get('perf') then require('Module:Performance/Util').stopAndSave() end return ... end return post(f()) end return Lua