|
|
Line 1: |
Line 1: |
| --[=[
| |
| -- For documentation, see [[Module:Infobox/doc]]
| |
| --]=]
| |
|
| |
|
| -- <nowiki>
| |
| local Infobox = {}
| |
| Infobox.__index = Infobox
| |
| Infobox.__tostring = Infobox.tostring
| |
|
| |
| -- Edit button for unknown params
| |
| local editbutton = require('Module:Edit button')
| |
| local var = mw.ext.VariablesLua
| |
| local edit = editbutton("'''?''' (edit)")
| |
|
| |
| -- Page title
| |
| local pagename = mw.title.getCurrentTitle().fullText
| |
|
| |
| -- map of flags to html tags used by Infobox.addRow()
| |
| -- let's only define it once, since :addRow() is used multiple times per module
| |
| local tagmap = {
| |
| tr = 'tr',
| |
| th = 'th',
| |
| td = 'td',
| |
| argh = 'th',
| |
| argd = 'td'
| |
| }
| |
|
| |
| --[=[
| |
| -- Standardised functions
| |
| -- called as string with defineParams
| |
| --]=]
| |
|
| |
| -- Standardised "has content" function
| |
| function hasContent(arg, default)
| |
| -- Return arg if any non-whitespace character is found
| |
| return string.match(arg or '','%S') and arg or default
| |
| end
| |
|
| |
|
| |
| -- Standardised "name" function
| |
| function subjectName(arg)
| |
| return string.match(arg or '','%S') and arg or nil
| |
| end
| |
|
| |
| -- Create a standardised 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
| |
|
| |
| -- Standardised image function
| |
| function image(img)
| |
| if img and img:find('%S') then
| |
| return img
| |
| else
| |
| return nil
| |
| end
| |
| end
| |
|
| |
| -- Standardised numbers
| |
| function numbers(num)
| |
| num = string.gsub(num or '',',','')
| |
| return tonumber(num)
| |
| end
| |
|
| |
| -- Wrap content with line breaks if it contains list-like wiki syntax
| |
| function wrapContent(content)
| |
| if type(content) == "string" then
| |
| local firstListItem = math.min(content:find('^[*#]') or math.huge, content:find('\n[*#]') or math.huge)
| |
| if firstListItem ~= math.huge then
| |
| local suffix = content:find('\n[*#][^\n]+$') and '\n' or ''
| |
| content = content:sub(1, firstListItem - 1) .. '\n' .. content:sub(firstListItem) .. suffix
| |
| end
| |
| end
| |
|
| |
| return content
| |
| 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 initialised 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 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
| |
|
| |
| local best = {-1, 100000}
| |
| if (numlines > 1) and (numlines <= MAX_LINES) then
| |
| -- attempt to balance line widths
| |
| local w_s, w_e = 0,total_width
| |
| for i = 1,#buttons-1 do
| |
| w_s = w_s + buttons[i][2]
| |
| w_e = w_e - buttons[i][2]
| |
| if w_s > LINE_WIDTH then
| |
| -- w_s only increases, so we're done once it exceeds the width
| |
| break
| |
| end
| |
| if w_e <= LINE_WIDTH then
| |
| -- w_e only decreases, so just continue if it exceeds line
| |
| local diff = math.abs(w_s - w_e)
| |
| if diff < best[2] then
| |
| best = { i, diff }
| |
| end
| |
| end
| |
| end
| |
| if best[1] == -1 then
| |
| best = { math.floor(#buttons/2), 100000 }
| |
| end
| |
| end
| |
| for i,v in ipairs(buttons) do
| |
| self.switch_buttons_tag:node(v[1])
| |
| if i == best[1] then
| |
| self.switch_buttons_tag:tag('span'):addClass('line-break')
| |
| 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('infobox')
| |
| end
| |
| -- Add necessary class if switch infobox
| |
| if self.switchfo then
| |
| self.rtable:addClass('infobox-switch')
| |
| end
| |
|
| |
| end
| |
|
| |
| -- Defines an infobox name ({{Template:arg}})
| |
| -- Used to create a link at the bottom of pages
| |
| function Infobox:defineName(arg)
| |
| self.infoboxname = arg
| |
| end
| |
|
| |
| -- Defines the bottom links of the infobox
| |
| -- pass a table whose elements are tables that define a link and a label
| |
| -- {
| |
| -- { 'link', 'label },
| |
| -- ...
| |
| -- }
| |
| -- The template name can be substituted into the tables using '%s'
| |
| -- If we wanted Template:InFooBar to link to it's /doc page with a "doc" label:
| |
| -- { ...
| |
| -- { 'Template:%s/doc', 'doc' },
| |
| -- ... }
| |
| -- 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
| |
|
| |
| -- Change max number of buttons before switching to menu
| |
| -- defaults to 5
| |
| -- MUST BE RUN BEFORE :create()
| |
| function Infobox:setMaxButtons(arg)
| |
| -- if not a number, just go back to default
| |
| self.maxbuttons = tonumber(arg) or DEFAULT_MAX_BUTTONS
| |
| end
| |
|
| |
| --[[
| |
| Add parameters functions
| |
| 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
| |
| -- if a table, add every value
| |
| -- mw.html:addClass() doesn't function with tables
| |
| -- so iterate over the class names here and add them individually
| |
| if v.class then
| |
| 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(wrapContent(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(wrapContent(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
| |
|
| |
| function Infobox.customButtonPlacement(box,arg)
| |
| box.custom_buttons = arg
| |
| return box
| |
| end
| |
|
| |
| -- Choose whether to set [[Property:Default version]]
| |
| -- Defaults to false.
| |
| function Infobox.setDefaultVersionSMW(box, arg)
| |
| box.set_default_version_smw = arg
| |
| return box
| |
| end
| |
|
| |
| function Infobox.addButtonsRow(box, args)
| |
| if box.switchfo then
| |
| box.custom_buttons = true
| |
| local _row = box.rtable:tag('tr')
| |
| :addClass('infobox-switch-buttons-row')
| |
| :tag('td')
| |
| :addClass('infobox-switch-buttons')
| |
| :attr('colspan', args.colspan)
| |
| :node(box.switch_buttons_tag)
| |
| end
| |
| return box
| |
| end
| |
| function Infobox.addButtonsCaption(box)
| |
| if box.switchfo then
| |
| box.custom_buttons = true
| |
| local _row = box.rtable:tag('caption')
| |
| :addClass('infobox-switch-buttons-caption')
| |
| :node(box.switch_buttons_tag)
| |
| end
| |
| return box
| |
| end
| |
|
| |
| --[[
| |
| -- adds a blank row of padding spanning the given number of columns
| |
| --]]
| |
| function Infobox.pad(box, colspan, class)
| |
| local tr = box:tag('tr')
| |
| :tag('td'):attr('colspan', colspan or 1):addClass('infobox-padding')
| |
| :done()
| |
| if class then
| |
| tr:addClass(class)
| |
| end
| |
| tr:done()
| |
| return box
| |
| end
| |
|
| |
| --[[
| |
| -- functions the same as mw.html:wikitext() on the wrapper
| |
| -- Should only be used for categories really
| |
| --]]
| |
| function Infobox.wikitext(box, arg)
| |
| box.rtable:wikitext(arg)
| |
| return box
| |
| end
| |
|
| |
| --[[
| |
| -- Adds the specified item(s) to the end of the infobox, outside of the table
| |
| -- items are concatenated together with an empty space
| |
| --]]
| |
| function Infobox.append(box, ...)
| |
| for i,v in ipairs({...}) do
| |
| table.insert(box.appendStrs, v)
| |
| end
| |
| return box
| |
| end
| |
|
| |
| --[[
| |
| -- Adds a caption to the infobox
| |
| -- defaults to the pagename
| |
| -- or the default argument if defined
| |
| --]]
| |
| 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
| |
|
| |
| -- addClass
| |
| function Infobox.addClass(box, arg)
| |
| box.rtable:addClass(arg)
| |
| return box
| |
| end
| |
|
| |
| -- Much like Infobox.addClass, but adds multiple classes
| |
| function Infobox.addClasses(box, ...)
| |
| for _, v in ipairs(...) do
| |
| box.rtable:addClass(box)
| |
| end
| |
| return box
| |
| end
| |
|
| |
| --[[
| |
| Add tags directly to the infobox table
| |
| Use sparingly
| |
| Returns the tag created rather than the entire box
| |
| Which is an mw.html object
| |
| Further uses of :tag() will be mw.html.tag, rather than Infobox.tag
| |
| As such, Infobox:addRow() cannot be used afterwards without restating the infobox as the object
| |
| --]]
| |
| function Infobox.tag(box, arg)
| |
| return box.rtable:tag(arg)
| |
| end
| |
|
| |
| --[[
| |
| Allows the infobox to use Semantic Media Wiki and give parameters properties
| |
| Pass a table to this function to map parameter names to properties
| |
|
| |
| Calling syntax:
| |
| -- {{#show:page|?property}}:
| |
| -- "<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
| |
| --[[
| |
| As above, but only assigns to "<property>", which will act like "all <property>" - "<property>#" not present
| |
|
| |
| Properties initiated in Infobox:finish()
| |
| --]]
| |
| function Infobox:useSMWOne(arg)
| |
| if type(arg) == 'table' then
| |
| for w, v in pairs(arg) do
| |
| self._smwOne[w] = v
| |
| end
| |
| end
| |
| end
| |
| --[[
| |
| Set up the infobox to set properties in a SMW subobject. This will create a subobject for each version
| |
| - if there is only one version, it will put the properties directly on to the page, like useSMWOne
| |
|
| |
| Properties initiated in Infobox:finish()
| |
| --]]
| |
| function Infobox:useSMWSubobject(arg)
| |
| if type(arg) == 'table' then
| |
| for w, v in pairs(arg) do
| |
| self._smwSubobject[w] = v
| |
| end
| |
| end
| |
| end
| |
|
| |
| function Infobox:useSMWElement(arg)
| |
| if type(arg) == 'table' then
| |
| for w, v in pairs(arg) do
| |
| self._smwElement[w] = v
| |
| end
| |
| self.setSMWElement = true
| |
| end
| |
| end
| |
| --[[
| |
| Finishing function
| |
| -- 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]
| |
| 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 organised 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 organised 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'
| |
| else
| |
| dropVersionFromInfobox = dropVersionFromInfobox .. ",DEFAULT"
| |
| end
| |
| for dropVersion in string.gmatch(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 v in string.gmatch(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>
| |