@@ -2,10 +2,15 @@ import * as ts from 'typescript';
2
2
import { isNoSubstitutionTemplateLiteral , isTemplateExpression } from './ts-is-kind' ;
3
3
4
4
type State = ';' | ';$' | 'x' | ' ' | '\n' | '"' | '(' | '\'' | '/' | '//' | ';/' | ';//' | '/$' | '//$' | '/*' | '/**' | ';/*' | ';/**' | '/*$' | '/*$*' ;
5
- type ReducerResult = { emit ?: string ; skipEmit ?: boolean ; state ?: State ; } | void ;
5
+ type StateDataDef = {
6
+ [ '(' ] : { count : number }
7
+ }
8
+ type StateData < K extends State > = K extends keyof StateDataDef ? StateDataDef [ K ] : void
9
+ type StateResult = { [ K in State ] : K extends keyof StateDataDef ? [ K , StateDataDef [ K ] ] : K } [ State ]
10
+ type ReducerResult = { emit ?: string ; skipEmit ?: boolean ; state ?: StateResult ; } | void ;
6
11
type StateMachine = {
7
12
[ K in State ] : {
8
- next ?( ch : string ) : ReducerResult ;
13
+ next ?( ch : string , data : StateData < K > ) : ReducerResult ;
9
14
flush ?( last : boolean ) : ReducerResult ;
10
15
}
11
16
} ;
@@ -21,7 +26,8 @@ function isSpace(ch: string) {
21
26
const stateMachine : StateMachine = {
22
27
';' : {
23
28
next ( ch ) {
24
- if ( ch == '\'' || ch == '"' || ch == '(' ) return { state : ch }
29
+ if ( ch == '(' ) return { state : [ '(' , { count : 1 } ] }
30
+ if ( ch == '\'' || ch == '"' ) return { state : ch }
25
31
if ( isSpace ( ch ) ) return { skipEmit : true }
26
32
if ( ch == '/' ) return { state : ';/' , skipEmit : true }
27
33
if ( isSymbol ( ch ) ) return ;
@@ -33,7 +39,8 @@ const stateMachine: StateMachine = {
33
39
} ,
34
40
';$' : { // after placeholder
35
41
next ( ch ) {
36
- if ( ch == '\'' || ch == '"' || ch == '(' ) return { state : ch }
42
+ if ( ch == '(' ) return { state : [ '(' , { count : 1 } ] }
43
+ if ( ch == '\'' || ch == '"' ) return { state : ch }
37
44
if ( isSpace ( ch ) ) return { skipEmit : true , state : ' ' } // we may need a space
38
45
if ( ch == '/' ) return { state : '/' , skipEmit : true }
39
46
if ( isSymbol ( ch ) ) return { state : ';' } ;
@@ -42,15 +49,17 @@ const stateMachine: StateMachine = {
42
49
} ,
43
50
'x' : {
44
51
next ( ch ) {
45
- if ( ch == '\'' || ch == '"' || ch == '(' ) return { state : ch }
52
+ if ( ch == '(' ) return { state : [ '(' , { count : 1 } ] }
53
+ if ( ch == '\'' || ch == '"' ) return { state : ch }
46
54
if ( isSpace ( ch ) ) return { state : ' ' , skipEmit : true }
47
55
if ( ch == '/' ) return { state : '/' , skipEmit : true }
48
56
if ( isSymbol ( ch ) ) return { state : ';' } ;
49
57
}
50
58
} ,
51
59
' ' : { // may need space
52
60
next ( ch ) {
53
- if ( ch == '\'' || ch == '"' || ch == '(' ) return { state : ch , emit : ' ' + ch }
61
+ if ( ch == '(' ) return { state : [ '(' , { count : 1 } ] , emit : ' ' + ch }
62
+ if ( ch == '\'' || ch == '"' ) return { state : ch , emit : ' ' + ch }
54
63
if ( isSpace ( ch ) ) return { state : ' ' , skipEmit : true }
55
64
if ( ch == '/' ) return { state : '/' , skipEmit : true }
56
65
if ( isSymbol ( ch ) ) return { state : ';' } ;
@@ -62,7 +71,8 @@ const stateMachine: StateMachine = {
62
71
} ,
63
72
'\n' : { // may need new line
64
73
next ( ch ) {
65
- if ( ch == '\'' || ch == '"' || ch == '(' ) return { state : ch , emit : '\n' + ch }
74
+ if ( ch == '(' ) return { state : [ '(' , { count : 1 } ] , emit : '\n' + ch }
75
+ if ( ch == '\'' || ch == '"' ) return { state : ch , emit : '\n' + ch }
66
76
if ( isSpace ( ch ) ) return { state : '\n' , skipEmit : true }
67
77
if ( ch == '/' ) return { state : '/' , emit : '\n' }
68
78
if ( isSymbol ( ch ) ) return { state : ';' , emit : '\n' + ch } ;
@@ -80,8 +90,13 @@ const stateMachine: StateMachine = {
80
90
}
81
91
} ,
82
92
'(' : {
83
- next ( ch ) {
84
- if ( ch == ')' ) return { state : ';' } ; // maybe return ' '? then it'd always add space after
93
+ next ( ch , { count } ) {
94
+ if ( ch == '(' ) return { state : [ '(' , { count : count + 1 } ] }
95
+ if ( ch == ')' )
96
+ if ( count > 1 )
97
+ return { state : [ '(' , { count : count - 1 } ] }
98
+ else
99
+ return { state : ';' } ; // maybe return ' '? then it'd always add space after
85
100
}
86
101
} ,
87
102
'/' : {
@@ -179,6 +194,7 @@ const stateMachine: StateMachine = {
179
194
180
195
export function createMinifier ( ) : ( next : string , last ?: boolean ) => string {
181
196
let state : State = ';' ;
197
+ let stateData : StateData < State > = undefined as StateData < ';' >
182
198
183
199
return ( next , last = false ) => {
184
200
let minified = '' ;
@@ -189,7 +205,14 @@ export function createMinifier(): (next: string, last?: boolean) => string {
189
205
minified += ch ;
190
206
} else {
191
207
if ( result . state !== undefined )
192
- state = result . state ;
208
+ {
209
+ if ( typeof result . state === 'string' )
210
+ state = result . state ;
211
+ else {
212
+ state = result . state [ 0 ]
213
+ stateData = result . state [ 1 ]
214
+ }
215
+ }
193
216
if ( result . emit !== undefined )
194
217
minified += result . emit ;
195
218
else if ( result . skipEmit !== true && ch !== undefined )
@@ -203,7 +226,7 @@ export function createMinifier(): (next: string, last?: boolean) => string {
203
226
const ch = next [ pos ++ ] ;
204
227
const reducer = stateMachine [ state ] ;
205
228
const prevState = state ;
206
- const reducerResult = reducer . next && reducer . next ( ch ) ;
229
+ const reducerResult = reducer . next && reducer . next ( ch , stateData as any ) ;
207
230
apply ( reducerResult , ch )
208
231
// console.log('next(', { ch, state: prevState }, '): ', reducerResult, ' -> ', { state, minified });
209
232
}
0 commit comments