diff --git a/Cargo.lock b/Cargo.lock index feba25e..8a75d96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -244,6 +244,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "aho-corasick" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +dependencies = [ + "memchr", +] + [[package]] name = "alloc-no-stdlib" version = "2.0.4" @@ -268,6 +277,55 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e579a7752471abc2a8268df8b20005e3eadd975f585398f17efcfd8d4927371" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" + +[[package]] +name = "anstyle-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "anstyle-wincon" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcd8291a340dd8ac70e18878bc4501dd7b4ff970cfa21c207d36ece51ea88fd" +dependencies = [ + "anstyle", + "windows-sys 0.48.0", +] + [[package]] name = "arrayvec" version = "0.7.2" @@ -288,7 +346,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.13", + "syn 2.0.15", ] [[package]] @@ -309,7 +367,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33b8de67cc41132507eeece2584804efcb15f85ba516e34c944b7667f480397a" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro-error", "proc-macro2", "quote", @@ -328,6 +386,30 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "1.3.2" @@ -453,6 +535,49 @@ dependencies = [ "winapi", ] +[[package]] +name = "clap" +version = "4.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ac1f6381d8d82ab4684768f89c0ea3afe66925ceadb4eeb3fc452ffc55d62" +dependencies = [ + "clap_builder", + "clap_derive", + "once_cell", +] + +[[package]] +name = "clap_builder" +version = "4.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84080e799e54cff944f4b4a4b0e71630b0e0443b25b985175c7dddc1a859b749" +dependencies = [ + "anstream", + "anstyle", + "bitflags", + "clap_lex", + "strsim", + "terminal_size", +] + +[[package]] +name = "clap_derive" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 2.0.15", +] + +[[package]] +name = "clap_lex" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -463,6 +588,31 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "comrak" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "482aa5695bca086022be453c700a40c02893f1ba7098a2c88351de55341ae894" +dependencies = [ + "clap", + "entities", + "memchr", + "once_cell", + "regex", + "shell-words", + "slug", + "syntect", + "typed-arena", + "unicode_categories", + "xdg", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -498,9 +648,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181" +checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" dependencies = [ "libc", ] @@ -559,7 +709,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.13", + "syn 2.0.15", ] [[package]] @@ -576,7 +726,7 @@ checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.13", + "syn 2.0.15", ] [[package]] @@ -627,6 +777,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "deunicode" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690" + [[package]] name = "digest" version = "0.10.6" @@ -637,6 +793,26 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "encoding_rs" version = "0.8.32" @@ -646,6 +822,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "entities" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca" + [[package]] name = "errno" version = "0.3.1" @@ -675,8 +857,8 @@ dependencies = [ "actix-web", "cached", "chrono", + "comrak", "glob", - "markdown", "minify-html", "ramhorns", "reqwest", @@ -685,6 +867,16 @@ dependencies = [ "toml", ] +[[package]] +name = "fancy-regex" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6b8560a05112eb52f04b00e5d3790c0dd75d9d980eb8a122fb23b92a623ccf" +dependencies = [ + "bit-set", + "regex", +] + [[package]] name = "fastrand" version = "1.9.0" @@ -824,9 +1016,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "h2" -version = "0.3.16" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d" +checksum = "17f8a914c2987b688368b5138aa05321db91f4090cf26118185672ad588bce21" dependencies = [ "bytes", "fnv", @@ -862,6 +1054,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "hermit-abi" version = "0.2.6" @@ -919,9 +1117,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" -version = "0.14.25" +version = "0.14.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899" +checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" dependencies = [ "bytes", "futures-channel", @@ -1030,6 +1228,18 @@ version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" +[[package]] +name = "is-terminal" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys 0.48.0", +] + [[package]] name = "itoa" version = "1.0.6" @@ -1068,9 +1278,18 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.141" +version = "0.2.142" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" +checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" + +[[package]] +name = "line-wrap" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9" +dependencies = [ + "safemem", +] [[package]] name = "link-cplusplus" @@ -1082,10 +1301,16 @@ dependencies = [ ] [[package]] -name = "linux-raw-sys" -version = "0.3.1" +name = "linked-hash-map" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "linux-raw-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b085a4f2cde5781fc4b1717f2e86c62f5cda49de7ba99a7c2eae02b61c9064c" [[package]] name = "local-channel" @@ -1143,19 +1368,10 @@ dependencies = [ "fnv", "proc-macro2", "quote", - "regex-syntax", + "regex-syntax 0.6.29", "syn 1.0.109", ] -[[package]] -name = "markdown" -version = "1.0.0-alpha.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98de49c677e95e00eaa74c42a0b07ea55e1e0b1ebca5b2cbc7657f288cd714eb" -dependencies = [ - "unicode-id", -] - [[package]] name = "memchr" version = "2.5.0" @@ -1184,7 +1400,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7754d4669873379ea6a8a5b56e406eb83de713af8a791517ef35a0c832b1e7d5" dependencies = [ - "aho-corasick", + "aho-corasick 0.7.20", "css-minify", "lazy_static", "memchr", @@ -1293,10 +1509,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] -name = "openssl" -version = "0.10.50" +name = "onig" +version = "6.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e30d8bc91859781f0a943411186324d580f2bbeb71b452fe91ae344806af3f1" +checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f" +dependencies = [ + "bitflags", + "libc", + "once_cell", + "onig_sys", +] + +[[package]] +name = "onig_sys" +version = "69.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7" +dependencies = [ + "cc", + "pkg-config", +] + +[[package]] +name = "openssl" +version = "0.10.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97ea2d98598bf9ada7ea6ee8a30fb74f9156b63bbe495d64ec2b87c269d2dda3" dependencies = [ "bitflags", "cfg-if", @@ -1315,7 +1553,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.13", + "syn 2.0.15", ] [[package]] @@ -1326,9 +1564,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.85" +version = "0.9.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d3d193fb1488ad46ffe3aaabc912cc931d02ee8518fe2959aea8ef52718b0c0" +checksum = "992bac49bdbab4423199c654a5515bd2a6c6a23bf03f2dd3bdb7e5ae6259bc69" dependencies = [ "cc", "libc", @@ -1365,7 +1603,7 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30534759e6ad87aa144c396544747e1c25b1020bd133356fd758c8facec764e5" dependencies = [ - "aho-corasick", + "aho-corasick 0.7.20", "lazy_static", "memchr", ] @@ -1400,6 +1638,20 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +[[package]] +name = "plist" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd9647b268a3d3e14ff09c23201133a62589c658db02bb7388c7246aafe0590" +dependencies = [ + "base64", + "indexmap", + "line-wrap", + "quick-xml", + "serde", + "time 0.3.20", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1450,6 +1702,15 @@ dependencies = [ "unicase", ] +[[package]] +name = "quick-xml" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce5e73202a820a31f8a0ee32ada5e21029c81fd9e3ebf668a40832e4219d9d1" +dependencies = [ + "memchr", +] + [[package]] name = "quote" version = "1.0.26" @@ -1535,14 +1796,25 @@ dependencies = [ ] [[package]] -name = "regex" -version = "1.7.3" +name = "redox_users" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "aho-corasick", + "getrandom", + "redox_syscall 0.2.16", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" +dependencies = [ + "aho-corasick 1.0.1", "memchr", - "regex-syntax", + "regex-syntax 0.7.1", ] [[package]] @@ -1551,6 +1823,12 @@ version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +[[package]] +name = "regex-syntax" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" + [[package]] name = "reqwest" version = "0.11.16" @@ -1605,9 +1883,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.11" +version = "0.37.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77" +checksum = "f79bef90eb6d984c72722595b5b1348ab39275a5e5123faca6863bf07d75a4e0" dependencies = [ "bitflags", "errno", @@ -1623,6 +1901,21 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.21" @@ -1675,29 +1968,29 @@ checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" [[package]] name = "serde" -version = "1.0.159" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" +checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.159" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" +checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" dependencies = [ "proc-macro2", "quote", - "syn 2.0.13", + "syn 2.0.15", ] [[package]] name = "serde_json" -version = "1.0.95" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" dependencies = [ "itoa", "ryu", @@ -1749,6 +2042,12 @@ dependencies = [ "digest", ] +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -1767,6 +2066,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "slug" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3bc762e6a4b6c6fcaade73e77f9ebc6991b676f88bb2358bddb56560f073373" +dependencies = [ + "deunicode", +] + [[package]] name = "smallvec" version = "1.10.0" @@ -1802,15 +2110,39 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.13" +version = "2.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec" +checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "syntect" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6c454c27d9d7d9a84c7803aaa3c50cd088d2906fe3c6e42da3209aa623576a8" +dependencies = [ + "bincode", + "bitflags", + "fancy-regex", + "flate2", + "fnv", + "lazy_static", + "once_cell", + "onig", + "plist", + "regex-syntax 0.6.29", + "serde", + "serde_derive", + "serde_json", + "thiserror", + "walkdir", + "yaml-rust", +] + [[package]] name = "tempfile" version = "3.5.0" @@ -1833,6 +2165,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "terminal_size" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237" +dependencies = [ + "rustix", + "windows-sys 0.48.0", +] + [[package]] name = "thiserror" version = "1.0.40" @@ -1850,7 +2192,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.13", + "syn 2.0.15", ] [[package]] @@ -1932,7 +2274,7 @@ checksum = "61a573bdc87985e9d6ddeed1b3d864e8a302c847e40d647746df2f1de209d1ce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.13", + "syn 2.0.15", ] [[package]] @@ -2026,6 +2368,12 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + [[package]] name = "typenum" version = "1.16.0" @@ -2047,12 +2395,6 @@ version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" -[[package]] -name = "unicode-id" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d70b6494226b36008c8366c288d77190b3fad2eb4c10533139c1c1f461127f1a" - [[package]] name = "unicode-ident" version = "1.0.8" @@ -2080,6 +2422,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + [[package]] name = "unsafe-libyaml" version = "0.2.8" @@ -2097,6 +2445,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "vcpkg" version = "0.2.15" @@ -2109,6 +2463,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.0" @@ -2412,6 +2776,24 @@ dependencies = [ "winapi", ] +[[package]] +name = "xdg" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4583db5cbd4c4c0303df2d15af80f0539db703fa1c68802d4cbbd2dd0f88f6" +dependencies = [ + "dirs", +] + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "zstd" version = "0.12.3+zstd.1.5.2" diff --git a/Cargo.toml b/Cargo.toml index 3dc597b..3e3d187 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,6 @@ serde = { version = "1.0.159", features = ["derive"] } serde_yaml = "0.9" minify-html = "0.10.8" glob = "0.3.1" -markdown = "1.0.0-alpha.7" +comrak = "0.18" reqwest = { version = "0.11", features = ["json"] } chrono = "0.4.24" diff --git a/src/misc/markdown.rs b/src/misc/markdown.rs new file mode 100644 index 0000000..f220963 --- /dev/null +++ b/src/misc/markdown.rs @@ -0,0 +1,149 @@ +use crate::misc::date::Date; +use comrak::nodes::{AstNode, NodeValue}; +use comrak::{ + format_html, parse_document, Arena, ComrakExtensionOptions, ComrakOptions, ComrakParseOptions, + ComrakRenderOptions, ListStyleType, +}; +use ramhorns::Content; +use serde::Deserialize; +use std::fs; + +#[derive(Default, Deserialize, Content)] +pub struct FileMetadata { + pub title: Option, + pub link: Option, + pub date: Option, +} + +#[derive(Content)] +pub struct Metadata { + pub info: FileMetadata, + pub math: bool, + pub mermaid: bool, + pub syntax_highlight: bool, +} + +#[derive(Content)] +pub struct File { + pub metadata: Metadata, + pub content: String, +} + +/// Options used for parser and compiler MD --> HTML +fn get_options() -> ComrakOptions { + ComrakOptions { + extension: ComrakExtensionOptions { + strikethrough: true, + tagfilter: true, + table: true, + autolink: true, + tasklist: true, + superscript: true, + header_ids: Some(String::new()), + footnotes: false, // true? + description_lists: true, + front_matter_delimiter: Some("---".to_string()), + }, + parse: ComrakParseOptions { + smart: false, // true one day? + default_info_string: None, + relaxed_tasklist_matching: true, + }, + render: ComrakRenderOptions { + hardbreaks: false, // could be true? change by metadata could be good for compatibility + github_pre_lang: false, + full_info_string: true, + width: 0, // 0 mean disabled? + unsafe_: false, // could be true? change by metadata could be good for compatibility + escape: false, // may change in the future? + list_style: ListStyleType::Dash, + sourcepos: false, + }, + } +} + +pub fn read(raw_text: &str) -> File { + let options = get_options(); + + let arena = Arena::new(); + let root = parse_document(&arena, raw_text, &options); + + // Find metadata + let _metadata = get_metadata(root); + + // Convert to HTML + let mut html = vec![]; + format_html(root, &options, &mut html).unwrap(); + + File { + metadata: Metadata { + info: FileMetadata::default(), + math: false, + mermaid: false, + syntax_highlight: false, + }, + content: String::from_utf8(html).unwrap(), + } +} + +/// Read markdown file +pub fn read_file(filename: &str) -> Option { + match fs::read_to_string(filename) { + Ok(text) => Some(read(&text)), + _ => None, + } +} + +/// Fetch metadata from AST +pub fn get_metadata<'a>(root: &'a AstNode<'a>) -> FileMetadata { + match root + .children() + .find_map(|node| match &node.data.borrow().value { + NodeValue::FrontMatter(text) => { + // '-' correspond to `front_matter_delimiter` + serde_yaml::from_str(text.trim_matches(&['-', '\n'] as &[_])).unwrap_or_default() + } + _ => None, + }) { + Some(data) => data, + None => FileMetadata::default(), + } +} + +/* /// Check recursively if maths is in the AST +fn check_math(vec: &[Node]) -> bool { + vec.iter().any(|x| { + matches!(x, Node::Math(_) | Node::InlineMath(_)) + || match x.children() { + Some(children) => check_math(children), + None => false, + } + }) +} + +/// Recursively check whether mermaid diagrams are in the AST +fn check_mermaid(vec: &[Node], mermaid_str: String) -> bool { + vec.iter().any(|x| match x { + Node::Code(code) => code.lang == Some(mermaid_str.clone()), + _ => false, + } || match x.children() { + Some(children) => check_mermaid(children, mermaid_str.clone()), + None => false + }) +} + +/// Recursively check if code is in the AST +fn check_code(vec: &[Node], blacklist: Vec) -> bool { + vec.iter().any(|x| match x { + Node::InlineCode(_) => true, + Node::Code(code) => match &code.lang { + Some(lang) => !blacklist.contains(lang), + None => true, + }, + _ => false, + } || match x.children() { + Some(children) => check_code(children, blacklist.clone()), + None => false + }) +} + */ diff --git a/src/misc/mod.rs b/src/misc/mod.rs index 2318286..725c25c 100644 --- a/src/misc/mod.rs +++ b/src/misc/mod.rs @@ -1,3 +1,4 @@ pub mod date; pub mod github; +pub mod markdown; mod utils; diff --git a/src/routes/blog.rs b/src/routes/blog.rs index b7543cd..87ae146 100644 --- a/src/routes/blog.rs +++ b/src/routes/blog.rs @@ -5,8 +5,11 @@ use ramhorns::Content; use crate::{ config::Config, - misc::date::Date, - template::{get_md_asm, get_md_metadata, read_md_file, File, FileMetadata, Infos}, + misc::{ + date::Date, + markdown::{read_file, File, FileMetadata}, + }, + template::Infos, }; #[get("/blog")] @@ -62,8 +65,8 @@ fn get_posts(location: &str) -> Vec { let file_without_ext = filename.split_at(filename.len() - 3).0; let file_metadata = match std::fs::read_to_string(format!("{location}/{filename}")) { - Ok(text) => { - let md_tree = get_md_asm(&text); + Ok(_text) => { + /* let md_tree = get_md_asm(&text); let md_nodes = md_tree.children().unwrap(); let mut metadata = get_md_metadata(md_nodes); @@ -72,7 +75,12 @@ fn get_posts(location: &str) -> Vec { None => Some(file_without_ext.to_string()), }; - metadata + metadata */ + FileMetadata { + title: Some(file_without_ext.to_string()), + link: None, + date: None, + } } Err(_) => FileMetadata { title: Some(file_without_ext.to_string()), @@ -125,7 +133,7 @@ fn get_post(post: &mut Option, filename: String) -> Infos { let blog_dir = "data/blog"; let ext = ".md"; - *post = read_md_file(&format!("{blog_dir}/{filename}{ext}")); + *post = read_file(&format!("{blog_dir}/{filename}{ext}")); let title = match post { Some(data) => match &data.metadata.info.title { diff --git a/src/routes/portfolio.rs b/src/routes/portfolio.rs index 6986dae..021d4d0 100644 --- a/src/routes/portfolio.rs +++ b/src/routes/portfolio.rs @@ -5,7 +5,8 @@ use ramhorns::Content; use crate::{ config::Config, - template::{read_md_file, File, Infos}, + misc::markdown::{read_file, File}, + template::Infos, }; #[get("/portfolio")] @@ -33,14 +34,14 @@ pub fn build_page(config: Config) -> String { let bots_apps_loc = format!("{projects_dir}/bots"); let bots_apps = glob(&format!("{bots_apps_loc}/*{ext}")) .unwrap() - .map(|e| read_md_file(&e.unwrap().to_string_lossy()).unwrap()) + .map(|e| read_file(&e.unwrap().to_string_lossy()).unwrap()) .collect::>(); // Get perso apps let perso_apps_loc = format!("{projects_dir}/perso"); let perso_apps = glob(&format!("{perso_apps_loc}/*{ext}")) .unwrap() - .map(|e| read_md_file(&e.unwrap().to_string_lossy()).unwrap()) + .map(|e| read_file(&e.unwrap().to_string_lossy()).unwrap()) .collect::>(); let univ_loc = format!("{projects_dir}/univ{ext}"); @@ -57,7 +58,7 @@ pub fn build_page(config: Config) -> String { (Some(perso_apps), None) }; - let (univ_content, univ_loc) = match read_md_file(&univ_loc) { + let (univ_content, univ_loc) = match read_file(&univ_loc) { Some(data) => (Some(data.content), None), _ => (None, Some(univ_loc)), }; diff --git a/src/template.rs b/src/template.rs index 89025ac..3361461 100644 --- a/src/template.rs +++ b/src/template.rs @@ -1,9 +1,4 @@ -use markdown::mdast::Node; use ramhorns::{Content, Ramhorns}; -use serde::Deserialize; -use std::fs; - -use crate::misc::date::Date; #[derive(Clone)] pub struct Template { @@ -44,167 +39,3 @@ impl Template { }) } } - -enum FrontMatter<'a> { - Yaml(&'a str), - Toml(&'a str), - Json(&'a str), -} - -impl FrontMatter<'_> { - fn parse(&self) -> FileMetadata { - match self { - Self::Yaml(val) => serde_yaml::from_str(val).unwrap_or_default(), - Self::Toml(_val) => todo!(), - Self::Json(_val) => todo!(), - } - } -} - -#[derive(Default, Deserialize, Content)] -pub struct FileMetadata { - pub title: Option, - pub link: Option, - pub date: Option, -} - -#[derive(Content)] -pub struct Metadata { - pub info: FileMetadata, - pub math: bool, - pub mermaid: bool, - pub syntax_highlight: bool, -} - -#[derive(Content)] -pub struct File { - pub metadata: Metadata, - pub content: String, -} - -pub fn read_md_file(filename: &str) -> Option { - // Read markdown file - match fs::read_to_string(filename) { - Ok(text) => Some(read_md(&text)), - _ => None, - } -} - -pub fn get_md_metadata(vec: &[Node]) -> FileMetadata { - if vec.is_empty() { - FileMetadata::default() - } else { - match &vec[0] { - Node::Yaml(v) => FrontMatter::Yaml(&v.value).parse(), - Node::Toml(v) => FrontMatter::Toml(&v.value).parse(), - Node::MdxjsEsm(v) => FrontMatter::Json(&v.value).parse(), - _ => FileMetadata::default(), - } - } -} - -fn get_parse_option() -> markdown::ParseOptions { - markdown::ParseOptions { - constructs: markdown::Constructs { - frontmatter: true, - math_text: true, - math_flow: true, - ..markdown::Constructs::gfm() - }, - ..markdown::ParseOptions::gfm() - } -} - -fn get_compile_option() -> markdown::CompileOptions { - markdown::CompileOptions { - allow_dangerous_html: true, - ..markdown::CompileOptions::gfm() - } -} - -pub fn get_md_asm(raw_text: &str) -> Node { - let parse_option = get_parse_option(); - - markdown::to_mdast(raw_text, &parse_option).unwrap() -} - -pub fn read_md(raw_text: &str) -> File { - let md_tree = get_md_asm(raw_text); - let md_nodes = md_tree.children().unwrap(); - let metadata = get_md_metadata(md_nodes); - let presence_mermaid; - let presence_math; - let presence_code; - if md_nodes.is_empty() { - presence_mermaid = false; - presence_math = false; - presence_code = false; - } else { - // Find if document contains maths - presence_math = check_math(md_nodes); - - // Find if document contains mermaid diagram - let mermaid = String::from("mermaid"); - presence_mermaid = check_mermaid(md_nodes, mermaid.clone()); - - // Find if document contains code to highlight - presence_code = check_code(md_nodes, vec![mermaid]); - } - - // Convert to HTML - let html = markdown::to_html_with_options( - raw_text, - &markdown::Options { - parse: get_parse_option(), - compile: get_compile_option(), - }, - ) - .unwrap(); - - File { - metadata: Metadata { - info: metadata, - math: presence_math, - mermaid: presence_mermaid, - syntax_highlight: presence_code, - }, - content: html, - } -} - -/// Check recursively if maths is in the AST -fn check_math(vec: &[Node]) -> bool { - vec.iter().any(|x| { - matches!(x, Node::Math(_) | Node::InlineMath(_)) - || match x.children() { - Some(children) => check_math(children), - None => false, - } - }) -} - -/// Recursively check whether mermaid diagrams are in the AST -fn check_mermaid(vec: &[Node], mermaid_str: String) -> bool { - vec.iter().any(|x| match x { - Node::Code(code) => code.lang == Some(mermaid_str.clone()), - _ => false, - } || match x.children() { - Some(children) => check_mermaid(children, mermaid_str.clone()), - None => false - }) -} - -/// Recursively check if code is in the AST -fn check_code(vec: &[Node], blacklist: Vec) -> bool { - vec.iter().any(|x| match x { - Node::InlineCode(_) => true, - Node::Code(code) => match &code.lang { - Some(lang) => !blacklist.contains(lang), - None => true, - }, - _ => false, - } || match x.children() { - Some(children) => check_code(children, blacklist.clone()), - None => false - }) -}