Skip to content

Commit 6b2aab2

Browse files
authored
Merge pull request #92 from ButteredCats/fix_preview_captions
Update embedding Reddit preview links to include captions and support i.redd.it embeds
2 parents 6b11d93 + 3469235 commit 6b2aab2

File tree

2 files changed

+65
-18
lines changed

2 files changed

+65
-18
lines changed

src/utils.rs

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -875,9 +875,9 @@ pub fn format_url(url: &str) -> String {
875875

876876
// These are links we want to replace in-body
877877
static REDDIT_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r#"href="(https|http|)://(www\.|old\.|np\.|amp\.|new\.|)(reddit\.com|redd\.it)/"#).unwrap());
878-
static REDDIT_PREVIEW_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"https?://(external-preview|preview)\.redd\.it(.*)[^?]").unwrap());
878+
static REDDIT_PREVIEW_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"https?://(external-preview|preview|i)\.redd\.it(.*)[^?]").unwrap());
879879
static REDDIT_EMOJI_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"https?://(www|).redditstatic\.com/(.*)").unwrap());
880-
static REDLIB_PREVIEW_LINK_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r#"/preview/(pre|external-pre)/(.*?)>"#).unwrap());
880+
static REDLIB_PREVIEW_LINK_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r#"/(img|preview/)(pre|external-pre)?/(.*?)>"#).unwrap());
881881
static REDLIB_PREVIEW_TEXT_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r">(.*?)</a>").unwrap());
882882

883883
// Rewrite Reddit links to Redlib in body of text
@@ -901,14 +901,47 @@ pub fn rewrite_urls(input_text: &str) -> String {
901901
let formatted_url = format_url(REDDIT_PREVIEW_REGEX.find(&text1).map(|x| x.as_str()).unwrap_or_default());
902902

903903
let image_url = REDLIB_PREVIEW_LINK_REGEX.find(&formatted_url).map_or("", |m| m.as_str()).to_string();
904-
let image_text = REDLIB_PREVIEW_TEXT_REGEX.find(&formatted_url).map_or("", |m| m.as_str()).to_string();
904+
let mut image_caption = REDLIB_PREVIEW_TEXT_REGEX.find(&formatted_url).map_or("", |m| m.as_str()).to_string();
905905

906-
let image_to_replace = format!("<a href=\"{image_url}{image_text}").replace(">>", ">");
907-
let image_replacement = format!("<a href=\"{image_url}<img src=\"{image_url}</a>");
906+
/* As long as image_caption isn't empty remove first and last four characters of image_text to leave us with just the text in the caption without any HTML.
907+
This makes it possible to enclose it in a <figcaption> later on without having stray HTML breaking it */
908+
if !image_caption.is_empty() {
909+
image_caption = image_caption[1..image_caption.len() - 4].to_string();
910+
}
911+
912+
// image_url contains > at the end of it, and right above this we remove image_text's front >, leaving us with just a single > between them
913+
let image_to_replace = format!("<a href=\"{image_url}{image_caption}</a>");
914+
915+
// _image_replacement needs to be in scope for the replacement at the bottom of the loop
916+
let mut _image_replacement = String::new();
917+
918+
/* We don't want to show a caption that's just the image's link, so we check if we find a Reddit preview link within the image's caption.
919+
If we don't find one we must have actual text, so we include a <figcaption> block that contains it.
920+
Otherwise we don't include the <figcaption> block as we don't need it. */
921+
if REDDIT_PREVIEW_REGEX.find(&image_caption).is_none() {
922+
// Without this " would show as \" instead. "\&quot;" is how the quotes are formatted within image_text beforehand
923+
image_caption = image_caption.replace("\\&quot;", "\"");
924+
925+
_image_replacement = format!("<figure><a href=\"{image_url}<img loading=\"lazy\" src=\"{image_url}</a><figcaption>{image_caption}</figcaption></figure>");
926+
} else {
927+
_image_replacement = format!("<figure><a href=\"{image_url}<img loading=\"lazy\" src=\"{image_url}</a></figure>");
928+
}
929+
930+
/* In order to know if we're dealing with a normal or external preview we need to take a look at the first capture group of REDDIT_PREVIEW_REGEX
931+
if it's preview we're dealing with something that needs /preview/pre, external-preview is /preview/external-pre, and i is /img */
932+
let reddit_preview_regex_capture = REDDIT_PREVIEW_REGEX.captures(&text1).unwrap().get(1).map_or("", |m| m.as_str()).to_string();
933+
let mut _preview_type = String::new();
934+
if reddit_preview_regex_capture == "preview" {
935+
_preview_type = "/preview/pre".to_string();
936+
} else if reddit_preview_regex_capture == "external-preview" {
937+
_preview_type = "/preview/external-pre".to_string();
938+
} else {
939+
_preview_type = "/img".to_string();
940+
}
908941

909942
text1 = REDDIT_PREVIEW_REGEX
910-
.replace(&text1, formatted_url)
911-
.replace(&image_to_replace, &image_replacement)
943+
.replace(&text1, format!("{_preview_type}$2"))
944+
.replace(&image_to_replace, &_image_replacement)
912945
.to_string()
913946
}
914947
}
@@ -1164,11 +1197,8 @@ async fn test_fetching_ws() {
11641197

11651198
#[test]
11661199
fn test_rewriting_image_links() {
1167-
let input = r#"<p><a href="https://preview.redd.it/zq21ggkj2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=539d8050628ec1190cac26468fe99cc66b6071ab">https://preview.redd.it/zq21ggkj2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=539d8050628ec1190cac26468fe99cc66b6071ab</a></p>
1168-
<p><a href="https://preview.redd.it/vty9ocij2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=fc7c7ef993a5e9ef656d5f5d9cf8290a0a1df877">https://preview.redd.it/vty9ocij2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=fc7c7ef993a5e9ef656d5f5d9cf8290a0a1df877</a></p>
1169-
<p><a href="https://preview.redd.it/bdfdxkjj2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=d0fa420ece27605e882e89cb4711d75d774322ac">https://preview.redd.it/bdfdxkjj2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=d0fa420ece27605e882e89cb4711d75d774322ac</a></p>
1170-
<p><a href="https://preview.redd.it/6awags382xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=9c563aed4f07a91bdd249b5a3cea43a79710dcfc">caption 1</a></p>
1171-
<p><a href="https://preview.redd.it/rbu2ca2b2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=afb538cf784d2e339de9a91aba5dc9c92e47988f">caption 2</a></p>"#;
1172-
let output = r#"<p><a href="/preview/pre/zq21ggkj2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=539d8050628ec1190cac26468fe99cc66b6071ab"><img src="/preview/pre/zq21ggkj2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=539d8050628ec1190cac26468fe99cc66b6071ab"></a></p> <p><a href="/preview/pre/vty9ocij2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=fc7c7ef993a5e9ef656d5f5d9cf8290a0a1df877"><img src="/preview/pre/vty9ocij2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=fc7c7ef993a5e9ef656d5f5d9cf8290a0a1df877"></a></p> <p><a href="/preview/pre/bdfdxkjj2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=d0fa420ece27605e882e89cb4711d75d774322ac"><img src="/preview/pre/bdfdxkjj2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=d0fa420ece27605e882e89cb4711d75d774322ac"></a></p> <p><a href="/preview/pre/6awags382xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=9c563aed4f07a91bdd249b5a3cea43a79710dcfc"><img src="/preview/pre/6awags382xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=9c563aed4f07a91bdd249b5a3cea43a79710dcfc"></a></p> <p><a href="/preview/pre/rbu2ca2b2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=afb538cf784d2e339de9a91aba5dc9c92e47988f"><img src="/preview/pre/rbu2ca2b2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=afb538cf784d2e339de9a91aba5dc9c92e47988f"></a></p>"#;
1200+
let input =
1201+
r#"<p><a href="https://preview.redd.it/6awags382xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=9c563aed4f07a91bdd249b5a3cea43a79710dcfc">caption 1</a></p>"#;
1202+
let output = r#"<p><figure><a href="/preview/pre/6awags382xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=9c563aed4f07a91bdd249b5a3cea43a79710dcfc"><img loading="lazy" src="/preview/pre/6awags382xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=9c563aed4f07a91bdd249b5a3cea43a79710dcfc"></a><figcaption>caption 1</figcaption></figure></p"#;
11731203
assert_eq!(rewrite_urls(input), output);
11741204
}

static/style.css

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,11 @@ nav #redlib {
187187
vertical-align: -2px;
188188
}
189189

