Module:Documentation

--Load loader function local loadLib = require('Module:LoadLib')

--Load Modules loadLib(_G)

--Begin Exports Doc = {} local nowiki = mw.text.nowiki local lb, rb = nowiki('['), nowiki(']') local sep = ' &bull; ' local titleObj = mw.title.getCurrentTitle local pagename = titleObj.fullText local table = require('Module:Table')

local notices = { protected='', } local noticePatterns = { protected='', }

function Doc:linksToList(t, ignoreBrackets) local ret = {} local t2 = {}

for i, v in ipairs(t) do		table.push(ret, self:parseLinkEntry(v, ignoreBrackets or t.main)) end ret = table.concat(ret, sep) if t.main then ret = table.concat{ t.prepend and self:parseLinkEntry(t.prepend, true)..' ' or '', self:parseLinkEntry(t.main, true), ' ', 			#t ~= 0 and '(' or , 			ret, 			#t ~= 0 and ')' or , ' ',		}	end return ret end

function Doc:exists(title) return mw.title.new(title).exists end

function Doc:msg(name, ...) checkType(1, name, 'string') if not self.config[name] then error(string.format('Message %q does not exist', name), 2) end return (tostring(self.config[name]):gsub('%$%d', '%%%s')):format(...) end

function Doc:parseLinkEntry(t2, isMain) t2[1] = string.parseDualArg(t2[1]) local val local title = string.makeTitle(t2[2] or '', t2[3], { disableAbbr=true }) if t2.query then val = string.fullUrl(t2[1], t2.query or {}, title) else val = string.makeLink(t2[1], title) end return isMain and (t2.alt or val) or table.concat{ lb, val, rb } end

function Doc:renderNotices self.noticeStr = {} if self.subpageExists then for id, pattern in pairs(noticePatterns) do 			local notice = notices[id] if not self.subpageContent:match(pattern) and self.noticeConditions[id] then table.push(self.noticeStr, notice) end end end self.noticeStr = table.concat(self.noticeStr, '\n')..'\n' return self.noticeStr end

function Doc:renderVariables self.title = self._title or self:msg('default-title') self.type = string.ucfirst(self._type or self:msg('type-module')) self.title = table.concat{ self.type, ':', ((self.title:gsub(table.concat{ '^', self.type, ':?' }, )):gsub('%/doc$', )) } self.sandbox = table.concat{ self.title, '/', self:msg('subpage-sandbox') } self.testcases = table.concat{ self.title, '/', self:msg('subpage-testcases') } self.doc = table.concat{ self.title, '/', self:msg('subpage-documentation') } self.titleObj = mw.title.new(self.title) self.titleExists = self.titleObj.exists self.talk = self.titleObj.talkPageTitle.fullText self.talkObj = self.titleObj.talkPageTitle self.sandboxObj = mw.title.new(self.sandbox) self.testcasesObj = mw.title.new(self.testcases) self.docObj = mw.title.new(self.doc) self.subpageExists = self.docObj.exists self.subpageContent = self.subpageExists and self.docObj:getContent or nil return self end

function Doc:generateData self.createDocQuery = { action='edit', redlink=1, minor=1, useeditor="source", preload='Template:__DIR__/__PRELOAD__', editintro='Template:__DIR__/__EDITINTRO__', summary=self:msg('doc-edit-summary', self.doc); }	self.createSandbox = { self.sandbox, string.makeTitle(self:msg('sandbox-create-text'), self:msg('sandbox-create-title'), { disableAbbr=true }), query = { action="edit", redlink=1, minor=1, useeditor="source", preload=self.title, summary=self:msg('sandbox-create-summary', self.doc); }	}	self.links = {} self.links.pageTools = { {			{ self.doc, self:msg('main-view-text'), self:msg('main-view-title'), }, { self.doc, self:msg('main-edit-text'), self:msg('main-edit-title'), query={ action='edit' }}, { self.doc, self:msg('main-curdiff-text'), self:msg('main-curdiff-title'), query={ diff='cur' }}, { self.doc, self:msg('main-hist-text'), self:msg('main-hist-title'), query={ action='history' }}, { self.title, self:msg('main-purge-text'), self:msg('main-purge-title'), query={ action="purge" }}, },		{			{ self.doc, self:msg('main-create-text'), self:msg('main-create-title'), query=self.createDocQuery }, { self.title, self:msg('main-purge-text'), self:msg('main-purge-title'), query={ action="purge" }}, }	}	self.links.sandbox = { main={ self.sandbox, self:msg('sandbox-main-text') }, { self.sandbox, self:msg('sandbox-edit-text'), self:msg('sandbox-edit-title'), query={ action="edit" }}, { self.sandbox, self:msg('sandbox-curdiff-text'), self:msg('sandbox-curdiff-title'), query={ diff="cur" }}, { self.sandbox, self:msg('sandbox-hist-text'), self:msg('sandbox-hist-title'), query={ action="history" }}, { 			alt=string.wrapHtml{ self:msg('sandbox-reset-text'), " ", attrs={ title=self:msg('sandbox-reset-title'), id="re-mirror-sandbox", style={ cursor="pointer"; } }			}, 		},	}	self.links.tools = { { { 'Special:PrefixIndex/', self.title, '/' }, self:msg('tool-subpages-text'), self:msg('tool-subpages-title') }, { { 'Special:WhatLinksHere/', self.title, }, self:msg('tool-whl-text'), self:msg('tool-whl-title') }, }	self.links.talk = { {			main={ self.talk, self:msg('talk-main-text') }, prepend={ self.talk, '+', self:msg('talk-newsec-title'), query={ action="edit", section="new" }}, { self.talk, self:msg('talk-edit-text'), self:msg('talk-edit-title'), query={ action="edit" }}, { self.talk, self:msg('talk-curdiff-text'), self:msg('talk-curdiff-title'), query={ diff="cur" }}, { self.talk, self:msg('talk-hist-text'), self:msg('talk-hist-title'), query={ action="history" }}, },		{			main={ self.talk, self:msg('talk-create-text'), self:msg('talk-create-title'), query={ action='edit', redlink=1, minor=1, useeditor="source", section="new", summary=self:msg('talk-create-summary', self.title), }			},		},	}	self.links.pageLinks = { { alt=self:linksToList(self.links.talk[self.talkObj.exists and 1 or 2]) }, { self.title, self:msg('page-curdiff-text'), self:msg('page-curdiff-title'), query={ diff="cur" }}, { { 'Special:Log/', self.title }, 'Page Logs', 'View the logs for this page', }, }	self.links.testcases = { {			 main={ self.testcases, self:msg('test-main-text'), self:msg('test-main-title') }, { self.testcases, self:msg('test-edit-text'), self:msg('test-edit-title') }, { self.testcases, self:msg('test-curdiff-text'), self:msg('test-curdiff-title') }, self.testcasesObj.talkPageTitle.exists and { self.testcasesObj.talkPageTitle.fullText, self:msg('test-run-text'), self:msg('test-run-title') } or { self.testcasesObj.talkPageTitle.fullText, self:msg('test-results-create-text'), self:msg('test-results-create-title'), query={ action='edit', redlink=1, minor=1, useeditor="source", preload='Template:__DIR__/__PRELOAD__/' .. self:msg('testcases-results-name'), editintro='Template:__DIR__/__EDITINTRO__/' .. self:msg('testcases-results-name'), summary=self:msg('test-results-create-summary', self.title), },				},		},		{ 			self.testcases, self:msg('test-create-text'), self:msg('test-create-title'), query={ action='edit', redlink=1, minor=1, useeditor="source", preload='Template:__DIR__/__PRELOAD__/' .. self:msg('testcases-name'), editintro='Template:__DIR__/__EDITINTRO__/' .. self:msg('testcases-name'), summary=self:msg('test-create-summary', self.title), }		}	}	self.noticeConditions = { protected = self.docObj.protectionLevels.edit[1] == 'sysop', } end

function Doc:buildMainBox local notices = self:renderNotices local inst = self.html :css{ ['font-family']='Arial !important'; ['clear']='both'; }		:tag('div') :addClass('color1') :css{ ['padding'] = '2px'; ['border-top'] = '1.3px solid black'; ['border-left'] = '1.3px solid black'; ['border-right'] = '1.3px solid black'; ['border-bottom'] = 'none'; ['margin'] = '4px 4px 0 4px'; ['box-shadow'] = '0 0 2px black'; }

if self.type == self:msg('type-module') then inst:tag('span') :css{ ['float'] = 'right'; ['font'] = 'italic small arial'; }			:wikitext('(', string.makeLink('#code', string.makeTitle(self:msg('jump-text'), self:msg('jump-title'), { disableAbbr=true })), ')')		:done end inst:tag('span') :css{ float="left"; }				:wikitext(string.makeImage(self:msg('doc-image'), { link='', size=60 })) :done :tag('span') :attr{ id="header" } :css{ ['font'] = 'bold x-large arial'; ['margin-left'] = '7px'; ['text-align'] = 'center'; }				:wikitext(self:msg('header-text')) :done :tag('span') :css{ ['margin-left']='7px'; }				:wikitext(self:linksToList(self.subpageExists and self.links.pageTools[1] or self.links.pageTools[2])) :done if self.type == self:msg('type-template') then inst:tag('small') :css{ display='block'; }			:tag('i') :tag('b'):wikitext(self:msg('note'), ': '):done :wikitext(self:msg('template-note')) :done :done end

inst = inst:tag('hr') :addClass('page-header__separator') :css{ ['background-color'] = '#daa9ad'; ['border'] = 0; ['height'] = '1px'; ['margin-bottom'] = '3px'; ['margin-top'] = 0; ['width'] = '100%'; }			:done :tag('div') :tag('p') :css{ margin=0; }					:wikitext(						string.wrapTag({ self:msg('page-tools'), ': '}, 'b'), 						(table.concat(table.merge({ self:exists(self.sandbox) and self:linksToList(self.links.sandbox) or self:parseLinkEntry(self.createSandbox, true), }, self:linksToList(self.links.tools, true)), sep):gsub(' &bull; 1', ''))					) :done :done :tag('hr') :addClass('page-header__separator') :css{ ['background-color'] = '#daa9ad'; ['border'] = 0; ['height'] = '1px'; ['margin-bottom'] = '3px'; ['margin-top'] = 0; ['width'] = '100%'; }			:done :tag('div') :tag('p') :css{ margin=0; }					:wikitext(						string.wrapTag({ self:msg('page-links'), ': '}, 'b'), 						self:linksToList(self.links.pageLinks, true)					) :done :done :done :tag('div') :css{ ['background-color'] = 'rgba(120,120,120,0.05)'; ['box-shadow'] = '0 0 2px black'; ['border-bottom'] = 'none'; ['border-top'] = 'none'; ['padding'] = '0.5em'; ['margin'] = '0 4px 0 4px'; ['border-right'] = '1.3px solid black'; ['border-left'] = '1.3px solid black'; ['clear'] = 'both'; }			:wikitext(				self.subpageExists and					mw.getCurrentFrame:newChild{ title=self.doc }:preprocess(self.noticeStr..self.subpageContent)				or					table.concat{ 						string.wrapHtml( {								self:msg('no-exist-message'), ' ', },							' ', {								class="error" }						),						string.wrapTag({ '(', string.fullUrl(self.doc, self.createDocQuery, self:msg('main-create-text')), ')', }, 'strong'),					}			) :wikitext(not self.subpageExists and table.concat{ , self:msg('no-exist-cat'),  } or '') :tag('span') :css{ display="none" } :wikitext(, self.doc, ) :done -- To Make sure the contents of the box does not overflow :tag('div') :css{ clear="both"; ['margin-bottom']='5px'; }			:done :done :tag('div') :addClass('color1') :css{ ['padding'] = '2px'; ['border-left'] = '1.3px solid black'; ['border-right'] = '1.3px solid black'; ['border-bottom'] = '1.3px solid black'; ['border-top'] = 'none'; ['margin'] = '0 4px 4px 4px'; ['box-shadow'] = '0 0 2px black'; }			:tag('span') :css{ ['font-size']='20px'; ['margin']='5px'; }				:wikitext('(', string.makeLink({ self:msg('hdtw-name') }, self:msg('hdtw-text')), ')') :done :tag('span') :css{ ['margin-left']=self.titleObj.exists and '13%' or '23%'; }				:wikitext(self.type == self:msg('type-module') and string.wrapTag({ self:msg('other-tools'), ': ' }, 'b') or '') :wikitext(					self.type == self:msg('type-module') and ( self:exists(self.testcases) and self:linksToList(self.links.testcases[1]) or self:parseLinkEntry(self.links.testcases[2], true) ) or ''				) :done :tag('span') :css{ float='right'; ['font-style']='italic'; }				:wikitext('(', string.makeLink('#header', self:msg('back-to-top')), ')') :done :done :allDone return inst end

function Doc:constructor(title, _type, noNotices) checkType(true, 1, title, 'string', true) checkType(true, 2, _type, 'string', true) self.config = require('Module:Documentation/Config') self._title, self._type = title, string.ucfirst(_type or self:msg('type-module') ) self._noNotices = noNotices self:renderVariables self.html = mw.html.create('div') self:generateData self.ret, _ = tostring(self:buildMainBox) :gsub('__TYPE__', self.type) :gsub('__DIR__', self.type == self:msg('type-module') and self:msg('dir-module') or self:msg('dir-template')) :gsub('__PRELOAD__', self:msg('dir-preload')) :gsub('__EDITINTRO__', self:msg('dir-editintro')) return self end

function Doc:__tostring return self.ret end

function Doc:__concat(a, b)	if a == self then return self.ret..b	else return b..self.ret end end

--Create Class Doc = table.makeClass(nil, Doc, nil, { ignore=true })

function Doc.main(frame) local args = getArgs(frame) return Doc:constructor(table.unpack(table.deepCopy(args, false))) end

function Doc.module(title, noNotices) checkType(1, title, 'string', true) return Doc(title or titleObj.text, 'Module', noNotices) end

function Doc.template(title, noNotices) checkType(1, title, 'string', true) return Doc(title or titleObj.text, 'Template', noNotices) end

function Doc._module(frame) local args = getArgs(frame) return Doc:constructor(args[1] or titleObj.text, 'Module', args['nonotices'] or args['nonotice'] or args['nonoti'] or args['nn']) end

function Doc._template(frame) local args = getArgs(frame) return Doc:constructor(args[1] or titleObj.text, 'Template', args['nonotices'] or args['nonotice'] or args['nonoti'] or args['nn']) end

--Finish __TYPE__/Exports return Doc