Module:Sandbox/MonkeysHK/3

local loader = require('Module:Loader') local _, table, makeClass = loader.require('LibraryUtil', 'Table', 'Class')

-- TODO (probably not by me): -- Restrict tags according to actual constraints -- according to https://community.fandom.com/wiki/Help:Infoboxes/Tags

-- Set exports local infobox = {}

--Variables local curTitle = mw.title.getCurrentTitle

local InfoboxCompound = makeClass('InfoboxCompound', {	constructor = function(self, tag, attrsTable, parentcompound, opts)		checkType(1, tag, 'string')		checkType(2, attrsTable, 'table', true)		checkType(4, opts, 'table', true)		attrsTable = attrsTable or {}		self.htmlnode = parentcompound and parentcompound.htmlnode:tag(tag) or mw.html.create(tag)		self.htmlnode:attr(attrsTable)		self.parentcompound = parentcompound		if opts then			-- handle extra options			if opts.header then				self.htmlnode					:tag('header')						:wikitext(table.format(opts.header))					:done			end			if opts.label then				self.htmlnode:tag('label')					:wikitext(table.format(opts.label))			end		end		return self	end, })

local Infobox = makeClass('Infobox', {	parent = InfoboxCompound,	constructor = function(self, attrs)		attrs = attrs or {}		self:super('infobox', { ["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, })

local Panel = makeClass('Panel', {	parent = InfoboxCompound,	constructor = function(self, t, parentcompound)		self:super('panel', { layout = t.layout, show = t.show, collapse = t.collapse, ['row-items'] = tonumber(t['row-items']), name = table.format(t.name), }, parentcompound, { header = t.header, })		self._fromSection = t._fromSection		return self	end,	done = function(self)		return self._fromSection and self.parentcompound:done or self.parentcompound	end, })

local Section = makeClass('Section', {	parent = InfoboxCompound,	constructor = function(self, t, parentcompound)		self:super('panel', { layout = t.layout, show = t.show, collapse = t.collapse, ['row-items'] = tonumber(t['row-items']), name = table.format(t.name), }, parentcompound, { label = t.label, })	end,	-- Shorthand for "section:addGroup:addPanel <...> :done:done"	addPanel = function(self, t)		checkType(1, t, 'table', true)		t = t or {}		t._fromSection = true		return self:addGroup:addPanel(t)	end, })

local Group = makeClass('Group', {	parent = InfoboxCompound,	constructor = function(self, t, parentcompound)		self:super('group', { layout = t.layout, show = t.show, collapse = t.collapse, ['row-items'] = tonumber(t['row-items']), name = table.format(t.name), }, parentcompound, { header = t.header, })	end, })

InfoboxCompound.prototype = { -- Static Types addTitle = function(self, t)		checkType(1, t, 'table', true) t = t or {} local inst = self.htmlnode :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, addData = function(self, t)		checkType(1, t, 'table', true) t = t or {} local inst = self.htmlnode: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 inst:tag('label') :wikitext(table.format(t.label)) :done end if t.format then inst:tag('format') :wikitext(table.format(t.format)) :done end inst:done return self end, addImage = function(self, t)		checkType(1, t, 'table', true) t = t or {} local inst = self.htmlnode :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 self end, addNavigation = function(self, t)		checkType(1, t, 'table', true); t = t or {} self.htmlnode :tag('navigation') :wikitext(table.format(t[1])) :attr{ name = t.name }			:done return self end, addHeader = function(self, t)		checkType(1, t, 'table', true); t = t or {} self.htmlnode :tag('header') :wikitext(table.format(t[1])) :attr{ name = t.name }			:done return self end, -- Compound Types addPanel = function(self, t)		checkType(1, t, 'table', true) t = t or {} return Panel(t, self) end, addGroup = function(self, t)		checkType(1, t, 'table', true) t = t or {} return Group(t, self) end, addSection = function(self, t)		checkType(1, t, 'table', true) t = t or {} return Section(t, self) end, -- Helpers done = function(self) return self.parentcompound or self.htmlnode:done end, __tostring = function(self) return tostring(self.htmlnode:allDone) end, tostring = function(self) return self:__tostring end, __concat = function(self, a, b)		if tostring(a) == tostring(self.htmlnode) then return tostring(a) .. tostring(b) else return tostring(b) .. tostring(a) end end, preprocess = function(self, 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, } function infobox.test return Infobox :addHeader{"Foobar"} :addData{ "TestStart" } :addPanel :addSection{ label="Test" } :addPanel :addHeader{"Foobarbaz"} :addSection{ label="Test2" } :addData{ "Test" } :addHeader{ "Test" } :addImage{ "Test" } :done :done :addData{ "Test123" } :addGroup :addTitle{"Foobar123"} :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 :__tostring -- :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