@@ -59,68 +59,96 @@ class CssPropertyNormalizer {
59
59
* @return the normalized property
60
60
*/
61
61
public static String normalize (String str ) {
62
- StringBuilder buffer = new StringBuilder ();
63
- int segmentStart = 0 ;
64
- for (int i = 0 ; i < str .length (); ++i ) {
62
+ StringBuilder sb = new StringBuilder ();
63
+ boolean isWhitespace = false ;
64
+ int i = 0 ;
65
+ while (i < str .length ()) {
65
66
if (str .charAt (i ) == '\\' ) {
67
+ sb .append (str .charAt (i ));
66
68
++i ;
67
- } else if (str .charAt (i ) == '\'' || str .charAt (i ) == '"' ) {
68
- appendAndFormatSegment (buffer , str , segmentStart , i + 1 );
69
- segmentStart = i = appendQuoteContent (buffer , str , i + 1 , str .charAt (i ));
70
- }
71
- }
72
- if (segmentStart < str .length ()) {
73
- appendAndFormatSegment (buffer , str , segmentStart , str .length ());
74
- }
75
- return buffer .toString ();
76
- }
77
-
78
- /**
79
- * Appends and formats a segment.
80
- *
81
- * @param buffer the current buffer
82
- * @param source a source
83
- * @param start where to start in the source
84
- * @param end where to end in the source
85
- */
86
- private static void appendAndFormatSegment (StringBuilder buffer , String source , int start , int end ) {
87
- String [] parts = source .substring (start , end ).split ("\\ s" );
88
- StringBuilder sb = new StringBuilder ();
89
- for (String part : parts ) {
90
- if (part .length () > 0 ) {
91
- if (sb .length () > 0 && !trimSpaceAfter (sb .charAt (sb .length () - 1 )) && !trimSpaceBefore (part .charAt (0 ))) {
92
- sb .append (" " );
69
+ if (i < str .length ()) {
70
+ sb .append (str .charAt (i ));
71
+ ++i ;
72
+ }
73
+ } else if (Character .isWhitespace (str .charAt (i ))) {
74
+ isWhitespace = true ;
75
+ ++i ;
76
+ } else {
77
+ if (isWhitespace ) {
78
+ if (sb .length () > 0 && !trimSpaceAfter (sb .charAt (sb .length () - 1 )) && !trimSpaceBefore (str .charAt (i ))) {
79
+ sb .append (" " );
80
+ }
81
+ isWhitespace = false ;
93
82
}
94
- // Do not make base64 data lowercase, function name only
95
- if (part .matches ("^[uU][rR][lL]\\ (.+\\ )" ) && CssUtils .isBase64Data (part .substring (4 , part .length () - 1 ))) {
96
- sb .append (part .substring (0 , 3 ).toLowerCase ()).append (part .substring (3 ));
83
+ if (str .charAt (i ) == '\'' || str .charAt (i ) == '"' ) {
84
+ i = appendQuotedString (sb , str , i );
85
+ } else if ((str .charAt (i ) == 'u' || str .charAt (i ) == 'U' ) && str .substring (i ).matches ("^[uU][rR][lL]\\ (.*?" )) {
86
+ sb .append (str .substring (i , i + 4 ).toLowerCase ());
87
+ i = appendUrlContent (sb , str , i + 4 );
97
88
} else {
98
- sb .append (part .toLowerCase ());
89
+ sb .append (Character .toLowerCase (str .charAt (i )));
90
+ ++i ;
99
91
}
100
92
}
101
93
}
102
- buffer . append ( sb );
94
+ return sb . toString ( );
103
95
}
104
96
105
97
/**
106
- * Appends quoted content .
98
+ * Appends quoted string .
107
99
*
108
100
* @param buffer the current buffer
109
101
* @param source a source
110
- * @param start where to start in the source
111
- * @param endQuoteSymbol the end quote symbol
102
+ * @param start where to start in the source. Should point at quote symbol.
112
103
* @return the new position in the source
113
104
*/
114
- private static int appendQuoteContent (StringBuilder buffer , String source , int start , char endQuoteSymbol ) {
115
- int end = CssUtils .findNextUnescapedChar (source , endQuoteSymbol , start );
105
+ private static int appendQuotedString (StringBuilder buffer , String source , int start ) {
106
+ char endQuoteSymbol = source .charAt (start );
107
+ int end = CssUtils .findNextUnescapedChar (source , endQuoteSymbol , start + 1 );
116
108
if (end == -1 ) {
117
109
end = source .length ();
118
110
LoggerFactory .getLogger (CssPropertyNormalizer .class ).warn (MessageFormatUtil .format (LogMessageConstant .QUOTE_IS_NOT_CLOSED_IN_CSS_EXPRESSION , source ));
111
+ } else {
112
+ ++end ;
119
113
}
120
114
buffer .append (source , start , end );
121
115
return end ;
122
116
}
123
117
118
+ /**
119
+ * Appends url content and end parenthesis if url is correct.
120
+ *
121
+ * @param buffer the current buffer
122
+ * @param source a source
123
+ * @param start where to start in the source. Should point at first symbol after "url(".
124
+ * @return the new position in the source
125
+ */
126
+ private static int appendUrlContent (StringBuilder buffer , String source , int start ) {
127
+ while (Character .isWhitespace (source .charAt (start )) && start < source .length ()) {
128
+ ++start ;
129
+ }
130
+ if (start < source .length ()) {
131
+ int curr = start ;
132
+ if (source .charAt (curr ) == '"' || source .charAt (curr ) == '\'' ) {
133
+ curr = appendQuotedString (buffer , source , curr );
134
+ return curr ;
135
+ } else {
136
+ curr = CssUtils .findNextUnescapedChar (source , ')' , curr );
137
+ if (curr == -1 ) {
138
+ LoggerFactory .getLogger (CssPropertyNormalizer .class ).warn (MessageFormatUtil .format (LogMessageConstant .URL_IS_NOT_CLOSED_IN_CSS_EXPRESSION , source ));
139
+ return source .length ();
140
+ } else {
141
+ buffer .append (source .substring (start , curr ).trim ());
142
+ buffer .append (')' );
143
+ return curr + 1 ;
144
+ }
145
+ }
146
+ } else {
147
+ LoggerFactory .getLogger (CssPropertyNormalizer .class ).warn (MessageFormatUtil .format (LogMessageConstant .URL_IS_EMPTY_IN_CSS_EXPRESSION , source ));
148
+ return source .length ();
149
+ }
150
+ }
151
+
124
152
/**
125
153
* Checks if spaces can be trimmed after a specific character.
126
154
*
0 commit comments