From 3e1f5777f131319873378654659923b749ca23dc Mon Sep 17 00:00:00 2001 From: Kartavya Vashishtha Date: Sat, 11 Feb 2023 19:42:40 +0530 Subject: [PATCH] feat: External URL redirect (#2080) --- components/content/src/section.rs | 28 ++++++++++++++++++++++++++++ components/markdown/src/markdown.rs | 6 +----- components/site/src/lib.rs | 9 +++++++-- components/utils/src/net.rs | 5 +++++ 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/components/content/src/section.rs b/components/content/src/section.rs index f5695bad..920f863e 100644 --- a/components/content/src/section.rs +++ b/components/content/src/section.rs @@ -7,6 +7,7 @@ use config::Config; use errors::{Context, Result}; use markdown::{render_content, RenderContext}; use utils::fs::read_file; +use utils::net::is_external_link; use utils::table_of_contents::Heading; use utils::templates::{render_template, ShortcodeDefinition}; @@ -168,7 +169,14 @@ impl Section { .with_context(|| format!("Failed to render content of {}", self.file.path.display()))?; self.content = res.body; self.toc = res.toc; + self.external_links = res.external_links; + if let Some(ref redirect_to) = self.meta.redirect_to { + if is_external_link(redirect_to) { + self.external_links.push(redirect_to.to_owned()); + } + } + self.internal_links = res.internal_links; Ok(()) @@ -356,4 +364,24 @@ Bonjour le monde"# assert_eq!(section.lang, "fr".to_string()); assert_eq!(section.permalink, "http://a-website.com/fr/subcontent/"); } + + #[test] + fn can_redirect_to_external_site() { + let config = Config::default(); + let content = r#" ++++ +redirect_to = "https://bar.com/something" ++++ +Example"# + .to_string(); + let res = Section::parse( + Path::new("content/subcontent/_index.md"), + &content, + &config, + &PathBuf::new(), + ); + assert!(res.is_ok()); + let section = res.unwrap(); + assert_eq!(section.meta.redirect_to, Some("https://bar.com/something".to_owned())); + } } diff --git a/components/markdown/src/markdown.rs b/components/markdown/src/markdown.rs index 6d66f88d..d773a21f 100644 --- a/components/markdown/src/markdown.rs +++ b/components/markdown/src/markdown.rs @@ -5,6 +5,7 @@ use libs::gh_emoji::Replacer as EmojiReplacer; use libs::once_cell::sync::Lazy; use libs::pulldown_cmark as cmark; use libs::tera; +use utils::net::is_external_link; use crate::context::RenderContext; use errors::{Context, Error, Result}; @@ -133,11 +134,6 @@ fn find_anchor(anchors: &[String], name: String, level: u16) -> String { find_anchor(anchors, name, level + 1) } -/// Returns whether a link starts with an HTTP(s) scheme. -fn is_external_link(link: &str) -> bool { - link.starts_with("http:") || link.starts_with("https:") -} - fn fix_link( link_type: LinkType, link: &str, diff --git a/components/site/src/lib.rs b/components/site/src/lib.rs index e0005b61..67ca956e 100644 --- a/components/site/src/lib.rs +++ b/components/site/src/lib.rs @@ -5,6 +5,7 @@ pub mod sass; pub mod sitemap; pub mod tpls; +use std::borrow::Cow; use std::collections::{HashMap, HashSet}; use std::fs::{remove_dir_all, remove_file}; use std::path::{Path, PathBuf}; @@ -25,7 +26,7 @@ use utils::fs::{ copy_directory, copy_file_if_needed, create_directory, create_file, ensure_directory_exists, is_dotfile, }; -use utils::net::get_available_port; +use utils::net::{get_available_port, is_external_link}; use utils::templates::{render_template, ShortcodeDefinition}; use utils::types::InsertAnchor; @@ -1142,7 +1143,11 @@ impl Site { } if let Some(ref redirect_to) = section.meta.redirect_to { - let permalink = self.config.make_permalink(redirect_to); + let permalink: Cow = if is_external_link(redirect_to) { + Cow::Borrowed(redirect_to) + } else { + Cow::Owned(self.config.make_permalink(redirect_to)) + }; self.write_content( &components, "index.html", diff --git a/components/utils/src/net.rs b/components/utils/src/net.rs index 314ec8e9..9f662e85 100644 --- a/components/utils/src/net.rs +++ b/components/utils/src/net.rs @@ -9,3 +9,8 @@ pub fn get_available_port(avoid: u16) -> Option { pub fn port_is_available(port: u16) -> bool { TcpListener::bind(("127.0.0.1", port)).is_ok() } + +/// Returns whether a link starts with an HTTP(s) scheme. +pub fn is_external_link(link: &str) -> bool { + link.starts_with("http:") || link.starts_with("https:") +}