pub struct LinkBuilder {
base_url: String,
}
impl LinkBuilder {
pub fn new(base_url: &str) -> Self {
LinkBuilder {
base_url: base_url.to_string(),
}
}
pub fn build_link(
&self,
utm_source: Option<&str>,
utm_medium: Option<&str>,
utm_campaign: Option<&str>,
) -> String {
let mut url = self.base_url.clone();
let mut params = Vec::new();
if let Some(source) = utm_source {
params.push(format!("utm_source={}", urlencoding::encode(source)));
}
if let Some(medium) = utm_medium {
params.push(format!("utm_medium={}", urlencoding::encode(medium)));
}
if let Some(campaign) = utm_campaign {
params.push(format!("utm_campaign={}", urlencoding::encode(campaign)));
}
if !params.is_empty() {
url.push('?');
url.push_str(¶ms.join("&"));
}
url
}
pub fn generate_anchor(
&self,
text: &str,
utm_source: Option<&str>,
utm_medium: Option<&str>,
utm_campaign: Option<&str>,
rel: Option<&str>,
target: Option<&str>,
class: Option<&str>,
) -> String {
let href = self.build_link(utm_source, utm_medium, utm_campaign);
let rel_attr = rel.unwrap_or("nofollow");
let target_attr = target.unwrap_or("_blank");
let class_attr = if let Some(c) = class {
format!(r#" class="{}""#, c)
} else {
String::new()
};
format!(
r#"<a href="{}" rel="{}" target="{}"{}>{}</a>"#,
href,
rel_attr,
target_attr,
class_attr,
text
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_build_link() {
let builder = LinkBuilder::new("https://example.com");
let url = builder.build_link(Some("github"), None, None);
assert!(url.contains("utm_source=github"));
}
}