diff options
author | Colin Reeder <colin@vpzom.click> | 2020-06-27 00:42:53 -0600 |
---|---|---|
committer | Colin Reeder <colin@vpzom.click> | 2020-06-27 00:43:07 -0600 |
commit | 0402d74194a2f9df00fab82e7d4425a92c898742 (patch) | |
tree | d701791013adc7e2e3f63f00773f2f9f9651870a | |
parent | 37b2482458a5995c370fd7e59c93cd8b21fe9c1c (diff) |
Add support for incoming HTML
-rw-r--r-- | Cargo.lock | 201 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/routes/mod.rs | 74 |
3 files changed, 259 insertions, 17 deletions
@@ -1,6 +1,21 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] +name = "ammonia" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89eac85170f4b3fb3dc5e442c1cfb036cb8eecf9dbbd431a161ffad15d90ea3b" +dependencies = [ + "html5ever", + "lazy_static", + "maplit", + "markup5ever_rcdom", + "matches", + "tendril", + "url", +] + +[[package]] name = "autocfg" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -96,6 +111,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] +name = "futf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] name = "futures-channel" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -177,6 +202,7 @@ dependencies = [ name = "hitide" version = "0.1.0" dependencies = [ + "ammonia", "fallible-iterator", "ginger", "hyper", @@ -191,6 +217,20 @@ dependencies = [ ] [[package]] +name = "html5ever" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aafcf38a1a36118242d29b92e1b08ef84e67e4a5ed06e0a80be20e6a32bfed6b" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "http" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -321,6 +361,47 @@ dependencies = [ ] [[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + +[[package]] +name = "markup5ever" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae38d669396ca9b707bfc3db254bc382ddb94f57cc5c235f34623a669a01dab" +dependencies = [ + "log", + "phf", + "phf_codegen", + "serde", + "serde_derive", + "serde_json", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "markup5ever_rcdom" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f015da43bcd8d4f144559a3423f4591d69b8ce0652c905374da7205df336ae2b" +dependencies = [ + "html5ever", + "markup5ever", + "tendril", + "xml5ever", +] + +[[package]] name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -393,6 +474,12 @@ dependencies = [ ] [[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + +[[package]] name = "openssl" version = "0.10.29" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -432,6 +519,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] +name = "phf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher", +] + +[[package]] name = "pin-project" version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -476,6 +601,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" [[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] name = "proc-macro2" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -504,6 +635,7 @@ dependencies = [ "rand_chacha", "rand_core", "rand_hc", + "rand_pcg", ] [[package]] @@ -535,6 +667,15 @@ dependencies = [ ] [[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core", +] + +[[package]] name = "redox_syscall" version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -647,6 +788,12 @@ dependencies = [ ] [[package]] +name = "siphasher" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa8f3741c7372e75519bd9346068370c9cdaabcc1f9599cbcf2a2719352286b7" + +[[package]] name = "slab" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -671,6 +818,31 @@ dependencies = [ ] [[package]] +name = "string_cache" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2940c75beb4e3bf3a494cef919a747a2cb81e52571e212bfbd185074add7208a" +dependencies = [ + "lazy_static", + "new_debug_unreachable", + "phf_shared", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f24c8e5e19d22a726626f1a5e16fe15b132dcf21d10177fa5a45ce7962996b97" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", +] + +[[package]] name = "syn" version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -696,6 +868,17 @@ dependencies = [ ] [[package]] +name = "tendril" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707feda9f2582d5d680d733e38755547a3e8fb471e7ba11452ecfd9ce93a5d3b" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] name = "thiserror" version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -836,6 +1019,12 @@ dependencies = [ ] [[package]] +name = "utf-8" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" + +[[package]] name = "vcpkg" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -900,3 +1089,15 @@ dependencies = [ "winapi 0.2.8", "winapi-build", ] + +[[package]] +name = "xml5ever" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b1b52e6e8614d4a58b8e70cf51ec0cc21b256ad8206708bcff8139b5bbd6a59" +dependencies = [ + "log", + "mac", + "markup5ever", + "time", +] @@ -19,3 +19,4 @@ serde_derive = "1.0.111" serde = "1.0.111" fallible-iterator = "0.2.0" ginger = "0.1.0" +ammonia = "3.1.0" diff --git a/src/routes/mod.rs b/src/routes/mod.rs index f808bf1..0958813 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -113,12 +113,18 @@ struct RespMinimalAuthorInfo<'a> { host: Cow<'a, str>, } +trait HavingContent { + fn content_text(&self) -> Option<&str>; + fn content_html(&self) -> Option<&str>; +} + #[derive(Deserialize, Debug)] struct RespPostListPost<'a> { id: i64, title: Cow<'a, str>, href: Option<Cow<'a, str>>, content_text: Option<Cow<'a, str>>, + content_html: Option<Cow<'a, str>>, #[serde(borrow)] author: Option<RespMinimalAuthorInfo<'a>>, created: Cow<'a, str>, @@ -126,17 +132,36 @@ struct RespPostListPost<'a> { community: RespMinimalCommunityInfo<'a>, } +impl<'a> HavingContent for RespPostListPost<'a> { + fn content_text(&self) -> Option<&str> { + self.content_text.as_deref() + } + fn content_html(&self) -> Option<&str> { + self.content_html.as_deref() + } +} + #[derive(Deserialize, Debug)] struct RespPostCommentInfo<'a> { id: i64, #[serde(borrow)] author: Option<RespMinimalAuthorInfo<'a>>, created: Cow<'a, str>, - content_text: Cow<'a, str>, + content_text: Option<Cow<'a, str>>, + content_html: Option<Cow<'a, str>>, #[serde(borrow)] replies: Option<Vec<RespPostCommentInfo<'a>>>, } +impl<'a> HavingContent for RespPostCommentInfo<'a> { + fn content_text(&self) -> Option<&str> { + self.content_text.as_deref() + } + fn content_html(&self) -> Option<&str> { + self.content_html.as_deref() + } +} + #[derive(Deserialize, Debug)] struct RespPostInfo<'a> { #[serde(flatten, borrow)] @@ -291,6 +316,33 @@ impl<'community> render::Render for CommunityLink<'community> { } } +struct Content<'a, T: HavingContent + 'a> { + src: &'a T, +} + +impl<'a, T: HavingContent + 'a> render::Render for Content<'a, T> { + fn render_into<W: std::fmt::Write>(self, writer: &mut W) -> std::fmt::Result { + match self.src.content_html() { + Some(html) => { + let cleaned = ammonia::clean(&html); + writer.write_str("<p>")?; + render::raw!(cleaned.as_ref()).render_into(writer)?; + writer.write_str("</p>")?; + } + None => match self.src.content_text() { + Some(text) => { + writer.write_str("<p>")?; + text.render_into(writer)?; + writer.write_str("</p>")?; + } + None => {} + }, + } + + Ok(()) + } +} + #[render::component] fn Comment<'comment, 'base_data>( comment: &'comment RespPostCommentInfo<'comment>, @@ -299,9 +351,7 @@ fn Comment<'comment, 'base_data>( render::rsx! { <li> <small><cite><UserLink user={comment.author.as_ref()} /></cite>{":"}</small> - <br /> - {comment.content_text.as_ref()} - <br /> + <Content src={comment} /> <div class={"actionList"}> <a href={format!("/comments/{}", comment.id)}>{"reply"}</a> { @@ -378,8 +428,7 @@ async fn page_comment( <HTPage base_data={&base_data}> <p> <small><cite><UserLink user={comment.author.as_ref()} /></cite>{":"}</small> - <br /> - {comment.content_text.as_ref()} + <Content src={&comment} /> </p> <form method={"POST"} action={format!("/comments/{}/submit_reply", comment.id)}> <div> @@ -423,7 +472,7 @@ async fn page_comment_delete( <p> <small><cite><UserLink user={comment.author.as_ref()} /></cite>{":"}</small> <br /> - {comment.content_text.as_ref()} + <Content src={&comment} /> </p> <div id={"delete"}> <h2>{"Delete this comment?"}</h2> @@ -714,16 +763,7 @@ async fn page_post( } } } - { - match &post.as_ref().content_text { - None => None, - Some(content_text) => { - Some(render::rsx! { - <p>{content_text.as_ref()}</p> - }) - } - } - } + <Content src={post.as_ref()} /> { if author_is_me(&post.as_ref().author, &base_data.login) { Some(render::rsx! { |