public static String jsStringEnc()

in freemarker-core/src/main/java/freemarker/template/utility/StringUtil.java [1427:1548]


    public static String jsStringEnc(String s, JsStringEncCompatibility compatibility, JsStringEncQuotation quotation) {
        NullArgumentException.check("s", s);
        
        int ln = s.length();
        StringBuilder sb;
        if (quotation == null) {
            sb = null;
        } else {
            if (quotation == APOSTROPHE && compatibility.jsonCompatible) {
                throw new IllegalArgumentException("JSON compatible mode doesn't allow quotationMode=" + quotation);
            }
            sb = new StringBuilder(ln + 8);
            sb.append(quotation.getSymbol());
        }
        for (int i = 0; i < ln; i++) {
            final char c = s.charAt(i);
            final int escapeType;  // 
            if (!(c > '>' && c < 0x7F && c != '\\') && c != ' ' && !(c >= 0xA0 && c < 0x2028)) {  // skip common chars
                if (c <= 0x1F) {  // control chars range 1
                    if (c == '\n') {
                        escapeType = 'n';
                    } else if (c == '\r') {
                        escapeType = 'r';
                    } else if (c == '\f') {
                        escapeType = 'f';
                    } else if (c == '\b') {
                        escapeType = 'b';
                    } else if (c == '\t') {
                        escapeType = 't';
                    } else {
                        escapeType = ESC_HEXA;
                    }
                } else if (c == '"') {
                    escapeType = quotation == APOSTROPHE ? NO_ESC : ESC_BACKSLASH;
                } else if (c == '\'') {
                    escapeType = !compatibility.javaScriptCompatible || quotation == QUOTATION_MARK ? NO_ESC
                            : (compatibility.jsonCompatible ? ESC_HEXA : ESC_BACKSLASH);
                } else if (c == '\\') {
                    escapeType = ESC_BACKSLASH; 
                } else if (c == '/'
                        && (i == 0 && quotation == null || i != 0 && s.charAt(i - 1) == '<')) {
                    // against closing elements with "</"
                    escapeType = ESC_BACKSLASH;
                } else if (c == '>') {
                    // against "]]> and "-->"
                    final boolean dangerous;
                    if (quotation != null && i < 2) {
                        dangerous = false;
                    } else if (i == 0) {
                        dangerous = true;
                    } else {
                        final char prevC = s.charAt(i - 1);
                        if (prevC == ']' || prevC == '-') {
                            if (i == 1) {
                                dangerous = true;
                            } else {
                                final char prevPrevC = s.charAt(i - 2);
                                dangerous = prevPrevC == prevC;
                            }
                        } else {
                            dangerous = false;
                        }
                    }
                    escapeType = dangerous ? (compatibility.jsonCompatible ? ESC_HEXA : ESC_BACKSLASH) : NO_ESC;
                } else if (c == '<') {
                    // against "<!"
                    final boolean dangerous;
                    if (i == ln - 1) {
                        dangerous = quotation == null;
                    } else {
                        char nextC = s.charAt(i + 1);
                        dangerous = nextC == '!' || nextC == '?';
                    }
                    escapeType = dangerous ? ESC_HEXA : NO_ESC;
                } else if ((c >= 0x7F && c <= 0x9F)  // control chars range 2
                            || (c == 0x2028 || c == 0x2029)  // UNICODE line terminators
                            ) {
                    escapeType = ESC_HEXA;
                } else {
                    escapeType = NO_ESC;
                }
                
                if (escapeType != NO_ESC) { // If needs escaping
                    if (sb == null) {
                        sb = new StringBuilder(ln + 6);
                        sb.append(s, 0, i);
                    }
                    
                    sb.append('\\');
                    if (escapeType > 0x20) {
                        sb.append((char) escapeType);
                    } else if (escapeType == ESC_HEXA) {
                        if (!compatibility.jsonCompatible && c < 0x100) {
                            sb.append('x');
                            sb.append(toHexDigitUpperCase(c >> 4));
                            sb.append(toHexDigitUpperCase(c & 0xF));
                        } else {
                            sb.append('u');
                            int cp = c;
                            sb.append(toHexDigitUpperCase((cp >> 12) & 0xF));
                            sb.append(toHexDigitUpperCase((cp >> 8) & 0xF));
                            sb.append(toHexDigitUpperCase((cp >> 4) & 0xF));
                            sb.append(toHexDigitUpperCase(cp & 0xF));
                        }
                    } else {  // escapeType == ESC_BACKSLASH
                        sb.append(c);
                    }
                    continue; 
                }
                // Falls through when escapeType == NO_ESC 
            }
            // Needs no escaping
                
            if (sb != null) sb.append(c);
        } // for each character

        if (quotation != null) {
            sb.append(quotation.getSymbol());
        }
        
        return sb == null ? s : sb.toString();
    }