<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.cultopedia.org/index.php?action=history&amp;feed=atom&amp;title=Module%3AWikitextParser</id>
	<title>Module:WikitextParser - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://www.cultopedia.org/index.php?action=history&amp;feed=atom&amp;title=Module%3AWikitextParser"/>
	<link rel="alternate" type="text/html" href="https://www.cultopedia.org/index.php?title=Module:WikitextParser&amp;action=history"/>
	<updated>2026-04-06T01:51:37Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.44.5</generator>
	<entry>
		<id>https://www.cultopedia.org/index.php?title=Module:WikitextParser&amp;diff=203&amp;oldid=prev</id>
		<title>imported&gt;Sophivorus: Rename variable &quot;WikitextParser&quot; to just &quot;parser&quot; for simplicty, and fix a few edge cases</title>
		<link rel="alternate" type="text/html" href="https://www.cultopedia.org/index.php?title=Module:WikitextParser&amp;diff=203&amp;oldid=prev"/>
		<updated>2026-02-11T14:45:12Z</updated>

		<summary type="html">&lt;p&gt;Rename variable &amp;quot;WikitextParser&amp;quot; to just &amp;quot;parser&amp;quot; for simplicty, and fix a few edge cases&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;-- Module:WikitextParser is a general-purpose wikitext parser&lt;br /&gt;
