Skip to main content

html_escape/decode/element/
style.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_style {
7    (@eof $step:ident, $b:block) => {
8        // The text ends right after `<\/style`.
9        if $step == 8 {
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't' | b'T' => $step = 5,
37                b'<' => $step = 1,
38                _ => $step = 0,
39            },
40            5 => match $e {
41                b'y' | b'Y' => $step = 6,
42                b'<' => $step = 1,
43                _ => $step = 0,
44            },
45            6 => match $e {
46                b'l' | b'L' => $step = 7,
47                b'<' => $step = 1,
48                _ => $step = 0,
49            },
50            7 => match $e {
51                b'e' | b'E' => $step = 8,
52                b'<' => $step = 1,
53                _ => $step = 0,
54            },
55            8 => match $e {
56                b'/' | b'>' | 9..=13 | 28..=32 => {
57                    $step = 0;
58                    $b
59                },
60                b'<' => $step = 1,
61                _ => $step = 0,
62            },
63            10 => match $e {
64                b'-' => $step = 11,
65                b'<' => $step = 1,
66                _ => $step = 0,
67            },
68            11 => match $e {
69                b'-' => {
70                    $step = 0;
71                    $bc
72                },
73                b'<' => $step = 1,
74                _ => $step = 0,
75            },
76            _ => unreachable!(),
77        }
78    };
79}
80
81decode_impl! {
82    6;
83    /// The following substring is unescaped:
84    ///
85    /// * `<\/style>` => `</style>`
86    /// * `<\!--` => `<!--`
87    ///
88    /// `<\/style` at the end of the text is also unescaped.
89    /// This only removes the listed escapes and does not parse CSS.
90    /// Existing escapes in the original text may also be removed, so encoding and decoding may not return the original text.
91    parse_style;
92    /// Decode text from the `<style>` element.
93    decode_style;
94    /// Write text from the `<style>` element to a mutable `String` reference and return the decoded string slice.
95    decode_style_to_string;
96    /// Write text from the `<style>` element to a mutable `Vec<u8>` reference and return the decoded data slice.
97    decode_style_to_vec;
98    /// Write text from the `<style>` element to a writer.
99    decode_style_to_writer;
100}
101
102decode_impl! {
103    quoted true, true, false;
104    /// Escapes emitted by the matching encoder are decoded.
105    /// Hex escapes need two uppercase digits and one ending space; only escaped C0 controls and `<` are decoded.
106    /// Only the ending space is removed; an input space after it is kept.
107    /// U+FFFD from an encoded NUL is kept as U+FFFD.
108    /// Backslashes and `'` escaped with a backslash are decoded.
109    /// Legacy `<\/style>` and `<\!--` escapes are also decoded.
110    /// Unknown or incomplete escapes are kept, and decoded text is not decoded again.
111    raw_text;
112    /// Decode content of a single-quoted CSS string from `<style>`.
113    decode_style_single_quoted_text;
114    /// Decode content of a single-quoted CSS string to a mutable `String` and return the new string slice.
115    decode_style_single_quoted_text_to_string;
116    /// Decode content of a single-quoted CSS string to a mutable `Vec<u8>` and return the new data slice.
117    decode_style_single_quoted_text_to_vec;
118    /// Decode content of a single-quoted CSS string to a writer.
119    decode_style_single_quoted_text_to_writer;
120}
121
122decode_impl! {
123    quoted true, false, true;
124    /// Escapes emitted by the matching encoder are decoded.
125    /// Hex escapes need two uppercase digits and one ending space; only escaped C0 controls and `<` are decoded.
126    /// Only the ending space is removed; an input space after it is kept.
127    /// U+FFFD from an encoded NUL is kept as U+FFFD.
128    /// Backslashes and `"` escaped with a backslash are decoded.
129    /// Legacy `<\/style>` and `<\!--` escapes are also decoded.
130    /// Unknown or incomplete escapes are kept, and decoded text is not decoded again.
131    raw_text;
132    /// Decode content of a double-quoted CSS string from `<style>`.
133    decode_style_double_quoted_text;
134    /// Decode content of a double-quoted CSS string to a mutable `String` and return the new string slice.
135    decode_style_double_quoted_text_to_string;
136    /// Decode content of a double-quoted CSS string to a mutable `Vec<u8>` and return the new data slice.
137    decode_style_double_quoted_text_to_vec;
138    /// Decode content of a double-quoted CSS string to a writer.
139    decode_style_double_quoted_text_to_writer;
140}
141
142decode_impl! {
143    quoted true, true, true;
144    /// Escapes emitted by the matching encoder are decoded.
145    /// Hex escapes need two uppercase digits and one ending space; only escaped C0 controls and `<` are decoded.
146    /// Only the ending space is removed; an input space after it is kept.
147    /// U+FFFD from an encoded NUL is kept as U+FFFD.
148    /// Backslashes, `'`, and `"` escaped with a backslash are decoded.
149    /// Legacy `<\/style>` and `<\!--` escapes are also decoded.
150    /// Unknown or incomplete escapes are kept, and decoded text is not decoded again.
151    raw_text;
152    /// Decode content of a single-quoted or double-quoted CSS string from `<style>`.
153    decode_style_quoted_text;
154    /// Decode content of a single-quoted or double-quoted CSS string to a mutable `String` and return the new string slice.
155    decode_style_quoted_text_to_string;
156    /// Decode content of a single-quoted or double-quoted CSS string to a mutable `Vec<u8>` and return the new data slice.
157    decode_style_quoted_text_to_vec;
158    /// Decode content of a single-quoted or double-quoted CSS string to a writer.
159    decode_style_quoted_text_to_writer;
160}