Initial commit
This commit is contained in:
125
skills/frontend-component/functions/props_interface_generator.py
Executable file
125
skills/frontend-component/functions/props_interface_generator.py
Executable file
@@ -0,0 +1,125 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate TypeScript props interface from user input.
|
||||
|
||||
Converts simple prop specifications into proper TypeScript interface definitions.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
from typing import List, Tuple
|
||||
|
||||
# Type mapping from simple names to TypeScript types
|
||||
TYPE_MAPPING = {
|
||||
'string': 'string',
|
||||
'str': 'string',
|
||||
'number': 'number',
|
||||
'num': 'number',
|
||||
'int': 'number',
|
||||
'boolean': 'boolean',
|
||||
'bool': 'boolean',
|
||||
'function': '() => void',
|
||||
'func': '() => void',
|
||||
'callback': '() => void',
|
||||
'array': 'any[]',
|
||||
'arr': 'any[]',
|
||||
'object': 'Record<string, any>',
|
||||
'obj': 'Record<string, any>',
|
||||
'react-node': 'React.ReactNode',
|
||||
'node': 'React.ReactNode',
|
||||
'children': 'React.ReactNode',
|
||||
'element': 'React.ReactElement',
|
||||
'style': 'React.CSSProperties',
|
||||
'class': 'string',
|
||||
'classname': 'string',
|
||||
}
|
||||
|
||||
def parse_prop_spec(prop_spec: str) -> Tuple[str, str, bool]:
|
||||
"""
|
||||
Parse a single prop specification.
|
||||
|
||||
Format: "propName:type" or "propName:type:optional"
|
||||
|
||||
Args:
|
||||
prop_spec: Prop specification string
|
||||
|
||||
Returns:
|
||||
tuple: (prop_name, ts_type, is_optional)
|
||||
"""
|
||||
parts = prop_spec.strip().split(':')
|
||||
|
||||
if len(parts) < 2:
|
||||
raise ValueError(f"Invalid prop specification: '{prop_spec}'. Expected format: 'propName:type' or 'propName:type:optional'")
|
||||
|
||||
prop_name = parts[0].strip()
|
||||
type_name = parts[1].strip().lower()
|
||||
is_optional = len(parts) > 2 and parts[2].strip().lower() in ('optional', 'opt', '?', 'true')
|
||||
|
||||
# Map to TypeScript type
|
||||
ts_type = TYPE_MAPPING.get(type_name, type_name)
|
||||
|
||||
return prop_name, ts_type, is_optional
|
||||
|
||||
def generate_props_interface(name: str, props: List[str], include_common: bool = True) -> str:
|
||||
"""
|
||||
Generate TypeScript props interface.
|
||||
|
||||
Args:
|
||||
name: Component name (will become {name}Props)
|
||||
props: List of prop specifications
|
||||
include_common: Whether to include common props (children, className, etc.)
|
||||
|
||||
Returns:
|
||||
str: TypeScript interface definition
|
||||
"""
|
||||
interface_name = f"{name}Props"
|
||||
lines = [f"interface {interface_name} {{"]
|
||||
|
||||
# Add custom props
|
||||
for prop_spec in props:
|
||||
if not prop_spec.strip():
|
||||
continue
|
||||
|
||||
prop_name, ts_type, is_optional = parse_prop_spec(prop_spec)
|
||||
optional_marker = '?' if is_optional else ''
|
||||
lines.append(f" {prop_name}{optional_marker}: {ts_type};")
|
||||
|
||||
# Add common props if requested
|
||||
if include_common:
|
||||
# Only add children if not already specified
|
||||
if not any('children' in prop for prop in props):
|
||||
lines.append(" children?: React.ReactNode;")
|
||||
|
||||
# Only add className if not already specified
|
||||
if not any('className' in prop or 'class' in prop.lower() for prop in props):
|
||||
lines.append(" className?: string;")
|
||||
|
||||
lines.append("}")
|
||||
|
||||
return '\n'.join(lines)
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Generate TypeScript props interface')
|
||||
parser.add_argument('--name', required=True, help='Component name')
|
||||
parser.add_argument('--props', required=True, help='Comma-separated prop specifications (e.g., "userId:string,onUpdate:function,isActive:boolean:optional")')
|
||||
parser.add_argument('--no-common', action='store_true', help='Do not include common props (children, className)')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Parse prop specifications
|
||||
prop_specs = [p.strip() for p in args.props.split(',') if p.strip()]
|
||||
|
||||
try:
|
||||
interface = generate_props_interface(
|
||||
args.name,
|
||||
prop_specs,
|
||||
include_common=not args.no_common
|
||||
)
|
||||
print(interface)
|
||||
sys.exit(0)
|
||||
except ValueError as e:
|
||||
print(f"❌ Error: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user