FishTank's Tank Wikia
Advertisement

Documentation for this module may be created at Module:ComicsInfobox/doc

-- Start Module skeleton. Everything builds off this.
local Infobox = {}

----------------------------
-- Libraries of functions --
----------------------------

-- stands for High Frequency
local HF = require("Module:ComicsHF")
-- Parses invocation parameters, trims whitespace, and removes blanks
local getArgs = require('Dev:Arguments').getArgs
-- Functions for making Wikitext lists
local L = require("Dev:List")

-- Since this should only be evaluated once per pageview, it's now global
_G.vars = { Pagename = mw.title.getCurrentTitle().text }

---------------------
-- Local functions --
---------------------
local function invokeInt(funcName)
  -- This wrapper allows invocation from articles and templates
  -- of internal Lua functions.
	return function (frame)
		local args = getArgs(frame, { trim = true, removeBlanks = true })
		return Infobox[funcName](args, vars)
	end
end

----------------------
-- Public functions --
----------------------

function Infobox.CategoriesFromKeywords( fieldValue, valid, exceptions, vars )
  local output = ""
  -- Field isn't blank
  if fieldValue ~= nil then
    -- Grab a valid pair and use it
    for validKey, validValue in pairs(valid) do
        -- If you find the validKey in the field, look more closely
        if string.find( string.lower(fieldValue), validKey ) ~= nil then
            -- Check if there are exceptions for the validKey
            if type(exceptions[validKey]) ~= "table" then
                -- There are no exceptions
                -- Just categorize using this validKey 
                -- and move to the next validKey
                for valueKey, valueCategoryName in ipairs( validValue ) do
                    output = output .. HF.CategoryLink(
                        valueCategoryName,
                        vars.Pagename,
                        ""
                    )
                end
            end
        end
    end
  end
  return output
end

-- Calls _sanitizeInput from a Template
function Infobox.sanitize(frame)
		local args = getArgs(frame, { trim = true, removeBlanks = true })
		return Infobox._sanitizeInput(args[1])
end

-- Cleans up sloppy inputs into something more useful
-- This reduces the need to run a bot and get users to change habits
function Infobox._sanitizeInput( input )
    -- set "output" from "input", and manipulate "output"
    local output = input
    
    -- No more line breaks
    output = string.gsub( output, '([,;])<br>%s*.', '%1 ' )
    -- Where there's just a line break and no delimiter, there should be a delimiter.
    output = string.gsub( output, '<br>%s*.', '; ' )
    -- Put references where they belong (before a delimiter)
    output = string.gsub( output, '([,;])(["]?){{([rR])|([^}]*)}} ', '%2{{%3|%4}}%1 ' )
    return output
end

function Infobox._cloakCommas( input )
    local output = input
    -- temporarily change those interior commas to obscure symbol '§'
    output = string.gsub( output, 
        '%(([^,)]*),([^,)]*)%)',
        '(%1§%2)'
    )
    -- Do the same thing for Templates
    output = string.gsub( output,
        '{{([%w%s]*)|([^}]*),([^}]*)}}',
        '{{%1|%2§%3}}' )
    -- Do the same for Links and Categories
--        itemstring = string.gsub( itemstring, 
--            '%[%[([^,)]*),([^,)]*)|[([^,)]*),([^,)]*)%]%]',
--            '[[%1§%2|%3§%4]]'
--        )
    return output
end

-- Calls _hlist from a Template
Infobox.hlist = invokeInt('_hlist')

