diff --git a/Cargo.lock b/Cargo.lock index e881ef9..bfe3eac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,15 +71,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "autocfg" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" -dependencies = [ - "autocfg 1.1.0", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -203,15 +194,6 @@ dependencies = [ "os_str_bytes", ] -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -dependencies = [ - "bitflags", -] - [[package]] name = "codespan-reporting" version = "0.11.1" @@ -268,29 +250,25 @@ dependencies = [ [[package]] name = "cssparser" -version = "0.29.6" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93d03419cb5950ccfd3daf3ff1c7a36ace64609a1a8746d493df1ca0afde0fa" +checksum = "5b3df4f93e5fbbe73ec01ec8d3f68bba73107993a5b1e7519273c32db9b0d5be" dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "matches", - "phf 0.10.1", - "proc-macro2", - "quote", + "phf", "smallvec", - "syn", ] [[package]] name = "cssparser-macros" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn", + "syn 2.0.18", ] [[package]] @@ -317,7 +295,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn", + "syn 1.0.103", ] [[package]] @@ -334,7 +312,7 @@ checksum = "b846f081361125bfc8dc9d3940c84e1fd83ba54bbca7b17cd29483c828be0704" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -382,9 +360,9 @@ checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "encoding_rs" -version = "0.8.31" +version = "0.8.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" dependencies = [ "cfg-if", ] @@ -431,19 +409,13 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - [[package]] name = "futf" version = "0.1.5" @@ -559,16 +531,16 @@ dependencies = [ [[package]] name = "html5ever" -version = "0.24.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "025483b0a1e4577bb28578318c886ee5f817dda6eb62473269349044406644cb" +checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" dependencies = [ "log", "mac", "markup5ever", "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -668,9 +640,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -682,7 +654,7 @@ version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ - "autocfg 1.1.0", + "autocfg", "hashbrown", ] @@ -746,6 +718,16 @@ dependencies = [ "cc", ] +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.17" @@ -763,26 +745,29 @@ checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" [[package]] name = "markup5ever" -version = "0.9.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65381d9d47506b8592b97c4efd936afcf673b09b059f2bef39c7211ee78b9d03" +checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" dependencies = [ "log", - "phf 0.7.24", + "phf", "phf_codegen", - "serde", - "serde_derive", - "serde_json", "string_cache", "string_cache_codegen", "tendril", ] [[package]] -name = "matches" -version = "0.1.9" +name = "markup5ever_rcdom" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +checksum = "b9521dd6750f8e80ee6c53d65e2e4656d7de37064f3a7a5d2d11d05df93839c2" +dependencies = [ + "html5ever", + "markup5ever", + "tendril", + "xml5ever", +] [[package]] name = "memchr" @@ -829,6 +814,8 @@ dependencies = [ "cssparser", "encoding_rs", "html5ever", + "markup5ever_rcdom", + "once_cell", "percent-encoding", "regex", "reqwest", @@ -866,7 +853,7 @@ version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ - "autocfg 1.1.0", + "autocfg", "num-traits", ] @@ -876,7 +863,7 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ - "autocfg 1.1.0", + "autocfg", ] [[package]] @@ -918,7 +905,7 @@ checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -933,7 +920,7 @@ version = "0.9.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b03b84c3b2d099b81f0953422b4d4ad58761589d0229b5506356afca05a3670a" dependencies = [ - "autocfg 1.1.0", + "autocfg", "cc", "libc", "pkg-config", @@ -947,20 +934,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3baf96e39c5359d2eb0dd6ccb42c62b91d9678aa68160d261b9e0ccbf9e9dea9" [[package]] -name = "percent-encoding" -version = "2.2.0" +name = "parking_lot" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] [[package]] -name = "phf" -version = "0.7.24" +name = "parking_lot_core" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ - "phf_shared 0.7.24", + "cfg-if", + "libc", + "redox_syscall 0.3.5", + "smallvec", + "windows-targets", ] +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + [[package]] name = "phf" version = "0.10.1" @@ -968,28 +969,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" dependencies = [ "phf_macros", - "phf_shared 0.10.0", + "phf_shared", "proc-macro-hack", ] [[package]] name = "phf_codegen" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" -dependencies = [ - "phf_generator 0.7.24", - "phf_shared 0.7.24", -] - -[[package]] -name = "phf_generator" -version = "0.7.24" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" dependencies = [ - "phf_shared 0.7.24", - "rand 0.6.5", + "phf_generator", + "phf_shared", ] [[package]] @@ -998,8 +989,8 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" dependencies = [ - "phf_shared 0.10.0", - "rand 0.8.5", + "phf_shared", + "rand", ] [[package]] @@ -1008,21 +999,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", + "phf_generator", + "phf_shared", "proc-macro-hack", "proc-macro2", "quote", - "syn", -] - -[[package]] -name = "phf_shared" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" -dependencies = [ - "siphasher 0.2.3", + "syn 1.0.103", ] [[package]] @@ -1031,7 +1013,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" dependencies = [ - "siphasher 0.3.10", + "siphasher", ] [[package]] @@ -1099,41 +1081,22 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.21" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -dependencies = [ - "autocfg 0.1.8", - "libc", - "rand_chacha 0.1.1", - "rand_core 0.4.2", - "rand_hc", - "rand_isaac", - "rand_jitter", - "rand_os", - "rand_pcg", - "rand_xorshift", - "winapi", -] - [[package]] name = "rand" version = "0.8.5" @@ -1141,18 +1104,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -dependencies = [ - "autocfg 0.1.8", - "rand_core 0.3.1", + "rand_chacha", + "rand_core", ] [[package]] @@ -1162,24 +1115,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", + "rand_core", ] -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - [[package]] name = "rand_core" version = "0.6.4" @@ -1190,90 +1128,28 @@ dependencies = [ ] [[package]] -name = "rand_hc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -dependencies = [ - "libc", - "rand_core 0.4.2", - "winapi", -] - -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -dependencies = [ - "cloudabi", - "fuchsia-cprng", - "libc", - "rand_core 0.4.2", - "rdrand", - "winapi", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -dependencies = [ - "autocfg 0.1.8", - "rand_core 0.4.2", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rdrand" -version = "0.4.0" +name = "redox_syscall" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "rand_core 0.3.1", + "bitflags", ] [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.7.0" +version = "1.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" dependencies = [ "regex-syntax", ] @@ -1286,9 +1162,9 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" [[package]] name = "regex-syntax" -version = "0.6.28" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" [[package]] name = "remove_dir_all" @@ -1354,6 +1230,12 @@ dependencies = [ "windows-sys 0.36.1", ] +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "scratch" version = "1.0.2" @@ -1389,17 +1271,6 @@ version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" -[[package]] -name = "serde_derive" -version = "1.0.147" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "serde_json" version = "1.0.87" @@ -1434,12 +1305,6 @@ dependencies = [ "digest", ] -[[package]] -name = "siphasher" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" - [[package]] name = "siphasher" version = "0.3.10" @@ -1452,7 +1317,7 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" dependencies = [ - "autocfg 1.1.0", + "autocfg", ] [[package]] @@ -1473,38 +1338,30 @@ dependencies = [ [[package]] name = "string_cache" -version = "0.7.5" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89c058a82f9fd69b1becf8c274f412281038877c553182f1d02eb027045a2d67" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" dependencies = [ - "lazy_static", "new_debug_unreachable", - "phf_shared 0.7.24", + "once_cell", + "parking_lot", + "phf_shared", "precomputed-hash", "serde", - "string_cache_codegen", - "string_cache_shared", ] [[package]] name = "string_cache_codegen" -version = "0.4.4" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f45ed1b65bf9a4bf2f7b7dc59212d1926e9eaf00fa998988e420fd124467c6" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" dependencies = [ - "phf_generator 0.7.24", - "phf_shared 0.7.24", + "phf_generator", + "phf_shared", "proc-macro2", "quote", - "string_cache_shared", ] -[[package]] -name = "string_cache_shared" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" - [[package]] name = "strsim" version = "0.10.0" @@ -1522,6 +1379,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "tempfile" version = "3.3.0" @@ -1531,7 +1399,7 @@ dependencies = [ "cfg-if", "fastrand", "libc", - "redox_syscall", + "redox_syscall 0.2.16", "remove_dir_all", "winapi", ] @@ -1600,7 +1468,7 @@ version = "1.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" dependencies = [ - "autocfg 1.1.0", + "autocfg", "bytes", "libc", "memchr", @@ -1675,9 +1543,9 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "unicode-bidi" -version = "0.3.8" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" @@ -1702,9 +1570,9 @@ checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "url" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" dependencies = [ "form_urlencoded", "idna", @@ -1781,7 +1649,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.103", "wasm-bindgen-shared", ] @@ -1815,7 +1683,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1886,21 +1754,42 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_gnullvm", + "windows_aarch64_gnullvm 0.42.0", "windows_aarch64_msvc 0.42.0", "windows_i686_gnu 0.42.0", "windows_i686_msvc 0.42.0", "windows_x86_64_gnu 0.42.0", - "windows_x86_64_gnullvm", + "windows_x86_64_gnullvm 0.42.0", "windows_x86_64_msvc 0.42.0", ] +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + [[package]] name = "windows_aarch64_msvc" version = "0.36.1" @@ -1913,6 +1802,12 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + [[package]] name = "windows_i686_gnu" version = "0.36.1" @@ -1925,6 +1820,12 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + [[package]] name = "windows_i686_msvc" version = "0.36.1" @@ -1937,6 +1838,12 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + [[package]] name = "windows_x86_64_gnu" version = "0.36.1" @@ -1949,12 +1856,24 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + [[package]] name = "windows_x86_64_msvc" version = "0.36.1" @@ -1967,6 +1886,12 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + [[package]] name = "winreg" version = "0.10.1" @@ -1975,3 +1900,14 @@ checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ "winapi", ] + +[[package]] +name = "xml5ever" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4034e1d05af98b51ad7214527730626f019682d797ba38b51689212118d8e650" +dependencies = [ + "log", + "mac", + "markup5ever", +] diff --git a/Cargo.toml b/Cargo.toml index a32a8bf..5397956 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ authors = [ "Emi Simpson ", "rhysd ", ] -edition = "2018" +edition = "2021" description = "CLI tool for saving web pages as a single HTML file" homepage = "https://github.com/Y2Z/monolith" repository = "https://github.com/Y2Z/monolith" @@ -26,16 +26,18 @@ atty = "0.2.14" # Used for highlighting network errors base64 = "0.13.0" # Used for integrity attributes chrono = "0.4.20" # Used for formatting creation timestamp clap = "3.2.16" -cssparser = "0.29.6" -encoding_rs = "0.8.31" -html5ever = "0.24.1" -percent-encoding = "2.1.0" -sha2 = "0.10.2" # Used for calculating checksums during integrity checks -url = "2.2.2" +cssparser = "0.31.2" +encoding_rs = "0.8.32" +html5ever = "0.26.0" +markup5ever_rcdom = "0.2.0" +once_cell = "*" +percent-encoding = "2.3.0" +sha2 = "0.10.6" # Used for calculating checksums during integrity checks +url = "2.4.0" # Used for parsing srcset and NOSCRIPT [dependencies.regex] -version = "1.6.0" +version = "1.8.4" default-features = false features = ["std", "perf-dfa", "unicode-perl"] diff --git a/src/css.rs b/src/css.rs index 2e16df7..faf1a4f 100644 --- a/src/css.rs +++ b/src/css.rs @@ -1,8 +1,6 @@ use cssparser::{ serialize_identifier, serialize_string, ParseError, Parser, ParserInput, SourcePosition, Token, }; -use reqwest::blocking::Client; -use std::collections::HashMap; use url::Url; use crate::opts::Options; @@ -30,29 +28,11 @@ const CSS_PROPS_WITH_IMAGE_URLS: &[&str] = &[ "symbols", ]; -pub fn embed_css( - cache: &mut HashMap>, - client: &Client, - document_url: &Url, - css: &str, - options: &Options, - depth: u32, -) -> String { - let mut input = ParserInput::new(&css); +pub fn embed_css(document_url: &Url, css: &str, options: &Options, depth: u32) -> String { + let mut input = ParserInput::new(css); let mut parser = Parser::new(&mut input); - process_css( - cache, - client, - document_url, - &mut parser, - options, - depth, - "", - "", - "", - ) - .unwrap() + process_css(document_url, &mut parser, options, depth, "", "", "").unwrap() } pub fn format_ident(ident: &str) -> String { @@ -71,13 +51,10 @@ pub fn format_quoted_string(string: &str) -> String { pub fn is_image_url_prop(prop_name: &str) -> bool { CSS_PROPS_WITH_IMAGE_URLS .iter() - .find(|p| prop_name.eq_ignore_ascii_case(p)) - .is_some() + .any(|p| prop_name.eq_ignore_ascii_case(p)) } pub fn process_css<'a>( - cache: &mut HashMap>, - client: &Client, document_url: &Url, parser: &mut Parser, options: &Options, @@ -88,8 +65,8 @@ pub fn process_css<'a>( ) -> Result> { let mut result: String = "".to_string(); - let mut curr_rule: String = rule_name.clone().to_string(); - let mut curr_prop: String = prop_name.clone().to_string(); + let mut curr_rule: String = rule_name.to_string(); + let mut curr_prop: String = prop_name.to_string(); let mut token: &Token; let mut token_offset: SourcePosition; @@ -107,9 +84,9 @@ pub fn process_css<'a>( let token_slice = parser.slice_from(token_offset); result.push_str(token_slice); } - Token::Semicolon => result.push_str(";"), - Token::Colon => result.push_str(":"), - Token::Comma => result.push_str(","), + Token::Semicolon => result.push(';'), + Token::Colon => result.push(':'), + Token::Comma => result.push(','), Token::ParenthesisBlock | Token::SquareBracketBlock | Token::CurlyBracketBlock => { if options.no_fonts && curr_rule == "font-face" { continue; @@ -117,21 +94,19 @@ pub fn process_css<'a>( let closure: &str; if token == &Token::ParenthesisBlock { - result.push_str("("); + result.push('('); closure = ")"; } else if token == &Token::SquareBracketBlock { - result.push_str("["); + result.push('['); closure = "]"; } else { - result.push_str("{"); + result.push('{'); closure = "}"; } let block_css: String = parser .parse_nested_block(|parser| { process_css( - cache, - client, document_url, parser, options, @@ -146,9 +121,9 @@ pub fn process_css<'a>( result.push_str(closure); } - Token::CloseParenthesis => result.push_str(")"), - Token::CloseSquareBracket => result.push_str("]"), - Token::CloseCurlyBracket => result.push_str("}"), + Token::CloseParenthesis => result.push(')'), + Token::CloseSquareBracket => result.push(']'), + Token::CloseCurlyBracket => result.push('}'), Token::IncludeMatch => result.push_str("~="), Token::DashMatch => result.push_str("|="), Token::PrefixMatch => result.push_str("^="), @@ -156,7 +131,7 @@ pub fn process_css<'a>( Token::SubstringMatch => result.push_str("*="), Token::CDO => result.push_str(""), - Token::WhiteSpace(ref value) => { + Token::WhiteSpace(value) => { result.push_str(value); } // div... @@ -171,11 +146,11 @@ pub fn process_css<'a>( if options.no_fonts && curr_rule == "font-face" { continue; } - result.push_str("@"); + result.push('@'); result.push_str(value); } Token::Hash(ref value) => { - result.push_str("#"); + result.push('#'); result.push_str(value); } Token::QuotedString(ref value) => { @@ -189,15 +164,8 @@ pub fn process_css<'a>( continue; } - let import_full_url: Url = resolve_url(&document_url, value); - match retrieve_asset( - cache, - client, - &document_url, - &import_full_url, - options, - depth + 1, - ) { + let import_full_url: Url = resolve_url(document_url, value); + match retrieve_asset(document_url, &import_full_url, options, depth + 1) { Ok(( import_contents, import_final_url, @@ -208,8 +176,6 @@ pub fn process_css<'a>( &import_media_type, &import_charset, embed_css( - cache, - client, &import_final_url, &String::from_utf8_lossy(&import_contents), options, @@ -219,9 +185,8 @@ pub fn process_css<'a>( &import_final_url, ); import_data_url.set_fragment(import_full_url.fragment()); - result.push_str( - format_quoted_string(&import_data_url.to_string()).as_str(), - ); + result + .push_str(format_quoted_string(import_data_url.as_ref()).as_str()); } Err(_) => { // Keep remote reference if unable to retrieve the asset @@ -229,54 +194,42 @@ pub fn process_css<'a>( || import_full_url.scheme() == "https" { result.push_str( - format_quoted_string(&import_full_url.to_string()).as_str(), + format_quoted_string(import_full_url.as_ref()).as_str(), ); } } } - } else { - if func_name == "url" { - // Skip empty url()'s - if value.len() == 0 { - continue; - } + } else if func_name == "url" { + // Skip empty url()'s + if value.len() == 0 { + continue; + } - if options.no_images && is_image_url_prop(curr_prop.as_str()) { - result.push_str(format_quoted_string(EMPTY_IMAGE_DATA_URL).as_str()); - } else { - let resolved_url: Url = resolve_url(&document_url, value); - match retrieve_asset( - cache, - client, - &document_url, - &resolved_url, - options, - depth + 1, - ) { - Ok((data, final_url, media_type, charset)) => { - let mut data_url = - create_data_url(&media_type, &charset, &data, &final_url); - data_url.set_fragment(resolved_url.fragment()); + if options.no_images && is_image_url_prop(curr_prop.as_str()) { + result.push_str(format_quoted_string(EMPTY_IMAGE_DATA_URL).as_str()); + } else { + let resolved_url: Url = resolve_url(document_url, value); + match retrieve_asset(document_url, &resolved_url, options, depth + 1) { + Ok((data, final_url, media_type, charset)) => { + let mut data_url = + create_data_url(&media_type, &charset, &data, &final_url); + data_url.set_fragment(resolved_url.fragment()); + result.push_str(format_quoted_string(data_url.as_ref()).as_str()); + } + Err(_) => { + // Keep remote reference if unable to retrieve the asset + if resolved_url.scheme() == "http" + || resolved_url.scheme() == "https" + { result.push_str( - format_quoted_string(&data_url.to_string()).as_str(), + format_quoted_string(resolved_url.as_ref()).as_str(), ); } - Err(_) => { - // Keep remote reference if unable to retrieve the asset - if resolved_url.scheme() == "http" - || resolved_url.scheme() == "https" - { - result.push_str( - format_quoted_string(&resolved_url.to_string()) - .as_str(), - ); - } - } } } - } else { - result.push_str(format_quoted_string(value).as_str()); } + } else { + result.push_str(format_quoted_string(value).as_str()); } } Token::Number { @@ -285,7 +238,7 @@ pub fn process_css<'a>( .. } => { if *has_sign && *value >= 0. { - result.push_str("+"); + result.push('+'); } result.push_str(&value.to_string()) } @@ -295,10 +248,10 @@ pub fn process_css<'a>( .. } => { if *has_sign && *unit_value >= 0. { - result.push_str("+"); + result.push('+'); } result.push_str(&(unit_value * 100.0).to_string()); - result.push_str("%"); + result.push('%'); } Token::Dimension { ref has_sign, @@ -307,15 +260,15 @@ pub fn process_css<'a>( .. } => { if *has_sign && *value >= 0. { - result.push_str("+"); + result.push('+'); } result.push_str(&value.to_string()); - result.push_str(&unit.to_string()); + result.push_str(unit); } // #selector, #id... Token::IDHash(ref value) => { curr_rule = "".to_string(); - result.push_str("#"); + result.push('#'); result.push_str(&format_ident(value)); } // url() @@ -331,31 +284,22 @@ pub fn process_css<'a>( if value.len() < 1 { result.push_str("url()"); continue; - } else if value.starts_with("#") { + } else if value.starts_with('#') { result.push_str("url("); result.push_str(value); - result.push_str(")"); + result.push(')'); continue; } result.push_str("url("); if is_import { - let full_url: Url = resolve_url(&document_url, value); - match retrieve_asset( - cache, - client, - &document_url, - &full_url, - options, - depth + 1, - ) { + let full_url: Url = resolve_url(document_url, value); + match retrieve_asset(document_url, &full_url, options, depth + 1) { Ok((css, final_url, media_type, charset)) => { let mut data_url = create_data_url( &media_type, &charset, embed_css( - cache, - client, &final_url, &String::from_utf8_lossy(&css), options, @@ -365,61 +309,46 @@ pub fn process_css<'a>( &final_url, ); data_url.set_fragment(full_url.fragment()); - result.push_str(format_quoted_string(&data_url.to_string()).as_str()); + result.push_str(format_quoted_string(data_url.as_ref()).as_str()); } Err(_) => { // Keep remote reference if unable to retrieve the asset if full_url.scheme() == "http" || full_url.scheme() == "https" { - result - .push_str(format_quoted_string(&full_url.to_string()).as_str()); + result.push_str(format_quoted_string(full_url.as_ref()).as_str()); } } } + } else if is_image_url_prop(curr_prop.as_str()) && options.no_images { + result.push_str(format_quoted_string(EMPTY_IMAGE_DATA_URL).as_str()); } else { - if is_image_url_prop(curr_prop.as_str()) && options.no_images { - result.push_str(format_quoted_string(EMPTY_IMAGE_DATA_URL).as_str()); - } else { - let full_url: Url = resolve_url(&document_url, value); - match retrieve_asset( - cache, - client, - &document_url, - &full_url, - options, - depth + 1, - ) { - Ok((data, final_url, media_type, charset)) => { - let mut data_url = - create_data_url(&media_type, &charset, &data, &final_url); - data_url.set_fragment(full_url.fragment()); - result - .push_str(format_quoted_string(&data_url.to_string()).as_str()); - } - Err(_) => { - // Keep remote reference if unable to retrieve the asset - if full_url.scheme() == "http" || full_url.scheme() == "https" { - result.push_str( - format_quoted_string(&full_url.to_string()).as_str(), - ); - } + let full_url: Url = resolve_url(document_url, value); + match retrieve_asset(document_url, &full_url, options, depth + 1) { + Ok((data, final_url, media_type, charset)) => { + let mut data_url = + create_data_url(&media_type, &charset, &data, &final_url); + data_url.set_fragment(full_url.fragment()); + result.push_str(format_quoted_string(data_url.as_ref()).as_str()); + } + Err(_) => { + // Keep remote reference if unable to retrieve the asset + if full_url.scheme() == "http" || full_url.scheme() == "https" { + result.push_str(format_quoted_string(full_url.as_ref()).as_str()); } } } } - result.push_str(")"); + result.push(')'); } // = Token::Delim(ref value) => result.push_str(&value.to_string()), Token::Function(ref name) => { let function_name: &str = &name.clone(); result.push_str(function_name); - result.push_str("("); + result.push('('); let block_css: String = parser .parse_nested_block(|parser| { process_css( - cache, - client, document_url, parser, options, @@ -432,14 +361,14 @@ pub fn process_css<'a>( .unwrap(); result.push_str(block_css.as_str()); - result.push_str(")"); + result.push(')'); } Token::BadUrl(_) | Token::BadString(_) => {} } } // Ensure empty CSS is really empty - if result.len() > 0 && result.trim().len() == 0 { + if !result.is_empty() && result.trim().is_empty() { result = result.trim().to_string() } diff --git a/src/html.rs b/src/html.rs index 89c0328..590a0b2 100644 --- a/src/html.rs +++ b/src/html.rs @@ -3,16 +3,15 @@ use chrono::prelude::*; use encoding_rs::Encoding; use html5ever::interface::QualName; use html5ever::parse_document; -use html5ever::rcdom::{Handle, NodeData, RcDom}; use html5ever::serialize::{serialize, SerializeOpts}; use html5ever::tendril::{format_tendril, TendrilSink}; use html5ever::tree_builder::{Attribute, TreeSink}; use html5ever::{local_name, namespace_url, ns, LocalName}; +use markup5ever_rcdom::{Handle, NodeData, RcDom, SerializableHandle}; use regex::Regex; -use reqwest::blocking::Client; + use reqwest::Url; use sha2::{Digest, Sha256, Sha384, Sha512}; -use std::collections::HashMap; use std::default::Default; use crate::css::embed_css; @@ -28,12 +27,16 @@ struct SrcSetItem<'a> { descriptor: &'a str, } -const ICON_VALUES: &'static [&str] = &["icon", "shortcut icon"]; +const ICON_VALUES: &[&str] = &["icon", "shortcut icon"]; pub fn add_favicon(document: &Handle, favicon_data_url: String) -> RcDom { let mut buf: Vec = Vec::new(); - serialize(&mut buf, document, SerializeOpts::default()) - .expect("unable to serialize DOM into buffer"); + serialize( + &mut buf, + &SerializableHandle::from(document.clone()), + SerializeOpts::default(), + ) + .expect("unable to serialize DOM into buffer"); let mut dom = html_to_dom(&buf, "utf-8".to_string()); let doc = dom.get_document(); @@ -54,7 +57,7 @@ pub fn add_favicon(document: &Handle, favicon_data_url: String) -> RcDom { Default::default(), ); // Insert favicon LINK tag into HEAD - head.children.borrow_mut().push(favicon_node.clone()); + head.children.borrow_mut().push(favicon_node); } } @@ -62,18 +65,18 @@ pub fn add_favicon(document: &Handle, favicon_data_url: String) -> RcDom { } pub fn check_integrity(data: &[u8], integrity: &str) -> bool { - if integrity.starts_with("sha256-") { + if let Some(stripped) = integrity.strip_prefix("sha256-") { let mut hasher = Sha256::new(); hasher.update(data); - base64::encode(hasher.finalize()) == integrity[7..] - } else if integrity.starts_with("sha384-") { + base64::encode(hasher.finalize()) == stripped + } else if let Some(stripped) = integrity.strip_prefix("sha384-") { let mut hasher = Sha384::new(); hasher.update(data); - base64::encode(hasher.finalize()) == integrity[7..] - } else if integrity.starts_with("sha512-") { + base64::encode(hasher.finalize()) == stripped + } else if let Some(stripped) = integrity.strip_prefix("sha512-") { let mut hasher = Sha512::new(); hasher.update(data); - base64::encode(hasher.finalize()) == integrity[7..] + base64::encode(hasher.finalize()) == stripped } else { false } @@ -125,7 +128,7 @@ pub fn create_metadata_tag(url: &Url) -> String { format!( "", if clean_url.scheme() == "http" || clean_url.scheme() == "https" { - &clean_url.as_str() + clean_url.as_str() } else { "local source" }, @@ -155,19 +158,12 @@ pub fn determine_link_node_type(node: &Handle) -> &str { link_type } -pub fn embed_srcset( - cache: &mut HashMap>, - client: &Client, - document_url: &Url, - srcset: &str, - options: &Options, - depth: u32, -) -> String { +pub fn embed_srcset(document_url: &Url, srcset: &str, options: &Options, depth: u32) -> String { let mut array: Vec = vec![]; let re = Regex::new(r",\s+").unwrap(); for srcset_item in re.split(srcset) { - let parts: Vec<&str> = srcset_item.trim().split_whitespace().collect(); - if parts.len() > 0 { + let parts: Vec<&str> = srcset_item.split_whitespace().collect(); + if !parts.is_empty() { let path = parts[0].trim(); let descriptor = if parts.len() > 1 { parts[1].trim() } else { "" }; let srcset_real_item = SrcSetItem { path, descriptor }; @@ -181,15 +177,8 @@ pub fn embed_srcset( if options.no_images { result.push_str(EMPTY_IMAGE_DATA_URL); } else { - let image_full_url: Url = resolve_url(&document_url, part.path); - match retrieve_asset( - cache, - client, - &document_url, - &image_full_url, - options, - depth + 1, - ) { + let image_full_url: Url = resolve_url(document_url, part.path); + match retrieve_asset(document_url, &image_full_url, options, depth + 1) { Ok((image_data, image_final_url, image_media_type, image_charset)) => { let mut image_data_url = create_data_url( &image_media_type, @@ -214,7 +203,7 @@ pub fn embed_srcset( } if !part.descriptor.is_empty() { - result.push_str(" "); + result.push(' '); result.push_str(part.descriptor); } @@ -239,11 +228,8 @@ pub fn find_base_node(node: &Handle) -> Option { } } NodeData::Element { ref name, .. } => { - match name.local.as_ref() { - "head" => { - return get_child_node_by_name(node, "base"); - } - _ => {} + if name.local.as_ref() == "head" { + return get_child_node_by_name(node, "base"); } // Dig deeper @@ -273,7 +259,7 @@ pub fn find_meta_charset_or_content_type_node(node: &Handle) -> Option { match name.local.as_ref() { "head" => { if let Some(meta_node) = get_child_node_by_name(node, "meta") { - if let Some(_) = get_node_attr(&meta_node, "charset") { + if get_node_attr(&meta_node, "charset").is_some() { return Some(meta_node); } else if let Some(meta_node_http_equiv_attr_value) = get_node_attr(&meta_node, "http-equiv") @@ -324,7 +310,7 @@ pub fn get_charset(node: &Handle) -> Option { } } - return None; + None } pub fn get_child_node_by_name(parent: &Handle, node_name: &str) -> Option { @@ -333,10 +319,7 @@ pub fn get_child_node_by_name(parent: &Handle, node_name: &str) -> Option &*name.local == node_name, _ => false, }); - match matching_children { - Some(node) => Some(node.clone()), - _ => None, - } + matching_children.cloned() } pub fn get_node_attr(node: &Handle, attr_name: &str) -> Option { @@ -361,7 +344,7 @@ pub fn get_node_name(node: &Handle) -> Option<&'_ str> { } pub fn get_parent_node(child: &Handle) -> Handle { - let parent = child.parent.take().clone(); + let parent = child.parent.take(); parent.and_then(|node| node.upgrade()).unwrap() } @@ -406,14 +389,14 @@ pub fn has_favicon(handle: &Handle) -> bool { found_favicon } -pub fn html_to_dom(data: &Vec, document_encoding: String) -> RcDom { +pub fn html_to_dom(data: &[u8], document_encoding: String) -> RcDom { let s: String; if let Some(encoding) = Encoding::for_label(document_encoding.as_bytes()) { - let (string, _, _) = encoding.decode(&data); + let (string, _, _) = encoding.decode(data); s = string.to_string(); } else { - s = String::from_utf8_lossy(&data).to_string(); + s = String::from_utf8_lossy(data).to_string(); } parse_document(RcDom::default(), Default::default()) @@ -428,8 +411,12 @@ pub fn is_icon(attr_value: &str) -> bool { pub fn set_base_url(document: &Handle, desired_base_href: String) -> RcDom { let mut buf: Vec = Vec::new(); - serialize(&mut buf, document, SerializeOpts::default()) - .expect("unable to serialize DOM into buffer"); + serialize( + &mut buf, + &SerializableHandle::from(document.clone()), + SerializeOpts::default(), + ) + .expect("unable to serialize DOM into buffer"); let mut dom = html_to_dom(&buf, "utf-8".to_string()); let doc = dom.get_document(); @@ -449,7 +436,7 @@ pub fn set_base_url(document: &Handle, desired_base_href: String) -> RcDom { ); // Insert newly created BASE node into HEAD - head_node.children.borrow_mut().push(base_node.clone()); + head_node.children.borrow_mut().push(base_node); } } } @@ -459,9 +446,9 @@ pub fn set_base_url(document: &Handle, desired_base_href: String) -> RcDom { pub fn set_charset(mut dom: RcDom, desired_charset: String) -> RcDom { if let Some(meta_charset_node) = find_meta_charset_or_content_type_node(&dom.document) { - if let Some(_) = get_node_attr(&meta_charset_node, "charset") { + if get_node_attr(&meta_charset_node, "charset").is_some() { set_node_attr(&meta_charset_node, "charset", Some(desired_charset)); - } else if let Some(_) = get_node_attr(&meta_charset_node, "content") { + } else if get_node_attr(&meta_charset_node, "content").is_some() { set_node_attr( &meta_charset_node, "content", @@ -481,10 +468,7 @@ pub fn set_charset(mut dom: RcDom, desired_charset: String) -> RcDom { // Insert newly created META charset node into HEAD if let Some(html_node) = get_child_node_by_name(&dom.document, "html") { if let Some(head_node) = get_child_node_by_name(&html_node, "head") { - head_node - .children - .borrow_mut() - .push(meta_charset_node.clone()); + head_node.children.borrow_mut().push(meta_charset_node); } } } @@ -505,7 +489,7 @@ pub fn set_node_attr(node: &Handle, attr_name: &str, attr_value: Option) if let Some(attr_value) = attr_value.clone() { let _ = &attrs_mut[i].value.clear(); - let _ = &attrs_mut[i].value.push_slice(&attr_value.as_str()); + let _ = &attrs_mut[i].value.push_slice(attr_value.as_str()); } else { // Remove attr completely if attr_value is not defined attrs_mut.remove(i); @@ -518,7 +502,7 @@ pub fn set_node_attr(node: &Handle, attr_name: &str, attr_value: Option) if !found_existing_attr { // Add new attribute (since originally the target node didn't have it) - if let Some(attr_value) = attr_value.clone() { + if let Some(attr_value) = attr_value { let name = LocalName::from(attr_name); attrs_mut.push(Attribute { @@ -564,20 +548,24 @@ pub fn serialize_document(mut dom: RcDom, document_encoding: String, options: &O // since there already may be one defined in the original document, // and browsers don't allow re-defining them (for obvious reasons) head.children.borrow_mut().reverse(); - head.children.borrow_mut().push(meta.clone()); + head.children.borrow_mut().push(meta); head.children.borrow_mut().reverse(); } } } - serialize(&mut buf, &doc, SerializeOpts::default()) - .expect("Unable to serialize DOM into buffer"); + serialize( + &mut buf, + &SerializableHandle::from(doc), + SerializeOpts::default(), + ) + .expect("Unable to serialize DOM into buffer"); // Unwrap NOSCRIPT elements if options.unwrap_noscript { let s: &str = &String::from_utf8_lossy(&buf); let noscript_re = Regex::new(r"<(?P/?noscript[^>]*)>").unwrap(); - buf = noscript_re.replace_all(&s, "").as_bytes().to_vec(); + buf = noscript_re.replace_all(s, "").as_bytes().to_vec(); } if !document_encoding.is_empty() { @@ -592,8 +580,6 @@ pub fn serialize_document(mut dom: RcDom, document_encoding: String, options: &O } pub fn retrieve_and_embed_asset( - cache: &mut HashMap>, - client: &Client, document_url: &Url, node: &Handle, attr_name: &str, @@ -601,18 +587,11 @@ pub fn retrieve_and_embed_asset( options: &Options, depth: u32, ) { - let resolved_url: Url = resolve_url(document_url, attr_value.clone()); - - match retrieve_asset( - cache, - client, - &document_url.clone(), - &resolved_url, - options, - depth + 1, - ) { + let resolved_url: Url = resolve_url(document_url, attr_value); + + match retrieve_asset(&document_url.clone(), &resolved_url, options, depth + 1) { Ok((data, final_url, mut media_type, charset)) => { - let node_name: &str = get_node_name(&node).unwrap(); + let node_name: &str = get_node_name(node).unwrap(); // Check integrity if it's a LINK or SCRIPT element let mut ok_to_include: bool = true; @@ -639,28 +618,21 @@ pub fn retrieve_and_embed_asset( if node_name == "link" && determine_link_node_type(node) == "stylesheet" { // Stylesheet LINK elements require special treatment - let css: String = embed_css(cache, client, &final_url, &s, options, depth + 1); + let css: String = embed_css(&final_url, &s, options, depth + 1); // Create and embed data URL let css_data_url = create_data_url(&media_type, &charset, css.as_bytes(), &final_url); - set_node_attr(&node, attr_name, Some(css_data_url.to_string())); + set_node_attr(node, attr_name, Some(css_data_url.to_string())); } else if node_name == "frame" || node_name == "iframe" { // (I)FRAMEs are also quite different from conventional resources let frame_dom = html_to_dom(&data, charset.clone()); - walk_and_embed_assets( - cache, - client, - &final_url, - &frame_dom.document, - &options, - depth + 1, - ); + walk_and_embed_assets(&final_url, &frame_dom.document, options, depth + 1); let mut frame_data: Vec = Vec::new(); serialize( &mut frame_data, - &frame_dom.document, + &SerializableHandle::from(frame_dom.document), SerializeOpts::default(), ) .unwrap(); @@ -674,14 +646,12 @@ pub fn retrieve_and_embed_asset( // Every other type of element gets processed here // Parse media type for SCRIPT elements - if node_name == "script" { - if let Some(_) = get_node_attr(node, "src") { - if let Some(script_node_type_attr_value) = get_node_attr(node, "type") { - media_type = script_node_type_attr_value.to_string(); - } else { - // Fallback to default one if it's not specified - media_type = "application/javascript".to_string(); - } + if node_name == "script" && get_node_attr(node, "src").is_some() { + if let Some(script_node_type_attr_value) = get_node_attr(node, "type") { + media_type = script_node_type_attr_value; + } else { + // Fallback to default one if it's not specified + media_type = "application/javascript".to_string(); } } @@ -704,19 +674,12 @@ pub fn retrieve_and_embed_asset( } } -pub fn walk_and_embed_assets( - cache: &mut HashMap>, - client: &Client, - document_url: &Url, - node: &Handle, - options: &Options, - depth: u32, -) { +pub fn walk_and_embed_assets(document_url: &Url, node: &Handle, options: &Options, depth: u32) { match node.data { NodeData::Document => { // Dig deeper for child in node.children.borrow().iter() { - walk_and_embed_assets(cache, client, &document_url, child, options, depth); + walk_and_embed_assets(document_url, child, options, depth); } } NodeData::Element { @@ -732,7 +695,7 @@ pub fn walk_and_embed_assets( || meta_attr_http_equiv_value.eq_ignore_ascii_case("location") { // Remove http-equiv attributes from META nodes if they're able to control the page - set_node_attr(&node, "http-equiv", None); + set_node_attr(node, "http-equiv", None); } } } @@ -744,9 +707,7 @@ pub fn walk_and_embed_assets( if let Some(link_attr_href_value) = get_node_attr(node, "href") { if !options.no_images && !link_attr_href_value.is_empty() { retrieve_and_embed_asset( - cache, - client, - &document_url, + document_url, node, "href", &link_attr_href_value, @@ -764,19 +725,15 @@ pub fn walk_and_embed_assets( set_node_attr(node, "href", None); // Wipe integrity attribute set_node_attr(node, "integrity", None); - } else { - if !link_attr_href_value.is_empty() { - retrieve_and_embed_asset( - cache, - client, - &document_url, - node, - "href", - &link_attr_href_value, - options, - depth, - ); - } + } else if !link_attr_href_value.is_empty() { + retrieve_and_embed_asset( + document_url, + node, + "href", + &link_attr_href_value, + options, + depth, + ); } } } else if link_type == "preload" || link_type == "dns-prefetch" { @@ -786,7 +743,7 @@ pub fn walk_and_embed_assets( // Make sure that all other LINKs' href attributes are full URLs if let Some(link_attr_href_value) = get_node_attr(node, "href") { let href_full_url: Url = - resolve_url(&document_url, &link_attr_href_value); + resolve_url(document_url, &link_attr_href_value); set_node_attr(node, "href", Some(href_full_url.to_string())); } } @@ -809,8 +766,6 @@ pub fn walk_and_embed_assets( if !options.no_images && !body_attr_background_value.is_empty() { retrieve_and_embed_asset( - cache, - client, document_url, node, "background", @@ -828,56 +783,46 @@ pub fn walk_and_embed_assets( if options.no_images { // Put empty images into src and data-src attributes - if img_attr_src_value != None { + if img_attr_src_value.is_some() { set_node_attr(node, "src", Some(EMPTY_IMAGE_DATA_URL.to_string())); } - if img_attr_data_src_value != None { + if img_attr_data_src_value.is_some() { set_node_attr(node, "data-src", Some(EMPTY_IMAGE_DATA_URL.to_string())); } + } else if img_attr_src_value.clone().unwrap_or_default().is_empty() + && img_attr_data_src_value + .clone() + .unwrap_or_default() + .is_empty() + { + // Add empty src attribute + set_node_attr(node, "src", Some("".to_string())); } else { - if img_attr_src_value.clone().unwrap_or_default().is_empty() - && img_attr_data_src_value - .clone() - .unwrap_or_default() - .is_empty() + // Add data URL src attribute + let img_full_url: String = if !img_attr_data_src_value + .clone() + .unwrap_or_default() + .is_empty() { - // Add empty src attribute - set_node_attr(node, "src", Some("".to_string())); + img_attr_data_src_value.unwrap_or_default() } else { - // Add data URL src attribute - let img_full_url: String = if !img_attr_data_src_value - .clone() - .unwrap_or_default() - .is_empty() - { - img_attr_data_src_value.unwrap_or_default() - } else { - img_attr_src_value.unwrap_or_default() - }; - retrieve_and_embed_asset( - cache, - client, - document_url, - node, - "src", - &img_full_url, - options, - depth, - ); - } + img_attr_src_value.unwrap_or_default() + }; + retrieve_and_embed_asset( + document_url, + node, + "src", + &img_full_url, + options, + depth, + ); } // Resolve srcset attribute if let Some(img_srcset) = get_node_attr(node, "srcset") { if !img_srcset.is_empty() { - let resolved_srcset: String = embed_srcset( - cache, - client, - &document_url, - &img_srcset, - options, - depth, - ); + let resolved_srcset: String = + embed_srcset(document_url, &img_srcset, options, depth); set_node_attr(node, "srcset", Some(resolved_srcset)); } } @@ -900,8 +845,6 @@ pub fn walk_and_embed_assets( set_node_attr(node, "src", Some(value.to_string())); } else { retrieve_and_embed_asset( - cache, - client, document_url, node, "src", @@ -933,8 +876,6 @@ pub fn walk_and_embed_assets( if !options.no_images && !image_href.is_empty() { retrieve_and_embed_asset( - cache, - client, document_url, node, "href", @@ -954,8 +895,6 @@ pub fn walk_and_embed_assets( set_node_attr(node, "src", None); } else { retrieve_and_embed_asset( - cache, - client, document_url, node, "src", @@ -969,8 +908,6 @@ pub fn walk_and_embed_assets( set_node_attr(node, "src", None); } else { retrieve_and_embed_asset( - cache, - client, document_url, node, "src", @@ -983,44 +920,36 @@ pub fn walk_and_embed_assets( } if let Some(source_attr_srcset_value) = get_node_attr(node, "srcset") { - if parent_node_name == "picture" { - if !source_attr_srcset_value.is_empty() { - if options.no_images { - set_node_attr( - node, - "srcset", - Some(EMPTY_IMAGE_DATA_URL.to_string()), - ); - } else { - let resolved_srcset: String = embed_srcset( - cache, - client, - &document_url, - &source_attr_srcset_value, - options, - depth, - ); - set_node_attr(node, "srcset", Some(resolved_srcset)); - } + if parent_node_name == "picture" && !source_attr_srcset_value.is_empty() { + if options.no_images { + set_node_attr( + node, + "srcset", + Some(EMPTY_IMAGE_DATA_URL.to_string()), + ); + } else { + let resolved_srcset: String = embed_srcset( + document_url, + &source_attr_srcset_value, + options, + depth, + ); + set_node_attr(node, "srcset", Some(resolved_srcset)); } } } } "a" | "area" => { if let Some(anchor_attr_href_value) = get_node_attr(node, "href") { - if anchor_attr_href_value - .clone() - .trim() - .starts_with("javascript:") - { + if anchor_attr_href_value.trim().starts_with("javascript:") { if options.no_js { // Replace with empty JS call to preserve original behavior set_node_attr(node, "href", Some("javascript:;".to_string())); } } else { // Don't touch mailto: links or hrefs which begin with a hash sign - if !anchor_attr_href_value.clone().starts_with('#') - && !is_url_and_has_protocol(&anchor_attr_href_value.clone()) + if !anchor_attr_href_value.starts_with('#') + && !is_url_and_has_protocol(&anchor_attr_href_value) { let href_full_url: Url = resolve_url(document_url, &anchor_attr_href_value); @@ -1037,15 +966,13 @@ pub fn walk_and_embed_assets( // Empty inner content node.children.borrow_mut().clear(); // Remove src attribute - if script_attr_src != None { + if script_attr_src.is_some() { set_node_attr(node, "src", None); // Wipe integrity attribute set_node_attr(node, "integrity", None); } } else if !script_attr_src.clone().unwrap_or_default().is_empty() { retrieve_and_embed_asset( - cache, - client, document_url, node, "src", @@ -1063,14 +990,8 @@ pub fn walk_and_embed_assets( for child_node in node.children.borrow_mut().iter_mut() { if let NodeData::Text { ref contents } = child_node.data { let mut tendril = contents.borrow_mut(); - let replacement = embed_css( - cache, - client, - &document_url, - tendril.as_ref(), - options, - depth, - ); + let replacement = + embed_css(document_url, tendril.as_ref(), options, depth); tendril.clear(); tendril.push_slice(&replacement); } @@ -1094,9 +1015,7 @@ pub fn walk_and_embed_assets( // Ignore (i)frames with empty source (they cause infinite loops) if !frame_attr_src_value.trim().is_empty() { retrieve_and_embed_asset( - cache, - client, - &document_url, + document_url, node, "src", &frame_attr_src_value, @@ -1114,8 +1033,6 @@ pub fn walk_and_embed_assets( set_node_attr(node, "src", None); } else { retrieve_and_embed_asset( - cache, - client, document_url, node, "src", @@ -1133,8 +1050,6 @@ pub fn walk_and_embed_assets( set_node_attr(node, "src", None); } else { retrieve_and_embed_asset( - cache, - client, document_url, node, "src", @@ -1157,8 +1072,6 @@ pub fn walk_and_embed_assets( ); } else { retrieve_and_embed_asset( - cache, - client, document_url, node, "poster", @@ -1183,11 +1096,9 @@ pub fn walk_and_embed_assets( ); // Embed assets of NOSCRIPT node contents walk_and_embed_assets( - cache, - client, - &document_url, + document_url, &noscript_contents_dom.document, - &options, + options, depth, ); // Get rid of original contents @@ -1198,8 +1109,12 @@ pub fn walk_and_embed_assets( { if let Some(body) = get_child_node_by_name(&html, "body") { let mut buf: Vec = Vec::new(); - serialize(&mut buf, &body, SerializeOpts::default()) - .expect("Unable to serialize DOM into buffer"); + serialize( + &mut buf, + &SerializableHandle::from(body), + SerializeOpts::default(), + ) + .expect("Unable to serialize DOM into buffer"); let result = String::from_utf8_lossy(&buf); noscript_contents.push_slice(&result); } @@ -1219,14 +1134,8 @@ pub fn walk_and_embed_assets( } else { // Embed URLs found within the style attribute of this node if let Some(node_attr_style_value) = get_node_attr(node, "style") { - let embedded_style = embed_css( - cache, - client, - &document_url, - &node_attr_style_value, - options, - depth, - ); + let embedded_style = + embed_css(document_url, &node_attr_style_value, options, depth); set_node_attr(node, "style", Some(embedded_style)); } } @@ -1249,7 +1158,7 @@ pub fn walk_and_embed_assets( // Dig deeper for child in node.children.borrow().iter() { - walk_and_embed_assets(cache, client, &document_url, child, options, depth); + walk_and_embed_assets(document_url, child, options, depth); } } _ => { diff --git a/src/js.rs b/src/js.rs index cfb19f6..a6b463a 100644 --- a/src/js.rs +++ b/src/js.rs @@ -1,4 +1,4 @@ -const JS_DOM_EVENT_ATTRS: &'static [&str] = &[ +const JS_DOM_EVENT_ATTRS: &[&str] = &[ // From WHATWG HTML spec 8.1.5.2 "Event handlers on elements, Document objects, and Window objects": // https://html.spec.whatwg.org/#event-handlers-on-elements,-document-objects,-and-window-objects // https://html.spec.whatwg.org/#attributes-3 (table "List of event handler content attributes") @@ -98,6 +98,5 @@ const JS_DOM_EVENT_ATTRS: &'static [&str] = &[ pub fn attr_is_event_handler(attr_name: &str) -> bool { JS_DOM_EVENT_ATTRS .iter() - .find(|a| attr_name.eq_ignore_ascii_case(a)) - .is_some() + .any(|a| attr_name.eq_ignore_ascii_case(a)) } diff --git a/src/main.rs b/src/main.rs index 0517d57..6c4582f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,20 +1,16 @@ use encoding_rs::Encoding; -use html5ever::rcdom::RcDom; -use reqwest::blocking::Client; -use reqwest::header::{HeaderMap, HeaderValue, USER_AGENT}; -use std::collections::HashMap; +use markup5ever_rcdom::RcDom; use std::fs; use std::io::{self, prelude::*, Error, Write}; use std::path::Path; use std::process; -use std::time::Duration; use url::Url; use monolith::html::{ add_favicon, create_metadata_tag, get_base_url, get_charset, has_favicon, html_to_dom, serialize_document, set_base_url, set_charset, walk_and_embed_assets, }; -use monolith::opts::Options; +use monolith::opts::OPTIONS; use monolith::url::{create_data_url, resolve_url}; use monolith::utils::retrieve_asset; @@ -32,13 +28,13 @@ impl Output { } } - fn write(&mut self, bytes: &Vec) -> Result<(), Error> { + fn write(&mut self, bytes: &[u8]) -> Result<(), Error> { match self { Output::Stdout(stdout) => { stdout.write_all(bytes)?; // Ensure newline at end of output if bytes.last() != Some(&b"\n"[0]) { - stdout.write(b"\n")?; + stdout.write_all(b"\n")?; } stdout.flush() } @@ -46,7 +42,7 @@ impl Output { file.write_all(bytes)?; // Ensure newline at end of output if bytes.last() != Some(&b"\n"[0]) { - file.write(b"\n")?; + file.write_all(b"\n")?; } file.flush() } @@ -64,19 +60,17 @@ pub fn read_stdin() -> Vec { } fn main() { - let options = Options::from_args(); - // Check if target was provided - if options.target.len() == 0 { - if !options.silent { + if OPTIONS.target.is_empty() { + if !OPTIONS.silent { eprintln!("No target specified"); } process::exit(1); } // Check if custom charset is valid - if let Some(custom_charset) = options.charset.clone() { - if !Encoding::for_label_no_replacement(custom_charset.as_bytes()).is_some() { + if let Some(custom_charset) = &OPTIONS.charset { + if Encoding::for_label_no_replacement(custom_charset.as_bytes()).is_none() { eprintln!("Unknown encoding: {}", &custom_charset); process::exit(1); } @@ -84,18 +78,18 @@ fn main() { let mut use_stdin: bool = false; - let target_url = match options.target.as_str() { + let target_url = match OPTIONS.target.as_str() { "-" => { // Read from pipe (stdin) use_stdin = true; // Set default target URL to an empty data URL; the user can set it via --base-url Url::parse("data:text/html,").unwrap() } - target => match Url::parse(&target) { + target => match Url::parse(target) { Ok(url) => match url.scheme() { "data" | "file" | "http" | "https" => url, unsupported_scheme => { - if !options.silent { + if !OPTIONS.silent { eprintln!("Unsupported target URL type: {}", unsupported_scheme); } process::exit(1) @@ -107,11 +101,11 @@ fn main() { match path.exists() { true => match path.is_file() { true => { - let canonical_path = fs::canonicalize(&path).unwrap(); + let canonical_path = fs::canonicalize(path).unwrap(); match Url::from_file_path(canonical_path) { Ok(url) => url, Err(_) => { - if !options.silent { + if !OPTIONS.silent { eprintln!( "Could not generate file URL out of given path: {}", &target @@ -122,7 +116,7 @@ fn main() { } } false => { - if !options.silent { + if !OPTIONS.silent { eprintln!("Local target is not a file: {}", &target); } process::exit(1); @@ -139,26 +133,6 @@ fn main() { }, }; - // Initialize client - let mut cache = HashMap::new(); - let mut header_map = HeaderMap::new(); - if let Some(user_agent) = &options.user_agent { - header_map.insert( - USER_AGENT, - HeaderValue::from_str(&user_agent).expect("Invalid User-Agent header specified"), - ); - } - let client = if options.timeout > 0 { - Client::builder().timeout(Duration::from_secs(options.timeout)) - } else { - // No timeout is default - Client::builder() - } - .danger_accept_invalid_certs(options.insecure) - .default_headers(header_map) - .build() - .expect("Failed to initialize HTTP client"); - // At first we assume that base URL is the same as target URL let mut base_url: Url = target_url.clone(); @@ -173,7 +147,7 @@ fn main() { || (target_url.scheme() == "http" || target_url.scheme() == "https") || target_url.scheme() == "data" { - match retrieve_asset(&mut cache, &client, &target_url, &target_url, &options, 0) { + match retrieve_asset(&target_url, &target_url, &OPTIONS, 0) { Ok((retrieved_data, final_url, media_type, charset)) => { // Provide output as text without processing it, the way browsers do if !media_type.eq_ignore_ascii_case("text/html") @@ -181,7 +155,7 @@ fn main() { { // Define output let mut output = - Output::new(&options.output).expect("Could not prepare output"); + Output::new(&OPTIONS.output).expect("Could not prepare output"); // Write retrieved data into STDOUT or file output @@ -192,7 +166,7 @@ fn main() { process::exit(0); } - if options + if OPTIONS .base_url .clone() .unwrap_or("".to_string()) @@ -205,7 +179,7 @@ fn main() { document_encoding = charset; } Err(_) => { - if !options.silent { + if !OPTIONS.silent { eprintln!("Could not retrieve target document"); } process::exit(1); @@ -233,7 +207,7 @@ fn main() { } // Use custom base URL if specified, read and use what's in the DOM otherwise - let custom_base_url: String = options.base_url.clone().unwrap_or("".to_string()); + let custom_base_url: String = OPTIONS.base_url.clone().unwrap_or("".to_string()); if custom_base_url.is_empty() { // No custom base URL is specified // Try to see if document has BASE element @@ -260,12 +234,12 @@ fn main() { // Relative paths could work for documents saved from filesystem let path: &Path = Path::new(&custom_base_url); if path.exists() { - match Url::from_file_path(fs::canonicalize(&path).unwrap()) { + match Url::from_file_path(fs::canonicalize(path).unwrap()) { Ok(file_url) => { base_url = file_url; } Err(_) => { - if !options.silent { + if !OPTIONS.silent { eprintln!( "Could not map given path to base URL: {}", custom_base_url @@ -281,57 +255,50 @@ fn main() { } // Traverse through the document and embed remote assets - walk_and_embed_assets(&mut cache, &client, &base_url, &dom.document, &options, 0); + walk_and_embed_assets(&base_url, &dom.document, &OPTIONS, 0); // Update or add new BASE element to reroute network requests and hash-links - if let Some(new_base_url) = options.base_url.clone() { + if let Some(new_base_url) = OPTIONS.base_url.clone() { dom = set_base_url(&dom.document, new_base_url); } // Request and embed /favicon.ico (unless it's already linked in the document) - if !options.no_images + if !OPTIONS.no_images && (target_url.scheme() == "http" || target_url.scheme() == "https") && !has_favicon(&dom.document) { let favicon_ico_url: Url = resolve_url(&base_url, "/favicon.ico"); - match retrieve_asset( - &mut cache, - &client, - &target_url, - &favicon_ico_url, - &options, - 0, - ) { + match retrieve_asset(&target_url, &favicon_ico_url, &OPTIONS, 0) { Ok((data, final_url, media_type, charset)) => { let favicon_data_url: Url = create_data_url(&media_type, &charset, &data, &final_url); dom = add_favicon(&dom.document, favicon_data_url.to_string()); } Err(_) => { - // Failed to retrieve /favicon.ico + eprintln!("Failed to retrieve /favicon.ico"); } } } // Save using specified charset, if given - if let Some(custom_charset) = options.charset.clone() { + if let Some(custom_charset) = OPTIONS.charset.clone() { document_encoding = custom_charset; dom = set_charset(dom, document_encoding.clone()); } // Serialize DOM tree - let mut result: Vec = serialize_document(dom, document_encoding, &options); + let mut result: Vec = serialize_document(dom, document_encoding, &OPTIONS); // Prepend metadata comment tag - if !options.no_metadata { + if !OPTIONS.no_metadata { let mut metadata_comment: String = create_metadata_tag(&target_url); metadata_comment += "\n"; result.splice(0..0, metadata_comment.as_bytes().to_vec()); } // Define output - let mut output = Output::new(&options.output).expect("Could not prepare output"); + let mut output = Output::new(&OPTIONS.output).expect("Could not prepare output"); // Write result into STDOUT or file output.write(&result).expect("Could not write output"); diff --git a/src/opts.rs b/src/opts.rs index bee5d86..f5fbb56 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -1,6 +1,9 @@ use clap::{App, Arg, ArgAction}; +use once_cell::sync::Lazy; use std::env; +pub static OPTIONS: Lazy = Lazy::new(Options::from_args); + #[derive(Default)] pub struct Options { pub no_audio: bool, @@ -27,7 +30,7 @@ pub struct Options { pub unwrap_noscript: bool, } -const ASCII: &'static str = " \ +const ASCII: &str = " \ _____ ______________ __________ ___________________ ___ | \\ / \\ | | | | | | | \\_/ __ \\_| __ | | ___ ___ |__| | @@ -37,13 +40,13 @@ const ASCII: &'static str = " \ |___| |__________| \\_____________________| |___| |___| |___| "; const DEFAULT_NETWORK_TIMEOUT: u64 = 120; -const DEFAULT_USER_AGENT: &'static str = +const DEFAULT_USER_AGENT: &str = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:73.0) Gecko/20100101 Firefox/73.0"; const ENV_VAR_NO_COLOR: &str = "NO_COLOR"; const ENV_VAR_TERM: &str = "TERM"; impl Options { - pub fn from_args() -> Options { + fn from_args() -> Options { let app = App::new(env!("CARGO_PKG_NAME")) .version(env!("CARGO_PKG_VERSION")) .author(format!("\n{}\n\n", env!("CARGO_PKG_AUTHORS").replace(':', "\n")).as_str()) @@ -107,7 +110,7 @@ impl Options { options.charset = Some(charset.to_string()); } if let Some(domains) = app.get_many::("domains") { - let list_of_domains: Vec = domains.map(|v| v.clone()).collect::>(); + let list_of_domains: Vec = domains.cloned().collect::>(); options.domains = Some(list_of_domains); } options.ignore_errors = app.is_present("ignore-errors"); diff --git a/src/url.rs b/src/url.rs index 01dc5d9..01d3b16 100644 --- a/src/url.rs +++ b/src/url.rs @@ -4,11 +4,11 @@ use url::Url; use crate::utils::{detect_media_type, parse_content_type}; -pub const EMPTY_IMAGE_DATA_URL: &'static str = "data:image/png;base64,\ +pub const EMPTY_IMAGE_DATA_URL: &str = "data:image/png;base64,\ iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAQAAADY4iz3AAAAEUlEQVR42mNkwAkYR6UolgIACvgADsuK6xYAAAAASUVORK5CYII="; pub fn clean_url(url: Url) -> Url { - let mut url = url.clone(); + let mut url = url; // Clear fragment (if any) url.set_fragment(None); @@ -19,7 +19,7 @@ pub fn clean_url(url: Url) -> Url { pub fn create_data_url(media_type: &str, charset: &str, data: &[u8], final_asset_url: &Url) -> Url { // TODO: move this block out of this function let media_type: String = if media_type.is_empty() { - detect_media_type(data, &final_asset_url) + detect_media_type(data, final_asset_url) } else { media_type.to_string() }; @@ -39,13 +39,11 @@ pub fn create_data_url(media_type: &str, charset: &str, data: &[u8], final_asset } pub fn is_url_and_has_protocol(input: &str) -> bool { - match Url::parse(&input) { + match Url::parse(input) { Ok(parsed_url) => { - return parsed_url.scheme().len() > 0; - } - Err(_) => { - return false; + return !parsed_url.scheme().is_empty(); } + Err(_) => false, } } @@ -72,7 +70,7 @@ pub fn parse_data_url(url: &Url) -> (String, String, Vec) { } pub fn resolve_url(from: &Url, to: &str) -> Url { - match Url::parse(&to) { + match Url::parse(to) { Ok(parsed_url) => parsed_url, Err(_) => match from.join(to) { Ok(joined) => joined, diff --git a/src/utils.rs b/src/utils.rs index 621a083..e3804da 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,15 +1,18 @@ +use once_cell::sync::Lazy; use reqwest::blocking::Client; -use reqwest::header::CONTENT_TYPE; +use reqwest::header::{HeaderMap, HeaderValue, CONTENT_TYPE, USER_AGENT}; use std::collections::HashMap; use std::fs; use std::path::{Path, PathBuf}; +use std::sync::Mutex; +use std::time::Duration; use url::Url; -use crate::opts::Options; +use crate::opts::{Options, OPTIONS}; use crate::url::{clean_url, parse_data_url}; -const ANSI_COLOR_RED: &'static str = "\x1b[31m"; -const ANSI_COLOR_RESET: &'static str = "\x1b[0m"; +const ANSI_COLOR_RED: &str = "\x1b[31m"; +const ANSI_COLOR_RESET: &str = "\x1b[0m"; const MAGIC: [[&[u8]; 2]; 18] = [ // Image [b"GIF87a", b"image/gif"], @@ -39,6 +42,31 @@ const PLAINTEXT_MEDIA_TYPES: &[&str] = &[ "image/svg+xml", ]; +static CLIENT: Lazy = Lazy::new(|| { + let mut header_map = HeaderMap::new(); + if let Some(user_agent) = &OPTIONS.user_agent { + header_map.insert( + USER_AGENT, + HeaderValue::from_str(user_agent).expect("Invalid User-Agent header specified"), + ); + } + + if OPTIONS.timeout > 0 { + Client::builder().timeout(Duration::from_secs(OPTIONS.timeout)) + } else { + Client::builder() + } + .danger_accept_invalid_certs(OPTIONS.insecure) + .default_headers(header_map) + .build() + .expect("Failed to initialize HTTP client") +}); + +static CACHE: Lazy>>> = Lazy::new(|| { + let mut m = HashMap::new(); + Mutex::new(m) +}); + pub fn detect_media_type(data: &[u8], url: &Url) -> String { // At first attempt to read file's header for magic_item in MAGIC.iter() { @@ -93,7 +121,7 @@ pub fn detect_media_type_by_file_name(filename: &str) -> String { } pub fn domain_is_within_domain(domain: &str, domain_to_match_against: &str) -> bool { - if domain_to_match_against.len() == 0 { + if domain_to_match_against.is_empty() { return false; } @@ -101,12 +129,12 @@ pub fn domain_is_within_domain(domain: &str, domain_to_match_against: &str) -> b return true; } - let domain_partials: Vec<&str> = domain.trim_end_matches(".").rsplit(".").collect(); + let domain_partials: Vec<&str> = domain.trim_end_matches('.').rsplit('.').collect(); let domain_to_match_against_partials: Vec<&str> = domain_to_match_against - .trim_end_matches(".") - .rsplit(".") + .trim_end_matches('.') + .rsplit('.') .collect(); - let domain_to_match_against_starts_with_a_dot = domain_to_match_against.starts_with("."); + let domain_to_match_against_starts_with_a_dot = domain_to_match_against.starts_with('.'); let mut i: usize = 0; let l: usize = std::cmp::max( @@ -137,7 +165,7 @@ pub fn domain_is_within_domain(domain: &str, domain_to_match_against: &str) -> b let parts_match = domain_to_match_against_partial.eq_ignore_ascii_case(domain_partial); - if !parts_match && domain_to_match_against_partial.len() != 0 { + if !parts_match && !domain_to_match_against_partial.is_empty() { ok = false; break; } @@ -172,29 +200,22 @@ pub fn parse_content_type(content_type: &str) -> (String, String, bool) { // Parse meta data let content_type_items: Vec<&str> = content_type.split(';').collect(); - let mut i: i8 = 0; - for item in &content_type_items { + for (i, item) in (0_i8..).zip(content_type_items.iter()) { if i == 0 { - if item.trim().len() > 0 { + if !item.trim().is_empty() { media_type = item.trim().to_string(); } - } else { - if item.trim().eq_ignore_ascii_case("base64") { - is_base64 = true; - } else if item.trim().starts_with("charset=") { - charset = item.trim().chars().skip(8).collect(); - } + } else if item.trim().eq_ignore_ascii_case("base64") { + is_base64 = true; + } else if item.trim().starts_with("charset=") { + charset = item.trim().chars().skip(8).collect(); } - - i += 1; } (media_type, charset, is_base64) } pub fn retrieve_asset( - cache: &mut HashMap>, - client: &Client, parent_url: &Url, url: &Url, options: &Options, @@ -208,11 +229,10 @@ pub fn retrieve_asset( if parent_url.scheme() != "file" { if !options.silent { eprintln!( - "{}{}{} ({}){}", + "{}{}{} (Security Error){}", indent(depth).as_str(), if options.no_color { "" } else { ANSI_COLOR_RED }, &url, - "Security Error", if options.no_color { "" } else { @@ -221,10 +241,10 @@ pub fn retrieve_asset( ); } // Provoke error - client.get("").send()?; + CLIENT.get("").send()?; } - let path_buf: PathBuf = url.to_file_path().unwrap().clone(); + let path_buf: PathBuf = url.to_file_path().unwrap(); let path: &Path = path_buf.as_path(); if path.exists() { if path.is_dir() { @@ -243,20 +263,16 @@ pub fn retrieve_asset( } // Provoke error - Err(client.get("").send().unwrap_err()) + Err(CLIENT.get("").send().unwrap_err()) } else { if !options.silent { eprintln!("{}{}", indent(depth).as_str(), &url); } - let file_blob: Vec = fs::read(&path).expect("Unable to read file"); + let file_blob: Vec = fs::read(path).expect("Unable to read file"); + let file_type = detect_media_type(&file_blob, url); - Ok(( - file_blob.clone(), - url.clone(), - detect_media_type(&file_blob, url), - "".to_string(), - )) + Ok((file_blob, url.clone(), file_type, "".to_string())) } } else { if !options.silent { @@ -274,19 +290,19 @@ pub fn retrieve_asset( } // Provoke error - Err(client.get("").send().unwrap_err()) + Err(CLIENT.get("").send().unwrap_err()) } } else { let cache_key: String = clean_url(url.clone()).as_str().to_string(); - if cache.contains_key(&cache_key) { + if CACHE.lock().unwrap().contains_key(&cache_key) { // URL is in cache, we get and return it if !options.silent { eprintln!("{}{} (from cache)", indent(depth).as_str(), &url); } Ok(( - cache.get(&cache_key).unwrap().to_vec(), + CACHE.lock().unwrap().get(&cache_key).unwrap().to_vec(), url.clone(), "".to_string(), "".to_string(), @@ -295,16 +311,16 @@ pub fn retrieve_asset( if let Some(domains) = &options.domains { let domain_matches = domains .iter() - .any(|d| domain_is_within_domain(url.host_str().unwrap(), &d.trim())); + .any(|d| domain_is_within_domain(url.host_str().unwrap(), d.trim())); if (options.blacklist_domains && domain_matches) || (!options.blacklist_domains && !domain_matches) { - return Err(client.get("").send().unwrap_err()); + return Err(CLIENT.get("").send().unwrap_err()); } } // URL not in cache, we retrieve the file - match client.get(url.as_str()).send() { + match CLIENT.get(url.as_str()).send() { Ok(response) => { if !options.ignore_errors && response.status() != reqwest::StatusCode::OK { if !options.silent { @@ -322,7 +338,7 @@ pub fn retrieve_asset( ); } // Provoke error - return Err(client.get("").send().unwrap_err()); + return Err(CLIENT.get("").send().unwrap_err()); } let response_url: Url = response.url().clone(); @@ -344,7 +360,7 @@ pub fn retrieve_asset( .and_then(|header| header.to_str().ok()) .unwrap_or(""); - let (media_type, charset, _is_base64) = parse_content_type(&content_type); + let (media_type, charset, _is_base64) = parse_content_type(content_type); // Convert response into a byte array let mut data: Vec = vec![]; @@ -370,7 +386,7 @@ pub fn retrieve_asset( } // Add retrieved resource to cache - cache.insert(new_cache_key, data.clone()); + CACHE.lock().unwrap().insert(new_cache_key, data.clone()); // Return Ok((data, response_url, media_type, charset)) @@ -391,7 +407,7 @@ pub fn retrieve_asset( ); } - Err(client.get("").send().unwrap_err()) + Err(CLIENT.get("").send().unwrap_err()) } } } diff --git a/tests/cli/basic.rs b/tests/cli/basic.rs index 943c906..7393ca7 100644 --- a/tests/cli/basic.rs +++ b/tests/cli/basic.rs @@ -95,8 +95,8 @@ mod passing { {file_url_css}\n \ {file_url_css}\n\ ", - file_url_html = Url::from_file_path(fs::canonicalize(&path_html).unwrap()).unwrap(), - file_url_css = Url::from_file_path(fs::canonicalize(&path_css).unwrap()).unwrap(), + file_url_html = Url::from_file_path(fs::canonicalize(path_html).unwrap()).unwrap(), + file_url_css = Url::from_file_path(fs::canonicalize(path_css).unwrap()).unwrap(), ) ); diff --git a/tests/cli/local_files.rs b/tests/cli/local_files.rs index fbdc7e9..27bcbb4 100644 --- a/tests/cli/local_files.rs +++ b/tests/cli/local_files.rs @@ -23,7 +23,7 @@ mod passing { .unwrap() .to_str() .unwrap() - .replace("\\", "/"); + .replace('\\', "/"); let out = cmd .arg("-M") .arg(format!( @@ -88,7 +88,7 @@ mod passing { String::from_utf8_lossy(&out.stderr), format!( "{file_url_html}\n", - file_url_html = Url::from_file_path(fs::canonicalize(&path_html).unwrap()).unwrap(), + file_url_html = Url::from_file_path(fs::canonicalize(path_html).unwrap()).unwrap(), ) ); @@ -124,7 +124,7 @@ mod passing { .unwrap() .to_str() .unwrap() - .replace("\\", "/"); + .replace('\\', "/"); let file_url_protocol: &str = if cfg!(windows) { "file:///" } else { "file://" }; let out = cmd .arg("-M") @@ -188,8 +188,8 @@ mod passing { {file_url_html}\n \ {file_url_svg}\n\ ", - file_url_html = Url::from_file_path(fs::canonicalize(&path_html).unwrap()).unwrap(), - file_url_svg = Url::from_file_path(fs::canonicalize(&path_svg).unwrap()).unwrap(), + file_url_html = Url::from_file_path(fs::canonicalize(path_html).unwrap()).unwrap(), + file_url_svg = Url::from_file_path(fs::canonicalize(path_svg).unwrap()).unwrap(), ) ); @@ -210,24 +210,16 @@ mod passing { .unwrap() .to_str() .unwrap() - .replace("\\", "/"); + .replace('\\', "/"); let file_url_protocol: &str = if cfg!(windows) { "file:///" } else { "file://" }; let out = cmd .arg("-M") .arg("-i") - .arg(if cfg!(windows) { - format!( - "{file}{cwd}/tests/_data_/integrity/index.html", - file = file_url_protocol, - cwd = cwd_normalized, - ) - } else { - format!( - "{file}{cwd}/tests/_data_/integrity/index.html", - file = file_url_protocol, - cwd = cwd_normalized, - ) - }) + .arg(format!( + "{file}{cwd}/tests/_data_/integrity/index.html", + file = file_url_protocol, + cwd = cwd_normalized, + )) .output() .unwrap(); diff --git a/tests/cli/noscript.rs b/tests/cli/noscript.rs index 9195cc1..dc13467 100644 --- a/tests/cli/noscript.rs +++ b/tests/cli/noscript.rs @@ -30,8 +30,8 @@ mod passing { {file_url_html}\n \ {file_url_svg}\n\ ", - file_url_html = Url::from_file_path(fs::canonicalize(&path_html).unwrap()).unwrap(), - file_url_svg = Url::from_file_path(fs::canonicalize(&path_svg).unwrap()).unwrap(), + file_url_html = Url::from_file_path(fs::canonicalize(path_html).unwrap()).unwrap(), + file_url_svg = Url::from_file_path(fs::canonicalize(path_svg).unwrap()).unwrap(), ) ); @@ -61,8 +61,8 @@ mod passing { {file_url_html}\n \ {file_url_svg}\n\ ", - file_url_html = Url::from_file_path(fs::canonicalize(&path_html).unwrap()).unwrap(), - file_url_svg = Url::from_file_path(fs::canonicalize(&path_svg).unwrap()).unwrap(), + file_url_html = Url::from_file_path(fs::canonicalize(path_html).unwrap()).unwrap(), + file_url_svg = Url::from_file_path(fs::canonicalize(path_svg).unwrap()).unwrap(), ) ); @@ -92,8 +92,8 @@ mod passing { {file_url_html}\n \ {file_url_svg}\n\ ", - file_url_html = Url::from_file_path(fs::canonicalize(&path_html).unwrap()).unwrap(), - file_url_svg = Url::from_file_path(fs::canonicalize(&path_svg).unwrap()).unwrap(), + file_url_html = Url::from_file_path(fs::canonicalize(path_html).unwrap()).unwrap(), + file_url_svg = Url::from_file_path(fs::canonicalize(path_svg).unwrap()).unwrap(), ) ); @@ -123,8 +123,8 @@ mod passing { {file_url_html}\n \ {file_url_svg}\n\ ", - file_url_html = Url::from_file_path(fs::canonicalize(&path_html).unwrap()).unwrap(), - file_url_svg = Url::from_file_path(fs::canonicalize(&path_svg).unwrap()).unwrap(), + file_url_html = Url::from_file_path(fs::canonicalize(path_html).unwrap()).unwrap(), + file_url_svg = Url::from_file_path(fs::canonicalize(path_svg).unwrap()).unwrap(), ) ); diff --git a/tests/cli/unusual_encodings.rs b/tests/cli/unusual_encodings.rs index 2a68c37..222ad96 100644 --- a/tests/cli/unusual_encodings.rs +++ b/tests/cli/unusual_encodings.rs @@ -16,7 +16,7 @@ mod passing { #[test] fn properly_save_document_with_gb2312() { let cwd = env::current_dir().unwrap(); - let cwd_normalized: String = cwd.to_str().unwrap().replace("\\", "/"); + let cwd_normalized: String = cwd.to_str().unwrap().replace('\\', "/"); let mut cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")).unwrap(); let out = cmd .arg("-M") @@ -111,7 +111,7 @@ mod passing { #[test] fn properly_save_document_with_gb2312_custom_charset() { let cwd = env::current_dir().unwrap(); - let cwd_normalized: String = cwd.to_str().unwrap().replace("\\", "/"); + let cwd_normalized: String = cwd.to_str().unwrap().replace('\\', "/"); let mut cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")).unwrap(); let out = cmd .arg("-M") @@ -198,7 +198,7 @@ mod failing { #[test] fn change_iso88591_to_utf8_to_properly_display_html_entities() { let cwd = env::current_dir().unwrap(); - let cwd_normalized: String = cwd.to_str().unwrap().replace("\\", "/"); + let cwd_normalized: String = cwd.to_str().unwrap().replace('\\', "/"); let mut cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")).unwrap(); let out = cmd .arg("-M") diff --git a/tests/css/embed_css.rs b/tests/css/embed_css.rs index b8e2a97..10c3143 100644 --- a/tests/css/embed_css.rs +++ b/tests/css/embed_css.rs @@ -7,9 +7,7 @@ #[cfg(test)] mod passing { - use reqwest::blocking::Client; use reqwest::Url; - use std::collections::HashMap; use monolith::css; use monolith::opts::Options; @@ -17,34 +15,25 @@ mod passing { #[test] fn empty_input() { - let cache = &mut HashMap::new(); - let client = Client::new(); let document_url: Url = Url::parse("data:,").unwrap(); let options = Options::default(); - assert_eq!( - css::embed_css(cache, &client, &document_url, "", &options, 0), - "" - ); + assert_eq!(css::embed_css(&document_url, "", &options, 0), ""); } #[test] fn trim_if_empty() { - let cache = &mut HashMap::new(); - let client = Client::new(); let document_url: Url = Url::parse("https://doesntmatter.local/").unwrap(); let options = Options::default(); assert_eq!( - css::embed_css(cache, &client, &document_url, "\t \t ", &options, 0,), + css::embed_css(&document_url, "\t \t ", &options, 0,), "" ); } #[test] fn style_exclude_unquoted_images() { - let cache = &mut HashMap::new(); - let client = Client::new(); let document_url: Url = Url::parse("https://doesntmatter.local/").unwrap(); let mut options = Options::default(); options.no_images = true; @@ -59,7 +48,7 @@ mod passing { height: calc(100vh - 10pt)"; assert_eq!( - css::embed_css(cache, &client, &document_url, &STYLE, &options, 0,), + css::embed_css(&document_url, STYLE, &options, 0,), format!( "/* border: none;*/\ background-image: url(\"{empty_image}\"); \ @@ -75,8 +64,6 @@ mod passing { #[test] fn style_exclude_single_quoted_images() { - let cache = &mut HashMap::new(); - let client = Client::new(); let document_url: Url = Url::parse("data:,").unwrap(); let mut options = Options::default(); options.no_images = true; @@ -91,7 +78,7 @@ mod passing { height: calc(100vh - 10pt)"; assert_eq!( - css::embed_css(cache, &client, &document_url, &STYLE, &options, 0), + css::embed_css(&document_url, STYLE, &options, 0), format!( "/* border: none;*/\ background-image: url(\"{empty_image}\"); \ @@ -107,8 +94,6 @@ mod passing { #[test] fn style_block() { - let cache = &mut HashMap::new(); - let client = Client::new(); let document_url: Url = Url::parse("file:///").unwrap(); let mut options = Options::default(); options.silent = true; @@ -121,16 +106,11 @@ mod passing { \n\ html > body {}"; - assert_eq!( - css::embed_css(cache, &client, &document_url, &CSS, &options, 0), - CSS - ); + assert_eq!(css::embed_css(&document_url, CSS, &options, 0), CSS); } #[test] fn attribute_selectors() { - let cache = &mut HashMap::new(); - let client = Client::new(); let document_url: Url = Url::parse("https://doesntmatter.local/").unwrap(); let mut options = Options::default(); options.silent = true; @@ -165,16 +145,11 @@ mod passing { } "; - assert_eq!( - css::embed_css(cache, &client, &document_url, &CSS, &options, 0), - CSS - ); + assert_eq!(css::embed_css(&document_url, CSS, &options, 0), CSS); } #[test] fn import_string() { - let cache = &mut HashMap::new(); - let client = Client::new(); let document_url: Url = Url::parse("https://doesntmatter.local/").unwrap(); let mut options = Options::default(); options.silent = true; @@ -188,7 +163,7 @@ mod passing { "; assert_eq!( - css::embed_css(cache, &client, &document_url, &CSS, &options, 0,), + css::embed_css(&document_url, CSS, &options, 0,), "\ @charset \"UTF-8\";\n\ \n\ @@ -201,8 +176,6 @@ mod passing { #[test] fn hash_urls() { - let cache = &mut HashMap::new(); - let client = Client::new(); let document_url: Url = Url::parse("https://doesntmatter.local/").unwrap(); let mut options = Options::default(); options.silent = true; @@ -217,16 +190,11 @@ mod passing { }\n\ "; - assert_eq!( - css::embed_css(cache, &client, &document_url, &CSS, &options, 0,), - CSS - ); + assert_eq!(css::embed_css(&document_url, CSS, &options, 0,), CSS); } #[test] fn transform_percentages_and_degrees() { - let cache = &mut HashMap::new(); - let client = Client::new(); let document_url: Url = Url::parse("https://doesntmatter.local/").unwrap(); let mut options = Options::default(); options.silent = true; @@ -239,16 +207,11 @@ mod passing { }\n\ "; - assert_eq!( - css::embed_css(cache, &client, &document_url, &CSS, &options, 0,), - CSS - ); + assert_eq!(css::embed_css(&document_url, CSS, &options, 0,), CSS); } #[test] fn unusual_indents() { - let cache = &mut HashMap::new(); - let client = Client::new(); let document_url: Url = Url::parse("https://doesntmatter.local/").unwrap(); let mut options = Options::default(); options.silent = true; @@ -263,16 +226,11 @@ mod passing { }\n\ "; - assert_eq!( - css::embed_css(cache, &client, &document_url, &CSS, &options, 0,), - CSS - ); + assert_eq!(css::embed_css(&document_url, CSS, &options, 0,), CSS); } #[test] fn exclude_fonts() { - let cache = &mut HashMap::new(); - let client = Client::new(); let document_url: Url = Url::parse("https://doesntmatter.local/").unwrap(); let mut options = Options::default(); options.no_fonts = true; @@ -311,16 +269,11 @@ mod passing { }\n\ "; - assert_eq!( - css::embed_css(cache, &client, &document_url, &CSS, &options, 0,), - CSS_OUT - ); + assert_eq!(css::embed_css(&document_url, CSS, &options, 0,), CSS_OUT); } #[test] fn content() { - let cache = &mut HashMap::new(); - let client = Client::new(); let document_url: Url = Url::parse("data:,").unwrap(); let mut options = Options::default(); options.silent = true; @@ -336,16 +289,11 @@ mod passing { white-space: pre }\n\ "; - assert_eq!( - css::embed_css(cache, &client, &document_url, &CSS, &options, 0,), - CSS_OUT - ); + assert_eq!(css::embed_css(&document_url, CSS, &options, 0,), CSS_OUT); } #[test] fn ie_css_hack() { - let cache = &mut HashMap::new(); - let client = Client::new(); let document_url: Url = Url::parse("data:,").unwrap(); let mut options = Options::default(); options.silent = true; @@ -363,9 +311,6 @@ mod passing { }\n\ "; - assert_eq!( - css::embed_css(cache, &client, &document_url, &CSS, &options, 0,), - CSS_OUT - ); + assert_eq!(css::embed_css(&document_url, CSS, &options, 0,), CSS_OUT); } } diff --git a/tests/html/add_favicon.rs b/tests/html/add_favicon.rs index a276aca..0acecfb 100644 --- a/tests/html/add_favicon.rs +++ b/tests/html/add_favicon.rs @@ -9,17 +9,23 @@ mod passing { use html5ever::serialize::{serialize, SerializeOpts}; + use markup5ever_rcdom::SerializableHandle; use monolith::html; #[test] fn basic() { let html = "
text
"; - let mut dom = html::html_to_dom(&html.as_bytes().to_vec(), "".to_string()); + let mut dom = html::html_to_dom(html.as_bytes(), "".to_string()); dom = html::add_favicon(&dom.document, "I_AM_A_FAVICON_DATA_URL".to_string()); let mut buf: Vec = Vec::new(); - serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap(); + serialize( + &mut buf, + &SerializableHandle::from(dom.document), + SerializeOpts::default(), + ) + .unwrap(); assert_eq!( buf.iter().map(|&c| c as char).collect::(), diff --git a/tests/html/embed_srcset.rs b/tests/html/embed_srcset.rs index f130c19..54837c3 100644 --- a/tests/html/embed_srcset.rs +++ b/tests/html/embed_srcset.rs @@ -7,9 +7,7 @@ #[cfg(test)] mod passing { - use reqwest::blocking::Client; use reqwest::Url; - use std::collections::HashMap; use monolith::html; use monolith::opts::Options; @@ -17,20 +15,12 @@ mod passing { #[test] fn small_medium_large() { - let cache = &mut HashMap::new(); - let client = Client::new(); let srcset_value = "small.png 1x, medium.png 1.5x, large.png 2x"; let mut options = Options::default(); options.no_images = true; options.silent = true; - let embedded_css = html::embed_srcset( - cache, - &client, - &Url::parse("data:,").unwrap(), - &srcset_value, - &options, - 0, - ); + let embedded_css = + html::embed_srcset(&Url::parse("data:,").unwrap(), srcset_value, &options, 0); assert_eq!( embedded_css, @@ -43,20 +33,12 @@ mod passing { #[test] fn small_medium_only_medium_has_scale() { - let cache = &mut HashMap::new(); - let client = Client::new(); let srcset_value = "small.png, medium.png 1.5x"; let mut options = Options::default(); options.no_images = true; options.silent = true; - let embedded_css = html::embed_srcset( - cache, - &client, - &Url::parse("data:,").unwrap(), - &srcset_value, - &options, - 0, - ); + let embedded_css = + html::embed_srcset(&Url::parse("data:,").unwrap(), srcset_value, &options, 0); assert_eq!( embedded_css, @@ -66,20 +48,12 @@ mod passing { #[test] fn commas_within_file_names() { - let cache = &mut HashMap::new(); - let client = Client::new(); let srcset_value = "small,s.png 1x, large,l.png 2x"; let mut options = Options::default(); options.no_images = true; options.silent = true; - let embedded_css = html::embed_srcset( - cache, - &client, - &Url::parse("data:,").unwrap(), - &srcset_value, - &options, - 0, - ); + let embedded_css = + html::embed_srcset(&Url::parse("data:,").unwrap(), srcset_value, &options, 0); assert_eq!( embedded_css, @@ -89,20 +63,12 @@ mod passing { #[test] fn tabs_and_newlines_after_commas() { - let cache = &mut HashMap::new(); - let client = Client::new(); let srcset_value = "small,s.png 1x,\nmedium,m.png 2x,\nlarge,l.png 3x"; let mut options = Options::default(); options.no_images = true; options.silent = true; - let embedded_css = html::embed_srcset( - cache, - &client, - &Url::parse("data:,").unwrap(), - &srcset_value, - &options, - 0, - ); + let embedded_css = + html::embed_srcset(&Url::parse("data:,").unwrap(), srcset_value, &options, 0); assert_eq!( embedded_css, @@ -123,9 +89,7 @@ mod passing { #[cfg(test)] mod failing { - use reqwest::blocking::Client; use reqwest::Url; - use std::collections::HashMap; use monolith::html; use monolith::opts::Options; @@ -133,20 +97,12 @@ mod failing { #[test] fn trailing_comma() { - let cache = &mut HashMap::new(); - let client = Client::new(); let srcset_value = "small.png 1x, large.png 2x,"; let mut options = Options::default(); options.no_images = true; options.silent = true; - let embedded_css = html::embed_srcset( - cache, - &client, - &Url::parse("data:,").unwrap(), - &srcset_value, - &options, - 0, - ); + let embedded_css = + html::embed_srcset(&Url::parse("data:,").unwrap(), srcset_value, &options, 0); assert_eq!( embedded_css, diff --git a/tests/html/get_node_attr.rs b/tests/html/get_node_attr.rs index 2be351c..a89046d 100644 --- a/tests/html/get_node_attr.rs +++ b/tests/html/get_node_attr.rs @@ -7,14 +7,14 @@ #[cfg(test)] mod passing { - use html5ever::rcdom::{Handle, NodeData}; + use markup5ever_rcdom::{Handle, NodeData}; use monolith::html; #[test] fn div_two_style_attributes() { let html = "
"; - let dom = html::html_to_dom(&html.as_bytes().to_vec(), "".to_string()); + let dom = html::html_to_dom(&html.as_bytes(), "".to_string()); let mut count = 0; fn test_walk(node: &Handle, i: &mut i8) { diff --git a/tests/html/get_node_name.rs b/tests/html/get_node_name.rs index 7019206..ed79bec 100644 --- a/tests/html/get_node_name.rs +++ b/tests/html/get_node_name.rs @@ -7,7 +7,7 @@ #[cfg(test)] mod passing { - use html5ever::rcdom::{Handle, NodeData}; + use markup5ever_rcdom::{Handle, NodeData}; use monolith::html; diff --git a/tests/html/set_node_attr.rs b/tests/html/set_node_attr.rs index 120e44d..114de70 100644 --- a/tests/html/set_node_attr.rs +++ b/tests/html/set_node_attr.rs @@ -7,7 +7,7 @@ #[cfg(test)] mod passing { - use html5ever::rcdom::{Handle, NodeData}; + use markup5ever_rcdom::{Handle, NodeData}; use monolith::html; diff --git a/tests/html/walk_and_embed_assets.rs b/tests/html/walk_and_embed_assets.rs index 5db25a5..2babfe1 100644 --- a/tests/html/walk_and_embed_assets.rs +++ b/tests/html/walk_and_embed_assets.rs @@ -8,8 +8,7 @@ #[cfg(test)] mod passing { use html5ever::serialize::{serialize, SerializeOpts}; - use reqwest::blocking::Client; - use std::collections::HashMap; + use markup5ever_rcdom::SerializableHandle; use url::Url; use monolith::html; @@ -18,8 +17,6 @@ mod passing { #[test] fn basic() { - let cache = &mut HashMap::new(); - let html: &str = "

"; let dom = html::html_to_dom(&html.as_bytes().to_vec(), "".to_string()); let url: Url = Url::parse("http://localhost").unwrap(); @@ -27,12 +24,15 @@ mod passing { let mut options = Options::default(); options.silent = true; - let client = Client::new(); - - html::walk_and_embed_assets(cache, &client, &url, &dom.document, &options, 0); + html::walk_and_embed_assets(&url, &dom.document, &options, 0); let mut buf: Vec = Vec::new(); - serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap(); + serialize( + &mut buf, + &SerializableHandle::from(dom.document), + SerializeOpts::default(), + ) + .unwrap(); assert_eq!( buf.iter().map(|&c| c as char).collect::(), @@ -45,17 +45,19 @@ mod passing { let html = "

"; let dom = html::html_to_dom(&html.as_bytes().to_vec(), "".to_string()); let url: Url = Url::parse("http://localhost").unwrap(); - let cache = &mut HashMap::new(); let mut options = Options::default(); options.silent = true; - let client = Client::new(); - - html::walk_and_embed_assets(cache, &client, &url, &dom.document, &options, 0); + html::walk_and_embed_assets(&url, &dom.document, &options, 0); let mut buf: Vec = Vec::new(); - serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap(); + serialize( + &mut buf, + &SerializableHandle::from(dom.document), + SerializeOpts::default(), + ) + .unwrap(); assert_eq!( buf.iter().map(|&c| c as char).collect::(), @@ -68,17 +70,19 @@ mod passing { let html = ""; let dom = html::html_to_dom(&html.as_bytes().to_vec(), "".to_string()); let url: Url = Url::parse("http://localhost").unwrap(); - let cache = &mut HashMap::new(); let mut options = Options::default(); options.silent = true; - let client = Client::new(); - - html::walk_and_embed_assets(cache, &client, &url, &dom.document, &options, 0); + html::walk_and_embed_assets(&url, &dom.document, &options, 0); let mut buf: Vec = Vec::new(); - serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap(); + serialize( + &mut buf, + &SerializableHandle::from(dom.document), + SerializeOpts::default(), + ) + .unwrap(); assert_eq!( buf.iter().map(|&c| c as char).collect::(), @@ -96,18 +100,20 @@ mod passing { "; let dom = html::html_to_dom(&html.as_bytes().to_vec(), "".to_string()); let url: Url = Url::parse("http://localhost").unwrap(); - let cache = &mut HashMap::new(); 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, &options, 0); + html::walk_and_embed_assets(&url, &dom.document, &options, 0); let mut buf: Vec = Vec::new(); - serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap(); + serialize( + &mut buf, + &SerializableHandle::from(dom.document), + SerializeOpts::default(), + ) + .unwrap(); assert_eq!( buf.iter().map(|&c| c as char).collect::(), @@ -132,18 +138,20 @@ mod passing {
"; let dom = html::html_to_dom(&html.as_bytes().to_vec(), "".to_string()); let url: Url = Url::parse("http://localhost").unwrap(); - let cache = &mut HashMap::new(); 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, &options, 0); + html::walk_and_embed_assets(&url, &dom.document, &options, 0); let mut buf: Vec = Vec::new(); - serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap(); + serialize( + &mut buf, + &SerializableHandle::from(dom.document), + SerializeOpts::default(), + ) + .unwrap(); assert_eq!( buf.iter().map(|&c| c as char).collect::(), @@ -169,18 +177,20 @@ mod passing { ""; let dom = html::html_to_dom(&html.as_bytes().to_vec(), "".to_string()); let url: Url = Url::parse("http://localhost").unwrap(); - let cache = &mut HashMap::new(); 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, &options, 0); + html::walk_and_embed_assets(&url, &dom.document, &options, 0); let mut buf: Vec = Vec::new(); - serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap(); + serialize( + &mut buf, + &SerializableHandle::from(dom.document), + SerializeOpts::default(), + ) + .unwrap(); assert_eq!( buf.iter().map(|&c| c as char).collect::(), @@ -193,18 +203,20 @@ mod passing { let html = ""; let dom = html::html_to_dom(&html.as_bytes().to_vec(), "".to_string()); let url: Url = Url::parse("http://localhost").unwrap(); - let cache = &mut HashMap::new(); 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, &options, 0); + html::walk_and_embed_assets(&url, &dom.document, &options, 0); let mut buf: Vec = Vec::new(); - serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap(); + serialize( + &mut buf, + &SerializableHandle::from(dom.document), + SerializeOpts::default(), + ) + .unwrap(); assert_eq!( buf.iter().map(|&c| c as char).collect::(), @@ -225,18 +237,20 @@ mod passing { let html = ""; let dom = html::html_to_dom(&html.as_bytes().to_vec(), "".to_string()); let url: Url = Url::parse("http://localhost").unwrap(); - let cache = &mut HashMap::new(); 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, &options, 0); + html::walk_and_embed_assets(&url, &dom.document, &options, 0); let mut buf: Vec = Vec::new(); - serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap(); + serialize( + &mut buf, + &SerializableHandle::from(dom.document), + SerializeOpts::default(), + ) + .unwrap(); assert_eq!( buf.iter().map(|&c| c as char).collect::(), @@ -261,18 +275,20 @@ mod passing { "; let dom = html::html_to_dom(&html.as_bytes().to_vec(), "".to_string()); let url: Url = Url::parse("http://localhost").unwrap(); - let cache = &mut HashMap::new(); 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, &options, 0); + html::walk_and_embed_assets(&url, &dom.document, &options, 0); let mut buf: Vec = Vec::new(); - serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap(); + serialize( + &mut buf, + &SerializableHandle::from(dom.document), + SerializeOpts::default(), + ) + .unwrap(); assert_eq!( buf.iter().map(|&c| c as char).collect::(), @@ -296,17 +312,19 @@ mod passing { "; let dom = html::html_to_dom(&html.as_bytes().to_vec(), "".to_string()); let url: Url = Url::parse("http://localhost").unwrap(); - let cache = &mut HashMap::new(); let mut options = Options::default(); options.silent = true; - let client = Client::new(); - - html::walk_and_embed_assets(cache, &client, &url, &dom.document, &options, 0); + html::walk_and_embed_assets(&url, &dom.document, &options, 0); let mut buf: Vec = Vec::new(); - serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap(); + serialize( + &mut buf, + &SerializableHandle::from(dom.document), + SerializeOpts::default(), + ) + .unwrap(); assert_eq!( buf.iter().map(|&c| c as char).collect::(), @@ -331,19 +349,21 @@ mod passing { "; let dom = html::html_to_dom(&html.as_bytes().to_vec(), "".to_string()); let url: Url = Url::parse("http://localhost").unwrap(); - let cache = &mut HashMap::new(); let mut options = Options::default(); options.no_css = true; options.no_js = true; options.silent = true; - let client = Client::new(); - - html::walk_and_embed_assets(cache, &client, &url, &dom.document, &options, 0); + html::walk_and_embed_assets(&url, &dom.document, &options, 0); let mut buf: Vec = Vec::new(); - serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap(); + serialize( + &mut buf, + &SerializableHandle::from(dom.document), + SerializeOpts::default(), + ) + .unwrap(); assert_eq!( buf.iter().map(|&c| c as char).collect::(), @@ -369,19 +389,21 @@ mod passing { "; let dom = html::html_to_dom(&html.as_bytes().to_vec(), "".to_string()); let url: Url = Url::parse("http://localhost").unwrap(); - let cache = &mut HashMap::new(); let mut options = Options::default(); options.no_css = true; options.no_js = true; options.silent = true; - let client = Client::new(); - - html::walk_and_embed_assets(cache, &client, &url, &dom.document, &options, 0); + html::walk_and_embed_assets(&url, &dom.document, &options, 0); let mut buf: Vec = Vec::new(); - serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap(); + serialize( + &mut buf, + &SerializableHandle::from(dom.document), + SerializeOpts::default(), + ) + .unwrap(); assert_eq!( buf.iter().map(|&c| c as char).collect::(), @@ -413,7 +435,6 @@ mod passing { "; let dom = html::html_to_dom(&html.as_bytes().to_vec(), "".to_string()); let url: Url = Url::parse("http://localhost").unwrap(); - let cache = &mut HashMap::new(); let mut options = Options::default(); options.no_css = true; @@ -422,12 +443,15 @@ mod passing { options.no_images = true; options.silent = true; - let client = Client::new(); - - html::walk_and_embed_assets(cache, &client, &url, &dom.document, &options, 0); + html::walk_and_embed_assets(&url, &dom.document, &options, 0); let mut buf: Vec = Vec::new(); - serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap(); + serialize( + &mut buf, + &SerializableHandle::from(dom.document), + SerializeOpts::default(), + ) + .unwrap(); assert_eq!( buf.iter().map(|&c| c as char).collect::(), @@ -455,18 +479,20 @@ mod passing { "; let dom = html::html_to_dom(&html.as_bytes().to_vec(), "".to_string()); let url: Url = Url::parse("http://localhost").unwrap(); - let cache = &mut HashMap::new(); 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, &options, 0); + html::walk_and_embed_assets(&url, &dom.document, &options, 0); let mut buf: Vec = Vec::new(); - serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap(); + serialize( + &mut buf, + &SerializableHandle::from(dom.document), + SerializeOpts::default(), + ) + .unwrap(); assert_eq!( buf.iter().map(|&c| c as char).collect::(), @@ -491,17 +517,19 @@ mod passing { let html = ""; let dom = html::html_to_dom(&html.as_bytes().to_vec(), "".to_string()); let url: Url = Url::parse("http://localhost").unwrap(); - let cache = &mut HashMap::new(); let mut options = Options::default(); options.silent = true; - let client = Client::new(); - - html::walk_and_embed_assets(cache, &client, &url, &dom.document, &options, 0); + html::walk_and_embed_assets(&url, &dom.document, &options, 0); let mut buf: Vec = Vec::new(); - serialize(&mut buf, &dom.document, SerializeOpts::default()).unwrap(); + serialize( + &mut buf, + &SerializableHandle::from(dom.document), + SerializeOpts::default(), + ) + .unwrap(); assert_eq!( buf.iter().map(|&c| c as char).collect::(), diff --git a/tests/opts.rs b/tests/opts.rs index f307ec3..aa0ebf8 100644 --- a/tests/opts.rs +++ b/tests/opts.rs @@ -13,22 +13,22 @@ mod passing { fn defaults() { let options: Options = Options::default(); - assert_eq!(options.no_audio, false); + assert!(!options.no_audio); assert_eq!(options.base_url, None); - assert_eq!(options.no_css, false); + assert!(!options.no_css); assert_eq!(options.charset, None); - 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!(!options.no_frames); + assert!(!options.no_fonts); + assert!(!options.no_images); + assert!(!options.isolate); + assert!(!options.no_js); + assert!(!options.insecure); + assert!(!options.no_metadata); assert_eq!(options.output, "".to_string()); - assert_eq!(options.silent, false); + assert!(!options.silent); assert_eq!(options.timeout, 0); assert_eq!(options.user_agent, None); - assert_eq!(options.no_video, false); + assert!(!options.no_video); assert_eq!(options.target, "".to_string()); } diff --git a/tests/url/is_url_and_has_protocol.rs b/tests/url/is_url_and_has_protocol.rs index 38a1d8f..7523db2 100644 --- a/tests/url/is_url_and_has_protocol.rs +++ b/tests/url/is_url_and_has_protocol.rs @@ -84,27 +84,25 @@ mod failing { #[test] fn url_with_no_protocol() { - assert_eq!( - url::is_url_and_has_protocol("//some-hostname.com/some-file.html"), - false + assert!( + !url::is_url_and_has_protocol("//some-hostname.com/some-file.html") ); } #[test] fn relative_path() { - assert_eq!( - url::is_url_and_has_protocol("some-hostname.com/some-file.html"), - false + assert!( + !url::is_url_and_has_protocol("some-hostname.com/some-file.html") ); } #[test] fn relative_to_root_path() { - assert_eq!(url::is_url_and_has_protocol("/some-file.html"), false); + assert!(!url::is_url_and_has_protocol("/some-file.html")); } #[test] fn empty_string() { - assert_eq!(url::is_url_and_has_protocol(""), false); + assert!(!url::is_url_and_has_protocol("")); } } diff --git a/tests/utils/retrieve_asset.rs b/tests/utils/retrieve_asset.rs index 698c450..115270f 100644 --- a/tests/utils/retrieve_asset.rs +++ b/tests/utils/retrieve_asset.rs @@ -7,9 +7,7 @@ #[cfg(test)] mod passing { - use reqwest::blocking::Client; use reqwest::Url; - use std::collections::HashMap; use std::env; use monolith::opts::Options; @@ -18,17 +16,12 @@ mod passing { #[test] fn read_data_url() { - let cache = &mut HashMap::new(); - let client = Client::new(); - let mut options = Options::default(); options.silent = true; // If both source and target are data URLs, // ensure the result contains target data URL let (data, final_url, media_type, charset) = utils::retrieve_asset( - cache, - &client, &Url::parse("data:text/html;base64,c291cmNl").unwrap(), &Url::parse("data:text/html;base64,dGFyZ2V0").unwrap(), &options, @@ -49,9 +42,6 @@ mod passing { #[test] fn read_local_file_with_file_url_parent() { - let cache = &mut HashMap::new(); - let client = Client::new(); - let mut options = Options::default(); options.silent = true; @@ -60,8 +50,6 @@ mod passing { // Inclusion of local assets from local sources should be allowed let cwd = env::current_dir().unwrap(); let (data, final_url, media_type, charset) = utils::retrieve_asset( - cache, - &client, &Url::parse(&format!( "{file}{cwd}/tests/_data_/basic/local-file.html", file = file_url_protocol, @@ -102,25 +90,18 @@ mod passing { #[cfg(test)] mod failing { - use reqwest::blocking::Client; use reqwest::Url; - use std::collections::HashMap; use monolith::opts::Options; use monolith::utils; #[test] fn read_local_file_with_data_url_parent() { - let cache = &mut HashMap::new(); - let client = Client::new(); - let mut options = Options::default(); options.silent = true; // Inclusion of local assets from data URL sources should not be allowed match utils::retrieve_asset( - cache, - &client, &Url::parse("data:text/html;base64,SoUrCe").unwrap(), &Url::parse("file:///etc/passwd").unwrap(), &options, @@ -137,16 +118,11 @@ mod failing { #[test] fn read_local_file_with_https_parent() { - let cache = &mut HashMap::new(); - let client = Client::new(); - let mut options = Options::default(); options.silent = true; // Inclusion of local assets from remote sources should not be allowed match utils::retrieve_asset( - cache, - &client, &Url::parse("https://kernel.org/").unwrap(), &Url::parse("file:///etc/passwd").unwrap(), &options,