Module:Introspection utils: Difference between revisions

Ganaram inukshuk (talk | contribs)
mNo edit summary
Ganaram inukshuk (talk | contribs)
No edit summary
 
(11 intermediate revisions by the same user not shown)
Line 3: Line 3:


-- TODO:
-- TODO:
-- - Detect whether a template invokes a specific module
-- Add support for detecting modules providing data, not just functions.
-- Address edge case of lazy-loaded modules (loaded within a function)


-- Common functions for module and template introspection.
-- Common functions for module and template introspection.
Line 82: Line 83:
end
end


-- Normalize:
-- Normalize tags
-- 1. Convert all newlines to spaces
text_to_scan = text_to_scan
-- 2. Collapse multiple spaces/tabs/newlines
:gsub("<noinclude>.-</noinclude>", "")
-- 3. Trim leading/trailing whitespace
:gsub("<noinclude%s*/>", "")
local normalized = text_to_scan
:gsub("<includeonly>", "")
:gsub("</includeonly>", "")
:gsub("<onlyinclude>", "")
:gsub("</onlyinclude>", "")
 
-- Normalize subst/safesubst
text_to_scan = text_to_scan
    :gsub("{{+%s*[Ss]afesubst:", "{{")
    :gsub("{{+%s*[Ss]ubst:", "{{")
 
-- Normalize spaces
text_to_scan = text_to_scan
:gsub("[\r\n]", " ")
:gsub("[\r\n]", " ")
:gsub("%s+", " ")
:gsub("%s+", " ")
:match("^%s*(.-)%s*$")
:match("^%s*(.-)%s*$")
-- Normalize more by removing subst, safesubst, and any extra curly brackets
normalized = normalized
:gsub("{{{|safesubst:}}}", "")  -- Remove {{{{|safesubst:}}} if used
:gsub("{{{|subst:}}}", "")      -- Remove {{{{|subst:}}} if used
:gsub("{{{{", "{{")            -- Collapse excessive curly brackets
:gsub("}}}}", "}}")            -- Collapse excessive curly brackets


return normalized
return text_to_scan
end
end


Line 325: Line 330:
end
end


-- Check whether a template invokes a function from a module.
local function normalize_module_name(name)
-- If no function name is provided, it will match any function name.
if not name then return "" end
-- Wikitext is assumed to have been preprocessed.
-- Trim, replace spaces with underscores, remove namespace, lowercase first
function p.invocation_exists(wikitext, mod_name, func_name)
-- letter
local func_name = func_name or "[%w_%-]+"
name = mw.text.trim(name)
name = name:gsub(" ", "_")
name = name:gsub("^[Mm]odule:", "")
name = name:gsub("^%a", string.lower)
return name
end
 
-- Check whether a template invokes a function from a module. Input is a table
-- of invocations, from find_invokes, and mod_name is the module name.
function p.invocation_exists(invokes, mod_name)
if type(invokes) ~= "table" then
return false
end
-- Helper function
local target_mod = normalize_module_name(mod_name)
-- Normalizes a module name according to how Mediawiki processes module
 
-- names as part of an #invoke statement
for _, invoke in ipairs(invokes) do
function normalize_module_name(mod_name)
if normalize_module_name(invoke["module"]) == target_mod then
    if not mod_name then return nil end
return true
    -- Trim whitespace
end
    mod_name = mw.text.trim(mod_name)
    -- Replace spaces with underscores
    mod_name = mod_name:gsub(" ", "_")
    -- Leave as snake case
    return mod_name
end
end
return false
end
function p.tester()
-- Preprocess module name to guarantee match
local wikitext = p.get_and_preprocess_content("Template", "MOS intro")
local safe_mod_name = normalize_module_name(mod_name)
local invokes = p.find_invokes(wikitext)
safe_mod_name = safe_mod_name:gsub("([^%w])", "%%%1")
local pattern = "{{%s*#invoke:%s*" .. safe_mod_name .. "%s*|%s*" .. func_name
return p.invocation_exists(invokes, "MOS intro")
return string.find(wikitext, pattern) ~= nil
end
end


return p
return p