@@ -185,83 +185,105 @@ export function clean_nodes(
185
185
}
186
186
}
187
187
188
- if ( preserve_whitespace ) {
189
- return { hoisted, trimmed : regular } ;
190
- }
188
+ let trimmed = regular ;
191
189
192
- let first , last ;
190
+ if ( ! preserve_whitespace ) {
191
+ trimmed = [ ] ;
193
192
194
- while ( ( first = regular [ 0 ] ) && first . type === 'Text' && ! regex_not_whitespace . test ( first . data ) ) {
195
- regular . shift ( ) ;
196
- }
193
+ let first , last ;
197
194
198
- if ( first ?. type === 'Text' ) {
199
- first . raw = first . raw . replace ( regex_starts_with_whitespaces , '' ) ;
200
- first . data = first . data . replace ( regex_starts_with_whitespaces , '' ) ;
201
- }
195
+ while (
196
+ ( first = regular [ 0 ] ) &&
197
+ first . type === 'Text' &&
198
+ ! regex_not_whitespace . test ( first . data )
199
+ ) {
200
+ regular . shift ( ) ;
201
+ }
202
202
203
- while ( ( last = regular . at ( - 1 ) ) && last . type === 'Text' && ! regex_not_whitespace . test ( last . data ) ) {
204
- regular . pop ( ) ;
205
- }
203
+ if ( first ?. type === 'Text' ) {
204
+ first . raw = first . raw . replace ( regex_starts_with_whitespaces , '' ) ;
205
+ first . data = first . data . replace ( regex_starts_with_whitespaces , '' ) ;
206
+ }
206
207
207
- if ( last ?. type === 'Text' ) {
208
- last . raw = last . raw . replace ( regex_ends_with_whitespaces , '' ) ;
209
- last . data = last . data . replace ( regex_ends_with_whitespaces , '' ) ;
210
- }
208
+ while (
209
+ ( last = regular . at ( - 1 ) ) &&
210
+ last . type === 'Text' &&
211
+ ! regex_not_whitespace . test ( last . data )
212
+ ) {
213
+ regular . pop ( ) ;
214
+ }
211
215
212
- const can_remove_entirely =
213
- ( namespace === 'svg' &&
214
- ( parent . type !== 'RegularElement' || parent . name !== 'text' ) &&
215
- ! path . some ( ( n ) => n . type === 'RegularElement' && n . name === 'text' ) ) ||
216
- ( parent . type === 'RegularElement' &&
217
- // TODO others?
218
- ( parent . name === 'select' ||
219
- parent . name === 'tr' ||
220
- parent . name === 'table' ||
221
- parent . name === 'tbody' ||
222
- parent . name === 'thead' ||
223
- parent . name === 'tfoot' ||
224
- parent . name === 'colgroup' ||
225
- parent . name === 'datalist' ) ) ;
216
+ if ( last ?. type === 'Text' ) {
217
+ last . raw = last . raw . replace ( regex_ends_with_whitespaces , '' ) ;
218
+ last . data = last . data . replace ( regex_ends_with_whitespaces , '' ) ;
219
+ }
226
220
227
- /** @type {Compiler.SvelteNode[] } */
228
- const trimmed = [ ] ;
229
-
230
- // Replace any whitespace between a text and non-text node with a single spaceand keep whitespace
231
- // as-is within text nodes, or between text nodes and expression tags (because in the end they count
232
- // as one text). This way whitespace is mostly preserved when using CSS with `white-space: pre-line`
233
- // and default slot content going into a pre tag (which we can't see).
234
- for ( let i = 0 ; i < regular . length ; i ++ ) {
235
- const prev = regular [ i - 1 ] ;
236
- const node = regular [ i ] ;
237
- const next = regular [ i + 1 ] ;
238
-
239
- if ( node . type === 'Text' ) {
240
- if ( prev ?. type !== 'ExpressionTag' ) {
241
- const prev_is_text_ending_with_whitespace =
242
- prev ?. type === 'Text' && regex_ends_with_whitespaces . test ( prev . data ) ;
243
- node . data = node . data . replace (
244
- regex_starts_with_whitespaces ,
245
- prev_is_text_ending_with_whitespace ? '' : ' '
246
- ) ;
247
- node . raw = node . raw . replace (
248
- regex_starts_with_whitespaces ,
249
- prev_is_text_ending_with_whitespace ? '' : ' '
250
- ) ;
251
- }
252
- if ( next ?. type !== 'ExpressionTag' ) {
253
- node . data = node . data . replace ( regex_ends_with_whitespaces , ' ' ) ;
254
- node . raw = node . raw . replace ( regex_ends_with_whitespaces , ' ' ) ;
255
- }
256
- if ( node . data && ( node . data !== ' ' || ! can_remove_entirely ) ) {
221
+ const can_remove_entirely =
222
+ ( namespace === 'svg' &&
223
+ ( parent . type !== 'RegularElement' || parent . name !== 'text' ) &&
224
+ ! path . some ( ( n ) => n . type === 'RegularElement' && n . name === 'text' ) ) ||
225
+ ( parent . type === 'RegularElement' &&
226
+ // TODO others?
227
+ ( parent . name === 'select' ||
228
+ parent . name === 'tr' ||
229
+ parent . name === 'table' ||
230
+ parent . name === 'tbody' ||
231
+ parent . name === 'thead' ||
232
+ parent . name === 'tfoot' ||
233
+ parent . name === 'colgroup' ||
234
+ parent . name === 'datalist' ) ) ;
235
+
236
+ // Replace any whitespace between a text and non-text node with a single spaceand keep whitespace
237
+ // as-is within text nodes, or between text nodes and expression tags (because in the end they count
238
+ // as one text). This way whitespace is mostly preserved when using CSS with `white-space: pre-line`
239
+ // and default slot content going into a pre tag (which we can't see).
240
+ for ( let i = 0 ; i < regular . length ; i ++ ) {
241
+ const prev = regular [ i - 1 ] ;
242
+ const node = regular [ i ] ;
243
+ const next = regular [ i + 1 ] ;
244
+
245
+ if ( node . type === 'Text' ) {
246
+ if ( prev ?. type !== 'ExpressionTag' ) {
247
+ const prev_is_text_ending_with_whitespace =
248
+ prev ?. type === 'Text' && regex_ends_with_whitespaces . test ( prev . data ) ;
249
+ node . data = node . data . replace (
250
+ regex_starts_with_whitespaces ,
251
+ prev_is_text_ending_with_whitespace ? '' : ' '
252
+ ) ;
253
+ node . raw = node . raw . replace (
254
+ regex_starts_with_whitespaces ,
255
+ prev_is_text_ending_with_whitespace ? '' : ' '
256
+ ) ;
257
+ }
258
+ if ( next ?. type !== 'ExpressionTag' ) {
259
+ node . data = node . data . replace ( regex_ends_with_whitespaces , ' ' ) ;
260
+ node . raw = node . raw . replace ( regex_ends_with_whitespaces , ' ' ) ;
261
+ }
262
+ if ( node . data && ( node . data !== ' ' || ! can_remove_entirely ) ) {
263
+ trimmed . push ( node ) ;
264
+ }
265
+ } else {
257
266
trimmed . push ( node ) ;
258
267
}
259
- } else {
260
- trimmed . push ( node ) ;
261
268
}
262
269
}
263
270
264
- return { hoisted, trimmed } ;
271
+ var first = trimmed [ 0 ] ;
272
+
273
+ /**
274
+ * In a case like `{#if x}<Foo />{/if}`, we don't need to wrap the child in
275
+ * comments — we can just use the parent block's anchor for the component.
276
+ * TODO extend this optimisation to other cases
277
+ */
278
+ const is_standalone =
279
+ trimmed . length === 1 &&
280
+ ( ( first . type === 'RenderTag' && ! first . metadata . dynamic ) ||
281
+ ( first . type === 'Component' &&
282
+ ! first . attributes . some (
283
+ ( attribute ) => attribute . type === 'Attribute' && attribute . name . startsWith ( '--' )
284
+ ) ) ) ;
285
+
286
+ return { hoisted, trimmed, is_standalone } ;
265
287
}
266
288
267
289
/**
0 commit comments