Editing Module:Infobox

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. Read the Privacy Policy to learn what information we collect about you and how we use it.

If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.

Latest revision Your text
Line 2: Line 2:
-- This module implements {{Infobox}}
-- This module implements {{Infobox}}
--
--
 
local p = {}
local p = {}
 
local navbar = require('Module:Navbar')._navbar
local HtmlBuilder = require('Module:HtmlBuilder')
 
local args = {}
local args
local origArgs
local root
local root
 
   
local function notempty( s ) return s and s:match( '%S' ) end
function union(t1, t2)
 
local function fixChildBoxes(sval, tt)
if notempty(sval) then
local marker = '<span class=special_infobox_marker>'
local s = sval
s = mw.ustring.gsub(s, '(<%s*[Tt][Rr])', marker .. '%1')
s = mw.ustring.gsub(s, '(</[Tt][Rr]%s*>)', '%1' .. marker)
if s:match(marker) then
s = mw.ustring.gsub(s, marker .. '%s*' .. marker, '')
s = mw.ustring.gsub(s, '([\r\n]|-[^\r\n]*[\r\n])%s*' .. marker, '%1')
s = mw.ustring.gsub(s, marker .. '%s*([\r\n]|-)', '%1')
s = mw.ustring.gsub(s, '(</[Cc][Aa][Pp][Tt][Ii][Oo][Nn]%s*>%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, '(<%s*[Tt][Aa][Bb][Ll][Ee][^<>]*>%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, '^(%{|[^\r\n]*[\r\n]%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, '([\r\n]%{|[^\r\n]*[\r\n]%s*)' .. marker, '%1')
s = mw.ustring.gsub(s,  marker .. '(%s*</[Tt][Aa][Bb][Ll][Ee]%s*>)', '%1')
s = mw.ustring.gsub(s, marker .. '(%s*\n|%})', '%1')
end
if s:match(marker) then
local subcells = mw.text.split(s, marker)
s = ''
for k = 1, #subcells do
if k == 1 then
s = s .. subcells[k] .. '</' .. tt .. '></tr>'
elseif k == #subcells then
local rowstyle = ' style="display:none"'
if notempty(subcells[k]) then rowstyle = '' end
s = s .. '<tr' .. rowstyle ..'><' .. tt .. ' colspan=2>\n' .. subcells[k]
elseif notempty(subcells[k]) then
if (k % 2) == 0 then
s = s .. subcells[k]
else
s = s .. '<tr><' .. tt .. ' colspan=2>\n' .. subcells[k] .. '</' .. tt .. '></tr>'
end
end
end
end
-- the next two lines add a newline at the end of lists for the PHP parser
-- https://en.wikipedia.org/w/index.php?title=Template_talk:Infobox_musical_artist&oldid=849054481
-- remove when [[:phab:T191516]] is fixed or OBE
s = mw.ustring.gsub(s, '([\r\n][%*#;:][^\r\n]*)$', '%1\n')
s = mw.ustring.gsub(s, '^([%*#;:][^\r\n]*)$', '%1\n')
return s
else
return sval
end
end
 
local function union(t1, t2)
     -- Returns the union of the values of two tables, as a sequence.
     -- Returns the union of the values of two tables, as a sequence.
     local vals = {}
     local vals = {}
Line 94: Line 44:
     if rowArgs.header then
     if rowArgs.header then
         root
         root
             :tag('tr')
             .tag('tr')
                 :addClass(rowArgs.rowclass)
                 .tag('th')
                :cssText(rowArgs.rowstyle)
                     .attr('colspan', 2)
                :attr('id', rowArgs.rowid)
                     .addClass(rowArgs.class)
                :tag('th')
                     .css('text-align', 'center')
                     :attr('colspan', 2)
                     .cssText(args.headerstyle)
                     :attr('id', rowArgs.headerid)
                     .wikitext(rowArgs.header)
                    :addClass(rowArgs.class)
                     :addClass(args.headerclass)
                    :css('text-align', 'center')
                     :cssText(args.headerstyle)
                     :cssText(rowArgs.rowcellstyle)
                    :wikitext(fixChildBoxes(rowArgs.header, 'th'))
     elseif rowArgs.data then
     elseif rowArgs.data then
         local row = root:tag('tr')
         local row = root.tag('tr')
         row:addClass(rowArgs.rowclass)
         row.addClass(rowArgs.rowclass)
        row:cssText(rowArgs.rowstyle)
        row:attr('id', rowArgs.rowid)
         if rowArgs.label then
         if rowArgs.label then
             row
             row
                 :tag('th')
                 .tag('th')
                     :attr('scope', 'row')
                     .attr('scope', 'row')
                     :attr('id', rowArgs.labelid)
                     .css('text-align', 'left')
                     :cssText(args.labelstyle)
                     .cssText(args.labelstyle)
                     :cssText(rowArgs.rowcellstyle)
                     .wikitext(rowArgs.label)
                    :wikitext(rowArgs.label)
                     .done()
                     :done()
         end
         end
          
          
         local dataCell = row:tag('td')
         local dataCell = row.tag('td')
         if not rowArgs.label then  
         if not rowArgs.label then  
             dataCell
             dataCell
                 :attr('colspan', 2)
                 .attr('colspan', 2)
                 :css('text-align', 'center')  
                 .css('text-align', 'center')  
         end
         end
         dataCell
         dataCell
             :attr('id', rowArgs.dataid)
             .addClass(rowArgs.class)
            :addClass(rowArgs.class)
             .cssText(rowArgs.datastyle)
             :cssText(rowArgs.datastyle)
             .newline()
             :cssText(rowArgs.rowcellstyle)
             .wikitext(rowArgs.data)
            :newline()
             :wikitext(fixChildBoxes(rowArgs.data, 'td'))
     end
     end
end
end
Line 143: Line 82:


     root
     root
         :tag('caption')
         .tag('caption')
             :addClass(args.titleclass)
             .addClass(args.titleclass)
             :cssText(args.titlestyle)
             .cssText(args.titlestyle)
             :wikitext(args.title)
             .wikitext(args.title)
end
end


Line 153: Line 92:
      
      
     root
     root
         :tag('tr')
         .tag('tr')
             :tag('th')
             .tag('th')
                 :attr('colspan', 2)
                 .attr('colspan', 2)
                 :addClass(args.aboveclass)
                 .addClass(args.aboveclass)
                 :css('text-align', 'center')
                 .css('text-align', 'center')
                 :css('font-size', '125%')
                 .css('font-size', '125%')
                 :css('font-weight', 'bold')
                 .css('font-weight', 'bold')
                 :cssText(args.abovestyle)
                 .cssText(args.abovestyle)
                 :wikitext(fixChildBoxes(args.above,'th'))
                 .wikitext(args.above)
end
end


Line 168: Line 107:
      
      
     root
     root
         :tag('tr')
         .tag('tr')
             :tag('td')
             .tag('td')
                 :attr('colspan', '2')
                 .attr('colspan', '2')
                 :addClass(args.belowclass)
                 .addClass(args.belowclass)
                 :css('text-align', 'center')
                 .css('text-align', 'center')
                 :cssText(args.belowstyle)
                 .cssText(args.belowstyle)
                 :newline()
                 .newline()
                 :wikitext(fixChildBoxes(args.below,'td'))
                 .wikitext(args.below)
                .newline()
end
end


Line 188: Line 128:
     for k, num in ipairs(subheadernums) do
     for k, num in ipairs(subheadernums) do
         addRow({
         addRow({
             data = args['subheader' .. tostring(num)],
             data = args['subheader' .. num],
             datastyle = args.subheaderstyle or args['subheaderstyle' .. tostring(num)],
             datastyle = args.subheaderstyle or args['subheaderstyle' .. num],
             class = args.subheaderclass,
             class = args.subheaderclass,
             rowclass = args['subheaderrowclass' .. tostring(num)]
             rowclass = args['subheaderrowclass' .. num]
         })
         })
     end
     end
Line 205: Line 145:
     local imagenums = getArgNums('image')
     local imagenums = getArgNums('image')
     for k, num in ipairs(imagenums) do
     for k, num in ipairs(imagenums) do
         local caption = args['caption' .. tostring(num)]
         local caption = args['caption' .. num]
         local data = mw.html.create():wikitext(args['image' .. tostring(num)])
         local data = HtmlBuilder.create().wikitext(args['image' .. num])
         if caption then
         if caption then
             data
             data
                 :tag('div')
                 .tag('br', {selfClosing = true})
                     :cssText(args.captionstyle)
                     .done()
                     :wikitext(caption)
                .tag('span')
                    .cssText(args.captionstyle)
                     .wikitext(caption)
         end
         end
         addRow({
         addRow({
Line 217: Line 159:
             datastyle = args.imagestyle,
             datastyle = args.imagestyle,
             class = args.imageclass,
             class = args.imageclass,
             rowclass = args['imagerowclass' .. tostring(num)]
             rowclass = args['imagerowclass' .. num]
         })
         })
     end
     end
Line 229: Line 171:
     for k, num in ipairs(rownums) do
     for k, num in ipairs(rownums) do
         addRow({
         addRow({
             header = args['header' .. tostring(num)],
             header = args['header' .. num],
             label = args['label' .. tostring(num)],
             label = args['label' .. num],
             data = args['data' .. tostring(num)],
             data = args['data' .. num],
             datastyle = args.datastyle,
             datastyle = args.datastyle,
             class = args['class' .. tostring(num)],
             class = args['class' .. num],
             rowclass = args['rowclass' .. tostring(num)],
             rowclass = args['rowclass' .. num]
            rowstyle = args['rowstyle' .. tostring(num)],
            rowcellstyle = args['rowcellstyle' .. tostring(num)],
            dataid = args['dataid' .. tostring(num)],
            labelid = args['labelid' .. tostring(num)],
            headerid = args['headerid' .. tostring(num)],
            rowid = args['rowid' .. tostring(num)]
         })
         })
     end
     end
Line 249: Line 185:
      
      
     root
     root
         :tag('tr')
         .tag('tr')
             :tag('td')
             .tag('td')
                 :attr('colspan', '2')
                 .attr('colspan', '2')
                 :css('text-align', 'right')
                 .css('text-align', 'right')
                 :wikitext(navbar{
                 .wikitext(mw.getCurrentFrame():expandTemplate({
                     args.name,
                    title = 'navbar',
                    mini = 1,
                     args = { args.name, mini = 1 }
                 })
                 }))
end
end


Line 262: Line 198:
     local italicTitle = args['italic title'] and mw.ustring.lower(args['italic title'])
     local italicTitle = args['italic title'] and mw.ustring.lower(args['italic title'])
     if italicTitle == '' or italicTitle == 'force' or italicTitle == 'yes' then
     if italicTitle == '' or italicTitle == 'force' or italicTitle == 'yes' then
         root:wikitext(mw.getCurrentFrame():expandTemplate({title = 'italic title'}))
         root.wikitext(mw.getCurrentFrame():expandTemplate({title = 'italic title'}))
     end
     end
end
end
Line 268: Line 204:
local function renderTrackingCategories()
local function renderTrackingCategories()
     if args.decat ~= 'yes' then
     if args.decat ~= 'yes' then
    if args.child == 'yes' then
        if #(getArgNums('data')) == 0 and mw.title.getCurrentTitle().namespace == 0 then
        if args.title then
            root.wikitext('[[Category:Articles which use infobox templates with no data rows]]')
            root:wikitext('[[Category:Pages which use embedded infobox templates with the title parameter]]')
        end
        end
         if args.child == 'yes' and args.title then
         elseif #(getArgNums('data')) == 0 and mw.title.getCurrentTitle().namespace == 0 then
             root.wikitext('[[Category:Articles which use embedded infobox templates with the title parameter]]')
             root:wikitext('[[Category:Articles which use infobox templates with no data rows]]')
         end
         end
     end
     end
Line 282: Line 217:
     -- if the infobox is used as a 'child' inside another infobox.
     -- if the infobox is used as a 'child' inside another infobox.
     if args.child ~= 'yes' then
     if args.child ~= 'yes' then
         root = mw.html.create('table')
         root = HtmlBuilder.create('table')
          
          
         root
         root
             :addClass((args.subbox ~= 'yes') and 'infobox' or nil)
             .addClass('infobox')
             :addClass(args.bodyclass)
             .addClass(args.bodyclass)
            .attr('cellspacing', 3)
            .css('border-spacing', '3px')
              
              
             if args.subbox == 'yes' then
             if args.subbox == 'yes' then
                 root
                 root
                     :css('padding', '0')
                     .css('padding', '0')
                     :css('border', 'none')
                     .css('border', 'none')
                     :css('margin', '-3px')
                     .css('margin', '-3px')
                     :css('width', 'auto')
                     .css('width', 'auto')
                     :css('min-width', '100%')
                     .css('min-width', '100%')
                     :css('font-size', '100%')
                     .css('font-size', '100%')
                     :css('clear', 'none')
                     .css('clear', 'none')
                     :css('float', 'none')
                     .css('float', 'none')
                     :css('background-color', 'transparent')
                     .css('background-color', 'transparent')
             else
             else
                 root
                 root
                     :css('width', '22em')
                     .css('width', '22em')
             end
             end
         root
         root
             :cssText(args.bodystyle)
             .cssText(args.bodystyle)
      
      
         renderTitle()
         renderTitle()
         renderAboveRow()
         renderAboveRow()
     else
     else
         root = mw.html.create()
         root = HtmlBuilder.create()
          
          
         root
         root
             :wikitext(args.title)
             .wikitext(args.title)
     end
     end


Line 326: Line 263:
end
end


local function preprocessSingleArg(argName)
local function touchParameters(prefixTable, origArgs, step)
     -- If the argument exists and isn't blank, add it to the argument table.
     -- Parse the parameters with the given prefixes, in order, in batches
     -- Blank arguments are treated as nil to match the behaviour of ParserFunctions.
    -- of the step size specified. This is to prevent references etc. from
     if origArgs[argName] and origArgs[argName] ~= '' then
     -- appearing in the wrong order.
         args[argName] = origArgs[argName]
     if type(prefixTable) ~= 'table' or type(origArgs) ~= 'table' then
         error("Invalid input to the touchParameters function detected. Both parameters must be tables.", 2)
     end
     end
end
     if step and type(step) ~= 'number' then
 
         error("Non-numerical step value detected.", 2)
local function preprocessArgs(prefixTable, step)
     -- Assign the parameters with the given prefixes to the args table, in order, in batches
    -- of the step size specified. This is to prevent references etc. from appearing in the
    -- wrong order. The prefixTable should be an array containing tables, each of which has
    -- two possible fields, a "prefix" string and a "depend" table. The function always parses
    -- parameters containing the "prefix" string, but only parses parameters in the "depend"
    -- table if the prefix parameter is present and non-blank.
    if type(prefixTable) ~= 'table' then
         error("Non-table value detected for the prefix table", 2)
    end
    if type(step) ~= 'number' then
        error("Invalid step value detected", 2)
     end
     end
      
      
     -- Get arguments without a number suffix, and check for bad input.
     step = step or 20 -- If the step size is not given, the default is 20.
     for i,v in ipairs(prefixTable) do
    local temp
         if type(v) ~= 'table' or type(v.prefix) ~= "string" or (v.depend and type(v.depend) ~= 'table') then
    local a = 1 -- Counter variable.
             error('Invalid input detected to preprocessArgs prefix table', 2)
    local moreArgumentsExist = true
        end
     for j,v in ipairs(prefixTable) do
        preprocessSingleArg(v.prefix)
         if not type(v) == "string" then
        -- Only parse the depend parameter if the prefix parameter is present and not blank.
             error("Non-string value detected in the prefix table in the touchParameters function.", 2)
        if args[v.prefix] and v.depend then
            for j, dependValue in ipairs(v.depend) do
                if type(dependValue) ~= 'string' then
                    error('Invalid "depend" parameter value detected in preprocessArgs')
                end
                preprocessSingleArg(dependValue)
            end
         end
         end
        temp = origArgs[v]
     end
     end
    -- Get arguments with number suffixes.
    local a = 1 -- Counter variable.
    local moreArgumentsExist = true
     while moreArgumentsExist == true do
     while moreArgumentsExist == true do
         moreArgumentsExist = false
         moreArgumentsExist = false
         for i = a, a + step - 1 do
         for i = a, a + step - 1 do
             for j,v in ipairs(prefixTable) do
             for j,v in ipairs(prefixTable) do
                 local prefixArgName = v.prefix .. tostring(i)
                 temp = origArgs[v .. tostring(i)]
                 if origArgs[prefixArgName] then
                 if temp then
                     moreArgumentsExist = true -- Do another loop if any arguments are found, even blank ones.
                     moreArgumentsExist = true
                    preprocessSingleArg(prefixArgName)
                end
                -- Process the depend table if the prefix argument is present and not blank, or
                -- we are processing "prefix1" and "prefix" is present and not blank, and
                -- if the depend table is present.
                if v.depend and (args[prefixArgName] or (i == 1 and args[v.prefix])) then
                    for j,dependValue in ipairs(v.depend) do
                        local dependArgName = dependValue .. tostring(i)
                        preprocessSingleArg(dependArgName)
                    end
                 end
                 end
             end
             end
Line 393: Line 299:
   
   
function p.infobox(frame)
function p.infobox(frame)
    local origArgs
     -- If called via #invoke, use the args passed into the invoking template.
     -- If called via #invoke, use the args passed into the invoking template.
     -- Otherwise, for testing purposes, assume args are being passed directly in.
     -- Otherwise, for testing purposes, assume args are being passed directly in.
Line 402: Line 309:
      
      
     -- Parse the data parameters in the same order that the old {{infobox}} did, so that
     -- Parse the data parameters in the same order that the old {{infobox}} did, so that
     -- references etc. will display in the expected places. Parameters that depend on
     -- references etc. will display in the expected places.
     -- another parameter are only processed if that parameter is present, to avoid
     local temp
     -- phantom references appearing in article reference lists.
     temp = origArgs.title
    preprocessSingleArg('child')
     temp = origArgs.above
    preprocessSingleArg('bodyclass')
     touchParameters({'subheader'}, origArgs, 5)
    preprocessSingleArg('subbox')
     touchParameters({'image', 'caption'}, origArgs, 5)
    preprocessSingleArg('bodystyle')
     touchParameters({'header', 'label', 'data'}, origArgs, 20)
    preprocessSingleArg('title')
    temp = origArgs.below
     preprocessSingleArg('titleclass')
    preprocessSingleArg('titlestyle')
    -- ParserFunctions considers whitespace to be false, so to preserve the previous
    preprocessSingleArg('above')
    -- behavior of {{infobox}}, change any whitespace arguments to nil, so Lua will consider
    preprocessSingleArg('aboveclass')
     -- them false too. (Except the 'italic title' param, which specifies different behavior
     preprocessSingleArg('abovestyle')
     -- depending on whether it's absent or empty)
    preprocessArgs({
     args = {}
        {prefix = 'subheader', depend = {'subheaderstyle', 'subheaderrowclass'}}
     for k, v in pairs(origArgs) do
    }, 10)
        if mw.ustring.match(v, '%S') or k == 'italic title' then
    preprocessSingleArg('subheaderstyle')
            args[k] = v
    preprocessSingleArg('subheaderclass')
        end
     preprocessArgs({
     end
        {prefix = 'image', depend = {'caption', 'imagerowclass'}}
    }, 10)
    preprocessSingleArg('captionstyle')
     preprocessSingleArg('imagestyle')
    preprocessSingleArg('imageclass')
    preprocessArgs({
        {prefix = 'header'},
        {prefix = 'data', depend = {'label'}},
        {prefix = 'rowclass'},
        {prefix = 'rowstyle'},
        {prefix = 'rowcellstyle'},
        {prefix = 'class'},
        {prefix = 'dataid'},
        {prefix = 'labelid'},
        {prefix = 'headerid'},
        {prefix = 'rowid'}
    }, 50)
     preprocessSingleArg('headerclass')
     preprocessSingleArg('headerstyle')
     preprocessSingleArg('labelstyle')
     preprocessSingleArg('datastyle')
    preprocessSingleArg('below')
    preprocessSingleArg('belowclass')
    preprocessSingleArg('belowstyle')
    preprocessSingleArg('name')
    args['italic title'] = origArgs['italic title'] -- different behaviour if blank or absent
     preprocessSingleArg('decat')
   
   
     return _infobox()
     return _infobox()
Please note that all contributions to Nonbinary Wiki are considered to be released under the Creative Commons Attribution-ShareAlike (see Nonbinary Wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!
Cancel Editing help (opens in new window)

Template used on this page: