Setting the file. One moment.
Split Excalidraw Library · Excalidraw Diagram Generator · github/awesome-copilot · Skills Docs
ContentsBack to the top of the page scripts/split-excalidraw-library.py
scripts/ split-excalidraw-library.py
Python · 183 lines · 5 KB
17 """
18
19 import json
20 import os
21 import re
22 import sys
23 from pathlib import Path
24
25
26 def sanitize_filename (name: str ) -> str :
27 """
28 Sanitize icon name to create a valid filename.
29
30 Args:
31 name: Original icon name
32
33 Returns:
34 Sanitized filename safe for all platforms
35 """
36 # Replace spaces with hyphens
37 filename = name.replace( ' ' , '-' )
38
39 # Remove or replace special characters
40 filename = re.sub( r ' [ ^ \w \- . ] ' , '' , filename)
41
42 # Remove multiple consecutive hyphens
43 filename = re.sub( r '- + ' , '-' , filename)
44
45 # Remove leading/trailing hyphens
46 filename = filename.strip( '-' )
47
48 return filename
49
50
51 def find_library_file (directory: Path) -> Path:
52 """
53 Find the .excalidrawlib file in the given directory.
54
55 Args:
56 directory: Directory to search
57
58 Returns:
59 Path to the library file
60
61 Raises:
62 SystemExit: If no library file or multiple library files found
63 """
64 library_files = list (directory.glob( '*.excalidrawlib' ))
65
66 if len (library_files) == 0 :
67 print ( f "Error: No .excalidrawlib file found in { directory } " )
68 print ( f "Please place a .excalidrawlib file in { directory } first." )
69 sys.exit( 1 )
70
71 if len (library_files) > 1 :
72 print ( f "Error: Multiple .excalidrawlib files found in { directory } " )
73 print ( f "Please keep only one library file in { directory } ." )
74 sys.exit( 1 )
75
76 return library_files[ 0 ]
77
78
79 def split_library (library_dir: str ) -> None :
80 """
81 Split an Excalidraw library file into individual icon files.
82
83 Args:
84 library_dir: Path to the directory containing the .excalidrawlib file
85 """
86 library_dir = Path(library_dir)
87
88 if not library_dir.exists():
89 print ( f "Error: Directory not found: { library_dir } " )
90 sys.exit( 1 )
91
92 if not library_dir.is_dir():
93 print ( f "Error: Path is not a directory: { library_dir } " )
94 sys.exit( 1 )
95
96 # Find the library file
97 library_path = find_library_file(library_dir)
98 print ( f "Found library: { library_path.name } " )
99
100 # Load library file
101 print ( f "Loading library data..." )
102 with open (library_path, 'r' , encoding = 'utf-8' ) as f:
103 library_data = json.load(f)
104
105 # Validate library structure
106 if 'libraryItems' not in library_data:
107 print ( "Error: Invalid library file format (missing 'libraryItems')" )
108 sys.exit( 1 )
109
110 # Create icons directory
111 icons_dir = library_dir / 'icons'
112 icons_dir.mkdir( exist_ok = True )
113 print ( f "Output directory: { library_dir } " )
114
115 # Process each library item (icon)
116 library_items = library_data[ 'libraryItems' ]
117 icon_list = []
118
119 print ( f "Processing { len (library_items) } icons..." )
120
121 for item in library_items:
122 # Get icon name
123 icon_name = item.get( 'name' , 'Unnamed' )
124
125 # Create sanitized filename
126 filename = sanitize_filename(icon_name) + '.json'
127
128 # Save icon data
129 icon_path = icons_dir / filename
130 with open (icon_path, 'w' , encoding = 'utf-8' ) as f:
131 json.dump(item, f, ensure_ascii = False , indent = 2 )
132
133 # Add to reference list
134 icon_list.append({
135 'name' : icon_name,
136 'filename' : filename
137 })
138
139 print ( f " ✓ { icon_name } → { filename } " )
140
141 # Sort icon list by name
142 icon_list.sort( key =lambda x: x[ 'name' ])
143
144 # Generate reference.md
145 library_name = library_path.stem
146 reference_path = library_dir / 'reference.md'
147 with open (reference_path, 'w' , encoding = 'utf-8' ) as f:
148 f.write( f "# { library_name } Reference \n\n " )
149 f.write( f "This directory contains { len (icon_list) } icons extracted from ` { library_path.name } `. \n\n " )
150 f.write( "## Available Icons \n\n " )
151 f.write( "| Icon Name | Filename | \n " )
152 f.write( "|-----------|----------| \n " )
153
154 for icon in icon_list:
155 f.write( f "| { icon[ 'name' ] } | `icons/ { icon[ 'filename' ] } ` | \n " )
156
157 f.write( " \n ## Usage \n\n " )
158 f.write( "Each icon JSON file contains the complete `elements` array needed to render that icon in Excalidraw. \n " )
159 f.write( "You can copy the elements from these files into your Excalidraw diagrams. \n " )
160
161 print ( f " \n ✅ Successfully split library into { len (icon_list) } icons" )
162 print ( f "📄 Reference file created: { reference_path } " )
163 print ( f "📁 Icons directory: { icons_dir } " )
164
165
166 def main ():
167 """Main entry point."""
168 if hasattr (sys.stdout, "reconfigure" ):
169 # Ensure consistent UTF-8 output on Windows consoles.
170 sys.stdout.reconfigure( encoding = "utf-8" )
171 if len (sys.argv) != 2 :
172 print ( "Usage: python split-excalidraw-library.py <path-to-library-directory>" )
173 print ( " \n Example:" )
174 print ( " python split-excalidraw-library.py skills/excalidraw-diagram-generator/libraries/aws-architecture-icons/" )
175 print ( " \n Note: The directory should contain a .excalidrawlib file." )
176 sys.exit( 1 )
177
178 library_dir = sys.argv[ 1 ]
179 split_library(library_dir)
180
181
182 if __name__ == '__main__' :
183 main()