$ cat node-template.py
Infographic Renderer
// Renders AntV Infographic DSL syntax into an image. Accepts the declarative DSL format (starting with 'infographic <template-name>') and produces a PNG or SVG output. Use this to render manually written or LLM-generated infographic syntax.
Process
Document
template.py
1import os2import sys3import json4import traceback56try:7 import requests8except ImportError:9 import subprocess10 subprocess.check_call([sys.executable, "-m", "pip", "install", "requests"])11 import requests1213EMBLEMA_API_BASE_URL = os.getenv("EMBLEMA_API_BASE_URL", "http://localhost:3000")14USER_TOKEN = os.getenv("USER_TOKEN")15OUTPUT_DIR = "/data/output"161718def render_infographic(syntax, fmt="png", width=1920, height=1080, scale=2):19 """Call the Emblema infographic rendering API."""20 url = f"{EMBLEMA_API_BASE_URL}/api/v2/helpers/infographic/render"2122 headers = {23 "Content-Type": "application/json",24 }25 if USER_TOKEN:26 headers["Authorization"] = f"Bearer {USER_TOKEN}"2728 payload = {29 "syntax": syntax,30 "format": fmt,31 "width": width,32 "height": height,33 "scale": scale,34 }3536 print(f"Calling render API: {url}", file=sys.stderr)37 print(f"Payload: format={fmt}, width={width}, height={height}, scale={scale}, syntax_length={len(syntax)}", file=sys.stderr)3839 response = requests.post(url, headers=headers, json=payload, timeout=60)4041 if response.status_code != 200:42 try:43 error_detail = response.json()44 error_msg = error_detail.get("message", response.text)45 except Exception:46 error_msg = response.text47 raise RuntimeError(f"Render API returned {response.status_code}: {error_msg}")4849 return response.content, response.headers.get("Content-Type", "image/png")505152def main():53 try:54 input_json = sys.stdin.read()55 execution_input = json.loads(input_json)56 inputs = execution_input.get("inputs", {})5758 syntax = inputs.get("syntax", "")59 fmt = inputs.get("format", "png")60 width = int(inputs.get("width", 1920))61 height = int(inputs.get("height", 1080))62 scale = int(inputs.get("scale", 2))6364 if not syntax or not syntax.strip():65 raise ValueError("Infographic DSL syntax is required")6667 if not syntax.strip().startswith("infographic "):68 raise ValueError("DSL syntax must start with 'infographic <template-name>'")6970 os.makedirs(OUTPUT_DIR, exist_ok=True)7172 # Call rendering API73 image_data, content_type = render_infographic(syntax, fmt, width, height, scale)7475 # Determine file extension from format76 ext = "svg" if fmt == "svg" else "png"77 out_filename = f"infographic.{ext}"78 out_path = os.path.join(OUTPUT_DIR, out_filename)7980 with open(out_path, "wb") as f:81 f.write(image_data)8283 print(f"Rendered infographic: {out_filename} ({len(image_data)} bytes)", file=sys.stderr)8485 output = {86 "image": out_filename,87 }88 print(json.dumps(output, indent=2))8990 except Exception as e:91 error_output = {92 "error": str(e),93 "errorType": type(e).__name__,94 "traceback": traceback.format_exc(),95 }96 print(json.dumps(error_output), file=sys.stderr)97 sys.exit(1)9899100if __name__ == "__main__":101 main()