Module:ComicsInfobox

-- 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, '([,;]) %s*.', '%1 ' ) -- Where there's just a line break and no delimiter, there should be a delimiter. output = string.gsub( output, ' %s*.', '; ' ) -- Put references where they belong (before a delimiter) output = string.gsub( output, '([,;])(["]?){{([rR])|([^}]*)}} ', '%2%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]*)|([^}]*),([^}]*)}}',        '' ) -- Do the same for Links and Categories --       itemstring = string.gsub( itemstring, --            '%[%[([^,)]*),([^,)]*)|[([^,)]*),([^,)]*)%]%]', --            '%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     local delimiter  = args['delimiter'] or args[1] or ';' -- The actual plaintext string to be changed into a list. -- If there's no, 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