Ext.ns("Terrasoft.utils.string");

/**
 * @singleton
 */

/**
 * Empty string literal.
 * @type {String}
 */
Terrasoft.utils.string.emptyString = "";

/**
 * Alias for {@link Terrasoft.utils.string#emptyString}
 * @member Terrasoft
 * @inheritdoc Terrasoft.utils.string#emptyString
 */
Terrasoft.emptyString = Terrasoft.utils.string.emptyString;

/**
 * Decodes special characters of HTML-markup.
 * @param {String} value String to decode.
 * @return {String} Decoded value.
 */
Terrasoft.utils.string.decodeHtml = function (value) {
	return Ext.util.Format.htmlDecode(value);
};

/**
 * Alias for {@link Terrasoft.utils.string#decodeHtml}
 * @member Terrasoft
 * @method decodeHtml
 * @inheritdoc Terrasoft.utils.string#decodeHtml
 */
Terrasoft.decodeHtml = Terrasoft.utils.string.decodeHtml;

/**
 * Encodes special characters of HTML-markup.
 * @param {String} value String to encode.
 * @return {String} Encoded value.
 */
Terrasoft.utils.string.encodeHtml = function (value) {
	return Ext.util.Format.htmlEncode(value);
};

/**
 * Alias for {@link Terrasoft.utils.string#encodeHtml}
 * @member Terrasoft
 * @method encodeHtml
 * @inheritdoc Terrasoft.utils.string#encodeHtml
 */
Terrasoft.encodeHtml = Terrasoft.utils.string.encodeHtml;

/**
 * Replaces mnemonic symbols of HTML-markup.
 * @param {String} value String to replace.
 * @return {String} Encoded value.
 */
Terrasoft.utils.string.decodeHtmlEntities = function (value) {
	if (!Ext.isString(value) || value === "") {
		return value;
	}
	var element = document.createElement("textarea");
	element.innerHTML = value.replace(/</g, "&lt;").replace(/>/g, "&gt;");
	var result = element.value;
	element = null;
	return result;
};

/**
 * Alias for {@link Terrasoft.utils.string#decodeHtmlEntities}
 * @member Terrasoft
 * @method decodeHtmlEntities
 * @inheritdoc Terrasoft.utils.string#decodeHtmlEntities
 */
Terrasoft.decodeHtmlEntities = Terrasoft.utils.string.decodeHtmlEntities;

/**
 * Strips all HTML tags from text.
 * @param {Object} value The text with tags.
 * @return {String} The text without tags.
 */
Terrasoft.utils.string.stripTags = function (value) {
	return Ext.util.Format.stripTags(value);
};

/**
 * Alias for {@link Terrasoft.utils.string#stripTags}
 * @member Terrasoft
 * @method stripTags
 * @inheritdoc Terrasoft.utils.string#stripTags
 */
Terrasoft.stripTags = Terrasoft.utils.string.stripTags;

/**
 * Replaces html spec symbols for normal symbols.
 * @param {String} value The text with html spec symbols.
 * @return {String} The text with replaced symbols.
 */
Terrasoft.utils.string.unescape = function (value) {
	return _.unescape(value);
};

/**
 * Alias for {@link Terrasoft.utils.string#unescape}
 * @member Terrasoft
 * @method unescape
 * @inheritdoc Terrasoft.utils.string#unescape
 */
Terrasoft.unescape = Terrasoft.utils.string.unescape;

/**
 * Performs parametrized replace in string.
 * Example:
 * getFormattedString('some {0} text {1}', 'good', 'allowed')
 * Result:
 * 'some good text allowed'
 * @param {String} string String to format.
 * @return {String} Formatted string.
 */
Terrasoft.getFormattedString = function (string) {
	var args = Array.prototype.slice.call(arguments, 1);
	var searchRegExp = /\{(\d*)\}/ig;
	if (string === undefined) {
		throw new Error("parameter string is not defined");
	}
	return string.replace(searchRegExp, function (value, index) {
		var positionIndex = parseInt(index, Terrasoft.NumeralSystem.DECIMAL);
		return args[positionIndex] || value;
	});
};

/**
 * Returns string representation of value.
 * @throws {Terrasoft.exceptions.ItemNotFoundException}
 * Throws exception {@link Terrasoft.exceptions#ItemNotFoundException} if type is unsupported.
 * @param {Number/String/Object/Boolean/Date} value Value to transform.
 * @param {Terrasoft.DataValueType} type Value datatype.
 * @param {Object} [config] String format config.
 * @return {String} Value string representation.
 */
Terrasoft.utils.string.getTypedStringValue = function (value, type, config) {
	if (!Ext.isNumber(type)) {
		return;
	}
	switch (type) {
		case Terrasoft.DataValueType.DATE:
			return Ext.isDate(value) ? Ext.Date.format(value, Terrasoft.Resources.CultureSettings.dateFormat) : "";
		case Terrasoft.DataValueType.TIME:
			return Ext.isDate(value) ? Ext.Date.format(value, Terrasoft.Resources.CultureSettings.timeFormat) : "";
		case Terrasoft.DataValueType.DATE_TIME:
			return Ext.isDate(value) ? Ext.Date.format(value, Terrasoft.Resources.CultureSettings.dateFormat + " " + Terrasoft.Resources.CultureSettings.timeFormat) : "";
		case Terrasoft.DataValueType.LOOKUP:
		case Terrasoft.DataValueType.MAPPING:
			return value ? value.displayValue : "";
		case Terrasoft.DataValueType.MONEY:
			return Terrasoft.getFormattedNumberValue(value, { type: Terrasoft.DataValueType.MONEY });
		case Terrasoft.DataValueType.FLOAT:
			var decimalPrecision = config ? config.decimalPrecision : null;
			return Terrasoft.getFormattedNumberValue(value, { decimalPrecision: decimalPrecision });
		case Terrasoft.DataValueType.INTEGER:
			return Terrasoft.getFormattedNumberValue(value, { type: Terrasoft.DataValueType.INTEGER });
		case Terrasoft.DataValueType.TEXT:
		case Terrasoft.DataValueType.SHORT_TEXT:
		case Terrasoft.DataValueType.MEDIUM_TEXT:
		case Terrasoft.DataValueType.LONG_TEXT:
		case Terrasoft.DataValueType.MAXSIZE_TEXT:
		case Terrasoft.DataValueType.GUID:
			return value;
		case Terrasoft.DataValueType.BOOLEAN:
			var result = null;
			result = value ? Terrasoft.Resources.CommonUtils.TrueStringValue : Terrasoft.Resources.CommonUtils.FalseStringValue;
			return result;
		default:
			throw new Terrasoft.exceptions.UnsupportedTypeException({
				message: type + " is unsupported type"
			});
	}
};

/**
 * Alias for {@link Terrasoft.utils.string#getTypedStringValue}
 */
Terrasoft.getTypedStringValue = Terrasoft.utils.string.getTypedStringValue;

/**
 * Creates string of given length consisting of given character.
 * Example:
 * var str = Terrasoft.utils.string.getUniformString(5, 'a') // str = 'aaaaa'
 * @param  {Number} length String length.
 * @param  {String} symbol Character to fill string.
 * @return {String} String of given length and given character.
 */
Terrasoft.utils.string.getUniformString = function (length, symbol) {
	if (length <= 0) {
		return "";
	}
	var zerosArr = new Array(length + 1);
	return zerosArr.join(symbol);
};

/**
 * Alias for {@link Terrasoft.utils.string#getUniformString}
 * @member Terrasoft
 * @method getUniformString
 * @inheritdoc Terrasoft.utils.string#getUniformString
 */
Terrasoft.getUniformString = Terrasoft.utils.string.getUniformString;

/**
 * Checks whether string is valid URL.
 * @param {String} value String representation of URL.
 * @return {Boolean} Returns true if string is valid URL.
 */
Terrasoft.utils.string.isUrl = function (value) {
	var obsoleteMessage = Ext.String.format(Terrasoft.Resources.ObsoleteMessages.ObsoleteMethodMessage, "Terrasoft.utils.isUrl", "Terrasoft.utils.uri.isUrl");
	console.log(obsoleteMessage);
	return Terrasoft.utils.uri.isUrl(value);
};

/**
 * Adds missing number of characters in the beginning of the string.
 * @param {String} value Source string.
 * @param {Number} length Required length of result string.
 * @param {String} symbol (optional) Symbol to add to string (optional).
 * @return {String} String of required length.
 */
Terrasoft.utils.string.pad = function (value, length, symbol) {
	symbol = symbol || "0";
	value = String(value);
	return value.length >= length ? value : new Array(length - value.length + 1).join(symbol) + value;
};

