function cleanupHTML(sHtml)
{
	var iEnt=-1;
	var flagTag=false,begTag=false,flagAttr=false,begAttr=false,flagEntity=false,begEntity=false,flagLi=false,dropTag=false;
	var empty=false,unclosed=false,unquoted=false,unopened=false;
	var tag="",lastTag="",ret="",entity="",attr="";
	
	for(var x=0;x<sHtml.length;x++)
	{
		c=sHtml.charAt(x);
		
		if(begEntity)
		{
			if(c==";")
			{
				begEntity=false;
				iEnt=indexOfArray(entities,entity);
				if(iEnt>-1)flagEntity=true;
			}
			else if(c==" " || c=="#"){begEntity=false;flagEntity=false;entity="";}
			else entity+=c;
		}
		
		if(c=="&")begEntity=true;
		if(begTag)
		{
			if(c==" " || c==">")
			{
				switch(tag.toLowerCase())
				{
					case "br":
					case "img":
					case "hr":
					case "input":
					case "link":
					case "base":
					case "basefont":
					case "col":
					case "frame":
					case "isindex":
					case "meta":
					case "param":
						empty=true;
						break;
					case "li":
						if(flagLi && lastTag!="ul" && lastTag!="ol" && lastTag!="/li")unclosed=true;
						flagLi=true;
						empty=false;
						break;
					case "ol":
					case "ul":
						if(lastTag=="/li")unopened=true;
						empty=false;
						break;
					case "font":case "/font":
					case "b":case "/b":
					case "i":case "/i":
					case "u":case "/u":
					case "center":case "/center":
					case "marquee":case "/marquee":
					case "blink":case "/blink":
					case "big":case "/big":
					case "small":case "/small":
					
						dropTag=true;
						empty=false;
						break;
					default:
						empty=false;
						break;	
				}
				lastTag=tag.toLowerCase();
				tag="";
				begTag=false;
			}
			else tag+=c;
		}
		
		if(c=="<"){begTag=true;flagTag=true;}
		if(c==">" && empty){c=" />";}
		
		if(begTag)ret+=c.toLowerCase();
		
		else if(flagTag)
		{
			if(flagAttr)
			{
				if(begAttr)
				{
					if(c!="\""){ret+="\""+c;unquoted=true;begAttr=false;}
					else{ret+=c;unquoted=false;begAttr=false;}
				} 
				else if(c==" " || c==">" || c==" />")
				{
					if(unquoted)
					{
						if(sHtml.charAt(x-1)!="\""){ret+="\""+c;flagAttr=false;}
						else ret+=c;
					}
					else ret+=c;
				}
				else if(c=="\""){ret+=c;flagAttr=false;}
				else ret+=c;
				
				if(!flagAttr)
				{
					switch(attr.toLowerCase())
					{
						case "align":
						case "background":
						case "bgcolor":
						case "style":
							ret=ret.substr(0,ret.lastIndexOf(attr+"=\""));
							if(c==">" || c==" />")ret+=c;
							break;
						default:
							break;
					}	
				}
			}
			else if(c=="=")
			{
				begAttr=true;flagAttr=true;ret+=c;
				attr=ret.substr(ret.lastIndexOf(" ")+1,ret.length-(ret.lastIndexOf(" ")+2));
			}
			else ret+=c.toLowerCase();
			
			if(c==">" || c==" />")
			{
				flagTag=false;
				flagAttr=false;
				if(unclosed){ret=insertAt(ret,"</"+lastTag+">",ret.lastIndexOf("<"));unclosed=false;}
				if(unopened){ret=insertAt(ret,"<li>",ret.lastIndexOf("<"));unopened=false;}
				if(dropTag){ret=ret.substr(0,ret.lastIndexOf("<"));dropTag=false;}
			}
		}	
		else ret+=c;
		
		if(flagEntity)
		{
			ret=ret.substr(0,ret.lastIndexOf("&"))+"&#"+numEntities[iEnt]+ret.substr(ret.lastIndexOf(";"));
			entity="";
			flagEntity=false;
		}
	}
	
	//various cleanups
	
	//replacing '> <' by '><'
	var rExp=/> </gi;
	ret=ret.replace(rExp,"><");
	
	return(ret);
}
/*
HTML cleanup
- closes empty tags and add missing double-quotes (for attributes) (bad MSIE behaviours)
- closes unclosed list items (li) (MSIE again)
- converts html entities to numerical ones
- drops presentational tags and attributes

IMPORTANT NOTE:
If you really need 100% well-formed XHTML code, please add code cleanup at the server side (see i.e. HTML Tidy).
Generating well-formed XHTML with 'MSIE contentEditable' is very, very difficult (it continuously breaks the well-formed code) !
We've intensely tested this function, but we can't guarantee it will correct every error.
*/
HTML cleanup
closes empty tags and add missing double-quotes (for attributes) (bad MSIE behaviours)
closes unclosed list items (li) (MSIE again)
converts html entities to numerical ones
drops presentational tags and attributes

