Module:Sandbox/Yestarhumeler/ArgParse
From Fallen London Wiki
Documentation for this module may be created at Module:Sandbox/Yestarhumeler/ArgParse/doc
local m = {}
-- raw wikitext
local function page_contents(page, namespace)
local title = mw.title.new(page, namespace)
return title:getContent()
end
local function strip_whitespaces(s)
local result = '' .. s
while result:sub(1, 1):match('%s') do
result = result:sub(2)
end
while result:sub(-1, -1):match('%s') do
result = result:sub(1, -2)
end
return result
end
-- Iterates over template arguments.
local function template_args(wikitext)
local argc = 0
local pos = 1
return function()
local argname = nil
local argval = ''
local context = {}
-- skip whitespace symbols
while wikitext:sub(pos, pos):match('%s') do
pos = pos + 1
end
if wikitext:sub(pos, pos + 1) == '}}' then
return nil
end
if wikitext:sub(pos, pos) ~= '|' then
-- error
return nil
end
pos = pos + 1
-- parse the entry
local is_potential_name = true
local nowiki = 0
local _
while true do
local skip = false -- there is no continue
if #context == 0 and wikitext:sub(pos, pos + 1) == '}}' then
break
end
if #context == 0 and wikitext:sub(pos, pos) == '|' then
break
end
if not skip and wikitext:sub(pos):find('<%s*nowiki%s*>') == 1 then
table.insert(context, '<nowiki>')
argval = argval + '<nowiki>'
_, pos = wikitext:find('<%s*nowiki%s*>', pos)
pos = pos + 1
nowiki = nowiki + 1
skip = true
end
if nowiki == 0 and not skip and not argname and is_potential_name and #context == 0 and wikitext:sub(pos, pos) == '=' then
argname = argval
argval = ''
pos = pos + 1
skip = true
end
if nowiki == 0 and not skip and wikitext:sub(pos, pos + 1) == '{{' then
table.insert(context, '{{')
argval = argval .. '{{'
pos = pos + 2
is_potential_name = false
skip = true
end
if nowiki == 0 and not skip and wikitext:sub(pos, pos + 1) == '[[' then
table.insert(context, '[[')
argval = argval .. '[['
pos = pos + 2
is_potential_name = false
skip = true
end
if not skip and wikitext:sub(pos):find('</%s*nowiki%s*>') == 1 and context[#context]== '<nowiki>' then
table.remove(context)
argval = argval .. '</nowiki>'
_, pos = wikitext:find('</%s*nowiki%s*>', pos)
pos = pos + 1
nowiki = nowiki - 1
skip = true
end
if nowiki == 0 and not skip and wikitext:sub(pos, pos + 1) == '}}' and context[#context]== '{{' then
table.remove(context)
argval = argval .. '}}'
pos = pos + 2
skip = true
end
if nowiki == 0 and not skip and wikitext:sub(pos, pos + 1) == ']]' and context[#context]== '[[' then
table.remove(context)
argval = argval .. ']]'
pos = pos + 2
skip = true
end
if not skip then
argval = argval .. wikitext:sub(pos, pos)
pos = pos + 1
end
end
argval = strip_whitespaces(argval)
if argname then
argname = strip_whitespaces(argname)
return argname, argval
else
argc = argc + 1
return '' .. argc, argval
end
end
end
--[[
{{#invoke:ArgParse|value|page|template|parameter|<default=>}}
Finds the first occurrence of template `template` in `page`;
returns the value set to `parameter` (unparsed),
or `default`.
]]
function m.value(frame)
local page = frame.args[1]
local template = frame.args[2]
local parameter = frame.args[3]
local default = frame.args[4] or ''
local wikitext = page_contents(page, '')
local template_pat = '[' .. string.upper(template:sub(1, 1)) .. string.lower(template:sub(1, 1)) .. ']' .. template:sub(2)
local _, pos = wikitext:find('{{%s*' .. template_pat .. '%s*[|}]')
if pos == nil then
return default
end
wikitext = wikitext:sub(pos)
for argname, argval in template_args(wikitext) do
if argname == parameter then
return frame:preprocess(argval)
end
end
return default
end
return m