Skip to content

Commit

Permalink
Do not require logos to be in SVG format (#667)
Browse files Browse the repository at this point in the history
This only applies to the landscapes generator software. Landscapes may
still have this requirement (i.e. CNCF landscape).

Closes #651

Signed-off-by: Sergio Castaño Arteaga <tegioz@icloud.com>
  • Loading branch information
tegioz authored Jul 19, 2024
1 parent 2bc43d2 commit d7dd1fc
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 30 deletions.
71 changes: 44 additions & 27 deletions crates/cli/src/build/logos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ use regex::bytes::Regex;
use reqwest::StatusCode;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use std::{fs, path::PathBuf};
use std::{
fs,
path::{Path, PathBuf},
};
use usvg::{NodeExt, Rect, TreeParsing};

lazy_static! {
Expand All @@ -36,50 +39,64 @@ pub struct LogosSource {
/// Represents some information about an item's logo.
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub(crate) struct Logo {
pub svg_data: Vec<u8>,
pub data: Vec<u8>,
pub extension: String,
pub digest: String,
}

/// Get SVG logo from the source provided and apply some modifications to it.
/// Get logo from the source provided and apply some modifications to it when
/// applicable.
pub(crate) async fn prepare_logo(
http_client: reqwest::Client,
logos_source: &LogosSource,
logos_viewbox: &LogosViewbox,
file_name: &str,
) -> Result<Logo> {
// Get SVG logo from the source provided
let mut svg_data = get_svg(http_client.clone(), logos_source, file_name).await?;

// Remove title if present (some identical logos are using a different
// title, so we do this before computing the digest)
svg_data = SVG_TITLE.replace(&svg_data, b"").into_owned();

// Update viewbox to the smallest rectangle in which the object fits
if logos_viewbox.adjust && !logos_viewbox.exclude.contains(&file_name.to_string()) {
if let Ok(Some(bounding_box)) = get_svg_bounding_box(&svg_data) {
if bounding_box.left() >= 0.0 && bounding_box.top() >= 0.0 {
let new_viewbox_bounds = format!(
"{} {} {} {}",
bounding_box.left(),
bounding_box.top(),
bounding_box.right() - bounding_box.left(),
bounding_box.bottom() - bounding_box.top()
);
let new_viewbox = format!(r#"viewBox="{new_viewbox_bounds}""#);
svg_data = SVG_VIEWBOX.replace(&svg_data, new_viewbox.as_bytes()).into_owned();
// Get logo from the source provided
let mut logo_data = get_logo(http_client.clone(), logos_source, file_name).await?;

// Apply some modifications to the logo if it is an SVG file
let extension = Path::new(file_name)
.extension()
.and_then(|ext| ext.to_str())
.unwrap_or_default()
.to_lowercase();
if extension == "svg" {
// Remove title if present (some identical logos are using a different
// title, so we do this before computing the digest)
logo_data = SVG_TITLE.replace(&logo_data, b"").into_owned();

// Update viewbox to the smallest rectangle in which the object fits
if logos_viewbox.adjust && !logos_viewbox.exclude.contains(&file_name.to_string()) {
if let Ok(Some(bounding_box)) = get_svg_bounding_box(&logo_data) {
if bounding_box.left() >= 0.0 && bounding_box.top() >= 0.0 {
let new_viewbox_bounds = format!(
"{} {} {} {}",
bounding_box.left(),
bounding_box.top(),
bounding_box.right() - bounding_box.left(),
bounding_box.bottom() - bounding_box.top()
);
let new_viewbox = format!(r#"viewBox="{new_viewbox_bounds}""#);
logo_data = SVG_VIEWBOX.replace(&logo_data, new_viewbox.as_bytes()).into_owned();
}
}
}
}

// Calculate digest
let digest = hex::encode(Sha256::digest(&svg_data));
let digest = hex::encode(Sha256::digest(&logo_data));

Ok(Logo { svg_data, digest })
Ok(Logo {
data: logo_data,
extension,
digest,
})
}

/// Get SVG logo content from the corresponding source.
/// Get logo content from the corresponding source.
#[allow(clippy::similar_names)]
async fn get_svg(
async fn get_logo(
http_client: reqwest::Client,
logos_source: &LogosSource,
file_name: &str,
Expand Down
6 changes: 3 additions & 3 deletions crates/cli/src/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -643,16 +643,16 @@ async fn prepare_items_logos(
}
};

// Copy logo to output dir using the digest(+.svg) as filename
let file_name = format!("{}.svg", logo.digest);
// Copy logo to output dir using the digest(+.extenstion) as filename
let file_name = format!("{}.{}", logo.digest, logo.extension);
let mut file = match File::create(output_dir.join(LOGOS_PATH).join(&file_name)) {
Ok(file) => file,
Err(err) => {
error!(?err, ?file_name, "error creating logo file in output dir");
return (item.id.clone(), None);
}
};
if let Err(err) = file.write_all(&logo.svg_data) {
if let Err(err) = file.write_all(&logo.data) {
error!(?err, ?file_name, "error writing logo to file in output dir");
};

Expand Down

0 comments on commit d7dd1fc

Please sign in to comment.