@@ -32,6 +32,8 @@ pub struct CodegenConfig<'a> {
3232 /// Don't print optional tags (only when `minify` enabled)
3333 /// By default `true` when `minify` enabled, otherwise `false`
3434 pub tag_omission : Option < bool > ,
35+ /// Keep <head> tags and </body> closing tag when `tag_omission` is enabled
36+ pub keep_head_and_body : Option < bool > ,
3537 /// Making SVG and MathML elements self-closing where possible (only when
3638 /// `minify` enabled) By default `false` when `minify` enabled,
3739 /// otherwise `true`
5860 // For legacy `<plaintext>`
5961 is_plaintext : bool ,
6062 tag_omission : bool ,
63+ keep_head_and_body : bool ,
6164 self_closing_void_elements : bool ,
6265 quotes : bool ,
6366}
6871{
6972 pub fn new ( wr : W , config : CodegenConfig < ' a > ) -> Self {
7073 let tag_omission = config. tag_omission . unwrap_or ( config. minify ) ;
74+ let keep_head_and_body = config. keep_head_and_body . unwrap_or ( false ) ;
7175 let self_closing_void_elements = config. tag_omission . unwrap_or ( !config. minify ) ;
7276 let quotes = config. quotes . unwrap_or ( !config. minify ) ;
7377
7781 ctx : Default :: default ( ) ,
7882 is_plaintext : false ,
7983 tag_omission,
84+ keep_head_and_body,
8085 self_closing_void_elements,
8186 quotes,
8287 }
@@ -227,49 +232,56 @@ where
227232 // A head element's start tag can be omitted if the element is empty, or if the
228233 // first thing inside the head element is an element.
229234 "head"
230- if n. children . is_empty ( )
231- || matches ! ( n. children. first( ) , Some ( Child :: Element ( ..) ) ) =>
235+ if !self . keep_head_and_body
236+ && ( n. children . is_empty ( )
237+ || matches ! ( n. children. first( ) , Some ( Child :: Element ( ..) ) ) ) =>
232238 {
233239 true
234240 }
235241 // A body element's start tag can be omitted if the element is empty, or if the
236242 // first thing inside the body element is not ASCII whitespace or a comment, except
237243 // if the first thing inside the body element would be parsed differently outside.
238244 "body"
239- if n. children . is_empty ( )
240- || ( match n. children . first ( ) {
241- Some ( Child :: Text ( text) )
242- if !text. data . is_empty ( )
243- && text. data . chars ( ) . next ( ) . unwrap ( ) . is_ascii_whitespace ( ) =>
244- {
245- false
246- }
247- Some ( Child :: Comment ( ..) ) => false ,
248- Some ( Child :: Element ( Element {
249- namespace,
250- tag_name,
251- ..
252- } ) ) if * namespace == Namespace :: HTML
253- && matches ! (
254- & * * tag_name,
255- "base"
256- | "basefont"
257- | "bgsound"
258- | "frameset"
259- | "link"
260- | "meta"
261- | "noframes"
262- | "noscript"
263- | "script"
264- | "style"
265- | "template"
266- | "title"
267- ) =>
268- {
269- false
270- }
271- _ => true ,
272- } ) =>
245+ if !self . keep_head_and_body
246+ && ( n. children . is_empty ( )
247+ || ( match n. children . first ( ) {
248+ Some ( Child :: Text ( text) )
249+ if !text. data . is_empty ( )
250+ && text
251+ . data
252+ . chars ( )
253+ . next ( )
254+ . unwrap ( )
255+ . is_ascii_whitespace ( ) =>
256+ {
257+ false
258+ }
259+ Some ( Child :: Comment ( ..) ) => false ,
260+ Some ( Child :: Element ( Element {
261+ namespace,
262+ tag_name,
263+ ..
264+ } ) ) if * namespace == Namespace :: HTML
265+ && matches ! (
266+ & * * tag_name,
267+ "base"
268+ | "basefont"
269+ | "bgsound"
270+ | "frameset"
271+ | "link"
272+ | "meta"
273+ | "noframes"
274+ | "noscript"
275+ | "script"
276+ | "style"
277+ | "template"
278+ | "title"
279+ ) =>
280+ {
281+ false
282+ }
283+ _ => true ,
284+ } ) ) =>
273285 {
274286 true
275287 }
@@ -432,10 +444,11 @@ where
432444 //
433445 // A body element's end tag can be omitted if the body element is not
434446 // immediately followed by a comment.
435- "html" | "body" => !matches ! ( next, Some ( Child :: Comment ( ..) ) ) ,
447+ "html" => !matches ! ( next, Some ( Child :: Comment ( ..) ) ) ,
448+ "body" if !self . keep_head_and_body => !matches ! ( next, Some ( Child :: Comment ( ..) ) ) ,
436449 // A head element's end tag can be omitted if the head element is not
437450 // immediately followed by ASCII whitespace or a comment.
438- "head" => match next {
451+ "head" if ! self . keep_head_and_body => match next {
439452 Some ( Child :: Text ( text) )
440453 if text. data . chars ( ) . next ( ) . unwrap ( ) . is_ascii_whitespace ( ) =>
441454 {
0 commit comments