@@ -84,12 +84,14 @@ function serializeToHtml(node: Node, opts: SerializeNodeToHtmlOptions, output: S
84
84
const ignoreTag = opts . excludeTags != null && opts . excludeTags . includes ( tagName ) ;
85
85
86
86
if ( ignoreTag === false ) {
87
- if ( opts . newLines ) {
87
+ const isWithinWhitespaceSensitiveNode =
88
+ opts . newLines || opts . indentSpaces > 0 ? isWithinWhitespaceSensitive ( node ) : false ;
89
+ if ( opts . newLines && ! isWithinWhitespaceSensitiveNode ) {
88
90
output . text . push ( '\n' ) ;
89
91
output . currentLineWidth = 0 ;
90
92
}
91
93
92
- if ( opts . indentSpaces > 0 ) {
94
+ if ( opts . indentSpaces > 0 && ! isWithinWhitespaceSensitiveNode ) {
93
95
for ( let i = 0 ; i < output . indent ; i ++ ) {
94
96
output . text . push ( ' ' ) ;
95
97
}
@@ -100,7 +102,10 @@ function serializeToHtml(node: Node, opts: SerializeNodeToHtmlOptions, output: S
100
102
output . currentLineWidth += tagName . length + 1 ;
101
103
102
104
const attrsLength = ( node as HTMLElement ) . attributes . length ;
103
- const attributes = opts . prettyHtml && attrsLength > 1 ? cloneAttributes ( ( node as HTMLElement ) . attributes as any , true ) : ( node as Element ) . attributes ;
105
+ const attributes =
106
+ opts . prettyHtml && attrsLength > 1
107
+ ? cloneAttributes ( ( node as HTMLElement ) . attributes as any , true )
108
+ : ( node as Element ) . attributes ;
104
109
105
110
for ( let i = 0 ; i < attrsLength ; i ++ ) {
106
111
const attr = attributes . item ( i ) ;
@@ -173,7 +178,10 @@ function serializeToHtml(node: Node, opts: SerializeNodeToHtmlOptions, output: S
173
178
if ( ( node as Element ) . hasAttribute ( 'style' ) ) {
174
179
const cssText = ( node as HTMLElement ) . style . cssText ;
175
180
176
- if ( opts . approximateLineWidth > 0 && output . currentLineWidth + cssText . length + 10 > opts . approximateLineWidth ) {
181
+ if (
182
+ opts . approximateLineWidth > 0 &&
183
+ output . currentLineWidth + cssText . length + 10 > opts . approximateLineWidth
184
+ ) {
177
185
output . text . push ( `\nstyle="${ cssText } ">` ) ;
178
186
output . currentLineWidth = 0 ;
179
187
} else {
@@ -194,7 +202,10 @@ function serializeToHtml(node: Node, opts: SerializeNodeToHtmlOptions, output: S
194
202
195
203
if (
196
204
opts . newLines &&
197
- ( node . childNodes . length === 0 || ( node . childNodes . length === 1 && node . childNodes [ 0 ] . nodeType === NODE_TYPES . TEXT_NODE && node . childNodes [ 0 ] . nodeValue . trim ( ) === '' ) )
205
+ ( node . childNodes . length === 0 ||
206
+ ( node . childNodes . length === 1 &&
207
+ node . childNodes [ 0 ] . nodeType === NODE_TYPES . TEXT_NODE &&
208
+ node . childNodes [ 0 ] . nodeValue . trim ( ) === '' ) )
198
209
) {
199
210
output . text . push ( '\n' ) ;
200
211
output . currentLineWidth = 0 ;
@@ -207,11 +218,16 @@ function serializeToHtml(node: Node, opts: SerializeNodeToHtmlOptions, output: S
207
218
}
208
219
209
220
if ( opts . excludeTagContent == null || opts . excludeTagContent . includes ( tagName ) === false ) {
210
- const childNodes = tagName === 'template' ? ( ( ( node as any ) as HTMLTemplateElement ) . content . childNodes as any ) : node . childNodes ;
221
+ const childNodes =
222
+ tagName === 'template' ? ( ( ( node as any ) as HTMLTemplateElement ) . content . childNodes as any ) : node . childNodes ;
211
223
const childNodeLength = childNodes . length ;
212
224
213
225
if ( childNodeLength > 0 ) {
214
- if ( childNodeLength === 1 && childNodes [ 0 ] . nodeType === NODE_TYPES . TEXT_NODE && ( typeof childNodes [ 0 ] . nodeValue !== 'string' || childNodes [ 0 ] . nodeValue . trim ( ) === '' ) ) {
226
+ if (
227
+ childNodeLength === 1 &&
228
+ childNodes [ 0 ] . nodeType === NODE_TYPES . TEXT_NODE &&
229
+ ( typeof childNodes [ 0 ] . nodeValue !== 'string' || childNodes [ 0 ] . nodeValue . trim ( ) === '' )
230
+ ) {
215
231
// skip over empty text nodes
216
232
} else {
217
233
if ( opts . indentSpaces > 0 && ignoreTag === false ) {
@@ -223,12 +239,14 @@ function serializeToHtml(node: Node, opts: SerializeNodeToHtmlOptions, output: S
223
239
}
224
240
225
241
if ( ignoreTag === false ) {
226
- if ( opts . newLines ) {
242
+ const isWithinWhitespaceSensitiveNode =
243
+ opts . newLines || opts . indentSpaces > 0 ? isWithinWhitespaceSensitive ( node ) : false ;
244
+ if ( opts . newLines && ! isWithinWhitespaceSensitiveNode ) {
227
245
output . text . push ( '\n' ) ;
228
246
output . currentLineWidth = 0 ;
229
247
}
230
248
231
- if ( opts . indentSpaces > 0 ) {
249
+ if ( opts . indentSpaces > 0 && ! isWithinWhitespaceSensitiveNode ) {
232
250
output . indent = output . indent - opts . indentSpaces ;
233
251
for ( let i = 0 ; i < output . indent ; i ++ ) {
234
252
output . text . push ( ' ' ) ;
@@ -287,12 +305,14 @@ function serializeToHtml(node: Node, opts: SerializeNodeToHtmlOptions, output: S
287
305
}
288
306
} else {
289
307
// this text node has text content
290
- if ( opts . newLines ) {
308
+ const isWithinWhitespaceSensitiveNode =
309
+ opts . newLines || opts . indentSpaces > 0 || opts . prettyHtml ? isWithinWhitespaceSensitive ( node ) : false ;
310
+ if ( opts . newLines && ! isWithinWhitespaceSensitiveNode ) {
291
311
output . text . push ( '\n' ) ;
292
312
output . currentLineWidth = 0 ;
293
313
}
294
314
295
- if ( opts . indentSpaces > 0 ) {
315
+ if ( opts . indentSpaces > 0 && ! isWithinWhitespaceSensitiveNode ) {
296
316
for ( let i = 0 ; i < output . indent ; i ++ ) {
297
317
output . text . push ( ' ' ) ;
298
318
}
@@ -303,7 +323,10 @@ function serializeToHtml(node: Node, opts: SerializeNodeToHtmlOptions, output: S
303
323
if ( textContentLength > 0 ) {
304
324
// this text node has text content
305
325
306
- const parentTagName = node . parentNode != null && node . parentNode . nodeType === NODE_TYPES . ELEMENT_NODE ? node . parentNode . nodeName : null ;
326
+ const parentTagName =
327
+ node . parentNode != null && node . parentNode . nodeType === NODE_TYPES . ELEMENT_NODE
328
+ ? node . parentNode . nodeName
329
+ : null ;
307
330
if ( NON_ESCAPABLE_CONTENT . has ( parentTagName ) ) {
308
331
// this text node cannot have its content escaped since it's going
309
332
// into an element like <style> or <script>
@@ -316,7 +339,7 @@ function serializeToHtml(node: Node, opts: SerializeNodeToHtmlOptions, output: S
316
339
output . currentLineWidth += textContentLength ;
317
340
} else {
318
341
// this text node is going into a normal element and html can be escaped
319
- if ( opts . prettyHtml ) {
342
+ if ( opts . prettyHtml && ! isWithinWhitespaceSensitiveNode ) {
320
343
// pretty print the text node
321
344
output . text . push ( escapeString ( textContent . replace ( / \s \s + / g, ' ' ) . trim ( ) , false ) ) ;
322
345
output . currentLineWidth += textContentLength ;
@@ -334,7 +357,10 @@ function serializeToHtml(node: Node, opts: SerializeNodeToHtmlOptions, output: S
334
357
textContentLength = textContent . length ;
335
358
if ( textContentLength > 1 ) {
336
359
if ( / \s / . test ( textContent . charAt ( textContentLength - 1 ) ) ) {
337
- if ( opts . approximateLineWidth > 0 && output . currentLineWidth + textContentLength > opts . approximateLineWidth ) {
360
+ if (
361
+ opts . approximateLineWidth > 0 &&
362
+ output . currentLineWidth + textContentLength > opts . approximateLineWidth
363
+ ) {
338
364
textContent = textContent . trimRight ( ) + '\n' ;
339
365
output . currentLineWidth = 0 ;
340
366
} else {
@@ -365,12 +391,14 @@ function serializeToHtml(node: Node, opts: SerializeNodeToHtmlOptions, output: S
365
391
}
366
392
}
367
393
368
- if ( opts . newLines ) {
394
+ const isWithinWhitespaceSensitiveNode =
395
+ opts . newLines || opts . indentSpaces > 0 ? isWithinWhitespaceSensitive ( node ) : false ;
396
+ if ( opts . newLines && ! isWithinWhitespaceSensitiveNode ) {
369
397
output . text . push ( '\n' ) ;
370
398
output . currentLineWidth = 0 ;
371
399
}
372
400
373
- if ( opts . indentSpaces > 0 ) {
401
+ if ( opts . indentSpaces > 0 && ! isWithinWhitespaceSensitiveNode ) {
374
402
for ( let i = 0 ; i < output . indent ; i ++ ) {
375
403
output . text . push ( ' ' ) ;
376
404
}
@@ -419,9 +447,26 @@ function isWithinWhitespaceSensitive(node: Node) {
419
447
return false ;
420
448
}
421
449
422
- /*@__PURE__ */ export const NON_ESCAPABLE_CONTENT = new Set ( [ 'STYLE' , 'SCRIPT' , 'IFRAME' , 'NOSCRIPT' , 'XMP' , 'NOEMBED' , 'NOFRAMES' , 'PLAINTEXT' ] ) ;
450
+ /*@__PURE__ */ export const NON_ESCAPABLE_CONTENT = new Set ( [
451
+ 'STYLE' ,
452
+ 'SCRIPT' ,
453
+ 'IFRAME' ,
454
+ 'NOSCRIPT' ,
455
+ 'XMP' ,
456
+ 'NOEMBED' ,
457
+ 'NOFRAMES' ,
458
+ 'PLAINTEXT' ,
459
+ ] ) ;
423
460
424
- /*@__PURE__ */ export const WHITESPACE_SENSITIVE = new Set ( [ 'CODE' , 'OUTPUT' , 'PLAINTEXT' , 'PRE' , 'TEMPLATE' , 'TEXTAREA' ] ) ;
461
+ /*@__PURE__ */ export const WHITESPACE_SENSITIVE = new Set ( [
462
+ 'CODE' ,
463
+ 'OUTPUT' ,
464
+ 'PLAINTEXT' ,
465
+ 'PRE' ,
466
+ 'SCRIPT' ,
467
+ 'TEMPLATE' ,
468
+ 'TEXTAREA' ,
469
+ ] ) ;
425
470
426
471
/*@__PURE__ */ const EMPTY_ELEMENTS = new Set ( [
427
472
'area' ,
@@ -491,7 +536,18 @@ function isWithinWhitespaceSensitive(node: Node) {
491
536
'visible' ,
492
537
] ) ;
493
538
494
- /*@__PURE__ */ const STRUCTURE_ELEMENTS = new Set ( [ 'html' , 'body' , 'head' , 'iframe' , 'meta' , 'link' , 'base' , 'title' , 'script' , 'style' ] ) ;
539
+ /*@__PURE__ */ const STRUCTURE_ELEMENTS = new Set ( [
540
+ 'html' ,
541
+ 'body' ,
542
+ 'head' ,
543
+ 'iframe' ,
544
+ 'meta' ,
545
+ 'link' ,
546
+ 'base' ,
547
+ 'title' ,
548
+ 'script' ,
549
+ 'style' ,
550
+ ] ) ;
495
551
496
552
interface SerializeOutput {
497
553
currentLineWidth : number ;
0 commit comments