")
parts.append(f"
{chart_name}
")
parts.append(
f"
"
f"{s.get('chart_type', '')} · "
f"done {s.get('done', '?')}/{s.get('target', '?')} · "
f"ok {s['n_success']} · "
f"fail {s.get('n_fail', 0)} · "
f"fallback_png {s['n_fallback_png']} · "
f"empty {s.get('n_empty', 0)} · "
f"mean_svg {s.get('mean_size_kb', s.get('mean_final_svg_kb', '?'))}KB · "
f"mean_shapes {s.get('mean_shapes', s.get('mean_n_shapes', '?'))} · "
f"mean_time {s['mean_elapsed_s']}s
"
)
parts.append("
")
for t in by_tpl.get(chart_name, []):
card_cls = "card"
if t["ok"] != "True":
card_cls += " failed"
elif t["chart_svg_fallback_png"] == "True":
card_cls += " fb"
elif int(t.get("n_shapes") or 0) + int(t.get("n_text") or 0) < 8:
card_cls += " empty"
img_html = ""
if t["final_svg"]:
img_html = f"
"
elif t["chart_svg"]:
img_html = (
f"
"
f"render failed
"
)
label = (
f"{t['input'][:30]}
"
f"shapes={t['n_shapes']} t={t['elapsed_s']}s "
f"size={int(t['final_svg_bytes'])//1024}KB"
)
parts.append(
f"
"
)
parts.append("
")
parts.append("")
html_path.write_text("\n".join(parts))
return html_path
def main():
args = parse_args()
out_dir = Path(args.output_dir)
html_path = Path(args.out) if args.out else None
written = build_preview(out_dir, html_path)
print(f"Wrote {written}")
print(f"Open with: file://{written.resolve()}")
if __name__ == "__main__":
main()