spb/vquant Public MIT
VibeQuant — AI-powered institutional-grade financial intelligence platform.
TypeScript 84.3%
Python 11.7%
JavaScript 1.6%
CSS 1.5%
HTML 0.7%
1/*2 * =============================================================================3 * VibeQuant (vquant) — AI-Powered Financial Intelligence Platform4 * -----------------------------------------------------------------------------5 * File: client/src/utils/chartCapture.ts6 *7 * Author: Simon-Pierre Boucher8 * Contact: contact@spboucher.ai9 * Website: https://www.spboucher.ai10 * Demo: https://www.vquant.ai11 * License: MIT (see LICENSE)12 *13 * Copyright © 2026 Simon-Pierre Boucher. All rights reserved.14 * =============================================================================15 */1617import html2canvas from 'html2canvas';1819/**20 * Capture un élément spécifique (graphique, tableau, etc.) en PNG21 */22export async function captureChartToPNG(element: HTMLElement): Promise<string | null> {23 try {24 console.log('Capturing chart:', element.className);2526 const canvas = await html2canvas(element, {27 scale: 2,28 backgroundColor: '#ffffff',29 logging: false,30 useCORS: true,31 allowTaint: true,32 imageTimeout: 15000,33 });3435 const dataUrl = canvas.toDataURL('image/png', 0.95);36 console.log('Chart captured successfully, size:', canvas.width, 'x', canvas.height);3738 return dataUrl;39 } catch (error) {40 console.error('Error capturing chart:', error);41 return null;42 }43}4445/**46 * Trouve et capture tous les graphiques dans le contenu47 */48export async function captureAllCharts(contentElement: HTMLElement): Promise<{ element: HTMLElement; imageData: string }[]> {49 const results: { element: HTMLElement; imageData: string }[] = [];5051 // Sélecteurs pour les différents types de graphiques52 const chartSelectors = [53 '.recharts-wrapper', // Graphiques Recharts54 '[data-chart]', // Éléments marqués avec data-chart55 '.financial-chart', // Charts financiers custom56 'canvas', // Canvas directs57 'svg.recharts-surface', // SVG Recharts58 ];5960 for (const selector of chartSelectors) {61 const charts = contentElement.querySelectorAll(selector);62 console.log(`Found ${charts.length} charts for selector: ${selector}`);6364 for (const chart of charts) {65 const chartElement = chart as HTMLElement;6667 // Skip si déjà capturé (pour éviter les doublons)68 if (results.some(r => r.element === chartElement)) {69 continue;70 }7172 // Capturer le parent si c'est juste un SVG ou Canvas73 let elementToCapture = chartElement;74 if (chart.tagName.toLowerCase() === 'svg' || chart.tagName.toLowerCase() === 'canvas') {75 const parent = chartElement.parentElement;76 if (parent && parent.classList.contains('recharts-wrapper')) {77 elementToCapture = parent;78 }79 }8081 const imageData = await captureChartToPNG(elementToCapture);82 if (imageData) {83 results.push({84 element: elementToCapture,85 imageData86 });87 }88 }89 }9091 console.log(`Total charts captured: ${results.length}`);92 return results;93}94