mirror of
				https://github.com/walkxcode/dashboard-icons.git
				synced 2025-10-31 16:57:58 +01:00 
			
		
		
		
	🚀 Much needed maintenance
This commit is contained in:
		
							
								
								
									
										12
									
								
								scripts/TEMPLATE.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								scripts/TEMPLATE.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
|  | ||||
|  | ||||
| ## Dashboard Icons | ||||
|  | ||||
| The best source for dashboard icons.<br /> | ||||
| [**← Back to repository**](https://github.com/walkxcode/dashboard-icons/) | ||||
|  | ||||
| <div align="center"> | ||||
| <!-- ICONS --> | ||||
|  | ||||
| <!-- END ICONS --> | ||||
| </div> | ||||
							
								
								
									
										157
									
								
								scripts/convert_svg_assets.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								scripts/convert_svg_assets.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,157 @@ | ||||
| import os | ||||
| import re | ||||
| import hashlib | ||||
| from pathlib import Path | ||||
| from PIL import Image | ||||
| import cairosvg | ||||
|  | ||||
| # Define paths | ||||
| ROOT_DIR = Path(__file__).resolve().parent.parent | ||||
| SVG_DIR = ROOT_DIR / "svg" | ||||
| PNG_DIR = ROOT_DIR / "png" | ||||
| WEBP_DIR = ROOT_DIR / "webp" | ||||
|  | ||||
| # Ensure the output folders exist | ||||
| PNG_DIR.mkdir(parents=True, exist_ok=True) | ||||
| WEBP_DIR.mkdir(parents=True, exist_ok=True) | ||||
|  | ||||
| # Track results | ||||
| failed_files = [] | ||||
| converted_pngs = 0 | ||||
| converted_webps = 0 | ||||
| total_icons = 0 | ||||
|  | ||||
| def file_size_readable(size_bytes): | ||||
|     """Convert bytes to a human-readable format.""" | ||||
|     for unit in ['B', 'KB', 'MB', 'GB']: | ||||
|         if size_bytes < 1024: | ||||
|             return f"{size_bytes:.2f} {unit}" | ||||
|         size_bytes /= 1024 | ||||
|  | ||||
| def hash_file(file_path): | ||||
|     """Generate an MD5 hash for a file.""" | ||||
|     hash_md5 = hashlib.md5() | ||||
|     with open(file_path, "rb") as f: | ||||
|         for chunk in iter(lambda: f.read(4096), b""): | ||||
|             hash_md5.update(chunk) | ||||
|     return hash_md5.hexdigest() | ||||
|  | ||||
| def convert_to_kebab_case(name): | ||||
|     """Convert a filename to kebab-case.""" | ||||
|     cleaned = re.sub(r'[^a-zA-Z0-9\s-]', '', name) | ||||
|     kebab_case_name = re.sub(r'[\s_]+', '-', cleaned).lower() | ||||
|     return kebab_case_name | ||||
|  | ||||
| def rename_if_needed(file_path): | ||||
|     """Ensure the filename is in kebab-case; rename if necessary.""" | ||||
|     new_name = convert_to_kebab_case(file_path.stem) + file_path.suffix | ||||
|     new_path = file_path.parent / new_name | ||||
|  | ||||
|     if new_path != file_path: | ||||
|         if new_path.exists(): | ||||
|             raise FileExistsError(f"File conflict: {new_path} already exists.") | ||||
|         file_path.rename(new_path) | ||||
|         print(f"Renamed: {file_path} -> {new_path}") | ||||
|  | ||||
|     return new_path | ||||
|  | ||||
| def needs_conversion(output_file, data=None): | ||||
|     """Check if a file needs to be converted or overwritten.""" | ||||
|     if output_file.exists(): | ||||
|         if data: | ||||
|             existing_hash = hash_file(output_file) | ||||
|             new_hash = hashlib.md5(data).hexdigest() | ||||
|             return existing_hash != new_hash | ||||
|         return False | ||||
|     return True | ||||
|  | ||||
| def convert_svg_to_png(svg_path, png_path): | ||||
|     """Convert SVG to PNG.""" | ||||
|     global converted_pngs | ||||
|     try: | ||||
|         png_data = cairosvg.svg2png(url=str(svg_path), output_height=512) | ||||
|  | ||||
|         if needs_conversion(png_path, png_data): | ||||
|             with open(png_path, 'wb') as f: | ||||
|                 f.write(png_data) | ||||
|             print(f"Converted PNG: {png_path} ({file_size_readable(png_path.stat().st_size)})") | ||||
|             converted_pngs += 1 | ||||
|         else: | ||||
|             print(f"PNG already up-to-date: {png_path}") | ||||
|  | ||||
|     except Exception as e: | ||||
|         print(f"Failed to convert {svg_path} to PNG: {e}") | ||||
|         failed_files.append(svg_path) | ||||
|  | ||||
| def convert_png_to_webp(png_path, webp_path): | ||||
|     """Convert PNG to WEBP.""" | ||||
|     global converted_webps | ||||
|     try: | ||||
|         image = Image.open(png_path) | ||||
|  | ||||
|         if needs_conversion(webp_path): | ||||
|             image.save(webp_path, format='WEBP') | ||||
|             print(f"Converted WEBP: {webp_path} ({file_size_readable(webp_path.stat().st_size)})") | ||||
|             converted_webps += 1 | ||||
|         else: | ||||
|             print(f"WEBP already up-to-date: {webp_path}") | ||||
|  | ||||
|     except Exception as e: | ||||
|         print(f"Failed to convert {png_path} to WEBP: {e}") | ||||
|         failed_files.append(png_path) | ||||
|  | ||||
| def clean_up_files(folder, valid_basenames): | ||||
|     """Remove files that no longer have corresponding SVG files.""" | ||||
|     removed_files = 0 | ||||
|     for file_path in folder.glob('*'): | ||||
|         if file_path.stem not in valid_basenames: | ||||
|             file_path.unlink() | ||||
|             print(f"Removed: {file_path}") | ||||
|             removed_files += 1 | ||||
|     return removed_files | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     # Track valid basenames (existing SVG files) | ||||
|     valid_basenames = set() | ||||
|  | ||||
|     # Process all SVG files | ||||
|     for svg_file in SVG_DIR.glob("*.svg"): | ||||
|         total_icons += 1 | ||||
|  | ||||
|         # Ensure the filename is in kebab-case | ||||
|         try: | ||||
|             svg_path = rename_if_needed(svg_file) | ||||
|         except Exception as e: | ||||
|             print(f"Error renaming {svg_file}: {e}") | ||||
|             failed_files.append(svg_file) | ||||
|             continue | ||||
|  | ||||
|         valid_basenames.add(svg_path.stem) | ||||
|  | ||||
|         # Set paths for PNG and WEBP | ||||
|         png_path = PNG_DIR / f"{svg_path.stem}.png" | ||||
|         webp_path = WEBP_DIR / f"{svg_path.stem}.webp" | ||||
|  | ||||
|         # Convert SVG to PNG | ||||
|         convert_svg_to_png(svg_path, png_path) | ||||
|  | ||||
|         # Convert PNG to WEBP | ||||
|         if png_path.exists(): | ||||
|             convert_png_to_webp(png_path, webp_path) | ||||
|  | ||||
|     # Clean up unused files | ||||
|     removed_pngs = clean_up_files(PNG_DIR, valid_basenames) | ||||
|     removed_webps = clean_up_files(WEBP_DIR, valid_basenames) | ||||
|  | ||||
|     # Display summary | ||||
|     if converted_pngs == 0 and converted_webps == 0 and removed_pngs == 0 and removed_webps == 0: | ||||
|         print("\nAll icons are already up-to-date.") | ||||
|     else: | ||||
|         print(f"\nConverted {converted_pngs} PNGs and {converted_webps} WEBPs out of {total_icons} icons.") | ||||
|         print(f"Removed {removed_pngs} PNGs and {removed_webps} WEBPs.") | ||||
|  | ||||
|     # Display any failed conversions | ||||
|     if failed_files: | ||||
|         print("\nThe following files failed to convert:") | ||||
|         for file in failed_files: | ||||
|             print(file) | ||||
							
								
								
									
										37
									
								
								scripts/generate_file_tree.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								scripts/generate_file_tree.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| import os | ||||
| import json | ||||
| import sys | ||||
| from pathlib import Path | ||||
|  | ||||
| def generate_folder_tree(paths): | ||||
|     tree = {} | ||||
|     for path in paths: | ||||
|         resolved_path = Path(path).resolve() | ||||
|         base_folder = resolved_path.name or Path.cwd().name | ||||
|         for root, _, files in os.walk(resolved_path): | ||||
|             relative_path = os.path.relpath(root, resolved_path) | ||||
|             key = base_folder if relative_path == '.' else os.path.join(base_folder, relative_path) | ||||
|             if files: | ||||
|                 tree[key] = sorted(files)  # Sort the list of files alphabetically | ||||
|     return tree | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     # Adjust paths to be one level up | ||||
|     folder_paths = sys.argv[1:] | ||||
|     folder_paths = [str(Path(path).resolve()) for path in folder_paths] | ||||
|  | ||||
|     if not folder_paths: | ||||
|         print("Please provide at least one folder path.") | ||||
|         sys.exit(1) | ||||
|  | ||||
|     # Generate the combined folder tree | ||||
|     folder_tree = generate_folder_tree(folder_paths) | ||||
|  | ||||
|     # Write the JSON structure to 'tree.json' in the root folder | ||||
|     root_dir = Path(__file__).resolve().parent.parent  # Assuming script is in 'scripts' folder | ||||
|     tree_json_path = root_dir / 'tree.json' | ||||
|  | ||||
|     with open(tree_json_path, 'w') as f: | ||||
|         json.dump(folder_tree, f, indent=4, sort_keys=True)  # Sort the keys in the JSON output | ||||
|  | ||||
|     print(f"Folder tree successfully written to '{tree_json_path}'.") | ||||
							
								
								
									
										38
									
								
								scripts/generate_icons_page.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								scripts/generate_icons_page.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| import pathlib | ||||
| from pathlib import Path | ||||
| import sys | ||||
|  | ||||
| def generate_img_tag(file): | ||||
|     return ( | ||||
|         f'<a href="https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/webp/{file.name}">' | ||||
|         f'<img src="https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/webp/{file.name}" ' | ||||
|         f'alt="{file.stem}" height="50"></a>' | ||||
|     ) | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     root = pathlib.Path(__file__).parent.resolve() | ||||
|     template_path = root / "TEMPLATE.md" | ||||
|     icons_md_path = root.parent / "ICONS.md" | ||||
|  | ||||
|     imgs = sorted((root.parent / "webp").glob("*.webp")) | ||||
|     img_tags = [generate_img_tag(x) for x in imgs] | ||||
|  | ||||
|     # Read the template file | ||||
|     with open(template_path, "r", encoding="UTF-8") as f: | ||||
|         lines = f.readlines() | ||||
|  | ||||
|     # Find the line that starts with "<!-- ICONS -->" | ||||
|     try: | ||||
|         line_number = lines.index("<!-- ICONS -->\n") | ||||
|     except ValueError: | ||||
|         print("<!-- ICONS --> placeholder not found in TEMPLATE.md") | ||||
|         sys.exit(1) | ||||
|  | ||||
|     # Insert the icons after the placeholder | ||||
|     lines.insert(line_number + 1, " ".join(img_tags) + "\n") | ||||
|  | ||||
|     # Write the new ICONS.md file | ||||
|     with open(icons_md_path, "w", encoding="UTF-8") as f: | ||||
|         f.writelines(lines) | ||||
|  | ||||
|     print("ICONS.md has been successfully generated.") | ||||
		Reference in New Issue
	
	Block a user