Difference between revisions 51783 and 51784 on wikimaniawiki

-- This module implements {{documentation}}.

-- Get required modules.
local getArgs = require('Module:Arguments').getArgs
local htmlBuilder = require('Module:HtmlBuilder')
local messageBox = require('Module:Message box')

-- Get the config table.
local cfg = mw.loadData('Module:Documentation/config')

local p = {}

-- Constants.
local currentTitle = mw.title.getCurrentTitle()
local subjectSpace = mw.site.namespaces[currentTitle.namespace].subject.id -- The number of the current subject namespace.

-- Often-used functions.
local gsub = mw.ustring.gsub

----------------------------------------------------------------------------
-- Helper functions
----------------------------------------------------------------------------

local function message(cfgKey, expectType, valArray)
(contracted; show full)			end
		})
		return p[funcName](args)
	end
end

----------------------------------------------------------------------------
-- Main function
s
----------------------------------------------------------------------------

p.main = makeInvokeFunc('_main')

function p._main(args)
	-- Get environment data, using pcall in case we get any errors.
	local success, env = pcall(p.getEnv, args)
	if not success then
		return string.format('<strong class="error">[[Module:Documentation]] error: %s</strong>', env) -- If there's an error, env is the error message.
	end
	-- Build the documentation.
	local root = htmlBuilder.create()
	root
		.wikitext(p.protectionTemplate(env))
		.wikitext(p.sandboxNotice(args, env))
		 -- This div tag is from {{documentation/start box}}, but moving it here
		 -- so that we don't have to worry about unclosed tags.
		.tag('div')
			.attr('id', message('mainDivId', 'string'))
			.addClass(message('mainDivClasses', 'string'))
			.newline()
			.wikitext(p._startBox(args, env))
			.wikitext(p._content(args, env))
			.tag('div')
				.css('clear', 'both') -- So right or left floating items don't stick out of the doc box.
				.newline()
				.done()
			.done()
		.wikitext(p._endBox(args, env))
		.newline()
		.wikitext(p.addTrackingCategories(env))
	return tostring(root)
end

function p.sandboxNotice(args----------------------------------------------------------------------------
-- Environment settings
----------------------------------------------------------------------------

function p.getEnv(args)
	-- Returns a table with information about the environment, including the title to use, the subject namespace, etc.
	-- This is called from p._main using pcall in case we get any errors from exceeding the expensive function count
	-- limit, or other perils unknown.
	--
	-- Data includes:
	-- env.title - the title object of the page we are making documentation for (usually the current title)
	-- env.subjectSpace - the number of the title's subject namespace.
	-- env.docspace - the name of the namespace the title puts its documentation in.
	-- env.templatePage - the name of the template page with no namespace or interwiki prefixes.
	local env = {}

	-- Get the title.
	local title
	local titleArg = args[message('titleArg', 'string')]
	if titleArg then
		title = mw.title.new(titleArg)
		if not title then
			error(message('titleArgError', 'string', {titleArg}))
		end
	else
		title = mw.title.getCurrentTitle()
	end
	env.title = title

	-- Get the subject namespace number.
	local subjectSpace = mw.site.namespaces[title.namespace].subject.id
	env.subjectSpace = subjectSpace
	
	-- Get the name of the documentation namespace.
	local docspace
	if subjectSpace == 0 or subjectSpace == 6 or subjectSpace == 8 or subjectSpace == 14 then
		-- Pages in the Article, File, MediaWiki or Category namespaces must have their
		-- /doc, /sandbox and /testcases pages in talk space.
		docspace = mw.site.namespaces[subjectSpace].talk.name 
	else
		docspace = title.subjectNsText
	end
	env.docspace = docspace
	
	-- Get the template page with no namespace or interwiki prefixes.
	local templatePage
	local subpage = title.subpageText
	if subpage == message('sandboxSubpage', 'string') or subpage == message('testcasesSubpage', 'string') then
		templatePage = title.baseText
	else
		templatePage = title.text
	end
	env.templatePage = templatePage

	return env
end	

----------------------------------------------------------------------------
-- Auxiliary templates
----------------------------------------------------------------------------

function p.sandboxNotice(args, env)
	local sandboxNoticeTemplate = message('sandboxNoticeTemplate', 'string')
	if not (sandboxNoticeTemplate and currentTenv.title.subpageText == message('sandboxSubpage', 'string')) then
		return nil
	end
	local frame = mw.getCurrentFrame()
	local notice = htmlBuilder.create()
	notice
		.tag('div')
			.css('clear', 'both')
			.done()
		.wikitext(frame:expandTemplate{title = sandboxNoticeTemplate, args = {[message('sandboxNoticeLivepageParam')] = args[message('livepageArg', 'string')]}})
	return tostring(notice)
end

function p.protectionTemplate()env)
	local title = env.title
	local protectionTemplate = message('protectionTemplate', 'string')
	if not (protectionTemplate and currentTtitle.namespace == 10) then
		-- Don't display the protection template if we are not in the template namespace.
		return nil
	end
	local frame = mw.getCurrentFrame()
	local function getProtectionLevel(protectionType, page)
		-- Gets the protection level for page, or for the current page if page is not specified.
		local level = frame:callParserFunction('PROTECTIONLEVEL', protectionType, page)
		if level ~= '' then
			return level
		else
			return nil -- The parser function returns the blank string if there is no match.
		end
	end
	local prefixedTitle = title.prefixedText
	if getProtectionLevel('move', prefixedTitle) == 'sysop' or getProtectionLevel('edit', prefixedTitle) then
		-- The page is full-move protected, or full, template, or semi-protected.
		return frame:expandTemplate{title = protectionTemplate, args = message('protectionTemplateArgs', 'table')}
	end
	return nil
