Module:Find sources/autodoc: Difference between revisions
From All Skies Encyclopaedia
imported>Mr. Stradivarius change end box section link |
imported>Gonnym use proper scopes which automatically apply bold |
||
| (14 intermediate revisions by 2 users not shown) | |||
| Line 1: | Line 1: | ||
-- Define constants | -- Define constants | ||
local ROOT_PAGE = 'Module:Find sources' | local ROOT_PAGE = 'Module:Find sources' | ||
local | local TEMPLATE_LIST = ROOT_PAGE .. '/templates' -- template config module list | ||
local | local TEMPLATE_ROOT = TEMPLATE_LIST .. '/' -- template config module prefix | ||
local LINK_CONFIG = ROOT_PAGE .. '/links' -- link config module list | |||
local AUTODOC_SUFFIX = '/autodoc' | local AUTODOC_SUFFIX = '/autodoc' | ||
-- Load necessary modules. | -- Load necessary modules. | ||
local mFindSources = require('Module:Find sources') | local mFindSources = require('Module:Find sources') | ||
local cfg = mw.loadData('Module:Find sources/autodoc/config') | |||
local p = {} | local p = {} | ||
| Line 37: | Line 17: | ||
end | end | ||
local function | local function substituteParams(msg, ...) | ||
return | return mw.message.newRawMessage(msg, ...):plain() | ||
end | end | ||
local function | local function sortKeys(t) | ||
local | local ret = {} | ||
for k in pairs(t) do | |||
ret[#ret + 1] = k | |||
for | |||
end | end | ||
return | table.sort(ret) | ||
return ret | |||
end | end | ||
local function | local function isValidLinkCfg(linkCfg) | ||
if type(linkCfg) ~= 'table' then | |||
for | return false | ||
end | |||
for _, s in ipairs{'url', 'display'} do | |||
if type(linkCfg[s]) ~= 'string' then | |||
return false | |||
end | |||
end | |||
for _, s in ipairs{'separator'} do | |||
if linkCfg[s] ~= nil and type(linkCfg[s]) ~= 'string' then | |||
return false | |||
end | |||
end | end | ||
return | return true | ||
end | end | ||
local function | local function isValidLink(code) | ||
return | if type(code) ~= 'string' or code == '' then | ||
return false | |||
end | |||
local links = maybeLoadData(LINK_CONFIG) | |||
local linkCfg = links[code] | |||
return isValidLinkCfg(linkCfg) | |||
end | end | ||
local function | local function isValidTemplateCfg(templateCfg) | ||
if type(templateCfg) ~= 'table' then | |||
return false | |||
end | |||
for _, s in ipairs{'blurb'} do | |||
if type(templateCfg[s]) ~= 'string' then | |||
for _, | return false | ||
if | end | ||
end | |||
for _, s in ipairs{'separator', 'class', 'style'} do | |||
if templateCfg[s] ~= nil and type(templateCfg[s]) ~= 'string' then | |||
return false | |||
end | end | ||
end | end | ||
return | if templateCfg.isUsedInMainspace and templateCfg.isUsedInMainspace ~= true then | ||
end | return false | ||
end | |||
if type(templateCfg.links) ~= 'table' then | |||
return false | |||
end | |||
local function isValidLinkTable(t) | |||
if type(t) ~= 'table' then | |||
return false | |||
end | |||
if type(t.code) ~= 'string' then | |||
return false | |||
end | |||
if t.display and type(t.display) ~= 'string' then | |||
return false | |||
end | |||
return true | |||
end | |||
if templateCfg.introLink and not isValidLinkTable(templateCfg.introLink) then | |||
return false | |||
end | |||
for _, t in ipairs(templateCfg.links) do | |||
if not isValidLinkTable(t) then | |||
return false | |||
end | |||
end | |||
return true | |||
end | |||
local function isValidTemplate(template) | |||
if type(template) ~= 'string' or template == '' then | |||
return false | |||
end | |||
local templateCfg = maybeLoadData(TEMPLATE_ROOT .. template) | |||
return isValidTemplateCfg(templateCfg) | |||
end | |||
local function isValidTemplateAutdocCfg(t) | |||
if type(t) ~= 'table' then | |||
return false | |||
end | |||
for _, s in ipairs{'description', 'docIntro'} do | |||
if t[s] and type(t[s]) ~= 'string' then | |||
return false | |||
end | |||
end | |||
if t.shortcuts and type(t.shortcuts) ~= 'table' then | |||
return false | |||
elseif t.shortcuts then | |||
for _, s in ipairs(t.shortcuts) do | |||
if type(s) ~= 'string' then | |||
return false | |||
end | |||
end | |||
end | |||
return true | |||
end | |||
local function makeWikitable(headers, rows) | local function makeWikitable(headers, rows) | ||
| Line 88: | Line 140: | ||
ret[#ret + 1] = '|-' | ret[#ret + 1] = '|-' | ||
for i, header in ipairs(headers) do | for i, header in ipairs(headers) do | ||
ret[#ret + 1] = '! ' .. header | ret[#ret + 1] = '! scope="col | ' .. header | ||
end | end | ||
| Line 95: | Line 147: | ||
ret[#ret + 1] = '|-' | ret[#ret + 1] = '|-' | ||
for j, cell in ipairs(row) do | for j, cell in ipairs(row) do | ||
ret[#ret + 1] = '| ' .. cell | if j == 1 then | ||
ret[#ret + 1] = '! scope="row" | ' .. cell | |||
else | |||
ret[#ret + 1] = '| ' .. cell | |||
end | |||
end | end | ||
end | end | ||
| Line 109: | Line 165: | ||
end | end | ||
local function | local function colspan(s, n) | ||
return string.format("'' | return string.format('colspan="%d" | %s', n, s) | ||
end | |||
local function makeWikitextError(msg) | |||
return string.format('<strong class="error">%s</strong>', msg) | |||
end | end | ||
| Line 122: | Line 182: | ||
function p.linkTable() | function p.linkTable() | ||
local codes = | local codes = sortKeys(require(LINK_CONFIG)) | ||
local headers = { | local headers = { | ||
cfg['link-table-code-header'], | cfg['link-table-code-header'], | ||
cfg['link-table-description-header'], | cfg['link-table-description-header'], | ||
cfg['link-table-example-header'], | cfg['link-table-example-header'], | ||
cfg['link-table-notes-header'] | cfg['link-table-notes-header'] | ||
} | } | ||
local rows = {} | local rows = {} | ||
local links = maybeLoadData(LINK_CONFIG) | |||
for i, code in ipairs(codes) do | for i, code in ipairs(codes) do | ||
local | if isValidLink(code) then | ||
local linkData = links[code] | |||
-- Make the example link. | |||
local success, link = pcall( | |||
mFindSources._renderLink, | |||
code, | |||
{cfg['example-search-term']} | |||
) | |||
if not success then | |||
link = makeWikitextError(link) | |||
end | |||
-- Build the row. | |||
local row = { | |||
code, | |||
linkData.description or grey("''No description available''"), | |||
link, | |||
linkData.notes or '', | |||
} | |||
rows[i] = row | |||
else | |||
local msg = substituteParams(cfg['invalid-link-config-error'], code) | |||
msg = makeWikitextError(msg) | |||
msg = colspan(msg, 5) | |||
rows[i] = {msg} | |||
end | |||
end | end | ||
return makeWikitable(headers, rows) | return makeWikitable(headers, rows) | ||
| Line 151: | Line 225: | ||
function p.templateTable() | function p.templateTable() | ||
local templates = | local templates = sortKeys(require(TEMPLATE_LIST)) | ||
local headers = { | local headers = { | ||
cfg['template-table-template-header'], | cfg['template-table-template-header'], | ||
| Line 160: | Line 234: | ||
local rows = {} | local rows = {} | ||
for i, template in ipairs(templates) do | for i, template in ipairs(templates) do | ||
local configPage = TEMPLATE_ROOT .. template | if isValidTemplate(template) then | ||
local configPage = TEMPLATE_ROOT .. template | |||
local autodocConfigPage = configPage .. AUTODOC_SUFFIX | |||
local templateData = maybeLoadData(autodocConfigPage) | |||
if not isValidTemplateAutdocCfg(templateData) then | |||
templateData = {} | |||
end | |||
-- Make the example text | |||
local success, example = pcall( | |||
mFindSources._main, | |||
template, | |||
rows[i] = | {cfg['example-search-term']} | ||
) | |||
if not success then | |||
example = makeWikitextError(example) | |||
end | |||
-- Build the row. | |||
local row = { | |||
makeWikilink(mw.site.namespaces[10].name .. ':' .. template, template), | |||
templateData.description or grey("''No description available''"), | |||
example, | |||
table.concat({ | |||
makeWikilink(configPage, cfg['template-table-main-config-link-display']), | |||
makeWikilink(autodocConfigPage, cfg['template-table-autodoc-config-link-display']) | |||
}, cfg['table-config-separator']) | |||
} | |||
rows[i] = row | |||
else | |||
local msg = substituteParams( | |||
cfg['invalid-template-config-error'], | |||
TEMPLATE_ROOT .. template | |||
) | |||
msg = makeWikitextError(msg) | |||
msg = colspan(msg, 4) | |||
rows[i] = {msg} | |||
end | |||
end | end | ||
return makeWikitable(headers, rows) | return makeWikitable(headers, rows) | ||
| Line 179: | Line 278: | ||
local function documentation(template) | local function documentation(template) | ||
-- This function makes documentation for the template specified in | -- This function makes documentation for the template specified in | ||
-- | -- the template parameter. The template should be without the "Template:" | ||
-- prefix. | -- prefix. | ||
| Line 189: | Line 288: | ||
-- Load the config files | -- Load the config files | ||
local templateCfg = maybeLoadData(TEMPLATE_ROOT .. template) | local templateCfg = maybeLoadData(TEMPLATE_ROOT .. template) | ||
if not templateCfg then | if not isValidTemplateCfg(templateCfg) then | ||
error( | error(substituteParams( | ||
cfg['invalid-template-name-error'], | |||
template, | template, | ||
TEMPLATE_ROOT .. template | TEMPLATE_ROOT .. template | ||
)) | )) | ||
end | end | ||
local autodocCfg = maybeLoadData(TEMPLATE_ROOT .. template .. AUTODOC_SUFFIX) | local autodocCfg = maybeLoadData(TEMPLATE_ROOT .. template .. AUTODOC_SUFFIX) | ||
if not isValidTemplateAutdocCfg(autodocCfg) then | |||
autodocCfg = {} | |||
end | |||
-- Get the documentation content | -- Get the documentation content | ||
| Line 215: | Line 317: | ||
codes[#codes + 1] = t.code | codes[#codes + 1] = t.code | ||
end | end | ||
local links = maybeLoadData(LINK_CONFIG) | |||
for i, code in ipairs(codes) do | for i, code in ipairs(codes) do | ||
if links[code] then | |||
codes[i] = | codes[i] = links[code].description or code | ||
else | |||
codes[i] = code | |||
end | |||
end | end | ||
local linkDescriptions = mList.bulleted(codes) | local linkDescriptions = mList.bulleted(codes) | ||
| Line 225: | Line 332: | ||
template = template, | template = template, | ||
shortcuts = shortcuts, | shortcuts = shortcuts, | ||
docIntro = autodocCfg.docIntro, | |||
isUsedInMainspace = templateCfg.isUsedInMainspace and 'yes' or nil, | isUsedInMainspace = templateCfg.isUsedInMainspace and 'yes' or nil, | ||
linkDescriptions = linkDescriptions | linkDescriptions = linkDescriptions | ||
Latest revision as of 10:15, 6 December 2021
This module provides automatic documentation for templates based on Module:Find sources. See Module:Find sources for an overview.
-- Define constants
local ROOT_PAGE = 'Module:Find sources'
local TEMPLATE_LIST = ROOT_PAGE .. '/templates' -- template config module list
local TEMPLATE_ROOT = TEMPLATE_LIST .. '/' -- template config module prefix
local LINK_CONFIG = ROOT_PAGE .. '/links' -- link config module list
local AUTODOC_SUFFIX = '/autodoc'
-- Load necessary modules.
local mFindSources = require('Module:Find sources')
local cfg = mw.loadData('Module:Find sources/autodoc/config')
local p = {}
local function maybeLoadData(page)
local success, data = pcall(mw.loadData, page)
return success and data
end
local function substituteParams(msg, ...)
return mw.message.newRawMessage(msg, ...):plain()
end
local function sortKeys(t)
local ret = {}
for k in pairs(t) do
ret[#ret + 1] = k
end
table.sort(ret)
return ret
end
local function isValidLinkCfg(linkCfg)
if type(linkCfg) ~= 'table' then
return false
end
for _, s in ipairs{'url', 'display'} do
if type(linkCfg[s]) ~= 'string' then
return false
end
end
for _, s in ipairs{'separator'} do
if linkCfg[s] ~= nil and type(linkCfg[s]) ~= 'string' then
return false
end
end
return true
end
local function isValidLink(code)
if type(code) ~= 'string' or code == '' then
return false
end
local links = maybeLoadData(LINK_CONFIG)
local linkCfg = links[code]
return isValidLinkCfg(linkCfg)
end
local function isValidTemplateCfg(templateCfg)
if type(templateCfg) ~= 'table' then
return false
end
for _, s in ipairs{'blurb'} do
if type(templateCfg[s]) ~= 'string' then
return false
end
end
for _, s in ipairs{'separator', 'class', 'style'} do
if templateCfg[s] ~= nil and type(templateCfg[s]) ~= 'string' then
return false
end
end
if templateCfg.isUsedInMainspace and templateCfg.isUsedInMainspace ~= true then
return false
end
if type(templateCfg.links) ~= 'table' then
return false
end
local function isValidLinkTable(t)
if type(t) ~= 'table' then
return false
end
if type(t.code) ~= 'string' then
return false
end
if t.display and type(t.display) ~= 'string' then
return false
end
return true
end
if templateCfg.introLink and not isValidLinkTable(templateCfg.introLink) then
return false
end
for _, t in ipairs(templateCfg.links) do
if not isValidLinkTable(t) then
return false
end
end
return true
end
local function isValidTemplate(template)
if type(template) ~= 'string' or template == '' then
return false
end
local templateCfg = maybeLoadData(TEMPLATE_ROOT .. template)
return isValidTemplateCfg(templateCfg)
end
local function isValidTemplateAutdocCfg(t)
if type(t) ~= 'table' then
return false
end
for _, s in ipairs{'description', 'docIntro'} do
if t[s] and type(t[s]) ~= 'string' then
return false
end
end
if t.shortcuts and type(t.shortcuts) ~= 'table' then
return false
elseif t.shortcuts then
for _, s in ipairs(t.shortcuts) do
if type(s) ~= 'string' then
return false
end
end
end
return true
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] = '! scope="col | ' .. header
end
-- Rows
for i, row in ipairs(rows) do
ret[#ret + 1] = '|-'
for j, cell in ipairs(row) do
if j == 1 then
ret[#ret + 1] = '! scope="row" | ' .. cell
else
ret[#ret + 1] = '| ' .. cell
end
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 colspan(s, n)
return string.format('colspan="%d" | %s', n, s)
end
local function makeWikitextError(msg)
return string.format('<strong class="error">%s</strong>', msg)
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 = sortKeys(require(LINK_CONFIG))
local headers = {
cfg['link-table-code-header'],
cfg['link-table-description-header'],
cfg['link-table-example-header'],
cfg['link-table-notes-header']
}
local rows = {}
local links = maybeLoadData(LINK_CONFIG)
for i, code in ipairs(codes) do
if isValidLink(code) then
local linkData = links[code]
-- Make the example link.
local success, link = pcall(
mFindSources._renderLink,
code,
{cfg['example-search-term']}
)
if not success then
link = makeWikitextError(link)
end
-- Build the row.
local row = {
code,
linkData.description or grey("''No description available''"),
link,
linkData.notes or '',
}
rows[i] = row
else
local msg = substituteParams(cfg['invalid-link-config-error'], code)
msg = makeWikitextError(msg)
msg = colspan(msg, 5)
rows[i] = {msg}
end
end
return makeWikitable(headers, rows)
end
function p.templateTable()
local templates = sortKeys(require(TEMPLATE_LIST))
local headers = {
cfg['template-table-template-header'],
cfg['template-table-description-header'],
cfg['template-table-example-header'],
cfg['template-table-config-header'],
}
local rows = {}
for i, template in ipairs(templates) do
if isValidTemplate(template) then
local configPage = TEMPLATE_ROOT .. template
local autodocConfigPage = configPage .. AUTODOC_SUFFIX
local templateData = maybeLoadData(autodocConfigPage)
if not isValidTemplateAutdocCfg(templateData) then
templateData = {}
end
-- Make the example text
local success, example = pcall(
mFindSources._main,
template,
{cfg['example-search-term']}
)
if not success then
example = makeWikitextError(example)
end
-- Build the row.
local row = {
makeWikilink(mw.site.namespaces[10].name .. ':' .. template, template),
templateData.description or grey("''No description available''"),
example,
table.concat({
makeWikilink(configPage, cfg['template-table-main-config-link-display']),
makeWikilink(autodocConfigPage, cfg['template-table-autodoc-config-link-display'])
}, cfg['table-config-separator'])
}
rows[i] = row
else
local msg = substituteParams(
cfg['invalid-template-config-error'],
TEMPLATE_ROOT .. template
)
msg = makeWikitextError(msg)
msg = colspan(msg, 4)
rows[i] = {msg}
end
end
return makeWikitable(headers, rows)
end
local function documentation(template)
-- This function makes documentation for the template specified in
-- the template parameter. The template should be without the "Template:"
-- prefix.
-- Load necessary modules
local mDocumentation = require('Module:Documentation')
local mList = require('Module:List')
local frame = mw.getCurrentFrame()
-- Load the config files
local templateCfg = maybeLoadData(TEMPLATE_ROOT .. template)
if not isValidTemplateCfg(templateCfg) then
error(substituteParams(
cfg['invalid-template-name-error'],
template,
TEMPLATE_ROOT .. template
))
end
local autodocCfg = maybeLoadData(TEMPLATE_ROOT .. template .. AUTODOC_SUFFIX)
if not isValidTemplateAutdocCfg(autodocCfg) then
autodocCfg = {}
end
-- 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
local links = maybeLoadData(LINK_CONFIG)
for i, code in ipairs(codes) do
if links[code] then
codes[i] = links[code].description or code
else
codes[i] = code
end
end
local linkDescriptions = mList.bulleted(codes)
-- Build the content.
content = frame:expandTemplate{title = 'Find sources documentation', args = {
template = template,
shortcuts = shortcuts,
docIntro = autodocCfg.docIntro,
isUsedInMainspace = templateCfg.isUsedInMainspace and 'yes' or nil,
linkDescriptions = linkDescriptions
}}
end
return mDocumentation.main{content = content, ['link box'] = cfg['end-box-blurb']}
end
setmetatable(p, { __index = function(t, template)
return function()
return documentation(template)
end
end})
return p





