Merge pull request #193 from snshn/options-struct

Pass options object instead of using separate parameters
This commit is contained in:
Sunshine 2020-06-28 01:51:05 -04:00 committed by GitHub
commit 438ebd520a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 320 additions and 632 deletions

View file

@ -2,6 +2,7 @@ use cssparser::{ParseError, Parser, ParserInput, SourcePosition, Token};
use reqwest::blocking::Client;
use std::collections::HashMap;
use crate::opts::Options;
use crate::url::{data_to_data_url, get_url_fragment, is_http_url, resolve_url, url_with_fragment};
use crate::utils::retrieve_asset;
@ -59,12 +60,10 @@ pub fn process_css<'a>(
client: &Client,
parent_url: &str,
parser: &mut Parser,
options: &Options,
rule_name: &str,
prop_name: &str,
func_name: &str,
opt_no_fonts: bool,
opt_no_images: bool,
opt_silent: bool,
) -> Result<String, ParseError<'a, String>> {
let mut result: String = str!();
@ -91,7 +90,7 @@ pub fn process_css<'a>(
Token::Colon => result.push_str(":"),
Token::Comma => result.push_str(","),
Token::ParenthesisBlock | Token::SquareBracketBlock | Token::CurlyBracketBlock => {
if opt_no_fonts && curr_rule == "font-face" {
if options.no_fonts && curr_rule == "font-face" {
continue;
}
@ -114,12 +113,10 @@ pub fn process_css<'a>(
client,
parent_url,
parser,
options,
rule_name,
curr_prop.as_str(),
func_name,
opt_no_fonts,
opt_no_images,
opt_silent,
)
})
.unwrap();
@ -149,7 +146,7 @@ pub fn process_css<'a>(
// @import, @font-face, @charset, @media...
Token::AtKeyword(ref value) => {
curr_rule = str!(value);
if opt_no_fonts && curr_rule == "font-face" {
if options.no_fonts && curr_rule == "font-face" {
continue;
}
result.push_str("@");
@ -172,7 +169,13 @@ pub fn process_css<'a>(
let import_full_url = resolve_url(&parent_url, value).unwrap_or_default();
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,
options.silent,
) {
Ok((import_contents, import_final_url, _import_media_type)) => {
let import_data_url = data_to_data_url(
"text/css",
@ -181,9 +184,7 @@ pub fn process_css<'a>(
client,
&import_final_url,
&String::from_utf8_lossy(&import_contents),
opt_no_fonts,
opt_no_images,
opt_silent,
options,
)
.as_bytes(),
&import_final_url,
@ -212,7 +213,7 @@ pub fn process_css<'a>(
continue;
}
if opt_no_images && is_image_url_prop(curr_prop.as_str()) {
if options.no_images && is_image_url_prop(curr_prop.as_str()) {
result.push_str(enquote(str!(empty_image!()), false).as_str());
} else {
let resolved_url = resolve_url(&parent_url, value).unwrap_or_default();
@ -222,7 +223,7 @@ pub fn process_css<'a>(
client,
&parent_url,
&resolved_url,
opt_silent,
options.silent,
) {
Ok((data, final_url, media_type)) => {
let data_url = data_to_data_url(&media_type, &data, &final_url);
@ -265,7 +266,7 @@ pub fn process_css<'a>(
if *has_sign && *unit_value >= 0. {
result.push_str("+");
}
result.push_str(str!(unit_value * 100.).as_str());
result.push_str(str!(unit_value * 100.0).as_str());
result.push_str("%");
}
Token::Dimension {
@ -309,7 +310,7 @@ pub fn process_css<'a>(
if is_import {
let full_url = resolve_url(&parent_url, value).unwrap_or_default();
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, options.silent) {
Ok((css, final_url, _media_type)) => {
let data_url = data_to_data_url(
"text/css",
@ -318,9 +319,7 @@ pub fn process_css<'a>(
client,
&final_url,
&String::from_utf8_lossy(&css),
opt_no_fonts,
opt_no_images,
opt_silent,
options,
)
.as_bytes(),
&final_url,
@ -339,12 +338,13 @@ pub fn process_css<'a>(
}
}
} else {
if opt_no_images && is_image_url_prop(curr_prop.as_str()) {
if options.no_images && is_image_url_prop(curr_prop.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 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, options.silent)
{
Ok((data, final_url, media_type)) => {
let data_url = data_to_data_url(&media_type, &data, &final_url);
let assembled_url: String =
@ -377,12 +377,10 @@ pub fn process_css<'a>(
client,
parent_url,
parser,
options,
curr_rule.as_str(),
curr_prop.as_str(),
function_name,
opt_no_fonts,
opt_no_images,
opt_silent,
)
})
.unwrap();
@ -407,24 +405,10 @@ pub fn embed_css(
client: &Client,
parent_url: &str,
css: &str,
opt_no_fonts: bool,
opt_no_images: bool,
opt_silent: bool,
options: &Options,
) -> String {
let mut input = ParserInput::new(&css);
let mut parser = Parser::new(&mut input);
process_css(
cache,
client,
parent_url,
&mut parser,
"",
"",
"",
opt_no_fonts,
opt_no_images,
opt_silent,
)
.unwrap()
process_css(cache, client, parent_url, &mut parser, options, "", "", "").unwrap()
}

View file

@ -15,6 +15,7 @@ use std::default::Default;
use crate::css::embed_css;
use crate::js::attr_is_event_handler;
use crate::opts::Options;
use crate::url::{
data_to_data_url, get_url_fragment, is_http_url, resolve_url, url_has_protocol,
url_with_fragment,
@ -73,8 +74,7 @@ pub fn embed_srcset(
client: &Client,
parent_url: &str,
srcset: &str,
opt_no_images: bool,
opt_silent: bool,
options: &Options,
) -> String {
let mut array: Vec<SrcSetItem> = vec![];
let srcset_items: Vec<&str> = srcset.split(',').collect();
@ -89,12 +89,12 @@ pub fn embed_srcset(
let mut result: String = str!();
let mut i: usize = array.len();
for part in array {
if opt_no_images {
if options.no_images {
result.push_str(empty_image!());
} else {
let image_full_url = resolve_url(&parent_url, part.path).unwrap_or_default();
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, options.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);
@ -137,29 +137,13 @@ pub fn walk_and_embed_assets(
client: &Client,
url: &str,
node: &Handle,
opt_no_css: bool,
opt_no_fonts: bool,
opt_no_frames: bool,
opt_no_js: bool,
opt_no_images: bool,
opt_silent: bool,
options: &Options,
) {
match node.data {
NodeData::Document => {
// Dig deeper
for child in node.children.borrow().iter() {
walk_and_embed_assets(
cache,
client,
&url,
child,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
opt_silent,
);
walk_and_embed_assets(cache, client, &url, child, options);
}
}
NodeData::Element {
@ -245,7 +229,7 @@ pub fn walk_and_embed_assets(
}
}
if !opt_no_images && !link_href.is_empty() {
if !options.no_images && !link_href.is_empty() {
let link_href_full_url =
resolve_url(&url, link_href).unwrap_or_default();
let link_href_url_fragment =
@ -255,7 +239,7 @@ pub fn walk_and_embed_assets(
client,
&url,
&link_href_full_url,
opt_silent,
options.silent,
) {
Ok((
link_href_data,
@ -319,7 +303,7 @@ pub fn walk_and_embed_assets(
}
}
if !opt_no_css && !link_href.is_empty() {
if !options.no_css && !link_href.is_empty() {
let link_href_full_url =
resolve_url(&url, link_href).unwrap_or_default();
match retrieve_asset(
@ -327,7 +311,7 @@ pub fn walk_and_embed_assets(
client,
&url,
&link_href_full_url,
opt_silent,
options.silent,
) {
Ok((
link_href_data,
@ -343,9 +327,7 @@ pub fn walk_and_embed_assets(
client,
&link_href_final_url,
&String::from_utf8_lossy(&link_href_data),
opt_no_fonts,
opt_no_images,
opt_silent,
options,
);
let link_href_data_url = data_to_data_url(
"text/css",
@ -415,11 +397,16 @@ pub fn walk_and_embed_assets(
}
}
if !opt_no_images && !background.is_empty() {
if !options.no_images && !background.is_empty() {
let background_full_url = resolve_url(&url, background).unwrap_or_default();
let background_url_fragment = get_url_fragment(background_full_url.clone());
match retrieve_asset(cache, client, &url, &background_full_url, opt_silent)
{
match retrieve_asset(
cache,
client,
&url,
&background_full_url,
options.silent,
) {
Ok((background_data, background_final_url, background_media_type)) => {
let background_data_url = data_to_data_url(
&background_media_type,
@ -471,7 +458,7 @@ pub fn walk_and_embed_assets(
}
}
if opt_no_images {
if options.no_images {
// Add empty image src attribute
attrs_mut.push(Attribute {
name: QualName::new(None, ns!(), local_name!("src")),
@ -496,7 +483,8 @@ pub fn walk_and_embed_assets(
)
.unwrap_or_default();
let img_url_fragment = get_url_fragment(img_full_url.clone());
match retrieve_asset(cache, client, &url, &img_full_url, opt_silent) {
match retrieve_asset(cache, client, &url, &img_full_url, options.silent)
{
Ok((img_data, img_final_url, img_media_type)) => {
let img_data_url = data_to_data_url(
&img_media_type,
@ -533,21 +521,13 @@ pub fn walk_and_embed_assets(
attrs_mut.push(Attribute {
name: QualName::new(None, ns!(), local_name!("srcset")),
value: Tendril::from_slice(
embed_srcset(
cache,
client,
&url,
&img_srcset,
opt_no_images,
opt_silent,
)
.as_ref(),
embed_srcset(cache, client, &url, &img_srcset, options).as_ref(),
),
});
}
}
"svg" => {
if opt_no_images {
if options.no_images {
node.children.borrow_mut().clear();
}
}
@ -573,7 +553,7 @@ pub fn walk_and_embed_assets(
}
}
if opt_no_images || input_image_src.is_empty() {
if options.no_images || input_image_src.is_empty() {
attrs_mut.push(Attribute {
name: QualName::new(None, ns!(), local_name!("src")),
value: Tendril::from_slice(if input_image_src.is_empty() {
@ -592,7 +572,7 @@ pub fn walk_and_embed_assets(
client,
&url,
&input_image_full_url,
opt_silent,
options.silent,
) {
Ok((
input_image_data,
@ -646,10 +626,10 @@ pub fn walk_and_embed_assets(
}
}
if !opt_no_images && !image_href.is_empty() {
if !options.no_images && !image_href.is_empty() {
let image_full_url = resolve_url(&url, image_href).unwrap_or_default();
let image_url_fragment = get_url_fragment(image_full_url.clone());
match retrieve_asset(cache, client, &url, &image_full_url, opt_silent) {
match retrieve_asset(cache, client, &url, &image_full_url, options.silent) {
Ok((image_data, image_final_url, image_media_type)) => {
let image_data_url = data_to_data_url(
&image_media_type,
@ -693,7 +673,7 @@ pub fn walk_and_embed_assets(
attr.value.push_slice(src_full_url.as_str());
} else if attr_name.eq_ignore_ascii_case("srcset") {
if get_node_name(&get_parent_node(&node)) == Some("picture") {
if opt_no_images {
if options.no_images {
attr.value.clear();
attr.value.push_slice(empty_image!());
} else {
@ -706,7 +686,7 @@ pub fn walk_and_embed_assets(
client,
&url,
&srcset_full_url,
opt_silent,
options.silent,
) {
Ok((srcset_data, srcset_final_url, srcset_media_type)) => {
let srcset_data_url = data_to_data_url(
@ -744,7 +724,7 @@ pub fn walk_and_embed_assets(
if attr_name.eq_ignore_ascii_case("href") {
let attr_value = attr.value.trim();
if opt_no_js && attr_value.starts_with("javascript:") {
if options.no_js && attr_value.trim().starts_with("javascript:") {
attr.value.clear();
// Replace with empty JS call to preserve original behavior
attr.value.push_slice("javascript:;");
@ -778,12 +758,13 @@ pub fn walk_and_embed_assets(
}
}
if opt_no_js {
if options.no_js {
// Empty inner content (src is already gone)
node.children.borrow_mut().clear();
} else if !script_src.is_empty() {
let script_full_url = resolve_url(&url, script_src).unwrap_or_default();
match retrieve_asset(cache, client, &url, &script_full_url, opt_silent) {
match retrieve_asset(cache, client, &url, &script_full_url, options.silent)
{
Ok((script_data, script_final_url, _script_media_type)) => {
// Only embed if we're able to validate integrity
if script_integrity.is_empty()
@ -814,22 +795,15 @@ pub fn walk_and_embed_assets(
}
}
"style" => {
if opt_no_css {
if options.no_css {
// Empty inner content of STYLE tags
node.children.borrow_mut().clear();
} else {
for node in node.children.borrow_mut().iter_mut() {
if let NodeData::Text { ref contents } = node.data {
let mut tendril = contents.borrow_mut();
let replacement = embed_css(
cache,
client,
&url,
tendril.as_ref(),
opt_no_fonts,
opt_no_images,
opt_silent,
);
let replacement =
embed_css(cache, client, &url, tendril.as_ref(), options);
tendril.clear();
tendril.push_slice(&replacement);
}
@ -855,7 +829,7 @@ pub fn walk_and_embed_assets(
for attr in attrs_mut.iter_mut() {
let attr_name: &str = &attr.name.local;
if attr_name.eq_ignore_ascii_case("src") {
if opt_no_frames {
if options.no_frames {
// Empty the src attribute
attr.value.clear();
continue;
@ -870,7 +844,13 @@ pub fn walk_and_embed_assets(
let frame_full_url = resolve_url(&url, frame_src).unwrap_or_default();
let frame_url_fragment = get_url_fragment(frame_full_url.clone());
match retrieve_asset(cache, client, &url, &frame_full_url, opt_silent) {
match retrieve_asset(
cache,
client,
&url,
&frame_full_url,
options.silent,
) {
Ok((frame_data, frame_final_url, frame_media_type)) => {
let frame_dom =
html_to_dom(&String::from_utf8_lossy(&frame_data));
@ -879,12 +859,7 @@ pub fn walk_and_embed_assets(
client,
&frame_final_url,
&frame_dom.document,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
opt_silent,
&options,
);
let mut frame_data: Vec<u8> = Vec::new();
serialize(
@ -931,7 +906,7 @@ pub fn walk_and_embed_assets(
continue;
}
if opt_no_images {
if options.no_images {
attr.value.clear();
continue;
}
@ -945,7 +920,7 @@ pub fn walk_and_embed_assets(
client,
&url,
&video_poster_full_url,
opt_silent,
options.silent,
) {
Ok((
video_poster_data,
@ -983,7 +958,7 @@ pub fn walk_and_embed_assets(
}
// Process style attributes
if opt_no_css {
if options.no_css {
// Get rid of style attributes
let mut i = 0;
while i < attrs_mut.len() {
@ -1000,22 +975,15 @@ pub fn walk_and_embed_assets(
.iter_mut()
.filter(|a| a.name.local.as_ref().eq_ignore_ascii_case("style"))
{
let replacement = embed_css(
cache,
client,
&url,
attribute.value.as_ref(),
opt_no_fonts,
opt_no_images,
opt_silent,
);
let replacement =
embed_css(cache, client, &url, attribute.value.as_ref(), options);
// let replacement = str!();
attribute.value.clear();
attribute.value.push_slice(&replacement);
}
}
if opt_no_js {
if options.no_js {
// Get rid of JS event attributes
let mut js_attr_indexes = Vec::new();
for (i, attr) in attrs_mut.iter_mut().enumerate() {
@ -1031,22 +999,11 @@ pub fn walk_and_embed_assets(
// Dig deeper
for child in node.children.borrow().iter() {
walk_and_embed_assets(
cache,
client,
&url,
child,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
opt_silent,
);
walk_and_embed_assets(cache, client, &url, child, options);
}
}
_ => {
// Note: in case of opt_no_js being set to true, there's no need to worry about
// Note: in case of options.no_js being set to true, there's no need to worry about
// getting rid of comments that may contain scripts, e.g. <!--[if IE]><script>...
// since that's not part of W3C standard and therefore gets ignored
// by browsers other than IE [5, 9]
@ -1073,15 +1030,7 @@ fn get_child_node_by_name(handle: &Handle, node_name: &str) -> Handle {
}
}
pub fn stringify_document(
handle: &Handle,
opt_no_css: bool,
opt_no_fonts: bool,
opt_no_frames: bool,
opt_no_js: bool,
opt_no_images: bool,
opt_isolate: bool,
) -> String {
pub fn stringify_document(handle: &Handle, options: &Options) -> String {
let mut buf: Vec<u8> = Vec::new();
serialize(&mut buf, handle, SerializeOpts::default())
.expect("unable to serialize DOM into buffer");
@ -1089,20 +1038,19 @@ pub fn stringify_document(
let mut result = String::from_utf8(buf).unwrap();
// Take care of CSP
if opt_isolate || opt_no_css || opt_no_fonts || opt_no_frames || opt_no_js || opt_no_images {
if options.isolate
|| options.no_css
|| options.no_fonts
|| options.no_frames
|| options.no_js
|| options.no_images
{
let mut buf: Vec<u8> = Vec::new();
let mut dom = html_to_dom(&result);
let doc = dom.get_document();
let html = get_child_node_by_name(&doc, "html");
let head = get_child_node_by_name(&html, "head");
let csp_content: String = csp(
opt_isolate,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
);
let csp_content: String = csp(options);
let meta = dom.create_element(
QualName::new(None, ns!(), local_name!("meta")),
@ -1136,38 +1084,31 @@ pub fn stringify_document(
result
}
pub fn csp(
opt_isolate: bool,
opt_no_css: bool,
opt_no_fonts: bool,
opt_no_frames: bool,
opt_no_js: bool,
opt_no_images: bool,
) -> String {
pub fn csp(options: &Options) -> String {
let mut string_list = vec![];
if opt_isolate {
if options.isolate {
string_list.push("default-src 'unsafe-inline' data:;");
}
if opt_no_css {
if options.no_css {
string_list.push("style-src 'none';");
}
if opt_no_fonts {
if options.no_fonts {
string_list.push("font-src 'none';");
}
if opt_no_frames {
if options.no_frames {
string_list.push("frame-src 'none';");
string_list.push("child-src 'none';");
}
if opt_no_js {
if options.no_js {
string_list.push("script-src 'none';");
}
if opt_no_images {
if options.no_images {
// Note: data: is needed for transparent pixels
string_list.push("img-src data:;");
}

View file

@ -1,9 +1,13 @@
#[macro_use]
extern crate clap;
#[macro_use]
mod macros;
pub mod css;
pub mod html;
pub mod js;
pub mod opts;
pub mod url;
pub mod utils;

View file

@ -9,16 +9,12 @@ use std::process;
use std::time::Duration;
use monolith::html::{html_to_dom, metadata_tag, stringify_document, walk_and_embed_assets};
use monolith::opts::Options;
use monolith::url::{data_url_to_data, is_data_url, is_file_url, is_http_url};
use monolith::utils::retrieve_asset;
mod args;
mod macros;
#[macro_use]
extern crate clap;
use crate::args::AppArgs;
enum Output {
Stdout(io::Stdout),
File(fs::File),
@ -48,8 +44,8 @@ impl Output {
}
fn main() {
let app_args = AppArgs::get();
let original_target: &str = &app_args.target;
let options = Options::from_args();
let original_target: &str = &options.target;
let target_url: &str;
let base_url;
let dom;
@ -89,30 +85,30 @@ fn main() {
}
// Define output
let mut output = Output::new(&app_args.output).expect("Could not prepare output");
let mut output = Output::new(&options.output).expect("Could not prepare output");
// Initialize client
let mut cache = HashMap::new();
let mut header_map = HeaderMap::new();
header_map.insert(
USER_AGENT,
HeaderValue::from_str(&app_args.user_agent).expect("Invalid User-Agent header specified"),
HeaderValue::from_str(&options.user_agent).expect("Invalid User-Agent header specified"),
);
let timeout: u64 = if app_args.timeout > 0 {
app_args.timeout
let timeout: u64 = if options.timeout > 0 {
options.timeout
} else {
std::u64::MAX / 4
};
let client = Client::builder()
.timeout(Duration::from_secs(timeout))
.danger_accept_invalid_certs(app_args.insecure)
.danger_accept_invalid_certs(options.insecure)
.default_headers(header_map)
.build()
.expect("Failed to initialize HTTP client");
// Retrieve target document
if is_file_url(target_url) || is_http_url(target_url) {
match retrieve_asset(&mut cache, &client, target_url, target_url, app_args.silent) {
match retrieve_asset(&mut cache, &client, target_url, target_url, options.silent) {
Ok((data, final_url, _media_type)) => {
base_url = final_url;
dom = html_to_dom(&String::from_utf8_lossy(&data));
@ -135,32 +131,13 @@ fn main() {
}
// Embed remote assets
walk_and_embed_assets(
&mut cache,
&client,
&base_url,
&dom.document,
app_args.no_css,
app_args.no_fonts,
app_args.no_frames,
app_args.no_js,
app_args.no_images,
app_args.silent,
);
walk_and_embed_assets(&mut cache, &client, &base_url, &dom.document, &options);
// Serialize DOM tree
let mut result: String = stringify_document(
&dom.document,
app_args.no_css,
app_args.no_fonts,
app_args.no_frames,
app_args.no_js,
app_args.no_images,
app_args.isolate,
);
let mut result: String = stringify_document(&dom.document, &options);
// Add metadata tag
if !app_args.no_metadata {
if !options.no_metadata {
let metadata_comment = metadata_tag(&base_url);
result.insert_str(0, &metadata_comment);
if metadata_comment.len() > 0 {

View file

@ -1,7 +1,7 @@
use clap::{App, Arg};
#[derive(Default)]
pub struct AppArgs {
pub struct Options {
pub target: String,
pub no_css: bool,
pub no_fonts: bool,
@ -21,8 +21,8 @@ const DEFAULT_NETWORK_TIMEOUT: u64 = 120;
const DEFAULT_USER_AGENT: &str =
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:73.0) Gecko/20100101 Firefox/73.0";
impl AppArgs {
pub fn get() -> AppArgs {
impl Options {
pub fn from_args() -> Options {
let app = App::new(env!("CARGO_PKG_NAME"))
.version(crate_version!())
.author(crate_authors!("\n"))
@ -34,7 +34,7 @@ impl AppArgs {
.index(1)
.help("URL or file path"),
)
// .args_from_usage("-a, --include-audio 'Removes audio sources'")
// .args_from_usage("-a, --no-audio 'Removes audio sources'")
.args_from_usage("-c, --no-css 'Removes CSS'")
.args_from_usage("-f, --no-frames 'Removes frames and iframes'")
.args_from_usage("-F, --no-fonts 'Removes fonts'")
@ -47,33 +47,35 @@ impl AppArgs {
.args_from_usage("-s, --silent 'Suppresses verbosity'")
.args_from_usage("-t, --timeout=[60] 'Adjusts network request timeout'")
.args_from_usage("-u, --user-agent=[Firefox] 'Sets custom User-Agent string'")
// .args_from_usage("-v, --include-video 'Removes video sources'")
// .args_from_usage("-v, --no-video 'Removes video sources'")
.get_matches();
let mut app_args = AppArgs::default();
let mut options: Options = Options::default();
// Process the command
app_args.target = app
options.target = app
.value_of("target")
.expect("please set target")
.to_string();
app_args.no_css = app.is_present("no-css");
app_args.no_fonts = app.is_present("no-fonts");
app_args.no_frames = app.is_present("no-frames");
app_args.no_images = app.is_present("no-images");
app_args.no_js = app.is_present("no-js");
app_args.insecure = app.is_present("insecure");
app_args.no_metadata = app.is_present("no-metadata");
app_args.isolate = app.is_present("isolate");
app_args.silent = app.is_present("silent");
app_args.timeout = app
options.no_css = app.is_present("no-css");
options.no_frames = app.is_present("no-frames");
options.no_fonts = app.is_present("no-fonts");
options.no_images = app.is_present("no-images");
options.isolate = app.is_present("isolate");
options.no_js = app.is_present("no-js");
options.insecure = app.is_present("insecure");
options.no_metadata = app.is_present("no-metadata");
options.output = app.value_of("output").unwrap_or("").to_string();
options.silent = app.is_present("silent");
options.timeout = app
.value_of("timeout")
.unwrap_or(&DEFAULT_NETWORK_TIMEOUT.to_string())
.parse::<u64>()
.unwrap();
app_args.output = app.value_of("output").unwrap_or("").to_string();
app_args.user_agent = app
options.user_agent = app
.value_of("user-agent")
.unwrap_or(DEFAULT_USER_AGENT)
.to_string();
app_args
options
}
}

View file

@ -7,25 +7,26 @@
#[cfg(test)]
mod passing {
use crate::css;
use reqwest::blocking::Client;
use std::collections::HashMap;
use crate::css;
use crate::opts::Options;
#[test]
fn empty_input() {
let cache = &mut HashMap::new();
let client = Client::new();
let options = Options::default();
assert_eq!(
css::embed_css(cache, &client, "", "", false, false, false,),
""
);
assert_eq!(css::embed_css(cache, &client, "", "", &options), "");
}
#[test]
fn trim_if_empty() {
let cache = &mut HashMap::new();
let client = Client::new();
let options = Options::default();
assert_eq!(
css::embed_css(
@ -33,9 +34,7 @@ mod passing {
&client,
"https://doesntmatter.local/",
"\t \t ",
false,
false,
false,
&options,
),
""
);
@ -45,6 +44,9 @@ mod passing {
fn style_exclude_unquoted_images() {
let cache = &mut HashMap::new();
let client = Client::new();
let mut options = Options::default();
options.no_images = true;
options.silent = true;
const STYLE: &str = "/* border: none;*/\
background-image: url(https://somewhere.com/bg.png); \
@ -60,9 +62,7 @@ mod passing {
&client,
"https://doesntmatter.local/",
&STYLE,
false,
true,
true,
&options,
),
format!(
"/* border: none;*/\
@ -81,6 +81,9 @@ mod passing {
fn style_exclude_single_quoted_images() {
let cache = &mut HashMap::new();
let client = Client::new();
let mut options = Options::default();
options.no_images = true;
options.silent = true;
const STYLE: &str = "/* border: none;*/\
background-image: url('https://somewhere.com/bg.png'); \
@ -91,7 +94,7 @@ mod passing {
height: calc(100vh - 10pt)";
assert_eq!(
css::embed_css(cache, &client, "", &STYLE, false, true, true,),
css::embed_css(cache, &client, "", &STYLE, &options),
format!(
"/* border: none;*/\
background-image: url('{empty_image}'); \
@ -109,6 +112,8 @@ mod passing {
fn style_block() {
let cache = &mut HashMap::new();
let client = Client::new();
let mut options = Options::default();
options.silent = true;
const CSS: &str = "\
#id.class-name:not(:nth-child(3n+0)) {\n \
@ -119,7 +124,7 @@ mod passing {
html > body {}";
assert_eq!(
css::embed_css(cache, &client, "file:///", &CSS, false, false, true,),
css::embed_css(cache, &client, "file:///", &CSS, &options),
CSS
);
}
@ -128,6 +133,8 @@ mod passing {
fn attribute_selectors() {
let cache = &mut HashMap::new();
let client = Client::new();
let mut options = Options::default();
options.silent = true;
const CSS: &str = "\
[data-value] {
@ -159,16 +166,15 @@ mod passing {
}
";
assert_eq!(
css::embed_css(cache, &client, "", &CSS, false, false, false,),
CSS
);
assert_eq!(css::embed_css(cache, &client, "", &CSS, &options), CSS);
}
#[test]
fn import_string() {
let cache = &mut HashMap::new();
let client = Client::new();
let mut options = Options::default();
options.silent = true;
const CSS: &str = "\
@charset 'UTF-8';\n\
@ -184,9 +190,7 @@ mod passing {
&client,
"https://doesntmatter.local/",
&CSS,
false,
false,
true,
&options,
),
"\
@charset 'UTF-8';\n\
@ -202,6 +206,8 @@ mod passing {
fn hash_urls() {
let cache = &mut HashMap::new();
let client = Client::new();
let mut options = Options::default();
options.silent = true;
const CSS: &str = "\
body {\n \
@ -219,9 +225,7 @@ mod passing {
&client,
"https://doesntmatter.local/",
&CSS,
false,
false,
true,
&options,
),
CSS
);
@ -231,6 +235,8 @@ mod passing {
fn transform_percentages_and_degrees() {
let cache = &mut HashMap::new();
let client = Client::new();
let mut options = Options::default();
options.silent = true;
const CSS: &str = "\
div {\n \
@ -246,9 +252,7 @@ mod passing {
&client,
"https://doesntmatter.local/",
&CSS,
false,
false,
true,
&options,
),
CSS
);
@ -258,6 +262,8 @@ mod passing {
fn unusual_indents() {
let cache = &mut HashMap::new();
let client = Client::new();
let mut options = Options::default();
options.silent = true;
const CSS: &str = "\
.is\\:good:hover {\n \
@ -275,9 +281,7 @@ mod passing {
&client,
"https://doesntmatter.local/",
&CSS,
false,
false,
true,
&options,
),
CSS
);
@ -287,6 +291,9 @@ mod passing {
fn exclude_fonts() {
let cache = &mut HashMap::new();
let client = Client::new();
let mut options = Options::default();
options.no_fonts = true;
options.silent = true;
const CSS: &str = "\
@font-face {\n \
@ -328,9 +335,7 @@ mod passing {
&client,
"https://doesntmatter.local/",
&CSS,
true,
false,
true,
&options,
),
CSS_OUT
);

View file

@ -8,143 +8,72 @@
#[cfg(test)]
mod passing {
use crate::html;
use crate::opts::Options;
#[test]
fn isolated() {
let opt_isolate: bool = true;
let opt_no_css: bool = false;
let opt_no_fonts: bool = false;
let opt_no_frames: bool = false;
let opt_no_js: bool = false;
let opt_no_images: bool = false;
let csp_content = html::csp(
opt_isolate,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
);
let mut options = Options::default();
options.isolate = true;
let csp_content = html::csp(&options);
assert_eq!(csp_content, "default-src 'unsafe-inline' data:;");
}
#[test]
fn no_css() {
let opt_isolate: bool = false;
let opt_no_css: bool = true;
let opt_no_fonts: bool = false;
let opt_no_frames: bool = false;
let opt_no_js: bool = false;
let opt_no_images: bool = false;
let csp_content = html::csp(
opt_isolate,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
);
let mut options = Options::default();
options.no_css = true;
let csp_content = html::csp(&options);
assert_eq!(csp_content, "style-src 'none';");
}
#[test]
fn no_fonts() {
let opt_isolate: bool = false;
let opt_no_css: bool = false;
let opt_no_fonts: bool = true;
let opt_no_frames: bool = false;
let opt_no_js: bool = false;
let opt_no_images: bool = false;
let csp_content = html::csp(
opt_isolate,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
);
let mut options = Options::default();
options.no_fonts = true;
let csp_content = html::csp(&options);
assert_eq!(csp_content, "font-src 'none';");
}
#[test]
fn no_frames() {
let opt_isolate: bool = false;
let opt_no_css: bool = false;
let opt_no_fonts: bool = false;
let opt_no_frames: bool = true;
let opt_no_js: bool = false;
let opt_no_images: bool = false;
let csp_content = html::csp(
opt_isolate,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
);
let mut options = Options::default();
options.no_frames = true;
let csp_content = html::csp(&options);
assert_eq!(csp_content, "frame-src 'none'; child-src 'none';");
}
#[test]
fn no_js() {
let opt_isolate: bool = false;
let opt_no_css: bool = false;
let opt_no_fonts: bool = false;
let opt_no_frames: bool = false;
let opt_no_js: bool = true;
let opt_no_images: bool = false;
let csp_content = html::csp(
opt_isolate,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
);
let mut options = Options::default();
options.no_js = true;
let csp_content = html::csp(&options);
assert_eq!(csp_content, "script-src 'none';");
}
#[test]
fn no_image() {
let opt_isolate: bool = false;
let opt_no_css: bool = false;
let opt_no_fonts: bool = false;
let opt_no_frames: bool = false;
let opt_no_js: bool = false;
let opt_no_images: bool = true;
let csp_content = html::csp(
opt_isolate,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
);
fn no_images() {
let mut options = Options::default();
options.no_images = true;
let csp_content = html::csp(&options);
assert_eq!(csp_content, "img-src data:;");
}
#[test]
fn all() {
let opt_isolate: bool = true;
let opt_no_css: bool = true;
let opt_no_fonts: bool = true;
let opt_no_frames: bool = true;
let opt_no_js: bool = true;
let opt_no_images: bool = true;
let csp_content = html::csp(
opt_isolate,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
);
let mut options = Options::default();
options.isolate = true;
options.no_css = true;
options.no_fonts = true;
options.no_frames = true;
options.no_js = true;
options.no_images = true;
let csp_content = html::csp(&options);
assert_eq!(csp_content, "default-src 'unsafe-inline' data:; style-src 'none'; font-src 'none'; frame-src 'none'; child-src 'none'; script-src 'none'; img-src data:;");
}

View file

@ -7,16 +7,21 @@
#[cfg(test)]
mod passing {
use crate::html;
use reqwest::blocking::Client;
use std::collections::HashMap;
use crate::html;
use crate::opts::Options;
#[test]
fn replace_with_empty_images() {
let cache = &mut HashMap::new();
let client = Client::new();
let srcset_value = "small.png 1x, large.png 2x";
let embedded_css = html::embed_srcset(cache, &client, "", &srcset_value, true, true);
let mut options = Options::default();
options.no_images = true;
options.silent = true;
let embedded_css = html::embed_srcset(cache, &client, "", &srcset_value, &options);
assert_eq!(
format!("{} 1x, {} 2x", empty_image!(), empty_image!()),

View file

@ -7,9 +7,10 @@
#[cfg(test)]
mod passing {
use crate::html;
use html5ever::rcdom::{Handle, NodeData};
use crate::html;
#[test]
fn get_node_name() {
let html = "<!doctype html><html><HEAD></HEAD><body><div><P></P></div></body></html>";

View file

@ -8,29 +8,16 @@
#[cfg(test)]
mod passing {
use crate::html;
use crate::opts::Options;
#[test]
fn div_as_root_element() {
let html = "<div><script src=\"some.js\"></script></div>";
let dom = html::html_to_dom(&html);
let opt_no_css: bool = false;
let opt_no_fonts: bool = false;
let opt_no_frames: bool = false;
let opt_no_js: bool = false;
let opt_no_images: bool = false;
let opt_isolate: bool = false;
let options = Options::default();
assert_eq!(
html::stringify_document(
&dom.document,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
opt_isolate,
),
html::stringify_document(&dom.document, &options),
"<html><head></head><body><div><script src=\"some.js\"></script></div></body></html>"
);
}
@ -42,23 +29,13 @@ mod passing {
<meta http-equiv=\"Content-Security-Policy\" content=\"default-src https:\">\
<div><script src=\"some.js\"></script></div>";
let dom = html::html_to_dom(&html);
let opt_no_css: bool = false;
let opt_no_fonts: bool = false;
let opt_no_frames: bool = false;
let opt_no_js: bool = false;
let opt_no_images: bool = false;
let opt_isolate: bool = true;
let mut options = Options::default();
options.isolate = true;
assert_eq!(
html::stringify_document(
&dom.document,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
opt_isolate,
&options
),
"<html>\
<head>\
@ -83,24 +60,11 @@ mod passing {
<link rel=\"stylesheet\" href=\"main.css\"/>\
<div style=\"display: none;\"></div>";
let dom = html::html_to_dom(&html);
let opt_no_css: bool = true;
let opt_no_fonts: bool = false;
let opt_no_frames: bool = false;
let opt_no_js: bool = false;
let opt_no_images: bool = false;
let opt_isolate: bool = false;
let mut options = Options::default();
options.no_css = true;
assert_eq!(
html::stringify_document(
&dom.document,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
opt_isolate,
),
html::stringify_document(&dom.document, &options),
"<!DOCTYPE html>\
<html>\
<head>\
@ -120,23 +84,13 @@ mod passing {
<link rel=\"something\"/>\
<div><script src=\"some.js\"></script></div>";
let dom = html::html_to_dom(&html);
let opt_no_css: bool = false;
let opt_no_fonts: bool = false;
let opt_no_frames: bool = true;
let opt_no_js: bool = false;
let opt_no_images: bool = false;
let opt_isolate: bool = false;
let mut options = Options::default();
options.no_frames = true;
assert_eq!(
html::stringify_document(
&dom.document,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
opt_isolate,
&options
),
"<!DOCTYPE html>\
<html>\
@ -162,23 +116,18 @@ mod passing {
<iframe src=\"some.html\"></iframe>\
</div>";
let dom = html::html_to_dom(&html);
let opt_isolate: bool = true;
let opt_no_css: bool = true;
let opt_no_fonts: bool = true;
let opt_no_frames: bool = true;
let opt_no_js: bool = true;
let opt_no_images: bool = true;
let mut options = Options::default();
options.isolate = true;
options.no_css = true;
options.no_fonts = true;
options.no_frames = true;
options.no_js = true;
options.no_images = true;
assert_eq!(
html::stringify_document(
&dom.document,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
opt_isolate,
&options
),
"<!DOCTYPE html>\
<html>\

View file

@ -7,11 +7,13 @@
#[cfg(test)]
mod passing {
use crate::html;
use html5ever::serialize::{serialize, SerializeOpts};
use reqwest::blocking::Client;
use std::collections::HashMap;
use crate::html;
use crate::opts::Options;
#[test]
fn basic() {
let cache = &mut HashMap::new();
@ -20,27 +22,12 @@ mod passing {
let dom = html::html_to_dom(&html);
let url = "http://localhost";
let opt_no_css: bool = false;
let opt_no_fonts: bool = false;
let opt_no_frames: bool = false;
let opt_no_js: bool = false;
let opt_no_images: bool = false;
let opt_silent = true;
let mut options = Options::default();
options.silent = true;
let client = Client::new();
html::walk_and_embed_assets(
cache,
&client,
&url,
&dom.document,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
opt_silent,
);
html::walk_and_embed_assets(cache, &client, &url, &dom.document, &options);
let mut buf: Vec<u8> = Vec::new();
serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap();
@ -58,27 +45,12 @@ mod passing {
let url = "http://localhost";
let cache = &mut HashMap::new();
let opt_no_css: bool = false;
let opt_no_fonts: bool = false;
let opt_no_frames: bool = false;
let opt_no_js: bool = false;
let opt_no_images: bool = false;
let opt_silent = true;
let mut options = Options::default();
options.silent = true;
let client = Client::new();
html::walk_and_embed_assets(
cache,
&client,
&url,
&dom.document,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
opt_silent,
);
html::walk_and_embed_assets(cache, &client, &url, &dom.document, &options);
let mut buf: Vec<u8> = Vec::new();
serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap();
@ -96,27 +68,12 @@ mod passing {
let url = "http://localhost";
let cache = &mut HashMap::new();
let opt_no_css: bool = false;
let opt_no_fonts: bool = false;
let opt_no_frames: bool = false;
let opt_no_js: bool = false;
let opt_no_images: bool = false;
let opt_silent = true;
let mut options = Options::default();
options.silent = true;
let client = Client::new();
html::walk_and_embed_assets(
cache,
&client,
&url,
&dom.document,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
opt_silent,
);
html::walk_and_embed_assets(cache, &client, &url, &dom.document, &options);
let mut buf: Vec<u8> = Vec::new();
serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap();
@ -136,26 +93,13 @@ mod passing {
let url = "http://localhost";
let cache = &mut HashMap::new();
let opt_no_css: bool = true;
let opt_no_fonts: bool = false;
let opt_no_frames: bool = false;
let opt_no_js: bool = false;
let opt_no_images: bool = false;
let opt_silent = true;
let mut options = Options::default();
options.no_css = true;
options.silent = true;
let client = Client::new();
html::walk_and_embed_assets(
cache,
&client,
&url,
&dom.document,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
opt_silent,
);
html::walk_and_embed_assets(cache, &client, &url, &dom.document, &options);
let mut buf: Vec<u8> = Vec::new();
serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap();
@ -182,27 +126,13 @@ mod passing {
let url = "http://localhost";
let cache = &mut HashMap::new();
let opt_no_css: bool = false;
let opt_no_fonts: bool = false;
let opt_no_frames: bool = false;
let opt_no_js: bool = false;
let opt_no_images: bool = true;
let opt_silent = true;
let mut options = Options::default();
options.no_images = true;
options.silent = true;
let client = Client::new();
html::walk_and_embed_assets(
cache,
&client,
&url,
&dom.document,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
opt_silent,
);
html::walk_and_embed_assets(cache, &client, &url, &dom.document, &options);
let mut buf: Vec<u8> = Vec::new();
serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap();
@ -233,27 +163,13 @@ mod passing {
let url = "http://localhost";
let cache = &mut HashMap::new();
let opt_no_css: bool = false;
let opt_no_fonts: bool = false;
let opt_no_frames: bool = false;
let opt_no_js: bool = false;
let opt_no_images: bool = true;
let opt_silent = true;
let mut options = Options::default();
options.no_images = true;
options.silent = true;
let client = Client::new();
html::walk_and_embed_assets(
cache,
&client,
&url,
&dom.document,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
opt_silent,
);
html::walk_and_embed_assets(cache, &client, &url, &dom.document, &options);
let mut buf: Vec<u8> = Vec::new();
serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap();
@ -271,26 +187,13 @@ mod passing {
let url = "http://localhost";
let cache = &mut HashMap::new();
let opt_no_css: bool = false;
let opt_no_fonts: bool = false;
let opt_no_frames: bool = true;
let opt_no_js: bool = false;
let opt_no_images: bool = false;
let opt_silent = true;
let mut options = Options::default();
options.no_frames = true;
options.silent = true;
let client = Client::new();
html::walk_and_embed_assets(
cache,
&client,
&url,
&dom.document,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
opt_silent,
);
html::walk_and_embed_assets(cache, &client, &url, &dom.document, &options);
let mut buf: Vec<u8> = Vec::new();
serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap();
@ -308,26 +211,13 @@ mod passing {
let url = "http://localhost";
let cache = &mut HashMap::new();
let opt_no_css: bool = false;
let opt_no_fonts: bool = false;
let opt_no_frames: bool = true;
let opt_no_js: bool = false;
let opt_no_images: bool = false;
let opt_silent = true;
let mut options = Options::default();
options.no_frames = true;
options.silent = true;
let client = Client::new();
html::walk_and_embed_assets(
cache,
&client,
&url,
&dom.document,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
opt_silent,
);
html::walk_and_embed_assets(cache, &client, &url, &dom.document, &options);
let mut buf: Vec<u8> = Vec::new();
serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap();
@ -348,27 +238,13 @@ mod passing {
let url = "http://localhost";
let cache = &mut HashMap::new();
let opt_no_css: bool = false;
let opt_no_fonts: bool = false;
let opt_no_frames: bool = false;
let opt_no_js: bool = true;
let opt_no_images: bool = false;
let opt_silent = true;
let mut options = Options::default();
options.no_js = true;
options.silent = true;
let client = Client::new();
html::walk_and_embed_assets(
cache,
&client,
&url,
&dom.document,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
opt_silent,
);
html::walk_and_embed_assets(cache, &client, &url, &dom.document, &options);
let mut buf: Vec<u8> = Vec::new();
serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap();
@ -388,26 +264,17 @@ mod passing {
let dom = html::html_to_dom(&html);
let url = "http://localhost";
let cache = &mut HashMap::new();
let client = Client::new();
let opt_no_css: bool = true;
let opt_no_fonts: bool = false;
let opt_no_frames: bool = true;
let opt_no_js: bool = true;
let opt_no_images: bool = true;
let opt_silent = true;
html::walk_and_embed_assets(
cache,
&client,
&url,
&dom.document,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
opt_silent,
);
let mut options = Options::default();
options.no_css = true;
options.no_frames = true;
options.no_js = true;
options.no_images = true;
options.silent = true;
let client = Client::new();
html::walk_and_embed_assets(cache, &client, &url, &dom.document, &options);
let mut buf: Vec<u8> = Vec::new();
serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap();
@ -433,26 +300,17 @@ mod passing {
let dom = html::html_to_dom(&html);
let url = "http://localhost";
let cache = &mut HashMap::new();
let client = Client::new();
let opt_no_css: bool = true;
let opt_no_fonts: bool = false;
let opt_no_frames: bool = true;
let opt_no_js: bool = true;
let opt_no_images: bool = true;
let opt_silent = true;
html::walk_and_embed_assets(
cache,
&client,
&url,
&dom.document,
opt_no_css,
opt_no_fonts,
opt_no_frames,
opt_no_js,
opt_no_images,
opt_silent,
);
let mut options = Options::default();
options.no_css = true;
options.no_frames = true;
options.no_js = true;
options.no_images = true;
options.silent = true;
let client = Client::new();
html::walk_and_embed_assets(cache, &client, &url, &dom.document, &options);
let mut buf: Vec<u8> = Vec::new();
serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap();

View file

@ -3,4 +3,5 @@ mod css;
mod html;
mod js;
mod macros;
mod opts;
mod utils;

30
src/tests/opts.rs Normal file
View file

@ -0,0 +1,30 @@
// ██████╗ █████╗ ███████╗███████╗██╗███╗ ██╗ ██████╗
// ██╔══██╗██╔══██╗██╔════╝██╔════╝██║████╗ ██║██╔════╝
// ██████╔╝███████║███████╗███████╗██║██╔██╗ ██║██║ ███╗
// ██╔═══╝ ██╔══██║╚════██║╚════██║██║██║╚██╗██║██║ ██║
// ██║ ██║ ██║███████║███████║██║██║ ╚████║╚██████╔╝
// ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚═╝╚═╝ ╚═══╝ ╚═════╝
#[cfg(test)]
mod passing {
use crate::opts::Options;
#[test]
fn defaults() {
let options: Options = Options::default();
assert_eq!(options.target, str!());
assert_eq!(options.no_css, false);
assert_eq!(options.no_frames, false);
assert_eq!(options.no_fonts, false);
assert_eq!(options.no_images, false);
assert_eq!(options.isolate, false);
assert_eq!(options.no_js, false);
assert_eq!(options.insecure, false);
assert_eq!(options.no_metadata, false);
assert_eq!(options.output, str!());
assert_eq!(options.silent, false);
assert_eq!(options.timeout, 0);
assert_eq!(options.user_agent, "");
}
}

View file

@ -7,9 +7,10 @@
#[cfg(test)]
mod passing {
use crate::url;
use url::ParseError;
use crate::url;
#[test]
fn from_https_to_level_up_relative() -> Result<(), ParseError> {
let resolved_url =

View file

@ -86,10 +86,11 @@ mod passing {
#[cfg(test)]
mod failing {
use crate::utils;
use reqwest::blocking::Client;
use std::collections::HashMap;
use crate::utils;
#[test]
fn read_local_file_with_data_url_parent() {
let cache = &mut HashMap::new();