Json to img
import React, { useRef, useState } from 'react';
// JSON-to-Preview-Generator
// A single-file React component that:
// 1) Accepts a .json file (an Elementor/CartFlows export like your file)
// 2) Parses out common design elements: images, headings, buttons, and paragraph text
// 3) Renders a simple visual preview (mobile-friendly card layout)
// 4) Lets the user export the rendered preview as a PNG using html2canvas
//
// Usage notes:
// - This is a client-side-only tool. Drop the component into a React app that uses Tailwind CSS.
// - Install dependency: `npm install html2canvas` in your project.
// - CORS: If image URLs block cross-origin requests, html2canvas may not capture them. The component tries to prefetch images as blobs to reduce CORS issues, but some hosts still block it.
// - The parser is intentionally permissive: it scans the JSON for likely image URLs, heading text, button labels, and long text blocks.
import html2canvas from 'html2canvas';
export default function JsonPreviewGenerator() {
  const [jsonName, setJsonName] = useState('');
  const [parsed, setParsed] = useState({ images: [], headings: [], buttons: [], paragraphs: [] });
  const [error, setError] = useState('');
  const [loading, setLoading] = useState(false);
  const previewRef = useRef(null);
  // Basic helpers to extract data from deeply nested JSON structure
  function collectStrings(obj, found = { images: new Set(), headings: new Set(), buttons: new Set(), paragraphs: new Set() }) {
    if (!obj) return found;
    if (typeof obj === 'string') {
      const s = obj.trim();
      // image url heuristics
      if (/https?:\/\/.+\.(png|jpe?g|webp|gif)(\?.*)?$/i.test(s)) found.images.add(s);
      // elementor image object pattern contains "url": "https..."
      if (/^https?:\/\/.+/i.test(s) && /uploads\//i.test(s)) found.images.add(s);
      // heading heuristics: reasonably short and contains letters (Bangla or Latin)
      if (s.length > 3 && s.length < 120 && /[\p{L}]/u.test(s)) {
        // treat very short as heading/button
        if (s.length <= 40 && /^(place order|order|add to cart|অর্ডার|অর্ডার কর|order now)/i.test(s)) found.buttons.add(s);
        else if (s.length <= 40) found.headings.add(s);
        else found.paragraphs.add(s);
      }
    } else if (Array.isArray(obj)) {
      for (const el of obj) collectStrings(el, found);
    } else if (typeof obj === 'object') {
      for (const k of Object.keys(obj)) collectStrings(obj[k], found);
    }
    return found;
  }
  async function handleFile(e) {
    setError('');
    setLoading(true);
    try {
      const file = e.target.files[0];
      if (!file) return setLoading(false);
      setJsonName(file.name);
      const text = await file.text();
      let data = null;
      try { data = JSON.parse(text); }
      catch (err) {
        // some exports wrap JSON as a string array like ["{...}"]
        try {
          const alt = JSON.parse(text.replace(/^"/, '').replace(/"$/, '').replace(/\\"/g, '"'));
          data = alt;
        } catch (err2) {
          throw new Error('Invalid JSON file');
        }
      }
      const found = collectStrings(data);
      // Convert sets -> arrays (limit length)
      const images = Array.from(found.images).slice(0, 8);
      const headings = Array.from(found.headings).slice(0, 6);
      const buttons = Array.from(found.buttons).slice(0, 6);
      const paragraphs = Array.from(found.paragraphs).slice(0, 6);
      // Prefetch images & convert to object URLs when possible to minimize CORS problems
      const prefetched = await Promise.all(images.map(async (url) => {
        try {
          // try fetch as blob
          const resp = await fetch(url, { mode: 'cors' });
          if (!resp.ok) throw new Error('fetch failed');
          const blob = await resp.blob();
          const objectUrl = URL.createObjectURL(blob);
          return { original: url, preview: objectUrl };
        } catch (err) {
          // fallback: use original url (may cause html2canvas tainting)
          return { original: url, preview: url };
        }
      }));
      setParsed({ images: prefetched, headings, buttons, paragraphs });
    } catch (err) {
      console.error(err);
      setError(err.message || 'ফাইল পড়তে সমস্যা হয়েছে');
    } finally {
      setLoading(false);
    }
  }
  async function exportAsImage() {
    if (!previewRef.current) return;
    try {
      setLoading(true);
      // html2canvas options
      const canvas = await html2canvas(previewRef.current, { useCORS: true, scale: 2, allowTaint: true });
      const dataUrl = canvas.toDataURL('image/png');
      const a = document.createElement('a');
      a.href = dataUrl;
      a.download = (jsonName ? jsonName.replace(/\.[^.]+$/, '') : 'preview') + '-preview.png';
      document.body.appendChild(a);
      a.click();
      a.remove();
    } catch (err) {
      console.error(err);
      setError('Image export failed. কিছু ছবি CORS ব্লক করেছে বলে হতে পারে.');
    } finally {
      setLoading(false);
    }
  }
  return (
    
      
        
      
  );
}
JSON → Visual Preview Generator
Upload an Elementor / CartFlows JSON export and get a visual preview image. (Client-side)
        
        
        {loading && 
      {error && Processing...
}
      {error}
}
      
        {/* Header */}
        
          
            
        
        {/* Hero image */}
        
          
            
          
            
              
            {parsed.buttons[0] ? (
              
            ) : (
              
            )}
            {parsed.buttons[1] && }
          
        
        {/* Footer small gallery */}
        
      
            {parsed.images[0] ?  :
 : 
          Logo
}
          {parsed.headings[0] || 'Product / Page Title'}
{parsed.paragraphs[0] ? parsed.paragraphs[0].slice(0, 120) + (parsed.paragraphs[0].length>120? '...':'') : 'Short description goes here.'}
          
          {parsed.images[1] ?  :
 : 
        {/* Gallery */}
        Hero image
}
        
          {parsed.images.slice(2, 6).map((it, idx) => (
            
               ))}
            
          ))}
        
        {/* Description + CTA */}
        {parsed.headings[1] || 'About this item'}
{parsed.paragraphs[1] || 'This preview is generated from your JSON file. If you want a different layout, edit the tool or the JSON.'}
Price
              ৳ ২০০
            
          {parsed.images.slice(6, 10).map((it, idx) => (
            
               ))}
            
          ))}
        
      Tip: If exported PNG has missing images, those image hosts may block cross-origin fetch. Try hosting images on an allowlisted CDN or upload images to a server you control.
     
.webp) 
 
 
 
 
 
 
 
