Skip to content

Commit 505de5b

Browse files
authored
fix(span): track end tag positions correctly in naive state switching mode (#124)
1 parent c700599 commit 505de5b

File tree

8 files changed

+244
-84
lines changed

8 files changed

+244
-84
lines changed

src/emitters/callback.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -447,11 +447,18 @@ where
447447
_ => {}
448448
}
449449

450-
if self.emitter_state.naively_switch_states {
450+
let next_state = if self.emitter_state.naively_switch_states {
451451
naive_next_state(&self.emitter_state.last_start_tag)
452452
} else {
453453
None
454+
};
455+
456+
// After flushing characters, initialize a new string span for text-accumulating states
457+
if next_state.is_some() {
458+
self.init_string();
454459
}
460+
461+
next_state
455462
}
456463
fn emit_current_comment(&mut self) {
457464
self.callback_state.emit_event(

src/machine.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ pub(crate) mod states {
6262
enter_state!(slf, CharacterReference, false)
6363
}
6464
Some(b"<") => {
65+
slf.emitter.start_open_tag();
6566
switch_to!(slf, RcDataLessThanSign)
6667
}
6768
Some(b"\0") => {
@@ -85,6 +86,7 @@ pub(crate) mod states {
8586
slf,
8687
match xs {
8788
Some(b"<") => {
89+
slf.emitter.start_open_tag();
8890
switch_to!(slf, RawTextLessThanSign)
8991
}
9092
Some(b"\0") => {
@@ -108,6 +110,7 @@ pub(crate) mod states {
108110
slf,
109111
match xs {
110112
Some(b"<") => {
113+
slf.emitter.start_open_tag();
111114
switch_to!(slf, ScriptDataLessThanSign)
112115
}
113116
Some(b"\0") => {

tests/test_spans.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,3 +210,45 @@ fn simple() {
210210
},
211211
);
212212
}
213+
214+
#[test]
215+
fn simple_with_naively_switch_states() {
216+
let msg: Rc<RefCell<Option<_>>> = Default::default();
217+
run(
218+
include_str!("test_spans/input.html"),
219+
include_str!("test_spans/naively_switch_states.stdout.txt").trim(),
220+
|m| {
221+
*msg.borrow_mut() = Some(m);
222+
let mut emitter = DefaultEmitter::new_with_span();
223+
emitter.naively_switch_states(true);
224+
emitter
225+
},
226+
|token| {
227+
let mut msg = msg.borrow_mut();
228+
let msg = msg.as_mut().unwrap();
229+
match token {
230+
Token::StartTag(start_tag) => {
231+
msg.add(Level::Info, start_tag.span, "start tag");
232+
for (_name, value) in start_tag.attributes {
233+
msg.add(Level::Note, value.span, "attribute");
234+
}
235+
}
236+
Token::EndTag(end_tag) => {
237+
msg.add(Level::Note, end_tag.span, "end tag");
238+
}
239+
Token::String(v) => {
240+
if **v != b"\n" {
241+
msg.add(Level::Info, v.span, "string");
242+
}
243+
}
244+
Token::Comment(v) => {
245+
msg.add(Level::Info, v.span, "comment");
246+
}
247+
Token::Doctype(v) => {
248+
msg.add(Level::Info, v.span, "doctype");
249+
}
250+
Token::Error(error) => panic!("error: {}", *error),
251+
}
252+
},
253+
);
254+
}
Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
error: test output
2-
|
3-
1 | <!DOCTYPE html>
4-
| --------------- info: doctype
5-
2 | <h1>Hello</h1>
6-
| ---- note: close start tag
7-
| |
8-
| h1 start
9-
3 | <p attr="value"></p>
10-
| ---- ----- attribute value
11-
| |
12-
| attribute name
13-
4 | <p>content</p>
14-
| ------- note: content
15-
5 | <!-- A comment -->
16-
| ------------------ info: comment
17-
6 | <h2>Subtitle</h2>
18-
| ----- info: end tag
19-
7 | <br/>
20-
| - note: close start tag
21-
|
2+
|
3+
1 | <!DOCTYPE html>
4+
| --------------- info: doctype
5+
2 | <h1>Hello</h1>
6+
| ---- note: close start tag
7+
| |
8+
| h1 start
9+
3 | <p attr="value"></p>
10+
| ---- ----- attribute value
11+
| |
12+
| attribute name
13+
4 | <p>content</p>
14+
| ------- note: content
15+
5 | <!-- A comment -->
16+
| ------------------ info: comment
17+
6 | <h2>Subtitle</h2>
18+
| ----- info: end tag
19+
7 | <br/>
20+
| - note: close start tag
21+
8 | <script>console.log('hello')</script>
22+
9 | <script>nested('<div></div>')</script>
23+
10 | <style>.class { color: red; }</style>
24+
11 | <textarea>user input</textarea>
25+
|
Lines changed: 63 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,64 @@
11
error: test output
2-
|
3-
1 | <!DOCTYPE html>
4-
| --------------- info: doctype
5-
2 | <h1>Hello</h1>
6-
| -------------- info: end tag
7-
| | ||
8-
| | |note: string
9-
| | note: close start tag
10-
| open start tag
11-
3 | <p attr="value"></p>
12-
| ------- ----- ----- info: end tag
13-
| | | | |
14-
| | | | note: close start tag
15-
| | | note: attribute value
16-
| | attribute name
17-
| open start tag
18-
4 | <p>content</p>
19-
| -------------- info: end tag
20-
| | ||
21-
| | |note: string
22-
| | note: close start tag
23-
| open start tag
24-
5 | <!-- A comment -->
25-
| ------------------ info: comment
26-
6 | <h2>Subtitle</h2>
27-
| ----------------- info: end tag
28-
| | ||
29-
| | |note: string
30-
| | note: close start tag
31-
| open start tag
32-
7 | <br/>
33-
| ----- note: close start tag (self closing)
34-
| |
35-
| open start tag
36-
|
2+
|
3+
1 | <!DOCTYPE html>
4+
| --------------- info: doctype
5+
2 | <h1>Hello</h1>
6+
| -------------- info: end tag
7+
| | ||
8+
| | |note: string
9+
| | note: close start tag
10+
| open start tag
11+
3 | <p attr="value"></p>
12+
| ------- ----- ----- info: end tag
13+
| | | | |
14+
| | | | note: close start tag
15+
| | | note: attribute value
16+
| | attribute name
17+
| open start tag
18+
4 | <p>content</p>
19+
| -------------- info: end tag
20+
| | ||
21+
| | |note: string
22+
| | note: close start tag
23+
| open start tag
24+
5 | <!-- A comment -->
25+
| ------------------ info: comment
26+
6 | <h2>Subtitle</h2>
27+
| ----------------- info: end tag
28+
| | ||
29+
| | |note: string
30+
| | note: close start tag
31+
| open start tag
32+
7 | <br/>
33+
| ----- note: close start tag (self closing)
34+
| |
35+
| open start tag
36+
8 | <script>console.log('hello')</script>
37+
| ------------------------------------- info: end tag
38+
| | ||
39+
| | |note: string
40+
| | note: close start tag
41+
| open start tag
42+
9 | <script>nested('<div></div>')</script>
43+
| -------------------------------------- info: end tag
44+
| | || | || |
45+
| | || | || note: string
46+
| | || | |info: end tag
47+
| | || | note: close start tag
48+
| | || open start tag
49+
| | |note: string
50+
| | note: close start tag
51+
| open start tag
52+
10 | <style>.class { color: red; }</style>
53+
| ------------------------------------- info: end tag
54+
| | ||
55+
| | |note: string
56+
| | note: close start tag
57+
| open start tag
58+
11 | <textarea>user input</textarea>
59+
| ------------------------------- info: end tag
60+
| | ||
61+
| | |note: string
62+
| | note: close start tag
63+
| open start tag
64+
|

tests/test_spans/input.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@ <h1>Hello</h1>
55
<!-- A comment -->
66
<h2>Subtitle</h2>
77
<br/>
8+
<script>console.log('hello')</script>
9+
<script>nested('<div></div>')</script>
10+
<style>.class { color: red; }</style>
11+
<textarea>user input</textarea>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
error: test output
2+
|
3+
1 | <!DOCTYPE html>
4+
| --------------- info: doctype
5+
2 | <h1>Hello</h1>
6+
| -------------- note: end tag
7+
| | |
8+
| | info: string
9+
| info: start tag
10+
3 | <p attr="value"></p>
11+
| -------------------- note: end tag
12+
| | |
13+
| | note: attribute
14+
| info: start tag
15+
4 | <p>content</p>
16+
| -------------- note: end tag
17+
| | |
18+
| | info: string
19+
| info: start tag
20+
5 | <!-- A comment -->
21+
| ------------------ info: comment
22+
6 | <h2>Subtitle</h2>
23+
| ----------------- note: end tag
24+
| | |
25+
| | info: string
26+
| info: start tag
27+
7 | <br/>
28+
| ----- info: start tag
29+
8 | <script>console.log('hello')</script>
30+
| ------------------------------------- note: end tag
31+
| | |
32+
| | info: string
33+
| info: start tag
34+
9 | <script>nested('<div></div>')</script>
35+
| -------------------------------------- note: end tag
36+
| | |
37+
| | info: string
38+
| info: start tag
39+
10 | <style>.class { color: red; }</style>
40+
| ------------------------------------- note: end tag
41+
| | |
42+
| | info: string
43+
| info: start tag
44+
11 | <textarea>user input</textarea>
45+
| ------------------------------- note: end tag
46+
| | |
47+
| | info: string
48+
| info: start tag
49+
|

tests/test_spans/simple.stdout.txt

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,52 @@
11
error: test output
2-
|
3-
1 | <!DOCTYPE html>
4-
| --------------- info: doctype
5-
2 | <h1>Hello</h1>
6-
| -------------- note: end tag
7-
| | |
8-
| | info: string
9-
| info: start tag
10-
3 | <p attr="value"></p>
11-
| -------------------- note: end tag
12-
| | |
13-
| | note: attribute
14-
| info: start tag
15-
4 | <p>content</p>
16-
| -------------- note: end tag
17-
| | |
18-
| | info: string
19-
| info: start tag
20-
5 | <!-- A comment -->
21-
| ------------------ info: comment
22-
6 | <h2>Subtitle</h2>
23-
| ----------------- note: end tag
24-
| | |
25-
| | info: string
26-
| info: start tag
27-
7 | <br/>
28-
| ----- info: start tag
29-
|
2+
|
3+
1 | <!DOCTYPE html>
4+
| --------------- info: doctype
5+
2 | <h1>Hello</h1>
6+
| -------------- note: end tag
7+
| | |
8+
| | info: string
9+
| info: start tag
10+
3 | <p attr="value"></p>
11+
| -------------------- note: end tag
12+
| | |
13+
| | note: attribute
14+
| info: start tag
15+
4 | <p>content</p>
16+
| -------------- note: end tag
17+
| | |
18+
| | info: string
19+
| info: start tag
20+
5 | <!-- A comment -->
21+
| ------------------ info: comment
22+
6 | <h2>Subtitle</h2>
23+
| ----------------- note: end tag
24+
| | |
25+
| | info: string
26+
| info: start tag
27+
7 | <br/>
28+
| ----- info: start tag
29+
8 | <script>console.log('hello')</script>
30+
| ------------------------------------- note: end tag
31+
| | |
32+
| | info: string
33+
| info: start tag
34+
9 | <script>nested('<div></div>')</script>
35+
| -------------------------------------- note: end tag
36+
| | | | | |
37+
| | | | | info: string
38+
| | | | note: end tag
39+
| | | info: start tag
40+
| | info: string
41+
| info: start tag
42+
10 | <style>.class { color: red; }</style>
43+
| ------------------------------------- note: end tag
44+
| | |
45+
| | info: string
46+
| info: start tag
47+
11 | <textarea>user input</textarea>
48+
| ------------------------------- note: end tag
49+
| | |
50+
| | info: string
51+
| info: start tag
52+
|

0 commit comments

Comments
 (0)