IMPORTANT NOTE:
If you really need 100% well-formed XHTML code, please add code cleanup at the server side .
Generating well-formed XHTML with 'MSIE contentEditable' is very, very difficult (it continuously breaks the well-formed code) .
We've intensely tested this function, but we can't guarantee it will correct every error.
HTML cleanup closes empty tags and add missing double - quotes ( for attributes ) ( bad MSIE behaviours ) closes unclosed list items ( li ) ( MSIE again ) converts html entities to numerical ones drops presentational tags and attributes IMPORTANT NOTE : If you really need 100% well - formed XHTML code please add code cleanup at the server side . Generating well - formed XHTML with ' MSIE contentEditable ' is very very difficult ( it continuously breaks the well - formed code ) . We ' ve intensely tested this function but we can ' t guarantee it will correct every error .
function cleanupHTML(sHtml)
{
	var iEnt=-1;
	var flagTag=false,begTag=false,flagAttr=false,begAttr=false,flagEntity=false,begEntity=false,flagLi=false,dropTag=false;
	var empty=false,unclosed=false,unquoted=false,unopened=false;
	var tag="",lastTag="",ret="",entity="",attr="";
	for(var x=0;x<sHtml.length;x++)
	{
		c=sHtml.charAt(x);
		if(begEntity)
		{
			if(c==";")
			{
				begEntity=false;
				iEnt=indexOfArray(entities,entity);
				if(iEnt>-1)flagEntity=true;
			}
			else if(c==" " || c=="#"){begEntity=false;flagEntity=false;entity="";}
			else entity+=c;
		}
		if(c=="&")begEntity=true;
		if(begTag)
		{
			if(c==" " || c==">")
			{
				switch(tag.toLowerCase())
				{
					case "br":
					case "img":
					case "hr":
					case "input":
					case "link":
					case "base":
					case "basefont":
					case "col":
					case "frame":
					case "isindex":
					case "meta":
					case "param":
						empty=true;
						break;
					case "li":
						if(flagLi && lastTag!="ul" && lastTag!="ol" && lastTag!="/li")unclosed=true;
						flagLi=true;
						empty=false;
						break;
					case "ol":
					case "ul":
						if(lastTag=="/li")unopened=true;
						empty=false;
						break;
					case "font":case "/font":
					case "b":case "/b":
					case "i":case "/i":
					case "u":case "/u":
					case "center":case "/center":
					case "marquee":case "/marquee":
					case "blink":case "/blink":
					case "big":case "/big":
					case "small":case "/small":
						dropTag=true;
						empty=false;
						break;
					default:
						empty=false;
						break;	
				}
				lastTag=tag.toLowerCase();
				tag="";
				begTag=false;
			}
			else tag+=c;
		}
		if(c=="<"){begTag=true;flagTag=true;}
		if(c==">" && empty){c=" />";}
		if(begTag)ret+=c.toLowerCase();
		else if(flagTag)
		{
			if(flagAttr)
			{
				if(begAttr)
				{
					if(c!="\""){ret+="\""+c;unquoted=true;begAttr=false;}
					else{ret+=c;unquoted=false;begAttr=false;}
				} 
				else if(c==" " || c==">" || c==" />")
				{
					if(unquoted)
					{
						if(sHtml.charAt(x-1)!="\""){ret+="\""+c;flagAttr=false;}
						else ret+=c;
					}
					else ret+=c;
				}
				else if(c=="\""){ret+=c;flagAttr=false;}
				else ret+=c;
				if(!flagAttr)
				{
					switch(attr.toLowerCase())
					{
						case "align":
						case "background":
						case "bgcolor":
						case "style":
							ret=ret.substr(0,ret.lastIndexOf(attr+"=\""));
							if(c==">" || c==" />")ret+=c;
							break;
						default:
							break;
					}	
				}
			}
			else if(c=="=")
			{
				begAttr=true;flagAttr=true;ret+=c;
				attr=ret.substr(ret.lastIndexOf(" ")+1,ret.length-(ret.lastIndexOf(" ")+2));
			}
			else ret+=c.toLowerCase();
			if(c==">" || c==" />")
			{
				flagTag=false;
				flagAttr=false;
				if(unclosed){ret=insertAt(ret,"</"+lastTag+">",ret.lastIndexOf("<"));unclosed=false;}
				if(unopened){ret=insertAt(ret,"<li>",ret.lastIndexOf("<"));unopened=false;}
				if(dropTag){ret=ret.substr(0,ret.lastIndexOf("<"));dropTag=false;}
			}
		}	
		else ret+=c;
		if(flagEntity)
		{
			ret=ret.substr(0,ret.lastIndexOf("&"))+"&#"+numEntities[iEnt]+ret.substr(ret.lastIndexOf(";"));
			entity="";
			flagEntity=false;
		}
	}
	var rExp=/> </gi;
	ret=ret.replace(rExp,"><");
	return(ret);
}
function cleanupHTML ( sHtml ) { var iEnt = - 1 ; var flagTag = false , begTag = false , flagAttr = false , begAttr = false , flagEntity = false , begEntity = false , flagLi = false , dropTag = false ; var empty = false , unclosed = false , unquoted = false , unopened = false ; var tag = "" , lastTag = "" , ret = "" , entity = "" , attr = "" ; for ( var x = 0 ; x < sHtml . length ; x ++ ) { c = sHtml . charAt ( x ) ; if ( begEntity ) { if ( c == ";" ) { begEntity = false ; iEnt = indexOfArray ( entities , entity ) ; if ( iEnt > - 1 ) flagEntity = true ; } else if ( c == " " || c == "#" ) { begEntity = false ; flagEntity = false ; entity = "" ; } else entity += c ; } if ( c == "&" ) begEntity = true ; if ( begTag ) { if ( c == " " || c == ">" ) { switch ( tag . toLowerCase ( ) ) { case "br" : case "img" : case "hr" : case "input" : case "link" : case "base" : case "basefont" : case "col" : case "frame" : case "isindex" : case "meta" : case "param" : empty = true ; break ; case "li" : if ( flagLi && lastTag != "ul" && lastTag != "ol" && lastTag != "/li" ) unclosed = true ; flagLi = true ; empty = false ; break ; case "ol" : case "ul" : if ( lastTag == "/li" ) unopened = true ; empty = false ; break ; case "font" : case "/font" : case "b" : case "/b" : case "i" : case "/i" : case "u" : case "/u" : case "center" : case "/center" : case "marquee" : case "/marquee" : case "blink" : case "/blink" : case "big" : case "/big" : case "small" : case "/small" : dropTag = true ; empty = false ; break ; default : empty = false ; break ; } lastTag = tag . toLowerCase ( ) ; tag = "" ; begTag = false ; } else tag += c ; } if ( c == "<" ) { begTag = true ; flagTag = true ; } if ( c == ">" && empty ) { c = " />" ; } if ( begTag ) ret += c . toLowerCase ( ) ; else if ( flagTag ) { if ( flagAttr ) { if ( begAttr ) { if ( c != "\"" ) { ret += "\"" + c ; unquoted = true ; begAttr = false ; } else { ret += c ; unquoted = false ; begAttr = false ; } } else if ( c == " " || c == ">" || c == " />" ) { if ( unquoted ) { if ( sHtml . charAt ( x - 1 ) != "\"" ) { ret += "\"" + c ; flagAttr = false ; } else ret += c ; } else ret += c ; } else if ( c == "\"" ) { ret += c ; flagAttr = false ; } else ret += c ; if ( ! flagAttr ) { switch ( attr . toLowerCase ( ) ) { case "align" : case "background" : case "bgcolor" : case "style" : ret = ret . substr ( 0 , ret . lastIndexOf ( attr + "=\"" ) ) ; if ( c == ">" || c == " />" ) ret += c ; break ; default : break ; } } } else if ( c == "=" ) { begAttr = true ; flagAttr = true ; ret += c ; attr = ret . substr ( ret . lastIndexOf ( " " ) + 1 , ret . length - ( ret . lastIndexOf ( " " ) + 2 ) ) ; } else ret += c . toLowerCase ( ) ; if ( c == ">" || c == " />" ) { flagTag = false ; flagAttr = false ; if ( unclosed ) { ret = insertAt ( ret , "</" + lastTag + ">" , ret . lastIndexOf ( "<" ) ) ; unclosed = false ; } if ( unopened ) { ret = insertAt ( ret , "<li>" , ret . lastIndexOf ( "<" ) ) ; unopened = false ; } if ( dropTag ) { ret = ret . substr ( 0 , ret . lastIndexOf ( "<" ) ) ; dropTag = false ; } } } else ret += c ; if ( flagEntity ) { ret = ret . substr ( 0 , ret . lastIndexOf ( "&" ) ) + "&#" + numEntities [ iEnt ] + ret . substr ( ret . lastIndexOf ( ";" ) ) ; entity = "" ; flagEntity = false ; } } var rExp = / > < / gi ; ret = ret . replace ( rExp , "><" ) ; return ( ret ) ; }
HTML cleanup
closes empty tags and add missing double-quotes (for attributes) (bad MSIE behaviours)
closes unclosed list items (li) (MSIE again)
converts html entities to numerical ones
drops presentational tags and attributes
HTML cleanup closes empty tags and add missing double - quotes ( for attributes ) ( bad MSIE behaviours ) closes unclosed list items ( li ) ( MSIE again ) converts html entities to numerical ones drops presentational tags and attributes
//various cleanups //replacing '> <' by '><'