FANDOM


local mw = require "Module:mw-patch"
local __ = require "Module:underscore"
 
local _M = {}
 
-- convert string into format and components, and back again. Deals with nesting
local function escape(content)
    local subexprs = {}
    content = content:gsub('%$', '$:')
    content = content:gsub('%b{}', function(m)
        subexprs[#subexprs+1] = m
        return ("$%s:"):format(#subexprs)
    end)
    content = content:gsub('%b[]', function(m)
        subexprs[#subexprs+1] = m
        return ("$%s:"):format(#subexprs)
    end)
 
    return content, subexprs
end
local function unescape(content, subexprs)
    if not content then mw.log(debug.traceback()) return "nop" end
 
    -- parens needed here to truncate tuple
    return (content:gsub('%$(.-):', function(m)
        if m == '' then return '$' end
        local i = tonumber(m)
        return subexprs[i]
    end))
end
 
local function parseTemplate(content)
    local subexprs
    content, subexprs = escape(content)
 
    -- separate name and args
    local parts = mw.text.split(content, '|')
    local res = {
        name = mw.text.trim(unescape(table.remove(parts, 1), subexprs)),
        args = {},
        expand = _M.expand
    }
 
    local i = 1
    __.each(parts, function(p)
        local eqPos = p:find('=')
        if eqPos then
            -- named args
            local name = p:sub(1, eqPos-1)
            local value = p:sub(eqPos+1, #p)
            res.args[mw.text.trim(unescape(name, subexprs))] = unescape(value, subexprs)
        else
            -- positional args
            res.args[i] = unescape(p, subexprs)
            i = i + 1
        end
    end)
 
    return res
end
 
function _M.iter(content)
    at = 1
    return function()
        while true do
            -- find matching braces
            ts, te = content:find('%b{}', at)
            if not ts then break end
 
            -- advance the scanner
            at = te
 
            -- verify it's a template
            local isTemplate = content:sub(ts, ts+1) == '{{' and content:sub(te-1, te) == '}}'
            if isTemplate then
                return parseTemplate(content:sub(ts+2, te-2))
            end
        end
    end
end
 
function _M.byName(content, name)
    local matches = __.filter(_M.iter(content), function(t) return t.name == name end)
    if #matches > 1 then
        error(("Found multiple matches: %d"):format(#matches))
    else        
        return matches[1]
    end
end
 
function _M.parseArg(content, argName)
    local first =  _M.iter(content)()
    return first.args[argName]
end
 
function _M.expand(t, frame)
    frame = frame or mw.getCurrentFrame()
    local res = {
        name = frame:preprocess(t.name),
        args = {}
    }
    for k, v in pairs(t.args) do
        res.args[frame:preprocess(k)]=frame:preprocess(v)
    end
    return res
end
 
return _M

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.