/**
 * Alias for {@link Terrasoft.utils.string#pad}
 * @member Terrasoft
 * @method pad
 * @inheritdoc Terrasoft.utils.string#pad
 */
Terrasoft.pad = Terrasoft.utils.string.pad;

/**
 * Performs reverse of string.
 *
 * Example:
 * var str = Terrasoft.utils.string.reverseStr('1234') // str = '4321'
 *
 * @param {String} str Source string.
 * @return {String} Reversed string.
 */
Terrasoft.utils.string.reverseStr = function (str) {
	var arr = str.split("");
	var reverseArr = arr.reverse();
	return reverseArr.join("");
};

/**
 * Alias for {@link Terrasoft.utils.string#reverseStr}
 * @member Terrasoft
 * @method reverseStr
 * @inheritdoc Terrasoft.utils.string#reverseStr
 */
Terrasoft.reverseStr = Terrasoft.utils.string.reverseStr;

/**
 * Returns copy of string transformed to lowerCamelCase.
 * @param  {String} value Source string.
 * @return {String} String transformed to lowerCamelCase.
 */
Terrasoft.utils.string.toLowerCamelCase = function (value) {
	return value.length > 0 ? value.substr(0, 1).toLowerCase() + value.substr(1) : "";
};

/**
 * Alias for {@link Terrasoft.utils.string#toLowerCamelCase}
 * @member Terrasoft
 * @method toLowerCamelCase
 * @inheritdoc Terrasoft.utils.string#toLowerCamelCase
 */
Terrasoft.toLowerCamelCase = Terrasoft.utils.string.toLowerCamelCase;

/**
 * Returns string with converted eol char to unix style.
 * @param  {String} value Source string.
 * @return {String} String converted eol char to unix style.
 */
Terrasoft.utils.string.convertEolToUnix = function (value) {
	var winEol = String.fromCharCode(13, 10);
	var unixEol = String.fromCharCode(10);
	return (value || "").replace(new RegExp(winEol, "g"), unixEol);
};

/**
 * Alias for {@link Terrasoft.utils.string#convertEolToUnix}
 * @member Terrasoft
 * @method convertEolToUnix
 * @inheritdoc Terrasoft.utils.string#convertEolToUnix
 */
Terrasoft.convertEolToUnix = Terrasoft.utils.string.convertEolToUnix;

/**
 * Checks whether string is serialized JSON object.
 * @param {String} value Value to check.
 * @param {Boolean} [checksPropertyNamesOnQuotes] Flag that indicates whether to check property names on quotes.
 * Default true.
 * @return {Boolean}
 */
Terrasoft.isJsonObject = function (value, checksPropertyNamesOnQuotes) {
	if (value == null) {
		return false;
	}
	var jsonParseFn = checksPropertyNamesOnQuotes === false ? Ext.global.JSON5.parse : Ext.JSON.decode;
	try {
		var jsonObject = jsonParseFn(value);
		return Ext.isArray(jsonObject) || Ext.isObject(jsonObject);
	} catch (e) {
		return false;
	}
};

/**
 * Alias for {@link Terrasoft#isJsonObject}
 * @member Terrasoft.utils.string
 * @method isJsonObject
 * @inheritdoc Terrasoft#isJsonObject
 */
Terrasoft.utils.string.isJsonObject = Terrasoft.isJsonObject;

/**
 * Removes html tags from string.
 * @param {String} value Source string.
 * @return {String} String without html tags.
 */
Terrasoft.utils.string.removeHtmlTags = function (value) {
	if (Ext.isString(value)) {
		value = Terrasoft.decodeHtml(value);
		value = value.replace(/<head>[\s\S]*<\/head>/, "");
		value = value.replace(/<style>[\s\S]*<\/style>/, "");
		value = value.replace(/<script>[\s\S]*<\/script>/, "");
		value = value.replace(/<noscript>[\s\S]*<\/noscript>/, "");
		value = value.replace(/<svg[\s\S]*<\/svg>/, "");
		value = value.replace(/<form[\s\S]*<\/form>/, "");
		/* jshint ignore:start */
		var regExp = /(<([\s/]*(a|o:p|xml|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdi|bdo|bgsound|blockquote|big|body|blink|br|button|canvas|caption|center|cite|code|col|colgroup|command|comment|datalist|dd|del|details|dfn|dir|div|dl|dt|em|embed|fieldset|figcaption|figure|font|form|footer|frame|frameset|h1|h2|h3|h4|h5|h6|head|header|hgroup|hr|html|i|iframe|img|input|ins|isindex|kbd|keygen|label|legend|li|link|main|map|marquee|mark|menu|meta|meter|nav|nobr|noembed|noframes|noscript|object|ol|optgroup|option|output|p|param|plaintext|pre|progress|q|rp|rt|ruby|s|samp|script|section|select|small|span|source|strike|strong|style|sub|summary|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|u|ul|var|video|wbr|xmp)(\b|\/)[^@>]*)>)/ig;
		value = value.replace(regExp, "");
		value = value.replace(/&nbsp;/g, " ");
		value = value.replace(/<![\s\S]*?>/g, "");
		value = value.replace(/<!DOCTYPE[\s\S]*?>/g, "");
		/* jshint ignore:end */
	}
	return value;
};

