Module:DependencyList: Difference between revisionsGive feedback
osrsw>CephHunter Module:Enum -> Module:Array |
osrsw>CephHunter Add support for loadJsonData |
||
| Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
local libraryUtil = require( 'libraryUtil' ) | local libraryUtil = require( 'libraryUtil' ) | ||
| Line 11: | Line 10: | ||
local MAX_DYNAMIC_REQUIRE_LIST_LENGTH = 30 | local MAX_DYNAMIC_REQUIRE_LIST_LENGTH = 30 | ||
local dynamicRequireListQueryCache = {} | local dynamicRequireListQueryCache = {} | ||
local builtins = { | |||
["libraryUtil"] = { | |||
link = "mw:Special:MyLanguage/Extension:Scribunto/Lua reference manual#libraryUtil", | |||
categories = {}, | |||
}, | |||
["strict"] = { | |||
link = "mw:Special:MyLanguage/Extension:Scribunto/Lua reference manual#strict", | |||
categories = { "Strict mode modules" }, | |||
}, | |||
} | |||
--- Used in case 'require( varName )' is found. Attempts to find a string value stored in 'varName'. | --- Used in case 'require( varName )' is found. Attempts to find a string value stored in 'varName'. | ||
| Line 44: | Line 54: | ||
local function formatPageName( str ) | local function formatPageName( str ) | ||
local name = mw.text.trim(str) | local name = mw.text.trim(str) | ||
:gsub( '^([\'\"])(.-)%1$', | :gsub( '^([\'\"])(.-)%1$', '%2' ) -- Only remove quotes at start and end of string if both are the same type | ||
:gsub( '_', ' ' ) | :gsub( '_', ' ' ) | ||
:gsub( '^.', string.upper ) | :gsub( '^.', string.upper ) | ||
| Line 53: | Line 63: | ||
---@param str string | ---@param str string | ||
---@param allowBuiltins? boolean | |||
---@return string | ---@return string | ||
local function formatModuleName( str ) | local function formatModuleName( str, allowBuiltins ) | ||
if allowBuiltins then | |||
local name = mw.text.trim(str) | |||
-- Only remove quotes at start and end of string if both are the same type | |||
:gsub([[^(['"])(.-)%1$]], '%2') | |||
if builtins[name] then | |||
return name | |||
end | |||
end | |||
local module = formatPageName( str ) | local module = formatPageName( str ) | ||
| Line 66: | Line 87: | ||
local function dualGmatch( str, pat1, pat2 ) | local function dualGmatch( str, pat1, pat2 ) | ||
local f1 = string.gmatch( str, pat1 ) | local f1 = string.gmatch( str, pat1 ) | ||
local f2 = string.gmatch( str, pat2 ) | if pat2 then | ||
local f2 = string.gmatch( str, pat2 ) | |||
return function() | |||
return f1() or f2() | |||
end | |||
else | |||
return f1 | |||
end | end | ||
end | |||
local function isDynamicPath( str ) | |||
return string.find( str, '%.%.' ) or string.find( str, '%%%a' ) | |||
end | end | ||
| Line 75: | Line 104: | ||
--- Will return a list of pages which satisfy this pattern where 'isTheBest' can take any value. | --- Will return a list of pages which satisfy this pattern where 'isTheBest' can take any value. | ||
---@param query string | ---@param query string | ||
---@return string[] | ---@return string[] | ||
local function getDynamicRequireList( query ) | local function getDynamicRequireList( query ) | ||
if query:find( '%.%.' ) then | if query:find( '%.%.' ) then | ||
| Line 83: | Line 112: | ||
query = table.concat( query ) | query = table.concat( query ) | ||
else | else | ||
_, | local _, _query = query:match( '(["\'])(.-)%1' ) | ||
query = | query = _query:gsub( '%%%a', '%%' ) | ||
end | end | ||
query = query:gsub( '^[Mm]odule:', '' ) | query = query:gsub( '^[Mm]odule:', '' ) | ||
| Line 120: | Line 149: | ||
--- Returns a list of modules loaded and required by module 'moduleName'. | --- Returns a list of modules loaded and required by module 'moduleName'. | ||
---@param moduleName string | ---@param moduleName string | ||
---@param searchForUsedTemplates boolean | ---@param searchForUsedTemplates? boolean | ||
---@return string | ---@return table<string, string[]> | ||
local function getRequireList( moduleName, searchForUsedTemplates ) | local function getRequireList( moduleName, searchForUsedTemplates ) | ||
local content = mw.title.new( moduleName ):getContent() | local content = mw.title.new( moduleName ):getContent() | ||
local requireList = arr{} | local requireList = arr{} | ||
local loadDataList = arr{} | local loadDataList = arr{} | ||
local loadJsonDataList = arr{} | |||
local usedTemplateList = arr{} | local usedTemplateList = arr{} | ||
local dynamicRequirelist = arr{} | local dynamicRequirelist = arr{} | ||
local dynamicLoadDataList = arr{} | local dynamicLoadDataList = arr{} | ||
local dynamicLoadJsonDataList = arr{} | |||
local extraCategories = arr{} | |||
assert( content ~= nil, string.format( '%s does not exist', moduleName ) ) | assert( content ~= nil, string.format( '%s does not exist', moduleName ) ) | ||
| Line 134: | Line 166: | ||
content = content:gsub( '%-%-%[(=-)%[.-%]%1%]', '' ):gsub( '%-%-[^\n]*', '' ) -- Strip comments | content = content:gsub( '%-%-%[(=-)%[.-%]%1%]', '' ):gsub( '%-%-[^\n]*', '' ) -- Strip comments | ||
for match in dualGmatch( content, | local function getList( pat1, pat2, list, dynList ) | ||
for match in dualGmatch( content, pat1, pat2 ) do | |||
match = mw.text.trim( match ) | |||
local name = extractModuleName( match, content ) | |||
if isDynamicPath( name ) then | |||
dynList:insert( getDynamicRequireList( name ), true ) | |||
elseif name ~= '' then | |||
name = formatModuleName( name, true ) | |||
table.insert( list, name ) | |||
if builtins[name] then | |||
extraCategories = extraCategories:insert( builtins[name].categories, true ) | |||
end | |||
end | end | ||
end | end | ||
end | end | ||
getList( 'require%s*(%b())', 'require%s*((["\'])%s*[Mm]odule:.-%2)', requireList, dynamicRequirelist ) | |||
getList( 'mw%.loadData%s*(%b())', 'mw%.loadData%s*((["\'])%s*[Mm]odule:.-%2)', loadDataList, dynamicLoadDataList ) | |||
getList( 'mw%.loadJsonData%s*(%b())', 'mw%.loadJsonData%s*((["\'])%s*[Mm]odule:.-%2)', loadJsonDataList, dynamicLoadJsonDataList ) | |||
getList( 'pcall%s*%(%s*require%s*,([^%),]+)', nil, requireList, dynamicRequirelist ) | |||
getList( 'pcall%s*%(%s*mw%.loadData%s*,([^%),]+)', nil, loadDataList, dynamicLoadDataList ) | |||
getList( 'pcall%s*%(%s*mw%.loadJsonData%s*,([^%),]+)', nil, loadJsonDataList, dynamicLoadJsonDataList ) | |||
if searchForUsedTemplates then | if searchForUsedTemplates then | ||
| Line 218: | Line 232: | ||
end | end | ||
requireList = requireList .. dynamicRequirelist | requireList = requireList .. dynamicRequirelist | ||
requireList = requireList:unique() | requireList = requireList:unique() | ||
loadDataList = loadDataList .. dynamicLoadDataList | loadDataList = loadDataList .. dynamicLoadDataList | ||
loadDataList = loadDataList:unique() | loadDataList = loadDataList:unique() | ||
loadJsonDataList = loadJsonDataList .. dynamicLoadJsonDataList | |||
usedTemplateList = usedTemplateList:unique() | usedTemplateList = usedTemplateList:unique() | ||
extraCategories = extraCategories:unique() | |||
table.sort( requireList ) | table.sort( requireList ) | ||
table.sort( loadDataList ) | table.sort( loadDataList ) | ||
table.sort( loadJsonDataList ) | |||
table.sort( usedTemplateList ) | table.sort( usedTemplateList ) | ||
table.sort( extraCategories ) | |||
return requireList, loadDataList, usedTemplateList | return { | ||
requireList = requireList, | |||
loadDataList = loadDataList, | |||
loadJsonDataList = loadJsonDataList, | |||
usedTemplateList = usedTemplateList, | |||
extraCategories = extraCategories | |||
} | |||
end | end | ||
| Line 243: | Line 267: | ||
funcName = mw.text.trim( funcName ) | funcName = mw.text.trim( funcName ) | ||
if string.find( funcName, '^{{{' ) then | if string.find( funcName, '^{{{' ) then | ||
funcName = funcName .. '}}}' | |||
end | end | ||
table.insert( invokeList, {moduleName=moduleName, funcName=funcName} ) | table.insert( invokeList, {moduleName=moduleName, funcName=funcName} ) | ||
| Line 271: | Line 295: | ||
html:tag( 'td' ) | html:tag( 'td' ) | ||
:attr( 'width', '40xp' ) | :attr( 'width', '40xp' ) | ||
:wikitext( '[[File: | :wikitext( '[[File:Iron full helm detail old.png|center|30px|link=]]' ) | ||
:done() | :done() | ||
:tag( 'td' ) | :tag( 'td' ) | ||
| Line 353: | Line 377: | ||
---@return string | ---@return string | ||
local function formatInvokedByList( moduleName, addCategories, whatLinksHere ) | local function formatInvokedByList( moduleName, addCategories, whatLinksHere ) | ||
local function lcfirst( str ) | |||
return string.gsub( str, '^[Mm]odule:.', string.lower ) | |||
end | |||
local templateData = arr.map( whatLinksHere, function(x) return {templateName=x, invokeList=getInvokeCallList(x)} end ) | local templateData = arr.map( whatLinksHere, function(x) return {templateName=x, invokeList=getInvokeCallList(x)} end ) | ||
| Line 406: | Line 430: | ||
local function formatRequiredByList( moduleName, addCategories, whatLinksHere ) | local function formatRequiredByList( moduleName, addCategories, whatLinksHere ) | ||
local childModuleData = arr.map( whatLinksHere, function ( title ) | local childModuleData = arr.map( whatLinksHere, function ( title ) | ||
local | local lists = getRequireList( title ) | ||
return {name=title, requireList=requireList, loadDataList=loadDataList} | return {name=title, requireList=lists.requireList, loadDataList=lists.loadDataList .. lists.loadJsonDataList} | ||
end ) | end ) | ||
| Line 471: | Line 495: | ||
end | end | ||
local function | local function formatImportList( currentPageName, moduleList, id, message, category ) | ||
if #moduleList > COLLAPSE_LIST_LENGTH_THRESHOLD then | |||
moduleList = collapseList( moduleList, id, 'modules' ) | |||
if # | |||
end | end | ||
local res = arr.map( moduleList, function( moduleName ) | |||
return '<div class="seealso">' .. string.format( message, currentPageName, moduleName ) .. '</div>' | |||
end ) | |||
end | |||
if # | if #moduleList > 0 and category then | ||
table.insert( res, ( | table.insert( res, string.format( '[[Category:%s]]', category ) ) | ||
end | end | ||
| Line 563: | Line 559: | ||
if title.text:lower():find( 'sandbox' ) then | if title.text:lower():find( 'sandbox' ) then | ||
moduleIsUsed = true -- Don't show sandbox modules as unused | |||
end | end | ||
if currentPageName:find( '^Template:' ) or currentPageName:find( '^Calculator:' ) then | if currentPageName:find( '^Template:' ) or currentPageName:find( '^Calculator:' ) then | ||
local invokeList = getInvokeCallList( currentPageName ) | local invokeList = getInvokeCallList( currentPageName ) | ||
return formatInvokeCallList( currentPageName, addCategories, invokeList ) | return formatInvokeCallList(currentPageName, addCategories, invokeList) | ||
end | end | ||
| Line 590: | Line 586: | ||
} ) | } ) | ||
local | local lists = getRequireList( currentPageName, true ) | ||
requireList = arr.map( requireList, function ( moduleName ) | local requireList = arr.map( lists.requireList, function ( moduleName ) | ||
if moduleName:find( '%%' ) then | if moduleName:find( '%%' ) then | ||
return formatDynamicQueryLink( moduleName ) | return formatDynamicQueryLink( moduleName ) | ||
elseif builtins[moduleName] then | |||
return '[[' .. builtins[moduleName].link .. '|' .. moduleName .. ']]' | |||
else | else | ||
return '[[' .. moduleName .. ']]' | return '[[' .. moduleName .. ']]' | ||
| Line 600: | Line 598: | ||
end ) | end ) | ||
loadDataList = arr.map( loadDataList, function ( moduleName ) | local loadDataList = arr.map( lists.loadDataList, function ( moduleName ) | ||
if moduleName:find( '%%' ) then | if moduleName:find( '%%' ) then | ||
return formatDynamicQueryLink( moduleName ) | return formatDynamicQueryLink( moduleName ) | ||
| Line 608: | Line 606: | ||
end ) | end ) | ||
usedTemplateList = arr.map( usedTemplateList, function( templateName ) | local loadJsonDataList = arr.map( lists.loadJsonDataList, function ( moduleName ) | ||
if moduleName:find( '%%' ) then | |||
return formatDynamicQueryLink( moduleName ) | |||
else | |||
return '[[' .. moduleName .. ']]' | |||
end | |||
end ) | |||
local usedTemplateList = arr.map( lists.usedTemplateList, function( templateName ) | |||
if string.find( templateName, ':' ) then -- Real templates are prefixed by a namespace, magic words are not | if string.find( templateName, ':' ) then -- Real templates are prefixed by a namespace, magic words are not | ||
return '[['..templateName..']]' | return '[['..templateName..']]' | ||
| Line 619: | Line 625: | ||
table.insert( res, formatInvokedByList( currentPageName, addCategories, whatTemplatesLinkHere ) ) | table.insert( res, formatInvokedByList( currentPageName, addCategories, whatTemplatesLinkHere ) ) | ||
table.insert( res, | table.insert( res, formatImportList( currentPageName, requireList, 'require', "'''%s''' requires %s.", addCategories and 'Modules requiring modules' ) ) | ||
table.insert( res, | table.insert( res, formatImportList( currentPageName, loadDataList, 'loadData', "'''%s''' loads data from %s.", addCategories and 'Modules using data' ) ) | ||
table.insert( res, formatImportList( currentPageName, loadJsonDataList, 'loadJsonData', "'''%s''' loads data from %s.", addCategories and 'Modules using data' ) ) | |||
table.insert( res, formatUsedTemplatesList( currentPageName, addCategories, usedTemplateList ) ) | table.insert( res, formatUsedTemplatesList( currentPageName, addCategories, usedTemplateList ) ) | ||
table.insert( res, formatRequiredByList( currentPageName, addCategories, whatModulesLinkHere ) ) | table.insert( res, formatRequiredByList( currentPageName, addCategories, whatModulesLinkHere ) ) | ||
if addCategories then | |||
local extraCategories = arr.map( lists.extraCategories, function( categoryName ) | |||
return "[[Category:" .. categoryName .. "]]" | |||
end ) | |||
table.insert( res, table.concat( extraCategories ) ) | |||
end | |||
if not moduleIsUsed then | if not moduleIsUsed then | ||
| Line 632: | Line 647: | ||
return p | return p | ||