function replace(str, opt_withCommentsOrParams, opt_content, opt_snakeskin) {
	symbols = symbols || Escaper.symbols || 'a-z';
	snakeskinRgxp = snakeskinRgxp || Escaper.snakeskinRgxp || new RegExp('[!$' + symbols + '_]', 'i');

	var _Escaper = Escaper,
	    cache = _Escaper.cache,
	    content = _Escaper.content;


	var isObj = Boolean(opt_withCommentsOrParams && objMap[typeof opt_withCommentsOrParams === 'undefined' ? 'undefined' : _typeof(opt_withCommentsOrParams)]);

	var p = isObj ? Object(opt_withCommentsOrParams) : {};

	function mark(pos) {
		if (p['@label']) {
			return p['@label'].replace(posRgxp, pos);
		}

		return '__ESCAPER_QUOT__' + pos + '_';
	}

	var withComments = false;
	if (typeof opt_withCommentsOrParams === 'boolean') {
		withComments = Boolean(opt_withCommentsOrParams);
	}

	if ('@comments' in p) {
		mix(multComments, p, p['@comments']);
		mix(singleComments, p, p['@comments']);
		delete p['@comments'];
	}

	if ('@strings' in p) {
		mix(stringLiterals, p, p['@strings']);
		delete p['@strings'];
	}

	if ('@literals' in p) {
		mix(literals, p, p['@literals']);
		delete p['@literals'];
	}

	if ('@all' in p) {
		mix(finalMap, p, p['@all']);
		delete p['@all'];
	}

	var cacheKey = '';
	for (var i = -1; ++i < keyArr.length;) {
		var el = keyArr[i];

		if (multComments[el] || singleComments[el]) {
			p[el] = withComments || p[el];
		} else {
			p[el] = p[el] || !isObj;
		}

		cacheKey += p[el] + ',';
	}

	var initStr = str,
	    stack = opt_content || content;

	if (stack === content && cache[cacheKey] && cache[cacheKey][initStr]) {
		return cache[cacheKey][initStr];
	}

	var begin = false,
	    end = true;

	var escape = false,
	    comment = false;

	var selectionStart = 0,
	    block = false;

	var templateVar = 0,
	    filterStart = false;

	var cut = void 0,
	    label = void 0;

	var part = '',
	    rPart = '';

	for (var _i = -1; ++_i < str.length;) {
		var _el = str.charAt(_i);

		var next = str.charAt(_i + 1),
		    word = str.substr(_i, 2),
		    extWord = str.substr(_i, 3);

		if (!comment) {
			if (!begin) {
				if (_el === '/') {
					if (singleComments[word] || multComments[word]) {
						if (singleComments[extWord] || multComments[extWord]) {
							comment = extWord;
						} else {
							comment = word;
						}
					}

					if (comment) {
						selectionStart = _i;
						continue;
					}
				}

				if (escapeEndMap[_el] || escapeEndWordMap[rPart]) {
					end = true;
					rPart = '';
				} else if (uSRgxp.test(_el)) {
					end = false;
				}

				if (wRgxp.test(_el)) {
					part += _el;
				} else {
					rPart = part;
					part = '';
				}

				var skip = false;
				if (opt_snakeskin) {
					if (_el === '|' && snakeskinRgxp.test(next)) {
						filterStart = true;
						end = false;
						skip = true;
					} else if (filterStart && sRgxp.test(_el)) {
						filterStart = false;
						end = true;
						skip = true;
					}
				}

				if (!skip) {
					if (escapeEndMap[_el]) {
						end = true;
					} else if (uSRgxp.test(_el)) {
						end = false;
					}
				}
			}

			// [] inside RegExp
			if (begin === '/' && !escape) {
				if (_el === '[') {
					block = true;
				} else if (_el === ']') {
					block = false;
				}
			}

			if (!begin && templateVar) {
				if (_el === '}') {
					templateVar--;
				} else if (_el === '{') {
					templateVar++;
				}

				if (!templateVar) {
					_el = '`';
				}
			}

			if (begin === '`' && !escape && word === '${') {
				_el = '`';
				_i++;
				templateVar++;
			}

			if (finalMap[_el] && (_el !== '/' || end) && !begin) {
				begin = _el;
				selectionStart = _i;
			} else if (begin && (_el === '\\' || escape)) {
				escape = !escape;
			} else if (finalMap[_el] && begin === _el && !escape && (begin !== '/' || !block)) {
				if (_el === '/') {
					for (var j = -1; ++j < rgxpFlags.length;) {
						if (rgxpFlagsMap[str.charAt(_i + 1)]) {
							_i++;
						}
					}
				}

				begin = false;
				end = false;

				if (p[_el]) {
					cut = str.substring(selectionStart, _i + 1);

					if (p[_el] === -1) {
						label = '';
					} else {
						label = mark(stack.length);
						stack.push(cut);
					}

					str = str.substring(0, selectionStart) + label + str.substring(_i + 1);
					_i += label.length - cut.length;
				}
			}
		} else if (nRgxp.test(next) && singleComments[comment] || multComments[_el + str.charAt(_i - 1)] && _i - selectionStart > 2 && multComments[comment]) {
			if (p[comment]) {
				cut = str.substring(selectionStart, _i + 1);

				if (p[comment] === -1) {
					label = '';
				} else {
					label = mark(stack.length);
					stack.push(cut);
				}

				str = str.substring(0, selectionStart) + label + str.substring(_i + 1);
				_i += label.length - cut.length;
			}

			comment = false;
		}
	}

	if (stack === content) {
		cache[cacheKey] = cache[cacheKey] || {};
		cache[cacheKey][initStr] = str;
	}

	return str;
}
Replaces all found blocks ' ... ', " ... ", ` ... `, / ... /, // ..., /* ... *\/ to
__ESCAPER_QUOT__number_ in a string and returns a new string

@param {string} str - source string
@param {(Object<string, boolean>|boolean)=} [opt_withCommentsOrParams=false] - parameters:

    (if a parameter value is set to -1, then all found matches will be removed from the final string,
         or if the value will be set to true/false they will be included/excluded)

    *) @label    - template for replacement, e.g. __ESCAPER_QUOT__${pos}_
    *) @all      - replaces all found matches
    *) @comments - replaces all kinds of comments
    *) @strings  - replaces all kinds of string literals
    *) @literals - replaces all kinds of string literals and regular expressions
    *) `
    *) '
    *) "
    *) /
    *) //
    *) //*
    *) //!
    *) //#
    *) //@
    *) //$
    *) /*
    *) /**
    *) /*!
    *) /*#
    *) /*@
    *) /*$

    OR if the value is boolean, then will be replaced all found comments (true) / literals (false)

@param {Array=} [opt_content=Escaper.content] - array for matches
@param {?boolean=} [opt_snakeskin] - private parameter for using with Snakeskin
@return {string}