Module:DependencyList: Difference between revisions

No edit summary
mNo edit summary
Line 13: Line 13:


--- 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'.
---@param content string    @The content of the module to look in as a string
---@param content string    The content of the module to search in
---@param varName string
---@param varName string
---@return string
---@return string
local function substVarValue( content, varName )
local function substVarValue( content, varName )
     if varName:find( "%b''" ) or varName:find( '%b""' ) then -- Look for balanced quotes
     local res = content:match( varName .. '%s*=%s*(%b""%s-%.*)' ) or content:match( varName .. "%s*=%s*(%b''%s-%.*)" ) or ''
         return varName -- Is already a string
    if res:find( '^(["\'])[Mm]odule:[%S]+%1' ) and not res:find( '%.%.' ) and not res:find( '%%%a' ) then
         return mw.text.trim( res )
     else
     else
         local res = content:match( varName .. '%s*=%s*(%b""%s-%.*)' ) or content:match( varName .. "%s*=%s*(%b''%s-%.*)" ) or ''
         return ''
        if res:find( '^(["\'])[Mm]odule:[%S]+%1' ) and not res:find( '%.%.' ) then
    end
            return mw.text.trim( res )
end
        else
 
            return ''
---@param capture string
        end
---@param content string    The content of the module to search in
---@return string
local function extractModuleName( capture, content )
    capture = capture:gsub( '^%(%s*(.-)%s*%)$', '%1' )
 
    if capture:find( '^(["\']).-%1$' ) then -- Check if it is already a pure string
        return capture
    elseif capture:find( '^[%a_][%w_]*$' ) then -- Check if if is a single variable
        return substVarValue( content, capture )
     end
     end
    return capture
end
end


Line 33: Line 44:
local function formatModuleName( str )
local function formatModuleName( str )
     return (str:gsub( '^([\'\"])(.-)%1$', function(_, x) return x end ) -- Only remove quotes at start and end of string if both are the same type
     return (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( ':(.)', function(x) return ':'..x:upper() end ))
        :gsub( ':(.)', function(x) return ':'..x:upper() end ))
end
end


Line 41: Line 52:
--- 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[]    @Sequence of strings
---@return string[]    Sequence of strings
local function getDynamicRequireList( query )
local function getDynamicRequireList( query )
     query = mw.text.split( query, '..', true )
     if query:find( '%.%.' ) then
    query = enum.map( query, function(x) return mw.text.trim(x) end )
        query = mw.text.split( query, '..', true )
    query = enum.map( query, function(x) return (x:match('^[\'\"]([^\'\"]+)[\'\"]$') or '%') end )
        query = enum.map( query, function(x) return mw.text.trim(x) end )
    query = table.concat( query )
        query = enum.map( query, function(x) return (x:match('^[\'\"](.-)[\'\"]$') or '%') end )
        query = table.concat( query )
    else
        _, query = query:match( '(["\'])(.-)%1' )
        query = query:gsub( '%%%a', '%%' )
    end
     query = query:gsub( '^[Mm]odule:', '' )
     query = query:gsub( '^[Mm]odule:', '' )


Line 60: Line 76:
         namespace = 'Module',
         namespace = 'Module',
         titlematch = query,
         titlematch = query,
         nottitlematch = '%/doc|%sandbox%%|'..query..'/%',
         nottitlematch = '%/doc|'..query..'/%',
         distinct = 'strict',
         distinct = 'strict',
         ignorecase = true,
         ignorecase = true,
Line 103: Line 119:
     end
     end


     for match in dualGmatch( content, 'require%s*%(([^%)]+)', 'require%s*((["\'])%s*[Mm]odule:.-%2)' ) do
     for match in dualGmatch( content, 'require%s*(%b())', 'require%s*((["\'])%s*[Mm]odule:.-%2)' ) do
         match = mw.text.trim( match )
         match = mw.text.trim( match )
         match = substVarValue( content, match )
         match = extractModuleName( match, content )


         if match:find( '%.%.' ) then
         if match:find( '%.%.' ) or match:find( '%%%a' ) then
             for _, x in ipairs( getDynamicRequireList( match ) ) do
             for _, x in ipairs( getDynamicRequireList( match ) ) do
                 table.insert( dynamicRequirelist, x )
                 table.insert( dynamicRequirelist, x )
