88#![ warn( missing_docs) ]
99#![ cfg_attr( docsrs, feature( doc_auto_cfg) ) ]
1010
11+ /// HTTP Server integrations.
1112mod http;
1213
13- #[ allow( missing_docs) ]
14+ /// [`crate::Node`] variant definitions.
15+ mod node;
16+
17+ /// Pretty printing utilities.
18+ #[ cfg( feature = "pretty" ) ]
19+ pub mod pretty;
20+
21+ /// Typed HTML Nodes.
1422#[ cfg( feature = "typed" ) ]
1523pub mod typed;
1624
1725use std:: fmt:: { self , Display , Formatter } ;
1826
27+ pub use self :: node:: * ;
1928#[ cfg( feature = "typed" ) ]
2029use self :: typed:: TypedElement ;
2130
@@ -84,17 +93,18 @@ impl Node {
8493 pub fn from_typed < E : TypedElement > ( element : E , children : Option < Vec < Self > > ) -> Self {
8594 element. into_node ( children)
8695 }
96+
97+ /// Wrap the node in a pretty-printing wrapper.
98+ #[ cfg( feature = "pretty" ) ]
99+ #[ must_use]
100+ pub fn pretty ( self ) -> pretty:: Pretty {
101+ self . into ( )
102+ }
87103}
88104
89- impl < I , N > From < I > for Node
90- where
91- I : IntoIterator < Item = N > ,
92- N : Into < Self > ,
93- {
94- fn from ( iter : I ) -> Self {
95- Self :: Fragment ( Fragment {
96- children : iter. into_iter ( ) . map ( Into :: into) . collect ( ) ,
97- } )
105+ impl Default for Node {
106+ fn default ( ) -> Self {
107+ Self :: EMPTY
98108 }
99109}
100110
@@ -111,226 +121,48 @@ impl Display for Node {
111121 }
112122}
113123
114- impl Default for Node {
115- fn default ( ) -> Self {
116- Self :: EMPTY
124+ impl < I , N > From < I > for Node
125+ where
126+ I : IntoIterator < Item = N > ,
127+ N : Into < Self > ,
128+ {
129+ fn from ( iter : I ) -> Self {
130+ Self :: Fragment ( iter. into ( ) )
117131 }
118132}
119133
120- /// A comment.
121- ///
122- /// ```html
123- /// <!-- I'm a comment! -->
124- /// ```
125- #[ derive( Debug , Clone , PartialEq , Eq ) ]
126- #[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
127- pub struct Comment {
128- /// The text of the comment.
129- ///
130- /// ```html
131- /// <!-- comment -->
132- /// ```
133- pub comment : String ,
134- }
135-
136- impl Display for Comment {
137- fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
138- write ! ( f, "<!-- {} -->" , self . comment)
134+ impl From < Comment > for Node {
135+ fn from ( comment : Comment ) -> Self {
136+ Self :: Comment ( comment)
139137 }
140138}
141139
142- /// A doctype.
143- ///
144- /// ```html
145- /// <!DOCTYPE html>
146- /// ```
147- #[ derive( Debug , Clone , PartialEq , Eq ) ]
148- #[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
149- pub struct Doctype {
150- /// The value of the doctype.
151- ///
152- /// ```html
153- /// <!DOCTYPE synax>
154- /// ```
155- pub syntax : String ,
156- }
157-
158- impl Display for Doctype {
159- fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
160- write ! ( f, "<!DOCTYPE {}>" , self . syntax)
140+ impl From < Doctype > for Node {
141+ fn from ( doctype : Doctype ) -> Self {
142+ Self :: Doctype ( doctype)
161143 }
162144}
163145
164- /// A fragment.
165- ///
166- /// ```html
167- /// <>
168- /// I'm in a fragment!
169- /// </>
170- /// ```
171- #[ derive( Debug , Clone , PartialEq , Eq ) ]
172- #[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
173- pub struct Fragment {
174- /// The children of the fragment.
175- ///
176- /// ```html
177- /// <>
178- /// <!-- I'm a child! -->
179- /// <child>I'm another child!</child>
180- /// </>
181- pub children : Vec < Node > ,
182- }
183-
184- impl Display for Fragment {
185- fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
186- write_children ( f, & self . children , true )
146+ impl From < Fragment > for Node {
147+ fn from ( fragment : Fragment ) -> Self {
148+ Self :: Fragment ( fragment)
187149 }
188150}
189151
190- /// An element.
191- ///
192- /// ```html
193- /// <div class="container">
194- /// I'm in an element!
195- /// </div>
196- /// ```
197- #[ derive( Debug , Clone , PartialEq , Eq ) ]
198- #[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
199- pub struct Element {
200- /// The name of the element.
201- ///
202- /// ```html
203- /// <name>
204- /// ```
205- pub name : String ,
206-
207- /// The attributes of the element.
208- ///
209- /// ```html
210- /// <div attribute="value">
211- /// ```
212- pub attributes : Vec < ( String , Option < String > ) > ,
213-
214- /// The children of the element.
215- ///
216- /// ```html
217- /// <div>
218- /// <!-- I'm a child! -->
219- /// <child>I'm another child!</child>
220- /// </div>
221- /// ```
222- pub children : Option < Vec < Node > > ,
223- }
224-
225- impl Element {
226- /// Create a new [`Element`] from a [`TypedElement`].
227- #[ cfg( feature = "typed" ) ]
228- pub fn from_typed < E : TypedElement > ( element : E , children : Option < Vec < Node > > ) -> Self {
229- element. into_element ( children)
230- }
231- }
232-
233- impl Display for Element {
234- fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
235- write ! ( f, "<{}" , self . name) ?;
236-
237- for ( key, value) in & self . attributes {
238- write ! ( f, " {key}" ) ?;
239-
240- if let Some ( value) = value {
241- let encoded_value = html_escape:: encode_double_quoted_attribute ( value) ;
242- write ! ( f, r#"="{encoded_value}""# ) ?;
243- }
244- }
245- write ! ( f, ">" ) ?;
246-
247- if let Some ( children) = & self . children {
248- write_children ( f, children, false ) ?;
249-
250- write ! ( f, "</{}>" , self . name) ?;
251- } ;
252-
253- Ok ( ( ) )
254- }
255- }
256-
257- /// A text node.
258- ///
259- /// ```html
260- /// <div>
261- /// I'm a text node!
262- /// </div>
263- #[ derive( Debug , Clone , PartialEq , Eq ) ]
264- #[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
265- pub struct Text {
266- /// The text of the node.
267- ///
268- /// ```html
269- /// <div>
270- /// text
271- /// </div>
272- pub text : String ,
273- }
274-
275- impl Display for Text {
276- fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
277- let encoded_value = html_escape:: encode_text_minimal ( & self . text ) ;
278- write ! ( f, "{encoded_value}" )
152+ impl From < Element > for Node {
153+ fn from ( element : Element ) -> Self {
154+ Self :: Element ( element)
279155 }
280156}
281157
282- /// An unsafe text node.
283- ///
284- /// # Warning
285- ///
286- /// [`UnsafeText`] is not escaped when rendered, and as such, can allow
287- /// for XSS attacks. Use with caution!
288- #[ derive( Debug , Clone , PartialEq , Eq ) ]
289- #[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
290- pub struct UnsafeText {
291- /// The text of the node.
292- pub text : String ,
293- }
294-
295- impl Display for UnsafeText {
296- fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
297- write ! ( f, "{}" , self . text)
158+ impl From < Text > for Node {
159+ fn from ( text : Text ) -> Self {
160+ Self :: Text ( text)
298161 }
299162}
300163
301- /// Writes the children of a node.
302- ///
303- /// If the formatter is in alternate mode, then the children are put on their
304- /// own lines.
305- ///
306- /// If alternate mode is enabled and `is_fragment` is false, then each line
307- /// is indented by 4 spaces.
308- fn write_children ( f : & mut Formatter < ' _ > , children : & [ Node ] , is_fragment : bool ) -> fmt:: Result {
309- if f. alternate ( ) {
310- let mut children_iter = children. iter ( ) ;
311-
312- if is_fragment {
313- if let Some ( first_child) = children_iter. next ( ) {
314- write ! ( f, "{first_child:#}" ) ?;
315-
316- for child in children_iter {
317- write ! ( f, "\n {child:#}" ) ?;
318- }
319- }
320- } else {
321- for child_str in children_iter. map ( |child| format ! ( "{child:#}" ) ) {
322- for line in child_str. lines ( ) {
323- write ! ( f, "\n {line}" ) ?;
324- }
325- }
326-
327- // exit inner block
328- writeln ! ( f) ?;
329- }
330- } else {
331- for child in children {
332- child. fmt ( f) ?;
333- }
164+ impl From < UnsafeText > for Node {
165+ fn from ( text : UnsafeText ) -> Self {
166+ Self :: UnsafeText ( text)
334167 }
335- Ok ( ( ) )
336168}
0 commit comments