Module:Find sources/autodoc: Difference between revisions
From Zoophilia Wiki
Jump to navigationJump to search
meta>Mr. Stradivarius (add a makeWikitable helper function, and start functions for link and template tables) |
m (36 revisions imported) |
||
(33 intermediate revisions by one other user 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_LIST = ROOT_PAGE .. '/links' -- link config module list | |||
local LINK_ROOT = LINK_LIST .. '/' -- link config module prefix | |||
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 p = {} | ||
Line 14: | Line 18: | ||
end | end | ||
local function | local function substituteParams(msg, ...) | ||
local | return mw.message.newRawMessage(msg, ...):plain() | ||
end | |||
local function sortKeys(t) | |||
for s in | 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 linkCfg = maybeLoadData(LINK_ROOT .. 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 | end | ||
return | local templateCfg = maybeLoadData(TEMPLATE_ROOT .. template) | ||
return isValidTemplateCfg(templateCfg) | |||
end | end | ||
local function | local function isValidLinkAutdocCfg(t) | ||
if type(t) ~= 'table' then | |||
return false | |||
end | end | ||
return | for _, s in ipairs{'description', 'notes'} do | ||
if t[s] and type(t[s]) ~= 'string' then | |||
return false | |||
end | |||
end | |||
return true | |||
end | end | ||
local function | local function isValidTemplateAutdocCfg(t) | ||
return | 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 | end | ||
local function makeWikitable(headers, | local function makeWikitable(headers, rows) | ||
local ret = {} | local ret = {} | ||
Line 51: | Line 156: | ||
-- Rows | -- Rows | ||
for i, row in ipairs | for i, row in ipairs(rows) do | ||
ret[#ret + 1] = '|-' | ret[#ret + 1] = '|-' | ||
for j, cell in ipairs(row) do | for j, cell in ipairs(row) do | ||
Line 62: | Line 167: | ||
return table.concat(ret, '\n') | return table.concat(ret, '\n') | ||
end | |||
local function grey(s) | |||
return string.format('<span style="color: gray;">%s</span>', s) | |||
end | |||
local function bold(s) | |||
return string.format("'''%s'''", 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 | end | ||
function p.linkTable() | function p.linkTable() | ||
local codes = | local codes = sortKeys(require(LINK_LIST)) | ||
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 | |||
if isValidLink(code) then | |||
local configPage = LINK_ROOT .. code | |||
local autodocConfigPage = configPage .. AUTODOC_SUFFIX | |||
local linkData = maybeLoadData(autodocConfigPage) | |||
if not isValidLinkAutdocCfg(linkData) then | |||
linkData = {} | |||
end | |||
-- 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 = { | |||
bold(code), | |||
linkData.description or grey("''No description available''"), | |||
link, | |||
table.concat({ | |||
makeWikilink(configPage, cfg['link-table-main-config-link-display']), | |||
makeWikilink(autodocConfigPage, cfg['link-table-autodoc-config-link-display']) | |||
}, cfg['table-config-separator']), | |||
linkData.notes or '' | |||
} | |||
rows[i] = row | |||
else | |||
local msg = substituteParams( | |||
cfg['invalid-link-config-error'], | |||
LINK_ROOT .. code | |||
) | |||
msg = makeWikitextError(msg) | |||
msg = colspan(msg, 5) | |||
rows[i] = {msg} | |||
end | |||
end | |||
return makeWikitable(headers, rows) | |||
end | end | ||
function p.templateTable() | function p.templateTable() | ||
local templates = | 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 = { | |||
bold(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 | |||
for i, code in ipairs(codes) do | |||
local linkAutodocCfg = maybeLoadData(LINK_ROOT .. code .. AUTODOC_SUFFIX) | |||
if not isValidLinkAutdocCfg(linkAutodocCfg) then | |||
linkAutodocCfg = {} | |||
end | |||
codes[i] = linkAutodocCfg.description or code | |||
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 | end | ||
setmetatable(p, { __index = function(t, template) | |||
return function() | |||
return documentation(template) | |||
end | |||
end}) | |||
return p | return p |
Latest revision as of 04:29, 3 September 2020
Documentation for this module may be created at Module:Find sources/autodoc/doc
-- 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_LIST = ROOT_PAGE .. '/links' -- link config module list local LINK_ROOT = LINK_LIST .. '/' -- link config module prefix 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 linkCfg = maybeLoadData(LINK_ROOT .. 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 isValidLinkAutdocCfg(t) if type(t) ~= 'table' then return false end for _, s in ipairs{'description', 'notes'} do if t[s] and type(t[s]) ~= 'string' then return false end end return true 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] = '! ' .. 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 bold(s) return string.format("'''%s'''", 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_LIST)) 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 if isValidLink(code) then local configPage = LINK_ROOT .. code local autodocConfigPage = configPage .. AUTODOC_SUFFIX local linkData = maybeLoadData(autodocConfigPage) if not isValidLinkAutdocCfg(linkData) then linkData = {} end -- 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 = { bold(code), linkData.description or grey("''No description available''"), link, table.concat({ makeWikilink(configPage, cfg['link-table-main-config-link-display']), makeWikilink(autodocConfigPage, cfg['link-table-autodoc-config-link-display']) }, cfg['table-config-separator']), linkData.notes or '' } rows[i] = row else local msg = substituteParams( cfg['invalid-link-config-error'], LINK_ROOT .. 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 = { bold(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 for i, code in ipairs(codes) do local linkAutodocCfg = maybeLoadData(LINK_ROOT .. code .. AUTODOC_SUFFIX) if not isValidLinkAutdocCfg(linkAutodocCfg) then linkAutodocCfg = {} end codes[i] = linkAutodocCfg.description or code 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