create a separate function for appending URL fragments

pull/186/head
Sunshine 4 years ago
parent 877b11d52c
commit f6ea16b3ad
No known key found for this signature in database
GPG Key ID: B80CA68703CD8AB1

@ -2,7 +2,9 @@ use cssparser::{ParseError, Parser, ParserInput, SourcePosition, Token};
use reqwest::blocking::Client; use reqwest::blocking::Client;
use std::collections::HashMap; use std::collections::HashMap;
use crate::utils::{data_to_data_url, get_url_fragment, is_http_url, resolve_url, retrieve_asset}; use crate::utils::{
data_to_data_url, get_url_fragment, is_http_url, resolve_url, retrieve_asset, url_with_fragment,
};
const CSS_PROPS_WITH_IMAGE_URLS: &[&str] = &[ const CSS_PROPS_WITH_IMAGE_URLS: &[&str] = &[
// Universal // Universal
@ -173,32 +175,34 @@ pub fn process_css<'a>(
let import_url_fragment = get_url_fragment(import_full_url.clone()); let import_url_fragment = get_url_fragment(import_full_url.clone());
match retrieve_asset(cache, client, &parent_url, &import_full_url, opt_silent) { match retrieve_asset(cache, client, &parent_url, &import_full_url, opt_silent) {
Ok((import_contents, import_final_url, _import_media_type)) => { Ok((import_contents, import_final_url, _import_media_type)) => {
result.push_str( let import_data_url = data_to_data_url(
enquote( "text/css",
data_to_data_url( embed_css(
"text/css", cache,
embed_css( client,
cache, &import_final_url,
client, &String::from_utf8_lossy(&import_contents),
&import_final_url, opt_no_fonts,
&String::from_utf8_lossy(&import_contents), opt_no_images,
opt_no_fonts, opt_silent,
opt_no_images,
opt_silent,
)
.as_bytes(),
&import_final_url,
&import_url_fragment,
),
false,
) )
.as_str(), .as_bytes(),
&import_final_url,
);
let assembled_url: String = url_with_fragment(
import_data_url.as_str(),
import_url_fragment.as_str(),
); );
result.push_str(enquote(assembled_url, false).as_str());
} }
Err(_) => { Err(_) => {
// Keep remote reference if unable to retrieve the asset // Keep remote reference if unable to retrieve the asset
if is_http_url(import_full_url.clone()) { if is_http_url(import_full_url.clone()) {
result.push_str(enquote(import_full_url, false).as_str()); let assembled_url: String = url_with_fragment(
import_full_url.as_str(),
import_url_fragment.as_str(),
);
result.push_str(enquote(assembled_url, false).as_str());
} }
} }
} }
@ -222,18 +226,19 @@ pub fn process_css<'a>(
opt_silent, opt_silent,
) { ) {
Ok((data, final_url, media_type)) => { Ok((data, final_url, media_type)) => {
let data_url = data_to_data_url( let data_url = data_to_data_url(&media_type, &data, &final_url);
&media_type, let assembled_url: String =
&data, url_with_fragment(data_url.as_str(), url_fragment.as_str());
&final_url, result.push_str(enquote(assembled_url, false).as_str());
&url_fragment,
);
result.push_str(enquote(data_url, false).as_str());
} }
Err(_) => { Err(_) => {
// Keep remote reference if unable to retrieve the asset // Keep remote reference if unable to retrieve the asset
if is_http_url(resolved_url.clone()) { if is_http_url(resolved_url.clone()) {
result.push_str(enquote(resolved_url, false).as_str()); let assembled_url: String = url_with_fragment(
resolved_url.as_str(),
url_fragment.as_str(),
);
result.push_str(enquote(assembled_url, false).as_str());
} }
} }
} }
@ -320,14 +325,17 @@ pub fn process_css<'a>(
) )
.as_bytes(), .as_bytes(),
&final_url, &final_url,
&url_fragment,
); );
result.push_str(enquote(data_url, false).as_str()); let assembled_url: String =
url_with_fragment(data_url.as_str(), url_fragment.as_str());
result.push_str(enquote(assembled_url, false).as_str());
} }
Err(_) => { Err(_) => {
// Keep remote reference if unable to retrieve the asset // Keep remote reference if unable to retrieve the asset
if is_http_url(full_url.clone()) { if is_http_url(full_url.clone()) {
result.push_str(enquote(full_url, false).as_str()); let assembled_url: String =
url_with_fragment(full_url.as_str(), url_fragment.as_str());
result.push_str(enquote(assembled_url, false).as_str());
} }
} }
} }
@ -339,14 +347,17 @@ pub fn process_css<'a>(
let url_fragment = get_url_fragment(full_url.clone()); let url_fragment = get_url_fragment(full_url.clone());
match retrieve_asset(cache, client, &parent_url, &full_url, opt_silent) { match retrieve_asset(cache, client, &parent_url, &full_url, opt_silent) {
Ok((data, final_url, media_type)) => { Ok((data, final_url, media_type)) => {
let data_url = let data_url = data_to_data_url(&media_type, &data, &final_url);
data_to_data_url(&media_type, &data, &final_url, &url_fragment); let assembled_url: String =
result.push_str(enquote(data_url, false).as_str()); url_with_fragment(data_url.as_str(), url_fragment.as_str());
result.push_str(enquote(assembled_url, false).as_str());
} }
Err(_) => { Err(_) => {
// Keep remote reference if unable to retrieve the asset // Keep remote reference if unable to retrieve the asset
if is_http_url(full_url.clone()) { if is_http_url(full_url.clone()) {
result.push_str(enquote(full_url, false).as_str()); let assembled_url: String =
url_with_fragment(full_url.as_str(), url_fragment.as_str());
result.push_str(enquote(assembled_url, false).as_str());
} }
} }
} }

