@@ -20,7 +20,13 @@ impl ast::ComponentValue {
20
20
css. push_char ( '@' ) ;
21
21
serialize_identifier ( value. as_slice ( ) , css) ;
22
22
} ,
23
- Hash ( ref value) | IDHash ( ref value) => {
23
+ Hash ( ref value) => {
24
+ css. push_char ( '#' ) ;
25
+ for c in value. iter ( ) {
26
+ serialize_char ( c, css, /* is_identifier_start = */ false ) ;
27
+ }
28
+ } ,
29
+ IDHash ( ref value) => {
24
30
css. push_char ( '#' ) ;
25
31
serialize_identifier ( value. as_slice ( ) , css) ;
26
32
}
@@ -39,7 +45,16 @@ impl ast::ComponentValue {
39
45
} ,
40
46
Dimension ( ref value, ref unit) => {
41
47
css. push_str ( value. representation ) ;
42
- serialize_identifier ( unit. as_slice ( ) , css) ;
48
+ // Disambiguate with scientific notation.
49
+ let unit = unit. as_slice ( ) ;
50
+ if unit == "e" || unit == "E" || unit. starts_with ( "e-" ) || unit. starts_with ( "E-" ) {
51
+ css. push_str ( "\\ 65 " ) ;
52
+ for c in unit. slice_from ( 1 ) . iter ( ) {
53
+ serialize_char ( c, css, /* is_identifier_start = */ false ) ;
54
+ }
55
+ } else {
56
+ serialize_identifier ( unit, css)
57
+ }
43
58
} ,
44
59
45
60
UnicodeRange ( start, end) => {
@@ -104,32 +119,34 @@ pub fn serialize_identifier(value: &str, css: &mut ~str) {
104
119
Some ( c) => { css. push_char ( '-' ) ; c } ,
105
120
}
106
121
} ;
107
- serialize_char ( c, css, /* is_start = */ true ) ;
122
+ serialize_char ( c, css, /* is_identifier_start = */ true ) ;
108
123
for c in iter {
109
- serialize_char ( c, css, /* is_start = */ false ) ;
124
+ serialize_char ( c, css, /* is_identifier_start = */ false ) ;
110
125
}
126
+ }
111
127
112
- # [ inline ]
113
- fn serialize_char ( c : char , css : & mut ~ str , is_start : bool ) {
114
- match c {
115
- '0' .. '9' if is_start => css . push_str ( format ! ( " \\ \\ 3{} " , c ) ) ,
116
- '-' if is_start => css. push_str ( "\\ -" ) ,
117
- '0' .. '9' | 'A' .. 'Z' | 'a' .. 'z' | '_' | '-' => css. push_char ( c ) ,
118
- _ if c > '\x7F ' => css. push_char ( c) ,
119
- '\n ' => css. push_str ( " \\ A " ) ,
120
- '\r ' => css. push_str ( "\\ D " ) ,
121
- '\x0C ' => css. push_str ( "\\ C " ) ,
122
- _ => { css. push_char ( '\\' ) ; css . push_char ( c ) } ,
123
- }
128
+
129
+ # [ inline ]
130
+ fn serialize_char ( c : char , css : & mut ~ str , is_identifier_start : bool ) {
131
+ match c {
132
+ '0' .. '9' if is_identifier_start => css. push_str ( format ! ( "\\ \\ 3{} " , c ) ) ,
133
+ '-' if is_identifier_start => css. push_str ( " \\ -" ) ,
134
+ '0' .. '9' | 'A' .. 'Z' | 'a' .. 'z' | '_' | '- ' => css. push_char ( c) ,
135
+ _ if c > '\x7F ' => css. push_char ( c ) ,
136
+ '\n ' => css. push_str ( "\\ A " ) ,
137
+ '\r ' => css. push_str ( "\\ D " ) ,
138
+ '\x0C' => css. push_str ( " \\ C " ) ,
139
+ _ => { css . push_char ( '\\' ) ; css . push_char ( c ) } ,
124
140
}
125
141
}
126
142
143
+
127
144
pub fn serialize_string ( value : & str , css : & mut ~str ) {
128
145
css. push_char ( '"' ) ;
129
146
// TODO: avoid decoding/re-encoding UTF-8?
130
147
for c in value. iter ( ) {
131
148
match c {
132
- '"' => css. push_str ( "\" " ) ,
149
+ '"' => css. push_str ( "\\ \ " " ) ,
133
150
'\\' => css. push_str ( "\\ \\ " ) ,
134
151
'\n' => css. push_str ( "\\ A " ) ,
135
152
'\r' => css. push_str ( "\\ D " ) ,
@@ -163,44 +180,52 @@ impl<'self, I: Iterator<&'self ComponentValue>> ToCss for I {
163
180
match $value { $( $pattern) |+ => true , _ => false }
164
181
) ;
165
182
)
183
+ // This does not borrow-check: for component_value in self {
166
184
loop { match self . next ( ) { None => break , Some ( component_value) => {
167
- let ( _a, _b) = ( previous, component_value) ;
168
- // FIXME: this is incorrect.
169
- // See https://github.com/mozilla-servo/rust-cssparser/issues/24
170
- // if (
171
- // matches!(*a, Hash(*) | IDHash(*) | AtKeyword(*)) &&
172
- // matches!(*b, Number(*) | Percentage(*) | Ident(*) | Dimension(*) |
173
- // UnicodeRange(*) | URL(*) | Function(*))
174
- // ) || (
175
- // matches!(*a, Number(*) | Ident(*) | Dimension(*)) &&
176
- // matches!(*b, Number(*) | Ident(*) | Dimension(*))
177
- // ) || (
178
- // matches!(*a, Number(*) | Ident(*) | Dimension(*)) &&
179
- // matches!(*b, Percentage(*) | UnicodeRange(*) | URL(*) | Function(*))
180
- // ) || (
181
- // matches!(*a, Ident(*)) &&
182
- // matches!(*b, ParenthesisBlock(*))
183
- // ) || (
184
- // matches!(*a, Delim('#') | Delim('@')) &&
185
- // !matches!(*b, WhiteSpace)
186
- // ) || (
187
- // matches!(*a, Delim('-') | Delim('+') | Delim('.') | Delim('<') |
188
- // Delim('>') | Delim('!')) &&
189
- // !matches!(*b, WhiteSpace)
190
- // ) || (
191
- // !matches!(*a, WhiteSpace) &&
192
- // matches!(*b, Delim('-') | Delim('+') | Delim('.') | Delim('<') |
193
- // Delim('>') | Delim('!'))
194
- // ) || (
195
- // matches!(*a, Delim('/')) &&
196
- // matches!(*b, Delim('*'))
197
- // ) || (
198
- // matches!(*a, Delim('*')) &&
199
- // matches!(*b, Delim('/'))
200
- // ) {
201
- // css.push_str("/**/")
202
- // }
203
- component_value. to_css_push ( css) ;
185
+ let ( a, b) = ( previous, component_value) ;
186
+ if (
187
+ matches ! ( * a, Ident ( * ) | AtKeyword ( * ) | Hash ( * ) | IDHash ( * ) |
188
+ Dimension ( * ) | Delim ( '#' ) | Delim ( '-' ) | Number ( * ) ) &&
189
+ matches ! ( * b, Ident ( * ) | Function ( * ) | URL ( * ) | BadURL ( * ) |
190
+ Number ( * ) | Percentage ( * ) | Dimension ( * ) | UnicodeRange ( * ) )
191
+ ) || (
192
+ matches ! ( * a, Ident ( * ) ) &&
193
+ matches ! ( * b, ParenthesisBlock ( * ) )
194
+ ) || (
195
+ matches ! ( * a, Ident ( * ) | AtKeyword ( * ) | Hash ( * ) | IDHash ( * ) | Dimension ( * ) ) &&
196
+ matches ! ( * b, Delim ( '-' ) | CDC )
197
+ ) || (
198
+ matches ! ( * a, Delim ( '#' ) | Delim ( '-' ) | Number ( * ) | Delim ( '@' ) ) &&
199
+ matches ! ( * b, Ident ( * ) | Function ( * ) | URL ( * ) | BadURL ( * ) )
200
+ ) || (
201
+ matches ! ( * a, Delim ( '@' ) ) &&
202
+ matches ! ( * b, Ident ( * ) | Function ( * ) | URL ( * ) | BadURL ( * ) |
203
+ UnicodeRange ( * ) | Delim ( '-' ) )
204
+ ) || (
205
+ matches ! ( * a, UnicodeRange ( * ) | Delim ( '.' ) | Delim ( '+' ) ) &&
206
+ matches ! ( * b, Number ( * ) | Percentage ( * ) | Dimension ( * ) )
207
+ ) || (
208
+ matches ! ( * a, UnicodeRange ( * ) ) &&
209
+ matches ! ( * b, Ident ( * ) | Function ( * ) | Delim ( '?' ) )
210
+ ) || ( match ( a, b) { ( & Delim ( a) , & Delim ( b) ) => matches ! ( ( a, b) ,
211
+ ( '#' , '-' ) |
212
+ ( '$' , '=' ) |
213
+ ( '*' , '=' ) |
214
+ ( '^' , '=' ) |
215
+ ( '~' , '=' ) |
216
+ ( '|' , '=' ) |
217
+ ( '|' , '|' ) |
218
+ ( '/' , '*' )
219
+ ) , _ => false } ) {
220
+ css. push_str ( "/**/" )
221
+ }
222
+ // Skip whitespace when '\n' was previously written at the previous iteration.
223
+ if !matches ! ( ( previous, component_value) , ( & Delim ( '\\' ) , & WhiteSpace ) ) {
224
+ component_value. to_css_push ( css) ;
225
+ }
226
+ if component_value == & Delim ( '\\' ) {
227
+ css. push_char ( '\n' ) ;
228
+ }
204
229
previous = component_value;
205
230
} } }
206
231
}
0 commit comments