Module:InfoboxNeue
From Amaranth Legacy, available at amaranth-legacy.community
More actions
This module is used for Template:InfoboxNeue. See the template's page for more information.
-- original source: https://github.com/The-Star-Citizen-Wikis/SharedModules/blob/e6e1ef118b211e8247e0e1bc9c0257879579c147/InfoboxNeue/InfoboxNeue.lua
-- heavily modified for Amaranth Legacy
local InfoboxNeue = {}
local metatable = {}
local methodtable = {}
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
metatable.__index = methodtable
metatable.__tostring = function(self)
return tostring(self:renderInfobox())
end
local function orderedPairs(t, f)
local a = {}
for n in pairs(t) do table.insert(a, n) end
table.sort(a, f)
local i = 0 -- iterator variable
local iter = function() -- iterator function
i = i + 1
if a[i] == nil then
return nil
else
return a[i], t[a[i]]
end
end
return iter
end
local function removeprefix(s, p)
return (s:sub(0, #p) == p) and s:sub(#p + 1) or s
end
local function getDetailsHTML(data, frame)
local summary = frame:extensionTag {
name = 'summary',
content = data.summary.content,
args = {
class = data.summary.class
}
}
local details = frame:extensionTag {
name = 'details',
content = summary .. data.details.content,
args = {
class = data.details.class,
open = true
}
}
return details
end
--- render an image into HTML
---
--- @param filename string
--- @param caption string
function methodtable.renderImage(self, filename, caption)
-- input validation
checkType('Module:InfoboxNeue.renderImage', 1, self, 'table')
checkType('Module:InfoboxNeue.renderImage', 2, filename, 'string')
checkType('Module:InfoboxNeue.renderImage', 3, caption, 'string', true)
-- input is wikitext
filename = filename:gsub('^%[%[File:(.+)]]', '%1')
-- input is complete file page name
filename = filename:gsub('^File:(.+)', '%1')
local html
if filename:match('ul') then
html = mw.html.create('div')
:addClass('infobox__gallery')
:wikitext(filename)
else
html = mw.html.create('div')
:addClass('infobox__image')
:wikitext(string.format('[[File:%s|400px]]', filename))
end
if caption ~= nil then
html:tag('div')
:addClass('infobox__caption')
:wikitext(caption)
end
table.insert(self.entries, tostring(html))
end
--- wrap the infobox section into ready-to-use HTML
---
--- @param data table
function methodtable.renderSection(self, data)
-- input validation
checkType('Module:InfoboxNeue.renderSection', 1, self, 'table')
checkType('Module:InfoboxNeue.renderSection', 2, data, 'table')
-- if there's nothing to render, return an empty string
if data['content'] == nil or next(data['content']) == nil then return end
-- section wrapper
local html = mw.html.create('div'):addClass('infobox__section')
-- already checked that there's a title at this point
-- section header
local header = html:tag('div')
:addClass('infobox__sectionTitle')
:wikitext(data['title'])
-- content wrapper
local content = html:tag('div')
content:addClass('infobox__sectionContent')
:wikitext(table.concat(data['content']))
-- set column count
if data['col'] then content:addClass('infobox__grid--cols-' .. data['col']) end
table.insert(self.entries, tostring(html))
end
--- render an item in the infobox
---
--- @param data table
--- @return string
function methodtable.renderItem(self, data)
-- input validation
checkType('Module:InfoboxNeue.renderItem', 1, self, 'table')
checkType('Module:InfoboxNeue.renderItem', 2, data, 'table')
-- if there's nothing to render, return an empty string
if data['content'] == nil or data['content'] == '' then
return ''
end
-- item wrapper
local html = mw.html.create('div'):addClass('infobox__item')
if data['row'] == true then html:addClass('infobox__grid--row') end
if data['spacebetween'] == true then html:addClass('infobox__grid--space-between') end
if data['colspan'] then html:addClass('infobox__grid--col-span-' .. data['colspan']) end
-- already checked that there's a label and content at this point
-- fix bulleted lists
if string.find(data['content'], '^%*') then
data['content'] = "\n\n" .. data['content']
end
html:tag('div')
:addClass('infobox__label')
:wikitext(data['label'])
:done()
:tag('div')
:addClass('infobox__content')
:wikitext(data['content'])
return tostring(html)
end
--- wrap the infobox into ready-to-use HTML
---
--- @param title string text used as the header
--- @return string
function methodtable.renderInfobox(self, title)
-- input validation
checkType('Module:InfoboxNeue.renderInfobox', 1, self, 'table')
checkType('Module:InfoboxNeue.renderInfobox', 2, title, 'string', true)
local function renderContent()
local html = mw.html.create('div')
:addClass('infobox__content')
:wikitext(table.concat(self.entries))
return tostring(html)
end
local frame = mw.getCurrentFrame()
local output = getDetailsHTML({
details = {
class = 'infobox floatright noexcerpt',
content = renderContent()
},
summary = {
class = 'infobox__title',
content = title
}
}, frame)
return frame:extensionTag { name = 'templatestyles', args = { src = 'Module:InfoboxNeue/styles.css' } }
.. output
end
--- New Instance
---
--- @return table InfoboxNeue
function InfoboxNeue.new()
local instance = {
entries = {}
}
setmetatable(instance, metatable)
return instance
end
--- create an infobox from the given arguments
---
--- @param frame table
--- @return string
function InfoboxNeue.fromArgs(frame)
-- setup
local instance = InfoboxNeue:new()
local args = require('Module:Arguments').getArgs(frame)
-- section tracking
local sections = {}
local sectionMap = {}
local currentSection
-- image rendering
if args['image'] then
-- backwards compatibility: render a single image
instance:renderImage(args['image'], args['caption'])
else
for i = 1, 10, 1 do
if args['image' .. i] then
-- render image1 through image3
instance:renderImage(args['image' .. i], args['caption' .. i])
end
end
end
-- for each argument (ordered alphabetically)
for key, value in orderedPairs(args) do
-- if it's a label
if type(string.match(key, '^label')) ~= 'nil' then
-- if there's a section with this label's number
if args['section' .. removeprefix(key, 'label')] then
-- set the current section
currentSection = args['section' .. removeprefix(key, 'label')]
-- insert a new section
table.insert(sections, {
title = currentSection,
col = args['section-col' .. removeprefix(key, 'label')] or 2,
content = {}
})
-- map the section name to the section number
sectionMap[currentSection] = #sections
end
-- set up the data for the item
local data = {
label = value,
content = args['content' .. removeprefix(key, 'label')],
colspan = args['colspan' .. removeprefix(key, 'label')]
}
local renderedItem = instance:renderItem(data)
if renderedItem ~= '' then
-- add to the section's content
table.insert(sections[sectionMap[currentSection]].content, renderedItem)
end
end
end
-- for each section
for _, section in ipairs(sections) do
-- render it
instance:renderSection(section)
end
-- render the entire infobox and return
return instance:renderInfobox(args['title'])
end
return InfoboxNeue