Fix next sibling calc

This commit is contained in:
Wilson Lin 2021-08-06 23:07:55 +10:00
parent b0c574dbd7
commit 766498ebfb
5 changed files with 26 additions and 29 deletions

View File

@ -39,6 +39,7 @@ pub enum NodeData {
closing_tag: ElementClosingTag,
name: Vec<u8>,
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<u8>,

View File

@ -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"<p> Hello, world! </p>";
/// 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"<p>Hello, world!".to_vec());

View File

@ -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;

View File

@ -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 &amp&amp;'10';'8'$4 a'"#);
let min = encode_using_single_quotes(br#"'abr'aca'dab &amp&amp;''10';''8'$4 a'"#);
assert_eq!(
min.str(),
r#"'&#39abr&#39aca&#39dab &amp&amp;&#39&#39;10&#39;;&#39&#39;8&#39$4 a&#39'"#,

View File

@ -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::<NodeData>::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;