From 29836d979a66ae3376cf1ba181a9faadeebe10ba Mon Sep 17 00:00:00 2001 From: Sunshine Date: Fri, 3 Apr 2020 03:30:52 -0400 Subject: [PATCH] add support for image inputs --- src/css.rs | 7 +-- src/html.rs | 59 ++++++++++++++++++++++--- src/macros.rs | 8 ++++ src/tests/cli.rs | 49 +++++++++++++------- src/tests/css/embed_css.rs | 31 +++++++------ src/tests/html/walk_and_embed_assets.rs | 11 ++--- 6 files changed, 119 insertions(+), 46 deletions(-) diff --git a/src/css.rs b/src/css.rs index 0be8eff..83938bc 100644 --- a/src/css.rs +++ b/src/css.rs @@ -18,9 +18,6 @@ const CSS_PROPS_WITH_IMAGE_URLS: &[&str] = &[ "mask-image", ]; -const TRANSPARENT_PIXEL: &str = "data:image/png;base64,\ - iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="; - pub fn is_image_url_prop(prop_name: &str) -> bool { CSS_PROPS_WITH_IMAGE_URLS .iter() @@ -185,7 +182,7 @@ pub fn process_css<'a>( } if opt_no_images && is_image_url_prop(curr_prop.as_str()) { - result.push_str(enquote(str!(TRANSPARENT_PIXEL), false).as_str()); + result.push_str(enquote(str!(empty_image!()), false).as_str()); } else { let resolved_url = resolve_url(&parent_url, value).unwrap_or_default(); let (data_url, _final_url) = retrieve_asset( @@ -294,7 +291,7 @@ pub fn process_css<'a>( ); } else { if opt_no_images && is_image_url_prop(curr_prop.as_str()) { - result.push_str(enquote(str!(TRANSPARENT_PIXEL), false).as_str()); + result.push_str(enquote(str!(empty_image!()), false).as_str()); } else { let full_url = resolve_url(&parent_url, value).unwrap_or_default(); let (data_url, _final_url) = retrieve_asset( diff --git a/src/html.rs b/src/html.rs index bf4bb7e..71380c2 100644 --- a/src/html.rs +++ b/src/html.rs @@ -20,9 +20,6 @@ const ICON_VALUES: &[&str] = &[ "fluid-icon", ]; -const TRANSPARENT_PIXEL: &str = "data:image/png;base64,\ - iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="; - pub fn get_parent_node(node: &Handle) -> Handle { let parent = node.parent.take().clone(); parent.and_then(|node| node.upgrade()).unwrap() @@ -270,7 +267,7 @@ pub fn walk_and_embed_assets( if opt_no_images { attrs_mut.push(Attribute { name: QualName::new(None, ns!(), local_name!("src")), - value: Tendril::from_slice(TRANSPARENT_PIXEL), + value: Tendril::from_slice(empty_image!()), }); } else if let Some((data_url, _)) = found_datasrc .iter() @@ -297,6 +294,58 @@ pub fn walk_and_embed_assets( }); } } + "input" => { + let mut is_image: bool = false; + for attr in attrs_mut.iter_mut() { + let attr_name: &str = &attr.name.local; + if attr_name == "type" { + is_image = attr.value.to_string().eq_ignore_ascii_case("image"); + } + } + + if is_image { + let mut found_src: Option = None; + let mut i = 0; + while i < attrs_mut.len() { + let attr_name = attrs_mut[i].name.local.as_ref(); + if attr_name.eq_ignore_ascii_case("src") { + found_src = Some(attrs_mut.remove(i)); + } else { + i += 1; + } + } + + // If images are disabled, clear both sources + if opt_no_images { + attrs_mut.push(Attribute { + name: QualName::new(None, ns!(), local_name!("src")), + value: Tendril::from_slice(empty_image!()), + }); + } else if let Some((data_url, _)) = found_src + .iter() + .map(|attr| attr.value.trim()) + .filter(|src| !src.is_empty()) // Skip if empty + .next() + .and_then(|src| resolve_url(&url, src).ok()) // Make absolute + .and_then(|abs_src| // Download and convert to data_url + retrieve_asset( + cache, + client, + &url, + &abs_src, + true, + "", + opt_silent, + ).ok()) + { + // Add new data_url src attribute + attrs_mut.push(Attribute { + name: QualName::new(None, ns!(), local_name!("src")), + value: Tendril::from_slice(data_url.as_ref()), + }); + } + } + } "source" => { for attr in attrs_mut.iter_mut() { let attr_name: &str = &attr.name.local; @@ -310,7 +359,7 @@ pub fn walk_and_embed_assets( if get_node_name(&get_parent_node(&node)) == Some("picture") { if opt_no_images { attr.value.clear(); - attr.value.push_slice(TRANSPARENT_PIXEL); + attr.value.push_slice(empty_image!()); } else { let srcset_full_url = resolve_url(&url, attr.value.trim()).unwrap_or_default(); diff --git a/src/macros.rs b/src/macros.rs index 475ce87..b93329c 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -7,3 +7,11 @@ macro_rules! str { ToString::to_string(&$val) }; } + +#[macro_export] +macro_rules! empty_image { + () => { +"data:image/png;base64,\ +iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAQAAADY4iz3AAAAEUlEQVR42mNkwAkYR6UolgIACvgADsuK6xYAAAAASUVORK5CYII=" + }; +} diff --git a/src/tests/cli.rs b/src/tests/cli.rs index b2732de..3158483 100644 --- a/src/tests/cli.rs +++ b/src/tests/cli.rs @@ -162,15 +162,18 @@ fn passing_remove_images_from_data_url() -> Result<(), Box\ + format!( + "\ \ \ \ \ -\ +\ Hi\ \ -\n" +\n", + empty_image = empty_image!() + ) ); // STDERR should be empty @@ -229,7 +232,8 @@ fn passing_local_file_target_input() -> Result<(), Box> { // STDOUT should contain HTML from the local file assert_eq!( std::str::from_utf8(&out.stdout).unwrap(), - "\n \ + "\ +\n \ \n \ Local HTML file\n \ \n \ @@ -238,16 +242,19 @@ fn passing_local_file_target_input() -> Result<(), Box> { Tricky href\n \ Remote URL\n \ \n\n\n\n\ -\n" +\n\ +" ); // STDERR should contain list of retrieved file URLs assert_eq!( std::str::from_utf8(&out.stderr).unwrap(), format!( - "{file}{cwd}/src/tests/data/local-file.html\n\ + "\ +{file}{cwd}/src/tests/data/local-file.html\n\ {file}{cwd}/src/tests/data/local-style.css\n\ -{file}{cwd}/src/tests/data/local-script.js\n", +{file}{cwd}/src/tests/data/local-script.js\n\ +", file = file_url_protocol, cwd = cwd_normalized ) @@ -286,17 +293,22 @@ fn passing_local_file_target_input_absolute_target_path() -> Result<(), Box\ + format!( + "\ +\ \n \ \n \ Local HTML file\n \ \n \ \n\n\n\n \ -\"\"\n \ +\"\"\n \ Tricky href\n \ Remote URL\n \ \n\n\n\n\ -\n" +\n\ +", + empty_image = empty_image!() + ) ); // STDERR should contain only the target file @@ -342,17 +354,22 @@ fn passing_local_file_url_target_input() -> Result<(), Box\ + format!( + "\ +\ \n \ \n \ Local HTML file\n \ \n \ \n\n\n\n \ -\"\"\n \ +\"\"\n \ Tricky href\n \ Remote URL\n \ \n\n\n\n\ -\n" +\n\ +", + empty_image = empty_image!() + ) ); // STDERR should contain list of retrieved file URLs @@ -458,7 +475,8 @@ fn passing_css_import_string() -> Result<(), Box> { let mut file_html = NamedTempFile::new()?; writeln!( file_html, - "\n", +\n\ +", file = file_url_prefix, css_path = str!(file_css.path().to_str().unwrap()).replace("\\", "/"), )?; diff --git a/src/tests/css/embed_css.rs b/src/tests/css/embed_css.rs index 2304b39..e4e2b58 100644 --- a/src/tests/css/embed_css.rs +++ b/src/tests/css/embed_css.rs @@ -40,13 +40,16 @@ height: calc(100vh - 10pt)"; true, true, ), - "/* border: none;*/\ -background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII='); \ -list-style: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=');\ + format!( + "/* border: none;*/\ +background-image: url('{empty_image}'); \ +list-style: url('{empty_image}');\ width:99.998%; \ margin-top: -20px; \ line-height: -1; \ -height: calc(100vh - 10pt)" +height: calc(100vh - 10pt)", + empty_image = empty_image!() + ) ); } @@ -64,21 +67,17 @@ line-height: -1; \ height: calc(100vh - 10pt)"; assert_eq!( - css::embed_css( - cache, - &client, - "", - &STYLE, - true, - true, - ), - "/* border: none;*/\ -background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII='); \ -list-style: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=');\ + css::embed_css(cache, &client, "", &STYLE, true, true,), + format!( + "/* border: none;*/\ +background-image: url('{empty_image}'); \ +list-style: url('{empty_image}');\ width:99.998%; \ margin-top: -20px; \ line-height: -1; \ -height: calc(100vh - 10pt)" +height: calc(100vh - 10pt)", + empty_image = empty_image!() + ) ); } diff --git a/src/tests/html/walk_and_embed_assets.rs b/src/tests/html/walk_and_embed_assets.rs index 716e6c8..7dbd8be 100644 --- a/src/tests/html/walk_and_embed_assets.rs +++ b/src/tests/html/walk_and_embed_assets.rs @@ -197,18 +197,19 @@ fn passing_no_images() { assert_eq!( buf.iter().map(|&c| c as char).collect::(), - "\ + format!( + "\ \ \ \ \
\ - \ + \
\ \ - " + ", + empty_image = empty_image!() + ) ); }