/**
 * Alias for {@link Terrasoft.utils.string#removeHtmlTags}
 * @member Terrasoft
 * @method removeHtmlTags
 * @inheritdoc Terrasoft.utils.string#removeHtmlTags
 */
Terrasoft.removeHtmlTags = Terrasoft.utils.string.removeHtmlTags;

/**
 * Determines whether one string may be found within another string, returning true or false as appropriate.
 * @param {String} sourceString String to search inside.
 * @param {String} searchString String to search for.
 * @return {Boolean} True if the given string is found anywhere within the search string, otherwise, false if not.
 */
Terrasoft.utils.string.includes = function (sourceString, searchString) {
	return sourceString.indexOf(searchString) !== -1;
};

/**
 * Alias for {@link Terrasoft.utils.string#includes}
 * @member Terrasoft
 * @method includes
 * @inheritdoc Terrasoft.utils.string#includes
 */
Terrasoft.includes = Terrasoft.utils.string.includes;

/**
 * Checks the string contains RTL characters.
 * @param {String} sourceString Source string.
 * @return {Boolean} True if string contains RTL characters.
 */
Terrasoft.utils.string.containsRtlChars = function (sourceString) {
	var rtlCharsPattern = /[\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]/;
	return rtlCharsPattern.test(sourceString);
};

/**
 * Alias for {@link Terrasoft.utils.string#containsRtlChars}
 * @member Terrasoft
 * @method containsRtlChars
 * @inheritdoc Terrasoft.utils.string#containsRtlChars
 */
Terrasoft.containsRtlChars = Terrasoft.utils.string.containsRtlChars;

/**
 * Gets direction of the source text.
 * @param {String} text Source text.
 * @return {String|null} Direction of the source text.
 */
Terrasoft.utils.string.getTextDirection = function (text) {
	if (!Terrasoft.getIsRtlMode() || Ext.isEmpty(text)) {
		return null;
	}
	return Terrasoft.containsRtlChars(text) ? "rtl" : "ltr";
};

/**
 * Alias for {@link Terrasoft.utils.string#getTextDirection}
 * @member Terrasoft
 * @method getTextDirection
 * @inheritdoc Terrasoft.utils.string#getTextDirection
 */
Terrasoft.getTextDirection = Terrasoft.utils.string.getTextDirection;

/**
 * Gets random string.
 * @return {String} Random string.
 */
Terrasoft.utils.string.randomString = function () {
	var randomFloat = Math.random();
	var randomString = randomFloat.toString(36);
	return randomString.substring(2);
};

/**
 * Alias for {@link Terrasoft.utils.string#randomString}
 * @member Terrasoft
 * @method randomString
 * @inheritdoc Terrasoft.utils.string#randomString
 */
Terrasoft.randomString = Terrasoft.utils.string.randomString;

/**
 * Generate new html with  safe content only, using for protect against XSS
 * @param {String} html Html to sanitize.
 * @method sanitizeHTML
 * @return {String} XSS-safe html.
 */
