+22
-32
src/minify.rs
+22
-32
src/minify.rs
···
1
1
pub fn minify_html(input: &str) -> String {
2
2
let mut out = String::with_capacity(input.len());
3
3
let mut in_tag = false;
4
-
let mut last = ' ';
4
+
let mut last_was_space = false;
5
5
6
-
let chars: Vec<char> = input.chars().collect();
7
-
8
-
for (i, c) in chars.iter().enumerate() {
6
+
for c in input.chars() {
9
7
match c {
10
8
'<' => {
11
9
in_tag = true;
12
-
13
-
// remove space before '<'
14
-
if last.is_whitespace() && !out.ends_with('>') {
15
-
// trim trailing space
16
-
while out.ends_with(' ') {
17
-
out.pop();
18
-
}
19
-
}
20
-
10
+
// Do not trim potential preceding text space here; that can
11
+
// break patterns like "on " + "<a>" into "on<a>".
21
12
out.push('<');
22
-
last = '<';
13
+
last_was_space = false;
23
14
}
24
15
25
16
'>' => {
26
17
in_tag = false;
27
18
out.push('>');
28
-
last = '>';
19
+
last_was_space = false;
29
20
}
30
21
31
-
c if c.is_whitespace() => {
22
+
ch if ch.is_whitespace() => {
32
23
if in_tag {
33
-
// inside a tag collapse to a single space
34
-
if last != ' ' {
24
+
// Inside a tag: collapse any whitespace run to a single space
25
+
// so attributes stay tidy.
26
+
if !last_was_space {
35
27
out.push(' ');
36
-
last = ' ';
28
+
last_was_space = true;
37
29
}
38
30
} else {
39
-
// outside a tag
40
-
// remove text spaces *between tags*
41
-
let next = chars.get(i + 1).copied().unwrap_or('x');
42
-
if last == '>' && next == '<' {
43
-
// skip whitespace entirely
44
-
continue;
45
-
}
46
-
47
-
// otherwise allow a single space
48
-
if last != ' ' {
31
+
// Outside a tag (text content):
32
+
// - Collapse runs of whitespace to a single space,
33
+
// - but never remove the space entirely.
34
+
//
35
+
// This preserves spaces like:
36
+
// "on " + "<a>tangled</a>" => "on <a>tangled</a>"
37
+
// instead of "on<a>tangled</a>".
38
+
if !last_was_space {
49
39
out.push(' ');
50
-
last = ' ';
40
+
last_was_space = true;
51
41
}
52
42
}
53
43
}
54
44
55
45
_ => {
56
-
out.push(*c);
57
-
last = *c;
46
+
out.push(c);
47
+
last_was_space = false;
58
48
}
59
49
}
60
50
}