@ -19,6 +19,7 @@ const LINE_BREAK_THRESHOLD = 50;
* /
export function print ( ast , options = undefined ) {
const comments = ( ast . type === 'Root' && ast . comments ) || [ ] ;
const state = { preserve _whitespace : 0 } ;
const css _comments =
( ast . type === 'Root' ? ast . css ? . comments : ast . type === 'StyleSheet' ? ast . comments : null ) ||
[ ] ;
@ -31,7 +32,7 @@ export function print(ast, options = undefined) {
getLeadingComments : options ? . getLeadingComments ,
getTrailingComments : options ? . getTrailingComments
} ) ,
... svelte _visitors ( comments ),
... svelte _visitors ( comments , state ),
... css _visitors ( css _comments , comments )
} ) ,
{
@ -43,9 +44,15 @@ export function print(ast, options = undefined) {
/ * *
* @ param { Context } context
* @ param { AST . SvelteNode } node
* @ param { boolean } preserve _whitespace
* @ param { boolean } allow _inline
* /
function block ( context , node , allow _inline = false ) {
function block ( context , node , preserve _whitespace = false , allow _inline = false ) {
if ( preserve _whitespace ) {
context . visit ( node ) ;
return ;
}
const child _context = context . new ( ) ;
child _context . visit ( node ) ;
@ -146,8 +153,9 @@ function attributes(node, attributes, context, comments) {
* @ param { AST . BaseElement } node
* @ param { Context } context
* @ param { AST . JSComment [ ] } comments
* @ param { { preserve _whitespace : number } } state
* /
function base _element ( node , context , comments ) {
function base _element ( node , context , comments , state ) {
const child _context = context . new ( ) ;
child _context . write ( '<' + node . name ) ;
@ -173,13 +181,30 @@ function base_element(node, context, comments) {
child _context . write ( ` ${ multiline _attributes ? '' : ' ' } /> ` ) ;
} else {
child _context . write ( '>' ) ;
block ( child _context , node . fragment , true ) ;
block ( child _context , node . fragment , state . preserve _whitespace > 0 , true ) ;
child _context . write ( ` </ ${ node . name } > ` ) ;
}
context . append ( child _context ) ;
}
/ * *
* @ param { AST . BaseElement } node
* @ param { Context } context
* @ param { AST . JSComment [ ] } comments
* @ param { { preserve _whitespace : number } } state
* /
function print _element ( node , context , comments , state ) {
const name = node . name . toLowerCase ( ) ;
const preserve =
( node . type === 'RegularElement' || node . type === 'TitleElement' ) &&
( name === 'pre' || name === 'textarea' || name === 'title' ) ;
if ( preserve ) state . preserve _whitespace += 1 ;
base _element ( node , context , comments , state ) ;
if ( preserve ) state . preserve _whitespace -= 1 ;
}
/ * *
* @ param { AST . CSS . CSSComment [ ] } comments
* @ param { AST . JSComment [ ] } js _comments
@ -440,9 +465,10 @@ function css_visitors(comments, js_comments) {
/ * *
* @ param { AST . JSComment [ ] } comments
* @ param { { preserve _whitespace : number } } state
* @ returns { Visitors < AST . SvelteNode > }
* /
const svelte _visitors = ( comments ) => ( {
const svelte _visitors = ( comments , state ) => ( {
Root ( node , context ) {
if ( node . options ) {
context . write ( '<svelte:options' ) ;
@ -474,11 +500,27 @@ const svelte_visitors = (comments) => ({
context . write ( '<script' ) ;
attributes ( node , node . attributes , context , comments ) ;
context . write ( '>' ) ;
block ( context , node . content );
block ( context , node . content , state . preserve _whitespace > 0 );
context . write ( '</script>' ) ;
} ,
Fragment ( node , context ) {
if ( state . preserve _whitespace > 0 ) {
for ( const child of node . nodes ) {
context . visit ( child ) ;
context . multiline || = child . type === 'Text' && /[\r\n]/ . test ( child . data ) ;
}
return ;
}
const first = node . nodes [ 0 ] ;
const last = node . nodes . at ( - 1 ) ;
const has _surrounding _whitespace =
first ? . type === 'Text' &&
/^\s/ . test ( first . data ) &&
last ? . type === 'Text' &&
/\s$/ . test ( last . data ) ;
/** @type {AST.SvelteNode[][]} */
const items = [ ] ;
@ -570,6 +612,10 @@ const svelte_visitors = (comments) => ({
} ) ;
multiline || = width > LINE _BREAK _THRESHOLD ;
// Normally context.newline() also makes context.multiline true, but the below loop only
// does that if we have more than one child context. If there's one long text block inside
// with whitespace at the edges we wanna split that up, too.
context . multiline || = has _surrounding _whitespace && width > LINE _BREAK _THRESHOLD * 2 ;
for ( let i = 0 ; i < child _contexts . length ; i += 1 ) {
const prev = child _contexts [ i ] ;
@ -636,7 +682,7 @@ const svelte_visitors = (comments) => ({
if ( node . pending ) {
context . write ( '}' ) ;
block ( context , node . pending );
block ( context , node . pending , state . preserve _whitespace > 0 );
context . write ( '{:' ) ;
} else {
context . write ( ' ' ) ;
@ -647,7 +693,7 @@ const svelte_visitors = (comments) => ({
if ( node . value ) context . visit ( node . value ) ;
context . write ( '}' ) ;
block ( context , node . then );
block ( context , node . then , state . preserve _whitespace > 0 );
if ( node . catch ) {
context . write ( '{:' ) ;
@ -659,7 +705,7 @@ const svelte_visitors = (comments) => ({
if ( node . error ) context . visit ( node . error ) ;
context . write ( '}' ) ;
block ( context , node . catch );
block ( context , node . catch , state . preserve _whitespace > 0 );
}
context . write ( '{/await}' ) ;
@ -703,7 +749,7 @@ const svelte_visitors = (comments) => ({
} ,
Component ( node , context ) {
base _element ( node , context , comments ) ;
print _element ( node , context , comments , state ) ;
} ,
ConstTag ( node , context ) {
@ -793,11 +839,11 @@ const svelte_visitors = (comments) => ({
context . write ( '}' ) ;
block ( context , node . body );
block ( context , node . body , state . preserve _whitespace > 0 );
if ( node . fallback ) {
context . write ( '{:else}' ) ;
block ( context , node . fallback );
block ( context , node . fallback , state . preserve _whitespace > 0 );
}
context . write ( '{/each}' ) ;
@ -821,13 +867,13 @@ const svelte_visitors = (comments) => ({
context . visit ( node . test ) ;
context . write ( '}' ) ;
block ( context , node . consequent );
block ( context , node . consequent , state . preserve _whitespace > 0 );
} else {
context . write ( '{#if ' ) ;
context . visit ( node . test ) ;
context . write ( '}' ) ;
block ( context , node . consequent );
block ( context , node . consequent , state . preserve _whitespace > 0 );
}
if ( node . alternate !== null ) {
@ -839,7 +885,7 @@ const svelte_visitors = (comments) => ({
)
) {
context . write ( '{:else}' ) ;
block ( context , node . alternate );
block ( context , node . alternate , state . preserve _whitespace > 0 );
} else {
context . visit ( node . alternate ) ;
}
@ -854,7 +900,7 @@ const svelte_visitors = (comments) => ({
context . write ( '{#key ' ) ;
context . visit ( node . expression ) ;
context . write ( '}' ) ;
block ( context , node . fragment );
block ( context , node . fragment , state . preserve _whitespace > 0 );
context . write ( '{/key}' ) ;
} ,
@ -886,7 +932,7 @@ const svelte_visitors = (comments) => ({
} ,
RegularElement ( node , context ) {
base _element ( node , context , comments ) ;
print _element ( node , context , comments , state ) ;
} ,
RenderTag ( node , context ) {
@ -896,7 +942,7 @@ const svelte_visitors = (comments) => ({
} ,
SlotElement ( node , context ) {
base _element ( node , context , comments ) ;
print _element ( node , context , comments , state ) ;
} ,
SnippetBlock ( node , context ) {
@ -915,7 +961,7 @@ const svelte_visitors = (comments) => ({
}
context . write ( ')}' ) ;
block ( context , node . body );
block ( context , node . body , state . preserve _whitespace > 0 );
context . write ( '{/snippet}' ) ;
} ,
@ -951,11 +997,11 @@ const svelte_visitors = (comments) => ({
} ,
SvelteBody ( node , context ) {
base _element ( node , context , comments ) ;
print _element ( node , context , comments , state ) ;
} ,
SvelteBoundary ( node , context ) {
base _element ( node , context , comments ) ;
print _element ( node , context , comments , state ) ;
} ,
SvelteComponent ( node , context ) {
@ -967,7 +1013,7 @@ const svelte_visitors = (comments) => ({
attributes ( node , node . attributes , context , comments ) ;
if ( node . fragment && node . fragment . nodes . length > 0 ) {
context . write ( '>' ) ;
block ( context , node . fragment , true ) ;
block ( context , node . fragment , state . preserve _whitespace > 0 , true ) ;
context . write ( ` </svelte:component> ` ) ;
} else {
context . write ( ' />' ) ;
@ -975,7 +1021,7 @@ const svelte_visitors = (comments) => ({
} ,
SvelteDocument ( node , context ) {
base _element ( node , context , comments ) ;
print _element ( node , context , comments , state ) ;
} ,
SvelteElement ( node , context ) {
@ -988,7 +1034,7 @@ const svelte_visitors = (comments) => ({
if ( node . fragment && node . fragment . nodes . length > 0 ) {
context . write ( '>' ) ;
block ( context , node . fragment );
block ( context , node . fragment , state . preserve _whitespace > 0 );
context . write ( ` </svelte:element> ` ) ;
} else {
context . write ( ' />' ) ;
@ -996,19 +1042,19 @@ const svelte_visitors = (comments) => ({
} ,
SvelteFragment ( node , context ) {
base _element ( node , context , comments ) ;
print _element ( node , context , comments , state ) ;
} ,
SvelteHead ( node , context ) {
base _element ( node , context , comments ) ;
print _element ( node , context , comments , state ) ;
} ,
SvelteSelf ( node , context ) {
base _element ( node , context , comments ) ;
print _element ( node , context , comments , state ) ;
} ,
SvelteWindow ( node , context ) {
base _element ( node , context , comments ) ;
print _element ( node , context , comments , state ) ;
} ,
Text ( node , context ) {
@ -1016,7 +1062,7 @@ const svelte_visitors = (comments) => ({
} ,
TitleElement ( node , context ) {
base _element ( node , context , comments ) ;
print _element ( node , context , comments , state ) ;
} ,
TransitionDirective ( node , context ) {