git-gemini-forge 0.6.6

A simple Gemini server that serves a read-only view of public repositories from a Git forge.
use super::{PercentEncoded, truncate_spaces};
use crate::network::responses::*;
use bytesize::ByteSize;

/// The size at which we should inform the user in the file list before they click it.
const LARGE: ByteSize = ByteSize::mb(40);

/// Creates an internal page link in Gemtext for the given file or directory.
pub fn file_link(repo: &Repo, branch_name: Option<&PercentEncoded>, file: &Item) -> String {
	// Replace space with "_"
	let username_clean: String = truncate_spaces(&repo.owner.login);
	let username_link = PercentEncoded::new(&username_clean);

	let repo_link = PercentEncoded::new(&repo.name);

	let file_name = file.name();
	let file_path = file.path();

	let size = match file {
		Item::Submodule { .. } | Item::Symlink { .. } => String::new(),
		Item::Dir { size, .. } if size.as_u64() == 0 => String::new(),
		Item::Dir { size, .. } if *size > LARGE => format!("{}", size.display().si()),
		Item::File { size, .. } if *size > LARGE => {
			format!("{}", size.display().si())
		}
		_ => String::new(),
	};

	let path = PercentEncoded::new(file_path);
	let branch_name = match branch_name {
		Some(branch) => branch,
		None => &PercentEncoded::new(&repo.default_branch),
	};

	let icon: &str = match file {
		Item::Submodule { .. } => "", // right arrow
		Item::Symlink { .. } => "",   // deep arrow
		Item::Dir { .. } => "📁",      // folder
		Item::File { .. } => "📄",     // doc
	};

	// TODO: This format matches Forgejo; we may want to support other formats for other forges.
	format!(
		"=> /{}/{}/src/branch/{}/{} {icon} {file_name}{size}",
		username_link.uri_component(),
		repo_link.uri_component(),
		branch_name.uri_component(),
		path.uri_component_retaining_sep()
	)
}