@ -2,6 +2,7 @@ use crate::css::embed_css;
use crate::js::attr_is_event_handler; use crate::js::attr_is_event_handler;
use crate::utils::{ use crate::utils::{
data_to_data_url, get_url_fragment, is_http_url, resolve_url, retrieve_asset, url_has_protocol, data_to_data_url, get_url_fragment, is_http_url, resolve_url, retrieve_asset, url_has_protocol,
url_with_fragment,
}; };
use base64; use base64;
use html5ever::interface::QualName; use html5ever::interface::QualName;
@ -91,19 +92,19 @@ pub fn embed_srcset(
let image_url_fragment = get_url_fragment(image_full_url.clone()); let image_url_fragment = get_url_fragment(image_full_url.clone());
match retrieve_asset(cache, client, &parent_url, &image_full_url, opt_silent) { match retrieve_asset(cache, client, &parent_url, &image_full_url, opt_silent) {
Ok((image_data, image_final_url, image_media_type)) => { Ok((image_data, image_final_url, image_media_type)) => {
let image_data_url = data_to_data_url( let image_data_url =
&image_media_type, data_to_data_url(&image_media_type, &image_data, &image_final_url);
&image_data,
&image_final_url,
&image_url_fragment,
);
// Append retreved asset as a data URL // Append retreved asset as a data URL
result.push_str(image_data_url.as_ref()); let assembled_url: String =
url_with_fragment(image_data_url.as_str(), image_url_fragment.as_str());
result.push_str(assembled_url.as_ref());
} }
Err(_) => { Err(_) => {
// Keep remote reference if unable to retrieve the asset // Keep remote reference if unable to retrieve the asset
if is_http_url(image_full_url.clone()) { if is_http_url(image_full_url.clone()) {
result.push_str(image_full_url.as_ref()); let assembled_url: String =
url_with_fragment(image_full_url.as_str(), image_url_fragment.as_str());
result.push_str(assembled_url.as_ref());
} else { } else {
// Avoid breaking the structure in case if not an HTTP(S) URL // Avoid breaking the structure in case if not an HTTP(S) URL
result.push_str(empty_image!()); result.push_str(empty_image!());
@ -246,33 +247,36 @@ pub fn walk_and_embed_assets(
&link_href_media_type, &link_href_media_type,
&link_href_data, &link_href_data,
&link_href_final_url, &link_href_final_url,
&link_href_url_fragment,
); );
// Add new data URL href attribute // Add new data URL href attribute
let assembled_url: String = url_with_fragment(
link_href_data_url.as_str(),
link_href_url_fragment.as_str(),
);
attrs_mut.push(Attribute { attrs_mut.push(Attribute {
name: QualName::new( name: QualName::new(
None, None,
ns!(), ns!(),
local_name!("href"), local_name!("href"),
), ),
value: Tendril::from_slice( value: Tendril::from_slice(assembled_url.as_ref()),
link_href_data_url.as_ref(),
),
}); });
} }
} }
Err(_) => { Err(_) => {
// Keep remote reference if unable to retrieve the asset // Keep remote reference if unable to retrieve the asset
if is_http_url(link_href_full_url.clone()) { if is_http_url(link_href_full_url.clone()) {
let assembled_url: String = url_with_fragment(
link_href_full_url.as_str(),
link_href_url_fragment.as_str(),
);
attrs_mut.push(Attribute { attrs_mut.push(Attribute {
name: QualName::new( name: QualName::new(
None, None,
ns!(), ns!(),
local_name!("href"), local_name!("href"),
), ),
value: Tendril::from_slice( value: Tendril::from_slice(assembled_url.as_ref()),
link_href_full_url.as_ref(),
),
}); });
} }
} }
@ -324,7 +328,6 @@ pub fn walk_and_embed_assets(
"text/css", "text/css",
css.as_bytes(), css.as_bytes(),
&link_href_final_url, &link_href_final_url,
"",
); );
// Add new data URL href attribute // Add new data URL href attribute
attrs_mut.push(Attribute { attrs_mut.push(Attribute {
@ -399,20 +402,27 @@ pub fn walk_and_embed_assets(
&background_media_type, &background_media_type,
&background_data, &background_data,
&background_final_url, &background_final_url,
&background_url_fragment,
); );
// Add new data URL background attribute // Add new data URL background attribute
let assembled_url: String = url_with_fragment(
background_data_url.as_str(),
background_url_fragment.as_str(),
);
attrs_mut.push(Attribute { attrs_mut.push(Attribute {
name: QualName::new(None, ns!(), local_name!("background")), name: QualName::new(None, ns!(), local_name!("background")),
value: Tendril::from_slice(background_data_url.as_ref()), value: Tendril::from_slice(assembled_url.as_ref()),
}); });
} }
Err(_) => { Err(_) => {
// Keep remote reference if unable to retrieve the asset // Keep remote reference if unable to retrieve the asset
if is_http_url(background_full_url.clone()) { if is_http_url(background_full_url.clone()) {
let assembled_url: String = url_with_fragment(
background_full_url.as_str(),
background_url_fragment.as_str(),
);
attrs_mut.push(Attribute { attrs_mut.push(Attribute {
name: QualName::new(None, ns!(), local_name!("background")), name: QualName::new(None, ns!(), local_name!("background")),
value: Tendril::from_slice(background_full_url.as_ref()), value: Tendril::from_slice(assembled_url.as_ref()),
}); });
} }
} }
@ -469,19 +479,26 @@ pub fn walk_and_embed_assets(
&img_media_type, &img_media_type,
&img_data, &img_data,
&img_final_url, &img_final_url,
&img_url_fragment, );
let assembled_url: String = url_with_fragment(
img_data_url.as_str(),
img_url_fragment.as_str(),
); );
attrs_mut.push(Attribute { attrs_mut.push(Attribute {
name: QualName::new(None, ns!(), local_name!("src")), name: QualName::new(None, ns!(), local_name!("src")),
value: Tendril::from_slice(img_data_url.as_ref()), value: Tendril::from_slice(assembled_url.as_ref()),
}); });
} }
Err(_) => { Err(_) => {
// Keep remote reference if unable to retrieve the asset // Keep remote reference if unable to retrieve the asset
if is_http_url(img_full_url.clone()) { if is_http_url(img_full_url.clone()) {
let assembled_url: String = url_with_fragment(
img_full_url.as_str(),
img_url_fragment.as_str(),
);
attrs_mut.push(Attribute { attrs_mut.push(Attribute {
name: QualName::new(None, ns!(), local_name!("src")), name: QualName::new(None, ns!(), local_name!("src")),
value: Tendril::from_slice(img_full_url.as_ref()), value: Tendril::from_slice(assembled_url.as_ref()),
}); });
} }
} }
@ -563,22 +580,27 @@ pub fn walk_and_embed_assets(
&input_image_media_type, &input_image_media_type,
&input_image_data, &input_image_data,
&input_image_final_url, &input_image_final_url,
&input_image_url_fragment,
); );
// Add data URL src attribute // Add data URL src attribute
let assembled_url: String = url_with_fragment(
input_image_data_url.as_str(),
input_image_url_fragment.as_str(),
);
attrs_mut.push(Attribute { attrs_mut.push(Attribute {
name: QualName::new(None, ns!(), local_name!("src")), name: QualName::new(None, ns!(), local_name!("src")),
value: Tendril::from_slice(input_image_data_url.as_ref()), value: Tendril::from_slice(assembled_url.as_ref()),
}); });
} }
Err(_) => { Err(_) => {
// Keep remote reference if unable to retrieve the asset // Keep remote reference if unable to retrieve the asset
if is_http_url(input_image_full_url.clone()) { if is_http_url(input_image_full_url.clone()) {
let assembled_url: String = url_with_fragment(
input_image_full_url.as_str(),
input_image_url_fragment.as_str(),
);
attrs_mut.push(Attribute { attrs_mut.push(Attribute {
name: QualName::new(None, ns!(), local_name!("src")), name: QualName::new(None, ns!(), local_name!("src")),
value: Tendril::from_slice( value: Tendril::from_slice(assembled_url.as_ref()),
input_image_full_url.as_ref(),
),
}); });
} }
} }
@ -610,20 +632,27 @@ pub fn walk_and_embed_assets(
&image_media_type, &image_media_type,
&image_data, &image_data,
&image_final_url, &image_final_url,
&image_url_fragment,
); );
// Add new data URL href attribute // Add new data URL href attribute
let assembled_url: String = url_with_fragment(
image_data_url.as_str(),
image_url_fragment.as_str(),
);
attrs_mut.push(Attribute { attrs_mut.push(Attribute {
name: QualName::new(None, ns!(), local_name!("href")), name: QualName::new(None, ns!(), local_name!("href")),
value: Tendril::from_slice(image_data_url.as_ref()), value: Tendril::from_slice(assembled_url.as_ref()),
}); });
} }
Err(_) => { Err(_) => {
// Keep remote reference if unable to retrieve the asset // Keep remote reference if unable to retrieve the asset
if is_http_url(image_full_url.clone()) { if is_http_url(image_full_url.clone()) {
let assembled_url: String = url_with_fragment(
image_full_url.as_str(),
image_url_fragment.as_str(),
);
attrs_mut.push(Attribute { attrs_mut.push(Attribute {
name: QualName::new(None, ns!(), local_name!("href")), name: QualName::new(None, ns!(), local_name!("href")),
value: Tendril::from_slice(image_full_url.as_ref()), value: Tendril::from_slice(assembled_url.as_ref()),
}); });
} }
} }
@ -661,21 +690,23 @@ pub fn walk_and_embed_assets(
&srcset_media_type, &srcset_media_type,
&srcset_data, &srcset_data,
&srcset_final_url, &srcset_final_url,
&srcset_url_fragment,
); );
attr.value.clear(); attr.value.clear();
attr.value.push_slice(srcset_data_url.as_str()); let assembled_url: String = url_with_fragment(
srcset_data_url.as_str(),
srcset_url_fragment.as_str(),
);
attr.value.push_slice(assembled_url.as_str());
} }
Err(_) => { Err(_) => {
// Keep remote reference if unable to retrieve the asset // Keep remote reference if unable to retrieve the asset
if is_http_url(srcset_full_url.clone()) { if is_http_url(srcset_full_url.clone()) {
attr.value.clear(); attr.value.clear();
attr.value.push_slice(srcset_full_url.as_str()); let assembled_url: String = url_with_fragment(
if !srcset_url_fragment.is_empty() { srcset_full_url.as_str(),
attr.value.push_slice("#"); srcset_url_fragment.as_str(),
attr.value );
.push_slice(srcset_url_fragment.as_str()); attr.value.push_slice(assembled_url.as_str());
}
} }
} }
} }
@ -739,7 +770,6 @@ pub fn walk_and_embed_assets(
"application/javascript", "application/javascript",
&script_data, &script_data,
&script_final_url, &script_final_url,
"",
); );
// Add new data URL src attribute // Add new data URL src attribute
attrs_mut.push(Attribute { attrs_mut.push(Attribute {
@ -844,16 +874,23 @@ pub fn walk_and_embed_assets(
&frame_media_type, &frame_media_type,
&frame_data, &frame_data,
&frame_final_url, &frame_final_url,
&frame_url_fragment,
); );
attr.value.clear(); attr.value.clear();
attr.value.push_slice(frame_data_url.as_str()); let assembled_url: String = url_with_fragment(
frame_data_url.as_str(),
frame_url_fragment.as_str(),
);
attr.value.push_slice(assembled_url.as_str());
} }
Err(_) => { Err(_) => {
// Keep remote reference if unable to retrieve the asset // Keep remote reference if unable to retrieve the asset
if is_http_url(frame_full_url.clone()) { if is_http_url(frame_full_url.clone()) {
attr.value.clear(); attr.value.clear();
attr.value.push_slice(frame_full_url.as_str()); let assembled_url: String = url_with_fragment(
frame_full_url.as_str(),
frame_url_fragment.as_str(),
);
attr.value.push_slice(assembled_url.as_str());
} }
} }
} }
@ -896,16 +933,23 @@ pub fn walk_and_embed_assets(
&video_poster_media_type, &video_poster_media_type,
&video_poster_data, &video_poster_data,
&video_poster_final_url, &video_poster_final_url,
&video_poster_url_fragment,
); );
attr.value.clear(); attr.value.clear();
attr.value.push_slice(video_poster_data_url.as_str()); let assembled_url: String = url_with_fragment(
video_poster_data_url.as_str(),
video_poster_url_fragment.as_str(),
);
attr.value.push_slice(assembled_url.as_str());
} }
Err(_) => { Err(_) => {
// Keep remote reference if unable to retrieve the asset // Keep remote reference if unable to retrieve the asset
if is_http_url(video_poster_full_url.clone()) { if is_http_url(video_poster_full_url.clone()) {
attr.value.clear(); attr.value.clear();
attr.value.push_slice(video_poster_full_url.as_str()); let assembled_url: String = url_with_fragment(
video_poster_full_url.as_str(),
video_poster_url_fragment.as_str(),
);
attr.value.push_slice(assembled_url.as_str());
} }
} }
} }

