Module:templateparser
Appearance
- පහත දැක්වෙන උපදෙස්, Module:templateparser/documentation හි පිහිටා ඇත. Module:templateparser/documentation]]. [සංස්කරණය]
- ප්රයෝජනවත් සබැඳි: උප පිටු ලැයිස්තුව • සබැඳි • transclusions • testcases • sandbox
This module provides functions for parsing and finding template invocations found in wikitext.
parseTemplate(text)
- Parses text as a template invocation and returns a pair of values, the template name and the arguments (containing anonymous, numbered and named arguments). If the text could not be parsed as a template invocation, the function returns nil. The parser will try to correctly parse subtemplates and tables when given as template parameters, but will throw an error if it detects invalid markup.
findTemplates(text)
- Finds all template invocations in the text. This is designed to be used as an iterator in for statements, and returns six or seven values for each invocation:
- The template name.
- The template arguments (as in parseTemplate).
- The the full template invocation as it appears in the original text.
- The index the template appears at within the given text; as with Lua in general, the beginning of the text is index 1.
- subst, safesubst or transclude, depending on whether the template has been substituted, safe substituted or trancluded.
- template, module or parser function, depending on what the template is.
- If a module, the name of the function.
Since the parser is not perfect, it should never be used to audit code.
local export = {}
-- local function strip_whitespace(text)
-- local text, _ = mw.ustring.gsub(text, "%s*(.*)%s*", "%1")
-- return text
-- end
local strip_whitespace = mw.text.trim
local parseTemplateSearchPattern = "(([{|}%[%]=<]).?)"
local parseTemplateSearchPatternNoEq = "(([{|}%[%]<]).?)"
local function invalidSyntax()
error("Invalid syntax detected!")
end
function export.parseTemplate(text)
local text, ok = text:gsub("^{{(.+)}}$", "%1")
if ok == 0 then
return nil
end
local prev = 1
local pos = 1, mend, found, f1
local in_template = 0
local in_table = 0
local in_link = 0
local search = parseTemplateSearchPattern
local has_key = false
local eq_index = 1
local name = nil
local args = {}
local next_i = 1
local function add_param(x, has_key, eq)
if name == nil then
name = strip_whitespace(x)
return
end
if has_key then
local key = strip_whitespace(x:sub(1, eq))
local value = strip_whitespace(x:sub(eq + 2))
local num = tonumber(key, 10)
if num ~= nil and num > 0 then
key = num
end
args[key] = value
else
args[next_i] = x
next_i = next_i + 1
end
end
while true do
pos, mend, found, f1 = text:find(search, pos)
if pos == nil then break end
if found == "{{" then
-- start of subtemplate
in_template = in_template + 1
pos = pos + 2
elseif found == "{|" then
-- start of a table
in_table = in_table + 1
pos = pos + 2
elseif found == "[[" then
-- start of link
in_link = in_link + 1
pos = pos + 2
elseif found == "<n" and text:sub(pos, pos + 7) == "<nowiki>" then
pos = text:find("</nowiki>", pos)
if pos == nil then return nil end
pos = pos + 8
elseif found == "<-" and text:sub(pos, pos + 3) == "<!--" then
pos = text:find("-->", pos + 4)
if pos == nil then return nil end
pos = pos + 3
--elseif found == "}}" and in_template == 0 then
-- invalidSyntax()
elseif in_template == 0 and in_table == 0 and in_link == 0 then
if f1 == "|" then
-- parameter separator
add_param(text:sub(prev, pos - 1), has_key, eq_index - prev)
has_key = false
search = parseTemplateSearchPattern -- allow equals sign again
prev = pos + 1
elseif f1 == "=" and not has_key then
-- parameter key/value separator
eq_index = pos
has_key = true
search = parseTemplateSearchPatternNoEq -- do not allow further equals signs
end
pos = pos + 1
elseif found == "}}" then
-- end of subtemplate
if in_template > 0 then in_template = in_template - 1 end
pos = pos + 2
elseif found == "|}" then
-- end of table
if in_table > 0 then in_table = in_table - 1 end
pos = pos + 2
elseif found == "]]" then
-- end of link
if in_link > 0 then in_link = in_link - 1 end
pos = pos + 2
else
pos = pos + 1
end
end
if in_template ~= 0 or in_table ~= 0 or in_link ~= 0 then
invalidSyntax()
end
add_param(text:sub(prev), has_key, eq_index - prev)
return name, args
end
function export.findTemplates(text)
local next = 1
local function findNextTemplate()
local pos, mend, found
local in_template, in_argument = 0, 0
local temp_start = 1
pos = next
while true do
pos, mend, found = text:find("([{}<][{}n!])", pos)
if pos == nil then break end
if found == "{{" then
if text:sub(pos, pos + 2) == "{{{" then
pos = pos + 3
in_argument = in_argument + 1
else
if in_template == 0 then
temp_start = pos
end
pos = pos + 2
in_template = in_template + 1
end
elseif found == "}}" then
if text:sub(pos, pos + 2) == "}}}" and in_argument > 0 then
in_argument = in_argument - 1
pos = pos + 3
else
if in_template > 0 then
in_template = in_template - 1
if in_template == 0 then
next = pos + 2
local src = text:sub(temp_start, pos + 1)
local name, args = export.parseTemplate(src)
if name ~= nil then
local modifier, type, func
for prefix in name:gmatch("%s*(.-):") do
if prefix == "subst" or prefix == "safesubst" then
view = prefix
name = name:gsub(prefix .. ":", "", 1)
elseif prefix:match("^#") then
if prefix == "#invoke" then
type = "module"
func = args[1]
for i = 2, #args do
args[i-1] = args[i]
end
args[#args] = nil
else
type = "parser function"
end
name = name:gsub(prefix .. ":", "", 1)
end
end
name = name:gsub("^%s*(.*)%s*$", "%1")
view = view or "transclude"
type = type or "template"
return name, args, src, temp_start, view, type, func
end
end
end
pos = pos + 2
end
elseif found == "<n" and text:sub(pos, pos + 7) == "<nowiki>" then
pos = text:find("</nowiki>", pos)
if pos == nil then break end
pos = pos + 8
elseif found == "<!" and text:sub(pos, pos + 3) == "<!--" then
pos = text:find("-->", pos + 4)
if pos == nil then break end
pos = pos + 3
else
pos = pos + 1
end
end
end
return findNextTemplate
end
return export