import argparse
import os
import shutil
from textwrap import dedent
from arrg import app, argument
def snake_to_camel(snake_str):
components = snake_str.split('_')
return components[0] + ''.join(x.title() for x in components[1:])
@app(
description='Generate a JavaScript dictionary from val source files using imports.',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=dedent(
"""\
Examples:
%(prog)s ./src/tests ./frontend/src/lib/examples.js
%(prog)s /path/to/val/files /path/to/output.js
"""
),
)
class App:
source_dir: str = argument(help='Directory containing the val source files')
output_file: str = argument(help='Path to the output JavaScript file')
examples_dir: str = argument(
help='Path to the assets/examples directory', default=None, nargs='?'
)
def run(self) -> int:
try:
self.generate()
return 0
except Exception as e:
print(f'error: {e}')
return 1
def generate(self):
if not os.path.exists(self.source_dir):
raise FileNotFoundError(f"Source directory '{self.source_dir}' does not exist")
if self.examples_dir is None:
output_dir = os.path.dirname(self.output_file)
base_dir = os.path.dirname(output_dir)
self.examples_dir = os.path.join(base_dir, 'assets', 'examples')
os.makedirs(self.examples_dir, exist_ok=True)
os.makedirs(os.path.dirname(self.output_file), exist_ok=True)
val_files = sorted([f for f in os.listdir(self.source_dir) if f.endswith('.val')])
if not val_files:
print(f'Warning: No .val files found in {self.source_dir}')
return
for file in val_files:
source_file = os.path.join(self.source_dir, file)
target_file = os.path.join(self.examples_dir, file)
shutil.copy2(source_file, target_file)
print(f'Copied {file} to {self.examples_dir}')
imports = []
dictionary_entries = []
for file in val_files:
base_name = file.replace('.val', '')
var_name = snake_to_camel(base_name)
rel_path = os.path.relpath(self.examples_dir, os.path.dirname(self.output_file))
imports.append(f"import {var_name} from '{rel_path}/{file}?raw';")
dictionary_entries.append(f' {var_name}: {var_name}')
content = self._generate_js_dictionary(imports, dictionary_entries)
with open(self.output_file, 'w') as f:
f.write(content)
print(f'Successfully generated JS dictionary at {self.output_file}')
print(f'Processed {len(val_files)} val files')
def _generate_js_dictionary(self, imports, dictionary_entries):
lines = [
'// This file is generated by `example-generator`. Do not edit manually.',
'',
]
for import_line in imports:
lines.append(import_line)
lines.append('')
lines.append('const EXAMPLES = {')
dictionary_text = ',\n'.join(dictionary_entries)
lines.append(dictionary_text)
lines.append('};')
lines.append('')
lines.append('export default EXAMPLES;')
return '\n'.join(lines)
if __name__ == '__main__':
exit(App.from_args().run())