public static string EscapeString()

in AjaxMinDll/JavaScript/OutputVisitor.cs [4269:4465]


        public static string EscapeString(string text)
        {
            // the quote factor is a calculation based on the relative number of
            // double-quotes in the string in relation to single-quotes. If the factor is
            // less than zero, then there are more double-quotes than single-quotes and
            // we can save bytes by using single-quotes as the delimiter. If it's greater
            // than zero, then there are more single quotes than double-quotes and we should
            // use double-quotes for the delimiter. If it's exactly zero, then 
            // there are exactly the same number, so it doesn't matter which delimiter
            // we use. In that case, use double-quotes because I think it's easier to read.
            // More like other languages (C/C++, C#, Java) that way.
            var delimiter = QuoteFactor(text) < 0 ? "\'" : "\"";

            // we also don't want to build a new string builder object if we don't have to.
            // and we only need to if we end up escaping characters. 
            var rawStart = 0;
            string escapedText = string.Empty;
            StringBuilder sb = null;
            try
            {
                if (!string.IsNullOrEmpty(text))
                {
                    // check each character of the string
                    for (var index = 0; index < text.Length; ++index)
                    {
                        var ch = text[index];
                        switch (ch)
                        {
                            case '\'':
                            case '"':
                                // we only need to escape whichever one we chose as our delimiter
                                if (ch == delimiter[0])
                                {
                                    // need to escape instances of the delimiter character
                                    goto case '\\';
                                }

                                break;

                            case '\b':
                                // output "\b"
                                ch = 'b';
                                goto case '\\';

                            case '\t':
                                // output "\t"
                                ch = 't';
                                goto case '\\';

                            case '\n':
                                // output "\n"
                                ch = 'n';
                                goto case '\\';

                            case '\v':
                                // w3c-strict can encode this character as a \v escape. 
                                // BUT... IE<9 doesn't recognize that escape sequence,
                                // so encode is as hex for maximum compatibility.
                                // if the source actually had "\v" in it, it wouldn't been
                                // marked as having issues and not get encoded anyway.
                                goto default;

                            case '\f':
                                // output "\f"
                                ch = 'f';
                                goto case '\\';

                            case '\r':
                                // output "\r"
                                ch = 'r';
                                goto case '\\';

                            case '\\':
                                // we need to output an escape, so create the string builder
                                // if we haven't already
                                if (sb == null)
                                {
                                    sb = StringBuilderPool.Acquire();
                                }

                                // output the block of raw characters we have since the last time
                                if (rawStart < index)
                                {
                                    sb.Append(text, rawStart, index - rawStart);
                                }

                                // set raw start to the next character
                                rawStart = index + 1;

                                // output the escape character, then the escaped character
                                sb.Append('\\');
                                sb.Append(ch);
                                break;

                            case '\x2028':
                            case '\x2029':
                                // issue #14398 - unescaped, these characters (Unicode LineSeparator and ParagraphSeparator)
                                // would introduce a line-break in the string.  they ALWAYS need to be escaped, 
                                // no matter what output encoding we may use.
                                if (sb == null)
                                {
                                    sb = StringBuilderPool.Acquire();
                                }

                                // output the block of raw characters we have since the last time
                                if (rawStart < index)
                                {
                                    sb.Append(text.Substring(rawStart, index - rawStart));
                                }

                                // set raw start to the next character
                                rawStart = index + 1;

                                // output the escape character, a "u", then the four-digit escaped character
                                sb.Append(@"\u");
                                sb.Append(((int)ch).ToStringInvariant("x4"));
                                break;

                            default:
                                if (ch < ' ')
                                {
                                    // need to escape control codes that aren't handled
                                    // by the single-letter escape codes
                                    // create the string builder if we haven't already
                                    if (sb == null)
                                    {
                                        sb = StringBuilderPool.Acquire();
                                    }

                                    // output the block of raw characters we have since the last time
                                    if (rawStart < index)
                                    {
                                        sb.Append(text, rawStart, index - rawStart);
                                    }

                                    // set raw start to the next character
                                    rawStart = index + 1;

                                    // strict ECMA-262 does not support octal escapes, but octal will
                                    // crunch down a full character more here than hexadecimal. Plus, if we do
                                    // octal, we'll still need to escape these characters to hex for RexExp
                                    // constructor strings so they don't get confused with back references.
                                    // minifies smaller, but octal is too much trouble.
                                    int intValue = ch;
                                    //if (noOctalEscapes)
                                    {
                                        // output the hex escape sequence
                                        sb.Append(@"\x");
                                        sb.Append(intValue.ToStringInvariant("x2"));
                                    }
                                    //else
                                    //{
                                    //    // octal representation of 0 through 31 are \0 through \37
                                    //    sb.Append('\\');
                                    //    if (intValue < 8)
                                    //    {
                                    //        // single octal digit
                                    //        sb.Append(intValue.ToStringInvariant());
                                    //    }
                                    //    else
                                    //    {
                                    //        // two octal digits
                                    //        sb.Append((intValue / 8).ToStringInvariant());
                                    //        sb.Append((intValue % 8).ToStringInvariant());
                                    //    }
                                    //}
                                }

                                break;
                        }
                    }

                    if (sb != null)
                    {
                        // we had escapes; use the string builder
                        // but first make sure the last batch of raw text is output
                        if (rawStart < text.Length)
                        {
                            sb.Append(text.Substring(rawStart));
                        }

                        escapedText = sb.ToString();
                    }
                    else
                    {
                        // no escaped needed; just use the text as-is
                        escapedText = text;
                    }
                }
            }
            finally
            {
                sb.Release();
            }

            return delimiter + escapedText + delimiter;
        }