Skip to content

Commit

Permalink
feat: allow custom item config
Browse files Browse the repository at this point in the history
  • Loading branch information
alexandre-abrioux committed Nov 11, 2024
1 parent 3f74fe3 commit 299b12b
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 36 deletions.
31 changes: 26 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@ tools:
<!-- START_SECTION:toolbox -->
<!-- Generated by github-profile-toolbox GitHub action -->
|Language|Tools|IDEs|
|-|-|-|
|[<img align="left" alt="HTML5" src="https://img.shields.io/badge/-HTML5-E34F26?logo=html5&logoColor=white">](#)|[<img align="left" alt="Git" src="https://img.shields.io/badge/-Git-F05032?logo=git&logoColor=white">](#)|[<img align="left" alt="VSCodium" src="https://img.shields.io/badge/-VSCodium-2F80ED?logo=vscodium&logoColor=white">](#)|
|[<img align="left" alt="CSS3" src="https://img.shields.io/badge/-CSS3-1572B6?logo=css3&logoColor=white">](#)|[<img align="left" alt="GitHub" src="https://img.shields.io/badge/-GitHub-181717?logo=github&logoColor=white">](#)|[<img align="left" alt="JetBrains" src="https://img.shields.io/badge/-JetBrains-000000?logo=jetbrains&logoColor=white">](#)|
|[<img align="left" alt="JavaScript" src="https://img.shields.io/badge/-JavaScript-F7DF1E?logo=javascript&logoColor=black">](#)|[<img align="left" alt="GitHub Actions" src="https://img.shields.io/badge/-GitHub Actions-2088FF?logo=githubactions&logoColor=white">](#)|[<img align="left" alt="Neovim" src="https://img.shields.io/badge/-Neovim-57A143?logo=neovim&logoColor=white">](#)|
| Language | Tools | IDEs |
|--------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|
| [<img align="left" alt="HTML5" src="https://img.shields.io/badge/-HTML5-E34F26?logo=html5&logoColor=white">](#) | [<img align="left" alt="Git" src="https://img.shields.io/badge/-Git-F05032?logo=git&logoColor=white">](#) | [<img align="left" alt="VSCodium" src="https://img.shields.io/badge/-VSCodium-2F80ED?logo=vscodium&logoColor=white">](#) |
| [<img align="left" alt="CSS3" src="https://img.shields.io/badge/-CSS3-1572B6?logo=css3&logoColor=white">](#) | [<img align="left" alt="GitHub" src="https://img.shields.io/badge/-GitHub-181717?logo=github&logoColor=white">](#) | [<img align="left" alt="JetBrains" src="https://img.shields.io/badge/-JetBrains-000000?logo=jetbrains&logoColor=white">](#) |
| [<img align="left" alt="JavaScript" src="https://img.shields.io/badge/-JavaScript-F7DF1E?logo=javascript&logoColor=black">](#) | [<img align="left" alt="GitHub Actions" src="https://img.shields.io/badge/-GitHub Actions-2088FF?logo=githubactions&logoColor=white">](#) | [<img align="left" alt="Neovim" src="https://img.shields.io/badge/-Neovim-57A143?logo=neovim&logoColor=white">](#) |
<!-- STOP_SECTION:toolbox -->
Here is a
Expand Down Expand Up @@ -102,12 +104,31 @@ You're all set!

## Configuration

### List of tools

This GitHub action uses https://shields.io to generate icons in your profile's README,
and `shield.io` itself uses https://simpleicons.org/ provide logos for brands.
You can find a list of all available brand names over here:
https://github.com/simple-icons/simple-icons/blob/develop/slugs.md.
Use the `Brand slug` name to furnish your configuration file.

### Custom tool

If the tool is not available on [SimpleIcons](https://simpleicons.org/) or
if you'd like to use one icon with a custom name, you can do so with the following:

```yaml
tools:
ides:
# VSCode not available on SimpleIcons, add the tool without an icon
- label: VSCode
color: 29a9f2
# RustRover not available on SimpleIcons, use JetBrains icon with a custom label and color
- label: RustRover
icon: jetbrains
color: 34c97a
```

## GitHub Action Inputs

Use the following input parameters to override defaults and customize the action to your use case:
Expand Down
127 changes: 109 additions & 18 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use clap::Parser;
use markdown_table_formatter::format_tables;
use std::fs;
use yaml_rust2::yaml::Hash;
use yaml_rust2::YamlLoader;
use yaml_rust2::{Yaml, YamlLoader};

#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
Expand Down Expand Up @@ -70,12 +70,12 @@ fn generate_header(tools: &Hash) -> String {
}

fn generate_items(tools: &Hash) -> String {
let lines_nb = tools.keys().fold(0, |max_tools_length, category| {
let category_items = tools[category].as_vec().unwrap();
if category_items.len() > max_tools_length {
return category_items.len();
let lines_nb = tools.keys().fold(0, |max_items_count, category| {
let category_items_count = tools[category].as_vec().unwrap().len();
if category_items_count > max_items_count {
return category_items_count;
}
return max_tools_length;
return max_items_count;
});

let mut items = String::new();
Expand All @@ -85,7 +85,7 @@ fn generate_items(tools: &Hash) -> String {
let category_items = tools[category].as_vec().unwrap();
if line <= category_items.len() {
let item = &category_items[line - 1];
items.push_str(generate_img_tag(item.as_str().unwrap()).as_str());
items.push_str(generate_img_tag(item).as_str());
}
items.push_str("|");
});
Expand All @@ -94,19 +94,85 @@ fn generate_items(tools: &Hash) -> String {
items
}

fn generate_img_tag(slug: &str) -> String {
struct Item {
label: String,
color: String,
icon: Option<String>,
}

fn extract_string_from_hash(hash: &Hash, key: &str) -> String {
let value = Yaml::String(key.to_string());
hash.get(&value)
.expect(format!("missing {key} for item").as_str())
.as_str()
.expect(format!("{key} is not a string").as_str())
.to_string()
}

fn generate_img_tag(item: &Yaml) -> String {
if !item.is_hash() {
return generate_img_tag_from_slug(item.as_str().unwrap());
}
let item_hash = item.as_hash().unwrap();
let icon = item_hash
.get(&Yaml::String("icon".to_string()))
.map(|s| s.as_str().unwrap().to_string());
let mut color_option: Option<String> = None;
if icon.is_some() {
let icon_from_slug = generate_item_from_slug(icon.unwrap().as_str());
color_option = Some(icon_from_slug.color)
}
if item_hash.get(&Yaml::String("color".to_string())).is_some() {
color_option = Some(extract_string_from_hash(item_hash, "color"))
}
let label = extract_string_from_hash(item_hash, "label");
let color = color_option
.expect(format!("missing color or icon for item {label}").as_str())
.to_string();
let item = Item {
label,
color,
icon: item_hash
.get(&Yaml::String("icon".to_string()))
.map(|s| s.as_str().unwrap().to_string()),
};
generate_img_tag_from_item(&item)
}

fn generate_img_tag_from_slug(slug: &str) -> String {
generate_img_tag_from_item(&generate_item_from_slug(&slug))
}

fn generate_item_from_slug(slug: &str) -> Item {
let icons = &SimpleIcons::global().icons;
let icon = icons
.get(slug)
.expect(format!("Could not find icon for slug {slug}").as_str());
let title = &icon.title;
let hex = &icon.hex;
let background = if is_relatively_light_icon_hex(&hex) {
Item {
label: title.to_string(),
color: hex.to_string(),
icon: Some(slug.to_string()),
}
}

fn generate_img_tag_from_item(item: &Item) -> String {
let mut tag = String::new();
let label = &item.label;
let color = &item.color;
let background = if is_relatively_light_icon_hex(&color) {
"black"
} else {
"white"
};
format!("[<img align=\"left\" alt=\"{title}\" src=\"https://img.shields.io/badge/-{title}-{hex}?logo={slug}&logoColor={background}\">](#)")
tag.push_str(format!(r#"[<img align="left" alt="{label}" src="https://img.shields.io/badge/-{label}-{color}?logoColor={background}"#).as_str());
if item.icon.is_some() {
let icon = item.icon.clone().unwrap();
tag.push_str(format!("&logo={icon}").as_str());
}
tag.push_str(r#"">](#)"#);
tag
}

fn update_readme(readme_path: &String, toolbox_markdown: &String) {
Expand Down Expand Up @@ -144,11 +210,11 @@ tools:
let markdown = generate_toolbox(&input.to_string());
assert_eq!(
markdown,
"| ides | languages |
r###"| ides | languages |
| --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| [<img align=\"left\" alt=\"JetBrains\" src=\"https://img.shields.io/badge/-JetBrains-000000?logo=jetbrains&logoColor=white\">](#) | [<img align=\"left\" alt=\"JavaScript\" src=\"https://img.shields.io/badge/-JavaScript-F7DF1E?logo=javascript&logoColor=black\">](#) |
| [<img align=\"left\" alt=\"Neovim\" src=\"https://img.shields.io/badge/-Neovim-57A143?logo=neovim&logoColor=white\">](#) | [<img align=\"left\" alt=\"Rust\" src=\"https://img.shields.io/badge/-Rust-000000?logo=rust&logoColor=white\">](#) |
"
| [<img align="left" alt="JetBrains" src="https://img.shields.io/badge/-JetBrains-000000?logo=jetbrains&logoColor=white">](#) | [<img align="left" alt="JavaScript" src="https://img.shields.io/badge/-JavaScript-F7DF1E?logo=javascript&logoColor=black">](#) |
| [<img align="left" alt="Neovim" src="https://img.shields.io/badge/-Neovim-57A143?logo=neovim&logoColor=white">](#) | [<img align="left" alt="Rust" src="https://img.shields.io/badge/-Rust-000000?logo=rust&logoColor=white">](#) |
"###
);
}

Expand All @@ -164,11 +230,36 @@ tools:
let markdown = generate_toolbox(&input.to_string());
assert_eq!(
markdown,
"| ides | languages |
r#"| ides | languages |
| ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
| [<img align=\"left\" alt=\"Neovim\" src=\"https://img.shields.io/badge/-Neovim-57A143?logo=neovim&logoColor=white\">](#) | [<img align=\"left\" alt=\"JavaScript\" src=\"https://img.shields.io/badge/-JavaScript-F7DF1E?logo=javascript&logoColor=black\">](#) |
| | [<img align=\"left\" alt=\"Rust\" src=\"https://img.shields.io/badge/-Rust-000000?logo=rust&logoColor=white\">](#) |
"
| [<img align="left" alt="Neovim" src="https://img.shields.io/badge/-Neovim-57A143?logo=neovim&logoColor=white">](#) | [<img align="left" alt="JavaScript" src="https://img.shields.io/badge/-JavaScript-F7DF1E?logo=javascript&logoColor=black">](#) |
| | [<img align="left" alt="Rust" src="https://img.shields.io/badge/-Rust-000000?logo=rust&logoColor=white">](#) |
"#
);
}

#[test]
fn should_handle_tools_with_custom_config() {
let input = "
tools:
ides:
- label: VSCode
color: 29a9f2
- label: RustRover
icon: jetbrains
- label: RustRover
icon: jetbrains
color: feab02
";
let markdown = generate_toolbox(&input.to_string());
assert_eq!(
markdown,
r#"| ides |
| --------------------------------------------------------------------------------------------------------------------------- |
| [<img align="left" alt="VSCode" src="https://img.shields.io/badge/-VSCode-29a9f2?logoColor=white">](#) |
| [<img align="left" alt="RustRover" src="https://img.shields.io/badge/-RustRover-000000?logoColor=white&logo=jetbrains">](#) |
| [<img align="left" alt="RustRover" src="https://img.shields.io/badge/-RustRover-feab02?logoColor=black&logo=jetbrains">](#) |
"#
);
}
}
30 changes: 17 additions & 13 deletions tests/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ mod tests {
fn should_generate_toolbox() -> Result<(), Box<dyn std::error::Error>> {
let config_file = assert_fs::NamedTempFile::new("config.yaml")?;
config_file.write_str(
"tools:
"
tools:
ides:
- jetbrains
- neovim
Expand All @@ -34,13 +35,13 @@ mod tests {

let mut cmd = Command::cargo_bin(BIN_NAME)?;
cmd.arg("--config").arg(config_file.path());
cmd.assert().success().stdout(predicate::eq("| ides | languages |
cmd.assert().success().stdout(predicate::eq(r#"| ides | languages |
| --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| [<img align=\"left\" alt=\"JetBrains\" src=\"https://img.shields.io/badge/-JetBrains-000000?logo=jetbrains&logoColor=white\">](#) | [<img align=\"left\" alt=\"JavaScript\" src=\"https://img.shields.io/badge/-JavaScript-F7DF1E?logo=javascript&logoColor=black\">](#) |
| [<img align=\"left\" alt=\"Neovim\" src=\"https://img.shields.io/badge/-Neovim-57A143?logo=neovim&logoColor=white\">](#) | [<img align=\"left\" alt=\"C++\" src=\"https://img.shields.io/badge/-C++-00599C?logo=cplusplus&logoColor=white\">](#) |
| | [<img align=\"left\" alt=\"Rust\" src=\"https://img.shields.io/badge/-Rust-000000?logo=rust&logoColor=white\">](#) |
| | [<img align=\"left\" alt=\"PHP\" src=\"https://img.shields.io/badge/-PHP-777BB4?logo=php&logoColor=white\">](#) |
"));
| [<img align="left" alt="JetBrains" src="https://img.shields.io/badge/-JetBrains-000000?logo=jetbrains&logoColor=white">](#) | [<img align="left" alt="JavaScript" src="https://img.shields.io/badge/-JavaScript-F7DF1E?logo=javascript&logoColor=black">](#) |
| [<img align="left" alt="Neovim" src="https://img.shields.io/badge/-Neovim-57A143?logo=neovim&logoColor=white">](#) | [<img align="left" alt="C++" src="https://img.shields.io/badge/-C++-00599C?logo=cplusplus&logoColor=white">](#) |
| | [<img align="left" alt="Rust" src="https://img.shields.io/badge/-Rust-000000?logo=rust&logoColor=white">](#) |
| | [<img align="left" alt="PHP" src="https://img.shields.io/badge/-PHP-777BB4?logo=php&logoColor=white">](#) |
"#));

Ok(())
}
Expand All @@ -50,7 +51,8 @@ mod tests {
let config_file = assert_fs::NamedTempFile::new("config.yaml")?;
let readme_file = assert_fs::NamedTempFile::new("README.md")?;
config_file.write_str(
"tools:
"
tools:
ides:
- jetbrains
- neovim
Expand All @@ -59,7 +61,8 @@ mod tests {
- cplusplus",
)?;
readme_file.write_str(
"# Title
"
# Title
## Toolbox
<!-- START_SECTION:toolbox --><!-- STOP_SECTION:toolbox -->
Expand All @@ -75,20 +78,21 @@ Lorem ipsum dolor sit amet
cmd.assert().success();

readme_file.assert(predicate::eq(
"# Title
r#"
# Title
## Toolbox
<!-- START_SECTION:toolbox -->
<!-- Generated by github-profile-toolbox GitHub action -->
| ides | languages |
| --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| [<img align=\"left\" alt=\"JetBrains\" src=\"https://img.shields.io/badge/-JetBrains-000000?logo=jetbrains&logoColor=white\">](#) | [<img align=\"left\" alt=\"JavaScript\" src=\"https://img.shields.io/badge/-JavaScript-F7DF1E?logo=javascript&logoColor=black\">](#) |
| [<img align=\"left\" alt=\"Neovim\" src=\"https://img.shields.io/badge/-Neovim-57A143?logo=neovim&logoColor=white\">](#) | [<img align=\"left\" alt=\"C++\" src=\"https://img.shields.io/badge/-C++-00599C?logo=cplusplus&logoColor=white\">](#) |
| [<img align="left" alt="JetBrains" src="https://img.shields.io/badge/-JetBrains-000000?logo=jetbrains&logoColor=white">](#) | [<img align="left" alt="JavaScript" src="https://img.shields.io/badge/-JavaScript-F7DF1E?logo=javascript&logoColor=black">](#) |
| [<img align="left" alt="Neovim" src="https://img.shields.io/badge/-Neovim-57A143?logo=neovim&logoColor=white">](#) | [<img align="left" alt="C++" src="https://img.shields.io/badge/-C++-00599C?logo=cplusplus&logoColor=white">](#) |
<!-- STOP_SECTION:toolbox -->
## Other things
Lorem ipsum dolor sit amet
",
"#,
));

Ok(())
Expand Down

0 comments on commit 299b12b

Please sign in to comment.