190+
figcaption {
191+
margin-top: 5px;
192+
text-align: center;
193+
}
194+
190195
#settings_link {
191196
opacity: 0.8;
192197
margin-left: 10px;
@@ -979,10 +984,6 @@ a.search_subreddit:hover {
979984
vertical-align: bottom;
980985
}
981986

982-
.gallery figcaption {
983-
margin-top: 5px;
984-
}
985-
986987
.gallery .outbound_url {
987988
color: var(--accent);
988989
text-overflow: ellipsis;
@@ -1010,6 +1011,9 @@ a.search_subreddit:hover {
10101011

10111012
.post_body img {
10121013
max-width: 100%;
1014+
display: block;
1015+
margin-left: auto;
1016+
margin-right: auto;
10131017
}
10141018

10151019
.post_poll {
@@ -1187,6 +1191,10 @@ a.search_subreddit:hover {
11871191
}
11881192
}
11891193

1194+
.comment figure {
1195+
margin: 0;
1196+
}
1197+
11901198
.comment_left, .comment_right {
11911199
display: flex;
11921200
flex-direction: column;
@@ -1484,10 +1492,19 @@ input[type="submit"] {
14841492
width: 100%;
14851493
}
14861494

1487-
.md > *:not(:first-child) {
1495+
.md > p:not(:first-child):not(:last-child) {
14881496
margin-top: 20px;
14891497
}
14901498

1499+
.md > figure:first-of-type {
1500+
margin-top: 5px;
1501+
margin-bottom: 0px;
1502+
}
1503+
1504+
.md > figure:not(:first-of-type) {
1505+
margin-top: 10px;
1506+
}
1507+
14911508
.md h1 { font-size: 22px; }
14921509
.md h2 { font-size: 20px; }
14931510
.md h3 { font-size: 18px; }

0 commit comments

Comments
 (0)