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
158
159
160
161
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_script_comment {
(@eof $step:ident, $b:block) => {
// An unfinished `</script` at the end can still end the element with the text after it.
if $step == 8 {
$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'c' | b'C' => $step = 4,
b'<' => $step = 1,
_ => $step = 0,
},
4 => match $e {
b'r' | b'R' => $step = 5,
b'<' => $step = 1,
_ => $step = 0,
},
5 => match $e {
b'i' | b'I' => $step = 6,
b'<' => $step = 1,
_ => $step = 0,
},
6 => match $e {
b'p' | b'P' => $step = 7,
b'<' => $step = 1,
_ => $step = 0,
},
7 => match $e {
b't' | b'T' => $step = 8,
b'<' => $step = 1,
_ => $step = 0,
},
8 => 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! {
7;
/// The following substring is escaped:
///
/// * `</script>` => `<\/script>`
/// * `<!--` => `<\!--`
///
/// `</script` 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 JavaScript and may change its meaning.
/// Existing escapes are kept, so encoding and decoding may not return the original text.
/// This is not a JSON encoder; the `\!` escape is not valid JSON.
/// For JSON, first serialize the data as JSON, then replace each literal `<` with `\u003C`.
/// Use a quoted text encoder when inserting raw text into a JavaScript string.
parse_script_comment;
/// Encode text used in the `<script>` element.
encode_script;
/// Write text used in the `<script>` element to a mutable `String` reference and return the encoded string slice.
encode_script_to_string;
/// Write text used in the `<script>` element to a mutable `Vec<u8>` reference and return the encoded data slice.
encode_script_to_vec;
/// Write text used in the `<script>` element to a writer.
encode_script_to_writer;
}
encode_impl! {
quoted false, 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 use `\xHH` with uppercase hex digits.
/// U+2028 and U+2029 use `\u2028` and `\u2029`.
/// Use the output in a JavaScript string inside `<script>`, not in a template literal or an HTML attribute.
raw_text;
/// Encode raw text for a single-quoted JavaScript string inside `<script>`.
encode_script_single_quoted_text;
/// Encode content of a single-quoted JavaScript string to a mutable `String` and return the new string slice.
encode_script_single_quoted_text_to_string;
/// Encode content of a single-quoted JavaScript string to a mutable `Vec<u8>` and return the new data slice.
encode_script_single_quoted_text_to_vec;
/// Encode content of a single-quoted JavaScript string to a writer.
encode_script_single_quoted_text_to_writer;
}
encode_impl! {
quoted false, 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 use `\xHH` with uppercase hex digits.
/// U+2028 and U+2029 use `\u2028` and `\u2029`.
/// Use the output in a JavaScript string inside `<script>`, not in a template literal or an HTML attribute.
raw_text;
/// Encode raw text for a double-quoted JavaScript string inside `<script>`.
encode_script_double_quoted_text;
/// Encode content of a double-quoted JavaScript string to a mutable `String` and return the new string slice.
encode_script_double_quoted_text_to_string;
/// Encode content of a double-quoted JavaScript string to a mutable `Vec<u8>` and return the new data slice.
encode_script_double_quoted_text_to_vec;
/// Encode content of a double-quoted JavaScript string to a writer.
encode_script_double_quoted_text_to_writer;
}
encode_impl! {
quoted false, 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 use `\xHH` with uppercase hex digits.
/// U+2028 and U+2029 use `\u2028` and `\u2029`.
/// Use the output in a JavaScript string inside `<script>`, not in a template literal or an HTML attribute.
raw_text;
/// Encode raw text for a single-quoted or double-quoted JavaScript string inside `<script>`.
encode_script_quoted_text;
/// Encode content of a single-quoted or double-quoted JavaScript string to a mutable `String` and return the new string slice.
encode_script_quoted_text_to_string;
/// Encode content of a single-quoted or double-quoted JavaScript string to a mutable `Vec<u8>` and return the new data slice.
encode_script_quoted_text_to_vec;
/// Encode content of a single-quoted or double-quoted JavaScript string to a writer.
encode_script_quoted_text_to_writer;
}