Terrasoft.utils.string.sanitizeHTML = function (html) {

	if (!html) {
		return "";
	}

	/* Adds a value before every matched tag
 * Use prefix = "<!--\"'-->", so that unterminated quotes aren't preventing the browser from
 * splitting a tag. Test case:
 * '<input style="foo;b:url(0);><input onclick="<input type=button onclick="too() href=;>">'
 */
	var prefix = "";

	/* Attributes should not be prefixed by these characters. This list is not complete, but will be sufficient
 * for this function.
 * (see http://www.w3.org/TR/REC-xml/#NT-NameChar) 
 */
	var att = "[^-a-z0-9:._]";
	var tag = "<[a-z]";
	var any = "(?:[^<>\"']*(?:\"[^\"]*\"|'[^']*'))*?[^<>]*";
	var etag = "(?:>|(?=<))";
	var entityEnd = "(?:;|(?!\\d))";
	var ents = {
		" ": Ext.String.format("(?:\\s|�?|&#0*32{0}|&#x0*20{1})", entityEnd, entityEnd),
		"(": Ext.String.format("(?:\\(|&#0*40{0}|&#x0*28{1})", entityEnd, entityEnd),
		")": Ext.String.format("(?:\\)|&#0*41{0}|&#x0*29{1})", entityEnd, entityEnd),
		".": Ext.String.format("(?:\\.|&#0*46{0}|&#x0*2e{1})", entityEnd, entityEnd)
	};

	/* Placeholder to avoid tricky filter-circumventing methods */
	var charMap = {};
	var s = Ext.String.format("{0}*", ents[" "]); /* Short-hand space */

	/* Important: Must be pre- and postfixed by < and >. RE matches a whole tag! */

	/**
 * @name ae
 * @description Converts a given string in a sequence of the original input and the HTML entity
 * @param {String} string  String to convert
 */
	function ae(string) {
		var allCharsLowercase = string.toLowerCase();
		if (ents[string]) {
			return ents[string];
		}
		var allCharsUppercase = string.toUpperCase();
		var reRes = "";
		for (var i = 0; i < string.length; i++) {
			var charLowercase = allCharsLowercase.charAt(i);
			if (charMap[charLowercase]) {
				reRes += charMap[charLowercase];
				continue;
			}
			var charUppercase = allCharsUppercase.charAt(i);
			var reSub = [charLowercase];
			reSub.push(Ext.String.format("&#0*{0}{1}", charLowercase.charCodeAt(0), entityEnd));
			reSub.push(Ext.String.format("&#x0*{0}{1}", charLowercase.charCodeAt(0).toString(16), entityEnd));
			if (charLowercase !== charUppercase) {
				reSub.push(Ext.String.format("&#0*{0}{1}", charUppercase.charCodeAt(0), entityEnd));
				reSub.push(Ext.String.format("&#x0*{0}{1}", charUppercase.charCodeAt(0).toString(16), entityEnd));
			}
			reSub = Ext.String.format("(?:{0})", reSub.join("|"));
			reRes += charMap[charLowercase] = reSub;
		}
		return ents[string] = reRes;
	}
	/**
 * @name by
 * @description second argument for the replace function.
 */
	function by(match, group1, group2) {
		/* Adds a data-prefix before every external pointer */
		return Ext.String.format("{0}data-{1}", group1, group2);
	}
	/**
 * @name cr
 * @description Selects a HTML element and performs a search-and-replace on attributes
 * @param {String} selector HTML substring to match
 * @param {String} attribute RegExp-escaped; HTML element attribute to match
 * @param {String} marker Optional RegExp-escaped; marks the prefix
 * @param {String} delimiter Optional RegExp escaped; non-quote delimiters
 * @param {String} end Optional RegExp-escaped; forces the match to	end before an occurence of <end> when
 * quotes are missing
 */
	function cr(selector, attribute, marker, delimiter, end) {
		if (typeof selector === "string") {
			selector = new RegExp(selector, "gi");
		}
		marker = typeof marker === "string" ? marker : "\\s*=";
		delimiter = typeof delimiter === "string" ? delimiter : "";
		end = typeof end === "string" ? end : "";
		var isEnd = end && "?";
		var re1 = new RegExp(Ext.String.format("({0})({1}{2}(?:\\s*\"[^\"{3}]*\"|\\s*'[^'{3}]*'|[^\\s{3}]+{4}){5})", att, attribute, marker, delimiter, isEnd, end), "gi");
		html = html.replace(selector, function (match) {
			return Ext.String.format("{0}{1}", prefix, match.replace(re1, by));
		});
	}

	/**
 * @name cri
 * @description Selects an attribute of a HTML element, and performs a search-and-replace on certain values
 * @param {String} selector HTML element to match
 * @param {String} attribute RegExp-escaped; HTML element attribute to match
 * @param {String} front	RegExp-escaped; attribute value, prefix to match
 * @param {String} flags Optional RegExp flags, default "gi"
 * @param {String} delimiter Optional RegExp-escaped; non-quote delimiters
 * @param {String} end Optional RegExp-escaped; forces the match to end before an occurence of <end> when quotes
 * are missing
 */
	function cri(selector, attribute, front, flags, delimiter, end) {
		if (typeof selector === "string") {
			selector = new RegExp(selector, "gi");
		}
		flags = typeof flags === "string" ? flags : "gi";
		var re1 = new RegExp("(" + att + attribute + "\\s*=)((?:\\s*\"[^\"]*\"|\\s*'[^']*'|[^\\s>]+))", "gi");
		end = typeof end === "string" ? end + ")" : ")";
		var at1 = new RegExp("(\")(" + front + "[^\"]+\")", flags);
		var at2 = new RegExp("(')(" + front + "[^']+')", flags);
		var at3 = new RegExp("()(" + front + "(?:\"[^\"]+\"|'[^']+'|(?:(?!" + delimiter + ").)+)" + end, flags);
		var handleAttr = function (match, g1, g2) {
			if (g2.charAt(0) === "\"") {
				return g1 + g2.replace(at1, by);
			}
			if (g2.charAt(0) === "'") {
				return g1 + g2.replace(at2, by);
			}
			return g1 + g2.replace(at3, by);
		};
		html = html.replace(selector, function (match) {
			return prefix + match.replace(re1, handleAttr);
		});
	}

	/* <meta http-equiv=refresh content="  ; url= " > */
	html = html.replace(new RegExp("<meta" + any + att + "http-equiv\\s*=\\s*(?:\"" + ae("refresh") + "\"" + any + etag + "|'" + ae("refresh") + "'" + any + etag + "|" + ae("refresh") + "(?:" + ae(" ") + any + etag + "|" + etag + "))", "gi"), "<!-- meta http-equiv=refresh stripped-->");

	/* Stripping all scripts */
	html = html.replace(new RegExp("<script" + any + ">\\s*//\\s*<\\[CDATA\\[[\\S\\s]*?]]>\\s*</script[^>]*>", "gi"), "<!--CDATA script-->");
	html = html.replace(/<script[\S\s]+?<\/script\s*>/gi, "<!--Non-CDATA script-->");
	cr(tag + any + att + "on[-a-z0-9:_.]+=" + any + etag, "on[-a-z0-9:_.]+"); /* Event listeners */

	//cr(tag+any+att+"href\\s*="+any+etag, "href"); /* Linked elements - disabled*/
	//cr(tag + any + att + "src\\s*=" + any + etag, "src"); /* Embedded elements  - disabled*/

	cr("<object" + any + att + "data\\s*=" + any + etag, "data"); /* <object data= > */
	cr("<applet" + any + att + "codebase\\s*=" + any + etag, "codebase"); /* <applet codebase= > */

	/* <param name=movie value= >*/
	cr("<param" + any + att + "name\\s*=\\s*(?:\"" + ae("movie") + "\"" + any + etag + "|'" + ae("movie") + "'" + any + etag + "|" + ae("movie") + "(?:" + ae(" ") + any + etag + "|" + etag + "))", "value");

	/* <style> and < style=  > url()*/
	cr(/<style[^>]*>(?:[^"']*(?:"[^"]*"|'[^']*'))*?[^'"]*(?:<\/style|$)/gi, "url", "\\s*\\(\\s*", "", "\\s*\\)");
	cri(tag + any + att + "style\\s*=" + any + etag, "style", ae("url") + s + ae("(") + s, 0, s + ae(")"), ae(")"));

	/* IE7- CSS expression() */
	cr(/<style[^>]*>(?:[^"']*(?:"[^"]*"|'[^']*'))*?[^'"]*(?:<\/style|$)/gi, "expression", "\\s*\\(\\s*", "", "\\s*\\)");
	cri(tag + any + att + "style\\s*=" + any + etag, "style", ae("expression") + s + ae("(") + s, 0, s + ae(")"), ae(")"));
	return html.replace(new RegExp("(?:" + prefix + ")+", "g"), prefix);
};

/**
 * Alias for {@link Terrasoft.utils.string#sanitizeHTML}
 * @member Terrasoft
 * @method sanitizeHTML
 * @inheritdoc Terrasoft.utils.string#sanitizeHTML
 */
Terrasoft.sanitizeHTML = Terrasoft.utils.string.sanitizeHTML;