Line 122: Line 138:
     end
     end


     for match in dualGmatch( content, 'mw%.loadData%s*%(([^%)]+)', 'mw%.loadData%s*((["\'])%s*[Mm]odule:.-%2)' ) do
     for match in dualGmatch( content, 'mw%.loadData%s*(%b())', 'mw%.loadData%s*((["\'])%s*[Mm]odule:.-%2)' ) do
         match = mw.text.trim( match )
         match = mw.text.trim( match )
         match = substVarValue( content, match )
         match = extractModuleName( match, content )


         if match:find( '%.%.' ) then
         if match:find( '%.%.' ) or match:find( '%%%a' ) then
             for _, x in ipairs( getDynamicRequireList( match ) ) do
             for _, x in ipairs( getDynamicRequireList( match ) ) do
                 table.insert( dynamicLoadDataList, x )
                 table.insert( dynamicLoadDataList, x )
Line 181: Line 197:
                         end
                         end
                     else
                     else
                         if name == name:upper() then
                         if name:match( '^%u+$' ) or name == '!' then
                             table.insert( usedTemplateList, name ) -- Probably a magic word
                             table.insert( usedTemplateList, name ) -- Probably a magic word
                         else
                         else
Line 216: Line 232:


     for moduleName, funcName in string.gmatch( content, '{{[{|safeubt:}]-#[Ii]nvoke:([^|]+)|([^}|]+)[^}]*}}' ) do
     for moduleName, funcName in string.gmatch( content, '{{[{|safeubt:}]-#[Ii]nvoke:([^|]+)|([^}|]+)[^}]*}}' ) do
         moduleName = string.format( 'Module:%s', moduleName )
         moduleName = string.format( 'Module:%s', mw.text.trim( moduleName ) )
         moduleName = formatModuleName( moduleName )
         moduleName = formatModuleName( moduleName )
        funcName = mw.text.trim( funcName )
         table.insert( invokeList, {moduleName=moduleName, funcName=funcName} )
         table.insert( invokeList, {moduleName=moduleName, funcName=funcName} )
     end
     end
Line 507: Line 524:
     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, sandbox or data 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 enum.contains( {'Module', 'Template', 'Calculator'}, title.nsText ) ) or
         ( not enum.contains( {'Module', 'Template', 'Calculator'}, title.nsText ) ) or
         ( title.nsText == 'Module' and ( enum.contains( {'Exchange', 'Exchange historical', 'Sandbox', 'Data'}, title.text:match( '^(.-)/' ) ) ) )
         ( title.nsText == 'Module' and ( enum.contains( {'Exchange', 'Exchange historical', 'Data'}, title.text:match( '^(.-)/' ) ) ) )
     ) then
     ) then
         return ''
         return ''
     end
     end
 
   
     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$', '' )
Line 520: Line 537:
     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:match( '^(.-)/' ) == 'Sandbox' then
    moduleIsUsed = true -- Don't show sandbox modules as unused
    end


     if currentPageName:find( '^Template:' ) or currentPageName:find( '^Calculator:' ) then
     if currentPageName:find( '^Template:' ) or currentPageName:find( '^Calculator:' ) then
Line 537: Line 558:
         namespace = 'Module',
         namespace = 'Module',
         linksto = currentPageName,
         linksto = currentPageName,
         nottitlematch = '%/doc|%sandbox%|Exchange/%|Exchange historical/%|Data/%|' .. currentPageName:gsub( 'Module:', '' ),
         nottitlematch = '%/doc|Exchange/%|Exchange historical/%|Data/%|' .. currentPageName:gsub( 'Module:', '' ),
         distinct = 'strict',
         distinct = 'strict',
         ignorecase = true,
         ignorecase = true,
Line 564: Line 585:


     usedTemplateList = enum.map( usedTemplateList, function( templateName )
     usedTemplateList = enum.map( usedTemplateList, function( templateName )
         if mw.title.new( templateName ).exists then
         if string.find( templateName, ':' ) then -- Real templates are prefixed by a namespace, magic words are not
             return '[['..templateName..']]'
             return '[['..templateName..']]'
         else
         else