<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.minetest.org/index.php?action=history&amp;feed=atom&amp;title=Module%3ATextUtil</id>
	<title>Module:TextUtil - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.minetest.org/index.php?action=history&amp;feed=atom&amp;title=Module%3ATextUtil"/>
	<link rel="alternate" type="text/html" href="https://wiki.minetest.org/index.php?title=Module:TextUtil&amp;action=history"/>
	<updated>2026-06-19T18:31:40Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.3</generator>
	<entry>
		<id>https://wiki.minetest.org/index.php?title=Module:TextUtil&amp;diff=15086&amp;oldid=prev</id>
		<title>&gt;FnControlOption: FnControlOption changed the content model of the page Module:TextUtil from &quot;plain text&quot; to &quot;Scribunto&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.minetest.org/index.php?title=Module:TextUtil&amp;diff=15086&amp;oldid=prev"/>
		<updated>2022-06-07T17:43:23Z</updated>

		<summary type="html">&lt;p&gt;FnControlOption changed the content model of the page &lt;a href=&quot;/Module:TextUtil&quot; title=&quot;Module:TextUtil&quot;&gt;Module:TextUtil&lt;/a&gt; from &amp;quot;plain text&amp;quot; to &amp;quot;Scribunto&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;--[[&lt;br /&gt;
    mw.text, modified for the Minetest Wiki.&lt;br /&gt;
&lt;br /&gt;
    Code released under the GPL v2+ as per:&lt;br /&gt;
    https://github.com/wikimedia/mediawiki-extensions-Scribunto/blob/7d676c3/COPYING&lt;br /&gt;
&lt;br /&gt;
    @license GNU GPL v2+&lt;br /&gt;
    @author Brad Jorsch &amp;lt; bjorsch@wikimedia.org &amp;gt;&lt;br /&gt;
    @author &amp;quot;Mr. Stradivarius&amp;quot; &amp;lt; misterstrad@gmail.com &amp;gt;&lt;br /&gt;
    @author MrIbby &amp;lt; siribby@outlook.com &amp;gt;&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local mwtext = {}&lt;br /&gt;
local php&lt;br /&gt;
local options&lt;br /&gt;
&lt;br /&gt;
local util = require( &amp;#039;Module:LibraryUtil&amp;#039; )&lt;br /&gt;
local checkType = util.checkType&lt;br /&gt;
local checkTypeForNamedArg = util.checkTypeForNamedArg&lt;br /&gt;
&lt;br /&gt;
function mwtext.trim( s, charset )&lt;br /&gt;
    charset = charset or &amp;#039;\t\r\n\f &amp;#039;&lt;br /&gt;
	s = mw.ustring.gsub( s, &amp;#039;^[&amp;#039; .. charset .. &amp;#039;]*(.-)[&amp;#039; .. charset .. &amp;#039;]*$&amp;#039;, &amp;#039;%1&amp;#039; )&lt;br /&gt;
	return s&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local htmlencode_map = {&lt;br /&gt;
	[&amp;#039;&amp;gt;&amp;#039;] = &amp;#039;&amp;amp;gt;&amp;#039;,&lt;br /&gt;
	[&amp;#039;&amp;lt;&amp;#039;] = &amp;#039;&amp;amp;lt;&amp;#039;,&lt;br /&gt;
	[&amp;#039;&amp;amp;&amp;#039;] = &amp;#039;&amp;amp;amp;&amp;#039;,&lt;br /&gt;
	[&amp;#039;&amp;quot;&amp;#039;] = &amp;#039;&amp;amp;quot;&amp;#039;,&lt;br /&gt;
	[&amp;quot;&amp;#039;&amp;quot;] = &amp;#039;&amp;amp;#039;&amp;#039;,&lt;br /&gt;
	[&amp;#039;\194\160&amp;#039;] = &amp;#039;&amp;amp;nbsp;&amp;#039;,&lt;br /&gt;
}&lt;br /&gt;
local htmldecode_map = {}&lt;br /&gt;
for k, v in pairs( htmlencode_map ) do&lt;br /&gt;
	htmldecode_map[v] = k&lt;br /&gt;
end&lt;br /&gt;
local decode_named_entities = nil&lt;br /&gt;
&lt;br /&gt;
function mwtext.encode( s, charset )&lt;br /&gt;
	charset = charset or &amp;#039;&amp;lt;&amp;gt;&amp;amp;&amp;quot;\&amp;#039;\194\160&amp;#039;&lt;br /&gt;
	s = mw.ustring.gsub( s, &amp;#039;[&amp;#039; .. charset .. &amp;#039;]&amp;#039;, function ( m )&lt;br /&gt;
		if not htmlencode_map[m] then&lt;br /&gt;
			local e = string.format( &amp;#039;&amp;amp;#%d;&amp;#039;, mw.ustring.codepoint( m ) )&lt;br /&gt;
			htmlencode_map[m] = e&lt;br /&gt;
			htmldecode_map[e] = m&lt;br /&gt;
		end&lt;br /&gt;
		return htmlencode_map[m]&lt;br /&gt;
	end )&lt;br /&gt;
	return s&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function mwtext.decode( s, decodeNamedEntities )&lt;br /&gt;
	local dec&lt;br /&gt;
	if decodeNamedEntities then&lt;br /&gt;
		if decode_named_entities == nil then&lt;br /&gt;
			decode_named_entities = php.getEntityTable()&lt;br /&gt;
			setmetatable( decode_named_entities, { __index = htmldecode_map } )&lt;br /&gt;
		end&lt;br /&gt;
		dec = decode_named_entities&lt;br /&gt;
	else&lt;br /&gt;
		dec = htmldecode_map&lt;br /&gt;
	end&lt;br /&gt;
	-- string.gsub is safe here, because only ASCII chars are in the pattern&lt;br /&gt;
	s = string.gsub( s, &amp;#039;(&amp;amp;(#?x?)([a-zA-Z0-9]+);)&amp;#039;, function ( m, flg, name )&lt;br /&gt;
		if not dec[m] then&lt;br /&gt;
			local n = nil&lt;br /&gt;
			if flg == &amp;#039;#&amp;#039; then&lt;br /&gt;
				n = tonumber( name, 10 )&lt;br /&gt;
			elseif flg == &amp;#039;#x&amp;#039; then&lt;br /&gt;
				n = tonumber( name, 16 )&lt;br /&gt;
			end&lt;br /&gt;
			if n and n &amp;lt;= 0x10ffff then&lt;br /&gt;
				n = mw.ustring.char( n )&lt;br /&gt;
				if n then&lt;br /&gt;
					htmldecode_map[m] = n&lt;br /&gt;
					htmlencode_map[n] = m&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		return dec[m]&lt;br /&gt;
	end )&lt;br /&gt;
	return s&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local nowikiRepl1 = {&lt;br /&gt;
	[&amp;#039;&amp;quot;&amp;#039;] = &amp;#039;&amp;amp;#34;&amp;#039;,&lt;br /&gt;
	[&amp;#039;&amp;amp;&amp;#039;] = &amp;#039;&amp;amp;#38;&amp;#039;,&lt;br /&gt;
	[&amp;quot;&amp;#039;&amp;quot;] = &amp;#039;&amp;amp;#39;&amp;#039;,&lt;br /&gt;
	[&amp;#039;&amp;lt;&amp;#039;] = &amp;#039;&amp;amp;#60;&amp;#039;,&lt;br /&gt;
	[&amp;#039;=&amp;#039;] = &amp;#039;&amp;amp;#61;&amp;#039;,&lt;br /&gt;
	[&amp;#039;&amp;gt;&amp;#039;] = &amp;#039;&amp;amp;#62;&amp;#039;,&lt;br /&gt;
	[&amp;#039;[&amp;#039;] = &amp;#039;&amp;amp;#91;&amp;#039;,&lt;br /&gt;
	[&amp;#039;]&amp;#039;] = &amp;#039;&amp;amp;#93;&amp;#039;,&lt;br /&gt;
	[&amp;#039;{&amp;#039;] = &amp;#039;&amp;amp;#123;&amp;#039;,&lt;br /&gt;
	[&amp;#039;|&amp;#039;] = &amp;#039;&amp;amp;#124;&amp;#039;,&lt;br /&gt;
	[&amp;#039;}&amp;#039;] = &amp;#039;&amp;amp;#125;&amp;#039;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local nowikiRepl2 = {&lt;br /&gt;
	[&amp;quot;\n#&amp;quot;] = &amp;quot;\n&amp;amp;#35;&amp;quot;, [&amp;quot;\r#&amp;quot;] = &amp;quot;\r&amp;amp;#35;&amp;quot;,&lt;br /&gt;
	[&amp;quot;\n*&amp;quot;] = &amp;quot;\n&amp;amp;#42;&amp;quot;, [&amp;quot;\r*&amp;quot;] = &amp;quot;\r&amp;amp;#42;&amp;quot;,&lt;br /&gt;
	[&amp;quot;\n:&amp;quot;] = &amp;quot;\n&amp;amp;#58;&amp;quot;, [&amp;quot;\r:&amp;quot;] = &amp;quot;\r&amp;amp;#58;&amp;quot;,&lt;br /&gt;
	[&amp;quot;\n;&amp;quot;] = &amp;quot;\n&amp;amp;#59;&amp;quot;, [&amp;quot;\r;&amp;quot;] = &amp;quot;\r&amp;amp;#59;&amp;quot;,&lt;br /&gt;
	[&amp;quot;\n &amp;quot;] = &amp;quot;\n&amp;amp;#32;&amp;quot;, [&amp;quot;\r &amp;quot;] = &amp;quot;\r&amp;amp;#32;&amp;quot;,&lt;br /&gt;
	[&amp;quot;\n\n&amp;quot;] = &amp;quot;\n&amp;amp;#10;&amp;quot;, [&amp;quot;\r\n&amp;quot;] = &amp;quot;&amp;amp;#13;\n&amp;quot;,&lt;br /&gt;
	[&amp;quot;\n\r&amp;quot;] = &amp;quot;\n&amp;amp;#13;&amp;quot;, [&amp;quot;\r\r&amp;quot;] = &amp;quot;\r&amp;amp;#13;&amp;quot;,&lt;br /&gt;
	[&amp;quot;\n\t&amp;quot;] = &amp;quot;\n&amp;amp;#9;&amp;quot;, [&amp;quot;\r\t&amp;quot;] = &amp;quot;\r&amp;amp;#9;&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local nowikiReplMagic = {}&lt;br /&gt;
for sp, esc in pairs( {&lt;br /&gt;
	[&amp;#039; &amp;#039;] = &amp;#039;&amp;amp;#32;&amp;#039;,&lt;br /&gt;
	[&amp;#039;\t&amp;#039;] = &amp;#039;&amp;amp;#9;&amp;#039;,&lt;br /&gt;
	[&amp;#039;\r&amp;#039;] = &amp;#039;&amp;amp;#13;&amp;#039;,&lt;br /&gt;
	[&amp;#039;\n&amp;#039;] = &amp;#039;&amp;amp;#10;&amp;#039;,&lt;br /&gt;
	[&amp;#039;\f&amp;#039;] = &amp;#039;&amp;amp;#12;&amp;#039;,&lt;br /&gt;
} ) do&lt;br /&gt;
	nowikiReplMagic[&amp;#039;ISBN&amp;#039; .. sp] = &amp;#039;ISBN&amp;#039; .. esc&lt;br /&gt;
	nowikiReplMagic[&amp;#039;RFC&amp;#039; .. sp] = &amp;#039;RFC&amp;#039; .. esc&lt;br /&gt;
	nowikiReplMagic[&amp;#039;PMID&amp;#039; .. sp] = &amp;#039;PMID&amp;#039; .. esc&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function mwtext.nowiki( s )&lt;br /&gt;
	-- string.gsub is safe here, because we&amp;#039;re only caring about ASCII chars&lt;br /&gt;
	s = string.gsub( s, &amp;#039;[&amp;quot;&amp;amp;\&amp;#039;&amp;lt;=&amp;gt;%[%]{|}]&amp;#039;, nowikiRepl1 )&lt;br /&gt;
	s = &amp;#039;\n&amp;#039; .. s&lt;br /&gt;
	s = string.gsub( s, &amp;#039;[\r\n][#*:; \n\r\t]&amp;#039;, nowikiRepl2 )&lt;br /&gt;
	s = string.gsub( s, &amp;#039;([\r\n])%-%-%-%-&amp;#039;, &amp;#039;%1&amp;amp;#45;---&amp;#039; )&lt;br /&gt;
	s = string.sub( s, 2 )&lt;br /&gt;
	s = string.gsub( s, &amp;#039;__&amp;#039;, &amp;#039;_&amp;amp;#95;&amp;#039; )&lt;br /&gt;
	s = string.gsub( s, &amp;#039;://&amp;#039;, &amp;#039;&amp;amp;#58;//&amp;#039; )&lt;br /&gt;
	s = string.gsub( s, &amp;#039;ISBN%s&amp;#039;, nowikiReplMagic )&lt;br /&gt;
	s = string.gsub( s, &amp;#039;RFC%s&amp;#039;, nowikiReplMagic )&lt;br /&gt;
	s = string.gsub( s, &amp;#039;PMID%s&amp;#039;, nowikiReplMagic )&lt;br /&gt;
	for k, v in pairs( options.nowiki_protocols ) do&lt;br /&gt;
		s = string.gsub( s, k, v )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return s&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function mwtext.tag( name, attrs, content )&lt;br /&gt;
	local named = false&lt;br /&gt;
	if type( name ) == &amp;#039;table&amp;#039; then&lt;br /&gt;
		named = true&lt;br /&gt;
		name, attrs, content = name.name, name.attrs, name.content&lt;br /&gt;
		checkTypeForNamedArg( &amp;#039;tag&amp;#039;, &amp;#039;name&amp;#039;, name, &amp;#039;string&amp;#039; )&lt;br /&gt;
		checkTypeForNamedArg( &amp;#039;tag&amp;#039;, &amp;#039;attrs&amp;#039;, attrs, &amp;#039;table&amp;#039;, true )&lt;br /&gt;
	else&lt;br /&gt;
		checkType( &amp;#039;tag&amp;#039;, 1, name, &amp;#039;string&amp;#039; )&lt;br /&gt;
		checkType( &amp;#039;tag&amp;#039;, 2, attrs, &amp;#039;table&amp;#039;, true )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local ret = { &amp;#039;&amp;lt;&amp;#039; .. name }&lt;br /&gt;
	for k, v in pairs( attrs or {} ) do&lt;br /&gt;
		if type( k ) ~= &amp;#039;string&amp;#039; then&lt;br /&gt;
			error( &amp;quot;bad named argument attrs to &amp;#039;tag&amp;#039; (keys must be strings, found &amp;quot; .. type( k ) .. &amp;quot;)&amp;quot;, 2 )&lt;br /&gt;
		end&lt;br /&gt;
		if string.match( k, &amp;#039;[\t\r\n\f /&amp;lt;&amp;gt;&amp;quot;\&amp;#039;=]&amp;#039; ) then&lt;br /&gt;
			error( &amp;quot;bad named argument attrs to &amp;#039;tag&amp;#039; (invalid key &amp;#039;&amp;quot; .. k .. &amp;quot;&amp;#039;)&amp;quot;, 2 )&lt;br /&gt;
		end&lt;br /&gt;
		local tp = type( v )&lt;br /&gt;
		if tp == &amp;#039;boolean&amp;#039; then&lt;br /&gt;
			if v then&lt;br /&gt;
				ret[#ret+1] = &amp;#039; &amp;#039; .. k&lt;br /&gt;
			end&lt;br /&gt;
		elseif tp == &amp;#039;string&amp;#039; or tp == &amp;#039;number&amp;#039; then&lt;br /&gt;
			ret[#ret+1] = string.format( &amp;#039; %s=&amp;quot;%s&amp;quot;&amp;#039;, k, mwtext.encode( tostring( v ) ) )&lt;br /&gt;
		else&lt;br /&gt;
			error( &amp;quot;bad named argument attrs to &amp;#039;tag&amp;#039; (value for key &amp;#039;&amp;quot; .. k .. &amp;quot;&amp;#039; may not be &amp;quot; .. tp .. &amp;quot;)&amp;quot;, 2 )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local tp = type( content )&lt;br /&gt;
	if content == nil then&lt;br /&gt;
		ret[#ret+1] = &amp;#039;&amp;gt;&amp;#039;&lt;br /&gt;
	elseif content == false then&lt;br /&gt;
		ret[#ret+1] = &amp;#039; /&amp;gt;&amp;#039;&lt;br /&gt;
	elseif tp == &amp;#039;string&amp;#039; or tp == &amp;#039;number&amp;#039; then&lt;br /&gt;
		ret[#ret+1] = &amp;#039;&amp;gt;&amp;#039;&lt;br /&gt;
		ret[#ret+1] = content&lt;br /&gt;
		ret[#ret+1] = &amp;#039;&amp;lt;/&amp;#039; .. name .. &amp;#039;&amp;gt;&amp;#039;&lt;br /&gt;
	else&lt;br /&gt;
		if named then&lt;br /&gt;
			checkTypeForNamedArg( &amp;#039;tag&amp;#039;, &amp;#039;content&amp;#039;, content, &amp;#039;string, number, nil, or false&amp;#039; )&lt;br /&gt;
		else&lt;br /&gt;
			checkType( &amp;#039;tag&amp;#039;, 3, content, &amp;#039;string, number, nil, or false&amp;#039; )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return table.concat( ret )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function mwtext.unstrip( s )&lt;br /&gt;
	return php.unstrip( s )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function mwtext.unstripNoWiki( s )&lt;br /&gt;
	return php.unstripNoWiki( s )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function mwtext.killMarkers( s )&lt;br /&gt;
	return php.killMarkers( s )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function mwtext.split( text, pattern, plain )&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for m in mwtext.gsplit( text, pattern, plain ) do&lt;br /&gt;
		ret[#ret+1] = m&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function mwtext.gsplit( text, pattern, plain )&lt;br /&gt;
	local s, l = 1, mw.ustring.len( text )&lt;br /&gt;
	return function ()&lt;br /&gt;
		if s then&lt;br /&gt;
			local e, n = mw.ustring.find( text, pattern, s, plain )&lt;br /&gt;
			local ret&lt;br /&gt;
			if not e then&lt;br /&gt;
				ret = mw.ustring.sub( text, s )&lt;br /&gt;
				s = nil&lt;br /&gt;
			elseif n &amp;lt; e then&lt;br /&gt;
				-- Empty separator!&lt;br /&gt;
				ret = mw.ustring.sub( text, s, e )&lt;br /&gt;
				if e &amp;lt; l then&lt;br /&gt;
					s = e + 1&lt;br /&gt;
				else&lt;br /&gt;
					s = nil&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				ret = e &amp;gt; s and mw.ustring.sub( text, s, e - 1 ) or &amp;#039;&amp;#039;&lt;br /&gt;
				s = n + 1&lt;br /&gt;
			end&lt;br /&gt;
			return ret&lt;br /&gt;
		end&lt;br /&gt;
	end, nil, nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function mwtext.listToText( list, separator, conjunction )&lt;br /&gt;
	separator = separator or options.comma&lt;br /&gt;
	conjunction = conjunction or options[&amp;#039;and&amp;#039;]&lt;br /&gt;
	local n = #list&lt;br /&gt;
&lt;br /&gt;
	local ret&lt;br /&gt;
	if n &amp;gt; 1 then&lt;br /&gt;
		ret = table.concat( list, separator, 1, n - 1 ) .. conjunction .. list[n]&lt;br /&gt;
	else&lt;br /&gt;
		ret = tostring( list[1] or &amp;#039;&amp;#039; )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function mwtext.truncate( text, length, ellipsis, adjustLength )&lt;br /&gt;
	local l = mw.ustring.len( text )&lt;br /&gt;
	if l &amp;lt;= math.abs( length ) then&lt;br /&gt;
		return text&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	ellipsis = ellipsis or options.ellipsis&lt;br /&gt;
	local elen = 0&lt;br /&gt;
	if adjustLength then&lt;br /&gt;
		elen = mw.ustring.len( ellipsis )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local ret&lt;br /&gt;
	if math.abs( length ) &amp;lt;= elen then&lt;br /&gt;
		ret = ellipsis&lt;br /&gt;
	elseif length &amp;gt; 0 then&lt;br /&gt;
		ret = mw.ustring.sub( text, 1, length - elen ) .. ellipsis&lt;br /&gt;
	else&lt;br /&gt;
		ret = ellipsis .. mw.ustring.sub( text, length + elen )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if mw.ustring.len( ret ) &amp;lt; l then&lt;br /&gt;
		return ret&lt;br /&gt;
	else&lt;br /&gt;
		return text&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Check for stuff that can&amp;#039;t even be passed to PHP properly and other stuff&lt;br /&gt;
-- that gives different error messages in different versions of PHP&lt;br /&gt;
local function checkForJsonEncode( t, seen, lvl )&lt;br /&gt;
	local tp = type( t )&lt;br /&gt;
	if tp == &amp;#039;table&amp;#039; then&lt;br /&gt;
		if seen[t] then&lt;br /&gt;
			error( &amp;quot;TextUtil.jsonEncode: Cannot use recursive tables&amp;quot;, lvl )&lt;br /&gt;
		end&lt;br /&gt;
		seen[t] = 1&lt;br /&gt;
		for k, v in pairs( t ) do&lt;br /&gt;
			if type( k ) == &amp;#039;number&amp;#039; then&lt;br /&gt;
				if k &amp;gt;= math.huge or k &amp;lt;= -math.huge then&lt;br /&gt;
					error( string.format( &amp;quot;TextUtil.jsonEncode: Cannot use &amp;#039;inf&amp;#039; as a table key&amp;quot;, type( k ) ), lvl )&lt;br /&gt;
				end&lt;br /&gt;
			elseif type( k ) ~= &amp;#039;string&amp;#039; then&lt;br /&gt;
				error( string.format( &amp;quot;TextUtil.jsonEncode: Cannot use type &amp;#039;%s&amp;#039; as a table key&amp;quot;, type( k ) ), lvl )&lt;br /&gt;
			end&lt;br /&gt;
			checkForJsonEncode( v, seen, lvl + 1 )&lt;br /&gt;
		end&lt;br /&gt;
		seen[t] = nil&lt;br /&gt;
	elseif tp == &amp;#039;number&amp;#039; then&lt;br /&gt;
		if t ~= t or t &amp;gt;= math.huge or t &amp;lt;= -math.huge then&lt;br /&gt;
			error( &amp;quot;TextUtil.jsonEncode: Cannot encode non-finite numbers&amp;quot;, lvl )&lt;br /&gt;
		end&lt;br /&gt;
	elseif tp ~= &amp;#039;boolean&amp;#039; and tp ~= &amp;#039;string&amp;#039; and tp ~= &amp;#039;nil&amp;#039; then&lt;br /&gt;
		error( string.format( &amp;quot;TextUtil.jsonEncode: Cannot encode type &amp;#039;%s&amp;#039;&amp;quot;, tp ), lvl )&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function mwtext.jsonEncode( value, flags )&lt;br /&gt;
	checkForJsonEncode( value, {}, 3 )&lt;br /&gt;
	return php.jsonEncode( value, flags )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function mwtext.jsonDecode( json, flags )&lt;br /&gt;
	return php.jsonDecode( json, flags )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Matches PHP Scribunto_LuaTextLibrary constants&lt;br /&gt;
mwtext.JSON_PRESERVE_KEYS = 1&lt;br /&gt;
mwtext.JSON_TRY_FIXING = 2&lt;br /&gt;
mwtext.JSON_PRETTY = 4&lt;br /&gt;
&lt;br /&gt;
return mwtext&lt;/div&gt;</summary>
		<author><name>&gt;FnControlOption</name></author>
	</entry>
</feed>