Module:Skill link: Difference between revisions
		
		
		
		Jump to navigation
		Jump to search
		
>OmegaK2  (Created page with "-- -- Module for skill linking --  local m_util = require('Module:Util') local getArgs = require('Module:Arguments').getArgs  local p = {}  -- --------------------------------...")  | 
				 (Bug fix; no globals -> strict)  | 
				||
| (26 intermediate revisions by 6 users not shown) | |||
| Line 1: | Line 1: | ||
--  | -------------------------------------------------------------------------------  | ||
-- Module   | --    | ||
--  | --                              Module:Skill link  | ||
--   | |||
-- This module implements [[Template:Skill link]] and   | |||
-- [[Template:Query skill infobox]]  | |||
-------------------------------------------------------------------------------  | |||
require('strict')  | |||
local m_util = require('Module:Util')  | local m_util = require('Module:Util')  | ||
local   | -- Should we use the sandbox version of our submodules?  | ||
local use_sandbox = m_util.misc.maybe_sandbox('Skill link')  | |||
local m_cargo = use_sandbox and require('Module:Cargo/sandbox') or require('Module:Cargo')  | |||
-- The cfg table contains all localisable strings and configuration, to make it  | |||
-- easier to port this module to another wiki.  | |||
local cfg = use_sandbox and mw.loadData('Module:Skill link/config/sandbox') or mw.loadData('Module:Skill link/config')  | |||
local i18n = cfg.i18n  | |||
-- ----------------------------------------------------------------------------  | -- ----------------------------------------------------------------------------  | ||
--   | -- Helper functions   | ||
-- ----------------------------------------------------------------------------  | -- ----------------------------------------------------------------------------  | ||
local   | local h = {}  | ||
}  | |||
function h.disambiguate_skill(results)  | |||
    --[[  | |||
        Disambiguates results from a skill query.  | |||
    ]]  | |||
    local str = {}  | |||
    for _, v in pairs(results) do  | |||
        str[#str+1] = string.format(  | |||
            '%s - %s ([[%s|page]])',  | |||
            v['skill.skill_id'] or v['skill._pageName'] or '',  | |||
            string.gsub(  | |||
                v['skill.stat_text'] or 'N/A',  | |||
                '<br>',  | |||
                ', '  | |||
            ) or '',  | |||
            v['skill._pageName'] or ''  | |||
        )  | |||
    end  | |||
    return table.concat(str, '<br>')  | |||
end  | |||
function h.format_skill_icon(skill, tpl_args)  | |||
    --[[  | |||
        Add a skill image.  | |||
    ]]  | |||
    if tpl_args.icon ~= nil then  | |||
        if m_util.cast.boolean(tpl_args.icon) == false then  | |||
            return nil  | |||
        end  | |||
        skill['skill.skill_icon'] = tpl_args.icon  | |||
    end  | |||
    if skill['skill.skill_icon'] == nil then  | |||
        return nil  | |||
    end  | |||
    local out  | |||
    if tpl_args.large then  | |||
        out = string.format(  | |||
            '[[%s|link=%s]]',  | |||
            skill['skill.skill_icon'],  | |||
            tpl_args.main_page  | |||
        )  | |||
    else  | |||
        -- Inline size  | |||
        out = string.format(  | |||
            '[[%s|14px|link=%s]]',  | |||
            skill['skill.skill_icon'],  | |||
            tpl_args.main_page  | |||
        )  | |||
    end  | |||
    return out  | |||
