15
15
class JSStrip
16
16
{
17
17
18
+ const REGEX_STARTERS = [
19
+ '( ' , '= ' , '< ' , '> ' , '? ' , '[ ' , '{ ' , ', ' , '; ' , ': ' , '! ' , '& ' , '| ' , '+ ' , '- ' , '% ' , '~ ' , '^ ' ,
20
+ 'return ' , 'yield ' , 'else ' , 'throw ' , 'await '
21
+ ];
22
+ const WHITESPACE_CHARS = [" " , "\t" , "\n" , "\r" , "\0" , "\x0B" ];
23
+
24
+ /** items that don't need spaces next to them */
25
+ const CHARS = "^&|!+\-*\/%=\?:;,{}()<>% \t\n\r' \"`[]~^ " ;
26
+
18
27
/**
19
- * @param string $s
28
+ * items which need a space if the sign before and after whitespace is equal.
29
+ * E.g. '+ ++' may not be compressed to '+++' --> syntax error.
30
+ */
31
+ const OPS = "+-/ " ;
32
+
33
+ /**
34
+ * Compress the given code
35
+ *
36
+ * @param string $source The JavaScript code to compress
20
37
* @return string
21
38
*/
22
- function compress ($ s )
39
+ function compress ($ source )
23
40
{
24
- $ s = ltrim ($ s ); // strip all initial whitespace
25
- $ s .= "\n" ;
41
+ $ source = ltrim ($ source ); // strip all initial whitespace
42
+ $ source .= "\n" ;
26
43
$ i = 0 ; // char index for input string
27
44
$ j = 0 ; // char forward index for input string
28
45
$ line = 0 ; // line number of file (close to it anyways)
29
- $ slen = strlen ($ s ); // size of input string
46
+ $ slen = strlen ($ source ); // size of input string
30
47
$ lch = '' ; // last char added
31
48
$ result = '' ; // we store the final result here
32
49
33
- // items that don't need spaces next to them
34
- $ chars = "^&|!+\-*\/%=\?:;,{}()<>% \t\n\r' \"`[]~^ " ;
35
-
36
- // items which need a space if the sign before and after whitespace is equal.
37
- // E.g. '+ ++' may not be compressed to '+++' --> syntax error.
38
- $ ops = "+-/ " ;
39
-
40
- $ regex_starters = array ("( " , "= " , "< " , "> " , "? " , "[ " , "{ " , ", " , "; " , ": " , "! " , "& " , "| " , "+ " , "- " , "% " , "~ " , "^ " , "return " , "yield " , "else " , "throw " , "await " );
41
- $ whitespaces_chars = array (" " , "\t" , "\n" , "\r" , "\0" , "\x0B" );
42
50
43
51
while ($ i < $ slen ) {
44
52
// skip all "boring" characters. This is either
45
53
// reserved word (e.g. "for", "else", "if") or a
46
54
// variable/object/method (e.g. "foo.color")
47
- while ($ i < $ slen && (strpos ($ chars , $ s [$ i ]) === false )) {
48
- $ result .= $ s [$ i ];
55
+ while ($ i < $ slen && (strpos (self :: CHARS , $ source [$ i ]) === false )) {
56
+ $ result .= $ source [$ i ];
49
57
$ i = $ i + 1 ;
50
58
}
51
59
52
- $ ch = $ s [$ i ];
60
+ $ ch = $ source [$ i ];
53
61
// multiline comments (keeping IE conditionals)
54
- if ($ ch == '/ ' && $ s [$ i + 1 ] == '* ' && $ s [$ i + 2 ] != '@ ' ) {
55
- $ endC = strpos ($ s , '*/ ' , $ i + 2 );
62
+ if ($ ch == '/ ' && $ source [$ i + 1 ] == '* ' && $ source [$ i + 2 ] != '@ ' ) {
63
+ $ endC = strpos ($ source , '*/ ' , $ i + 2 );
56
64
if ($ endC === false ) trigger_error ('Found invalid /*..*/ comment ' , E_USER_ERROR );
57
65
58
66
// check if this is a NOCOMPRESS comment
59
- if (substr ($ s , $ i , $ endC + 2 - $ i ) == '/* BEGIN NOCOMPRESS */ ' ) {
67
+ if (substr ($ source , $ i , $ endC + 2 - $ i ) == '/* BEGIN NOCOMPRESS */ ' ) {
60
68
// take nested NOCOMPRESS comments into account
61
69
$ depth = 0 ;
62
70
$ nextNC = $ endC ;
63
71
do {
64
- $ beginNC = strpos ($ s , '/* BEGIN NOCOMPRESS */ ' , $ nextNC + 2 );
65
- $ endNC = strpos ($ s , '/* END NOCOMPRESS */ ' , $ nextNC + 2 );
72
+ $ beginNC = strpos ($ source , '/* BEGIN NOCOMPRESS */ ' , $ nextNC + 2 );
73
+ $ endNC = strpos ($ source , '/* END NOCOMPRESS */ ' , $ nextNC + 2 );
66
74
67
75
if ($ endNC === false ) trigger_error ('Found invalid NOCOMPRESS comment ' , E_USER_ERROR );
68
76
if ($ beginNC !== false && $ beginNC < $ endNC ) {
@@ -75,7 +83,7 @@ function compress($s)
75
83
} while ($ depth >= 0 );
76
84
77
85
// verbatim copy contents, trimming but putting it on its own line
78
- $ result .= "\n" . trim (substr ($ s , $ i + 22 , $ endNC - ($ i + 22 ))) . "\n" ; // BEGIN comment = 22 chars
86
+ $ result .= "\n" . trim (substr ($ source , $ i + 22 , $ endNC - ($ i + 22 ))) . "\n" ; // BEGIN comment = 22 chars
79
87
$ i = $ endNC + 20 ; // END comment = 20 chars
80
88
} else {
81
89
$ i = $ endC + 2 ;
@@ -84,8 +92,8 @@ function compress($s)
84
92
}
85
93
86
94
// singleline
87
- if ($ ch == '/ ' && $ s [$ i + 1 ] == '/ ' ) {
88
- $ endC = strpos ($ s , "\n" , $ i + 2 );
95
+ if ($ ch == '/ ' && $ source [$ i + 1 ] == '/ ' ) {
96
+ $ endC = strpos ($ source , "\n" , $ i + 2 );
89
97
if ($ endC === false ) trigger_error ('Invalid comment ' , E_USER_ERROR );
90
98
$ i = $ endC ;
91
99
continue ;
@@ -95,32 +103,32 @@ function compress($s)
95
103
if ($ ch == '/ ' ) {
96
104
// rewind, skip white space
97
105
$ j = 1 ;
98
- while (in_array ($ s [$ i - $ j ], $ whitespaces_chars )) {
106
+ while (in_array ($ source [$ i - $ j ], self :: WHITESPACE_CHARS )) {
99
107
$ j = $ j + 1 ;
100
108
}
101
109
if (current (array_filter (
102
- $ regex_starters ,
103
- function ($ e ) use ($ s , $ i , $ j ) {
110
+ self :: REGEX_STARTERS ,
111
+ function ($ e ) use ($ source , $ i , $ j ) {
104
112
$ len = strlen ($ e );
105
113
$ idx = $ i - $ j + 1 - $ len ;
106
- return substr ($ s , $ idx , $ len ) === $ e ;
114
+ return substr ($ source , $ idx , $ len ) === $ e ;
107
115
}
108
116
))) {
109
117
// yes, this is an re
110
118
// now move forward and find the end of it
111
119
$ j = 1 ;
112
120
// we set this flag when inside a character class definition, enclosed by brackets [] where '/' does not terminate the re
113
121
$ ccd = false ;
114
- while ($ ccd || $ s [$ i + $ j ] != '/ ' ) {
115
- if ($ s [$ i + $ j ] == '\\' ) $ j = $ j + 2 ;
122
+ while ($ ccd || $ source [$ i + $ j ] != '/ ' ) {
123
+ if ($ source [$ i + $ j ] == '\\' ) $ j = $ j + 2 ;
116
124
else {
117
125
$ j ++;
118
126
// check if we entered/exited a character class definition and set flag accordingly
119
- if ($ s [$ i + $ j - 1 ] == '[ ' ) $ ccd = true ;
120
- else if ($ s [$ i + $ j - 1 ] == '] ' ) $ ccd = false ;
127
+ if ($ source [$ i + $ j - 1 ] == '[ ' ) $ ccd = true ;
128
+ else if ($ source [$ i + $ j - 1 ] == '] ' ) $ ccd = false ;
121
129
}
122
130
}
123
- $ result .= substr ($ s , $ i , $ j + 1 );
131
+ $ result .= substr ($ source , $ i , $ j + 1 );
124
132
$ i = $ i + $ j + 1 ;
125
133
continue ;
126
134
}
@@ -129,14 +137,14 @@ function ($e) use ($s, $i, $j) {
129
137
// double quote strings
130
138
if ($ ch == '" ' ) {
131
139
$ j = 1 ;
132
- while (($ i + $ j < $ slen ) && $ s [$ i + $ j ] != '" ' ) {
133
- if ($ s [$ i + $ j ] == '\\' && ($ s [$ i + $ j + 1 ] == '" ' || $ s [$ i + $ j + 1 ] == '\\' )) {
140
+ while (($ i + $ j < $ slen ) && $ source [$ i + $ j ] != '" ' ) {
141
+ if ($ source [$ i + $ j ] == '\\' && ($ source [$ i + $ j + 1 ] == '" ' || $ source [$ i + $ j + 1 ] == '\\' )) {
134
142
$ j += 2 ;
135
143
} else {
136
144
$ j += 1 ;
137
145
}
138
146
}
139
- $ string = substr ($ s , $ i , $ j + 1 );
147
+ $ string = substr ($ source , $ i , $ j + 1 );
140
148
// remove multiline markers:
141
149
$ string = str_replace ("\\\n" , '' , $ string );
142
150
$ result .= $ string ;
@@ -147,14 +155,14 @@ function ($e) use ($s, $i, $j) {
147
155
// single quote strings
148
156
if ($ ch == "' " ) {
149
157
$ j = 1 ;
150
- while (($ i + $ j < $ slen ) && $ s [$ i + $ j ] != "' " ) {
151
- if ($ s [$ i + $ j ] == '\\' && ($ s [$ i + $ j + 1 ] == "' " || $ s [$ i + $ j + 1 ] == '\\' )) {
158
+ while (($ i + $ j < $ slen ) && $ source [$ i + $ j ] != "' " ) {
159
+ if ($ source [$ i + $ j ] == '\\' && ($ source [$ i + $ j + 1 ] == "' " || $ source [$ i + $ j + 1 ] == '\\' )) {
152
160
$ j += 2 ;
153
161
} else {
154
162
$ j += 1 ;
155
163
}
156
164
}
157
- $ string = substr ($ s , $ i , $ j + 1 );
165
+ $ string = substr ($ source , $ i , $ j + 1 );
158
166
// remove multiline markers:
159
167
$ string = str_replace ("\\\n" , '' , $ string );
160
168
$ result .= $ string ;
@@ -165,14 +173,14 @@ function ($e) use ($s, $i, $j) {
165
173
// backtick strings
166
174
if ($ ch == "` " ) {
167
175
$ j = 1 ;
168
- while (($ i + $ j < $ slen ) && $ s [$ i + $ j ] != "` " ) {
169
- if ($ s [$ i + $ j ] == '\\' && ($ s [$ i + $ j + 1 ] == "` " || $ s [$ i + $ j + 1 ] == '\\' )) {
176
+ while (($ i + $ j < $ slen ) && $ source [$ i + $ j ] != "` " ) {
177
+ if ($ source [$ i + $ j ] == '\\' && ($ source [$ i + $ j + 1 ] == "` " || $ source [$ i + $ j + 1 ] == '\\' )) {
170
178
$ j += 2 ;
171
179
} else {
172
180
$ j += 1 ;
173
181
}
174
182
}
175
- $ string = substr ($ s , $ i , $ j + 1 );
183
+ $ string = substr ($ source , $ i , $ j + 1 );
176
184
// remove multiline markers:
177
185
$ string = str_replace ("\\\n" , '' , $ string );
178
186
$ result .= $ string ;
@@ -186,18 +194,18 @@ function ($e) use ($s, $i, $j) {
186
194
187
195
// Only consider deleting whitespace if the signs before and after
188
196
// are not equal and are not an operator which may not follow itself.
189
- if ($ i + 1 < $ slen && ((!$ lch || $ s [$ i + 1 ] == ' ' )
190
- || $ lch != $ s [$ i + 1 ]
191
- || strpos ($ ops , $ s [$ i + 1 ]) === false )) {
197
+ if ($ i + 1 < $ slen && ((!$ lch || $ source [$ i + 1 ] == ' ' )
198
+ || $ lch != $ source [$ i + 1 ]
199
+ || strpos (self :: OPS , $ source [$ i + 1 ]) === false )) {
192
200
// leading spaces
193
- if ($ i + 1 < $ slen && (strpos ($ chars , $ s [$ i + 1 ]) !== false )) {
201
+ if ($ i + 1 < $ slen && (strpos (self :: CHARS , $ source [$ i + 1 ]) !== false )) {
194
202
$ i = $ i + 1 ;
195
203
continue ;
196
204
}
197
205
// trailing spaces
198
206
// if this ch is space AND the last char processed
199
207
// is special, then skip the space
200
- if ($ lch && (strpos ($ chars , $ lch ) !== false )) {
208
+ if ($ lch && (strpos (self :: CHARS , $ lch ) !== false )) {
201
209
$ i = $ i + 1 ;
202
210
continue ;
203
211
}
0 commit comments