Jump to content

Module:Find sources/autodoc/sandbox

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Pppery (talk | contribs) at 20:48, 15 February 2019. The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
-- 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/sandbox')
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 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(frame)
	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
		local autodocConfigPage = TEMPLATE_ROOT .. template .. AUTODOC_SUFFIX
		local templateData = maybeLoadData(autodocConfigPage)
		if not isValidTemplateAutdocCfg(templateData) then
			templateData = {}
		end
		local example = frame:expandTemplate{title=template}
		-- 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
	end
	return makeWikitable(headers, rows)
end

function p.main(frame)
	-- 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 template = frame:getParent():getTitle()
	
	-- Remove "Template:"
	template = template:sub(10)
	if template:sub(-8) == '/sandbox' then
		-- This makes {{Find sources/sandbox|Albert Einstein}} work.
		template = template:sub(1, -9)
	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

		local args = frame.args
		-- Link descriptions
		local codes = {}
		if args.introlink and #args.introlink > 0 then
			codes[#codes + 1] = args.introlink
		end
		local linkno = 1
		while true do
			local linkArg = args["link"..tostring(linkno)]
			if linkArg == nil then
				break
			end
			codes[#codes + 1] = linkArg
			linkno = linkno + 1
		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 = frame.args.mainspace or nil,
			linkDescriptions = linkDescriptions
		}}
	end

	return mFindSources.main(frame) .. mDocumentation.main{content = content, ['link box'] = cfg['end-box-blurb'], page=template}
end

setmetatable(p, { __index = function(t, template)
	return function()
		return documentation(template)
	end
end})

return p