Skip to main content

html_escape/decode/element/
script.rs

1use alloc::{borrow::Cow, string::String, vec::Vec};
2use core::str::from_utf8_unchecked;
3#[cfg(feature = "std")]
4use std::io::{self, Write};
5
6macro_rules! parse_script {
7    (@eof $step:ident, $b:block) => {
8        // The text ends right after `<\/script`.
9        if $step == 9 {
10            $b
11        }
12    };
13    ($e:expr, $step:ident, $b:block, $bc:block) => {
14        match $step {
15            0 => match $e {
16                b'<' => $step = 1,
17                _ => (),
18            },
19            1 => match $e {
20                b'\\' => $step = 2,
21                b'<' => $step = 1,
22                _ => $step = 0,
23            },
24            2 => match $e {
25                b'/' => $step = 3,
26                b'!' => $step = 10,
27                b'<' => $step = 1,
28                _ => $step = 0,
29            },
30            3 => match $e {
31                b's' | b'S' => $step = 4,
32                b'<' => $step = 1,
33                _ => $step = 0,
34            },
35            4 => match $e {
36                b'c' | b'C' => $step = 5,
37                b'<' => $step = 1,
38                _ => $step = 0,
39            },
40            5 => match $e {
41                b'r' | b'R' => $step = 6,
42                b'<' => $step = 1,
43                _ => $step = 0,
44            },
45            6 => match $e {
46                b'i' | b'I' => $step = 7,
47                b'<' => $step = 1,
48                _ => $step = 0,
49            },
50            7 => match $e {
51                b'p' | b'P' => $step = 8,
52                b'<' => $step = 1,
53                _ => $step = 0,
54            },
55            8 => match $e {
56                b't' | b'T' => $step = 9,
57                b'<' => $step = 1,
58                _ => $step = 0,
59            },
60            9 => match $e {
61                b'/' | b'>' | 9..=13 | 28..=32 => {
62                    $step = 0;
63                    $b
64                },
65                b'<' => $step = 1,
66                _ => $step = 0,
67            },
68            10 => match $e {
69                b'-' => $step = 11,
70                b'<' => $step = 1,
71                _ => $step = 0,
72            },
73            11 => match $e {
74                b'-' => {
75                    $step = 0;
76                    $bc
77                },
78                b'<' => $step = 1,
79                _ => $step = 0,
80            },
81            _ => unreachable!(),
82        }
83    };
84}
85
86decode_impl! {
87    7;
88    /// The following substring is unescaped:
89    ///
90    /// * `<\/script>` => `</script>`
91    /// * `<\!--` => `<!--`
92    ///
93    /// `<\/script` at the end of the text is also unescaped.
94    /// This only removes the listed escapes and does not parse JavaScript.
95    /// Existing escapes in the original text may also be removed, so encoding and decoding may not return the original text.
96    parse_script;
97    /// Decode text from the `<script>` element.
98    decode_script;
99    /// Write text from the `<script>` element to a mutable `String` reference and return the decoded string slice.
100    decode_script_to_string;
101    /// Write text from the `<script>` element to a mutable `Vec<u8>` reference and return the decoded data slice.
102    decode_script_to_vec;
103    /// Write text from the `<script>` element to a writer.
104    decode_script_to_writer;
105}
106
107decode_impl! {
108    quoted false, true, false;
109    /// Escapes emitted by the matching encoder are decoded.
110    /// Hex escapes use `\xHH` with uppercase digits; only escaped C0 controls and `<` are decoded.
111    /// `\u2028` and `\u2029` are also decoded.
112    /// Backslashes and `'` escaped with a backslash are decoded.
113    /// Legacy `<\/script>` and `<\!--` escapes are also decoded.
114    /// Unknown or incomplete escapes are kept, and decoded text is not decoded again.
115    raw_text;
116    /// Decode content of a single-quoted JavaScript string from `<script>`.
117    decode_script_single_quoted_text;
118    /// Decode content of a single-quoted JavaScript string to a mutable `String` and return the new string slice.
119    decode_script_single_quoted_text_to_string;
120    /// Decode content of a single-quoted JavaScript string to a mutable `Vec<u8>` and return the new data slice.
121    decode_script_single_quoted_text_to_vec;
122    /// Decode content of a single-quoted JavaScript string to a writer.
123    decode_script_single_quoted_text_to_writer;
124}
125
126decode_impl! {
127    quoted false, false, true;
128    /// Escapes emitted by the matching encoder are decoded.
129    /// Hex escapes use `\xHH` with uppercase digits; only escaped C0 controls and `<` are decoded.
130    /// `\u2028` and `\u2029` are also decoded.
131    /// Backslashes and `"` escaped with a backslash are decoded.
132    /// Legacy `<\/script>` and `<\!--` escapes are also decoded.
133    /// Unknown or incomplete escapes are kept, and decoded text is not decoded again.
134    raw_text;
135    /// Decode content of a double-quoted JavaScript string from `<script>`.
136    decode_script_double_quoted_text;
137    /// Decode content of a double-quoted JavaScript string to a mutable `String` and return the new string slice.
138    decode_script_double_quoted_text_to_string;
139    /// Decode content of a double-quoted JavaScript string to a mutable `Vec<u8>` and return the new data slice.
140    decode_script_double_quoted_text_to_vec;
141    /// Decode content of a double-quoted JavaScript string to a writer.
142    decode_script_double_quoted_text_to_writer;
143}
144
145decode_impl! {
146    quoted false, true, true;
147    /// Escapes emitted by the matching encoder are decoded.
148    /// Hex escapes use `\xHH` with uppercase digits; only escaped C0 controls and `<` are decoded.
149    /// `\u2028` and `\u2029` are also decoded.
150    /// Backslashes, `'`, and `"` escaped with a backslash are decoded.
151    /// Legacy `<\/script>` and `<\!--` escapes are also decoded.
152    /// Unknown or incomplete escapes are kept, and decoded text is not decoded again.
153    raw_text;
154    /// Decode content of a single-quoted or double-quoted JavaScript string from `<script>`.
155    decode_script_quoted_text;
156    /// Decode content of a single-quoted or double-quoted JavaScript string to a mutable `String` and return the new string slice.
157    decode_script_quoted_text_to_string;
158    /// Decode content of a single-quoted or double-quoted JavaScript string to a mutable `Vec<u8>` and return the new data slice.
159    decode_script_quoted_text_to_vec;
160    /// Decode content of a single-quoted or double-quoted JavaScript string to a writer.
161    decode_script_quoted_text_to_writer;
162}