@ -13,7 +13,7 @@ mod passing {
fn encode_string_with_specific_media_type() { fn encode_string_with_specific_media_type() {
let mime = "application/javascript"; let mime = "application/javascript";
let data = "var word = 'hello';\nalert(word);\n"; let data = "var word = 'hello';\nalert(word);\n";
let data_url = utils::data_to_data_url(mime, data.as_bytes(), "", ""); let data_url = utils::data_to_data_url(mime, data.as_bytes(), "");
assert_eq!( assert_eq!(
&data_url, &data_url,
@ -24,8 +24,8 @@ mod passing {
#[test] #[test]
fn encode_append_fragment() { fn encode_append_fragment() {
let data = "<svg></svg>\n"; let data = "<svg></svg>\n";
let data_url = utils::data_to_data_url("text/css", data.as_bytes(), "", "fragment"); let data_url = utils::data_to_data_url("image/svg+xml", data.as_bytes(), "");
assert_eq!(&data_url, "data:text/css;base64,PHN2Zz48L3N2Zz4K#fragment"); assert_eq!(&data_url, "data:image/svg+xml;base64,PHN2Zz48L3N2Zz4K");
} }
} }

@ -11,3 +11,4 @@ mod is_http_url;
mod resolve_url; mod resolve_url;
mod retrieve_asset; mod retrieve_asset;
mod url_has_protocol; mod url_has_protocol;
mod url_with_fragment;

@ -28,12 +28,12 @@ mod passing {
) )
.unwrap(); .unwrap();
assert_eq!( assert_eq!(
utils::data_to_data_url(&media_type, &data, &final_url, ""), utils::data_to_data_url(&media_type, &data, &final_url),
utils::data_to_data_url("text/html", "target".as_bytes(), "", "") utils::data_to_data_url("text/html", "target".as_bytes(), "")
); );
assert_eq!( assert_eq!(
final_url, final_url,
utils::data_to_data_url("text/html", "target".as_bytes(), "", "") utils::data_to_data_url("text/html", "target".as_bytes(), "")
); );
assert_eq!(&media_type, "text/html"); assert_eq!(&media_type, "text/html");
} }
@ -63,7 +63,7 @@ mod passing {
false, false,
) )
.unwrap(); .unwrap();
assert_eq!(utils::data_to_data_url("application/javascript", &data, &final_url, ""), "data:application/javascript;base64,ZG9jdW1lbnQuYm9keS5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSAiZ3JlZW4iOwpkb2N1bWVudC5ib2R5LnN0eWxlLmNvbG9yID0gInJlZCI7Cg=="); assert_eq!(utils::data_to_data_url("application/javascript", &data, &final_url), "data:application/javascript;base64,ZG9jdW1lbnQuYm9keS5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSAiZ3JlZW4iOwpkb2N1bWVudC5ib2R5LnN0eWxlLmNvbG9yID0gInJlZCI7Cg==");
assert_eq!( assert_eq!(
&final_url, &final_url,
&format!( &format!(

@ -0,0 +1,40 @@
// ██████╗ █████╗ ███████╗███████╗██╗███╗ ██╗ ██████╗
// ██╔══██╗██╔══██╗██╔════╝██╔════╝██║████╗ ██║██╔════╝
// ██████╔╝███████║███████╗███████╗██║██╔██╗ ██║██║ ███╗
// ██╔═══╝ ██╔══██║╚════██║╚════██║██║██║╚██╗██║██║ ██║
// ██║ ██║ ██║███████║███████║██║██║ ╚████║╚██████╔╝
// ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚═╝╚═╝ ╚═══╝ ╚═════╝
#[cfg(test)]
mod passing {
use crate::utils;
#[test]
fn url_with_fragment_url() {
let url = "https://localhost.localdomain/path/";
let fragment = "test";
let assembled_url = utils::url_with_fragment(url, fragment);
assert_eq!(&assembled_url, "https://localhost.localdomain/path/#test");
}
#[test]
fn url_with_fragment_empty_url() {
let url = "https://localhost.localdomain/path/";
let fragment = "";
let assembled_url = utils::url_with_fragment(url, fragment);
assert_eq!(&assembled_url, "https://localhost.localdomain/path/");
}
#[test]
fn url_with_fragment_data_url() {
let url = "data:image/svg+xml;base64,PHN2Zz48L3N2Zz4K";
let fragment = "fragment";
let assembled_url = utils::url_with_fragment(url, fragment);
assert_eq!(
&assembled_url,
"data:image/svg+xml;base64,PHN2Zz48L3N2Zz4K#fragment"
);
}
}

@ -38,24 +38,14 @@ const PLAINTEXT_MEDIA_TYPES: &[&str] = &[
"text/plain", "text/plain",
]; ];
pub fn data_to_data_url(media_type: &str, data: &[u8], url: &str, fragment: &str) -> String { pub fn data_to_data_url(media_type: &str, data: &[u8], url: &str) -> String {
let media_type: String = if media_type.is_empty() { let media_type: String = if media_type.is_empty() {
detect_media_type(data, &url) detect_media_type(data, &url)
} else { } else {
media_type.to_string() media_type.to_string()
}; };
let hash: String = if fragment != "" {
format!("#{}", fragment)
} else {
str!()
};
format!( format!("data:{};base64,{}", media_type, base64::encode(data))
"data:{};base64,{}{}",
media_type,
base64::encode(data),
hash
)
} }
pub fn detect_media_type(data: &[u8], url: &str) -> String { pub fn detect_media_type(data: &[u8], url: &str) -> String {
@ -301,3 +291,14 @@ pub fn retrieve_asset(
} }
} }
} }
pub fn url_with_fragment(url: &str, fragment: &str) -> String {
let mut result = str!(&url);
if !fragment.is_empty() {
result += "#";
result += fragment;
}
result
}

Loading…
Cancel
Save