Skip to content

Commit 65d96a7

Browse files
committed
Issue with processing @import statements with new stream processing #97
1 parent c7cd917 commit 65d96a7

File tree

4 files changed

+161
-86
lines changed

4 files changed

+161
-86
lines changed

ClientDependency.Core/CompositeFiles/CssMinifier.cs

Lines changed: 82 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ namespace ClientDependency.Core.CompositeFiles
1818
{
1919
public sealed class CssMinifier
2020
{
21-
const int EOF = -1;
21+
private const int Eof = -1;
2222

23-
TextReader tr;
24-
StringBuilder sb;
25-
int theA;
26-
int theB;
27-
int theLookahead = EOF;
23+
private TextReader _tr;
24+
private StringBuilder _sb;
25+
int _theA;
26+
int _theB;
27+
int _theLookahead = Eof;
2828

2929

3030
/// <summary>
@@ -34,61 +34,61 @@ public sealed class CssMinifier
3434
/// <returns></returns>
3535
public string Minify(TextReader reader)
3636
{
37-
sb = new StringBuilder();
38-
tr = reader;
39-
theA = '\n';
40-
theB = 0;
41-
theLookahead = EOF;
42-
cssmin();
43-
return sb.ToString();
37+
_sb = new StringBuilder();
38+
_tr = reader;
39+
_theA = '\n';
40+
_theB = 0;
41+
_theLookahead = Eof;
42+
ExecuteCssMin();
43+
return _sb.ToString();
4444
}
4545

4646
/// <summary>
4747
/// Excute the actual minify
4848
/// </summary>
49-
void cssmin()
49+
private void ExecuteCssMin()
5050
{
51-
action(3);
52-
while (theA != EOF)
51+
Action(3);
52+
while (_theA != Eof)
5353
{
54-
switch (theA)
54+
switch (_theA)
5555
{
5656
case ' ':
5757
{
58-
switch (theB)
58+
switch (_theB)
5959
{
6060
case ' ': //body.Replace(" ", String.Empty);
6161
case '{': //body = body.Replace(" {", "{");
6262
case ':': //body = body.Replace(" {", "{");
6363
case '\n': //body = body.Replace(" \n", "\n");
6464
case '\r': //body = body.Replace(" \r", "\r");
6565
case '\t': //body = body.Replace(" \t", "\t");
66-
action(2);
66+
Action(2);
6767
break;
6868
default:
69-
action(1);
69+
Action(1);
7070
break;
7171
}
7272
break;
73-
}
73+
}
7474
case '\t': //body = body.Replace("\t", "");
7575
case '\r': //body = body.Replace("\r", "");
76-
action(2);
76+
Action(2);
7777
break;
7878
case '\n': //body = body.Replace("\n", "");
79-
if (char.IsWhiteSpace((char) theB))
79+
if (char.IsWhiteSpace((char)_theB))
8080
{
8181
//skip over whitespace
82-
action(3);
82+
Action(3);
8383
}
8484
else
8585
{
8686
//convert the line break to a space except when in the beginning
8787
//TODO: this isn't the best place to put this logic since all puts are done
8888
// in the action, but i don't see any other way to do this,
8989
//we could set theA = ' ' and call action(1) ?
90-
if (sb.Length > 0) put(' ');
91-
action(2);
90+
if (_sb.Length > 0) Put(' ');
91+
Action(2);
9292
}
9393
break;
9494
case '}':
@@ -97,10 +97,10 @@ void cssmin()
9797
case ',':
9898
case ';':
9999
//skip over whitespace
100-
action(char.IsWhiteSpace((char) theB) ? 3 : 1);
100+
Action(char.IsWhiteSpace((char)_theB) ? 3 : 1);
101101
break;
102102
default:
103-
action(1);
103+
Action(1);
104104
break;
105105
}
106106
}
@@ -110,97 +110,99 @@ 1 Output A. Copy B to A. Get the next B.
110110
2 Copy B to A. Get the next B. (Delete A).
111111
3 Get the next B. (Delete B).
112112
*/
113-
void action(int d)
113+
114+
private void Action(int d)
114115
{
115116
if (d <= 1)
116117
{
117-
put(theA);
118+
Put(_theA);
118119
}
119120
if (d <= 2)
120121
{
121-
theA = theB;
122-
if (theA == '\'' || theA == '"')
122+
_theA = _theB;
123+
if (_theA == '\'' || _theA == '"')
123124
{
124125
for (;;)
125126
{
126-
put(theA);
127-
theA = get();
128-
if (theA == theB)
127+
Put(_theA);
128+
_theA = Get();
129+
if (_theA == _theB)
129130
{
130131
break;
131132
}
132-
if (theA <= '\n')
133+
if (_theA <= '\n')
133134
{
134-
throw new FormatException(string.Format("Error: unterminated string literal: {0}\n", theA));
135+
throw new FormatException(string.Format("Error: unterminated string literal: {0}\n", _theA));
135136
}
136-
if (theA == '\\')
137+
if (_theA == '\\')
137138
{
138-
put(theA);
139-
theA = get();
139+
Put(_theA);
140+
_theA = Get();
140141
}
141142
}
142143
}
143144
}
144145
if (d <= 3)
145146
{
146-
theB = next();
147-
if (theB == '/' && (theA == '(' || theA == ',' || theA == '=' ||
148-
theA == '[' || theA == '!' || theA == ':' ||
149-
theA == '&' || theA == '|' || theA == '?' ||
150-
theA == '{' || theA == '}' || theA == ';' ||
151-
theA == '\n'))
147+
_theB = Next();
148+
if (_theB == '/' && (_theA == '(' || _theA == ',' || _theA == '=' ||
149+
_theA == '[' || _theA == '!' || _theA == ':' ||
150+
_theA == '&' || _theA == '|' || _theA == '?' ||
151+
_theA == '{' || _theA == '}' || _theA == ';' ||
152+
_theA == '\n'))
152153
{
153-
put(theA);
154-
put(theB);
154+
Put(_theA);
155+
Put(_theB);
155156
for (;;)
156157
{
157-
theA = get();
158-
if (theA == '/')
158+
_theA = Get();
159+
if (_theA == '/')
159160
{
160161
break;
161162
}
162-
else if (theA == '\\')
163+
else if (_theA == '\\')
163164
{
164-
put(theA);
165-
theA = get();
165+
Put(_theA);
166+
_theA = Get();
166167
}
167-
else if (theA <= '\n')
168+
else if (_theA <= '\n')
168169
{
169-
throw new FormatException(string.Format("Error: unterminated Regular Expression literal : {0}.\n", theA));
170+
throw new FormatException(string.Format("Error: unterminated Regular Expression literal : {0}.\n", _theA));
170171
}
171-
put(theA);
172+
Put(_theA);
172173
}
173-
theB = next();
174+
_theB = Next();
174175
}
175176
}
176177
}
177178
/* next -- get the next character, excluding comments. peek() is used to see
178179
if a '/' is followed by a '*'.
179180
*/
180-
int next()
181+
182+
private int Next()
181183
{
182-
int c = get();
184+
int c = Get();
183185
if (c == '/')
184186
{
185-
switch (peek())
186-
{
187+
switch (Peek())
188+
{
187189
case '*':
188190
{
189-
get();
191+
Get();
190192
for (;;)
191193
{
192-
switch (get())
194+
switch (Get())
193195
{
194196
case '*':
195197
{
196-
if (peek() == '/')
198+
if (Peek() == '/')
197199
{
198-
get();
200+
Get();
199201
return ' ';
200202
}
201203
break;
202204
}
203-
case EOF:
205+
case Eof:
204206
{
205207
throw new FormatException("Error: Unterminated comment.\n");
206208
}
@@ -217,24 +219,26 @@ int next()
217219
}
218220
/* peek -- get the next character without getting it.
219221
*/
220-
int peek()
222+
223+
private int Peek()
221224
{
222-
theLookahead = get();
223-
return theLookahead;
225+
_theLookahead = Get();
226+
return _theLookahead;
224227
}
225228
/* get -- return the next character from stdin. Watch out for lookahead. If
226229
the character is a control character, translate it to a space or
227230
linefeed.
228231
*/
229-
int get()
232+
233+
private int Get()
230234
{
231-
int c = theLookahead;
232-
theLookahead = EOF;
233-
if (c == EOF)
235+
int c = _theLookahead;
236+
_theLookahead = Eof;
237+
if (c == Eof)
234238
{
235-
c = tr.Read();
239+
c = _tr.Read();
236240
}
237-
if (c >= ' ' || c == '\n' || c == EOF)
241+
if (c >= ' ' || c == '\n' || c == Eof)
238242
{
239243
return c;
240244
}
@@ -244,9 +248,10 @@ int get()
244248
}
245249
return ' ';
246250
}
247-
void put(int c)
251+
252+
private void Put(int c)
248253
{
249-
sb.Append((char)c);
254+
_sb.Append((char)c);
250255
}
251256
}
252257
}

ClientDependency.Core/CssHelper.cs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,16 @@ public static long ParseImportStatements(Stream stream, out IEnumerable<string>
8383

8484
//new reader (but don't dispose since we don't want to dispose the stream)
8585
TextReader reader = new StreamReader(stream);
86-
var exit = false;
8786
var currIndex = -1;
8887

89-
while (exit == false)
88+
while (true)
9089
{
9190
var next = reader.Read();
92-
if (next == -1) exit = true;
91+
if (next == -1)
92+
{
93+
break;
94+
}
95+
9396
var c = (char) next;
9497

9598
//still searching for the '@import' block at the top
@@ -100,7 +103,7 @@ public static long ParseImportStatements(Stream stream, out IEnumerable<string>
100103
}
101104
else if (currIndex == -2)
102105
{
103-
//we've found the searchStatement, keep processing until we hit the end
106+
//we've found the entire searchStatement, keep processing until we hit the semicolon
104107

105108
tempImports.Append(c);
106109

@@ -110,7 +113,7 @@ public static long ParseImportStatements(Stream stream, out IEnumerable<string>
110113
currIndex = -1;
111114
//write to the main imports and reset the temp one
112115
imports.Append(tempImports);
113-
tempImports = new StringBuilder();
116+
tempImports.Clear();
114117
}
115118
}
116119
else if (searchStatement[currIndex + 1] == c)
@@ -126,9 +129,10 @@ public static long ParseImportStatements(Stream stream, out IEnumerable<string>
126129
}
127130
else
128131
{
129-
//time to quit
130-
exit = true;
131-
}
132+
//reset and start again
133+
currIndex = -1;
134+
tempImports.Clear();
135+
}
132136
}
133137

134138
externalImportedPaths = ParseImportStatements(imports.ToString(), out importedPaths);

0 commit comments

Comments
 (0)