Module:Dochead: Difference between revisions

Ganaram inukshuk (talk | contribs)
todo
Ganaram inukshuk (talk | contribs)
autocategorize metatemplates
 
(11 intermediate revisions by 2 users not shown)
Line 6: Line 6:
local p = {}
local p = {}


-- TODO: Change requirements for lua-based template
-- TODO: (Low-ish priority): rewrite to eliminate redundant code
-- FROM: detect whether a corresponding page exists
-- TO: detect whether it invokes ANYTHING at all


-- Produces a hatnote that is placed on the top of a documentation page (either
-- Produces a hatnote that is placed on the top of a documentation page (either
Line 19: Line 17:
--  - what functions from which modules are invoked
--  - what functions from which modules are invoked


-- Helper function
-- Helper function: categorize modules
-- Categorizes pages if they're in the right namespace, and based on the nature
local function categorize_module(pagename)
-- of the page
local function categorize(namespace, pagename, is_lua_based_template)
local is_lua_based_template = is_lua_based_template or false
local cats = ""
local cats = ""
if pagename:match("/doc$") then
if pagename:match("/doc$") then
-- Documentation subpages
cats = "[[Category:Module documentation]]"
if namespace == "Template" then
else
cats = "[[Category:Template documentation]]"
cats = "[[Category:Lua modules]]"
elseif namespace == "Module" then
cats = "[[Category:Module documentation]]"
end
else
-- Main pages
if namespace == "Template" then
cats = "[[Category:Templates]]"
if is_lua_based_template then
cats = cats .. " [[Category:Lua-based templates]]"
end
elseif namespace == "Module" then
cats = "[[Category:Lua modules]]"
else
--cats = "[[Category:Templates in the incorrect namespace]]"
end
end
end
return cats
return cats
end
end
Line 54: Line 32:
-- Check whether corresponding template exists
-- Check whether corresponding template exists
-- Then check whether that template invokes the module
-- Then check whether that template invokes the module
local has_template = iutils.page_exists("Template:" .. corr_template)
local has_template = iutils.page_exists("Template:" .. corr_template:gsub("/doc$", ""))
if has_template then
local wikitext = iutils.get_and_preprocess_content("Template", corr_template)
local invokes = iutils.find_invokes(wikitext)
has_template = has_template and iutils.invocation_exists(invokes, pagename)
end
-- Check whether to use detect_corr_page option
-- Check whether to use detect_corr_page option
Line 66: Line 39:
if header ~= "dualuse" and header ~= "metatemplate" and header ~= "noinvoke" then
if header ~= "dualuse" and header ~= "metatemplate" and header ~= "noinvoke" then
has_template = has_template and detect_corr_page
has_template = has_template and detect_corr_page
end
-- If the module has a template, check for whether it invokes it.
if has_template then
local wikitext = iutils.get_and_preprocess_content("Template", corr_template:gsub("/doc$", ""))
local invokes = iutils.find_invokes(wikitext)
has_template = has_template and iutils.invocation_exists(invokes, pagename:gsub("/doc$", ""))
end
end
Line 79: Line 59:
--  other modules. Such modules generally don't have a corresponding
--  other modules. Such modules generally don't have a corresponding
--  template.
--  template.
-- - data/datamodule indicates a module whose purpose is to provide data
--  values to other modules. Like library modules, these don't have a
--  corresponding template.
-- Does the module have a template?
-- Does the module have a template?
-- - dualuse, metatemplate, and noinvoke: YES (REQUIRED!!)
-- - dualuse, metatemplate, and noinvoke: YES (REQUIRED!!)
-- - metamodule/library: GENERALLY NO
-- - metamodule/library and data: GENERALLY NO
local result = ""
local result = ""
if header == "dualuse" then
if header == "dualuse" then
Line 87: Line 70:
result = string.format(
result = string.format(
"This module may be invoked by templates using its corresponding template [[Template:%s]], or used directly from other modules.",
"This module may be invoked by templates using its corresponding template [[Template:%s]], or used directly from other modules.",
corr_template
corr_template:gsub("/doc$", "")
)
)
else
else
result = string.format(
result = string.format(
"This module has a corresopnding template that is currently missing or does not use this module. ([[Special:EditPage/Template:%s|edit template]])",
"This module has a corresponding template that is currently missing or does not use this module. ([[Special:EditPage/Template:%s|edit template]])",
corr_template
corr_template:gsub("/doc$", "")
)
)
end
end
Line 100: Line 83:
result = string.format(
result = string.format(
"This module implements a metatemplate, and may be invoked by templates using its corresponding template [[Template:%s]], or used directly from other modules.",
"This module implements a metatemplate, and may be invoked by templates using its corresponding template [[Template:%s]], or used directly from other modules.",
corr_template
corr_template:gsub("/doc$", "")
)
)
else
else
Line 109: Line 92:
if has_template then
if has_template then
result = string.format(
result = string.format(
"This module should not be invoked directly; use its corresponding instead: [[Template:%s]].",
"This module should not be invoked directly; use its corresponding template instead: [[Template:%s]].",
corr_template
corr_template:gsub("/doc$", "")
)
)
else
else
result = string.format(
result = string.format(
"This module implements a template that is currently missing or does not use this module. ([[Special:EditPage/Template:%s|edit template]])",
"This module implements a template that is currently missing or does not use this module. ([[Special:EditPage/Template:%s|edit template]])",
corr_template
corr_template:gsub("/doc$", "")
)
)
end
end
Line 121: Line 104:
elseif header == "library" or header == "metamodule" then
elseif header == "library" or header == "metamodule" then
result = "This module primarily serves as a library for other modules and has no corresponding template."
result = "This module primarily serves as a library for other modules and has no corresponding template."
 
elseif header == "data" or pagename:gsub("/doc$", ""):match("/data$") then
result = "This module primarily serves to provide data values for other modules and has no corresponding template."
elseif header == "none" then
result = ""
else
else
if has_template and header ~= "" then
if has_template and header ~= "" then
result = string.format("%s This module implements [[Template:%s]].", header, corr_template)
result = string.format("%s This module implements [[Template:%s]].", header, corr_template:gsub("/doc$", ""))
elseif has_template and header == "" then
elseif has_template and header == "" then
result = string.format("This module implements [[Template:%s]].", corr_template)
result = string.format("This module implements [[Template:%s]].", corr_template:gsub("/doc$", ""))
else
else
result = header
result = header
Line 132: Line 121:
end
end
-- Produce categories
local cats = categorize_module(pagename)
-- Return
if result == "" then
if result == "" then
return ""
return "" .. cats
else
else
return string.format(":''%s''", result)
return string.format(": ''%s''%s\n", result, cats)
end
end
end
-- Helper function: categorize template
local function categorize_template(pagename, has_invoke, is_metatemplate)
local cats = ""
if pagename:match("/doc$") then
cats = "[[Category:Template documentation]]"
else
cats = "[[Category:Templates]]"
if has_invoke then
cats = cats .. " [[Category:Lua-based templates]]"
end
if is_metatemplate then
cats = cats .. " [[Category:Metatemplates]]"
end
end
return cats
end
end


Line 161: Line 171:
-- Check whether corresponding module exists
-- Check whether corresponding module exists
-- Then check whether this template invokes the module
-- Then check whether this template invokes the module
local has_module = iutils.page_exists("Module:" .. corr_module)
local has_module = iutils.page_exists("Module:" .. corr_module:gsub("/doc$", ""))
local wikitext = iutils.get_and_preprocess_content("Template", pagename)
local invokes = iutils.find_invokes(wikitext)
local is_module_invoked = iutils.invocation_exists(invokes, corr_module)
 
-- Find all invocations for the template and add it as an addl hatnote.
local invocation_hatnote = make_invocation_hatnote(invokes)
-- Check whether to use detect_corr_page option
-- Check whether to use detect_corr_page option
Line 176: Line 180:
has_module = has_module and detect_corr_page
has_module = has_module and detect_corr_page
end
end
-- Check for whether the template invokes that module, regardless of whether
-- it uses the corresponding module.
local wikitext = iutils.get_and_preprocess_content("Template", pagename:gsub("/doc$", ""))
local invokes = iutils.find_invokes(wikitext)
local is_module_invoked = iutils.invocation_exists(invokes, corr_module:gsub("/doc$", ""))
-- Heading meanings and usage on templates
-- Heading meanings and usage on templates
Line 185: Line 195:
-- Does the template have a module?
-- Does the template have a module?
-- - dualuse and metatemplate: YES (REQUIRED!!)
-- - dualuse and metatemplate: YES (REQUIRED!!)
-- - noinvoke and metamodule/library: options don't apply to templates.
-- - noinvoke, metamodule/library, and data/datamodule: option's don't apply
--  to templates.
-- RATIONALE FOR NOINVOKE NOT APPLYING: a template may invoke functions from
-- RATIONALE FOR NOINVOKE NOT APPLYING: a template may invoke functions from
-- more than one module, but one of them must be the "main" module. Since
-- more than one module, but one of them must be the "main" module. Since
Line 195: Line 206:
result = string.format(
result = string.format(
"This template is implemented by the Lua module [[Module:%s]]. See its module page for Lua-based template implementation.",
"This template is implemented by the Lua module [[Module:%s]]. See its module page for Lua-based template implementation.",
corr_module
corr_module:gsub("/doc$", "")
)
)
elseif has_module and not is_module_invoked then
elseif has_module and not is_module_invoked then
result = string.format(
result = string.format(
"This template has a corresponding Lua module [[Module:%s]], but does not invoke its functions.",
"This template has a corresponding Lua module [[Module:%s]], but does not invoke its functions.",
corr_module
corr_module:gsub("/doc$", "")
)
)
else
else
result = string.format(
result = string.format(
"This template is implemented by a module that is currently missing. [[Special:EditPage/Module:%s]]",
"This template is implemented by a module that is currently missing. [[Special:EditPage/Module:%s]]",
corr_module
corr_module:gsub("/doc$", "")
)
)
end
end
Line 213: Line 224:
result = string.format(
result = string.format(
"This template is a metatemplate. It is used to build other templates and should not be used standalone, except for testing or simple usage. This template is implemented by the Lua module [[Module:%s]].",
"This template is a metatemplate. It is used to build other templates and should not be used standalone, except for testing or simple usage. This template is implemented by the Lua module [[Module:%s]].",
corr_module
corr_module:gsub("/doc$", "")
)
)
elseif has_module and not is_module_invoked then
elseif has_module and not is_module_invoked then
result = string.format(
result = string.format(
"This metatemplate has a corresponding Lua module [[Module:%s]], but does not invoke its functions.",
"This metatemplate has a corresponding Lua module [[Module:%s]], but does not invoke its functions.",
corr_module
corr_module:gsub("/doc$", "")
)
)
else
else
Line 224: Line 235:
end
end


elseif header == "noinvoke" or header == "library" or header == "metamodule" then
elseif header == "noinvoke" or header == "library" or header == "metamodule" or header == "data" or header == "datamodule" then
result = "This template has a header option in the wrong namespace. It should be used within the Module namespace."
result = "This template has a header option in the wrong namespace. It should be used within the Module namespace."


Line 232: Line 243:
"%s. This template is implemented by the Lua module [[Module:%s]].",
"%s. This template is implemented by the Lua module [[Module:%s]].",
header,
header,
corr_module
corr_module:gsub("/doc$", "")
)
)
elseif has_module and header ~= "" and not is_module_invoked then
elseif has_module and header ~= "" and not is_module_invoked then
Line 238: Line 249:
"%s. This template has a corresponding Lua module [[Module:%s]], but does not invoke its functions.",
"%s. This template has a corresponding Lua module [[Module:%s]], but does not invoke its functions.",
header,
header,
corr_module
corr_module:gsub("/doc$", "")
)
)
elseif has_module and header == "" and is_module_invoked then
elseif has_module and header == "" and is_module_invoked then
result = string.format(
result = string.format(
"This template is implemented by the Lua module [[Module:%s]].",
"This template is implemented by the Lua module [[Module:%s]].",
corr_module
corr_module:gsub("/doc$", "")
)
)
elseif has_module and header == "" and not is_module_invoked then
elseif has_module and header == "" and not is_module_invoked then
result = string.format(
result = string.format(
"This template has a corresponding Lua module [[Module:%s]], but does not invoke its functions.",
"This template has a corresponding Lua module [[Module:%s]], but does not invoke its functions.",
corr_module
corr_module:gsub("/doc$", "")
)
)
else
else
Line 255: Line 266:
end
end
if result == "" and invocation_hatnote == "" then
-- Find all invocations for the template and add it as an addl hatnote.
local invocation_hatnote = make_invocation_hatnote(invokes)
-- Categorize
local cats = categorize_template(pagename, #invokes > 0, header == "metatemplate")
if header == "none" then
return cats
elseif result == "" and invocation_hatnote == "" then
return ""
return ""
elseif result == "" and invocation_hatnote ~= "" then
elseif result == "" and invocation_hatnote ~= "" then
return string.format(":''%s''", invocation_hatnote)
return string.format(": ''%s''%s\n", invocation_hatnote, cats)
elseif result ~= "" and invocation_hatnote == "" then
elseif result ~= "" and invocation_hatnote == "" then
return string.format(":''%s''", result)
return string.format(": ''%s''%s\n", result, cats)
else
else
return string.format(":''%s''\n:''%s''", result, invocation_hatnote)
return string.format(": ''%s''\n: ''%s'' %s\n", result, invocation_hatnote, cats)
end
end
end
end
Line 278: Line 297:
-- If header is none, skip everything
-- If header is none, skip everything
if header == "none" then
if header == "none" then
return categorize(namespace, pagename)
--return categorize(namespace, pagename)
end
end


-- Call appropriate hatnote-making function
-- Call appropriate hatnote-making function
-- Remove /doc suffix if this is on a /doc page to ensure links are made
-- Remove /doc suffix if this is on a /doc page to ensure links are made
-- properly.
-- properly. :gsub("/doc$", "")
local result = ""
local result = ""
if namespace == "Module" then
if namespace == "Module" then
result = p.make_module_hatnote(header, pagename:gsub("/doc$", ""), corr_template:gsub("/doc$", ""), detect_corr_page)
result = p.make_module_hatnote(header, pagename, corr_template, detect_corr_page)
elseif namespace == "Template" then
elseif namespace == "Template" then
result = p.make_template_hatnote(header, pagename:gsub("/doc$", ""), corr_module:gsub("/doc$", ""), detect_corr_page)
result = p.make_template_hatnote(header, pagename, corr_module, detect_corr_page)
else
else
result = ":''This documentation template is in the wrong namespace. It should be within the Template or Module namespaces.''\n"
result = ": ''This documentation template is in the wrong namespace. It should be within the Template or Module namespaces.''\n"
end
end


-- Categorization and output
return result
-- has_link only has an effect if this is used for template documentation.
local has_link = namespace == "Template" and iutils.page_exists("Module:" .. corr_module)
if result == "" then
return categorize(namespace, pagename, has_link)
else
return string.format("%s%s\n", result, categorize(namespace, pagename, has_link))
end
end
end


Line 327: Line 339:
-- Option to detect corresponding page (default true)
-- Option to detect corresponding page (default true)
args["detect_corr_page"] = args["detect_corr_page"] == nil and true or yesno(args["detect_corr_page"])
args["detect_corr_page"] = args["detect_corr_page"] == nil and true or yesno(args["detect_corr_page"])
local result = p._dochead(args)
    -- Debugger option to show generated WikiText
    local wtext = yesno(frame.args["wtext"] or args["wtext"])
if wtext == true then
result = "<syntaxhighlight lang=\"wikitext\">" .. result .. "</syntaxhighlight>"
end


return p._dochead(args)
return frame:preprocess(result)
end
end