Final Fantasy Wiki

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

-- <nowiki>
--------------------------------------------------------------------------------
-- This module calls information from releases and series by their Codename.
-- Functions are invoked for use in various templates and for generation of
-- site CSS.
-- See [[Help:Codenames]] for details on how they are used.
--------------------------------------------------------------------------------
local Codename = {}

local getArgs = require('Dev:Arguments').getArgs
local userError = require('Dev:User error')
local printTable = require('Module:Table').tostring
local uoTables = mw.loadData('Module:Codename/data')

local ERROR_CATEGORY = "Pages with invalid Codename invocations"

--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------

-- For a dictionary t and list f, returns t[f[1]][f[2]][f[...]][f[#f]] or nil if
-- any of those intermediate values are missing.
--
-- @example
-- dive({foo = {bar = {baz = 'hi'}}}, {'foo', 'bar', 'baz'}) --> 'hi'
--
-- @TODO
-- Move to [[Module:Table]] or something? It might be useful elsewhere...
local function dive(t, f)
	if not f[1] then return nil end
	
    for _, value in ipairs(f) do
        if type(t) ~= 'table' then
            return nil
        end

        t = t[value]
    end

    return t
end

--------------------------------------------------------------------------------
-- Database queries
--------------------------------------------------------------------------------

Codename.tables = {}
Codename.tables.odr = {}

for key, value in pairs(uoTables) do
    Codename.tables[key] = {}
    Codename.tables.odr[key] = {}

    -- For use in modules
    for index, value2 in ipairs(value) do
        local id = value2.id

        -- Convert a list of tables with ids to a dictionary, where each key is
        -- an id, and each value is its corresponding table.
        --
        -- ex. {{id='a'}, {id='b'}} --> {a={id='a'}, b={id='b'}}
        Codename.tables[key][id] = value2

        -- Convert a list of tables with ids to a list of ids.
        --
        -- ex. {{id='a'}, {id='b'}} --> {'a', 'b'}
        table.insert(Codename.tables.odr[key], id)
    end

    -- For use in wikitext via #invoke
    Codename[key] = function (frame)
        local args = getArgs(frame)
        -- when error-checking, we have to account for the fact that [[Module:Japanese]] will try to call this module
        -- even if it doesn't have anything valid in args[1], and this is not a bug
        -- However, [[Module:Japanese]] only calls this module with args[2] == 'link'
        if not args[1] and not args[2] == 'link' then return
        	userError(
        		"No codename passed to [[Module:Codename]] -- maybe a template argument is missing",
        		ERROR_CATEGORY
        	)
        end
        
        local value = dive(Codename.tables[key], args)

        if type(value) == 'table' then
            return printTable(value)
        end
        
        if not value and not (args[2] == 'pages' or args[2] == 'terms' or args[2] == 'link' or string.find(args[1], '{{{')) then
        	-- Don't throw an error if we try to look up something, with one of these as the second argument, as we might _want_ to not find anything
        	return userError(
        		"Could not find data from [[Module:Codename]]",
        		ERROR_CATEGORY
        	)
        end

        return value
    end
end
--------------------------------------------------------------------------------
-- Generators for lists (for use on [[Help:Codename]], [[Project:Scope]], etc.)
--------------------------------------------------------------------------------

-- Generates an ordered list of media.
-- arg == 'rel' or 'ser'.
-- optional info allows it to display some info from /data.
function Codename._generator(dset, info)
    local list = mw.html.create('ul')
    local data = Codename.tables[dset]
    local odr = Codename.tables.odr[dset]

    local function addItem(node, elem, info)
        if not elem then
            return 'null'
        end

        local addedinfo = ''

        if info then
            addedinfo = ': (' .. elem[info] .. ')'
        end

        return node:tag('li')
            :wikitext('[[' .. elem.link .. "|''" .. elem.title .. "'']]" .. addedinfo)
    end

    for _, parent in ipairs(odr) do
        if not data[parent].sub then
            local item = addItem(list, data[parent], info)
            local sublist

            for _, child in ipairs(odr) do
                if data[child].sub == parent then
                    if not sublist then
                        sublist = item:tag('ul')
                    end

                    addItem(sublist, data[child], info)
                end
            end
        end
    end

    return list
end

function Codename.generator(frame)
    local args = getArgs(frame)

    return Codename._generator(args[1], args[2])
end

-- Generate table of all infobox and navbox theme headers
function Codename.themebgtable()
    local container = mw.html.create('div')
        :css('display', 'flex')
        :css('font-family', '\'Source Code Pro\',monospace')
        :css('text-align', 'center')
    local namedtbls = {
        ser = 'Series',
        rel = 'Releases'
    }

    for _, dset in ipairs{'ser', 'rel'} do
        local odr = Codename.tables.odr[dset]
        local tbl = container:tag('table')
            :addClass('article-table darktext mw-collapsible mw-collapsed')
            :attr('data-expandtext', 'Show ' .. #odr .. ' items')
            :attr('data-collapsetext', 'Hide ' .. #odr .. ' items')
            :css('width', '50%')
            :tag('tr')
                :css('background', '#F5F5F5')
                :css('font-style', 'italic')
                :tag('th')
                    :attr('colspan', '7')
                    :css('text-align', 'left')
                    :wikitext(namedtbls[dset])
                    :done()
                :done()
            :tag('tr')
                :css('background', '#CCC')
                :tag('th')
                    :attr('scope', 'col')
                    :wikitext('Codename')
                    :done()
                :tag('th')
                    :attr('scope', 'col')
                    :wikitext('Header')
                    :done()
                :done()

        for _, cname in ipairs(odr) do
            if Codename.tables[dset][cname]['theme'] then
                tbl:tag('tr')
                    :tag('th')
                        :wikitext(cname .. '<br>' .. '[[' .. Codename.tables[dset][cname].link .. '|' .. Codename.tables[dset][cname].title .. ']]')
                        :done()
                    :tag('td')
                        :wikitext('[[' .. 'File:' .. cname .. ' theme header background.png|100px|' .. cname .. ']]')
                        :done()
                    :done()
            end
        end
    end

    return container
end

return Codename
-- </nowiki>