Module:Documentation

From Modded Wiki
Revision as of 01:41, 7 June 2020 by minecraft>AttemptToCallNil (the version that avoids captures took somewhat less memory in my test setup, maybe it will help here?)
Jump to navigation Jump to search

Documentation for this module may be created at Module:Documentation/doc

local p = {}
local defaultDocPage = 'doc'

local getType = function( namespace, page )
	local pageType = 'template'
	if namespace == 'Module' then
		pageType = 'module'
	elseif namespace == 'Widget' then
		pageType = 'widget'
	elseif page.fullText:gsub( '/' .. defaultDocPage .. '$', '' ):find( '%.css$' ) then
		pageType = 'stylesheet'
	elseif page.fullText:gsub( '/' .. defaultDocPage .. '$', '' ):find( '%.js$' ) then
		pageType = 'script'
	elseif namespace == 'MediaWiki' then
		pageType = 'message'
	end
	
	return pageType
end

-- Creating a documentation page or transclution through {{subst:doc}}
function p.create( f )
	local args = require( 'Module:ProcessArgs' ).norm()
	local page = mw.title.getCurrentTitle()
	local docPage = args.page or page.nsText .. ':' .. page.baseText .. '/' .. defaultDocPage
	
	local out
	if not args.content and tostring( page ) == docPage then
		out = f:preprocess( '{{subst:Template:Documentation/preload}}' )
	else
		local templateArgs = {}
		for _, key in ipairs{ 'type', 'page', 'content' } do
			local val = args[key]
			if val then
				if key == 'content' then val = '\n' .. val .. '\n' end
				table.insert( templateArgs, key .. '=' .. val )
			end
		end
		
		out = '{{documentation|' .. table.concat( templateArgs, '|' ) .. '}}'
		out = out:gsub( '|}}', '}}' )
		
		if not args.content then
			out = out .. '\n<!-- Put categories/interwiki on the documentation page -->'
		end
	end
	
	if not mw.isSubsting() then
		out = f:preprocess( out )
		if not args.nocat then
			out = out .. '[[Category:Pages with templates requiring substitution]]'
		end
	end
	
	return out
end

-- Header on the documentation page
function p.docPage( f )
	local args = require( 'Module:ProcessArgs' ).merge( true )
	local badDoc = args.baddoc
	if f:callParserFunction( '#dplvar', '$doc noheader' ) == '1' then
		if badDoc then
			f:callParserFunction( '#dplvar:set', '$doc bad', '1' )
		end
		return
	end
	
	local page = mw.title.getCurrentTitle()
	local namespace = page.nsText
	local pageType = mw.ustring.lower( args.type or getType( namespace, page ) )
	
	local body = mw.html.create( 'div' ):addClass( 'documentation-header' )
	body
		:css{
			['margin-bottom'] = '0.8em',
			padding = '0.8em 1em 0.7em',
			['background-color'] = '#' .. ( badDoc and 'F9F2EA' or 'EAF4F9' ),
			border = '1px solid #AAA'
		}
		:tag( 'div' )
			:css( 'float', 'right' )
			:wikitext( '[[', page:fullUrl( 'action=purge' ), ' purge]]' )
		:done()
		:wikitext(
			'This is the documentation page, it ',
			pageType == 'module' and 'will' or 'should',
			' be transcluded into the main ', pageType, ' page. ',
			'See [[Template:Documentation]] for more information'
		)
	if badDoc then
		body:wikitext( "<br>'''This ", pageType, "'s documentation needs improving or additional information.'''" )
	end
	if not ( args.nocat or namespace == 'User' ) then
		body:wikitext( '[[Category:Documentation pages]]' )
	end
	
	return body
end

