@ -19,6 +19,9 @@ const LINE_BREAK_THRESHOLD = 50;
* /
* /
export function print ( ast , options = undefined ) {
export function print ( ast , options = undefined ) {
const comments = ( ast . type === 'Root' && ast . comments ) || [ ] ;
const comments = ( ast . type === 'Root' && ast . comments ) || [ ] ;
const css _comments =
( ast . type === 'Root' ? ast . css ? . comments : ast . type === 'StyleSheet' ? ast . comments : null ) ||
[ ] ;
return esrap . print (
return esrap . print (
ast ,
ast ,
@ -29,7 +32,7 @@ export function print(ast, options = undefined) {
getTrailingComments : options ? . getTrailingComments
getTrailingComments : options ? . getTrailingComments
} ) ,
} ) ,
... svelte _visitors ( comments ) ,
... svelte _visitors ( comments ) ,
... css _visitors
... css _visitors ( css _comments , comments )
} ) ,
} ) ,
{
{
indent : options ? . indent
indent : options ? . indent
@ -177,11 +180,132 @@ function base_element(node, context, comments) {
context . append ( child _context ) ;
context . append ( child _context ) ;
}
}
/** @type {Visitors<AST.SvelteNode>} */
/ * *
const css _visitors = {
* @ param { AST . CSS . CSSComment [ ] } comments
* @ param { AST . JSComment [ ] } js _comments
* @ returns { Visitors < AST . SvelteNode > }
* /
function css _visitors ( comments , js _comments ) {
let comment _index = 0 ;
/** @param {number} end */
const has _comment _before = ( end ) => comments [ comment _index ] ? . start < end ;
/ * *
* @ param { Context } context
* @ param { AST . CSS . CSSComment } comment
* /
function write _comment ( context , comment ) {
context . write ( ` /* ${ comment . value } */ ` ) ;
}
/ * *
* @ param { Context } context
* @ param { number } end
* /
function write _inline _comments ( context , end ) {
let written = false ;
while ( has _comment _before ( end ) ) {
if ( written ) context . write ( ' ' ) ;
write _comment ( context , comments [ comment _index ++ ] ) ;
written = true ;
}
return written ;
}
/ * *
* @ param { Context } context
* @ param { string } value
* @ param { number } end
* /
function write _value ( context , value , end ) {
let offset = 0 ;
while ( has _comment _before ( end ) ) {
const comment = comments [ comment _index ++ ] ;
const position = Math . max ( offset , Math . min ( comment . position ? ? 0 , value . length ) ) ;
context . write ( value . slice ( offset , position ) ) ;
write _comment ( context , comment ) ;
offset = position ;
}
context . write ( value . slice ( offset ) ) ;
}
/ * *
* @ param { Context } context
* @ param { Array < AST . CSS . Rule | AST . CSS . Atrule | AST . CSS . Declaration > } children
* @ param { number } end
* @ param { boolean } margins
* /
function print _children ( context , children , end , margins ) {
let started = false ;
const separate = ( ) => {
if ( ! started ) return ;
if ( margins ) context . margin ( ) ;
context . newline ( ) ;
} ;
for ( const child of children ) {
while ( has _comment _before ( child . start ) ) {
separate ( ) ;
write _comment ( context , comments [ comment _index ++ ] ) ;
started = true ;
}
separate ( ) ;
context . visit ( child ) ;
started = true ;
}
while ( has _comment _before ( end ) ) {
separate ( ) ;
write _comment ( context , comments [ comment _index ++ ] ) ;
started = true ;
}
}
/ * *
* @ param { AST . CSS . SelectorList } node
* @ param { Context } context
* @ param { boolean } multiline
* /
function print _selector _list ( node , context , multiline ) {
let needs _separator = false ;
let remaining _selectors = node . children . length ;
for ( const selector of node . children ) {
while ( has _comment _before ( selector . start ) ) {
if ( needs _separator ) context . write ( ' ' ) ;
write _comment ( context , comments [ comment _index ++ ] ) ;
needs _separator = true ;
}
if ( needs _separator ) {
if ( multiline ) context . newline ( ) ;
else context . write ( ' ' ) ;
}
context . visit ( selector ) ;
needs _separator = true ;
remaining _selectors -= 1 ;
if ( remaining _selectors > 0 ) context . write ( ',' ) ;
}
}
return {
Atrule ( node , context ) {
Atrule ( node , context ) {
context . write ( ` @ ${ node . name } ` ) ;
context . write ( ` @ ${ node . name } ` ) ;
if ( node . prelude ) context . write ( ` ${ node . prelude } ` ) ;
const prelude _end = node . block ? . start ? ? node . end ;
if ( node . prelude || has _comment _before ( prelude _end ) ) {
context . write ( ' ' ) ;
write _value ( context , node . prelude , prelude _end ) ;
}
if ( node . block ) {
if ( node . block ) {
context . write ( ' ' ) ;
context . write ( ' ' ) ;
@ -196,9 +320,7 @@ const css_visitors = {
if ( node . matcher ) {
if ( node . matcher ) {
context . write ( node . matcher ) ;
context . write ( node . matcher ) ;
context . write ( ` " ${ node . value } " ` ) ;
context . write ( ` " ${ node . value } " ` ) ;
if ( node . flags ) {
if ( node . flags ) context . write ( ` ${ node . flags } ` ) ;
context . write ( ` ${ node . flags } ` ) ;
}
}
}
context . write ( ']' ) ;
context . write ( ']' ) ;
} ,
} ,
@ -206,22 +328,10 @@ const css_visitors = {
Block ( node , context ) {
Block ( node , context ) {
context . write ( '{' ) ;
context . write ( '{' ) ;
if ( node . children . length > 0 ) {
if ( node . children . length > 0 || has _comment _before ( node . end ) ) {
context . indent ( ) ;
context . indent ( ) ;
context . newline ( ) ;
context . newline ( ) ;
print _children ( context , node . children , node . end , false ) ;
let started = false ;
for ( const child of node . children ) {
if ( started ) {
context . newline ( ) ;
}
context . visit ( child ) ;
started = true ;
}
context . dedent ( ) ;
context . dedent ( ) ;
context . newline ( ) ;
context . newline ( ) ;
}
}
@ -234,13 +344,13 @@ const css_visitors = {
} ,
} ,
ComplexSelector ( node , context ) {
ComplexSelector ( node , context ) {
for ( const selector of node . children ) {
for ( const selector of node . children ) context . visit ( selector ) ;
context . visit ( selector ) ;
}
} ,
} ,
Declaration ( node , context ) {
Declaration ( node , context ) {
context . write ( ` ${ node . property } : ${ node . value } ; ` ) ;
context . write ( ` ${ node . property } : ` ) ;
write _value ( context , node . value , node . end ) ;
context . write ( ';' ) ;
} ,
} ,
IdSelector ( node , context ) {
IdSelector ( node , context ) {
@ -264,74 +374,69 @@ const css_visitors = {
if ( node . args ) {
if ( node . args ) {
context . write ( '(' ) ;
context . write ( '(' ) ;
context . visit ( node . args ) ;
let started = false ;
if ( has _comment _before ( node . end ) ) {
context . write ( ' ' ) ;
for ( const arg of node . args . children ) {
write _inline _comments ( context , node . end ) ;
if ( started ) {
context . write ( ', ' ) ;
}
context . visit ( arg ) ;
started = true ;
}
}
context . write ( ')' ) ;
context . write ( ')' ) ;
}
}
} ,
} ,
PseudoElementSelector ( node , context ) {
PseudoElementSelector ( node , context ) {
context . write ( ` :: ${ node . name } ` ) ;
context . write ( ` :: ${ node . name } ` ) ;
if ( node . args ) {
context . write ( '(' ) ;
context . visit ( node . args ) ;
if ( has _comment _before ( node . end ) ) {
context . write ( ' ' ) ;
write _inline _comments ( context , node . end ) ;
}
context . write ( ')' ) ;
}
} ,
} ,
RelativeSelector ( node , context ) {
RelativeSelector ( node , context ) {
if ( node . combinator ) {
if ( node . combinator ) {
if ( node . combinator . name === ' ' ) {
if ( node . combinator . name === ' ' ) context . write ( ' ' ) ;
context . write ( ' ' ) ;
else context . write ( ` ${ node . combinator . name } ` ) ;
} else {
context . write ( ` ${ node . combinator . name } ` ) ;
}
}
}
for ( const selector of node . selectors ) {
for ( const selector of node . selectors ) context . visit ( selector ) ;
context . visit ( selector ) ;
}
} ,
} ,
Rule ( node , context ) {
Rule ( node , context ) {
let started = false ;
print _selector _list ( node . prelude , context , true ) ;
for ( const selector of node . prelude . children ) {
if ( started ) {
context . write ( ',' ) ;
context . newline ( ) ;
}
context . visit ( selector ) ;
started = true ;
}
context . write ( ' ' ) ;
context . write ( ' ' ) ;
if ( write _inline _comments ( context , node . block . start ) ) context . write ( ' ' ) ;
context . visit ( node . block ) ;
context . visit ( node . block ) ;
} ,
} ,
SelectorList ( node , context ) {
SelectorList ( node , context ) {
let started = false ;
print _selector _list ( node , context , false ) ;
for ( const selector of node . children ) {
} ,
if ( started ) {
context . write ( ', ' ) ;
}
context . visit ( selector ) ;
StyleSheet ( node , context ) {
started = true ;
context . write ( '<style' ) ;
attributes ( node , node . attributes , context , js _comments ) ;
context . write ( '>' ) ;
if ( node . children . length > 0 || node . comments . length > 0 ) {
context . indent ( ) ;
context . newline ( ) ;
print _children ( context , node . children , node . content . end , true ) ;
context . dedent ( ) ;
context . newline ( ) ;
}
}
context . write ( '</style>' ) ;
} ,
} ,
TypeSelector ( node , context ) {
TypeSelector ( node , context ) {
context . write ( node . name ) ;
context . write ( node . name ) ;
}
}
} ;
} ;
}
/ * *
/ * *
* @ param { AST . JSComment [ ] } comments
* @ param { AST . JSComment [ ] } comments
@ -845,34 +950,6 @@ const svelte_visitors = (comments) => ({
}
}
} ,
} ,
StyleSheet ( node , context ) {
context . write ( '<style' ) ;
attributes ( node , node . attributes , context , comments ) ;
context . write ( '>' ) ;
if ( node . children . length > 0 ) {
context . indent ( ) ;
context . newline ( ) ;
let started = false ;
for ( const child of node . children ) {
if ( started ) {
context . margin ( ) ;
context . newline ( ) ;
}
context . visit ( child ) ;
started = true ;
}
context . dedent ( ) ;
context . newline ( ) ;
}
context . write ( '</style>' ) ;
} ,
SvelteBody ( node , context ) {
SvelteBody ( node , context ) {
base _element ( node , context , comments ) ;
base _element ( node , context , comments ) ;
} ,
} ,