I have a custom python script that generates a custom myapp/public/icons.svg to be loaded in hooks.py (Frappe v15 feature).
I’m currently running the script manually but i think it makes more sense to make it part of the build process somehow. i.e. when i run bench build --apps myapp.
That way I don’t have to version control the generated myapp/public/icons.svg file while also being assured the server will always have the latest version for it.
I know there’s patches but I’m unsure if that’s the right feature for my use case as the script will need to be run on every bench build, vs just once.
BTW, in case anyone stumbles upon this, here’s my script. It’s not particularly complex per se so converting to JS is certainly a valid option. I just figured I should try to keep it simple without JS dependencies for my particular use case.
pyproject.toml
# These dependencies are only installed when developer mode is enabled
[tool.bench.dev-dependencies]
# package_name = "~=1.1.0"
beautifulsoup4 = "4.12.2"
lxml = "4.9.3"
soupsieve = "2.5"
compile.py
import os
from bs4 import BeautifulSoup
input_dir = "./symbols"
output_file_path = "../../myapp/public/icons.svg"
# Start the combined SVG content
combined_svg_content = '<svg id="myapp-symbols" aria-hidden="true" style="position: absolute; width: 0; height: 0; overflow: hidden;" class="d-block" xmlns="http://www.w3.org/2000/svg">\n'
# Track used IDs for uniqueness check
used_ids = set()
# Track errors
errors = []
# Track if at least one valid symbol is found
valid_symbol_found = False
# Track valid symbol IDs
valid_symbol_ids = []
# Read each symbol file and append its content
for symbol_file in os.listdir(input_dir):
if symbol_file.endswith('.svg'):
file_path = os.path.join(input_dir, symbol_file)
with open(file_path, 'r') as file:
soup = BeautifulSoup(file.read(), 'xml')
symbol_tag = soup.find('symbol')
if symbol_tag:
symbol_id = symbol_tag.get('id')
if symbol_id:
# Check if the ID is correctly formatted
if not symbol_id.startswith("icon-myapp-"):
errors.append(f"Error: ID '{symbol_id}' in file '{symbol_file}' does not match the format 'icon-myapp-SOME_NAME'.")
# Check for uniqueness
elif symbol_id in used_ids:
errors.append(f"Error: Duplicate ID '{symbol_id}' found in file '{symbol_file}'.")
else:
used_ids.add(symbol_id)
valid_symbol_found = True
valid_symbol_ids.append(symbol_id)
combined_svg_content += str(symbol_tag) + "\n"
else:
errors.append(f"Error: Symbol tag in file '{symbol_file}' does not have an 'id' attribute.")
# Close the SVG tag and write the combined content to the output file
combined_svg_content += '</svg>'
# Show errors
if errors:
for error in errors:
print(error)
# Display a message indicating the number of valid symbols found and whether the SVG was created
if valid_symbol_found:
print(f"Found {len(valid_symbol_ids)} valid symbols. They've been compiled to icons.svg.")
if valid_symbol_found:
with open(output_file_path, 'w') as output_file:
output_file.write(combined_svg_content)
else:
print("No valid symbols found.")
# List valid symbol IDs in a row
if valid_symbol_ids:
print("Valid symbol IDs:")
print(", ".join(valid_symbol_ids))
You could probably use the after_migrate hook, at least in a production context. For local development you could use bench execute or develop a custom bench command instead.