1- // @ts -expect-error Typing of css-tree is incomplete 
2- import  parse  from  'css-tree/parser' 
3- 
4- /** 
5-  * @typedef  {import('css-tree').CssNode } CssNode 
6-  * @typedef  {import('css-tree').List<CssNode> } List 
7-  * @typedef  {import('css-tree').CssLocation } CssLocation 
8-  * @typedef  {import('css-tree').Raw } Raw 
9-  * @typedef  {import('css-tree').StyleSheet } StyleSheet 
10-  * @typedef  {import('css-tree').Atrule } Atrule 
11-  * @typedef  {import('css-tree').AtrulePrelude } AtrulePrelude 
12-  * @typedef  {import('css-tree').Rule } Rule 
13-  * @typedef  {import('css-tree').SelectorList } SelectorList 
14-  * @typedef  {import('css-tree').Selector } Selector 
15-  * @typedef  {import('css-tree').PseudoClassSelector } PseudoClassSelector 
16-  * @typedef  {import('css-tree').PseudoElementSelector } PseudoElementSelector 
17-  * @typedef  {import('css-tree').Block } Block 
18-  * @typedef  {import('css-tree').Declaration } Declaration 
19-  * @typedef  {import('css-tree').Value } Value 
20-  * @typedef  {import('css-tree').Operator } Operator 
21-  */ 
1+ import  { 
2+ 	parse , 
3+ 	type  CssNode , 
4+ 	type  List , 
5+ 	type  CssLocation , 
6+ 	type  Raw , 
7+ 	type  StyleSheet , 
8+ 	type  Atrule , 
9+ 	type  AtrulePrelude , 
10+ 	type  Rule , 
11+ 	type  SelectorList , 
12+ 	type  Selector , 
13+ 	type  PseudoClassSelector , 
14+ 	type  PseudoElementSelector , 
15+ 	type  Block , 
16+ 	type  Declaration , 
17+ 	type  Value , 
18+ 	type  Operator , 
19+ }  from  'css-tree' 
2220
2321const  SPACE  =  ' ' 
2422const  EMPTY_STRING  =  '' 
@@ -42,66 +40,51 @@ const TYPE_PSEUDO_ELEMENT_SELECTOR = 'PseudoElementSelector'
4240const  TYPE_DECLARATION  =  'Declaration' 
4341const  TYPE_OPERATOR  =  'Operator' 
4442
45- /** @param  {string } str */ 
46- function  lowercase ( str )  { 
43+ function  lowercase ( str : string )  { 
4744	// Only create new strings in memory if we need to 
4845	if  ( / [ A - Z ] / . test ( str ) )  { 
4946		return  str . toLowerCase ( ) 
5047	} 
5148	return  str 
5249} 
5350
51+ export  type  FormatOptions  =  { 
52+ 	/** Whether to minify the CSS or keep it formatted */ 
53+ 	minify ?: boolean 
54+ 	/** Tell the formatter to use N spaces instead of tabs  */ 
55+ 	tab_size ?: number 
56+ } 
57+ 
5458/** 
55-  * @typedef  {Object } Options 
56-  * @property  {boolean } [minify] Whether to minify the CSS or keep it formatted 
57-  * @property  {number } [tab_size] Tell the formatter to use N spaces instead of tabs 
58-  * 
5959 * Format a string of CSS using some simple rules 
60-  * @param  {string } css The original CSS 
61-  * @param  {Options } [options] 
62-  * @returns  {string } The formatted CSS 
6360 */ 
64- export  function  format ( css ,  { 
65- 	minify =  false , 
66- 	tab_size =  undefined , 
67- }  =  Object . create ( null ) )  { 
68- 
61+ export  function  format ( css : string ,  {  minify =  false ,  tab_size =  undefined  } : FormatOptions  =  Object . create ( null ) ) : string  { 
6962	if  ( tab_size  !==  undefined  &&  Number ( tab_size )  <  1 )  { 
7063		throw  new  TypeError ( 'tab_size must be a number greater than 0' ) 
7164	} 
7265
73- 	/** @type  { number[] }  [start0, end0, start1, end1, etc.]*/ 
74- 	let  comments  =  [ ] 
66+ 	/** [start0, end0, start1, end1, etc.]*/ 
67+ 	let  comments :  number [ ]  =  [ ] 
7568
76- 	/** 
77- 	 * @param  {string } _ The comment text 
78- 	 * @param  {CssLocation } position 
79- 	 */ 
80- 	function  on_comment ( _ ,  position )  { 
69+ 	function  on_comment ( _ : string ,  position : CssLocation )  { 
8170		comments . push ( position . start . offset ,  position . end . offset ) 
8271	} 
8372
84- 	/** @type  {StyleSheet } */ 
8573	let  ast  =  parse ( css ,  { 
8674		positions : true , 
8775		parseAtrulePrelude : false , 
8876		parseCustomProperty : true , 
8977		parseValue : true , 
9078		onComment : on_comment , 
91- 	} ) 
79+ 	} )   as   StyleSheet 
9280
9381	const  NEWLINE  =  minify  ? EMPTY_STRING  : '\n' 
9482	const  OPTIONAL_SPACE  =  minify  ? EMPTY_STRING  : SPACE 
9583	const  LAST_SEMICOLON  =  minify  ? EMPTY_STRING  : SEMICOLON 
9684
9785	let  indent_level  =  0 
9886
99- 	/** 
100- 	 * Indent a string 
101- 	 * @param  {number } size 
102- 	 * @returns  {string } A string with [size] tabs/spaces 
103- 	 */ 
104- 	function  indent ( size )  { 
87+ 	function  indent ( size : number )  { 
10588		if  ( minify  ===  true )  return  EMPTY_STRING 
10689
10790		if  ( tab_size  !==  undefined )  { 
@@ -111,34 +94,29 @@ export function format(css, {
11194		return  '\t' . repeat ( size ) 
11295	} 
11396
114- 	/** @param  {CssNode } node */ 
115- 	function  substr ( node )  { 
97+ 	function  substr ( node : CssNode )  { 
11698		let  loc  =  node . loc 
11799		// If the node has no location, return an empty string 
118100		// This is necessary for space toggles 
119101		if  ( loc  ===  undefined  ||  loc  ===  null )  return  EMPTY_STRING 
120102		return  css . slice ( loc . start . offset ,  loc . end . offset ) 
121103	} 
122104
123- 	/** @param  {CssNode } node */ 
124- 	function  start_offset ( node )  { 
125- 		let  loc  =  /** @type  {CssLocation } */ ( node . loc ) 
126- 		return  loc . start . offset 
105+ 	function  start_offset ( node : CssNode )  { 
106+ 		return  node . loc ?. start . offset 
127107	} 
128108
129- 	/** @param  {CssNode } node */ 
130- 	function  end_offset ( node )  { 
131- 		let  loc  =  /** @type  {CssLocation } */ ( node . loc ) 
132- 		return  loc . end . offset 
109+ 	function  end_offset ( node : CssNode )  { 
110+ 		return  node . loc ?. end . offset 
133111	} 
134112
135113	/** 
136114	 * Get a comment from the CSS string after the first offset and before the second offset 
137- 	 * @param  { number | undefined }  after After which offset to look for comments 
138- 	 * @param  { number | undefined }  before Before which offset to look for comments 
139- 	 * @returns  { string | undefined }  The comment string, if found 
115+ 	 * @param  after After which offset to look for comments 
116+ 	 * @param  before Before which offset to look for comments 
117+ 	 * @returns  The comment string, if found 
140118	 */ 
141- 	function  print_comment ( after ,  before )  { 
119+ 	function  print_comment ( after ?:  number ,  before ?:  number ) :  string   |   undefined  { 
142120		if  ( minify  ===  true  ||  after  ===  undefined  ||  before  ===  undefined )  { 
143121			return  EMPTY_STRING 
144122		} 
@@ -160,9 +138,8 @@ export function format(css, {
160138		return  buffer 
161139	} 
162140
163- 	/** @param  {Rule } node */ 
164- 	function  print_rule ( node )  { 
165- 		let  buffer 
141+ 	function  print_rule ( node : Rule )  { 
142+ 		let  buffer  =  '' 
166143		let  prelude  =  node . prelude 
167144		let  block  =  node . block 
168145
@@ -182,8 +159,7 @@ export function format(css, {
182159		return  buffer 
183160	} 
184161
185- 	/** @param  {SelectorList } node */ 
186- 	function  print_selectorlist ( node )  { 
162+ 	function  print_selectorlist ( node : SelectorList )  { 
187163		let  buffer  =  EMPTY_STRING 
188164
189165		node . children . forEach ( ( selector ,  item )  =>  { 
@@ -205,12 +181,11 @@ export function format(css, {
205181		return  buffer 
206182	} 
207183
208- 	/** @param  {Selector | PseudoClassSelector | PseudoElementSelector } node */ 
209- 	function  print_simple_selector ( node )  { 
184+ 	function  print_simple_selector ( node : Selector  |  PseudoClassSelector  |  PseudoElementSelector )  { 
210185		let  buffer  =  EMPTY_STRING 
211- 		let  children  =  node . children   ||   [ ] 
186+ 		let  children  =  node . children 
212187
213- 		children . forEach ( ( child )  =>  { 
188+ 		children ? .forEach ( ( child )  =>  { 
214189			switch  ( child . type )  { 
215190				case  'TypeSelector' : { 
216191					buffer  +=  lowercase ( child . name ) 
@@ -327,8 +302,7 @@ export function format(css, {
327302		return  buffer 
328303	} 
329304
330- 	/** @param  {Block } node */ 
331- 	function  print_block ( node )  { 
305+ 	function  print_block ( node : Block )  { 
332306		let  children  =  node . children 
333307		let  buffer  =  OPTIONAL_SPACE 
334308
@@ -348,7 +322,7 @@ export function format(css, {
348322
349323		indent_level ++ 
350324
351- 		let  opening_comment  =  print_comment ( start_offset ( node ) ,  start_offset ( /**  @type  { CssNode } */ ( children . first ) ) ) 
325+ 		let  opening_comment  =  print_comment ( start_offset ( node ) ,  start_offset ( children . first ! ) ) 
352326		if  ( opening_comment )  { 
353327			buffer  +=  indent ( indent_level )  +  opening_comment  +  NEWLINE 
354328		} 
@@ -392,7 +366,7 @@ export function format(css, {
392366			} 
393367		} ) 
394368
395- 		let  closing_comment  =  print_comment ( end_offset ( /**  @type  { CssNode } */ ( children . last ) ) ,  end_offset ( node ) ) 
369+ 		let  closing_comment  =  print_comment ( end_offset ( children . last ! ) ,  end_offset ( node ) ) 
396370		if  ( closing_comment )  { 
397371			buffer  +=  NEWLINE  +  indent ( indent_level )  +  closing_comment 
398372		} 
@@ -403,8 +377,7 @@ export function format(css, {
403377		return  buffer 
404378	} 
405379
406- 	/** @param  {Atrule } node */ 
407- 	function  print_atrule ( node )  { 
380+ 	function  print_atrule ( node : Atrule )  { 
408381		let  buffer  =  indent ( indent_level )  +  '@' 
409382		let  prelude  =  node . prelude 
410383		let  block  =  node . block 
@@ -431,9 +404,8 @@ export function format(css, {
431404	 * here to force some nice formatting. 
432405	 * Should be OK perf-wise, since the amount of atrules in most 
433406	 * stylesheets are limited, so this won't be called too often. 
434- 	 * @param  {AtrulePrelude | Raw } node 
435407	 */ 
436- 	function  print_prelude ( node )  { 
408+ 	function  print_prelude ( node :  AtrulePrelude   |   Raw )  { 
437409		let  buffer  =  substr ( node ) 
438410
439411		return  buffer 
@@ -447,11 +419,10 @@ export function format(css, {
447419				let  space  =  operator  ===  '+'  ||  operator  ===  '-'  ? SPACE  : OPTIONAL_SPACE 
448420				return  `calc(${ left . trim ( ) } ${ space } ${ operator } ${ space } ${ right . trim ( ) }  
449421			} ) 
450- 			. replace ( / s e l e c t o r | u r l | s u p p o r t s | l a y e r \( / ig ,  ( match )  =>  lowercase ( match ) )  // lowercase function names 
422+ 			. replace ( / s e l e c t o r | u r l | s u p p o r t s | l a y e r \( / gi ,  ( match )  =>  lowercase ( match ) )  // lowercase function names 
451423	} 
452424
453- 	/** @param  {Declaration } node */ 
454- 	function  print_declaration ( node )  { 
425+ 	function  print_declaration ( node : Declaration )  { 
455426		let  property  =  node . property 
456427
457428		// Lowercase the property, unless it's a custom property (starts with --) 
@@ -481,8 +452,7 @@ export function format(css, {
481452		return  indent ( indent_level )  +  property  +  COLON  +  OPTIONAL_SPACE  +  value 
482453	} 
483454
484- 	/** @param  {List } children */ 
485- 	function  print_list ( children )  { 
455+ 	function  print_list ( children : List < CssNode > )  { 
486456		let  buffer  =  EMPTY_STRING 
487457
488458		children . forEach ( ( node ,  item )  =>  { 
@@ -519,8 +489,7 @@ export function format(css, {
519489		return  buffer 
520490	} 
521491
522- 	/** @param  {Operator } node */ 
523- 	function  print_operator ( node )  { 
492+ 	function  print_operator ( node : Operator )  { 
524493		let  buffer  =  EMPTY_STRING 
525494		// https://developer.mozilla.org/en-US/docs/Web/CSS/calc#notes 
526495		// The + and - operators must be surrounded by whitespace 
@@ -555,21 +524,15 @@ export function format(css, {
555524		return  buffer 
556525	} 
557526
558- 	/** @param  {Value | Raw } node */ 
559- 	function  print_value ( node )  { 
527+ 	function  print_value ( node : Value  |  Raw )  { 
560528		if  ( node . type  ===  'Raw' )  { 
561529			return  print_unknown ( node ,  0 ) 
562530		} 
563531
564532		return  print_list ( node . children ) 
565533	} 
566534
567- 	/** 
568- 	 * @param  {CssNode } node 
569- 	 * @param  {number } indent_level 
570- 	 * @returns  {string } A formatted unknown CSS string 
571- 	 */ 
572- 	function  print_unknown ( node ,  indent_level )  { 
535+ 	function  print_unknown ( node : CssNode ,  indent_level : number )  { 
573536		return  indent ( indent_level )  +  substr ( node ) . trim ( ) 
574537	} 
575538
@@ -603,7 +566,7 @@ export function format(css, {
603566			} 
604567		} ) 
605568
606- 		let  closing_comment  =  print_comment ( end_offset ( /**  @type  { CssNode } */ ( children . last ) ) ,  end_offset ( ast ) ) 
569+ 		let  closing_comment  =  print_comment ( end_offset ( children . last ! ) ,  end_offset ( ast ) ) 
607570		if  ( closing_comment )  { 
608571			buffer  +=  NEWLINE  +  closing_comment 
609572		} 
@@ -619,6 +582,6 @@ export function format(css, {
619582 * @param  {string } css The original CSS 
620583 * @returns  {string } The minified CSS 
621584 */ 
622- export  function  minify ( css )  { 
585+ export  function  minify ( css :  string ) :  string  { 
623586	return  format ( css ,  {  minify : true  } ) 
624587} 
0 commit comments