Module:DependencyList: Difference between revisionsGive feedback
osrsw>Shayani knew i would mess this up |
osrsw>CephHunter Sync with rsw |
||
| Line 2: | Line 2: | ||
local p = {} | local p = {} | ||
local libraryUtil = require( 'libraryUtil' ) | local libraryUtil = require( 'libraryUtil' ) | ||
local | local arr = require( 'Module:Enum' ) | ||
local yn = require( 'Module:Yesno' ) | local yn = require( 'Module:Yesno' ) | ||
local param = require( 'Module:Paramtest' ) | local param = require( 'Module:Paramtest' ) | ||
| Line 42: | Line 42: | ||
---@param str string | ---@param str string | ||
---@return string | ---@return string | ||
local function | local function formatPageName( str ) | ||
local name = mw.text.trim(str) | |||
:gsub( '^([\'\"])(.-)%1$', function(_, x) return x end ) -- Only remove quotes at start and end of string if both are the same type | |||
:gsub( '_', ' ' ) | :gsub( '_', ' ' ) | ||
:gsub( '^.', string.upper ) | :gsub( '^.', string.upper ) | ||
:gsub( ': | :gsub( ':.', string.upper ) | ||
return name | |||
end | |||
---@param str string | |||
---@return string | |||
local function formatModuleName( str ) | |||
local module = formatPageName( str ) | |||
if not string.find( module, '^[Mm]odule:' ) then | |||
module = 'Module:' .. module | |||
end | |||
return module | |||
end | |||
local function dualGmatch( str, pat1, pat2 ) | |||
local f1 = string.gmatch( str, pat1 ) | |||
local f2 = string.gmatch( str, pat2 ) | |||
return function() | |||
return f1() or f2() | |||
end | |||
end | end | ||
| Line 56: | Line 79: | ||
if query:find( '%.%.' ) then | if query:find( '%.%.' ) then | ||
query = mw.text.split( query, '..', true ) | query = mw.text.split( query, '..', true ) | ||
query = | query = arr.map( query, function(x) return mw.text.trim(x) end ) | ||
query = | query = arr.map( query, function(x) return (x:match('^[\'\"](.-)[\'\"]$') or '%') end ) | ||
query = table.concat( query ) | query = table.concat( query ) | ||
else | else | ||
| Line 101: | Line 124: | ||
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 = {} | local requireList = arr{} | ||
local loadDataList = {} | local loadDataList = arr{} | ||
local usedTemplateList = {} | local usedTemplateList = arr{} | ||
local dynamicRequirelist = {} | local dynamicRequirelist = arr{} | ||
local dynamicLoadDataList = {} | local dynamicLoadDataList = arr{} | ||
assert( content ~= nil, string.format( '%s does not exist', moduleName ) ) | assert( content ~= nil, string.format( '%s does not exist', moduleName ) ) | ||
content = content:gsub( '%-%-%[(=-)%[.-%]%1%]', '' ):gsub( '%-%-[^\n]*', '' ) -- Strip comments | content = content:gsub( '%-%-%[(=-)%[.-%]%1%]', '' ):gsub( '%-%-[^\n]*', '' ) -- Strip comments | ||
for match in dualGmatch( content, 'require%s*(%b())', 'require%s*((["\'])%s*[Mm]odule:.-%2)' ) do | for match in dualGmatch( content, 'require%s*(%b())', 'require%s*((["\'])%s*[Mm]odule:.-%2)' ) do | ||
| Line 129: | Line 144: | ||
elseif match ~= '' then | elseif match ~= '' then | ||
match = formatModuleName( match ) | match = formatModuleName( match ) | ||
table.insert( requireList, match ) | table.insert( requireList, match ) | ||
end | end | ||
| Line 191: | Line 201: | ||
if name:find( ':' ) then | if name:find( ':' ) then | ||
local ns = name:match( '^(.-):' ) | local ns = name:match( '^(.-):' ) | ||
if | if arr.contains( {'', 'template', 'calculator', 'user'}, ns:lower() ) then | ||
table.insert( usedTemplateList, name ) | table.insert( usedTemplateList, name ) | ||
elseif ns == ns:upper() then | elseif ns == ns:upper() then | ||
| Line 208: | Line 218: | ||
end | end | ||
requireList = requireList .. dynamicRequirelist:reject( loadDataList ) | |||
requireList = requireList:unique() | |||
requireList = | loadDataList = loadDataList .. dynamicLoadDataList:reject( requireList ) | ||
loadDataList = loadDataList:unique() | |||
loadDataList = | usedTemplateList = usedTemplateList:unique() | ||
loadDataList = | |||
usedTemplateList = | |||
table.sort( requireList ) | table.sort( requireList ) | ||
table.sort( loadDataList ) | table.sort( loadDataList ) | ||
| Line 232: | Line 240: | ||
for moduleName, funcName in string.gmatch( content, '{{[{|safeubt:}]-#[Ii]nvoke:([^|]+)|([^}|]+)[^}]*}}' ) do | for moduleName, funcName in string.gmatch( content, '{{[{|safeubt:}]-#[Ii]nvoke:([^|]+)|([^}|]+)[^}]*}}' ) do | ||
moduleName = formatModuleName( moduleName ) | moduleName = formatModuleName( moduleName ) | ||
funcName = mw.text.trim( funcName ) | funcName = mw.text.trim( funcName ) | ||
if string.find( funcName, '^{{{' ) then | |||
funcName = funcName .. '}}}' | |||
end | |||
table.insert( invokeList, {moduleName=moduleName, funcName=funcName} ) | table.insert( invokeList, {moduleName=moduleName, funcName=funcName} ) | ||
end | end | ||
invokeList = | -- For form calcs invoking the module directly | ||
for config in dualGmatch( content, '<pre%s+class%s*=%s*["\']jcConfig["\'](.-)</pre>', '{{[Ff]orm calculator%s*|(.+)}}' ) do | |||
local moduleName = string.match( config, 'module%s*=%s*(.-)[\n|]' ) | |||
if param.has_content( moduleName ) then | |||
moduleName = formatModuleName( moduleName ) | |||
local funcName = string.match( config, 'modulefunc%s*=%s*(.-)[\n|]' ) or 'main' | |||
table.insert( invokeList, {moduleName=moduleName, funcName=funcName} ) | |||
end | |||
end | |||
invokeList = arr.unique( invokeList, function(x) return x.moduleName..x.funcName end ) | |||
table.sort( invokeList, function(x, y) return x.moduleName..x.funcName < y.moduleName..y.funcName end ) | table.sort( invokeList, function(x, y) return x.moduleName..x.funcName < y.moduleName..y.funcName end ) | ||
| Line 251: | Line 271: | ||
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 268: | Line 288: | ||
local text = string.format( '%d %s', #list, listType ) | local text = string.format( '%d %s', #list, listType ) | ||
local button = tooltip._span{ name=id, alt=text } | local button = tooltip._span{ name=id, alt=text } | ||
list = | list = arr.map( list, function(x) return '\n# '..x end ) | ||
local content = tooltip._div{ name=id, content='\n'..table.concat( list )..'\n\n' } | local content = tooltip._div{ name=id, content='\n'..table.concat( list )..'\n\n' } | ||
| Line 314: | Line 334: | ||
for _, item in ipairs( invokeList ) do | for _, item in ipairs( invokeList ) do | ||
table.insert( res, string.format( | table.insert( res, string.format( | ||
"<div class= | "<div class='seealso'>'''%s''' invokes function '''%s''' in [[%s]] using [[RuneScape:Lua|Lua]].</div>", | ||
templateName, | templateName, | ||
item.funcName, | item.funcName, | ||
| Line 333: | Line 353: | ||
---@return string | ---@return string | ||
local function formatInvokedByList( moduleName, addCategories, whatLinksHere ) | local function formatInvokedByList( moduleName, addCategories, whatLinksHere ) | ||
local templateData = | local function lcfirst( str ) | ||
templateData = | return string.gsub( str, '^[Mm]odule:.', string.lower ) | ||
return | end | ||
return y.moduleName | |||
local templateData = arr.map( whatLinksHere, function(x) return {templateName=x, invokeList=getInvokeCallList(x)} end ) | |||
templateData = arr.filter( templateData, function(x) | |||
return arr.any( x.invokeList, function(y) | |||
return lcfirst(y.moduleName) == lcfirst(moduleName) | |||
end ) | end ) | ||
end ) | end ) | ||
| Line 354: | Line 378: | ||
if #invokedByList > COLLAPSE_LIST_LENGTH_THRESHOLD then | if #invokedByList > COLLAPSE_LIST_LENGTH_THRESHOLD then | ||
table.insert( res, string.format( | table.insert( res, string.format( | ||
"<div class= | "<div class='seealso'>'''%s''' is invoked by %s.</div>", | ||
moduleName, | moduleName, | ||
collapseList( invokedByList, 'invokedBy', 'templates' )[1] | collapseList( invokedByList, 'invokedBy', 'templates' )[1] | ||
| Line 361: | Line 385: | ||
for _, item in ipairs( invokedByList ) do | for _, item in ipairs( invokedByList ) do | ||
table.insert( res, string.format( | table.insert( res, string.format( | ||
"<div class= | "<div class='seealso'>'''%s's''' %s.</div>", | ||
moduleName, | moduleName, | ||
item | item | ||
| Line 381: | Line 405: | ||
---@return string | ---@return string | ||
local function formatRequiredByList( moduleName, addCategories, whatLinksHere ) | local function formatRequiredByList( moduleName, addCategories, whatLinksHere ) | ||
local childModuleData = | local childModuleData = arr.map( whatLinksHere, function ( title ) | ||
local requireList, loadDataList = getRequireList( title ) | local requireList, loadDataList = getRequireList( title ) | ||
return {name=title, requireList=requireList, loadDataList=loadDataList} | return {name=title, requireList=requireList, loadDataList=loadDataList} | ||
end ) | end ) | ||
local requiredByList = | local requiredByList = arr.map( childModuleData, function ( item ) | ||
if | if arr.any( item.requireList, function(x) return x:lower()==moduleName:lower() end ) then | ||
if item.name:find( '%%' ) then | if item.name:find( '%%' ) then | ||
return formatDynamicQueryLink( item.name ) | return formatDynamicQueryLink( item.name ) | ||
| Line 396: | Line 420: | ||
end ) | end ) | ||
local loadedByList = | local loadedByList = arr.map( childModuleData, function ( item ) | ||
if | if arr.any( item.loadDataList, function(x) return x:lower()==moduleName:lower() end ) then | ||
if item.name:find( '%%' ) then | if item.name:find( '%%' ) then | ||
return formatDynamicQueryLink( item.name ) | return formatDynamicQueryLink( item.name ) | ||
| Line 422: | Line 446: | ||
for _, requiredByModuleName in ipairs( requiredByList ) do | for _, requiredByModuleName in ipairs( requiredByList ) do | ||
table.insert( res, string.format( | table.insert( res, string.format( | ||
"<div class= | "<div class='seealso'>'''%s''' is required by %s.</div>", | ||
moduleName, | moduleName, | ||
requiredByModuleName | requiredByModuleName | ||
| Line 434: | Line 458: | ||
for _, loadedByModuleName in ipairs( loadedByList ) do | for _, loadedByModuleName in ipairs( loadedByList ) do | ||
table.insert( res, string.format( | table.insert( res, string.format( | ||
"<div class= | "<div class='seealso'>'''%s''' is loaded by %s.</div>", | ||
moduleName, | moduleName, | ||
loadedByModuleName | loadedByModuleName | ||
| Line 456: | Line 480: | ||
for _, requiredModuleName in ipairs( requireList ) do | for _, requiredModuleName in ipairs( requireList ) do | ||
table.insert( res, string.format( | table.insert( res, string.format( | ||
"<div class= | "<div class='seealso'>'''%s''' requires %s.</div>", | ||
currentPageName, | currentPageName, | ||
requiredModuleName | requiredModuleName | ||
| Line 478: | Line 502: | ||
for _, loadedModuleName in ipairs( loadDataList ) do | for _, loadedModuleName in ipairs( loadDataList ) do | ||
table.insert( res, string.format( | table.insert( res, string.format( | ||
"<div class= | "<div class='seealso'>'''%s''' loads data from %s.</div>", | ||
currentPageName, | currentPageName, | ||
loadedModuleName | loadedModuleName | ||
| Line 500: | Line 524: | ||
for _, templateName in ipairs( usedTemplateList ) do | for _, templateName in ipairs( usedTemplateList ) do | ||
table.insert( res, string.format( | table.insert( res, string.format( | ||
"<div class= | "<div class='seealso'>'''%s''' transcludes %s using <samp>frame:preprocess()</samp>.</div>", | ||
currentPageName, | currentPageName, | ||
templateName | templateName | ||
| Line 524: | Line 548: | ||
local title = mw.title.getCurrentTitle() | local title = mw.title.getCurrentTitle() | ||
-- Leave early if not in module, template or calculator namespace or if module is part of exchange groups | -- Leave early if not in module, template or calculator namespace or if module is part of exchange or data groups | ||
if param.is_empty( currentPageName ) and ( | if param.is_empty( currentPageName ) and ( | ||
( not | ( not arr.contains( {'Module', 'Template', 'Calculator'}, title.nsText ) ) or | ||
( title.nsText == 'Module' and ( | ( title.nsText == 'Module' and ( arr.contains( {'Exchange', 'Exchange historical', 'Data'}, title.text:match( '^(.-)/' ) ) ) ) | ||
) then | ) then | ||
return '' | return '' | ||
| Line 534: | Line 558: | ||
currentPageName = param.default_to( currentPageName, title.fullText ) | currentPageName = param.default_to( currentPageName, title.fullText ) | ||
currentPageName = string.gsub( currentPageName, '/[Dd]oc$', '' ) | currentPageName = string.gsub( currentPageName, '/[Dd]oc$', '' ) | ||
currentPageName = | currentPageName = formatPageName( currentPageName ) | ||
addCategories = yn( param.default_to( addCategories, title.subpageText~='doc' ) ) | addCategories = yn( param.default_to( addCategories, title.subpageText~='doc' ) ) | ||
moduleIsUsed = yn( param.default_to( isUsed, false ) ) | moduleIsUsed = yn( param.default_to( isUsed, false ) ) | ||
if title.text:lower():find( 'sandbox' ) then | if title.text:lower():find( 'sandbox' ) then | ||
moduleIsUsed = true -- Don't show sandbox modules as unused | moduleIsUsed = true -- Don't show sandbox modules as unused | ||
| Line 558: | Line 582: | ||
namespace = 'Module', | namespace = 'Module', | ||
linksto = currentPageName, | linksto = currentPageName, | ||
nottitlematch = '%/doc|Exchange/%|Exchange historical/%|' .. currentPageName:gsub( 'Module:', '' ), | nottitlematch = '%/doc|Exchange/%|Exchange historical/%|Data/%|' .. currentPageName:gsub( 'Module:', '' ), | ||
distinct = 'strict', | distinct = 'strict', | ||
ignorecase = true, | ignorecase = true, | ||
| Line 568: | Line 592: | ||
local requireList, loadDataList, usedTemplateList = getRequireList( currentPageName, true ) | local requireList, loadDataList, usedTemplateList = getRequireList( currentPageName, true ) | ||
requireList = | requireList = arr.map( requireList, function ( moduleName ) | ||
if moduleName:find( '%%' ) then | if moduleName:find( '%%' ) then | ||
return formatDynamicQueryLink( moduleName ) | return formatDynamicQueryLink( moduleName ) | ||
| Line 576: | Line 600: | ||
end ) | end ) | ||
loadDataList = | loadDataList = arr.map( loadDataList, function ( moduleName ) | ||
if moduleName:find( '%%' ) then | if moduleName:find( '%%' ) then | ||
return formatDynamicQueryLink( moduleName ) | return formatDynamicQueryLink( moduleName ) | ||
| Line 584: | Line 608: | ||
end ) | end ) | ||
usedTemplateList = | usedTemplateList = arr.map( 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..']]' | ||