Module:Find sources/autodoc
Appearance
This module provides automatic documentation for templates based on Module:Find sources. See Module:Find sources#Automatic documentation for an overview.
-- Config
local cfg = {}
cfg['example-search-term'] = 'Example'
cfg['link-table-code-header'] = 'Code'
cfg['link-table-description-header'] = 'Description'
cfg['link-table-example-header'] = 'Example'
cfg['link-table-config-header'] = 'Configuration'
cfg['link-table-main-config-link-display'] = 'main'
cfg['link-table-autodoc-config-link-display'] = 'documentation'
cfg['link-table-notes-header'] = 'Notes'
-- Define constants
local ROOT_PAGE = 'Module:Find sources'
local TEMPLATE_ROOT = ROOT_PAGE .. '/templates/' -- for template config modules
local LINK_ROOT = ROOT_PAGE .. '/links/' -- for link config modules
local AUTODOC_SUFFIX = '/autodoc'
-- Load necessary modules.
local mFindSources = require('Module:Find sources')
local p = {}
local function maybeLoadData(page)
local success, data = pcall(mw.loadData, page)
return success and data
end
local function escapePattern(s)
return s:gsub('%p', '%%%0')
end
local function getPrefixPagenames(prefix)
local specialText = string.format('{{Special:PrefixIndex/%s}}', prefix)
specialText = mw.getCurrentFrame():preprocess(specialText)
specialText = mw.text.unstrip(specialText)
local pagenames = {}
for s in string.gmatch(specialText, '<a href="[^"]*" title="([^"]*)"[^>]*>[^<]*</a>') do
pagenames[#pagenames + 1] = mw.text.decode(s)
end
return pagenames
end
local function getSubpages(pagenames, prefix)
local stripped = {}
for i, page in ipairs(pagenames) do
local pattern = '^' .. escapePattern(prefix) -- Turn the prefix into a Lua pattern
stripped[i] = mw.ustring.gsub(page, pattern, '')
end
return stripped
end
local function getPrefixSubpages(prefix)
return getSubpages(getPrefixPagenames(prefix), prefix)
end
local function getFilteredPrefixSubpages(prefix)
-- Filter out unwanted pages from the subpage list. For now, this means
-- the autodoc pages.
local subpages = getPrefixSubpages(prefix)
local pattern = escapePattern(AUTODOC_SUFFIX) .. '$'
local filtered = {}
for _, subpage in ipairs(subpages) do
if not mw.ustring.find(subpage, pattern) then
filtered[#filtered + 1] = subpage
end
end
return filtered
end
local function makeWikitable(headers, rows)
local ret = {}
-- Table start
ret[#ret + 1] = '{| class="wikitable"'
-- Headers
ret[#ret + 1] = '|-'
for i, header in ipairs(headers) do
ret[#ret + 1] = '! ' .. header
end
-- Rows
for i, row in ipairs(rows) do
ret[#ret + 1] = '|-'
for j, cell in ipairs(row) do
ret[#ret + 1] = '| ' .. cell
end
end
-- Table end
ret[#ret + 1] = '|}'
return table.concat(ret, '\n')
end
local function grey(s)
return string.format('<span style="color: gray;">%s</span>', s)
end
local function makeWikilink(page, display)
if display then
return string.format('[[%s|%s]]', page, display)
else
return string.format('[[%s]]', page)
end
end
function p.linkTable()
local codes = getFilteredPrefixSubpages(LINK_ROOT)
local headers = {
cfg['link-table-code-header'],
cfg['link-table-description-header'],
cfg['link-table-example-header'],
cfg['link-table-config-header'],
cfg['link-table-notes-header']
}
local rows = {}
for i, code in ipairs(codes) do
local configPage = LINK_ROOT .. code
local autodocConfigPage = configPage .. AUTODOC_SUFFIX
local linkData = maybeLoadData(autodocConfigPage) or {}
local row = {
"'''" .. code .. "'''",
linkData.description or grey("''No description available''"),
mFindSources._renderLink(code, {cfg['example-search-term']}),
string.format(
'%s, %s',
makeWikilink(configPage, cfg['link-table-main-config-link-display']),
makeWikilink(autodocConfigPage, cfg['link-table-autodoc-config-link-display'])
),
linkData.notes or ''
}
rows[i] = row
end
return makeWikitable(headers, rows)
end
function p.documentation(frame)
-- This function makes documentation for the template specified in
-- frame.args[1]. The template name should be without the "Template:"
-- prefix.
-- Load necessary modules
local mDocumentation = require('Module:Documentation')
local mList = require('Module:List')
-- Get the template name
local template = frame.args[1] or ''
template = mw.text.trim(template)
if template == '' then
error('no template name specified')
end
-- Load the config files
local templateCfg = maybeLoadData(TEMPLATE_ROOT .. template)
if not templateCfg then
error(string.format(
"invalid template name '%s'; no template config found at [[%s]]",
template,
TEMPLATE_ROOT .. template
))
end
local autodocCfg = maybeLoadData(TEMPLATE_ROOT .. template .. AUTODOC_SUFFIX) or {}
-- Get the documentation content
local content
do
-- Shortcuts
local shortcuts
if autodocCfg.shortcuts then
shortcuts = frame:expandTemplate{title = 'Template shortcut', args = autodocCfg.shortcuts}
end
-- Link descriptions
local codes = {}
if templateCfg.introLink then
codes[#codes + 1] = templateCfg.introLink.code
end
for _, t in ipairs(templateCfg.links) do
codes[#codes + 1] = t.code
end
for i, code in ipairs(codes) do
local linkAutodocCfg = maybeLoadData(LINK_ROOT .. code .. AUTODOC_SUFFIX) or {}
codes[i] = linkAutodocCfg.description or string.format("'''%s'''", code)
end
local linkDescriptions = mList.unbulleted(codes)
-- Build the content.
content = frame:expandTemplate{title = 'Find sources documentation', args = {
template = template,
shortcuts = shortcuts,
isUsedInMainspace = templateCfg.isUsedInMainspace and 'yes' or nil,
linkDescriptions = linkDescriptions
}}
end
return content
end
return p