-- Internal function for creating horizontal lists
function Infobox._hlist( args )
    -- ** Determine values for the function ** --
    -- Delimiter is the separator between items. Defaults to {{{1|;}}} 
    local delimiter  = args['delimiter'] or args[1] or ';'
    -- The actual plaintext string to be changed into a list.
    -- If there's no {{{2}}}, then it's the only unnamed argument.
    local itemstring = args['value'] or args[2] or args[1] or nil
    if not args[2] then delimiter = args['delimiter'] or args[1] or ';' end
    
    itemstring = Infobox._sanitizeInput( itemstring )
    
    -- Optional length based trimming. 
    local trim       = args['trim'] or args[3] or false
    
    if delimiter == ',' and 
     ( string.match( itemstring, '%(([^,)]*),([^,)]*)%)') or
     string.match( itemstring, '{{([%w%s]*)|([^}]*),([^}]*)}}')
     )
     -- If items are separated by commas and
     -- there are commas inside parenthesis
     -- Like "Stark Tower (New York City, New York), "
     then
         itemstring = Infobox._cloakCommas( itemstring )
    end
    
    if mw.ustring.match(itemstring, ';' ) and 
     not mw.ustring.match(itemstring, '(.*);(.*);' ) and
     delimiter == ',' 
     -- if there's just ONE semicolon and delimiter is ','
     -- then no matter what, whatever is before the semicolon is in "front"
     then
        local primary   = mw.ustring.match(itemstring, '(.*);' )
        local secondary = mw.ustring.match(itemstring, ';(.*)' )
        
        -- Separate the individual items by delimiter 
        -- and put them in a table (or array)
        local items1      = HF.explode( delimiter, primary )
        local items2      = HF.explode( delimiter, secondary )

        -- Take the items in the back tables 
        -- and reproduce them as horizontal, bulleted lists
        local list1       = L.makeList( 'horizontal', items1 )
        local list2       = L.makeList( 'horizontal', items2 )
        
        -- Create the content wrapper for the back
        local morebox = mw.html.create('div')
            :addClass('expansion-tag')
            :addClass('mw-collapsible')
            :addClass('mw-collapsed')
            :attr('data-expandtext', morelabel)
            :attr('data-collapsetext', lesslabel)
            :wikitext(list2):allDone()
        -- Output everything
        -- If we changed the symbols before, we'll change them back now
        return mw.ustring.gsub( list1 .. tostring(morebox), '§', ',' )
    elseif type(trim)   == 'number' and
     mw.ustring.len( itemstring ) > trim 
     -- If there's a value for trim
     -- and the input is longer than the threshold given
     then
        -- break the initial string into the pre-threshold (front)
        -- and post-threshold (back) strings
        local primary   = string.sub( input, 1, trim )
        local secondary = string.sub( input, trim )
        local shiftatbreak = ''
        -- Make a natural break at the delimiter before the threshold
        -- and move the remainder to the back string
        primary, shiftatbreak = mw.ustring.match(
            primary,
            '(.*)'..delimiter..'(.*)$'
        )
        secondary = shiftatbreak .. secondary
        
        -- Separate the individual items by delimiter 
        -- and put them in a table (or array)
        local items1      = HF.explode( delimiter, primary )
        local items2      = HF.explode( delimiter, secondary )
        
        -- If we changed the symbols before, we'll change them back now
        for i, v in ipairs( items1 ) do
            v = mw.ustring.gsub( v, '§', ',' )
        end
        for i, v in ipairs( items2 ) do
            v = mw.string.gsub( v, '§', ',' )
        end

        -- Take the items in the front and back tables 
        -- and reproduce them as horizontal, bulleted lists
        local list1       = L.makeList( 'horizontal', items1 )
        local list2       = L.makeList( 'horizontal', items2 )
        
        -- Create the HTML content wrapper for the back
        local morebox = mw.html.create('div')
            :addClass('expansion-tag')
            :addClass('mw-collapsible')
            :addClass('mw-collapsed')
            :attr('data-expandtext', morelabel)
            :attr('data-collapsetext', lesslabel)
            :wikitext(list2):allDone()
        -- Output everything
        -- If we changed the symbols before, we'll change them back now
        return string.gsub( list1 .. tostring(morebox), '§', ',' )
     else
        -- If there's no trim, or it's all under the threshold
        -- Separate the individual items by delimiter 
        -- and put them in a table (or array)
        local items      = HF.explode( delimiter, itemstring )
        
        -- Take the items in the table 
        -- and reproduce them as a horizontal, bulleted list
        local list       = L.makeList( 'horizontal', items )
        
        -- Output the list
        -- If we changed the symbols before, we'll change them back now
        return string.gsub( list, '§', ',' )
    end
end

-- Return the Module skeleton.
return Infobox
Advertisement