Module:Dochead: Difference between revisions

From Xenharmonic Wiki
Jump to navigation Jump to search
Ganaram inukshuk (talk | contribs)
bugfix blank hatnote output
Ganaram inukshuk (talk | contribs)
comments
Line 18: Line 18:
--  but direct use of module code is allowed)
--  but direct use of module code is allowed)


-- Detect whether a page exists, where pagename is "Namespace:Title"
-- Helper function
function p.page_exists(fullpagename)
-- Detect whether a page exists, where fullpagename is "Namespace:Title"
local function page_exists(fullpagename)
local title = mw.title.new(fullpagename)
local title = mw.title.new(fullpagename)
Line 29: Line 30:
end
end


function p.categorize(namespace, pagename, is_lua_based_template)
-- Helper function
-- Categorizes pages if they're in the right namespace, and based on the nature
-- of the page
local function categorize(namespace, pagename, is_lua_based_template)
local is_lua_based_template = is_lua_based_template or false
local is_lua_based_template = is_lua_based_template or false
local cats = ""
local cats = ""
Line 55: Line 59:
end
end


-- Main function
function p._dochead(args)
function p._dochead(args)
local namespace = args["namespace"]
local namespace = args["namespace"]
Line 64: Line 69:
-- If header is none, don't bother
-- If header is none, don't bother
if header == "none" then
if header == "none" then
return p.categorize(namespace, pagename)
return categorize(namespace, pagename)
end
end
Line 72: Line 77:


local result = ""
local result = ""
local has_template = p.page_exists(corr_template)
local has_template = page_exists(corr_template)
local has_module  = p.page_exists(corr_module)
local has_module  = page_exists(corr_module)


-- Handle each header type first
-- Handle each header type first, then namespace, then if applicable,
-- presence of a corresponding template or module.
if header == "dualuse" then
if header == "dualuse" then
if namespace == "Module" then
if namespace == "Module" then
-- A dual-use module MUST have a corresponding template; if not, say
-- it's missing.
if has_template then
if has_template then
result = string.format("This module may be invoked by templates using its corresponding [[%s|template]], or used directly from other modules.", corr_template)
result = string.format("This module may be invoked by templates using its corresponding [[%s|template]], or used directly from other modules.", corr_template)
else
else
result = header
result = "This module has a template that is currently missing, so should be used directly from other modules."
end
end
else
else
Line 89: Line 97:
elseif header == "metatemplate" then
elseif header == "metatemplate" then
if namespace == "Module" then
if namespace == "Module" then
-- A metatemplate-implementing module MUST have a corresponding
-- template since it's expected to be dual-use.
if has_template then
if has_template then
result = string.format("This module implements a metatemplate, and may be invoked by templates using its corresponding [[%s|template]], or used directly from other modules.", corr_template)
result = string.format("This module implements a metatemplate, and may be invoked by templates using its corresponding [[%s|template]], or used directly from other modules.", corr_template)
else
else
result = "This module implements a metatemplate."
result = "This module implements a metatemplate whose template is currently missing."
end
end
elseif namespace == "Template" then
elseif namespace == "Template" then
-- A metatemplate may either be lua-implemented or not.
if has_module then
if has_module then
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 [[%s]].", corr_module)
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 [[%s]].", corr_module)
Line 105: Line 116:


elseif header == "noinvoke" then
elseif header == "noinvoke" then
-- A noinvoke module MUST have a corresponding template. Since this is
-- the default for modules, the absence of a template results in the
-- message being blank.
if namespace == "Module" then
if namespace == "Module" then
if has_template then
if has_template then
Line 110: Line 124:
else
else
result = header
result = header
--result = "This module's corresponding template is currently missing."
end
end
else
else
Line 116: Line 131:


elseif header == "library" or header == "metamodule" then
elseif header == "library" or header == "metamodule" then
-- A metamodule should NOT have a corresponding template.
if namespace == "Module" then
if namespace == "Module" then
result = "This module primarily serves as a library for other modules."
result = "This module primarily serves as a library for other modules."
Line 123: Line 139:


else
else
-- For any other case, just say that the module implements a template,
-- or a template invokes a module's function.
if namespace == "Module" then
if namespace == "Module" then
if has_template then
if has_template then
Line 145: Line 163:
local has_link = namespace == "Template" and has_module
local has_link = namespace == "Template" and has_module
if result == "" then
if result == "" then
return p.categorize(namespace, pagename, has_link)
return categorize(namespace, pagename, has_link)
else
else
return string.format(":''%s'' %s\n", result, p.categorize(namespace, pagename, has_link))
return string.format(":''%s'' %s\n", result, categorize(namespace, pagename, has_link))
end
end
end
end


-- Wrapper to be invoked
function p.dochead(frame)
function p.dochead(frame)
local args = getArgs(frame, { removeBlanks = true }) or {}
local args = getArgs(frame, { removeBlanks = true }) or {}

Revision as of 10:31, 28 October 2025

Module documentation[view] [edit] [history] [purge]
This module should not be invoked directly; use its corresponding template instead.
Module:Dochead is ready for use. This message indicates that a module is ready for use, or has recently been repaired. This message may be removed once this module has been used on several pages or once it is verified to work as intended.

Details: Functionally complete. Edge-case observations still ongoing. Links can now be viewed on /doc pages.

Introspection summary for Module:Dochead 
Functions provided (2)
Line Function Params
62 _dochead (main) (args)
172 dochead (invokable) (frame)
Lua modules required (1)
Variable Module Functions used
getArgs Module:Arguments getArgs

No function descriptions were provided. The Lua code may have further information.