-- Documentation and master version: https://en.wikipedia.org/wiki/Module:WikitextParser&lt;br /&gt;
-- Authors: User:Sophivorus, User:Certes, User:Aidan9382, et al.&lt;br /&gt;
-- License: CC-BY-SA-4.0&lt;br /&gt;
local parser = {}&lt;br /&gt;
&lt;br /&gt;
-- Private helper method to escape a string for use in regexes&lt;br /&gt;
local function escapeString( str )&lt;br /&gt;
	return string.gsub( str, &amp;#039;[%^%$%(%)%.%[%]%*%+%-%?%%]&amp;#039;, &amp;#039;%%%0&amp;#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the lead section from the given wikitext&lt;br /&gt;
-- The lead section is any content before the first section title.&lt;br /&gt;
-- @param wikitext Required. Wikitext to parse.&lt;br /&gt;
-- @return Wikitext of the lead section. May be empty if the lead section is empty.&lt;br /&gt;
function parser.getLead( wikitext )&lt;br /&gt;
	wikitext = &amp;#039;\n&amp;#039; .. wikitext&lt;br /&gt;
	wikitext = string.gsub( wikitext, &amp;#039;\n==.*&amp;#039;, &amp;#039;&amp;#039; )&lt;br /&gt;
	wikitext = mw.text.trim( wikitext )&lt;br /&gt;
	return wikitext&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the sections from the given wikitext&lt;br /&gt;
-- This method doesn&amp;#039;t get the lead section, use getLead for that&lt;br /&gt;
-- @param wikitext Required. Wikitext to parse.&lt;br /&gt;
-- @return Map from section title to section content&lt;br /&gt;
function parser.getSections( wikitext )&lt;br /&gt;
	local sections = {}&lt;br /&gt;
	wikitext = &amp;#039;\n&amp;#039; .. wikitext .. &amp;#039;\n==&amp;#039;&lt;br /&gt;
	for title in string.gmatch( wikitext, &amp;#039;\n==+ *([^=]-) *==+&amp;#039; ) do&lt;br /&gt;
		local section = string.match( wikitext, &amp;#039;\n==+ *&amp;#039; .. escapeString( title ) .. &amp;#039; *==+(.-)\n==&amp;#039; )&lt;br /&gt;
		section = mw.text.trim( section )&lt;br /&gt;
		sections[ title ] = section&lt;br /&gt;
	end&lt;br /&gt;
	return sections&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get a section from the given wikitext (including any subsections)&lt;br /&gt;
-- If the given section title appears more than once, only the section of the first instance will be returned&lt;br /&gt;
-- @param wikitext Required. Wikitext to parse.&lt;br /&gt;
-- @param title Required. Title of the section&lt;br /&gt;
-- @return Wikitext of the section, or nil if it isn&amp;#039;t found. May be empty if the section is empty or contains only subsections.&lt;br /&gt;
function parser.getSection( wikitext, title )&lt;br /&gt;
	title = mw.text.trim( title )&lt;br /&gt;
	title = escapeString( title )&lt;br /&gt;
	wikitext = &amp;#039;\n&amp;#039; .. wikitext .. &amp;#039;\n&amp;#039;&lt;br /&gt;
	local level&lt;br /&gt;
	level, wikitext = string.match( wikitext, &amp;#039;\n(==+) *&amp;#039; .. title .. &amp;#039; *==.-\n(.*)&amp;#039; )&lt;br /&gt;
	if wikitext then&lt;br /&gt;
		local nextSection = &amp;#039;\n==&amp;#039; .. string.rep( &amp;#039;=?&amp;#039;, #level - 2 ) .. &amp;#039;[^=].*&amp;#039;&lt;br /&gt;
		wikitext = string.gsub( wikitext, nextSection, &amp;#039;&amp;#039; ) -- remove later sections at this level or higher&lt;br /&gt;
		wikitext = mw.text.trim( wikitext )&lt;br /&gt;
		return wikitext&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the content of a &amp;lt;section&amp;gt; tag from the given wikitext.&lt;br /&gt;
-- We can&amp;#039;t use getTags because unlike all other tags, both opening and closing &amp;lt;section&amp;gt; tags are self-closing.&lt;br /&gt;
-- @param wikitext Required. Wikitext to parse.&lt;br /&gt;
-- @param name Required. Name of the &amp;lt;section&amp;gt; tag&lt;br /&gt;
-- @return Content of the &amp;lt;section&amp;gt; tag, or nil if it isn&amp;#039;t found. May be empty if the section tag is empty.&lt;br /&gt;
function parser.getSectionTag( wikitext, name )&lt;br /&gt;
	name = mw.text.trim( name )&lt;br /&gt;
	name = escapeString( name )&lt;br /&gt;
	local sections = {}&lt;br /&gt;
	for section in string.gmatch( wikitext, &amp;#039;&amp;lt; *section +begin *= *[&amp;quot;\&amp;#039;]? *&amp;#039; .. name .. &amp;#039; *[&amp;quot;\&amp;#039;]? */&amp;gt;(.-)&amp;lt; *section +end= *[&amp;quot;\&amp;#039;]? *&amp;#039;.. name ..&amp;#039; *[&amp;quot;\&amp;#039;]? */&amp;gt;&amp;#039; ) do&lt;br /&gt;
		table.insert( sections, section )&lt;br /&gt;
	end&lt;br /&gt;
	if #sections &amp;gt; 0 then&lt;br /&gt;
		return table.concat( sections )&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the lists from the given wikitext.&lt;br /&gt;
-- @param wikitext Required. Wikitext to parse.&lt;br /&gt;
-- @return Sequence of lists.&lt;br /&gt;
function parser.getLists( wikitext )&lt;br /&gt;
	local lists = {}&lt;br /&gt;
	wikitext = &amp;#039;\n&amp;#039; .. wikitext .. &amp;#039;\n\n&amp;#039;&lt;br /&gt;
	for list in string.gmatch( wikitext, &amp;#039;\n([*#].-)\n[^*#]&amp;#039; ) do&lt;br /&gt;
		table.insert( lists, list )&lt;br /&gt;
	end&lt;br /&gt;
	return lists&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the paragraphs from the given wikitext.&lt;br /&gt;
-- @param wikitext Required. Wikitext to parse.&lt;br /&gt;
-- @return Sequence of paragraphs.&lt;br /&gt;
function parser.getParagraphs( wikitext )&lt;br /&gt;
	local paragraphs = {}&lt;br /&gt;
&lt;br /&gt;
	-- Remove non-paragraphs&lt;br /&gt;
	wikitext = &amp;#039;\n&amp;#039; .. wikitext .. &amp;#039;\n&amp;#039; -- add newlines to simplfy patterns&lt;br /&gt;
	wikitext = string.gsub( wikitext, &amp;#039;%f[^\n]&amp;lt;!%-%-.-%-%-&amp;gt;%f[\n]&amp;#039;, &amp;#039;&amp;#039; ) -- remove comments&lt;br /&gt;
	wikitext = string.gsub( wikitext, &amp;#039;%f[^\n]%[%b[]%]%f[\n]&amp;#039;, &amp;#039;&amp;#039; ) -- remove files and categories&lt;br /&gt;
	wikitext = string.gsub( wikitext, &amp;#039;%f[^\n]%b{} *%f[\n]&amp;#039;, &amp;#039;&amp;#039; ) -- remove tables and block templates&lt;br /&gt;
	wikitext = string.gsub( wikitext, &amp;#039;%f[^\n]%b{} *%b{} *%f[\n]&amp;#039;, &amp;#039;&amp;#039; ) -- remove neighboring tables and block templates&lt;br /&gt;
	wikitext = string.gsub( wikitext, &amp;#039;%f[^\n]%b{} *&amp;lt;!%-%-.-%-%-&amp;gt; *%b{} *%f[\n]&amp;#039;, &amp;#039;&amp;#039; ) -- remove neighboring tables and block templates with a comment among them&lt;br /&gt;
	wikitext = string.gsub( wikitext, &amp;#039;%f[^\n][*#].-%f[\n]&amp;#039;, &amp;#039;&amp;#039; ) -- remove lists&lt;br /&gt;
	wikitext = string.gsub( wikitext, &amp;#039;%f[^\n]==+[^=]+==+ *%f[\n]&amp;#039;, &amp;#039;&amp;#039; ) -- remove section titles&lt;br /&gt;
	wikitext = mw.text.trim( wikitext )&lt;br /&gt;
&lt;br /&gt;
	for paragraph in mw.text.gsplit( wikitext, &amp;#039;\n\n+&amp;#039; ) do&lt;br /&gt;
		if mw.text.trim( paragraph ) ~= &amp;#039;&amp;#039; then&lt;br /&gt;
			table.insert( paragraphs, paragraph )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return paragraphs&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the templates from the given wikitext.&lt;br /&gt;
-- @param wikitext Required. Wikitext to parse.&lt;br /&gt;
-- @return Sequence of templates.&lt;br /&gt;
function parser.getTemplates( wikitext )&lt;br /&gt;
	local templates = {}&lt;br /&gt;
	for template in string.gmatch( wikitext, &amp;#039;{%b{}}&amp;#039; ) do&lt;br /&gt;
		if string.sub( template, 1, 3 ) ~= &amp;#039;{{#&amp;#039; then -- skip parser functions like #if&lt;br /&gt;
			table.insert( templates, template )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return templates&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the requested template from the given wikitext.&lt;br /&gt;
-- If the template appears more than once, only the first instance will be returned&lt;br /&gt;
-- @param wikitext Required. Wikitext to parse.&lt;br /&gt;
-- @param name Name of the template to get&lt;br /&gt;
-- @return Wikitext of the template, or nil if it wasn&amp;#039;t found&lt;br /&gt;
function parser.getTemplate( wikitext, name )&lt;br /&gt;
	local templates = parser.getTemplates( wikitext )&lt;br /&gt;
	local lang = mw.language.getContentLanguage()&lt;br /&gt;
	for _, template in pairs( templates ) do&lt;br /&gt;
		local templateName = parser.getTemplateName( template )&lt;br /&gt;
		if lang:ucfirst( templateName ) == lang:ucfirst( name ) then&lt;br /&gt;
			return template&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get name of the template from the given template wikitext.&lt;br /&gt;
-- @param templateWikitext Required. Wikitext of the template to parse.&lt;br /&gt;
-- @return Name of the template&lt;br /&gt;
-- @todo Strip &amp;quot;Template:&amp;quot; namespace?&lt;br /&gt;
function parser.getTemplateName( templateWikitext )&lt;br /&gt;
	return string.match( templateWikitext, &amp;#039;^{{ *([^}|\n]+)&amp;#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the parameters from the given template wikitext.&lt;br /&gt;
-- @param templateWikitext Required. Wikitext of the template to parse.&lt;br /&gt;
-- @return Map from parameter names to parameter values, NOT IN THE ORIGINAL ORDER.&lt;br /&gt;
-- @return Order in which the parameters were parsed.&lt;br /&gt;
function parser.getTemplateParameters( templateWikitext )&lt;br /&gt;
	local parameters = {}&lt;br /&gt;
	local paramOrder = {}&lt;br /&gt;
	local params = string.match( templateWikitext, &amp;#039;{{[^|}]-|(.*)}}&amp;#039; )&lt;br /&gt;
	if params then&lt;br /&gt;
		-- Temporarily replace pipes in subtemplates and links to avoid chaos&lt;br /&gt;
		for subtemplate in string.gmatch( params, &amp;#039;{%b{}}&amp;#039; ) do&lt;br /&gt;
			params = string.gsub( params, escapeString( subtemplate ), string.gsub( subtemplate, &amp;#039;.&amp;#039;, { [&amp;#039;%&amp;#039;]=&amp;#039;%%&amp;#039;, [&amp;#039;|&amp;#039;]=&amp;quot;@@:@@&amp;quot;, [&amp;#039;=&amp;#039;]=&amp;#039;@@_@@&amp;#039; } ) )&lt;br /&gt;
		end&lt;br /&gt;
		for link in string.gmatch( params, &amp;#039;%[%b[]%]&amp;#039; ) do&lt;br /&gt;
			params = string.gsub( params, escapeString( link ), string.gsub( link, &amp;#039;.&amp;#039;, { [&amp;#039;%&amp;#039;]=&amp;#039;%%&amp;#039;, [&amp;#039;|&amp;#039;]=&amp;#039;@@:@@&amp;#039;, [&amp;#039;=&amp;#039;]=&amp;#039;@@_@@&amp;#039; } ) )&lt;br /&gt;
		end&lt;br /&gt;
		local count = 0&lt;br /&gt;
		local parts, name, value&lt;br /&gt;
		for param in mw.text.gsplit( params, &amp;#039;|&amp;#039; ) do&lt;br /&gt;
			parts = mw.text.split( param, &amp;#039;=&amp;#039; )&lt;br /&gt;
			name = mw.text.trim( parts[1] )&lt;br /&gt;
			if tonumber( name ) then&lt;br /&gt;
				name = tonumber( name )&lt;br /&gt;
			end&lt;br /&gt;
			if #parts == 1 then&lt;br /&gt;
				value = name&lt;br /&gt;
				count = count + 1&lt;br /&gt;
				name = count&lt;br /&gt;
			else&lt;br /&gt;
				value = table.concat( parts, &amp;#039;=&amp;#039;, 2 );&lt;br /&gt;
				value = mw.text.trim( value )&lt;br /&gt;
			end&lt;br /&gt;
			value = string.gsub( value, &amp;#039;@@_@@&amp;#039;, &amp;#039;=&amp;#039; )&lt;br /&gt;
			value = string.gsub( value, &amp;#039;@@:@@&amp;#039;, &amp;#039;|&amp;#039; )&lt;br /&gt;
			parameters[ name ] = value&lt;br /&gt;
			table.insert( paramOrder, name )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return parameters, paramOrder&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the tags from the given wikitext.&lt;br /&gt;
-- @param wikitext Required. Wikitext to parse.&lt;br /&gt;
-- @return Sequence of tags.&lt;br /&gt;
function parser.getTags( wikitext )&lt;br /&gt;
	local tags = {}&lt;br /&gt;
	local tag, tagName, tagEnd&lt;br /&gt;
	-- Don&amp;#039;t match closing tags like &amp;lt;/div&amp;gt;, comments like &amp;lt;!--foo--&amp;gt;, comparisons like 1&amp;lt;2 or things like &amp;lt;3&lt;br /&gt;
	for tagStart, tagOpen in string.gmatch( wikitext, &amp;#039;()(&amp;lt;[^/!%d].-&amp;gt;)&amp;#039; ) do&lt;br /&gt;
		tagName = parser.getTagName( tagOpen )&lt;br /&gt;
&lt;br /&gt;
		-- If we&amp;#039;re in a self-closing tag, like &amp;lt;ref name=&amp;quot;foo&amp;quot; /&amp;gt;, &amp;lt;references/&amp;gt;, &amp;lt;br/&amp;gt;, &amp;lt;br&amp;gt;, &amp;lt;hr&amp;gt;, etc.&lt;br /&gt;
		if string.match( tagOpen, &amp;#039;&amp;lt;.-/&amp;gt;&amp;#039; ) or tagName == &amp;#039;br&amp;#039; or tagName == &amp;#039;hr&amp;#039; then&lt;br /&gt;
			tag = tagOpen&lt;br /&gt;
&lt;br /&gt;
		-- If we&amp;#039;re in a tag that may contain others like it, like &amp;lt;div&amp;gt; or &amp;lt;span&amp;gt;&lt;br /&gt;
		elseif tagName == &amp;#039;div&amp;#039; or tagName == &amp;#039;span&amp;#039; then&lt;br /&gt;
			local position = tagStart + #tagOpen - 1&lt;br /&gt;
			local depth = 1&lt;br /&gt;
			while depth &amp;gt; 0 do&lt;br /&gt;
				tagEnd = string.match( wikitext, &amp;#039;&amp;lt;/ ?&amp;#039; .. tagName .. &amp;#039; ?&amp;gt;()&amp;#039;, position )&lt;br /&gt;
				if tagEnd then&lt;br /&gt;
					tagEnd = tagEnd - 1&lt;br /&gt;
				else&lt;br /&gt;
					break -- unclosed tag&lt;br /&gt;
				end &lt;br /&gt;
				position = string.match( wikitext, &amp;#039;()&amp;lt; ?&amp;#039; .. tagName .. &amp;#039;[ &amp;gt;]&amp;#039;, position + 1 )&lt;br /&gt;
				if not position then&lt;br /&gt;
					position = tagEnd + 1&lt;br /&gt;
				end&lt;br /&gt;
				if position &amp;gt; tagEnd then&lt;br /&gt;
					depth = depth - 1&lt;br /&gt;
				else&lt;br /&gt;
					depth = depth + 1&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			tag = string.sub( wikitext, tagStart, tagEnd )&lt;br /&gt;
&lt;br /&gt;
		-- Else we&amp;#039;re probably in tag that shouldn&amp;#039;t contain others like it, like &amp;lt;math&amp;gt; or &amp;lt;strong&amp;gt;&lt;br /&gt;
		else&lt;br /&gt;
			tagEnd = string.match( wikitext, &amp;#039;&amp;lt;/ ?&amp;#039; .. tagName .. &amp;#039; ?&amp;gt;()&amp;#039;, tagStart )&lt;br /&gt;
			if tagEnd then&lt;br /&gt;
				tag = string.sub( wikitext, tagStart, tagEnd - 1 )&lt;br /&gt;
&lt;br /&gt;
			-- If no end tag is found, assume we matched something that wasn&amp;#039;t a tag, like &amp;lt;no. 1&amp;gt;&lt;br /&gt;
			else&lt;br /&gt;
				tag = nil&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		table.insert( tags, tag )&lt;br /&gt;
	end&lt;br /&gt;
	return tags&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the name of the tag in the given wikitext&lt;br /&gt;
-- @param tag Required. Tag to parse.&lt;br /&gt;
-- @return Name of the tag or nil if not found&lt;br /&gt;
function parser.getTagName( tagWikitext )&lt;br /&gt;
	local tagName = string.match( tagWikitext, &amp;#039;^&amp;lt; *(.-)[ /&amp;gt;]&amp;#039; )&lt;br /&gt;
	if tagName then tagName = string.lower( tagName ) end&lt;br /&gt;
	return tagName&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the value of an attribute in the given tag.&lt;br /&gt;
-- @param tagWikitext Required. Wikitext of the tag to parse.&lt;br /&gt;
-- @param attribute Required. Name of the attribute.&lt;br /&gt;
-- @return Value of the attribute or nil if not found&lt;br /&gt;
function parser.getTagAttribute( tagWikitext, attribute )&lt;br /&gt;
	local _, value = string.match( tagWikitext, &amp;#039;^&amp;lt;[^/&amp;gt;]*&amp;#039; .. attribute .. &amp;#039; *= *([&amp;quot;\&amp;#039;]?)([^/&amp;gt;]-)%1[ /&amp;gt;]&amp;#039; )&lt;br /&gt;
	return value&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the content of the given tag.&lt;br /&gt;
-- @param tagWikitext Required. Wikitext of the tag to parse.&lt;br /&gt;
-- @return Content of the tag. May be empty if the tag is empty. Will be nil if the tag is self-closing.&lt;br /&gt;
-- @todo May fail with nested tags&lt;br /&gt;
function parser.getTagContent( tagWikitext )&lt;br /&gt;
	return string.match( tagWikitext, &amp;#039;^&amp;lt;.-&amp;gt;.-&amp;lt;/.-&amp;gt;&amp;#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the &amp;lt;gallery&amp;gt; tags from the given wikitext.&lt;br /&gt;
-- @param wikitext Required. Wikitext to parse.&lt;br /&gt;
-- @return Sequence of gallery tags.&lt;br /&gt;
function parser.getGalleries( wikitext )&lt;br /&gt;
	local galleries = {}&lt;br /&gt;
	local tags = parser.getTags( wikitext )&lt;br /&gt;
	for _, tag in pairs( tags ) do&lt;br /&gt;
		local tagName = parser.getTagName( tag )&lt;br /&gt;
		if tagName == &amp;#039;gallery&amp;#039; then&lt;br /&gt;
			table.insert( galleries, tag )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return galleries&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the &amp;lt;ref&amp;gt; tags from the given wikitext.&lt;br /&gt;
-- @param wikitext Required. Wikitext to parse.&lt;br /&gt;
-- @return Sequence of ref tags.&lt;br /&gt;
function parser.getReferences( wikitext )&lt;br /&gt;
	local references = {}&lt;br /&gt;
	local tags = parser.getTags( wikitext )&lt;br /&gt;
	for _, tag in pairs( tags ) do&lt;br /&gt;
		local tagName = parser.getTagName( tag )&lt;br /&gt;
		if tagName == &amp;#039;ref&amp;#039; then&lt;br /&gt;
			table.insert( references, tag )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return references&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the reference with the given name from the given wikitext.&lt;br /&gt;
-- @param wikitext Required. Wikitext to parse.&lt;br /&gt;
-- @param referenceName Required. Name of the reference.&lt;br /&gt;
-- @return Wikitext of the reference&lt;br /&gt;
function parser.getReference( wikitext, referenceName )&lt;br /&gt;
	local references = parser.getReferences( wikitext )&lt;br /&gt;
	for _, reference in pairs( references ) do&lt;br /&gt;
		local content = parser.getTagContent( reference )&lt;br /&gt;
		local name = parser.getTagAttribute( reference, &amp;#039;name&amp;#039; )&lt;br /&gt;
		if content and name == referenceName then&lt;br /&gt;
			return reference&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the tables from the given wikitext.&lt;br /&gt;
-- @param wikitext Required. Wikitext to parse.&lt;br /&gt;
-- @return Sequence of tables.&lt;br /&gt;
function parser.getTables( wikitext )&lt;br /&gt;
	local tables = {}&lt;br /&gt;
	wikitext = &amp;#039;\n&amp;#039; .. wikitext&lt;br /&gt;
	for t in string.gmatch( wikitext, &amp;#039;\n%b{}&amp;#039; ) do&lt;br /&gt;
		if string.sub( t, 1, 3 ) == &amp;#039;\n{|&amp;#039; then&lt;br /&gt;
			t = mw.text.trim( t ) -- exclude the leading newline&lt;br /&gt;
			table.insert( tables, t )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return tables&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the id from the given table wikitext&lt;br /&gt;
-- @param tableWikitext Required. Wikitext of the table to parse.&lt;br /&gt;
-- @param attribute Required. Name of the attribute.&lt;br /&gt;
-- @return Value of the attribute or nil if not found&lt;br /&gt;
function parser.getTableAttribute( tableWikitext, attribute )&lt;br /&gt;
	local _, value = string.match( tableWikitext, &amp;#039;^{|[^\n]*&amp;#039; .. attribute .. &amp;#039; *= *([&amp;quot;\&amp;#039;]?)([^\n]-)%1[^\n]*\n&amp;#039; )&lt;br /&gt;
	if not value or value == &amp;#039;&amp;#039; then&lt;br /&gt;
		value = string.match( tableWikitext, &amp;#039;^{|[^\n]*&amp;#039; .. attribute .. &amp;#039; *= *([^\n ]+)[^\n]*\n&amp;#039; )&lt;br /&gt;
	end&lt;br /&gt;
	return value&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get a table by id from the given wikitext&lt;br /&gt;
-- @param wikitext Required. Wikitext to parse.&lt;br /&gt;
-- @param id Required. Id of the table&lt;br /&gt;
-- @return Wikitext of the table or nil if not found&lt;br /&gt;
function parser.getTable( wikitext, id )&lt;br /&gt;
	local tables = parser.getTables( wikitext )&lt;br /&gt;
	for _, t in pairs( tables ) do&lt;br /&gt;
		if id == parser.getTableAttribute( t, &amp;#039;id&amp;#039; ) then&lt;br /&gt;
			return t&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the data from the given table wikitext&lt;br /&gt;
-- @param tableWikitext Required. Wikitext of the table to parse.&lt;br /&gt;
-- @return Table data&lt;br /&gt;
-- @todo Test and make more robust&lt;br /&gt;
function parser.getTableData( tableWikitext )&lt;br /&gt;
	local tableData = {}&lt;br /&gt;
	tableWikitext = mw.text.trim( tableWikitext );&lt;br /&gt;
	tableWikitext = string.gsub( tableWikitext, &amp;#039;^{|.-\n&amp;#039;, &amp;#039;&amp;#039; ) -- remove the header&lt;br /&gt;
	tableWikitext = string.gsub( tableWikitext, &amp;#039;\n|}$&amp;#039;, &amp;#039;&amp;#039; ) -- remove the footer&lt;br /&gt;
	tableWikitext = string.gsub( tableWikitext, &amp;#039;^|%+.-\n&amp;#039;, &amp;#039;&amp;#039; ) -- remove any caption&lt;br /&gt;
	tableWikitext = string.gsub( tableWikitext, &amp;#039;|%-.-\n&amp;#039;, &amp;#039;|-\n&amp;#039; ) -- remove any row attributes&lt;br /&gt;
	tableWikitext = string.gsub( tableWikitext, &amp;#039;^|%-\n&amp;#039;, &amp;#039;&amp;#039; ) -- remove any leading empty row&lt;br /&gt;
	tableWikitext = string.gsub( tableWikitext, &amp;#039;\n|%-$&amp;#039;, &amp;#039;&amp;#039; ) -- remove any trailing empty row&lt;br /&gt;
	for rowWikitext in mw.text.gsplit( tableWikitext, &amp;#039;|-&amp;#039;, true ) do&lt;br /&gt;
		local rowData = {}&lt;br /&gt;
		rowWikitext = string.gsub( rowWikitext, &amp;#039;||&amp;#039;, &amp;#039;\n|&amp;#039; )&lt;br /&gt;
		rowWikitext = string.gsub( rowWikitext, &amp;#039;!!&amp;#039;, &amp;#039;\n|&amp;#039; )&lt;br /&gt;
		rowWikitext = string.gsub( rowWikitext, &amp;#039;\n!&amp;#039;, &amp;#039;\n|&amp;#039; )&lt;br /&gt;
		rowWikitext = string.gsub( rowWikitext, &amp;#039;^!&amp;#039;, &amp;#039;\n|&amp;#039; )&lt;br /&gt;
		rowWikitext = string.gsub( rowWikitext, &amp;#039;^\n|&amp;#039;, &amp;#039;&amp;#039; )&lt;br /&gt;
		for cellWikitext in mw.text.gsplit( rowWikitext, &amp;#039;\n|&amp;#039; ) do&lt;br /&gt;
			cellWikitext = mw.text.trim( cellWikitext )&lt;br /&gt;
			table.insert( rowData, cellWikitext )&lt;br /&gt;
		end&lt;br /&gt;
		table.insert( tableData, rowData )&lt;br /&gt;
	end&lt;br /&gt;
	return tableData&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the internal links from the given wikitext (includes category and file links).&lt;br /&gt;
-- @param wikitext Required. Wikitext to parse.&lt;br /&gt;
-- @return Sequence of internal links.&lt;br /&gt;
function parser.getLinks( wikitext )&lt;br /&gt;
	local links = {}&lt;br /&gt;
	for link in string.gmatch( wikitext, &amp;#039;%[%b[]%]&amp;#039; ) do&lt;br /&gt;
		table.insert( links, link )&lt;br /&gt;
	end&lt;br /&gt;
	return links&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the file links from the given wikitext.&lt;br /&gt;
-- @param wikitext Required. Wikitext to parse.&lt;br /&gt;
-- @return Sequence of file links.&lt;br /&gt;
function parser.getFiles( wikitext )&lt;br /&gt;
	local files = {}&lt;br /&gt;
	local links = parser.getLinks( wikitext )&lt;br /&gt;
	for _, link in pairs( links ) do&lt;br /&gt;
		local namespace = string.match( link, &amp;#039;^%[%[ *(.-) *:&amp;#039; )&lt;br /&gt;
		if namespace and mw.site.namespaces[ namespace ] and mw.site.namespaces[ namespace ].canonicalName == &amp;#039;File&amp;#039; then&lt;br /&gt;
			table.insert( files, link )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return files&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get name of the file from the given file wikitext.&lt;br /&gt;
-- @param fileWikitext Required. Wikitext of the file to parse.&lt;br /&gt;
-- @return Name of the file&lt;br /&gt;
function parser.getFileName( fileWikitext )&lt;br /&gt;
	return string.match( fileWikitext, &amp;#039;^%[%[ *.- *: *(.-) *[]|]&amp;#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the category links from the given wikitext.&lt;br /&gt;
-- @param wikitext Required. Wikitext to parse.&lt;br /&gt;
-- @return Sequence of category links.&lt;br /&gt;
function parser.getCategories( wikitext )&lt;br /&gt;
	local categories = {}&lt;br /&gt;
	local links = parser.getLinks( wikitext )&lt;br /&gt;
	for _, link in pairs( links ) do&lt;br /&gt;
		local namespace = string.match( link, &amp;#039;^%[%[ -(.-) -:&amp;#039; )&lt;br /&gt;
		if namespace and mw.site.namespaces[ namespace ] and mw.site.namespaces[ namespace ].canonicalName == &amp;#039;Category&amp;#039; then&lt;br /&gt;
			table.insert( categories, link )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return categories&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the external links from the given wikitext.&lt;br /&gt;
-- @param wikitext Required. Wikitext to parse.&lt;br /&gt;
-- @return Sequence of external links.&lt;br /&gt;
function parser.getExternalLinks( wikitext )&lt;br /&gt;
	local links = {}&lt;br /&gt;
	for link in string.gmatch( wikitext, &amp;#039;%b[]&amp;#039; ) do&lt;br /&gt;
		if string.match( link, &amp;#039;^%[//&amp;#039; ) or string.match( link, &amp;#039;^%[https?://&amp;#039; ) then&lt;br /&gt;
			table.insert( links, link )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return links&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return parser&lt;/div&gt;</summary>
		<author><name>imported&gt;Sophivorus</name></author>
	</entry>
</feed>