Module:Loader

require('Module:MultiRequire') local table, string, _ = multiRequire('Module:Table', 'Module:String', 'Module:LibraryUtil') local require, pcall = require, pcall

local p = {} p.registry = {} local loadable = table.Set{ 'bit32', 'libraryUtil', 'ustring', 'luabit.hex', 'luabit.bit', } local stack = table.slice(string.split(debug.traceback(''), '\n\t'), 1, 3) local moduleName = (not stack[2]:match('mw.lua:487:') and stack[2] or stack[1]):match('^(.+):%d+:.+')

local function formatError(e, module, path) if type(e) ~= 'string' then return nil end if e:match('not found') then return ('Module %q was not found (in path %q)'):format(module, path) elseif e:match('loop') then return ('Loop or previous error loading module %q'):format(module) elseif e:match('^Module:') then return ('Exception in loading module %q at line %s: %s'):format(module, e:match('^Module:%w+:(%d+)'), e:gsub('^Module:%w+:%d+:%s*', '')) end end

- -- function: .require(...modules: table |string[]) -- -- Loads the listed modules. Accepts relative paths - function p.require(...) local args = { ... }	local ret = {} local options local doUnpack = true if type(args[1]) == 'table' then args = args[1] doUnpack = false end if type(args[2]) == 'table' then options = args[2] end options = options or {} for i, path in ipairs(args) do		local oldPath = path path = p.resolvePath(path, moduleName) if p.registry[path] then args[i] = p.registry[path] else local success, res = pcall(require, path) assertTrue(success, formatError(res, path, oldPath), 2) args[i] = res p.registry[path] = res end end if doUnpack then return unpack(args) else return args end end

- -- function: .resolveRelativePath(relativePath: string, basePath: string) -- -- Resolves a relative path based on `basePath`. - function p.resolvePath(relativePath, basePath) checkType(1, relativePath, 'string') checkType(2, basePath, 'string') if not loadable[relativePath] and not loadable[basePath] then relativePath = relativePath:gsub('^Module:', '') basePath = basePath:gsub('^Module:', '') end local oldBase = string.split(basePath, "/") local ret = {} local parts = string.split(relativePath, "/") for i = 1, #parts, 1 do if parts[i] ~= "." then if parts[i] == ".." then if oldBase[i] then table.push(ret, oldBase[i]) end else table.push(ret, parts[i]) end else table.mergeRight(ret, oldBase) end end return 'Module:'..table.concat(ret, "/"); end _G.loader = p

return p