Module:Infobox

require('Module:LoadLib')(_G)

-- Set exports local infobox = {}

--Variables local curTitle = mw.title.getCurrentTitle

function infobox.create(attrs) local methods = {} function constructor(self, attrs) checkType(1, attrs, 'table', true) attrs = attrs or {} self.instance = mw.html.create('infobox'):attr{ ["theme"] = attrs["theme"], ["theme-source"] = attrs["theme-source"], ["type"] = attrs["type"], ["accent-color-source"] = attrs["accent-color-source"], ["accent-color-default"] = attrs["accent-color-default"], ["accent-color-text-source"] = attrs["accent-color-text-source"], ["accent-color-text-default"] = attrs["accent-color-text-default"], ["layout"] = attrs["layout"], ["name"] = attrs["name"], }		return self end

function methods:done return self.instance:done end function methods:addTitle(t, parent, appendTo) checkType(1, t, 'table', true) t = t or {} local inst = (appendTo or self.instance) :tag('title') :attr({					source=t.source or ((not t.default and not t[1]) and error('infobox:addTitle: No title source or default specified', 2) or nil),					name=t.name,				}) :tag('default') :wikitext(table.format(t.title or t[1] or t.default)) :done if t.format then inst:tag('format') :wikitext(table.format(t.format)) :done end inst:done return self end function methods:addData(t, parent) checkType(1, t, 'table', true) t = t or {} local dataInst = (parent or self.instance):tag('data') :attr({ 				name=table.format(t.name),				layout=table.format(t.layout),				span=tonumber(t.span),			}) :tag('default') :wikitext(table.format(t.data or t[1] or t.default)) :done if t.label then dataInst:tag('label') :wikitext(table.format(t.label)) :done end if t.format then dataInst:tag('format') :wikitext(table.format(t.format)) :done end dataInst:done return parent or self end function methods:addImage(t, parent, appendTo) checkType(1, t, 'table', true) t = t or {} local inst = (appendTo or self.instance) :tag('image') :attr({					source=t.source or ((not t.default and not t[1]) and error('infobox:addImage: No image source or default specified', 2) or nil),					name=t.name,				}) :tag('default') :wikitext(table.format(t.image or t[1] or t.default or curTitle.text..'.png')) :done if t.caption then local captionInst = inst:tag('caption') :attr({					source=t.caption.source or 'caption',				}) :tag('default') :wikitext(						table.includes({ 'string', 'number' }, type(t.caption))							and t.caption							or table.format(t.caption.text or t.caption[1] or t.caption.default)					) :done if t.caption.format then captionInst:tag('format') :wikitext(table.format(t.caption.format)) :done end end

if t.alt then local altInst = inst:tag('alt') :attr({					source=t.alt.source,				}) :tag('default') :wikitext(table.format(t.alt.text or t.alt[1] or t.alt.default or t.alt)) :done end inst:done return parent or self end function methods:addNavigation(t, parent, appendTo) checkType(1, t, 'table', true); t = t or {} (appendTo or self.instance) :tag('navigation') :wikitext(table.format(t[1])) :attr{ name = t.name }			:done return parent or self end function methods:addHeader(t, parent, appendTo) checkType(1, t, 'table', true); t = t or {} (appendTo or self.instance) :tag('header') :wikitext(table.format(t[1])) :attr{ name = t.name }			:done return parent or self end function methods:addPanel(t, parent, appendTo) checkType(1, t, 'table', true) t = t or {} local panelMethods = {} function panelMethods:addHeader(text) checkType(1, t, { 'string', 'number', 'table' }, true) self.currentPanel:tag('header') :wikitext(table.format(text)) :done return self end function panelMethods:addSection(t, parent) checkType(1, t, 'table', true) t = t or {} local sectionMethods = {} function sectionMethods:addData(t) self.parent:addData(t or {}, self.currentInstance) return self end function sectionMethods:addGroup(t) checkType(1, t, 'table', true) return self.parent.parent:addGroup(t, self, self.currentInstance) end function sectionMethods:addTitle(t) checkType(1, t, 'table', true) self.parent.parent:addTitle(t, self, self.currentInstance) return self end function sectionMethods:addImage(t) checkType(1, t, 'table', true) self.parent.parent:addImage(t, self, self.currentInstance) return self end function sectionMethods:addHeader(t) checkType(1, t, 'table', true) self.parent.parent:addHeader(t, self, self.currentInstance) return self end -- Shorthand for "section:addGroup:addPanel <...> :done:done" function sectionMethods:addPanel(t) checkType(1, t, 'table', true) t = t or {} t._fromSection = true return self:addGroup :addPanel(t) end function sectionMethods:done self.currentInstance:done self.currentInstance = self.currentPanel return self._parentInstance end function sectionMethods:__tostring return self.parent:__tostring end function constructor(self) self.currentInstance = self.currentPanel:tag('section') self._parentInstance = parent or self.parent

