Skip to content

Commit 5623024

Browse files
authored
Rollup merge of rust-lang#103505 - notriddle:notriddle/rustdoc-self-closing-tags, r=GuillaumeGomez
rustdoc: parse self-closing tags and attributes in `invalid_html_tags` Fixes rust-lang#103460
2 parents 571771e + f9cace0 commit 5623024

File tree

3 files changed

+204
-1
lines changed

3 files changed

+204
-1
lines changed

src/librustdoc/passes/html_tags.rs

+54-1
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,60 @@ fn extract_html_tag(
184184
}
185185
drop_tag(tags, tag_name, r, f);
186186
} else {
187-
tags.push((tag_name, r));
187+
let mut is_self_closing = false;
188+
let mut quote_pos = None;
189+
if c != '>' {
190+
let mut quote = None;
191+
let mut after_eq = false;
192+
for (i, c) in text[pos..].char_indices() {
193+
if !c.is_whitespace() {
194+
if let Some(q) = quote {
195+
if c == q {
196+
quote = None;
197+
quote_pos = None;
198+
after_eq = false;
199+
}
200+
} else if c == '>' {
201+
break;
202+
} else if c == '/' && !after_eq {
203+
is_self_closing = true;
204+
} else {
205+
if is_self_closing {
206+
is_self_closing = false;
207+
}
208+
if (c == '"' || c == '\'') && after_eq {
209+
quote = Some(c);
210+
quote_pos = Some(pos + i);
211+
} else if c == '=' {
212+
after_eq = true;
213+
}
214+
}
215+
} else if quote.is_none() {
216+
after_eq = false;
217+
}
218+
}
219+
}
220+
if let Some(quote_pos) = quote_pos {
221+
let qr = Range { start: quote_pos, end: quote_pos };
222+
f(
223+
&format!("unclosed quoted HTML attribute on tag `{}`", tag_name),
224+
&qr,
225+
false,
226+
);
227+
}
228+
if is_self_closing {
229+
// https://html.spec.whatwg.org/#parse-error-non-void-html-element-start-tag-with-trailing-solidus
230+
let valid = ALLOWED_UNCLOSED.contains(&&tag_name[..])
231+
|| tags.iter().take(pos + 1).any(|(at, _)| {
232+
let at = at.to_lowercase();
233+
at == "svg" || at == "math"
234+
});
235+
if !valid {
236+
f(&format!("invalid self-closing HTML tag `{}`", tag_name), &r, false);
237+
}
238+
} else {
239+
tags.push((tag_name, r));
240+
}
188241
}
189242
}
190243
break;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#![deny(rustdoc::invalid_html_tags)]
2+
3+
/// <p/>
4+
//~^ ERROR invalid self-closing HTML tag `p`
5+
pub struct A;
6+
7+
/// <p style/>
8+
//~^ ERROR invalid self-closing HTML tag `p`
9+
pub struct B;
10+
11+
/// <p style=""/>
12+
//~^ ERROR invalid self-closing HTML tag `p`
13+
pub struct C;
14+
15+
/// <p style="x"/>
16+
//~^ ERROR invalid self-closing HTML tag `p`
17+
pub struct D;
18+
19+
/// <p style="x/></p>
20+
//~^ ERROR unclosed quoted HTML attribute
21+
pub struct E;
22+
23+
/// <p style='x/></p>
24+
//~^ ERROR unclosed quoted HTML attribute
25+
pub struct F;
26+
27+
/// <p style="x/"></p>
28+
pub struct G;
29+
30+
/// <p style="x/"/>
31+
//~^ ERROR invalid self-closing HTML tag `p`
32+
pub struct H;
33+
34+
/// <p / >
35+
//~^ ERROR invalid self-closing HTML tag `p`
36+
pub struct I;
37+
38+
/// <br/>
39+
pub struct J;
40+
41+
/// <a href=/></a>
42+
pub struct K;
43+
44+
/// <a href=//></a>
45+
pub struct L;
46+
47+
/// <a href="/"/>
48+
//~^ ERROR invalid self-closing HTML tag `a`
49+
pub struct M;
50+
51+
/// <a href=x />
52+
//~^ ERROR invalid self-closing HTML tag `a`
53+
pub struct N;
54+
55+
/// <a href= />
56+
//~^ ERROR invalid self-closing HTML tag `a`
57+
pub struct O;
58+
59+
/// <a href=x/></a>
60+
pub struct P;
61+
62+
/// <svg><rect width=1 height=1 /></svg>
63+
pub struct Q;
64+
65+
/// <svg><rect width=1 height=/></svg>
66+
//~^ ERROR unclosed HTML tag `rect`
67+
pub struct R;
68+
69+
/// <svg / q>
70+
pub struct S;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
error: invalid self-closing HTML tag `p`
2+
--> $DIR/invalid-html-self-closing-tag.rs:3:5
3+
|
4+
LL | /// <p/>
5+
| ^^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/invalid-html-self-closing-tag.rs:1:9
9+
|
10+
LL | #![deny(rustdoc::invalid_html_tags)]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: invalid self-closing HTML tag `p`
14+
--> $DIR/invalid-html-self-closing-tag.rs:7:5
15+
|
16+
LL | /// <p style/>
17+
| ^^
18+
19+
error: invalid self-closing HTML tag `p`
20+
--> $DIR/invalid-html-self-closing-tag.rs:11:5
21+
|
22+
LL | /// <p style=""/>
23+
| ^^
24+
25+
error: invalid self-closing HTML tag `p`
26+
--> $DIR/invalid-html-self-closing-tag.rs:15:5
27+
|
28+
LL | /// <p style="x"/>
29+
| ^^
30+
31+
error: unclosed quoted HTML attribute on tag `p`
32+
--> $DIR/invalid-html-self-closing-tag.rs:19:14
33+
|
34+
LL | /// <p style="x/></p>
35+
| ^
36+
37+
error: unclosed quoted HTML attribute on tag `p`
38+
--> $DIR/invalid-html-self-closing-tag.rs:23:14
39+
|
40+
LL | /// <p style='x/></p>
41+
| ^
42+
43+
error: invalid self-closing HTML tag `p`
44+
--> $DIR/invalid-html-self-closing-tag.rs:30:5
45+
|
46+
LL | /// <p style="x/"/>
47+
| ^^
48+
49+
error: invalid self-closing HTML tag `p`
50+
--> $DIR/invalid-html-self-closing-tag.rs:34:5
51+
|
52+
LL | /// <p / >
53+
| ^^
54+
55+
error: invalid self-closing HTML tag `a`
56+
--> $DIR/invalid-html-self-closing-tag.rs:47:5
57+
|
58+
LL | /// <a href="/"/>
59+
| ^^
60+
61+
error: invalid self-closing HTML tag `a`
62+
--> $DIR/invalid-html-self-closing-tag.rs:51:5
63+
|
64+
LL | /// <a href=x />
65+
| ^^
66+
67+
error: invalid self-closing HTML tag `a`
68+
--> $DIR/invalid-html-self-closing-tag.rs:55:5
69+
|
70+
LL | /// <a href= />
71+
| ^^
72+
73+
error: unclosed HTML tag `rect`
74+
--> $DIR/invalid-html-self-closing-tag.rs:65:10
75+
|
76+
LL | /// <svg><rect width=1 height=/></svg>
77+
| ^^^^^
78+
79+
error: aborting due to 12 previous errors
80+

0 commit comments

Comments
 (0)