end  | |||
-- ----------------------------------------------------------------------------  | -- ----------------------------------------------------------------------------  | ||
--   | -- Main functions  | ||
-- ----------------------------------------------------------------------------  | -- ----------------------------------------------------------------------------  | ||
local function _query_skill_infobox(tpl_args)  | |||
--   |     --[[  | ||
    Finds and shows the infobox of a skill.  | |||
    Examples:  | |||
    = p.skill_infobox_link{id="IcestormUniqueStaff12"}  | |||
    = p.skill_infobox_link{"Icestorm"}  | |||
    = p.skill_infobox_link{q_where = 'skill.active_skill_name="Icestorm"'}  | |||
    ]]  | |||
    if tpl_args.id and (tpl_args.q_where == nil) then  | |||
        tpl_args.q_where = string.format(  | |||
            'skill.skill_id = "%s"',  | |||
            tpl_args.id  | |||
         )  | |||
     elseif tpl_args[1] and (tpl_args.q_where == nil) then  | |||
        tpl_args.q_where = string.format(  | |||
            [[  | |||
         error(  |                 skill.skill_id = "%s"  | ||
                OR skill.active_skill_name LIKE "%%%s%%"  | |||
                OR skill.stat_text LIKE "%%%s%%"  | |||
            ]],  | |||
            tpl_args[1],  | |||
            tpl_args[1],  | |||
            tpl_args[1]  | |||
        )  | |||
     elseif (tpl_args.id == nil) and (tpl_args.q_where == nil) then  | |||
         error(i18n.errors.missing_id_parameter)  | |||
     end  |      end  | ||
     local results =   |      local results = m_cargo.query(  | ||
         {'skill'},  |          {'skill'},  | ||
         {  |          {  | ||
             'skill.html',  | |||
            'skill.skill_screenshot',  | |||
            'skill.active_skill_name',  | |||
            'skill.skill_id',  | |||
            'skill.stat_text',  | |||
            'skill._pageName',  | |||
        },  | |||
        {  | |||
             where=tpl_args.q_where,  | |||
         }  |          }  | ||
     )  |      )  | ||
     results = results[1]  | |||
     -- Helpful error handling:  | |||
    local err_tbl = {  | |||
        {  | |||
            bool = function()  | |||
                return #results == 0  | |||
            end,  | |||
            display = function()  | |||
                return i18n.errors.no_results  | |||
            end,  | |||
        },  | |||
        {  | |||
            bool = function()  | |||
                return #results > 1  | |||
            end,  | |||
            display = function()  | |||
                return string.format(  | |||
                    i18n.errors.multiple_results,  | |||
                    tpl_args.q_where,  | |||
                    h.disambiguate_skill(results)  | |||
                )  | |||
            end,  | |||
        },  | |||
        {  | |||
            bool = function()  | |||
                return tpl_args.id == nil  | |||
            end,  | |||
            display = function()  | |||
                return string.format(  | |||
                    i18n.errors.missing_id_parameter,  | |||
                    h.disambiguate_skill(results)  | |||
                )  | |||
            end,  | |||
        },  | |||
    }  | |||
    local out = {}  | |||
    local cats = {}  | |||
    for _,v in ipairs(err_tbl) do  | |||
        if v.bool() then  | |||
            cats[#cats+1] = i18n.errors.category  | |||
            out[#out+1] = m_util.html.error({msg = v.display()})  | |||
            break  | |||
        end  | |||
     end  | |||
     local container = mw.html.create('span')  |      local container = mw.html.create('span')  | ||
     container:  |      for _,v in ipairs(results) do  | ||
        container  | |||
            :addClass('skill-box-page-container')  | |||
     return tostring(container)  |             :wikitext(v['skill.html'])  | ||
        if v['skill.skill_screenshot'] then  | |||
            container  | |||
                :wikitext(string.format(  | |||
                    '[[%s]]',  | |||
                    v['skill.skill_screenshot']  | |||
                    )  | |||
                )  | |||
        end  | |||
        -- Store as main page  | |||
        tpl_args.main = tpl_args.main and m_util.cast.boolean(tpl_args.main) or mw.title.getCurrentTitle():inNamespace(0)  | |||
        if tpl_args.main then  | |||
            m_cargo.store(  | |||
                {  | |||
                    _table='main_pages',  | |||
                    data_page = v['skill._pageName'],  | |||
                    id = v['skill.skill_id'],  | |||
                    name = v['skill.active_skill_name'],  | |||
                }  | |||
            )  | |||
            mw.getCurrentFrame():expandTemplate{title = cfg.attach_template}  | |||
        end  | |||
    end  | |||
    return tostring(container) .. table.concat(out, '') .. m_util.misc.add_category(cats)  | |||
end  | |||
local function _skill_link(tpl_args)  | |||
    --[[  | |||
    Links a skill  | |||
    Examples  | |||
    --------  | |||
    = p.skill_link{id="IcestormUniqueStaff12"}  | |||
    = p.skill_link{  | |||
        skip_query=true,  | |||
        page='Skill:IcestormUniqueStaff12',  | |||
        name='test',  | |||
        icon='Icestorm skill icon.png',  | |||
        large=1,  | |||
    }  | |||
    ]]  | |||
    tpl_args.skill_name = tpl_args.skill_name or tpl_args[1]  | |||
    tpl_args.name = tpl_args.name or tpl_args[2]  | |||
    -- Check if the correct parameters have been set:  | |||
    if m_util.table.has_all_value(tpl_args, cfg.selectors) and tpl_args.skip_query == nil then  | |||
        return m_util.html.error{  | |||
            msg=i18n.errors.invalid_args .. m_util.misc.add_category(i18n.errors.broken_skill_links)  | |||
        }  | |||
     end  | |||
    --  | |||
    local skill  | |||
    if m_util.table.has_one_value(tpl_args, cfg.selectors, nil) and tpl_args.skip_query == nil then  | |||
        -- Create q_where depending on the input:  | |||
        if tpl_args.skill_name then  | |||
            tpl_args.q_where = string.format('skill.active_skill_name="%s"', tpl_args.skill_name)  | |||
        elseif tpl_args.id then  | |||
            tpl_args.q_where = string.format('skill.skill_id="%s"', tpl_args.id)  | |||
        elseif tpl_args.q_where then  | |||
            -- Use tpl_args.q_where.  | |||
        else  | |||
            return m_util.html.error{  | |||
                msg=i18n.errors.invalid_args .. m_util.misc.add_category(i18n.errors.broken_skill_links)  | |||
            }  | |||
        end  | |||
        -- Query cargo:  | |||
        local results = m_cargo.query(  | |||
            {'skill', 'main_pages'},  | |||
            {  | |||
                'skill._pageName',  | |||
                'skill._pageNamespace',  | |||
                'skill.skill_id',  | |||
                'skill.stat_text',  | |||
                -- 'skill.main_page',  | |||
                'skill.active_skill_name',  | |||
                'skill.skill_icon',  | |||
                'skill.html',  | |||
                'main_pages._pageName',  | |||
            },  | |||
            {  | |||
                join='skill.skill_id=main_pages.id',  | |||
                where=string.format(  | |||
                    '(%s)',  | |||
                    tpl_args.q_where  | |||
                ),  | |||
                orderBy='skill.stat_text',  | |||
                limit=2,  | |||
            }  | |||
        )  | |||
        -- Check number of results, there should only be one result:  | |||
        if #results > 1 then  | |||
            local found = false  | |||
            for _,v in ipairs(results) do  | |||
                -- if there is only one result in the main namespace, use that  | |||
                if tonumber(v['skill._pageNamespace']) == 0 then  | |||
                    if found then  | |||
                        found = false  | |||
                        break  | |||
                    else  | |||
                        found = true  | |||
                        skill = v  | |||
                    end  | |||
                end  | |||
            end  | |||
            if not found then  | |||
                return m_util.html.error{  | |||
                    msg=string.format(  | |||
                        i18n.errors.multiple_results,  | |||
                        tpl_args.q_where,  | |||
                        h.disambiguate_skill(results) .. m_util.misc.add_category(i18n.errors.broken_skill_links)  | |||
                        )  | |||
                    }  | |||
            end  | |||
        elseif #results < 1 then  | |||
            return m_util.html.error{  | |||
                msg=string.format(  | |||
                    i18n.errors.no_results_found,  | |||
                    tostring(tpl_args.q_where) .. m_util.misc.add_category(i18n.errors.broken_skill_links)  | |||
                )  | |||
            }  | |||
        else  | |||
            skill = results[1]  | |||
        end  | |||
    else  | |||
        skill = {  | |||
            ['skill.main_page']=tpl_args.page or tpl_args.name  | |||
        }  | |||
    end  | |||
    -- Add allowed parameters:  | |||
    for k, prop in pairs(cfg.parameters) do  | |||
        if tpl_args[k] ~= nil then  | |||
            skill[prop] = tpl_args[k]  | |||
        end  | |||
    end  | |||
    -- Set the link to the main page:  | |||
    tpl_args.main_page = skill['skill.main_page']  | |||
                      or skill['main_pages._pageName']  | |||
                      or skill['skill._pageName']  | |||
    -- Format the skill icon:  | |||
    local img = h.format_skill_icon(skill, tpl_args)  | |||
    ---------------------------------------------------------------------------  | |||
    -- Output  | |||
    ---------------------------------------------------------------------------  | |||
     -- Normal inline link:  | |||
     if tpl_args.format == nil then  | |||
        local container = mw.html.create('span')  | |||
        container:addClass('hoverbox c-skill-hoverbox')  | |||
        if tpl_args.large then  | |||
            container:addClass('c-skill-hoverbox--large')  | |||
        end  | |||
        local activator = mw.html.create('span')  | |||
        activator:addClass('hoverbox__activator c-skill-hoverbox__activator')  | |||
        if img and not tpl_args.large then  | |||
            activator:wikitext(img)  | |||
        end  | |||
        activator:wikitext(string.format(  | |||
            '[[%s|%s]]',  | |||
            tpl_args.main_page,  | |||
            tpl_args.name or skill['skill.active_skill_name'] or tpl_args.main_page  | |||
            )  | |||
        )  | |||
        local display = mw.html.create('span')  | |||
        display:addClass('hoverbox__display c-item-hoverbox__display')  | |||
        -- TODO: Disable this until a nice solution for keeping the html table  | |||
        -- inline has been added:  | |||
        if false then -- skill['skill.html'] ~= nil then  | |||
            display:wikitext(skill['skill.html'])  | |||
            if img then  | |||
                display:wikitext(img)  | |||
            end  | |||
        end  | |||
        if img and tpl_args.large then  | |||
            activator:wikitext(img)  | |||
        end  | |||
        container  | |||
            :node(activator)  | |||
            :node(display)  | |||
        return tostring(container)  | |||
    else  | |||
        return m_util.html.error{  | |||
            msg=string.format(  | |||
                i18n.error.invalid_format,  | |||
                tpl_args.format .. m_util.misc.add_category(i18n.errors.broken_skill_links)  | |||
            )  | |||
        }  | |||
    end  | |||
end  | end  | ||
-- ----------------------------------------------------------------------------  | -- ----------------------------------------------------------------------------  | ||
--   | -- Exported functions  | ||
-- ----------------------------------------------------------------------------  | -- ----------------------------------------------------------------------------  | ||
local p = {}  | |||
--   | |||
-- [[Template:Skill link]]  | |||
--   | |||
p.skill_link = m_util.misc.invoker_factory(_skill_link, {  | |||
    wrappers = cfg.wrappers.skill_link,  | |||
})  | |||
--   | |||
-- [[Template:Query skill infobox]]  | |||
--   | |||
p.query_skill_infobox = m_util.misc.invoker_factory(_query_skill_infobox, {  | |||
    wrappers = cfg.wrappers.query_skill_infobox,  | |||
})  | |||
return p  | return p  | ||
Latest revision as of 04:09, 3 November 2025
Module for creating links to skills via cargo.
Implemented templates
- {{Skill link}}
 - {{Query skill infobox}}
 
The above documentation is transcluded from Module:Skill link/doc. 
Editors can experiment in this module's sandbox and testcases pages.
Subpages of this module.
Editors can experiment in this module's sandbox and testcases pages.
Subpages of this module.
-------------------------------------------------------------------------------
-- 
--                              Module:Skill link
-- 
-- This module implements [[Template:Skill link]] and 
-- [[Template:Query skill infobox]]
-------------------------------------------------------------------------------
require('strict')
local m_util = require('Module:Util')
-- Should we use the sandbox version of our submodules?
local use_sandbox = m_util.misc.maybe_sandbox('Skill link')
local m_cargo = use_sandbox and require('Module:Cargo/sandbox') or require('Module:Cargo')
-- The cfg table contains all localisable strings and configuration, to make it
-- easier to port this module to another wiki.
local cfg = use_sandbox and mw.loadData('Module:Skill link/config/sandbox') or mw.loadData('Module:Skill link/config')
local i18n = cfg.i18n
-- ----------------------------------------------------------------------------
-- Helper functions 
-- ----------------------------------------------------------------------------
local h = {}
function h.disambiguate_skill(results)
    --[[
        Disambiguates results from a skill query.
    ]]
    local str = {}
    for _, v in pairs(results) do
        str[#str+1] = string.format(
            '%s - %s ([[%s|page]])',
            v['skill.skill_id'] or v['skill._pageName'] or '',
            string.gsub(
                v['skill.stat_text'] or 'N/A',
                '<br>',
                ', '
            ) or '',
            v['skill._pageName'] or ''
        )
    end
    return table.concat(str, '<br>')
end
function h.format_skill_icon(skill, tpl_args)
    --[[
        Add a skill image.
    ]]
    if tpl_args.icon ~= nil then
        if m_util.cast.boolean(tpl_args.icon) == false then
            return nil
        end
        skill['skill.skill_icon'] = tpl_args.icon
    end
    if skill['skill.skill_icon'] == nil then
        return nil
    end
    local out
    if tpl_args.large then
        out = string.format(
            '[[%s|link=%s]]',
            skill['skill.skill_icon'],
            tpl_args.main_page
        )
    else
        -- Inline size
        out = string.format(
            '[[%s|14px|link=%s]]',
            skill['skill.skill_icon'],
            tpl_args.main_page
        )
    end
    return out
end
-- ----------------------------------------------------------------------------
-- Main functions
-- ----------------------------------------------------------------------------
local function _query_skill_infobox(tpl_args)
    --[[
    Finds and shows the infobox of a skill.
    Examples:
    = p.skill_infobox_link{id="IcestormUniqueStaff12"}
    = p.skill_infobox_link{"Icestorm"}
    = p.skill_infobox_link{q_where = 'skill.active_skill_name="Icestorm"'}
    ]]
    if tpl_args.id and (tpl_args.q_where == nil) then
        tpl_args.q_where = string.format(
            'skill.skill_id = "%s"',
            tpl_args.id
        )
    elseif tpl_args[1] and (tpl_args.q_where == nil) then
        tpl_args.q_where = string.format(
            [[
                skill.skill_id = "%s"
                OR skill.active_skill_name LIKE "%%%s%%"
                OR skill.stat_text LIKE "%%%s%%"
            ]],
            tpl_args[1],
            tpl_args[1],
            tpl_args[1]
        )
    elseif (tpl_args.id == nil) and (tpl_args.q_where == nil) then
        error(i18n.errors.missing_id_parameter)
    end
    local results = m_cargo.query(
        {'skill'},
        {
            'skill.html',
            'skill.skill_screenshot',
            'skill.active_skill_name',
            'skill.skill_id',
            'skill.stat_text',
            'skill._pageName',
        },
        {
            where=tpl_args.q_where,
        }
    )
    -- Helpful error handling:
    local err_tbl = {
        {
            bool = function()
                return #results == 0
            end,
            display = function()
                return i18n.errors.no_results
            end,
        },
        {
            bool = function()
                return #results > 1
            end,
            display = function()
                return string.format(
                    i18n.errors.multiple_results,
                    tpl_args.q_where,
                    h.disambiguate_skill(results)
                )
            end,
        },
        {
            bool = function()
                return tpl_args.id == nil
            end,
            display = function()
                return string.format(
                    i18n.errors.missing_id_parameter,
                    h.disambiguate_skill(results)
                )
            end,
        },
    }
    local out = {}
    local cats = {}
    for _,v in ipairs(err_tbl) do
        if v.bool() then
            cats[#cats+1] = i18n.errors.category
            out[#out+1] = m_util.html.error({msg = v.display()})
            break
        end
    end
    local container = mw.html.create('span')
    for _,v in ipairs(results) do
        container
            :addClass('skill-box-page-container')
            :wikitext(v['skill.html'])
        if v['skill.skill_screenshot'] then
            container
                :wikitext(string.format(
                    '[[%s]]',
                    v['skill.skill_screenshot']
                    )
                )
        end
        -- Store as main page
        tpl_args.main = tpl_args.main and m_util.cast.boolean(tpl_args.main) or mw.title.getCurrentTitle():inNamespace(0)
        if tpl_args.main then
            m_cargo.store(
                {
                    _table='main_pages',
                    data_page = v['skill._pageName'],
                    id = v['skill.skill_id'],
                    name = v['skill.active_skill_name'],
                }
            )
            mw.getCurrentFrame():expandTemplate{title = cfg.attach_template}
        end
    end
    return tostring(container) .. table.concat(out, '') .. m_util.misc.add_category(cats)
end
local function _skill_link(tpl_args)
    --[[
    Links a skill
    Examples
    --------
    = p.skill_link{id="IcestormUniqueStaff12"}
    = p.skill_link{
        skip_query=true,
        page='Skill:IcestormUniqueStaff12',
        name='test',
        icon='Icestorm skill icon.png',
        large=1,
    }
    ]]
    tpl_args.skill_name = tpl_args.skill_name or tpl_args[1]
    tpl_args.name = tpl_args.name or tpl_args[2]
    -- Check if the correct parameters have been set:
    if m_util.table.has_all_value(tpl_args, cfg.selectors) and tpl_args.skip_query == nil then
        return m_util.html.error{
            msg=i18n.errors.invalid_args .. m_util.misc.add_category(i18n.errors.broken_skill_links)
        }
    end
    --
    local skill
    if m_util.table.has_one_value(tpl_args, cfg.selectors, nil) and tpl_args.skip_query == nil then
        -- Create q_where depending on the input:
        if tpl_args.skill_name then
            tpl_args.q_where = string.format('skill.active_skill_name="%s"', tpl_args.skill_name)
        elseif tpl_args.id then
            tpl_args.q_where = string.format('skill.skill_id="%s"', tpl_args.id)
        elseif tpl_args.q_where then
            -- Use tpl_args.q_where.
        else
            return m_util.html.error{
                msg=i18n.errors.invalid_args .. m_util.misc.add_category(i18n.errors.broken_skill_links)
            }
        end
        -- Query cargo:
        local results = m_cargo.query(
            {'skill', 'main_pages'},
            {
                'skill._pageName',
                'skill._pageNamespace',
                'skill.skill_id',
                'skill.stat_text',
                -- 'skill.main_page',
                'skill.active_skill_name',
                'skill.skill_icon',
                'skill.html',
                'main_pages._pageName',
            },
            {
                join='skill.skill_id=main_pages.id',
                where=string.format(
                    '(%s)',
                    tpl_args.q_where
                ),
                orderBy='skill.stat_text',
                limit=2,
            }
        )
        -- Check number of results, there should only be one result:
        if #results > 1 then
            local found = false
            for _,v in ipairs(results) do
                -- if there is only one result in the main namespace, use that
                if tonumber(v['skill._pageNamespace']) == 0 then
                    if found then
                        found = false
                        break
                    else
                        found = true
                        skill = v
                    end
                end
            end
            if not found then
                return m_util.html.error{
                    msg=string.format(
                        i18n.errors.multiple_results,
                        tpl_args.q_where,
                        h.disambiguate_skill(results) .. m_util.misc.add_category(i18n.errors.broken_skill_links)
                        )
                    }
            end
        elseif #results < 1 then
            return m_util.html.error{
                msg=string.format(
                    i18n.errors.no_results_found,
                    tostring(tpl_args.q_where) .. m_util.misc.add_category(i18n.errors.broken_skill_links)
                )
            }
        else
            skill = results[1]
        end
    else
        skill = {
            ['skill.main_page']=tpl_args.page or tpl_args.name
        }
    end
    -- Add allowed parameters:
    for k, prop in pairs(cfg.parameters) do
        if tpl_args[k] ~= nil then
            skill[prop] = tpl_args[k]
        end
    end
    -- Set the link to the main page:
    tpl_args.main_page = skill['skill.main_page']
                      or skill['main_pages._pageName']
                      or skill['skill._pageName']
    -- Format the skill icon:
    local img = h.format_skill_icon(skill, tpl_args)
    ---------------------------------------------------------------------------
    -- Output
    ---------------------------------------------------------------------------
    -- Normal inline link:
    if tpl_args.format == nil then
        local container = mw.html.create('span')
        container:addClass('hoverbox c-skill-hoverbox')
        if tpl_args.large then
            container:addClass('c-skill-hoverbox--large')
        end
        local activator = mw.html.create('span')
        activator:addClass('hoverbox__activator c-skill-hoverbox__activator')
        if img and not tpl_args.large then
            activator:wikitext(img)
        end
        activator:wikitext(string.format(
            '[[%s|%s]]',
            tpl_args.main_page,
            tpl_args.name or skill['skill.active_skill_name'] or tpl_args.main_page
            )
        )
        local display = mw.html.create('span')
        display:addClass('hoverbox__display c-item-hoverbox__display')
        -- TODO: Disable this until a nice solution for keeping the html table
        -- inline has been added:
        if false then -- skill['skill.html'] ~= nil then
            display:wikitext(skill['skill.html'])
            if img then
                display:wikitext(img)
            end
        end
        if img and tpl_args.large then
            activator:wikitext(img)
        end
        container
            :node(activator)
            :node(display)
        return tostring(container)
    else
        return m_util.html.error{
            msg=string.format(
                i18n.error.invalid_format,
                tpl_args.format .. m_util.misc.add_category(i18n.errors.broken_skill_links)
            )
        }
    end
end
-- ----------------------------------------------------------------------------
-- Exported functions
-- ----------------------------------------------------------------------------
local p = {}
-- 
-- [[Template:Skill link]]
-- 
p.skill_link = m_util.misc.invoker_factory(_skill_link, {
    wrappers = cfg.wrappers.skill_link,
})
-- 
-- [[Template:Query skill infobox]]
-- 
p.query_skill_infobox = m_util.misc.invoker_factory(_query_skill_infobox, {
    wrappers = cfg.wrappers.query_skill_infobox,
})
return p