|
|
| Line 1: |
Line 1: |
| --[=[ | | -- |
| -- For documentation, see [[Module:Infobox/doc]] | | -- This module implements {{Infobox}} |
| --]=] | | -- |
| | |
| | local p = {} |
|
| |
|
| -- <nowiki>
| | local navbar = require('Module:Navbar')._navbar |
| local Infobox = {} | |
| Infobox.__index = Infobox
| |
| Infobox.__tostring = Infobox.tostring
| |
|
| |
|
| -- Edit button for unknown params
| | local args = {} |
| local editbutton = require('Module:Edit button') | | local origArgs |
| local var = mw.ext.VariablesLua | | local root |
| local edit = editbutton("'''?''' (edit)") | |
|
| |
|
| -- Page title
| | local function notempty( s ) return s and s:match( '%S' ) end |
| local pagename = mw.title.getCurrentTitle().fullText | |
|
| |
|
| -- map of flags to html tags used by Infobox.addRow()
| | local function fixChildBoxes(sval, tt) |
| -- let's only define it once, since :addRow() is used multiple times per module
| | if notempty(sval) then |
| local tagmap = { | | local marker = '<span class=special_infobox_marker>' |
| tr = 'tr',
| | local s = sval |
| th = 'th',
| | s = mw.ustring.gsub(s, '(<%s*[Tt][Rr])', marker .. '%1') |
| td = 'td',
| | s = mw.ustring.gsub(s, '(</[Tt][Rr]%s*>)', '%1' .. marker) |
| argh = 'th',
| | if s:match(marker) then |
| argd = 'td'
| | 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') |
| -- Standardized functions
| | s = mw.ustring.gsub(s, '(<%s*[Tt][Aa][Bb][Ll][Ee][^<>]*>%s*)' .. marker, '%1') |
| -- called as string with defineParams
| | 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') |
| -- Standardized "has content" function
| | s = mw.ustring.gsub(s, marker .. '(%s*\n|%})', '%1') |
| function hasContent(arg, default)
| |
| -- Return arg if any non-whitespace character is found
| |
| return string.match(arg or '','%S') and arg or default
| |
| end
| |
| | |
| | |
| -- Standardized "name" function
| |
| function subjectName(arg)
| |
| return string.match(arg or '','%S') and arg or nil
| |
| end
| |
| | |
| -- Create a standardized release function, since so many pages use it
| |
| -- Turns release and update into a single parameter
| |
| function releaseUpdate(release, update)
| |
| if not Infobox.isDefined(release) then
| |
| return nil | |
| end
| |
| if string.lower(release) == 'no' then
| |
| return 'N/A'
| |
| end
| |
| if not Infobox.isDefined(update) then
| |
| return string.format('%s (Update unknown)',release)
| |
| end
| |
| if string.lower(update) == 'no' then
| |
| return release
| |
| end
| |
| return string.format('%s ([[Update:%s|Update]])', release, update)
| |
| end
| |
| | |
| -- Standardized image function
| |
| function image(img)
| |
| if img and img:find('%S') then
| |
| return img | |
| else
| |
| return nil
| |
| end
| |
| end
| |
| | |
| -- Standardized numbers
| |
| function numbers(num)
| |
| num = string.gsub(num or '',',','')
| |
| return tonumber(num)
| |
| end
| |
| | |
| -- map of names to pre-defined functions, used by Infobox:defineParams
| |
| local func_map = {
| |
| name = subjectName,
| |
| release = { name = releaseUpdate, params = { 'release', 'update' }, flag = 'p' },
| |
| removal = { name = releaseUpdate, params = { 'removal', 'removalupdate' }, flag = 'p' },
| |
| has_content = hasContent,
| |
| hasContent = hasContent,
| |
| image = image,
| |
| numbers = numbers,
| |
| }
| |
| | |
| -- used to fill nil params in switching sections
| |
| -- this message isn't kidding
| |
| -- If you see this message anywhere outside of this code
| |
| -- (including inside switchfo box data)
| |
| -- report it | |
| local nil_param = 'UH OH YOU SHOULDN\'T SEE THIS!'
| |
| | |
| -- In case the nil_param is needed outside of this module
| |
| -- give it an easy way to be accessed
| |
| function Infobox.nilParam()
| |
| return nil_param
| |
| end
| |
| | |
| -- switch infobox globals
| |
| local LINE_WIDTH = 300
| |
| local MAX_LINES = 2
| |
| local DEFAULT_MAX_BUTTONS = 6
| |
| -- calculate with width of a switch infobox button
| |
| -- potential @TODO: rework to use actual character widths
| |
| function button_width(label)
| |
| local PX_PER_CHAR = 6
| |
| local PX_PAD_MAR = 24
| |
| return string.len(label) * PX_PER_CHAR + PX_PAD_MAR
| |
| end
| |
| | |
| Infobox.splitpoint = '&&SPLITPOINT&&'
| |
| | |
| -- quick test to see if a value is considered nil
| |
| function Infobox.isDefined(arg)
| |
| if arg == nil then
| |
| return false
| |
| end
| |
| | |
| if type(arg) == 'string' then
| |
| if arg == nil_param then
| |
| return false
| |
| elseif arg:find('%S') then
| |
| if arg:find('action=edit') then | |
| return false
| |
| else
| |
| return true
| |
| end
| |
| else
| |
| return false
| |
| end
| |
| end
| |
| | |
| return true
| |
| end
| |
| | |
| | |
| --[[
| |
| Infobox class
| |
| -- args : parameters from frame to pass through
| |
| -- Sets a meta table and creates a <div> tag wrapper
| |
| -- other fields are initialized in other functions
| |
| --]]
| |
| function Infobox.new(args)
| |
| local obj = setmetatable({
| |
| args = args, -- parameters (uncleaned)
| |
| rargs = {}, -- parameters (cleaned)
| |
| params = {}, -- parameters mapped to functions
| |
| paramnames = {}, -- parameter names
| |
| dupeable = {}, -- parameters that are allowed to have duplicated switch data
| |
| addrswibclass = true,
| |
| switchfo = false, -- switch infobox? or not?
| |
| switchfoattr = {}, -- switch data class changes
| |
| maxbuttons = DEFAULT_MAX_BUTTONS, -- maximum number of buttons before switching becomes a menu
| |
| switch_tag = '', -- switchfo data
| |
| switch_buttons_tag = '', -- switchfo buttons
| |
| custom_buttons = false,
| |
| smw_error_tag = '',
| |
| rtable = nil, -- returned infobox table
| |
| labels = nil, -- returned labels
| |
| _smw = {}, -- semantic mediawiki data
| |
| _smwOne = {}, -- semantic mediawiki data part 2
| |
| _smwSubobject = {}, -- semantic mediawiki data part 3
| |
| _smwSubobjectName = nil, -- semantic mediawiki data part 3.5
| |
| _smwElement = {}, -- semantic mediawiki data part 4
| |
| set_default_version_smw = false, -- whether to set [[Property:Default version]]
| |
| setSMWElement = true,
| |
| suppressAllSMW = false,
| |
| suppressVersionSMW = {},
| |
| versions = -1, -- number of switch versions (-1 is uncalculated)
| |
| infoboxname = nil, -- template name
| |
| appendStrs = {},
| |
| bottomlinks = { -- template bottom links
| |
| links = {
| |
| { 'Template talk:%s', 'talk' },
| |
| { 'Template:%s', 'view' }
| |
| },
| |
| colspan = 2
| |
| },
| |
| catdata = {}, -- meta category data
| |
| catlist = {}, -- defined table of category names (strings)
| |
| __finished = false, -- infobox status
| |
| },
| |
| Infobox)
| |
| return obj
| |
| end
| |
| | |
| --[[
| |
| Toggles the addition of rsw-infobox class
| |
| use before :create()
| |
| noop if not a boolean
| |
| --]]
| |
| function Infobox:setAddRSWInfoboxClass(bool)
| |
| if type(bool) == 'boolean' then
| |
| self.addrswibclass = bool
| |
| end
| |
| end
| |
| | |
| --[[
| |
| Creates an infobox
| |
| -- If Infobox:maxVersions() has not been run, it will be run here
| |
| -- If the infobox should be a switch infobox, all labels will be added
| |
| -- Creates a wikitable that will be the infobox
| |
| THIS SHOULD BE DONE AFTER ADDING AND CLEANING PARAMETERS
| |
| --]]
| |
| function Infobox:create()
| |
| -- Run to find if this is a switch infobox and if so, how many boxes
| |
| if self.versions == -1 then
| |
| self:maxVersion()
| |
| end
| |
|
| |
| -- Run if switch infobox
| |
| if self.switchfo then
| |
| -- Buttons wrapper
| |
| -- Hidden by default, unhidden by javascript
| |
| self.switch_buttons_tag = mw.html.create('div')
| |
| :addClass('infobox-buttons')
| |
| | |
| -- default version to immediately switch to via js
| |
| local defv = tonumber(self.args.defver)
| |
| if defv and defv <= self.versions then -- you troll, don't try to show something that isn't there
| |
| self.switch_buttons_tag:attr('data-default-version',defv) | |
| end
| |
| | |
| local numlines = 1
| |
| local width_working = 0
| |
| local total_width = 0
| |
| local buttons = {}
| |
| -- Add individual buttons to the wrapper
| |
| for i=1,self.versions do
| |
| local wid = button_width(self.labels[i] or i)
| |
| width_working = width_working + wid
| |
| total_width = total_width + wid
| |
| if width_working > LINE_WIDTH then
| |
| numlines = numlines + 1
| |
| width_working = wid
| |
| end | |
| local b = mw.html.create('span')
| |
| :attr('data-switch-index',tostring(i))
| |
| -- space to underscore
| |
| :attr('data-switch-anchor','#'..string.gsub(self.labels[i] or i,' ','_'))
| |
| :addClass('button')
| |
| :wikitext(self.labels[i] or i)
| |
| table.insert(buttons, {b, wid})
| |
| end | | end |
|
| | if s:match(marker) then |
| local best = {-1, 100000}
| | local subcells = mw.text.split(s, marker) |
| if (numlines > 1) and (numlines <= MAX_LINES) then | | s = '' |
| -- attempt to balance line widths | | for k = 1, #subcells do |
| local w_s, w_e = 0,total_width | | if k == 1 then |
| for i = 1,#buttons-1 do | | s = s .. subcells[k] .. '</' .. tt .. '></tr>' |
| w_s = w_s + buttons[i][2] | | elseif k == #subcells then |
| w_e = w_e - buttons[i][2]
| | local rowstyle = ' style="display:none"' |
| if w_s > LINE_WIDTH then | | if notempty(subcells[k]) then rowstyle = '' end |
| -- w_s only increases, so we're done once it exceeds the width | | s = s .. '<tr' .. rowstyle ..'><' .. tt .. ' colspan=2>\n' .. subcells[k] |
| break | | elseif notempty(subcells[k]) then |
| end
| | if (k % 2) == 0 then |
| if w_e <= LINE_WIDTH then
| | s = s .. subcells[k] |
| -- w_e only decreases, so just continue if it exceeds line | | else |
| local diff = math.abs(w_s - w_e)
| | s = s .. '<tr><' .. tt .. ' colspan=2>\n' .. subcells[k] .. '</' .. tt .. '></tr>' |
| if diff < best[2] then | |
| best = { i, diff }
| |
| end | | end |
| end | | end |
| end
| |
| if best[1] == -1 then
| |
| best = { math.floor(#buttons/2), 100000 }
| |
| end | | end |
| end | | end |
| for i,v in ipairs(buttons) do | | return s |
| self.switch_buttons_tag:node(v[1])
| | else |
| if i == best[1] then
| | return sval |
| self.switch_buttons_tag:tag('br')
| |
| end
| |
| end
| |
|
| |
| -- Used by JavaScript to turn the buttons into a menu list if too many variants
| |
| if self.versions > self.maxbuttons or numlines > MAX_LINES then
| |
| self.switch_buttons_tag:addClass('infobox-buttons-select')
| |
| end
| |
|
| |
| self.switch_buttons_tag:done()
| |
| end
| |
| | |
| -- Create infobox table
| |
| self.rtable = mw.html.create('table')
| |
| if self.addrswibclass then
| |
| self.rtable:addClass('rsw-infobox infobox')
| |
| end
| |
| -- Add necessary class if switch infobox
| |
| if self.switchfo then | |
| self.rtable:addClass('infobox-switch') | |
| end | | end |
|
| |
| end | | end |
|
| |
|
| -- Defines an infobox name ({{Template:arg}})
| | local function union(t1, t2) |
| -- Used to create a link at the bottom of pages | | -- Returns the union of the values of two tables, as a sequence. |
| function Infobox:defineName(arg)
| | local vals = {} |
| self.infoboxname = arg
| | for k, v in pairs(t1) do |
| | vals[v] = true |
| | end |
| | for k, v in pairs(t2) do |
| | vals[v] = true |
| | end |
| | local ret = {} |
| | for k, v in pairs(vals) do |
| | table.insert(ret, k) |
| | end |
| | return ret |
| end | | end |
|
| |
|
| -- Defines the bottom links of the infobox | | local function getArgNums(prefix) |
| -- pass a table whose elements are tables that define a link and a label | | -- Returns a table containing the numbers of the arguments that exist |
| -- { | | -- for the specified prefix. For example, if the prefix was 'data', and |
| -- { 'link', 'label },
| | -- 'data1', 'data2', and 'data5' exist, it would return {1, 2, 5}. |
| -- ...
| | local nums = {} |
| -- }
| | for k, v in pairs(args) do |
| -- The template name can be substituted into the tables using '%s'
| | local num = tostring(k):match('^' .. prefix .. '([1-9]%d*)$') |
| -- If we wanted Template:InFooBar to link to it's /doc page with a "doc" label:
| | if num then table.insert(nums, tonumber(num)) end |
| -- { ...
| | end |
| -- { 'Template:%s/doc', 'doc' },
| | table.sort(nums) |
| -- ... }
| | return nums |
| -- The template's name can only be called 5 times
| |
| function Infobox:defineLinks(arg)
| |
| if type(arg) == 'table' then
| |
| if arg.colspan then
| |
| self.bottomlinks.colspan = arg.colspan
| |
| end
| |
| if arg.links then
| |
| if type(arg.links) == 'table' then
| |
| self.bottomlinks.links = arg.links
| |
| end
| |
| end
| |
| if arg.hide then
| |
| self.bottomlinks.hide = arg.hide
| |
| end
| |
| end
| |
| end | | end |
|
| |
|
| -- Change max number of buttons before switching to menu | | local function addRow(rowArgs) |
| -- defaults to 5 | | -- Adds a row to the infobox, with either a header cell |
| -- MUST BE RUN BEFORE :create() | | -- or a label/data cell combination. |
| function Infobox:setMaxButtons(arg)
| | if rowArgs.header then |
| -- if not a number, just go back to default
| | root |
| self.maxbuttons = tonumber(arg) or DEFAULT_MAX_BUTTONS
| | :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) |
| | :cssText(rowArgs.rowcellstyle) |
| | :wikitext(fixChildBoxes(rowArgs.header, 'th')) |
| | elseif rowArgs.data then |
| | local row = root:tag('tr') |
| | row:addClass(rowArgs.rowclass) |
| | row:cssText(rowArgs.rowstyle) |
| | row:attr('id', rowArgs.rowid) |
| | if rowArgs.label then |
| | row |
| | :tag('th') |
| | :attr('scope', 'row') |
| | :attr('id', rowArgs.labelid) |
| | :cssText(args.labelstyle) |
| | :cssText(rowArgs.rowcellstyle) |
| | :wikitext(rowArgs.label) |
| | :done() |
| | end |
| | |
| | local dataCell = row:tag('td') |
| | if not rowArgs.label then |
| | dataCell |
| | :attr('colspan', 2) |
| | :css('text-align', 'center') |
| | end |
| | dataCell |
| | :attr('id', rowArgs.dataid) |
| | :addClass(rowArgs.class) |
| | :cssText(rowArgs.datastyle) |
| | :cssText(rowArgs.rowcellstyle) |
| | :newline() |
| | :wikitext(fixChildBoxes(rowArgs.data, 'td')) |
| | end |
| end | | end |
|
| |
|
| --[[
| | local function renderTitle() |
| Add parameters functions
| | if not args.title then return end |
| All parameters should be tables
| |
| The first parameter defines the type of cell to create
| |
| -- th : <th>
| |
| -- td : <td>
| |
| -- argh : <th>
| |
| -- argd : <td>
| |
| The second parameter defines what is inside the tag
| |
| -- th | th : text passed
| |
| -- argh | argd : parameter with the name passed
| |
| Additional named parameters can be used to add any styling or attributes
| |
| -- attr : mw.html:attr({ arg1 = '1', ... })
| |
| -- css : mw.html:css({ arg1 = '1', ...)
| |
| -- class : mw.html:addClass('arg')
| |
| ---- class also supports a table of values, even though mw.html:addClass() does not
| |
| -- rowspan : mw.html:attr('rowspan',arg)
| |
| -- colspan : mw.html:attr('colspan',arg)
| |
| -- title : mw.html:attr('title',arg)
| |
| Example:
| |
| ipsobox:addRow( { 'th' , 'Header', title = 'Title' },
| |
| { 'argh', 'arg1', class = 'parameter' } })
| |
| produces:
| |
| <tr><th title="Title">Header</th><th class="parameter">args.arg1</th></tr>
| |
| | |
| adding it to the infobox table of ipsobox
| |
| | |
| Cells defined as 'argh' and 'argd' will automatically have data-attr-param="" added, and defined as the passed argument if the infobox in creation is defined as a switch infobox
| |
| | |
| The row itself may be modified with metadata using the named index at "meta"
| |
| -- meta.addClass : mw.html:addClass('arg')
| |
| -- this function currently only supports a single string
| |
| --]]
| |
| function Infobox.addRow(box, ...)
| |
| -- New row to add
| |
| local args = ...
| |
| local _row = box.rtable:tag('tr')
| |
| -- For each member of tags
| |
| for i, v in ipairs(args) do
| |
| -- map tag name to appropriate tag, default to <td>
| |
| local _cell = _row:tag(tagmap[v.tag] or 'td')
| |
| | |
| -- mw.html:attr() and mw.html:css() both accept table input
| |
| -- colspan, rowspan, title will be quick ways to access attr
| |
| -- these functions also do all the necessary work
| |
| if v.attr then
| |
| _cell:attr(v.attr)
| |
| end
| |
| if v.colspan then
| |
| _cell:attr('colspan',v.colspan)
| |
| end
| |
| if v.rowspan then
| |
| _cell:attr('rowspan',v.rowspan)
| |
| end
| |
| if v.title then
| |
| _cell:attr('title',v.title)
| |
| end
| |
| if v.css then
| |
| _cell:css(v.css)
| |
| end
| |
|
| |
|
| -- if class is a string, it can be added directly
| | root |
| -- if a table, add every value
| | :tag('caption') |
| -- mw.html:addClass() doesn't function with tables
| | :addClass(args.titleclass) |
| -- so iterate over the class names here and add them individually
| | :cssText(args.titlestyle) |
| if v.class then
| | :wikitext(args.title) |
| if type(v.class) == 'string' then
| |
| _cell:addClass(v.class)
| |
| elseif type(v.class) == 'table' then
| |
| for _, w in ipairs(v.class) do
| |
| _cell:addClass(w)
| |
| end
| |
| end
| |
| end
| |
| | |
| -- if the cell is a normal th or td, add the exact argument passed
| |
| if v.tag == 'th' or v.tag == 'td' then
| |
| _cell:wikitext(v.content)
| |
| -- if defined with "arg", add the argument with name passed
| |
| elseif v.tag == 'argh' or v.tag == 'argd' then
| |
| local content = box.rargs[v.content]
| |
| -- if the requested parameter doesn't exist whatsoever, just return a blank string
| |
| if not content then
| |
| content = ''
| |
| -- If switches exist, first attempt to use the version1 values
| |
| elseif content.switches then
| |
| if content.switches[1] ~= nil_param then
| |
| content = content.switches[1] or ''
| |
| else
| |
| content = content.d or ''
| |
| end
| |
| -- fallback to default value
| |
| else
| |
| content = content.d or ''
| |
| end
| |
| | |
| _cell:wikitext(content)
| |
| | |
| -- add necessary attribute for switch infoboxes
| |
| if box.switchfo then
| |
| _cell:attr('data-attr-param',v.content)
| |
| end
| |
| end
| |
| end
| |
| | |
| -- not that meta
| |
| -- allow classes to be defined on the whole row
| |
| -- okay, sort of meta
| |
| if args.meta then
| |
| if args.meta.addClass then
| |
| _row:addClass(args.meta.addClass)
| |
| end
| |
| end
| |
| | |
| return box
| |
| end | | end |
|
| |
|
| function Infobox.customButtonPlacement(box,arg) | | local function renderAboveRow() |
| box.custom_buttons = arg
| | if not args.above then return end |
| return box
| | |
| | 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(fixChildBoxes(args.above,'th')) |
| end | | end |
|
| |
|
| -- Choose whether to set [[Property:Default version]]
| | local function renderBelowRow() |
| -- Defaults to false.
| | if not args.below then return end |
| function Infobox.setDefaultVersionSMW(box, arg)
| | |
| box.set_default_version_smw = arg
| | root |
| return box
| | :tag('tr') |
| | :tag('td') |
| | :attr('colspan', '2') |
| | :addClass(args.belowclass) |
| | :css('text-align', 'center') |
| | :cssText(args.belowstyle) |
| | :newline() |
| | :wikitext(fixChildBoxes(args.below,'td')) |
| end | | end |
|
| |
|
| function Infobox.addButtonsRow(box, args) | | local function renderSubheaders() |
| if box.switchfo then
| | if args.subheader then |
| box.custom_buttons = true
| | args.subheader1 = args.subheader |
| local _row = box.rtable:tag('tr')
| | end |
| :addClass('rsw-infobox-switch-buttons-row')
| | if args.subheaderrowclass then |
| :tag('td')
| | args.subheaderrowclass1 = args.subheaderrowclass |
| :addClass('rsw-infobox-switch-buttons')
| | end |
| :attr('colspan', args.colspan)
| | local subheadernums = getArgNums('subheader') |
| :node(box.switch_buttons_tag)
| | for k, num in ipairs(subheadernums) do |
| end
| | addRow({ |
| return box
| | data = args['subheader' .. tostring(num)], |
| end
| | datastyle = args.subheaderstyle or args['subheaderstyle' .. tostring(num)], |
| function Infobox.addButtonsCaption(box)
| | class = args.subheaderclass, |
| if box.switchfo then
| | rowclass = args['subheaderrowclass' .. tostring(num)] |
| box.custom_buttons = true
| | }) |
| local _row = box.rtable:tag('caption')
| | end |
| :addClass('rsw-infobox-switch-buttons-caption')
| |
| :node(box.switch_buttons_tag)
| |
| end
| |
| return box
| |
| end | | end |
|
| |
|
| --[[
| | local function renderImages() |
| -- adds a blank row of padding spanning the given number of columns
| | if args.image then |
| --]]
| | args.image1 = args.image |
| function Infobox.pad(box, colspan, class)
| | end |
| local tr = box:tag('tr')
| | if args.caption then |
| :tag('td'):attr('colspan', colspan or 1):addClass('infobox-padding')
| | args.caption1 = args.caption |
| :done()
| | end |
| if class then
| | local imagenums = getArgNums('image') |
| tr:addClass(class)
| | for k, num in ipairs(imagenums) do |
| end
| | local caption = args['caption' .. tostring(num)] |
| tr:done()
| | local data = mw.html.create():wikitext(args['image' .. tostring(num)]) |
| return box
| | if caption then |
| | data |
| | :tag('div') |
| | :cssText(args.captionstyle) |
| | :wikitext(caption) |
| | end |
| | addRow({ |
| | data = tostring(data), |
| | datastyle = args.imagestyle, |
| | class = args.imageclass, |
| | rowclass = args['imagerowclass' .. tostring(num)] |
| | }) |
| | end |
| end | | end |
|
| |
|
| --[[ | | local function renderRows() |
| -- functions the same as mw.html:wikitext() on the wrapper
| | -- Gets the union of the header and data argument numbers, |
| -- Should only be used for categories really
| | -- and renders them all in order using addRow. |
| --]]
| | local rownums = union(getArgNums('header'), getArgNums('data')) |
| function Infobox.wikitext(box, arg)
| | table.sort(rownums) |
| box.rtable:wikitext(arg)
| | for k, num in ipairs(rownums) do |
| return box
| | addRow({ |
| | header = args['header' .. tostring(num)], |
| | label = args['label' .. tostring(num)], |
| | data = args['data' .. tostring(num)], |
| | datastyle = args.datastyle, |
| | class = args['class' .. tostring(num)], |
| | rowclass = args['rowclass' .. tostring(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 | | end |
|
| |
|
| --[[
| | local function renderNavBar() |
| -- Adds the specified item(s) to the end of the infobox, outside of the table
| | if not args.name then return end |
| -- items are concatenated together with an empty space
| | |
| --]]
| | root |
| function Infobox.append(box, ...)
| | :tag('tr') |
| for i,v in ipairs({...}) do
| | :tag('td') |
| table.insert(box.appendStrs, v)
| | :attr('colspan', '2') |
| end
| | :css('text-align', 'right') |
| return box
| | :wikitext(navbar{ |
| | args.name, |
| | mini = 1, |
| | }) |
| end | | end |
|
| |
|
| --[[
| | local function renderItalicTitle() |
| -- Adds a caption to the infobox
| | local italicTitle = args['italic title'] and mw.ustring.lower(args['italic title']) |
| -- defaults to the pagename
| | if italicTitle == '' or italicTitle == 'force' or italicTitle == 'yes' then |
| -- or the default argument if defined
| | root:wikitext(mw.getCurrentFrame():expandTemplate({title = 'italic title'})) |
| --]]
| | end |
| function Infobox.caption(box) | |
| -- default to the article's name
| |
| local name = pagename
| |
| -- first see if the name parameter exists
| |
| if box.rargs.name then
| |
| -- then try the default
| |
| if box.rargs.name.d then
| |
| name = box.rargs.name.d
| |
| -- then look for swithes
| |
| elseif box.rargs.name.switches then
| |
| -- then look at version 1
| |
| if box.rargs.name.switches[1] ~= nil_param then
| |
| name = box.rargs.name.switches[1]
| |
| end
| |
| end
| |
| end
| |
| | |
| local caption = box.rtable:tag('caption')
| |
| :wikitext(name)
| |
| | |
| -- add necessary attribute for switch infoboxes
| |
| if box.switchfo then
| |
| caption:attr('data-attr-param','name')
| |
| end
| |
| | |
| return box
| |
| end
| |
| | |
| --[[
| |
| -- Functions for styling the infobox
| |
| -- works the same as the respective mw.html functions
| |
| --]]
| |
| -- attr
| |
| function Infobox.attr(box, arg)
| |
| box.rtable:attr(arg)
| |
| return box
| |
| end
| |
| | |
| -- css
| |
| function Infobox.float(box,float)
| |
| box.rtable:css('float',float)
| |
| return box
| |
| end | |
| | |
| function Infobox.css(box, ...)
| |
| box.rtable:css(...)
| |
| return box
| |
| end | | end |
|
| |
|
| -- addClass
| | local function renderTrackingCategories() |
| function Infobox.addClass(box, arg)
| | if args.decat ~= 'yes' then |
| box.rtable:addClass(arg)
| | if #(getArgNums('data')) == 0 and mw.title.getCurrentTitle().namespace == 0 then |
| return box
| | root:wikitext('[[Category:Articles which use infobox templates with no data rows]]') |
| | end |
| | if args.child == 'yes' and args.title then |
| | root:wikitext('[[Category:Pages which use embedded infobox templates with the title parameter]]') |
| | end |
| | end |
| end | | end |
|
| |
|
| -- Much like Infobox.addClass, but adds multiple classes | | local function _infobox() |
| function Infobox.addClasses(box, ...)
| | -- Specify the overall layout of the infobox, with special settings |
| for _, v in ipairs(...) do
| | -- if the infobox is used as a 'child' inside another infobox. |
| box.rtable:addClass(box)
| | if args.child ~= 'yes' then |
| end
| | root = mw.html.create('table') |
| return box
| | |
| end | | root |
| | :addClass('infobox') |
| | :addClass(args.bodyclass) |
| | |
| | if args.subbox == 'yes' then |
| | 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 |
| | root |
| | :css('width', '22em') |
| | end |
| | root |
| | :cssText(args.bodystyle) |
| | |
| | renderTitle() |
| | renderAboveRow() |
| | else |
| | root = mw.html.create() |
| | |
| | root |
| | :wikitext(args.title) |
| | end |
|
| |
|
| --[[
| | renderSubheaders() |
| Add tags directly to the infobox table
| | renderImages() |
| Use sparingly
| | renderRows() |
| Returns the tag created rather than the entire box
| | renderBelowRow() |
| Which is an mw.html object
| | renderNavBar() |
| Further uses of :tag() will be mw.html.tag, rather than Infobox.tag
| | renderItalicTitle() |
| As such, Infobox:addRow() cannot be used afterwards without restating the infobox as the object
| | renderTrackingCategories() |
| --]]
| | |
| function Infobox.tag(box, arg)
| | return tostring(root) |
| return box.rtable:tag(arg)
| |
| end | | end |
|
| |
|
| --[[ | | local function preprocessSingleArg(argName) |
| Allows the infobox to use Semantic Media Wiki and give parameters properties
| | -- If the argument exists and isn't blank, add it to the argument table. |
| Pass a table to this function to map parameter names to properties
| | -- Blank arguments are treated as nil to match the behaviour of ParserFunctions. |
| | | if origArgs[argName] and origArgs[argName] ~= '' then |
| Calling syntax:
| | args[argName] = origArgs[argName] |
| -- {{#show:page|?property}}:
| | end |
| -- "<property>" - unqualified and without a number will display the default value
| |
| -- "<property#>" - with a number will show the switch data from that index
| |
| -- "all <property>" - adding all will display every unique value in a comma separated list
| |
| | |
| Properties initiated in Infobox:finish()
| |
| --]]
| |
| function Infobox:useSMW(arg)
| |
| if type(arg) == 'table' then
| |
| for w, v in pairs(arg) do
| |
| self._smw[w] = v
| |
| end
| |
| end
| |
| end | | end |
| --[[
| |
| As above, but only assigns to "<property>", which will act like "all <property>" - "<property>#" not present
| |
|
| |
|
| Properties initiated in Infobox:finish()
| | local function preprocessArgs(prefixTable, step) |
| --]] | | -- Assign the parameters with the given prefixes to the args table, in order, in batches |
| function Infobox:useSMWOne(arg) | | -- of the step size specified. This is to prevent references etc. from appearing in the |
| if type(arg) == 'table' then
| | -- wrong order. The prefixTable should be an array containing tables, each of which has |
| for w, v in pairs(arg) do
| | -- two possible fields, a "prefix" string and a "depend" table. The function always parses |
| self._smwOne[w] = v
| | -- parameters containing the "prefix" string, but only parses parameters in the "depend" |
| end
| | -- table if the prefix parameter is present and non-blank. |
| end
| | if type(prefixTable) ~= 'table' then |
| end
| | error("Non-table value detected for the prefix table", 2) |
| --[[ | | end |
| Set up the infobox to set properties in a SMW subobject. This will create a subobject for each version
| | if type(step) ~= 'number' then |
| - if there is only one version, it will put the properties directly on to the page, like useSMWOne
| | error("Invalid step value detected", 2) |
| | end |
| | |
| | -- Get arguments without a number suffix, and check for bad input. |
| | for i,v in ipairs(prefixTable) do |
| | if type(v) ~= 'table' or type(v.prefix) ~= "string" or (v.depend and type(v.depend) ~= 'table') then |
| | error('Invalid input detected to preprocessArgs prefix table', 2) |
| | end |
| | preprocessSingleArg(v.prefix) |
| | -- Only parse the depend parameter if the prefix parameter is present and not blank. |
| | 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 |
|
| |
|
| Properties initiated in Infobox:finish()
| | -- Get arguments with number suffixes. |
| --]] | | local a = 1 -- Counter variable. |
| function Infobox:useSMWSubobject(arg)
| | local moreArgumentsExist = true |
| if type(arg) == 'table' then
| | while moreArgumentsExist == true do |
| for w, v in pairs(arg) do
| | moreArgumentsExist = false |
| self._smwSubobject[w] = v
| | for i = a, a + step - 1 do |
| end
| | for j,v in ipairs(prefixTable) do |
| end
| | local prefixArgName = v.prefix .. tostring(i) |
| | if origArgs[prefixArgName] then |
| | moreArgumentsExist = true -- Do another loop if any arguments are found, even blank ones. |
| | 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 |
| | a = a + step |
| | end |
| end | | end |
| | | |
| function Infobox:useSMWElement(arg) | | function p.infobox(frame) |
| if type(arg) == 'table' then
| | -- If called via #invoke, use the args passed into the invoking template. |
| for w, v in pairs(arg) do
| | -- Otherwise, for testing purposes, assume args are being passed directly in. |
| self._smwElement[w] = v
| | if frame == mw.getCurrentFrame() then |
| end
| | origArgs = frame:getParent().args |
| self.setSMWElement = true
| | else |
| end
| | origArgs = frame |
| | end |
| | |
| | -- 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 |
| | -- another parameter are only processed if that parameter is present, to avoid |
| | -- phantom references appearing in article reference lists. |
| | preprocessSingleArg('child') |
| | preprocessSingleArg('bodyclass') |
| | preprocessSingleArg('subbox') |
| | preprocessSingleArg('bodystyle') |
| | preprocessSingleArg('title') |
| | preprocessSingleArg('titleclass') |
| | preprocessSingleArg('titlestyle') |
| | preprocessSingleArg('above') |
| | preprocessSingleArg('aboveclass') |
| | preprocessSingleArg('abovestyle') |
| | preprocessArgs({ |
| | {prefix = 'subheader', depend = {'subheaderstyle', 'subheaderrowclass'}} |
| | }, 10) |
| | preprocessSingleArg('subheaderstyle') |
| | preprocessSingleArg('subheaderclass') |
| | preprocessArgs({ |
| | {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() |
| end | | end |
| --[[
| | |
| Finishing function
| | return p |
| -- Finishes the return, adding necessary final tags
| |
| --]]
| |
| function Infobox:finish()
| |
| local currentNamespace = mw.title.getCurrentTitle().namespace
| |
| -- 0 = mainspace, 4 = RuneScape
| |
| local onContentNamespace = currentNamespace == 0 or currentNamespace == 4
| |
| -- Don't finish twice
| |
| if self.__finished then
| |
| return
| |
| end
| |
|
| |
| -- Add switch infobox resources
| |
| if self.switchfo then
| |
| self.rtable:attr('data-resource-class', '.infobox-resources-'..string.gsub(tostring(self.infoboxname), ' ', '_'))
| |
| -- Wrapper tag, hidden
| |
| self.switch_tag = mw.html.create('div')
| |
| :addClass('infobox-switch-resources')
| |
| :addClass('infobox-resources-'..string.gsub(tostring(self.infoboxname), ' ', '_'))
| |
| :addClass('hidden')
| |
| | |
| for _, v in ipairs(self.paramnames) do
| |
| local param = self.rargs[v]
| |
| local default_value = param.d or edit
| |
| -- Parameters may not have any switches data, those are ignored
| |
| local switchattr = self.switchfoattr[v]
| |
| -- Parameter data wrapper
| |
| local res_span = self.switch_tag:tag('span')
| |
| :attr('data-attr-param',v)
| |
| -- Child for default value
| |
| local def = res_span:tag('span')
| |
| :attr('data-attr-index',0)
| |
| :wikitext(tostring(default_value))
| |
| | |
| -- Switch classes
| |
| if switchattr then
| |
| def:attr('data-addclass',switchattr.d)
| |
| end
| |
| | |
| def:done()
| |
| | |
| if param.switches then
| |
| -- Add all switches, ignore those defined as nil
| |
| for i, w in ipairs(param.switches) do
| |
| if w ~= nil_param and w ~= nil and w ~= default_value then
| |
| local _w = res_span:tag('span')
| |
| :attr('data-attr-index',i)
| |
| :wikitext(tostring(w))
| |
| -- Switch classes
| |
| if switchattr and switchattr.switches then
| |
| _w:attr('data-addclass',switchattr.switches[i])
| |
| elseif switchattr then
| |
| mw.logObject({string.format("Expected switches for `%s` but got none:", v), switchattr})
| |
| end
| |
| | |
| _w:done()
| |
| end
| |
| end
| |
| res_span:done()
| |
| end
| |
| end
| |
| | |
| -- Add a tracking category for pages that have more than 1 version
| |
| if onContentNamespace and self.versions > 1 then
| |
| -- version count data
| |
| self.switch_tag:wikitext('[[Category:Pages that contain switch infobox data]]')
| |
| | |
| if not self.suppressAllSMW then
| |
| self.switch_tag:tag('span')
| |
| :wikitext(string.format('Versions: [[Version count::%s]]',self.versions))
| |
| :done()
| |
| | |
| -- set default version smw
| |
| local defver = tonumber(self.args.defver) or 1
| |
| local default_subobject_value = self.args['smwname'..defver] or self.args['version'..defver]
| |
| if default_subobject_value and self.set_default_version_smw then
| |
| -- Only take first subobject if multiple are defined using "¦"
| |
| local default_subobject_name = default_subobject_value:match("[^¦]+")
| |
| self.switch_tag:tag('span')
| |
| :wikitext(string.format('Default version: [[Default version::%s]]',default_subobject_name))
| |
| end
| |
| end
| |
| end
| |
| | |
| self.switch_tag:done()
| |
| end
| |
|
| |
| -- smw data
| |
| if onContentNamespace and not self.suppressAllSMW then
| |
| -- members smw display, yes --> true; no --> false; other --> unknown
| |
| local function smwMembers(smw_arg)
| |
| local smw_argv = string.lower(smw_arg or '')
| |
| if smw_argv == 'yes' then
| |
| return 'true'
| |
| elseif smw_argv == 'no' then
| |
| return 'false'
| |
| else
| |
| return 'unknown'
| |
| end
| |
| end
| |
| | |
| -- release date smw display
| |
| local function smwRelease(smw_arg)
| |
| local _d,_m,_y = string.match(smw_arg or '', '%[%[(%d%d?) (%a+)%]%] %[%[(%d%d%d%d)%]%]')
| |
| if _d == nil then
| |
| return nil
| |
| end
| |
| return table.concat({_d,_m,_y},' ')
| |
| end
| |
| | |
| -- default, just return the text
| |
| local function smwDefault(smw_arg)
| |
| if smw_arg ~= nil_param and smw_arg ~= edit then
| |
| return smw_arg
| |
| else
| |
| return 'unknown'
| |
| end
| |
| end
| |
| | |
| local smw_to_func = {
| |
| members = smwMembers,
| |
| release = smwRelease,
| |
| removal = smwRelease,
| |
| default = smwDefault
| |
| }
| |
| local smw_data_arr = {}
| |
| | |
| -- custom properties
| |
| for w, v in pairs(self._smw) do
| |
| -- only needed to give special formatting to release
| |
| -- and to make members true/false
| |
| local smwfunc = smw_to_func[w] or smw_to_func.default
| |
| | |
| local curarg = self.rargs[w]
| |
| if curarg then
| |
| local _arg = curarg.d
| |
| local argdefault = _arg
| |
| if _arg == edit then
| |
| argdefault = 'unknown'
| |
| else
| |
| local _x = mw.text.split(tostring(_arg), Infobox.splitpoint, true)
| |
| if not smw_data_arr[v] then
| |
| smw_data_arr[v] = {}
| |
| end
| |
| if not smw_data_arr['All '..v] then
| |
| smw_data_arr['All '..v] = {}
| |
| end
| |
| for _,y in ipairs(_x) do
| |
| local temp_smw_data = smwfunc(y)
| |
| table.insert(smw_data_arr[v], temp_smw_data)
| |
| table.insert(smw_data_arr['All '..v], temp_smw_data)
| |
| end
| |
| end
| |
| | |
| if curarg.switches then
| |
| local _args = {}
| |
| | |
| for x_i, x in ipairs(curarg.switches) do
| |
| if not self.suppressVersionSMW[x_i] then
| |
| if x ~= nil_param then
| |
| table.insert(_args,x)
| |
| else
| |
| table.insert(_args,argdefault or nil_param)
| |
| end
| |
| end
| |
| end
| |
| | |
| for i, x in ipairs(_args) do
| |
| local _x = mw.text.split(tostring(x), Infobox.splitpoint, true)
| |
| if not smw_data_arr[v..i] then
| |
| smw_data_arr[v..i] = {}
| |
| end
| |
| if not smw_data_arr['All '..v] then
| |
| smw_data_arr['All '..v] = {}
| |
| end
| |
| for _,y in ipairs(_x) do
| |
| local temp_smw_data = smwfunc(y)
| |
| table.insert(smw_data_arr[v..i], temp_smw_data)
| |
| table.insert(smw_data_arr['All '..v], temp_smw_data)
| |
| end
| |
| end
| |
| end
| |
| end
| |
| end
| |
|
| |
| -- if one version, put smwSubobject into smwOne and just do that
| |
| if self.versions < 2 and not self._smwSubobjectName then
| |
| for w,v in pairs(self._smwSubobject) do
| |
| if not self._smwOne[w] then
| |
| self._smwOne[w] = v
| |
| elseif type(self._smwOne[w]) == 'table' then
| |
| table.insert(self._smwOne[w], v)
| |
| else
| |
| self._smwOne[w] = { self._smwOne[w], v }
| |
| end
| |
| end
| |
| end
| |
|
| |
| for w, _v in pairs(self._smwOne) do
| |
| -- only needed to give special formatting to release
| |
| -- and to make members true/false
| |
| local smwfunc = smw_to_func[w] or smw_to_func.default
| |
| | |
| local curarg = self.rargs[w]
| |
|
| |
| if curarg then
| |
| local _arg = curarg.d
| |
| local argdefault = _arg
| |
| if _arg == edit then
| |
| argdefault = 'unknown'
| |
| end
| |
| if curarg.switches then
| |
| local _args = {}
| |
| | |
| for x_i, x in ipairs(curarg.switches) do
| |
| if not self.suppressVersionSMW[x_i] then
| |
| if x ~= nil_param then
| |
| table.insert(_args,x)
| |
| else
| |
| table.insert(_args,argdefault or nil_param)
| |
| end
| |
| end
| |
| end
| |
| | |
| for i, x in ipairs(_args) do
| |
| local _x = mw.text.split(tostring(x), Infobox.splitpoint, true)
| |
| for _,y in ipairs(_x) do
| |
| local temp_smw_data = smwfunc(y)
| |
| for _,v in ipairs(type(_v) == 'table' and _v or {_v}) do
| |
| if not smw_data_arr[v] then
| |
| smw_data_arr[v] = {}
| |
| end
| |
| table.insert(smw_data_arr[v], temp_smw_data)
| |
| end
| |
| end
| |
| end
| |
| else
| |
| if Infobox.isDefined(_arg) then
| |
| local _targ = mw.text.split(tostring(_arg), Infobox.splitpoint, true)
| |
| for _,y in ipairs(_targ) do
| |
| local temp_smw_data = smwfunc(y)
| |
| for _,v in ipairs(type(_v) == 'table' and _v or {_v}) do
| |
| if not smw_data_arr[v] then
| |
| smw_data_arr[v] = {}
| |
| end
| |
| table.insert(smw_data_arr[v], temp_smw_data)
| |
| end
| |
| end
| |
| end
| |
| end
| |
| end
| |
| end
| |
| local smw_data_arr_elem = {}
| |
| for w, v in pairs(self._smwElement) do
| |
| -- only needed to give special formatting to release
| |
| -- and to make members true/false
| |
| local smwfunc = smw_to_func[w] or smw_to_func.default
| |
| | |
| local curarg = self.rargs[w]
| |
|
| |
| if curarg then
| |
| local _arg = curarg.d
| |
| local argdefault = _arg
| |
| if _arg == edit then
| |
| argdefault = 'unknown'
| |
| end
| |
| if curarg.switches then
| |
| local _args = {}
| |
| | |
| for x_i, x in ipairs(curarg.switches) do
| |
| if not self.suppressVersionSMW[x_i] then
| |
| if x ~= nil_param then
| |
| table.insert(_args,x)
| |
| else
| |
| table.insert(_args,argdefault or nil_param)
| |
| end
| |
| end
| |
| end
| |
| | |
| for i, x in ipairs(_args) do
| |
| if Infobox.isDefined(x) then
| |
| local _x = mw.text.split(tostring(x), Infobox.splitpoint, true)
| |
| for _,y in ipairs(_x) do
| |
| local temp_smw_data = smwfunc(y)
| |
| if not smw_data_arr_elem[v] then
| |
| smw_data_arr_elem[v] = {}
| |
| end
| |
| table.insert(smw_data_arr_elem[v], temp_smw_data)
| |
| end
| |
| end
| |
| end
| |
| else
| |
| if Infobox.isDefined(_arg) then
| |
| local _targ = mw.text.split(tostring(_arg), Infobox.splitpoint, true)
| |
| for _,y in ipairs(_targ) do
| |
| local temp_smw_data = smwfunc(y)
| |
| if not smw_data_arr_elem[v] then
| |
| smw_data_arr_elem[v] = {}
| |
| end
| |
| table.insert(smw_data_arr_elem[v], temp_smw_data)
| |
| end
| |
| end
| |
| end
| |
| end
| |
| end
| |
| -- if is a switchfo, setup for subobjects
| |
| local smw_data_arr_subobj = {}
| |
| if self._smwSubobjectName then
| |
| for i,k in ipairs(self._smwSubobjectName) do
| |
| if not self.suppressVersionSMW[i] then
| |
| local subobj_data = {
| |
| ['Is variant of'] = {pagename},
| |
| }
| |
| for w,v in pairs(self._smwSubobject) do
| |
| local smwfunc = smw_to_func[w] or smw_to_func.default
| |
| local curarg = self.rargs[w]
| |
| if curarg then
| |
| local argval = curarg.d
| |
| if curarg.switches then
| |
| argval = curarg.switches[i]
| |
| if not Infobox.isDefined(argval) then
| |
| argval = curarg.d
| |
| end
| |
| end
| |
| if Infobox.isDefined(argval) then
| |
| local _x = mw.text.split(tostring(argval), Infobox.splitpoint, true)
| |
| for _, _x1 in ipairs(_x) do
| |
| _x1 = smwfunc(_x1)
| |
| if _x1 ~= 'unknown' then
| |
| if not subobj_data[v] then
| |
| subobj_data[v] = {}
| |
| end
| |
| table.insert(subobj_data[v], _x1)
| |
| end
| |
| end
| |
| end
| |
| end
| |
| end
| |
| for w,v in ipairs(k) do
| |
| local subobj_name = v
| |
| -- can't have a . in the first 5 characters of a subobject identifier
| |
| if mw.ustring.find(mw.ustring.sub(subobj_name,0,5), '%.') then
| |
| self:wikitext('[[Category:Pages with an invalid subobject name]]')
| |
| subobj_name = mw.ustring.gsub(subobj_name, '%.', '')
| |
| end
| |
| if subobj_name == '0' or subobj_name == '' then
| |
| self:wikitext('[[Category:Pages with an invalid subobject name]]')
| |
| subobj_name = 'v_'..subobj_name
| |
| end
| |
| smw_data_arr_subobj[subobj_name] = subobj_data
| |
| end
| |
| end
| |
| end
| |
| end
| |
| local res = mw.smw.set(smw_data_arr)
| |
| local res_subobj = true
| |
| for w,v in pairs(smw_data_arr_subobj) do
| |
| res_subobj = mw.smw.subobject(v, w)
| |
| if not res_subobj == true then
| |
| break
| |
| end
| |
| end
| |
| if not (res == true and res_subobj == true) then
| |
| self.smw_error_tag = mw.html.create('div'):css('display','none'):addClass('infobox-smw-data')
| |
| if not res == true then
| |
| self.smw_error_tag:tag('div'):wikitext('Error setting SMW properties: '+res.error):done()
| |
| end
| |
| if not res_subobj == true then
| |
| self.smw_error_tag:tag('div'):wikitext('Error setting SMW subobject properties: '+res_subobj.error):done()
| |
| end
| |
| end
| |
|
| |
| if self.setSMWElement then
| |
| if self.smw_error_tag == '' then
| |
| self.smw_error_tag = mw.html.create('div'):css('display','none'):addClass('infobox-smw-data')
| |
| end
| |
| for i,v in pairs(smw_data_arr_elem) do
| |
| for j,k in ipairs(v) do
| |
| if k ~= 'unknown' then
| |
| self.smw_error_tag:tag('span'):wikitext(mw.ustring.format('%s: [[%s::%s]]', i,i,k ))
| |
| end
| |
| end
| |
| end
| |
| end
| |
| if self._smwSubobjectName then
| |
| if self.smw_error_tag == '' then
| |
| self.smw_error_tag = mw.html.create('div'):css('display','none'):addClass('infobox-smw-data')
| |
| end
| |
| for w,v in pairs(smw_data_arr_subobj) do
| |
| local subobjdiv = self.smw_error_tag:tag('div')
| |
| subobjdiv:tag('span'):wikitext('SMW Subobject for '..w)
| |
| for j,k in pairs(v) do
| |
| subobjdiv:tag('span'):wikitext(mw.ustring.format('%s: %s', j, table.concat(k, ', ')))
| |
| end
| |
| end
| |
| end
| |
| end
| |
|
| |
| | |
| -- Add view and talk links to infobox
| |
| -- Only done if a name is defined
| |
| if self.infoboxname and not self.bottomlinks.hide then
| |
| local bottom_links = {}
| |
| for _, v in ipairs(self.bottomlinks.links) do
| |
| table.insert(bottom_links,
| |
| string.format(
| |
| table.concat({'[[',
| |
| v[1],
| |
| '|',
| |
| v[2],
| |
| ']]'}),
| |
| self.infoboxname,
| |
| self.infoboxname,
| |
| self.infoboxname,
| |
| self.infoboxname,
| |
| self.infoboxname)
| |
| )
| |
| end
| |
| | |
| bottom_links = table.concat(bottom_links,' • ')
| |
| self.rtable:tag('tr'):tag('td')
| |
| :addClass('infobox-template-links')
| |
| :attr('colspan', self.bottomlinks.colspan)
| |
| :wikitext(bottom_links)
| |
| :done()
| |
| end
| |
| -- Define as finished
| |
| self.__finished = true
| |
| end
| |
| | |
| --[[
| |
| Function for defining parameters
| |
| -- name : parameter name
| |
| -- func : function to define param, defaults to looking at blanks
| |
| DO NOT DEFINE VERSION HERE
| |
| USE :maxVersion()
| |
| Can be used any number of times for efficient definition
| |
| --]]
| |
| function Infobox:defineParams(...)
| |
| for _, v in ipairs(...) do
| |
| -- For every parameter, store its corresponding function to self.params
| |
| if v.name then
| |
| -- If the value is a function or a table (which should define a function)
| |
| if type(v.func) == 'function' or type(v.func) == 'table' then
| |
| self.params[v.name] = v.func
| |
| -- If the value is a string, use the predefined Infobox function of that name
| |
| elseif type(v.func) == 'string' then
| |
| self.params[v.name] = func_map[v.func] or hasContent
| |
| -- Everything else just looks for blanks
| |
| else
| |
| self.params[v.name] = hasContent()
| |
| end
| |
| -- Create a list of all param names
| |
| table.insert(self.paramnames,v.name)
| |
| -- function to allow duplicated values
| |
| if v.dupes then
| |
| self.dupeable[v.name] = true
| |
| end
| |
| end
| |
| end
| |
| end
| |
| | |
| --[[
| |
| -- Forces an infobox to only use 1 variant
| |
| -- Mainly used by lite infoboxes
| |
| -- This should be run before creation
| |
| --]]
| |
| function Infobox:noSwitch()
| |
| self.versions = 1
| |
| self.switchfo = false
| |
| end
| |
| | |
| --[[
| |
| -- Calculates the max version
| |
| -- Adds labels
| |
| -- Sees if this needs to be a switch infobox
| |
| -- Returns extra version count (even if already run)
| |
| --]]
| |
| function Infobox.maxVersion(box)
| |
| -- Only allowed to run once
| |
| if box.versions ~= -1 then
| |
| return box.versions
| |
| end
| |
| | |
| box.labels = {}
| |
| box.versions = 0
| |
| local smwname = {}
| |
|
| |
| if string.lower(box.args['smw'] or '') == 'no' then
| |
| box.suppressAllSMW = true
| |
| end
| |
| -- Look for up to 125 variants, defined in order
| |
| for i=1, 125 do
| |
| -- If variant# exists
| |
| if box.args['version'..i] then
| |
| -- Increase version count
| |
| box.versions = box.versions + 1
| |
| | |
| -- Add its label
| |
| local label = box.args['version'..i] or ('Version '..i)
| |
| table.insert(box.labels,label)
| |
|
| |
| -- add to smwname
| |
| if box.args['smwname'..i] then
| |
| table.insert(smwname, mw.text.split(box.args['smwname'..i], '¦'))
| |
| else
| |
| table.insert(smwname, {label})
| |
| end
| |
|
| |
| box.suppressVersionSMW[i] = (box.args['smw'..i] and string.lower(box.args['smw'..i] or '') == 'no')
| |
| else
| |
| -- Stop if it doesn't exist
| |
| break
| |
| end
| |
| end
| |
| | |
| -- Define self as a switch infobox if at least 1 other version is found
| |
| if box.versions > 0 then
| |
| box.switchfo = true
| |
| box._smwSubobjectName = smwname
| |
| else
| |
| -- single version, check for smwname
| |
| if box.args['smwname'] then
| |
| box._smwSubobjectName = {mw.text.split(box.args['smwname'], '¦')}
| |
| end
| |
| end
| |
| | |
| -- versions calculated
| |
| return box.versions
| |
| end
| |
| | |
| --[[
| |
| -- Cleans parameters as defined by the above function
| |
| -- SHOULD NOT BE RUN UNTIL ALL THINGS ARE DEFINED
| |
| -- Handles switches as well
| |
| -- adds table _add to rargs, a cleaned up version of arguments
| |
| -- d : default value
| |
| -- switches : table of switches (in numerical order)
| |
| -- Functions can be defined with tables
| |
| ---- name : name of function
| |
| ---- params : table of args to pass to functions
| |
| ---- flag : flags for input
| |
| d | #default : use the cleaned parameter first, otherwise passed
| |
| p : use the passed value of parameters
| |
| r | l : use raw (literal) text, rather than values
| |
| -- Defining a single flag will use that flag on all parameters
| |
| -- Defining a table of flags will use the respective flag by position
| |
| --]]
| |
| function Infobox:cleanParams()
| |
| -- map of flags to functionality
| |
| local flagmap = {
| |
| r = 'r',
| |
| l = 'r',
| |
| d = 'd',
| |
| p = 'p'
| |
| }
| |
| -- For all parameters named
| |
| for _, v in ipairs(self.paramnames) do
| |
| -- Parameter to add
| |
| local _add = {}
| |
| local catdata = { all_defined = true, one_defined = false }
| |
| -- If the value of params is a function
| |
| if type(self.params[v]) == 'function' then
| |
| -- Perform that function with the parameter
| |
| _add.d = self.params[v](self.args[v])
| |
| -- If it's a table, parse it into a function
| |
| elseif type(self.params[v]) == 'table' then
| |
| -- Find the functions name
| |
| local func = self.params[v].name
| |
| | |
| if type(func) == 'string' then
| |
| func = func_map[func]
| |
| end
| |
| | |
| -- catch all
| |
| if type(func) ~= 'function' then
| |
| func = has_content
| |
| end
| |
| | |
| -- Recreate table of args and flags
| |
| local func_args = {}
| |
| local flag = {}
| |
| -- If the flags are NOT a table, turn them into a table
| |
| -- Same size as the parameter table
| |
| -- Every flag will be the same
| |
| if type(self.params[v].flag) ~= 'table' then
| |
| -- Map flags, if unmapped, use default
| |
| local _flag = flagmap[self.params[v].flag] or 'd'
| |
| -- recreate table
| |
| for x=1,#self.params[v].params do
| |
| table.insert(flag,_flag)
| |
| end
| |
| -- If flags are already a table, recreate them in new table
| |
| elseif type(self.params[v].flag) == 'table' then
| |
| local _flag = self.params[v].flag
| |
| -- recreate table
| |
| for x=1,#self.params[v].params do
| |
| -- Map flags, if unmapped, use default
| |
| table.insert(flag,flagmap[_flag[x]] or 'd')
| |
| end
| |
| end
| |
| -- Recreate param table, parsing flags as instructions
| |
| for x, w in ipairs(self.params[v].params) do
| |
| local xarg
| |
| -- By default or defined as 'd'
| |
| -- looks for the cleaned value of the named parameter first
| |
| -- if it doesn't exist, look at the passed value next
| |
| -- if that doesn't exist, use blank
| |
| if flag[x] == 'd' then
| |
| xarg = self.rargs[w] and self.rargs[w].d
| |
| -- compare to nil explicitly because false is a valid value
| |
| if xarg == nil then
| |
| xarg = self.args[w] or ''
| |
| end
| |
| -- Look only at the passed value of the named parameter
| |
| -- if that doesn't exist, use blank
| |
| elseif flag[x] == 'p' then
| |
| xarg = self.args[w] or ''
| |
| -- Don't interpret value as a parameter name, and paste the as is
| |
| elseif flag[x] == 'r' then
| |
| xarg = w
| |
| end
| |
| -- Add parsed argument to table
| |
| table.insert(func_args,xarg)
| |
| end
| |
| -- Run function
| |
| _add.d = func(unpack(func_args))
| |
| end
| |
| | |
| if _add.d == nil or _add.d == nil_param then
| |
| -- have to do pagename defaults here to prevent weird behaviour with switch values
| |
| if v == 'name' then
| |
| _add.d = pagename
| |
| else
| |
| _add.d = edit
| |
| end
| |
| catdata.all_defined = false
| |
| else
| |
| --_add.d is not nil
| |
| catdata.one_defined = true
| |
| end
| |
|
| |
| if self.switchfo then
| |
| -- Table of switches values and count of them
| |
| local _add_switch = {}
| |
| local switches = 0
| |
| -- Look for up to the maximum number
| |
| for i=1, self.versions do
| |
| local _addarg
| |
| -- see if this param is allowed to have switch
| |
| if v ~= 'image' and v ~= 'examine' and string.find(self.args[v..i] or '','%$%d') then
| |
| local refi = string.match(self.args[v..i],'%$(%d+)')
| |
| _addarg = _add_switch[tonumber(refi)] or nil_param
| |
| else
| |
| -- If the value of params is a function
| |
| if type(self.params[v]) == 'function' then
| |
| -- Perform that function with the parameter at that index
| |
| _addarg = self.params[v](self.args[v..i])
| |
| -- If it's a table, parse it into a function
| |
| elseif type(self.params[v]) == 'table' then
| |
| -- Find the functions name
| |
| local func = self.params[v].name
| |
| | |
| | |
| if type(func) == 'string' then
| |
| func = func_map[func]
| |
| end
| |
| | |
| -- catch all
| |
| if type(func) ~= 'function' then
| |
| func = has_content
| |
| end
| |
| | |
| -- Recreate table of args and flags
| |
| local func_args = {}
| |
| local flag = {}
| |
| -- If the flags are NOT a table, turn them into a table
| |
| -- Same size as the parameter table
| |
| -- Every flag will be the same
| |
| if type(self.params[v].flag) ~= 'table' then
| |
| -- Map flags, if unmapped, use default
| |
| local _flag = flagmap[self.params[v].flag] or 'd'
| |
| -- recreate table
| |
| for x=1,#self.params[v].params do
| |
| table.insert(flag,_flag)
| |
| end
| |
| -- If flags are already a table, recreate them in new table
| |
| elseif type(self.params[v].flag) == 'table' then
| |
| local _flag = self.params[v].flag
| |
| -- recreate table
| |
| for x=1,#self.params[v].params do
| |
| -- Map flags, if unmapped, use default
| |
| table.insert(flag,flagmap[_flag[x]] or 'd')
| |
| end
| |
| end
| |
| -- Recreate param table, parsing flags as instructions
| |
| for x, w in ipairs(self.params[v].params) do
| |
| local xarg
| |
| -- By default or defined as 'd'
| |
| -- looks for the cleaned value of the named parameter first
| |
| -- if it doesn't exist, look at the passed value next
| |
| -- if that doesn't exist, look at the default
| |
| -- if that doesn't exist, use blank
| |
| if flag[x] == 'd' then
| |
| if self.rargs[w] then
| |
| if self.rargs[w].switches then
| |
| xarg = self.rargs[w].switches[i]
| |
| else
| |
| xarg = self.args[w..i]
| |
| end
| |
| if xarg == nil or xarg == nil_param then
| |
| xarg = self.rargs[w].d
| |
| end
| |
| end
| |
| -- multiple catches in a row just to cover everything
| |
| if xarg == nil or xarg == nil_param then
| |
| xarg = self.args[w..i]
| |
| end
| |
| if xarg == nil or xarg == edit or xarg == nil_param then
| |
| xarg = self.args[w]
| |
| end
| |
| if xarg == nil or xarg == edit or xarg == nil_param then
| |
| xarg = ''
| |
| end
| |
| -- Look only at the passed value of the named parameter
| |
| -- if that doesn't exist, use unnumbered parameter
| |
| -- if that doesn't exist, use blank
| |
| elseif flag[x] == 'p' then
| |
| xarg = self.args[w..i] or self.args[w] or ''
| |
| -- Don't interpret value as a parameter name, and paste the as is
| |
| elseif flag[x] == 'r' then
| |
| xarg = w
| |
| end
| |
| -- Add parsed argument to table
| |
| table.insert(func_args,xarg)
| |
| end
| |
| -- Run function
| |
| _addarg = func(unpack(func_args))
| |
| end
| |
| end
| |
| -- If not defined, add the nil_param value
| |
| -- An actual nil would cause errors in placement
| |
| -- So it needs to be filled with an actual value
| |
| -- "nil_param" is understood as nil in other functions
| |
| -- Include table in case parameter isn't defined by template
| |
| | |
| if _addarg == nil or _addarg == nil_param then
| |
| table.insert(_add_switch, nil_param)
| |
| else
| |
| switches = switches + 1
| |
| table.insert(_add_switch, _addarg)
| |
| catdata.one_defined = true
| |
| end
| |
| end
| |
| -- If there are actually other values to switch to
| |
| -- Define a switches subtable, otherwise ignore it
| |
| if switches > 0 then
| |
| _add.switches = _add_switch
| |
| end
| |
| end
| |
| | |
| -- Quick fix for names (which defaults to pagename)
| |
| if v == 'name' then
| |
| if _add.d == pagename then
| |
| if _add.switches and _add.switches[1] ~= pagename and _add.switches[1] ~= nil_param then
| |
| _add.d = _add.switches[1]
| |
| end
| |
| end
| |
| end
| |
| | |
| -- Parameter cleaning finished, add to table of cleaned args
| |
| self.rargs[v] = _add
| |
| | |
| -- Category metadata
| |
| -- If every param except default is defined, all_defined = true
| |
| if catdata.all_defined == false then
| |
| if _add.d == edit then
| |
| if _add.switches then
| |
| catdata.all_defined = true
| |
| for _, v in ipairs(_add.switches) do
| |
| if v == nil_param then
| |
| catdata.all_defined = false
| |
| break
| |
| end
| |
| end
| |
| end
| |
| end
| |
| end
| |
| | |
| self.catdata[v] = catdata
| |
| end
| |
| | |
| -- mass dupe removal
| |
| -- this needs to be done at the end to keep dependent parameters working
| |
| -- also removes incompatible data types
| |
| for _, v in ipairs(self.paramnames) do
| |
| -- not removed from dupe enabled params parameters
| |
| if not self.dupeable[v] and self.rargs[v] and self.rargs[v].switches then
| |
| -- tells us whether or not we'll need to remove the switch data
| |
| -- switched to false if a switch values does not match the default
| |
| local rmvswitch = true
| |
| for q, z in ipairs(self.rargs[v].switches) do
| |
| -- remove types that don't turn into strings properly
| |
| if type(z) == 'table' or type(z) == 'function' then
| |
| self.rargs[v].switches[q] = nil_param
| |
| | |
| -- if it isn't nil or an edit button
| |
| -- change variable to keep the switch data
| |
| elseif z ~= nil_param and z ~= edit then
| |
| rmvswitch = false
| |
| end
| |
| end
| |
| -- remove switch data if everything was a dupe
| |
| if rmvswitch then
| |
| self.rargs[v].switches = nil
| |
| end
| |
| end
| |
| end
| |
| | |
| -- Title parentheses (has to be done here, sadly)
| |
| local _name
| |
| if self.rargs.name then
| |
| _name = self.rargs.name.d
| |
| -- replace html entities to their actual character
| |
| _name = mw.text.decode(_name)
| |
| | |
| -- if the page name matches the item name, don't add parentheses
| |
| if _name == mw.title.getCurrentTitle().fullText then
| |
| self.rtable:addClass('no-parenthesis-style')
| |
| end
| |
| end
| |
| end
| |
| | |
| --[[
| |
| Function to link internal use parameters with JS class attribution
| |
| -- self:linkParams{ { arg1, arg2 }, ... { arg1a, arg2a } }
| |
| -- arg1: parameter name being linked
| |
| -- arg2: parameter name that holds the classes
| |
| -- THIS FUNCTION SHOULD BE RUN AFTER :cleanParams()
| |
| -- THIS FUNCTION SHOULD BE RUN BEFORE :finish()
| |
| -- The second argument's data should always contain a value (a CSS class name) at every index
| |
| -- This function is cancelled for non switch boxes
| |
| --]]
| |
| function Infobox:linkParams(...)
| |
| if not self.switchfo then
| |
| return
| |
| end
| |
| for _, v in ipairs(...) do
| |
| self.switchfoattr[v[1]] = self.rargs[v[2]]
| |
| end
| |
| end
| |
| | |
| --[==========================================[
| |
| -- Functions for accessing parameters easily
| |
| --]==========================================]
| |
| --[[
| |
| Access the param
| |
| -- arg : param name
| |
| -- retp : return type
| |
| d | #default : self.rargs[arg].d -- Default value
| |
| f | full : self.rargs[arg] -- Entire table
| |
| s | switches : self.rargs[arg].switches -- Entire switch table
| |
| s# : self.rargs[arg].switches[#] -- Single switch value at index #
| |
| r : switches[1] or d
| |
| --]]
| |
| function Infobox:param(arg, retp)
| |
| -- All parameters
| |
| if arg == 'all' then
| |
| return self.rargs
| |
| end
| |
| -- case-insensitive flagging
| |
| retp = tostring(retp):lower()
| |
| local fmap = {
| |
| d = 'd', default = 'd', s0 = 'd', -- let s-naught count as default (since that's what it is)
| |
| f = 'f', full = 'f',
| |
| s = 's', switch = 's', switches = 's',
| |
| r = 'r'
| |
| }
| |
| local ret_func
| |
| -- quickly see if the parameter is a value greater than 0
| |
| if retp:match('s[1-9]') then
| |
| ret_func = 's2'
| |
| else
| |
| -- Otherwise map it to the correct flag, or the default
| |
| ret_func = fmap[retp] or fmap.d
| |
| end
| |
| | |
| -- Fetch parameter
| |
| local param = self.rargs[arg]
| |
| -- Return nil if no table found
| |
| if not param then return nil end
| |
| | |
| -- Return default
| |
| if ret_func == 'd' then
| |
| return param.d
| |
| end
| |
| | |
| -- Return full table
| |
| if ret_func == 'f' then
| |
| return param
| |
| end
| |
| | |
| -- Return switch table
| |
| if ret_func == 's' then
| |
| return param.switches
| |
| end
| |
| | |
| -- Return the first switch, otherwise the default
| |
| if ret_func == 'r' then
| |
| if not param.switches then
| |
| return param.d
| |
| elseif param.switches[1] == nil_param then
| |
| return param.d
| |
| else
| |
| return param.switches[1]
| |
| end
| |
| end
| |
| | |
| -- If s2, reread the param
| |
| if ret_func == 's2' then
| |
| -- no switches
| |
| if not param.switches then
| |
| return nil
| |
| end
| |
| -- Parse index by removing the s
| |
| local index = retp:match('s(%d+)')
| |
| -- nil_param
| |
| if param.switches[index] == nil_param then
| |
| return nil
| |
| else
| |
| return param.switches[index]
| |
| end
| |
| end
| |
| end
| |
| | |
| --[[
| |
| Checks if a parameter is defined and not blank
| |
| -- arg : parameter to look at
| |
| -- index : index of switches to look at (defaults to default param)
| |
| -- defining 'all' will look at every possible value for the parameter
| |
| --]]
| |
| function Infobox:paramDefined(arg,index)
| |
| -- Can use cleaned params for switches
| |
| -- but need the passed to identify blanks in the template
| |
| local param = self.rargs[arg]
| |
|
| |
| if not param then
| |
| error("No param specified.")
| |
| end
| |
|
| |
| local _arg = self.args[arg]
| |
| if string.find(_arg or '','%?action=edit') then
| |
| _arg = ''
| |
| end
| |
| index = index or 0
| |
| local ret
| |
| -- create a long strong of every value to test for things if 'all'
| |
| if string.lower(index) == 'all' then
| |
| return self.catdata[arg] and (self.catdata[arg].one_defined or self.catdata[arg].all_defined)
| |
| -- index to number otherwise
| |
| else
| |
| index = tonumber(index) or 0
| |
| if index == 0 then
| |
| if param.switches then
| |
| if Infobox.isDefined(param.switches[1]) then
| |
| ret = param.switches[1]
| |
| else
| |
| ret = _arg
| |
| end
| |
| else
| |
| ret = _arg
| |
| end
| |
| else
| |
| if not param.switches then
| |
| return nil
| |
| end
| |
| if param.switches[index] == nil_param then
| |
| return nil
| |
| end
| |
| ret = param.switches[index]
| |
| end
| |
| end
| |
| return tostring(ret or ''):find('%S')
| |
| end
| |
| | |
| --[[
| |
| Function to perform a search on all parameters of a defined name
| |
| -- param: param name
| |
| -- val: a value or function
| |
| -- functions passed must return either true or false
| |
| -- with true being counted as a match
| |
| --]]
| |
| function Infobox:paramGrep(param,val)
| |
| local arg = self.rargs[param]
| |
| -- if no parameters, return nil
| |
| if not arg then
| |
| return nil
| |
| end
| |
| | |
| local ret
| |
| local valtype = type(val)
| |
| -- start with the default value
| |
| -- if it's a function, run it
| |
| if valtype == 'function' then
| |
| ret = val(arg.d)
| |
| | |
| -- true means it matched
| |
| if ret == true then
| |
| return ret
| |
| end
| |
| | |
| -- switches up here for functions
| |
| if arg.switches then
| |
| for _, v in ipairs(arg.switches) do
| |
| ret = val(v)
| |
| if ret == true then
| |
| return true
| |
| end
| |
| end
| |
| end
| |
| | |
| -- if it's just a value, compare the two
| |
| -- only run if types match to avoid errors
| |
| -- compare switches later
| |
| elseif valtype == type(arg.d) then
| |
| -- if a string, make case insensitive
| |
| if valtype == 'string' then
| |
| if string.lower(val) == string.lower(arg.d) then
| |
| return true
| |
| end
| |
| -- everything else just test directly
| |
| elseif val == arg.d then
| |
| return true
| |
| end
| |
| end
| |
| | |
| -- switch cases
| |
| -- more organized putting them here
| |
| if arg.switches then
| |
| for _, v in ipairs(arg.switches) do
| |
| if valtype == type(v) then
| |
| if valtype == 'string' then
| |
| if val:lower() == v:lower() then
| |
| return true
| |
| end
| |
| elseif val == v then
| |
| return true
| |
| end
| |
| end
| |
| end
| |
| end
| |
| | |
| -- return false in every other case
| |
| return false
| |
| end
| |
| ------
| |
| | |
| function Infobox.paramRead(arg,val)
| |
| -- if no parameters, return nil
| |
| if not arg then
| |
| return nil
| |
| end
| |
| | |
| local ret
| |
| local valtype = type(val)
| |
| -- start with the default value
| |
| -- if it's a function, run it
| |
| if valtype == 'function' then
| |
| ret = val(arg.d)
| |
| | |
| -- true means it matched
| |
| if ret == true then
| |
| return ret
| |
| end
| |
| | |
| -- switches up here for functions
| |
| if arg.switches then
| |
| for _, v in ipairs(arg.switches) do
| |
| ret = val(v)
| |
| if ret == true then
| |
| return true
| |
| end
| |
| end
| |
| end
| |
| | |
| -- if it's just a value, compare the two
| |
| -- only run if types match to avoid errors
| |
| -- compare switches later
| |
| elseif valtype == type(arg.d) then
| |
| -- if a string, make case insensitive
| |
| if valtype == 'string' then
| |
| if string.lower(val) == string.lower(arg.d) then
| |
| return true
| |
| end
| |
| -- everything else just test directly
| |
| elseif val == arg.d then
| |
| return true
| |
| end
| |
| end
| |
| | |
| -- switch cases
| |
| -- more organized putting them here
| |
| if arg.switches then
| |
| for _, v in ipairs(arg.switches) do
| |
| if valtype == type(v) then
| |
| if valtype == 'string' then
| |
| if val:lower() == v:lower() then
| |
| return true
| |
| end
| |
| elseif val == v then
| |
| return true
| |
| end
| |
| end
| |
| end
| |
| end
| |
| | |
| -- return false in every other case
| |
| return false
| |
| end
| |
| | |
| ----
| |
| | |
| -- Return collected category data
| |
| function Infobox:categoryData()
| |
| return self.catdata
| |
| end
| |
| | |
| -- Infobox:addDropLevelVars("thieving", "skilllvl1")
| |
| function Infobox:addDropLevelVars(key, paramName)
| |
| local levelParams = self:param(paramName, 'f')
| |
| local dropParams = self:param('dropversion', 'f')
| |
| if levelParams == nil then
| |
| return
| |
| end
| |
| if dropParams == nil or not self:paramDefined("dropversion", "all") then
| |
| dropParams = {d = 'DEFAULT'}
| |
| end
| |
| if dropParams.switches == nil then
| |
| dropParams.switches = {}
| |
| end
| |
| local levels = levelParams.switches or {levelParams.d}
| |
| local dropVersions = {}
| |
| for i=1,#levels do
| |
| local dropVersionFromInfobox = dropParams.switches[i] or dropParams.d
| |
| if dropVersionFromInfobox == nil_param then
| |
| dropVersionFromInfobox = 'DEFAULT'
| |
| end
| |
| for _, dropVersion in ipairs(mw.text.split(dropVersionFromInfobox, ',')) do
| |
| if dropVersions[dropVersion] == nil then
| |
| dropVersions[dropVersion] = {}
| |
| end
| |
| dropVersions[dropVersion][levels[i]] = true
| |
| end
| |
| end
| |
| -- This part is to append levels from previous Infobox invocations
| |
| for dropVersion, dropLevels in pairs(dropVersions) do
| |
| -- set dummy property on versioned SMW subobject, otherwise it can't be part of an #ask
| |
| mw.smw.subobject({["Dummy property"] = true}, dropVersion)
| |
| -- example variable: DropLevel_combat_High_level
| |
| local var_name = string.format("DropLevel_%s_%s", key, dropVersion)
| |
| local previousVar = var.var(var_name)
| |
| if previousVar ~= "" then
| |
| for i, v in ipairs(mw.text.split(previousVar, ',')) do
| |
| dropVersions[dropVersion][v] = true
| |
| end
| |
| end
| |
| local ordered = {}
| |
| for k, v in pairs(dropVersions[dropVersion]) do
| |
| local n = tonumber(k)
| |
| if n ~= nil then
| |
| table.insert(ordered, n)
| |
| end
| |
| end
| |
| table.sort(ordered)
| |
| var.vardefine(var_name, table.concat(ordered, ','))
| |
| end
| |
| end
| |
| | |
| -- Override tostring
| |
| function Infobox.tostring(box)
| |
| -- If not finished, finish
| |
| if not box.__finished then
| |
| box:finish()
| |
| end
| |
| | |
| -- Make entire html wrapper a string and return it
| |
| local btns = box.switch_buttons_tag
| |
| if box.custom_buttons then
| |
| btns = ''
| |
| end
| |
| if box.args.__dump__ then
| |
| return '<' .. 'pre>'..mw.dumpObject(box) .. '</' .. 'pre>[[Category:Dumping infoboxes]]'
| |
| end
| |
| return tostring(btns) .. tostring(box.rtable) .. table.concat(box.appendStrs, '') .. tostring(box.switch_tag) .. tostring(box.smw_error_tag)
| |
| end
| |
| | |
| return Infobox
| |
| -- </nowiki>
| |