end

----------------------------------------------------------------------------
-- Start box
----------------------------------------------------------------------------

p.startBox = makeInvokeFunc('_startBox')

function p._startBox(args, env)
	-- Arg processing from {{documentation}}.
	local preload = args[message('preloadArg', 'string')] -- Allow custom preloads.
	local heading = args[message('headingArg', 'string')] -- Blank values are not removed.
	local headingStyle = args[message('headingStyleArg', 'string')]
	local content = args[message('contentArg', 'string')]
	local docspace = penv.docspace()
	local docname = args[1] -- Other docname, if fed.
	local templatePage = penv.templatePage()

	-- Arg processing from {{documentation/start box2}}.
	local docpage
	if docname then
		docpage = docname
	else
		local namespace = docspace or currentTitle.nsText
(contracted; show full)			lspan.wikitext(makeUrlLink(docTitle:fullUrl{action = 'edit', preload = preload}, message('createLinkDisplay', 'string')))
		end
	end

	return tostring(sbox)
end


----------------------------------------------------------------------------
-- Documentation content
----------------------------------------------------------------------------

p.content = makeInvokeFunc('_content')

function p._content(args)
	local content = args[message('contentArg', 'string')]
	if not content then
		local docpage = args[1]
		if docpage and mw.title.new(docpage).exists then
			local frame = mw.getCurrentFrame()
			content = frame:preprocess('{{ ' .. docpage .. ' }}')
		else
			docpage = p.docspace() .. ':' .. p.templatePage() .. '/' .. message('docSubpage', 'string')
			if mw.title.new(docpage).exists then
				local frame = mw.getCurrentFrame()
				content = frame:preprocess('{{ ' .. docpage .. ' }}')
			end
		end
	end
	-- The line breaks below are necessary so that "=== Headings ===" at the start and end
	-- of docs are interpreted correctly.
	return '\n' .. (content or '') .. '\n' 
end

----------------------------------------------------------------------------
-- End box
----------------------------------------------------------------------------

p.endBox = makeInvokeFunc('_endBox')

function p._endBox(args)
	-- Argument processing in {{documentation}}.
	local content = args[message('contentArg', 'string')]
	local linkBox = args[message('linkBoxArg', 'string')] -- So "link box=off" works.
	local docspace = p.docspace()
	local docname = args[1] -- Other docname, if fed.
(contracted; show full)	end
	fmargs.text = text

	-- Return the fmbox output.
	return messageBox.main('fmbox', fmargs)
end


----------------------------------------------------------------------------
-- Tracking categories
----------------------------------------------------------------------------

function p.addTrackingCategories()
	-- Check if {{documentation}} is transcluded on a /doc or /testcases page.
	local ret = ''
	local subpage = currentTitle.subpageText
	if message('displayStrangeUsageCategory', 'boolean') and (subpage == message('docSubpage', 'string') or subpage == message('testcasesSubpage', 'string')) then
		local sort = (currentTitle.namespace == 0 and message('strangeUsageCategoryMainspaceSort', 'string') or '') .. currentTitle.prefixedText -- Sort on namespace.
		ret = ret .. makeCategoryLink(message('strangeUsageCategory', 'string'), sort)
	end
	return ret
end

function p.docspace()
	-- Determines the namespace of the documentation.
	if subjectSpace == 0 or subjectSpace == 6 or subjectSpace == 8 or subjectSpace == 14 then
		-- Pages in the Article, File, MediaWiki or Category namespaces must have their
		-- /doc, /sandbox and /testcases pages in talk space.
		return mw.site.namespaces[subjectSpace].talk.name 
	else
		return currentTitle.subjectNsText
	end
end

function p.templatePage()
	-- Determines the template page. No namespace or interwiki prefixes are included.
	local subpage = currentTitle.subpageText
	if subpage == message('sandboxSubpage', 'string') or subpage == message('testcasesSubpage', 'string') then
		return currentTitle.baseText
	else
		return currentTitle.text
	end
end

return p