Module:module documentation
You might want to create a documentation page for this Scribunto module. Editors can experiment in this module's sandbox (create | mirror) and testcases (create) pages. Please add categories to the /doc subpage. Subpages of this module. |
--[===[
This module automatically generates documentation for other modules. It fetches in-line comments in Lua code and converts them into a form that can be used on a documentation page via {{tl|module documentation}}. In fact, this module's documentation is an example of it in action!
It's helpful to do documentation this way, as it means function/method documentation is available in two places: at the top of the module page (as conventional Wikitext), and above the function itself (as a Lua comment). Each suits a different kind of editing style, and doing it this way keeps them synchronised.
A section of documentation is given using Lua's multi-line comment syntax, which looks something like this: {--[==[ ... ]==]}.
]===]
local export = {}
local function format_doc(str)
return (str
:gsub('%f[\n,{]\n%f[^\n*#:;]', '\n\n') -- wiki newlines
:gsub('(\n[ *#:]*)(|?[_%w]+=?):', '%1<code><b>%2</b></code>:') -- parameter names
:gsub('%b{}', function(m0) -- {} blocks
if m0:sub(2, 2) == '{' and m0:sub(-2, -2) == '}' then return nil end
return '<syntaxhighlight lang=lua' .. (m0:match'\n' and '' or ' inline') .. '>' .. m0:sub(2, -2) .. '</syntaxhighlight>'
end))
end
--[===[
The main entrypoint for {{tl|module documentation}}. The frame object can contain 3 optional arguments:
* |comment_level=: The number of equals signs (=) a given section uses. Default: 2 (i.e. {--[==[ ... (comment block) ]==]})
*: e.g. The value 4 means {--[====[ ... (comment block) ]====]}.
* |section_level=: The header level used for each function/method. Default: 2 (i.e. L2: {== ... ==}).
* |identifier=: A Lua string pattern. Only the comments of functions whose names match this pattern are used. When not given, all function are accepted.
*: This is useful when giving object methods, using a pattern such as {^object_name:}.
]===]
function export.show(frame)
local args = frame:getParent().args or {}
local comment_level = tonumber(args['comment_level']) or 2
local pattern_comment = '%-%-%[' .. ('='):rep(comment_level) .. '%[\n?(.-)\n?]' .. ('='):rep(comment_level) .. ']()'
local section_mark = ('='):rep(tonumber(args['section_level']) or 2)
local pattern_identifier = args['identifier'] or ''
local mod_title = mw.title.getCurrentTitle()
if mod_title.text:match'/documentation$' then return '(<i>The generated documentation is located at the module page.</i>)' end
local mod_text = mod_title:getContent()
if not mod_text then return '(<i>The module page does not exist now.</i>)' end
local chunk
local leading_section_raw = mod_text:match('^' .. pattern_comment)
if leading_section_raw then
chunk = { format_doc(leading_section_raw) }
else chunk = {} end
for p0, f, fn in mod_text:gmatch('()\n[ \t]*function +(([^\n(]+)[^\n)]+%))') do
if fn:match(pattern_identifier) then
local c = mod_text:sub(1, p0 - 1):match('^.*' .. pattern_comment .. '%s*$')
table.insert(chunk, section_mark .. fn .. section_mark .. '\n\n' .. '<syntaxhighlight lang=lua inline>function ' .. f .. '</syntaxhighlight>\n\n' .. format_doc(c or '<strong class="error">This function lacks documentation. Please add a description of its usages, inputs and outputs, or its difference from similar functions, or make it local to remove it from the function list.</strong>[[Category:Templates and modules needing documentation]]'))
end
end
local postscriptum = mod_text:match('^.*' .. pattern_comment .. '%s*$')
if postscriptum then
table.insert(chunk, section_mark .. 'Usage notes' .. section_mark .. '\n\n' .. format_doc(postscriptum))
end
return frame:preprocess(table.concat(chunk, '\n\n'))
end
return export
--[===[
* All local functions are ignored, because they are invisible outside the module.
* The one exception to this is when object methods are defined inside a local function, as the object may be returned by the module.
* Curly brackets in comments are used as a shortcut for syntaxhighlight, as using syntaxhighlight doesn't work otherwise.
]===]