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}