HTML Entities

var
HTMLEntities        = {}
HTMLEntities.Encode = HTMLEntitiesEncode
HTMLEntities.Decode = DecodeHTMLEntities

Encode

/*
 *	The following implementations were copied from the following opensource implementations:
 *	
 *	http://locutus.io/php/strings/htmlentities/
 *	http://locutus.io/php/strings/get_html_translation_table/index.html
 */

function HTMLEntitiesEncode( string, quoteStyle, charset, doubleEncode )
{
	//  discuss at: http://locutus.io/php/htmlentities/
	// original by: Kevin van Zonneveld (http://kvz.io)
	//  revised by: Kevin van Zonneveld (http://kvz.io)
	//  revised by: Kevin van Zonneveld (http://kvz.io)
	// improved by: nobbler
	// improved by: Jack
	// improved by: RafaƂ Kukawski (http://blog.kukawski.pl)
	// improved by: Dj (http://locutus.io/php/htmlentities:425#comment_134018)
	// bugfixed by: Onno Marsman (https://twitter.com/onnomarsman)
	// bugfixed by: Brett Zamir (http://brett-zamir.me)
	//    input by: Ratheous
	//      note 1: function is compatible with PHP 5.2 and older
	//   example 1: htmlentities('Kevin & van Zonneveld')
	//   returns 1: 'Kevin & van Zonneveld'
	//   example 2: htmlentities("foo'bar","ENT_QUOTES")
	//   returns 2: 'foo'bar'

	var hashMap = HTMLEntitiesEncode.GetHTMLTranslationTable( 'HTML_ENTITIES', quoteStyle )

	string = string === null ? '' : string + ''

	if ( !hashMap )
	{
		return false
	}

	if ( quoteStyle && quoteStyle === 'ENT_QUOTES' )
	{
		hashMap["'"] = '''
	}

	doubleEncode = doubleEncode === null || !!doubleEncode

	var regex = new RegExp('&(?:#\\d+|#x[\\da-f]+|[a-zA-Z][\\da-z]*);|[' + Object.keys(hashMap).join('').replace(/([()[\]{}\-.*+?^$|\/\\])/g, '\\$1') + ']','g')

	return string.replace( regex,
		function ( ent )
		{
			if ( ent.length > 1 )
			{
				return doubleEncode ? hashMap['&'] + ent.substr(1) : ent
			}

			return hashMap[ent]
		}
	)
}

Decode

function DecodeHTMLEntities( htmlEncodedString )
{
	var ret = htmlEncodedString;

	if ( "string" == typeof htmlEncodedString )
	{
		var bits = htmlEncodedString.split( '&' );
		var n    = bits.length;

		if ( 1 < n )
		{
			for ( var i=0; i < n; i++ )
			{
				var s = bits[i].indexOf( ";" );

				if ( -1 != s )
				{
					var bit = bits[i];
					var bob = bit.substring( 0, s + 1 );

					switch ( bob )
					{
					case "amp;":
						bits[i] = "&"  + bit.substring( s + 1, bit.length );
						break;
						
					case "quot;":
						bits[i] = "\"" + bit.substring( s + 1, bit.length );
						break;

					case "rsquo;":
						bits[i] = "\'" + bit.substring( s + 1, bit.length );
						break;
						
					case "apos;":
						bits[i] = "\'" + bit.substring( s + 1, bit.length );
						break;
						
					case "lt;":
						bits[i] = "<"  + bit.substring( s + 1, bit.length );
						break;
						
					case "gt;":
						bits[i] = ">"  + bit.substring( s + 1, bit.length );
						break;

					default:
						bits[i] = DecodeHTMLEntities.DecodeEntity( bob ) + bit.substring( s + 1, bit.length );
					}
				}
			}
			ret = bits.join( "" );
		}
	}

	return ret;
}

Helper functions

HTMLEntitiesEncode.GetHTMLTranslationTable
=
function( table, quoteStyle )
{
	// eslint-disable-line camelcase
	//  discuss at: http://locutus.io/php/get_html_translation_table/
	// original by: Philip Peterson
	//  revised by: Kevin van Zonneveld (http://kvz.io)
	// bugfixed by: noname
	// bugfixed by: Alex
	// bugfixed by: Marco
	// bugfixed by: madipta
	// bugfixed by: Brett Zamir (http://brett-zamir.me)
	// bugfixed by: T.Wild
	// improved by: KELAN
	// improved by: Brett Zamir (http://brett-zamir.me)
	//    input by: Frank Forte
	//    input by: Ratheous
	//      note 1: It has been decided that we're not going to add global
	//      note 1: dependencies to Locutus, meaning the constants are not
	//      note 1: real constants, but strings instead. Integers are also supported if someone
	//      note 1: chooses to create the constants themselves.
	//   example 1: get_html_translation_table('HTML_SPECIALCHARS')
	//   returns 1: {'"': '"', '&': '&', '<': '<', '>': '>'}

	var entities = {}
	var hashMap = {}
	var decimal
	var constMappingTable = {}
	var constMappingQuoteStyle = {}
	var useTable = {}
	var useQuoteStyle = {}

	// Translate arguments
	constMappingTable[0] = 'HTML_SPECIALCHARS'
	constMappingTable[1] = 'HTML_ENTITIES'
	constMappingQuoteStyle[0] = 'ENT_NOQUOTES'
	constMappingQuoteStyle[2] = 'ENT_COMPAT'
	constMappingQuoteStyle[3] = 'ENT_QUOTES'

	useTable = !isNaN(table)
	? constMappingTable[table]
	: table
	  ? table.toUpperCase()
	  : 'HTML_SPECIALCHARS'

	useQuoteStyle = !isNaN(quoteStyle)
	? constMappingQuoteStyle[quoteStyle]
	: quoteStyle
	  ? quoteStyle.toUpperCase()
	  : 'ENT_COMPAT'

	if (useTable !== 'HTML_SPECIALCHARS' && useTable !== 'HTML_ENTITIES') {
	throw new Error('Table: ' + useTable + ' not supported')
	}

	entities['38'] = '&'
	if (useTable === 'HTML_ENTITIES')
	{
		entities['160'] = ' '
		entities['161'] = '¡'
		entities['162'] = '¢'
		entities['163'] = '£'
		entities['164'] = '¤'
		entities['165'] = '¥'
		entities['166'] = '¦'
		entities['167'] = '§'
		entities['168'] = '¨'
		entities['169'] = '©'
		entities['170'] = 'ª'
		entities['171'] = '«'
		entities['172'] = '¬'
		entities['173'] = '­'
		entities['174'] = '®'
		entities['175'] = '¯'
		entities['176'] = '°'
		entities['177'] = '±'
		entities['178'] = '²'
		entities['179'] = '³'
		entities['180'] = '´'
		entities['181'] = 'µ'
		entities['182'] = '¶'
		entities['183'] = '·'
		entities['184'] = '¸'
		entities['185'] = '¹'
		entities['186'] = 'º'
		entities['187'] = '»'
		entities['188'] = '¼'
		entities['189'] = '½'
		entities['190'] = '¾'
		entities['191'] = '¿'
		entities['192'] = 'À'
		entities['193'] = 'Á'
		entities['194'] = 'Â'
		entities['195'] = 'Ã'
		entities['196'] = 'Ä'
		entities['197'] = 'Å'
		entities['198'] = 'Æ'
		entities['199'] = 'Ç'
		entities['200'] = 'È'
		entities['201'] = 'É'
		entities['202'] = 'Ê'
		entities['203'] = 'Ë'
		entities['204'] = 'Ì'
		entities['205'] = 'Í'
		entities['206'] = 'Î'
		entities['207'] = 'Ï'
		entities['208'] = 'Ð'
		entities['209'] = 'Ñ'
		entities['210'] = 'Ò'
		entities['211'] = 'Ó'
		entities['212'] = 'Ô'
		entities['213'] = 'Õ'
		entities['214'] = 'Ö'
		entities['215'] = '×'
		entities['216'] = 'Ø'
		entities['217'] = 'Ù'
		entities['218'] = 'Ú'
		entities['219'] = 'Û'
		entities['220'] = 'Ü'
		entities['221'] = 'Ý'
		entities['222'] = 'Þ'
		entities['223'] = 'ß'
		entities['224'] = 'à'
		entities['225'] = 'á'
		entities['226'] = 'â'
		entities['227'] = 'ã'
		entities['228'] = 'ä'
		entities['229'] = 'å'
		entities['230'] = 'æ'
		entities['231'] = 'ç'
		entities['232'] = 'è'
		entities['233'] = 'é'
		entities['234'] = 'ê'
		entities['235'] = 'ë'
		entities['236'] = 'ì'
		entities['237'] = 'í'
		entities['238'] = 'î'
		entities['239'] = 'ï'
		entities['240'] = 'ð'
		entities['241'] = 'ñ'
		entities['242'] = 'ò'
		entities['243'] = 'ó'
		entities['244'] = 'ô'
		entities['245'] = 'õ'
		entities['246'] = 'ö'
		entities['247'] = '÷'
		entities['248'] = 'ø'
		entities['249'] = 'ù'
		entities['250'] = 'ú'
		entities['251'] = 'û'
		entities['252'] = 'ü'
		entities['253'] = 'ý'
		entities['254'] = 'þ'
		entities['255'] = 'ÿ'
	}

	if (useQuoteStyle !== 'ENT_NOQUOTES')
	{
		entities['34'] = '"'
	}

	if (useQuoteStyle === 'ENT_QUOTES')
	{
		entities['39'] = '''
	}
	entities['60'] = '<'
	entities['62'] = '>'

	// ascii decimals to real symbols
	for ( const decimal in entities)
	{
		if (entities.hasOwnProperty(decimal))
		{
			hashMap[String.fromCharCode(decimal)] = entities[decimal]
		}
	}

	return hashMap
}
DecodeHTMLEntities.DecodeEntity
=
function( entity )
{
	var ret = entity;

	if ( 0 == entity.indexOf( "#" ) )
	{
		var entity2 = entity.substring( 1, entity.length );
		var e       = entity2.indexOf( ";" );
	
		if ( (entity2.length - 1) == e )
		{
			var entity3 = entity2.substring( 0, entity2.length - 1 );
			
			var dec = parseInt( entity3 );
			
			if ( NaN !== dec )
			{
				ret = String.fromCharCode( dec );
			}
		}
	}
	
	return ret;
}