1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
use alloc::{borrow::Cow, string::String, vec::Vec};
use core::str::from_utf8_unchecked;
#[cfg(feature = "std")]
use std::io::{self, Write};
macro_rules! parse_style_comment {
(@eof $step:ident, $b:block) => {
// An unfinished `</style` at the end can still end the element with the text after it.
if $step == 7 {
$b
}
};
($e:expr, $step:ident, $b:block, $bc:block) => {
match $step {
0 => match $e {
b'<' => $step = 1,
_ => (),
},
1 => match $e {
b'/' => $step = 2,
b'!' => $step = 10,
b'<' => $step = 1,
_ => $step = 0,
},
2 => match $e {
b's' | b'S' => $step = 3,
b'<' => $step = 1,
_ => $step = 0,
},
3 => match $e {
b't' | b'T' => $step = 4,
b'<' => $step = 1,
_ => $step = 0,
},
4 => match $e {
b'y' | b'Y' => $step = 5,
b'<' => $step = 1,
_ => $step = 0,
},
5 => match $e {
b'l' | b'L' => $step = 6,
b'<' => $step = 1,
_ => $step = 0,
},
6 => match $e {
b'e' | b'E' => $step = 7,
b'<' => $step = 1,
_ => $step = 0,
},
7 => match $e {
b'/' | b'>' | 9..=13 | 28..=32 => {
$step = 0;
$b
},
b'<' => $step = 1,
_ => $step = 0,
},
10 => match $e {
b'-' => $step = 11,
b'<' => $step = 1,
_ => $step = 0,
},
11 => match $e {
b'-' => {
$step = 0;
$bc
},
b'<' => $step = 1,
_ => $step = 0,
},
_ => unreachable!(),
}
};
}
encode_impl! {
6;
/// The following substring is escaped:
///
/// * `</style>` => `<\/style>`
/// * `<!--` => `<\!--`
///
/// `</style` at the end of the text is also escaped, because the text after it can end the element.
/// Pass the whole element text in one call; separate calls do not share parsing state.
/// This scans text without parsing CSS and may change its meaning.
/// Existing escapes are kept, so encoding and decoding may not return the original text.
/// Use a quoted text encoder when inserting raw text into a CSS string.
parse_style_comment;
/// Encode text used in the `<style>` element.
encode_style;
/// Write text used in the `<style>` element to a mutable `String` reference and return the encoded string slice.
encode_style_to_string;
/// Write text used in the `<style>` element to a mutable `Vec<u8>` reference and return the encoded data slice.
encode_style_to_vec;
/// Write text used in the `<style>` element to a writer.
encode_style_to_writer;
}
encode_impl! {
quoted true, true, false;
/// The input is raw text; existing escapes are encoded as text.
/// The output is string content and does not include outer quotes.
/// Backslashes and `'` are escaped with a backslash.
/// `<` and C0 controls other than NUL use two uppercase hex digits and one ending space, such as `\3C `.
/// NUL is replaced with U+FFFD, so text containing NUL cannot round-trip without a change.
/// The ending space is part of the escape; an input space after it is kept.
/// Use the output in a CSS string inside `<style>`, not in a CSS identifier or an HTML attribute.
raw_text;
/// Encode raw text for a single-quoted CSS string inside `<style>`.
encode_style_single_quoted_text;
/// Encode content of a single-quoted CSS string to a mutable `String` and return the new string slice.
encode_style_single_quoted_text_to_string;
/// Encode content of a single-quoted CSS string to a mutable `Vec<u8>` and return the new data slice.
encode_style_single_quoted_text_to_vec;
/// Encode content of a single-quoted CSS string to a writer.
encode_style_single_quoted_text_to_writer;
}
encode_impl! {
quoted true, false, true;
/// The input is raw text; existing escapes are encoded as text.
/// The output is string content and does not include outer quotes.
/// Backslashes and `"` are escaped with a backslash.
/// `<` and C0 controls other than NUL use two uppercase hex digits and one ending space, such as `\3C `.
/// NUL is replaced with U+FFFD, so text containing NUL cannot round-trip without a change.
/// The ending space is part of the escape; an input space after it is kept.
/// Use the output in a CSS string inside `<style>`, not in a CSS identifier or an HTML attribute.
raw_text;
/// Encode raw text for a double-quoted CSS string inside `<style>`.
encode_style_double_quoted_text;
/// Encode content of a double-quoted CSS string to a mutable `String` and return the new string slice.
encode_style_double_quoted_text_to_string;
/// Encode content of a double-quoted CSS string to a mutable `Vec<u8>` and return the new data slice.
encode_style_double_quoted_text_to_vec;
/// Encode content of a double-quoted CSS string to a writer.
encode_style_double_quoted_text_to_writer;
}
encode_impl! {
quoted true, true, true;
/// The input is raw text; existing escapes are encoded as text.
/// The output is string content and does not include outer quotes.
/// Backslashes, `'`, and `"` are escaped with a backslash.
/// `<` and C0 controls other than NUL use two uppercase hex digits and one ending space, such as `\3C `.
/// NUL is replaced with U+FFFD, so text containing NUL cannot round-trip without a change.
/// The ending space is part of the escape; an input space after it is kept.
/// Use the output in a CSS string inside `<style>`, not in a CSS identifier or an HTML attribute.
raw_text;
/// Encode raw text for a single-quoted or double-quoted CSS string inside `<style>`.
encode_style_quoted_text;
/// Encode content of a single-quoted or double-quoted CSS string to a mutable `String` and return the new string slice.
encode_style_quoted_text_to_string;
/// Encode content of a single-quoted or double-quoted CSS string to a mutable `Vec<u8>` and return the new data slice.
encode_style_quoted_text_to_vec;
/// Encode content of a single-quoted or double-quoted CSS string to a writer.
encode_style_quoted_text_to_writer;
}