'ok','capabilities'=>['mermaid_svg','chart_png','pdf','graphviz']]));} $in=json_decode(file_get_contents('php://input'),true)?:[]; $text=trim($in['text']??''); $mode=trim($in['mode']??'auto'); // auto|mermaid|chart|pdf if(!$text)die(json_encode(['error'=>'text required'])); $id=uniqid('wr_'); $assets=[]; // ═══ 1. MERMAID → SVG ═══ function render_mermaid($code,$id,$idx){ $mmd_file="/tmp/{$id}_m{$idx}.mmd"; $svg_file="/var/www/html/test-report/render/{$id}_m{$idx}.svg"; @mkdir("/var/www/html/test-report/render",0777,true); file_put_contents($mmd_file,$code); $png_file=str_replace('.svg','.png',$svg_file); $out=shell_exec("python3 /opt/mermaid-render.py {$mmd_file} {$png_file} 2>&1"); $svg_file=$png_file; if(file_exists($svg_file)){ return ['type'=>'mermaid_png','url'=>"/test-report/render/{$id}_m{$idx}.svg",'size'=>filesize($svg_file)]; } return ['type'=>'mermaid_error','error'=>$out]; } // ═══ 2. CHART → PNG (matplotlib) ═══ function render_chart($spec,$id,$idx){ $json_file="/tmp/{$id}_c{$idx}.json"; $png_file="/var/www/html/test-report/render/{$id}_c{$idx}.png"; @mkdir("/var/www/html/test-report/render",0777,true); file_put_contents($json_file,json_encode($spec)); $py=<<<'PY' import json,sys,warnings warnings.filterwarnings("ignore") import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import matplotlib.ticker as ticker d=json.load(open(sys.argv[1])) t=d.get("type","bar") fig,ax=plt.subplots(figsize=(8,4)) ax.set_facecolor("#0d1117") fig.patch.set_facecolor("#0d1117") ax.tick_params(colors="#c8d6e5") ax.xaxis.label.set_color("#c8d6e5") ax.yaxis.label.set_color("#c8d6e5") for s in ax.spines.values():s.set_color("#21262d") labels=d.get("labels",[]) values=d.get("values",[]) colors=d.get("colors",["#7c3aed","#06b6d4","#10b981","#f59e0b","#ef4444","#ec4899"]) if t=="bar": ax.bar(labels,values,color=colors[:len(labels)]) elif t=="pie": ax.pie(values,labels=labels,colors=colors[:len(labels)],autopct="%1.0f%%",textprops={"color":"#c8d6e5"}) elif t=="line": ax.plot(labels,values,color="#7c3aed",linewidth=2,marker="o") ax.fill_between(range(len(labels)),values,alpha=0.2,color="#7c3aed") if d.get("title"):ax.set_title(d["title"],color="#fff",fontsize=13,fontweight="bold") if d.get("xlabel"):ax.set_xlabel(d["xlabel"]) if d.get("ylabel"):ax.set_ylabel(d["ylabel"]) plt.tight_layout() plt.savefig(sys.argv[2],dpi=150,bbox_inches="tight",facecolor="#0d1117") print("OK") PY; $py_file="/tmp/{$id}_c{$idx}.py"; file_put_contents($py_file,$py); $out=shell_exec("python3 {$py_file} {$json_file} {$png_file} 2>&1"); if(file_exists($png_file)){ return ['type'=>'chart_png','url'=>"/test-report/render/{$id}_c{$idx}.png",'size'=>filesize($png_file)]; } return ['type'=>'chart_error','error'=>$out]; } // ═══ 3. GRAPHVIZ → SVG ═══ function render_graphviz($code,$id,$idx){ $dot_file="/tmp/{$id}_g{$idx}.dot"; $svg_file="/var/www/html/test-report/render/{$id}_g{$idx}.svg"; @mkdir("/var/www/html/test-report/render",0777,true); file_put_contents($dot_file,$code); shell_exec("dot -Tsvg {$dot_file} -o {$svg_file} 2>&1"); if(file_exists($svg_file)){ return ['type'=>'graphviz_svg','url'=>"/test-report/render/{$id}_g{$idx}.svg"]; } return null; } // ═══ AUTO-DETECT & RENDER ═══ $rendered_text=$text; $midx=0; // Find mermaid code blocks if(preg_match_all('/```(?:mermaid)?\s*((?:graph |flowchart |sequenceDiagram|classDiagram|gantt|pie|erDiagram|stateDiagram|journey)[\s\S]*?)```/i',$text,$matches)){ foreach($matches[1] as $code){ $result=render_mermaid(trim($code),$id,$midx); $assets[]=$result; if(isset($result['url'])){ $svg_tag='Mermaid diagram'; $rendered_text=str_replace($matches[0][$midx],$svg_tag,$rendered_text); } $midx++; } } // Find graphviz if(preg_match_all('/```(?:dot|graphviz)\s*(digraph[\s\S]*?)```/i',$text,$gmatches)){ foreach($gmatches[1] as $i=>$code){ $result=render_graphviz(trim($code),$id,$i); if($result)$assets[]=$result; } } // Find chart requests (JSON chart spec) if(preg_match_all('/```chart\s*(\{[\s\S]*?\})\s*```/i',$text,$cmatches)){ foreach($cmatches[1] as $i=>$spec){ $data=json_decode($spec,true); if($data){ $result=render_chart($data,$id,$i); $assets[]=$result; if(isset($result['url'])){ $img_tag='Chart'; $rendered_text=str_replace($cmatches[0][$i],$img_tag,$rendered_text); } } } } die(json_encode([ 'rendered_text'=>$rendered_text, 'assets'=>$assets, 'asset_count'=>count($assets), 'original_length'=>strlen($text), 'rendered_length'=>strlen($rendered_text) ]));