create a separate function for appending URL fragments

This commit is contained in:
Sunshine 2020-06-24 02:17:16 -04:00
parent 877b11d52c
commit f6ea16b3ad
No known key found for this signature in database
GPG key ID: B80CA68703CD8AB1
7 changed files with 197 additions and 100 deletions

View file

@ -2,7 +2,9 @@ use cssparser::{ParseError, Parser, ParserInput, SourcePosition, Token};
use reqwest::blocking::Client;
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] = &[
// Universal
@ -173,32 +175,34 @@ pub fn process_css<'a>(
let import_url_fragment = get_url_fragment(import_full_url.clone());
match retrieve_asset(cache, client, &parent_url, &import_full_url, opt_silent) {
Ok((import_contents, import_final_url, _import_media_type)) => {
result.push_str(
enquote(
data_to_data_url(
"text/css",
embed_css(
cache,
client,
&import_final_url,
&String::from_utf8_lossy(&import_contents),
opt_no_fonts,
opt_no_images,
opt_silent,
)
.as_bytes(),
&import_final_url,
&import_url_fragment,
),
false,
let import_data_url = data_to_data_url(
"text/css",
embed_css(
cache,
client,
&import_final_url,
&String::from_utf8_lossy(&import_contents),
opt_no_fonts,
opt_no_images,
opt_silent,
)
.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(_) => {
// Keep remote reference if unable to retrieve the asset
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,
) {
Ok((data, final_url, media_type)) => {
let data_url = data_to_data_url(
&media_type,
&data,
&final_url,
&url_fragment,
);
result.push_str(enquote(data_url, false).as_str());
let data_url = data_to_data_url(&media_type, &data, &final_url);
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(_) => {
// Keep remote reference if unable to retrieve the asset
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(),
&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(_) => {
// Keep remote reference if unable to retrieve the asset
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());
match retrieve_asset(cache, client, &parent_url, &full_url, opt_silent) {
Ok((data, final_url, media_type)) => {
let data_url =
data_to_data_url(&media_type, &data, &final_url, &url_fragment);
result.push_str(enquote(data_url, false).as_str());
let data_url = data_to_data_url(&media_type, &data, &final_url);
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(_) => {
// Keep remote reference if unable to retrieve the asset
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());
}
}
}

View file

@ -2,6 +2,7 @@ use crate::css::embed_css;
use crate::js::attr_is_event_handler;
use crate::utils::{
data_to_data_url, get_url_fragment, is_http_url, resolve_url, retrieve_asset, url_has_protocol,
url_with_fragment,
};
use base64;
use html5ever::interface::QualName;
@ -91,19 +92,19 @@ pub fn embed_srcset(
let image_url_fragment = get_url_fragment(image_full_url.clone());
match retrieve_asset(cache, client, &parent_url, &image_full_url, opt_silent) {
Ok((image_data, image_final_url, image_media_type)) => {
let image_data_url = data_to_data_url(
&image_media_type,
&image_data,
&image_final_url,
&image_url_fragment,
);
let image_data_url =
data_to_data_url(&image_media_type, &image_data, &image_final_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(_) => {
// Keep remote reference if unable to retrieve the asset
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 {
// Avoid breaking the structure in case if not an HTTP(S) URL
result.push_str(empty_image!());
@ -246,33 +247,36 @@ pub fn walk_and_embed_assets(
&link_href_media_type,
&link_href_data,
&link_href_final_url,
&link_href_url_fragment,
);
// 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 {
name: QualName::new(
None,
ns!(),
local_name!("href"),
),
value: Tendril::from_slice(
link_href_data_url.as_ref(),
),
value: Tendril::from_slice(assembled_url.as_ref()),
});
}
}
Err(_) => {
// Keep remote reference if unable to retrieve the asset
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 {
name: QualName::new(
None,
ns!(),
local_name!("href"),
),
value: Tendril::from_slice(
link_href_full_url.as_ref(),
),
value: Tendril::from_slice(assembled_url.as_ref()),
});
}
}
@ -324,7 +328,6 @@ pub fn walk_and_embed_assets(
"text/css",
css.as_bytes(),
&link_href_final_url,
"",
);
// Add new data URL href attribute
attrs_mut.push(Attribute {
@ -399,20 +402,27 @@ pub fn walk_and_embed_assets(
&background_media_type,
&background_data,
&background_final_url,
&background_url_fragment,
);
// 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 {
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(_) => {
// Keep remote reference if unable to retrieve the asset
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 {
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_data,
&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 {
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(_) => {
// Keep remote reference if unable to retrieve the asset
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 {
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_data,
&input_image_final_url,
&input_image_url_fragment,
);
// 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 {
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(_) => {
// Keep remote reference if unable to retrieve the asset
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 {
name: QualName::new(None, ns!(), local_name!("src")),
value: Tendril::from_slice(
input_image_full_url.as_ref(),
),
value: Tendril::from_slice(assembled_url.as_ref()),
});
}
}
@ -610,20 +632,27 @@ pub fn walk_and_embed_assets(
&image_media_type,
&image_data,
&image_final_url,
&image_url_fragment,
);
// 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 {
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(_) => {
// Keep remote reference if unable to retrieve the asset
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 {
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_data,
&srcset_final_url,
&srcset_url_fragment,
);
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(_) => {
// Keep remote reference if unable to retrieve the asset
if is_http_url(srcset_full_url.clone()) {
attr.value.clear();
attr.value.push_slice(srcset_full_url.as_str());
if !srcset_url_fragment.is_empty() {
attr.value.push_slice("#");
attr.value
.push_slice(srcset_url_fragment.as_str());
}
let assembled_url: String = url_with_fragment(
srcset_full_url.as_str(),
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",
&script_data,
&script_final_url,
"",
);
// Add new data URL src attribute
attrs_mut.push(Attribute {
@ -844,16 +874,23 @@ pub fn walk_and_embed_assets(
&frame_media_type,
&frame_data,
&frame_final_url,
&frame_url_fragment,
);
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(_) => {
// Keep remote reference if unable to retrieve the asset
if is_http_url(frame_full_url.clone()) {
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_data,
&video_poster_final_url,
&video_poster_url_fragment,
);
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(_) => {
// Keep remote reference if unable to retrieve the asset
if is_http_url(video_poster_full_url.clone()) {
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());
}
}
}

View file

@ -13,7 +13,7 @@ mod passing {
fn encode_string_with_specific_media_type() {
let mime = "application/javascript";
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!(
&data_url,
@ -24,8 +24,8 @@ mod passing {
#[test]
fn encode_append_fragment() {
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");
}
}

View file

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

View file

@ -28,12 +28,12 @@ mod passing {
)
.unwrap();
assert_eq!(
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(&media_type, &data, &final_url),
utils::data_to_data_url("text/html", "target".as_bytes(), "")
);
assert_eq!(
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");
}
@ -63,7 +63,7 @@ mod passing {
false,
)
.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!(
&final_url,
&format!(

View file

@ -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"
);
}
}

View file

@ -38,24 +38,14 @@ const PLAINTEXT_MEDIA_TYPES: &[&str] = &[
"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() {
detect_media_type(data, &url)
} else {
media_type.to_string()
};
let hash: String = if fragment != "" {
format!("#{}", fragment)
} else {
str!()
};
format!(
"data:{};base64,{}{}",
media_type,
base64::encode(data),
hash
)
format!("data:{};base64,{}", media_type, base64::encode(data))
}
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
}