-- Wrapper around the documentation on the main page
function p.page( f )
	-- mw.text.trim uses mw.ustring.gsub, which silently fails on large strings
	local function trim( s )
		return (s:gsub( '^[\t\r\n\f ]+', '' ):gsub( '[\t\r\n\f ]+$', '' ))
		--return string.gsub( s, '^[\t\r\n\f ]*(.-)[\t\r\n\f ]*$', '%1' )
	end
	local args = require( 'Module:ProcessArgs' ).merge( true )
	local page = mw.title.getCurrentTitle()
	local namespace = page.nsText
	local docText = trim( args.content or '' )
	if docText == '' then docText = nil end
	
	local docPage
	local noDoc
	if docText then
		docPage = page
	else
		docPage = mw.title.new( args.page or namespace .. ':' .. page.text .. '/' .. defaultDocPage )
		noDoc = args.nodoc or not docPage.exists
	end
	local badDoc = args.baddoc
	local pageType = mw.ustring.lower( args.type or getType( namespace, page ) )
	
	if not docText and not noDoc then
		f:callParserFunction( '#dplvar:set', '$doc noheader', '1' )
		docText = trim( f:expandTemplate{ title = ':' .. docPage.fullText }  )
		if f:callParserFunction( '#dplvar', '$doc bad' ) == '1' then
			badDoc = 1
		end
		
		if docText == '' then
			docText = nil
			noDoc = 1
		end
	end
	if docText then
		docText = '\n' .. docText .. '\n'
	end
	
	local action = 'edit'
	local preload = ''
	local colour = 'EAF4F9'
	local message
	local category
	if noDoc then
		action = 'create'
		preload = '&preload=Template:Documentation/preload'
		colour = 'F9EAEA'
		message = "'''This " .. pageType .. " has no documentation. " ..
			"If you know how to use this " .. pageType .. ", please create it.'''"
		if not ( args.nocat or namespace == 'User' ) then
			category = pageType .. 's with no documentation'
			if not mw.title.new( 'Category:' .. category ).exists then
				category = 'Pages with no documentation'
			end
		end
	elseif badDoc then
		colour = 'F9F2EA'
		message = "'''This " .. pageType .. "'s documentation needs improving or additional information.'''\n"
		if not ( args.nocat or namespace == 'User' ) then
			category = pageType .. 's with bad documentation'
			if not mw.title.new( 'Category:' .. category ).exists then
				category = 'Pages with bad documentation'
			end
		end
	end
	
	local links = {
		'[' .. docPage:fullUrl( 'action=edit' .. preload ) .. ' ' .. action .. ']',
		'[' .. docPage:fullUrl( 'action=history' ) .. ' history]',
		'[' .. page:fullUrl( 'action=purge' ) .. ' purge]'
	}
	if not noDoc and page ~= docPage then
		table.insert( links, 1, '[[' .. docPage.fullText .. '|view]]' )
	end
	links = mw.html.create( 'span' )
		:css( 'float', 'right' )
		:wikitext( mw.text.nowiki( '[' ), table.concat( links, ' | ' ), mw.text.nowiki( ']' ) )
	
	local body = mw.html.create( 'div' ):addClass( 'documentation' )
	body:css{
		['background-color'] = '#' .. colour,
		border = '1px solid #AAA',
		padding = '0.8em 1em 0.7em',
		['margin-top'] = '1em',
		clear = 'both'
	}
	
	local header = mw.html.create( 'div' )
		:css{
			margin = '-0.8em -1em 0.8em',
			padding = '0.8em 1em 0.7em',
			['background-color'] = '#EAF4F9',
			['border-bottom'] = 'inherit'
		}
	
	header
		:node( links )
		:tag( 'span' )
			:css{
				['font-weight'] = 'bold',
				['font-size'] = '130%',
				['margin-right'] = '1em',
				['line-height'] = '1'
			}
			:wikitext( 'Documentation' )
	
	local codePages = {
		module = true,
		stylesheet = true,
		script = true,
	}
	if not noDoc and codePages[pageType] then
		header
			:tag( 'span' )
				:css( 'white-space', 'nowrap' )
				:wikitext( '[[#the-code|Jump to code ↴]]' )
	end
	
	body
		:node( header ):done()
		:wikitext( message )
		:wikitext( docText )
	
	if not noDoc and page ~= docPage then
		body
			:tag( 'div' )
				:css{
					margin = '0.7em -1em -0.7em',
					['background-color'] = '#EAF4F9',
					['border-top'] = 'inherit',
					padding = '0.8em 1em 0.7em',
					clear = 'both'
				}
				:node( links )
				:wikitext( 'The above documentation is transcluded from [[', docPage.fullText, ']].' )
	end
	
	if category then
		body:wikitext( f:expandTemplate{ title = 'Translation category', args = { category, project = '0' } } )
	end
	
	local anchor = ''
	if not noDoc and pageType ~= 'template' and pageType ~= 'message' then
		anchor = mw.html.create( 'div' ):attr( 'id', 'the-code' )
	end
	
	return tostring( body ) .. tostring( anchor )
end

return p