-- This module follows [[User:Ganaram inukshuk/Provisional style guide for Lua]]
local getArgs = require("Module:Arguments").getArgs

local p = {}

-- Produces a hatnote that is placed on the top of a documentation page (either
-- template or module documentation) and can autodetect and categorize:
-- - FOR MODULES:
--   - whether a module has an accompanying template (overridable)
--   - whether a module is meant as a library for other modules
-- - FOR TEMPLATES:
--   - whether a template has an accompanying module (overridable)
--   - what functions from which modules are invoked

-- Options for specific types of templates and modules include:
-- - (TEMPLATES) whether it's a metatemplate
-- - (MODULES) whether it's a metamodule (used the same way as a metatemplate,
--   but direct use of module code is allowed)

-- Helper function
-- Detect whether a page exists, where fullpagename is "Namespace:Title"
local function page_exists(fullpagename)
	local title = mw.title.new(fullpagename)
	
	if title and title.exists then
		return true
	else
		return false
	end
end

-- Helper function
-- Categorizes pages if they're in the right namespace, and based on the nature
-- 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 = ""

	if pagename:sub(-4) == "/doc" then
		-- Documentation subpages
		if namespace == "Template" then
			cats = "[[Category:Template documentation]]"
		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]]"
		end
	end

	return cats
end

-- Main function
function p._dochead(args)
	local namespace = args["namespace"]
	local pagename  = args["pagename"]
	local header    = args["header"] or "none"
	local corr_template = args["temp"] or ("Template:" .. pagename)
	local corr_module   = args["mod"]  or ("Module:"   .. pagename)

	-- If header is none, don't bother
	if header == "none" then
		return categorize(namespace, pagename)
	end
	
	-- Remove doc subpage if present
	corr_template = corr_template:gsub("/doc$", "")
	corr_module   = corr_module  :gsub("/doc$", "")

	local result = ""
	local has_template = page_exists(corr_template)
	local has_module   = page_exists(corr_module)

	-- Handle each header type first, then namespace, then if applicable, 
	-- presence of a corresponding template or module.
	if header == "dualuse" then
		if namespace == "Module" then
			-- A dual-use module MUST have a corresponding template; if not, say
			-- it's missing.
			if has_template then
				result = string.format("This module may be invoked by templates using its corresponding [[%s|template]], or used directly from other modules.", corr_template)
			else
				result = "This module has a template that is currently missing, so should be used directly from other modules."
			end
		else
			result = "This template or its options is in the wrong namespace. It should be used within the Module namespace."
		end

	elseif header == "metatemplate" then
		if namespace == "Module" then
			-- A metatemplate-implementing module MUST have a corresponding
			-- template since it's expected to be dual-use.
			if has_template then
				result = string.format("This module implements a metatemplate, and may be invoked by templates using its corresponding [[%s|template]], or used directly from other modules.", corr_template)
			else
				result = "This module implements a metatemplate whose template is currently missing."
			end
		elseif namespace == "Template" then
			-- A metatemplate may either be lua-implemented or not.
			if has_module then
				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 [[%s]].", corr_module)
			else
				result = "This template is a metatemplate. It is used to build other templates and should not be used standalone, except for testing or simple usage."
			end
		else
			result = "This template or its options is in the wrong namespace. It should be within the Template or Module namespaces."
		end

	elseif header == "noinvoke" then
		-- A noinvoke module MUST have a corresponding template. Since this is
		-- the default for modules, the absence of a template results in the
		-- message being blank.
		if namespace == "Module" then
			if has_template then
				result = string.format("This module should not be invoked directly; use its corresponding [[%s|template]] instead.", corr_template)
			else
				result = header
				--result = "This module's corresponding template is currently missing."
			end
		else
			result = "This template or its options is in the wrong namespace. It should be used within the Module namespace."
		end

	elseif header == "library" or header == "metamodule" then
		-- A metamodule should NOT have a corresponding template.
		if namespace == "Module" then
			result = "This module primarily serves as a library for other modules."
		else
			result = "This template or its options is in the wrong namespace. It should be used within the Module namespace."
		end

	else
		-- For any other case, just say that the module implements a template,
		-- or a template invokes a module's function.
		if namespace == "Module" then
			if has_template then
				result = string.format("%s This module implements [[%s]].", header, corr_template)
			else
				result = header
			end
		elseif namespace == "Template" then
			if has_module then
				result = string.format("%s This template is implemented by the Lua module [[%s]].", header, corr_module)
			else
				result = header
			end
		else
			result = "This template or its options is in the wrong namespace. It should be used within the Template or Module namespaces."
		end
	end

	-- Append categorization info to hatnote
	-- Check whether hatnote is blank; if so, don't bother with hatnote, just
	-- output categories
	local has_link = namespace == "Template" and has_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

-- Wrapper to be invoked
function p.dochead(frame)
	local args = getArgs(frame, { removeBlanks = true }) or {}
	local title = mw.title.getCurrentTitle()

	-- Extract or parse args
	args["namespace"] = args["namespace"] or title.nsText
	args["pagename" ] = args["pagename" ] or title.text

	-- Extract header or set it to defaults
	if args["header"] == nil or args["header"] == "" then
		if args["namespace"] == "Module" then
			args["header"] = "noinvoke"
		else
			args["header"] = ""
		end
	end
	
	-- Extract template/module names, or autogenerate them
	args["temp"] = args["temp"] or ("Template:" .. args["pagename"])
	args["mod" ] = args["mod" ] or ("Module:"   .. args["pagename"])

	return p._dochead(args)
end

return p