From 766498ebfb382b0edd87030639c10b23da44775d Mon Sep 17 00:00:00 2001 From: Wilson Lin Date: Fri, 6 Aug 2021 23:07:55 +1000 Subject: [PATCH] Fix next sibling calc --- src/ast/mod.rs | 1 + src/lib.rs | 9 +++++++-- src/minify/content.rs | 18 ++++++++++++++++-- src/minify/tests/attr.rs | 2 +- src/parse/content.rs | 25 +------------------------ 5 files changed, 26 insertions(+), 29 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 6272065..9cebffc 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -39,6 +39,7 @@ pub enum NodeData { closing_tag: ElementClosingTag, name: Vec, namespace: Namespace, + // WARNING: This should only be set during minification, as minification can alter tree (e.g. remove text nodes completely). // If the next text or element sibling is an element, this will be set to its tag name. // Otherwise, this will be empty. It should be empty on creation. next_sibling_element_name: Vec, diff --git a/src/lib.rs b/src/lib.rs index 8835a0d..46ac75a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -use crate::cfg::Cfg; +pub use crate::cfg::Cfg; use crate::minify::content::minify_content; use crate::parse::content::parse_content; use crate::parse::Code; @@ -31,8 +31,13 @@ mod whitespace; /// /// let mut code: &[u8] = b"

Hello, world!

"; /// let cfg = &Cfg { -/// minify_js: false, /// minify_css: false, +/// minify_js: false, +/// omit_closing_tags: true, +/// remove_bangs: false, +/// remove_comments: true, +/// remove_processing_instructions: false, +/// remove_spaces_between_attributes: true, /// }; /// let minified = minify(&code, cfg); /// assert_eq!(minified, b"

Hello, world!".to_vec()); diff --git a/src/minify/content.rs b/src/minify/content.rs index e7fd407..80afde4 100644 --- a/src/minify/content.rs +++ b/src/minify/content.rs @@ -59,9 +59,23 @@ pub fn minify_content( let mut found_first_text_or_elem = false; let mut index_of_last_nonempty_text_or_elem: isize = -1; let mut index_of_last_text_or_elem: isize = -1; - for (i, n) in nodes.iter_mut().enumerate() { + for i in 0..nodes.len() { + let (previous_nodes, next_nodes) = nodes.split_at_mut(i); + let n = &mut next_nodes[0]; match n { - NodeData::Element { .. } => { + NodeData::Element { name, .. } => { + if index_of_last_nonempty_text_or_elem > -1 { + match &mut previous_nodes[index_of_last_nonempty_text_or_elem as usize] { + NodeData::Element { + next_sibling_element_name, + .. + } => { + debug_assert!(next_sibling_element_name.is_empty()); + next_sibling_element_name.extend_from_slice(name); + } + _ => {} + }; + }; found_first_text_or_elem = true; index_of_last_nonempty_text_or_elem = i as isize; index_of_last_text_or_elem = i as isize; diff --git a/src/minify/tests/attr.rs b/src/minify/tests/attr.rs index 2d41ce6..4dfe178 100644 --- a/src/minify/tests/attr.rs +++ b/src/minify/tests/attr.rs @@ -13,7 +13,7 @@ fn test_encode_using_double_quotes() { #[test] fn test_encode_using_single_quotes() { - let min = encode_using_single_quotes(br#"'abr'aca'dab &&'10';'8'$4 a'"#); + let min = encode_using_single_quotes(br#"'abr'aca'dab &&''10';''8'$4 a'"#); assert_eq!( min.str(), r#"''abr'aca'dab &&''10';''8'$4 a''"#, diff --git a/src/parse/content.rs b/src/parse/content.rs index 002fb54..a6b211f 100644 --- a/src/parse/content.rs +++ b/src/parse/content.rs @@ -82,9 +82,6 @@ pub fn parse_content( // We assume the closing tag has been omitted until we see one explicitly before EOF (or it has been omitted as per the spec). let mut closing_tag_omitted = true; let mut nodes = Vec::::new(); - // This is set to the index of the last text or element node that is an element node. - // If it's not an element node, this is set to -1. - let mut last_elem_node_pos: isize = -1; loop { let (text_len, mut typ) = match CONTENT_TYPE_MATCHER.0.find(&code.str()) { Some(m) => (m.start(), CONTENT_TYPE_MATCHER.1[m.pattern()]), @@ -98,7 +95,6 @@ pub fn parse_content( Some(NodeData::Text { value }) => value.extend_from_slice(&text), _ => nodes.push(NodeData::Text { value: text }), }; - last_elem_node_pos = -1; }; // Check using Parsing.md tag rules. if typ == OpeningTag || typ == ClosingTag { @@ -130,26 +126,7 @@ pub fn parse_content( }; match typ { Text => break, - OpeningTag => { - let node = parse_element(code, ns, parent); - if last_elem_node_pos > -1 { - match (&mut nodes[last_elem_node_pos as usize], &node) { - ( - NodeData::Element { - next_sibling_element_name, - .. - }, - NodeData::Element { name, .. }, - ) => { - debug_assert!(next_sibling_element_name.is_empty()); - next_sibling_element_name.extend_from_slice(name); - } - _ => unreachable!(), - } - } - last_elem_node_pos = nodes.len() as isize; - nodes.push(node); - } + OpeningTag => nodes.push(parse_element(code, ns, parent)), ClosingTag => { closing_tag_omitted = false; break;