self.currentInstance:tag('label') :wikitext(table.format(t.label)) :done return parent or self end local currentInst = table.makeClass(constructor, sectionMethods, self)(parent) return currentInst end function panelMethods:done self.currentPanel:done self.currentPanel = appendTo or self.instance -- Support non-explicit group for panel adding via `sectionMethods:addPanel` local ret = parent or self.parentInstance return t._fromSection and ret:done or ret end function panelMethods:__tostring return self.parent:__tostring end

function constructor(self, parent) self.currentPanel = (appendTo or self.instance):tag('panel') :attr({					layout=t.layout,					show=t.show,					collapse=t.collapse,					['row-items']=tonumber(t['row-items']),					name=table.format(t.name),				}) self.parentInstance = parent or self.parent if t.header then self.currentPanel :tag('header') :wikitext(table.format(t.header)) :done end return parent or self end local currentInst = table.makeClass(constructor, panelMethods, self)(parent) return currentInst end function methods:addGroup(t, parent, appendTo) checkType(1, t, 'table', true) t = t or {} local groupMethods = {} function groupMethods:addTitle(t) checkType(1, t, 'table', true) self.parent:addTitle(t or {}, self.currentGroup) return self end function groupMethods:addImage(t) checkType(1, t, 'table', true) self.parent:addImage(t or {}, self.currentGroup) return self end function groupMethods:addHeader(text) checkType(1, t, 'string') self.parent:addHeader(text, self.currentGroup) return self end if t.layout ~= 'horizontal' then function groupMethods:addNavigation(text) checkType(1, text, 'string') self.parent:addNavigation(text, self, self.currentGroup) return self end end function groupMethods:addData(t) checkType(1, t, 'table', true) self.parent:addData(t or {}, self.currentGroup) return self end function groupMethods:addGroup(t) checkType(1, t, 'table', true) return self.parent:addGroup(t, self) end function groupMethods:addPanel(t) checkType(1, t, 'table', true) return self.parent:addPanel(t, self, self.currentGroup) end function groupMethods:done self.currentGroup :done self.currentGroup = self.parentGroup return self.parentGroupInstance end function groupMethods:__tostring return self.parent:__tostring end function constructor(self, parent) self.currentGroup = ((parent or {}).currentGroup or appendTo or self.instance) :tag('group') :attr({						layout=t.layout,						show=t.show,						collapse=t.collapse,						['row-items']=tonumber(t['row-items']),						name=table.format(t.name),					}) self.parentGroupInstance = parent or self.parent self.parentGroup = (parent or {}).currentGroup if t.header then self.currentGroup :tag('header') :wikitext(table.format(t.header)) :done end return parent or self end local currentInst = table.makeClass(constructor, groupMethods, self)(parent) return currentInst end function methods:__tostring return tostring(self.instance:allDone) end methods.done = methods.__tostring methods.tostring = methods.__tostring function methods:__concat(a, b)		if a == self.instance then return tostring(a)..b		else return tostring(b)..a		end end function methods:preprocess(args, title) local f = mw.getCurrentFrame local p = f:getParent if p then f = p end return f:newChild{ title=title or curTitle.fullText, args=args or getArgs(f) }:preprocess(self:__tostring) end -- Create and invoke class local Class = table.makeClass(constructor, methods) return Class(attrs) end

function infobox.test return infobox.create :addData{ "Test" } :addPanel :addSection{ label="Test" } :addPanel :addSection{ label="Test2" } :addData{ "Test" } :addHeader{ "Test" } :addImage{ "Test" } :done :done :addData{ "Test" } :addGroup :addData{ "Test" } :addPanel :addSection{ label="Test2" } :addData{ "Test" } :addHeader{ "Test" } :addImage{ "Test" } :done :done :addData :done :addData :done :addSection{ label="Test3" } :addData{ "Test" } :addGroup :addData{ "Test" } :addPanel :addSection{ label="Test2" } :addData{ "Test" } :addHeader{ "Test" } :addImage{ "Test" } :done :done :addData :done :addData :done :done :addData :preprocess end

infobox.templates = templates

function infobox.dedent(s) checkType(1, s, 'string') local matches = table.tableUtil local len s = s:gsub('^%s*(.-)%s*$', '%1') for s in s:gmatch('\n\t*') do		matches:push{ string=s, len=s:match("^\t*") } end return table.dumpObject(matches) end

return infobox