ಮಾಡ್ಯೂಲ್:Infobox/sandbox
ಗೋಚರ
Documentation for this module may be created at ಮಾಡ್ಯೂಲ್:Infobox/sandbox/doc
-- This module implements {{Infobox}}
local checkType = require('libraryUtil').checkType
local CONFIG_MODULE = 'Module:Infobox/config'
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function nilFunc ()
-- To avoid using a different anonymous function every time an argument
-- uses the Infobox.rowArgDefaults metatable.
return nil
end
local function trueFunc ()
-- To avoid using a different anonymous function for every data row.
return true
end
local function makeCategory(cat)
if cat then
return string.format('[[ವರ್ಗ:%s]]', cat)
end
end
--------------------------------------------------------------------------------
-- Infobox class
--------------------------------------------------------------------------------
local Infobox = {}
Infobox.__index = Infobox
Infobox.rowArgDefaults = {__index = function (t, key)
t[key] = nilFunc
return nilFunc
end}
function Infobox.new(args, cfg, title)
local self = setmetatable({}, Infobox)
self.cfg = cfg
self.title = title
self.root = mw.html.create('table')
-- Set the args. We pass the args around as functions, so that we can delay
-- argument expansion until the last minute. This enables us to expand the
-- arguments in the correct order, and only when necessary. This is
-- important for <ref>...</ref> tags, as otherwise:
-- 1. A <references /> tag at the bottom of an infobox might get expanded
-- before <ref>...</ref> tags higher up in an infobox, and the reference
-- doesn't appear where it should; or
-- 2. <ref>...</ref> tags in a label cell can be expanded, but not
-- displayed in the infobox due to the lack of a corresponding data
-- cell argument. This causes a "phantom reference" where the citation
-- is visible in the <references /> tag output, but there is no link to
-- it anywhere in the article.
self.args = setmetatable({}, {__index = function (t, key)
local val
local function expandThisArg ()
if val == false then
return nil
elseif val then
return val
else
val = args[key]
if val == '' then
val = false
return nil
elseif val == false then
return nil
else
return val
end
end
end
t[key] = expandThisArg
return expandThisArg
end})
-- Special case for italic title, which can be different depending on
-- whether it is blank or absent.
self.args['italic title'] = function () return args['italic title'] end
self.hasDataCell = false -- Track data cell usage.
return self
end
function Infobox:renderTitle()
local args = self.args
if not args.title() then return end
self.root
:tag('caption')
:addClass(args.titleclass())
:cssText(args.titlestyle())
:wikitext(args.title())
end
function Infobox:renderAboveRow()
local args = self.args
if not args.above() then return end
self.root
:tag('tr')
:tag('th')
:attr('colspan', 2)
:addClass(args.aboveclass())
:css('text-align', 'center')
:css('font-size', '125%')
:css('font-weight', 'bold')
:cssText(args.abovestyle())
:wikitext(args.above())
end
function Infobox:renderBelowRow()
local args = self.args
if not args.below() then return end
self.root
:tag('tr')
:tag('td')
:attr('colspan', '2')
:addClass(args.belowclass())
:css('text-align', 'center')
:cssText(args.belowstyle())
:newline()
:wikitext(args.below())
end
function Infobox:addRow(rowArgs)
-- Adds a row to the infobox, with either a header cell
-- or a label/data cell combination.
setmetatable(rowArgs, Infobox.rowArgDefaults) -- Set a default function
local hasContent = false -- Tracks whether we have rendered anything.
local args = self.args
local header = rowArgs.header()
if header then
hasContent = true
self.root
:tag('tr')
:addClass(rowArgs.rowclass())
:cssText(rowArgs.rowstyle())
:attr('id', rowArgs.rowid())
:tag('th')
:attr('colspan', 2)
:attr('id', rowArgs.headerid())
:addClass(rowArgs.class())
:addClass(args.headerclass())
:css('text-align', 'center')
:cssText(args.headerstyle())
:wikitext(header)
else
local data = rowArgs.data()
if data then
hasContent = true
-- Track data cells, but not images or subheaders, for use in
-- generating tracking categories.
if rowArgs.isDataCellCheck() then
self.hasDataCell = true
end
local row = self.root:tag('tr')
row:addClass(rowArgs.rowclass())
row:cssText(rowArgs.rowstyle())
row:attr('id', rowArgs.rowid())
local label = rowArgs.label()
if label then
row
:tag('th')
:attr('scope', 'row')
:attr('id', rowArgs.labelid())
:css('text-align', 'left')
:cssText(args.labelstyle())
:wikitext(label)
:done()
end
local dataCell = row:tag('td')
if not label then
dataCell
:attr('colspan', 2)
:css('text-align', 'center')
end
dataCell
:attr('id', rowArgs.dataid())
:addClass(rowArgs.class())
:cssText(rowArgs.datastyle())
:newline()
:wikitext(data)
end
end
return hasContent
end
function Infobox:renderNumberedRows(rowArgMaker, gap)
-- Renders numbered rows using Infobox:addRow. rowArgMaker is a function
-- that makes the table of rowArgs to be used by addRow. It takes the row
-- number as input. This method will continue to try and add rows until
-- the number of sequential blank rows is greater than the number specified
-- in gap.
local iRow, iGap = 0, 0
while iGap < gap do
iRow = iRow + 1
iGap = iGap + 1
if self:addRow(rowArgMaker(iRow)) then
iGap = 0
end
end
end
function Infobox:renderSubheaders()
local args = self.args
if args.subheader() then
args.subheader1 = args.subheader
end
if args.subheaderrowclass() then
args.subheaderrowclass1 = args.subheaderrowclass
end
return self:renderNumberedRows(
function (i)
i = tostring(i)
return {
data = args['subheader' .. i],
datastyle = function ()
return args.subheaderstyle() or args['subheaderstyle' .. i]()
end,
class = args.subheaderclass,
rowclass = args['subheaderrowclass' .. i]
}
end,
2
)
end
function Infobox:renderImages()
local args = self.args
if args.image() then
args.image1 = args.image
end
if args.caption() then
args.caption1 = args.caption
end
return self:renderNumberedRows(
function (i)
i = tostring(i)
return {
data = function ()
local image = args['image' .. i]()
if image then
local data = mw.html.create():wikitext(image)
local caption = args['caption' .. i]()
if caption then
data
:tag('div')
:cssText(args.captionstyle())
:wikitext(caption)
end
return tostring(data)
end
end,
datastyle = args.imagestyle,
class = args.imageclass,
rowclass = args['imagerowclass' .. i]
}
end,
3
)
end
function Infobox:renderContentRows()
local args = self.args
return self:renderNumberedRows(
function (i)
i = tostring(i)
return {
-- Tell addRow to set self.hasDataCells to true if it finds a
-- data cell argument.
isDataCellCheck = trueFunc,
header = args['header' .. i],
label = args['label' .. i],
data = args['data' .. i],
datastyle = args.datastyle,
class = args['class' .. i],
rowclass = args['rowclass' .. i],
rowstyle = args['rowstyle' .. i],
dataid = args['dataid' .. i],
labelid = args['labelid' .. i],
headerid = args['headerid' .. i],
rowid = args['rowid' .. i]
}
end,
10,
'hasContentRows'
)
end
function Infobox:renderNavBar()
local args = self.args
if not args.name() then return end
self.root
:tag('tr')
:tag('td')
:attr('colspan', '2')
:css('text-align', 'right')
:wikitext(mw.getCurrentFrame():expandTemplate({
title = 'navbar',
args = { args.name(), mini = 1 }
}))
end
function Infobox:renderItalicTitle()
local args = self.args
local italicTitle = args['italic title']() and mw.ustring.lower(args['italic title']())
if italicTitle == '' or italicTitle == 'force' or italicTitle == 'yes' then
self.root:wikitext(mw.getCurrentFrame():expandTemplate({title = 'italic title'}))
end
end
function Infobox:renderTrackingCategories()
local args = self.args
local cfg = self.cfg
if args.decat() ~= 'yes' then
if not self.hasContentRows and self.title.namespace == 0 then
self.root:wikitext(makeCategory(cfg['category-no-data-row']))
end
if args.child() == 'yes' and args.title() then
self.root:wikitext(makeCategory(cfg['category-embedded-title']))
end
end
end
function Infobox:__tostring()
-- Specify the overall layout of the infobox, with special settings
-- if the infobox is used as a 'child' inside another infobox.
local args = self.args
if args.child() ~= 'yes' then
self.root
:addClass('infobox')
:addClass(args.bodyclass())
if args.subbox() == 'yes' then
self.root
:css('padding', '0')
:css('border', 'none')
:css('margin', '-3px')
:css('width', 'auto')
:css('min-width', '100%')
:css('font-size', '100%')
:css('clear', 'none')
:css('float', 'none')
:css('background-color', 'transparent')
else
self.root
:css('width', '22em')
end
self.root
:cssText(args.bodystyle())
self:renderTitle()
self:renderAboveRow()
else
self.root = mw.html.create()
self.root
:wikitext(args.title())
end
self:renderSubheaders()
self:renderImages()
self:renderContentRows()
self:renderBelowRow()
self:renderNavBar()
self:renderItalicTitle()
self:renderTrackingCategories()
return tostring(self.root)
end
--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------
local p = {}
function p._infobox(args, cfg, title)
checkType('_infobox', 1, args, 'table')
checkType('_infobox', 2, cfg, 'table', true)
cfg = cfg or mw.loadData(CONFIG_MODULE)
title = title or mw.title.getCurrentTitle()
return tostring(Infobox.new(args, cfg, title))
end
function p.infobox(frame, cfg)
cfg = cfg or mw.loadData(CONFIG_MODULE)
local args
if cfg.wrapper then
local parent = frame:getParent()
local parentTitle = parent:getTitle()
local wrapper = mw.title.new(cfg.wrapper).prefixedText
if parentTitle == wrapper
or parentTitle == wrapper .. cfg['wrapper-sandbox-suffix']
then
args = parent.args
end
end
args = args or frame.args
return p._infobox(args, cfg)
end
return p