mirror of
https://github.com/thecyberlearn/quantum-ai-v2.git
synced 2026-08-18 12:52:59 +00:00
Fix data analyzer TypeError and enhance markdown parsing
## Issues Fixed - Fixed TypeError: text.replace is not a function in parseMarkdown - Enhanced type checking for null/undefined inputs in agent-utils.js - Data analyzer now properly handles all response data types ## Enhancements - Improved parseMarkdown function with better type safety - Enhanced markdown parsing with proper HTML styling - Added custom parseMarkdownToHTML for data analyzer with rich formatting - Better handling of headers, lists, bold text, and paragraphs ## Data Analyzer Improvements - Custom markdown parser with styled headers and lists - Proper content extraction priority: report_text > insights_summary > raw_response.analysis - Enhanced visual formatting with CSS variables for consistent theming - Better error handling and fallback content ## Technical Changes - Added typeof checks to prevent non-string inputs causing errors - Enhanced bullet point and numbered list conversion - Improved paragraph formatting and line break handling - Consistent styling across all markdown elements ## Test Results - Data analyzer successfully processes PDF files - Returns proper JSON responses with formatted analysis - Markdown parsing works correctly with complex content structure - No more JavaScript type errors in console 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
8189cca054
commit
f83c2497cc
@ -99,7 +99,7 @@ class DataAnalysisAgentProcessor(StandardWebhookProcessor):
|
||||
}
|
||||
|
||||
# Use analysis text for multiple fields for compatibility
|
||||
insights_summary = analysis_text[:500] + '...' if len(analysis_text) > 500 else analysis_text
|
||||
insights_summary = analysis_text
|
||||
report_text = analysis_text
|
||||
raw_response = response_data
|
||||
|
||||
|
||||
@ -676,16 +676,108 @@
|
||||
});
|
||||
});
|
||||
|
||||
// Display analysis results with markdown parsing
|
||||
// Display analysis results with custom Data Analyzer formatting
|
||||
function displayResults(result) {
|
||||
AgentUtils.displayResults({
|
||||
result: result,
|
||||
resultsId: 'analysisResults',
|
||||
contentId: 'analysisContent',
|
||||
defaultMessage: 'Data analysis completed successfully!',
|
||||
successMessage: '✅ Data analysis completed and payment processed!',
|
||||
errorMessage: '❌ Failed to analyze data - no charge applied'
|
||||
const resultsContainer = document.getElementById('analysisResults');
|
||||
const contentElement = document.getElementById('analysisContent');
|
||||
|
||||
if (!resultsContainer || !contentElement) {
|
||||
console.error('Results elements not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Update wallet balance if provided
|
||||
if (result.wallet_balance !== undefined) {
|
||||
updateWalletBalance(result.wallet_balance);
|
||||
}
|
||||
|
||||
// Handle errors
|
||||
if (result.error) {
|
||||
AgentUtils.showToast(`❌ ${result.error}`, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract content with priority: report_text > insights_summary > raw_response.analysis
|
||||
let content = '';
|
||||
|
||||
if (result.report_text && typeof result.report_text === 'string') {
|
||||
content = result.report_text;
|
||||
} else if (result.insights_summary && typeof result.insights_summary === 'string') {
|
||||
content = result.insights_summary;
|
||||
} else if (result.raw_response && result.raw_response.analysis && typeof result.raw_response.analysis === 'string') {
|
||||
content = result.raw_response.analysis;
|
||||
} else {
|
||||
content = 'Data analysis completed successfully!';
|
||||
}
|
||||
|
||||
// Parse markdown content to HTML
|
||||
const formattedContent = parseMarkdownToHTML(content);
|
||||
|
||||
// Update content
|
||||
contentElement.innerHTML = formattedContent;
|
||||
|
||||
// Show results
|
||||
resultsContainer.style.display = 'block';
|
||||
resultsContainer.scrollIntoView({ behavior: 'smooth' });
|
||||
|
||||
// Show success message
|
||||
const successMessage = result.success ? '✅ Data analysis completed and payment processed!' : '✅ Data analysis completed!';
|
||||
AgentUtils.showToast(successMessage, 'success');
|
||||
}
|
||||
|
||||
// Enhanced markdown parser for Data Analyzer results
|
||||
function parseMarkdownToHTML(markdown) {
|
||||
if (!markdown || typeof markdown !== 'string') {
|
||||
return '<p>No content available.</p>';
|
||||
}
|
||||
|
||||
let html = markdown;
|
||||
|
||||
// Convert headers (### Header, ## Header, # Header)
|
||||
html = html.replace(/^### (.*$)/gm, '<h3 style="font-size: 18px; font-weight: 600; color: var(--text-primary); margin: 20px 0 12px 0; border-bottom: 2px solid var(--success-green); padding-bottom: 8px;">$1</h3>');
|
||||
html = html.replace(/^## (.*$)/gm, '<h2 style="font-size: 20px; font-weight: 600; color: var(--text-primary); margin: 24px 0 16px 0; border-bottom: 2px solid var(--success-green); padding-bottom: 8px;">$1</h2>');
|
||||
html = html.replace(/^# (.*$)/gm, '<h1 style="font-size: 22px; font-weight: 600; color: var(--text-primary); margin: 28px 0 18px 0; border-bottom: 2px solid var(--success-green); padding-bottom: 10px;">$1</h1>');
|
||||
|
||||
// Convert bold text (**text** or __text__)
|
||||
html = html.replace(/\*\*(.*?)\*\*/g, '<strong style="font-weight: 600; color: var(--text-primary);">$1</strong>');
|
||||
html = html.replace(/__(.*?)__/g, '<strong style="font-weight: 600; color: var(--text-primary);">$1</strong>');
|
||||
|
||||
// Convert italic text (*text* or _text_)
|
||||
html = html.replace(/\*(.*?)\*/g, '<em style="font-style: italic; color: var(--text-secondary);">$1</em>');
|
||||
html = html.replace(/_(.*?)_/g, '<em style="font-style: italic; color: var(--text-secondary);">$1</em>');
|
||||
|
||||
// Convert bullet points (- item or * item)
|
||||
html = html.replace(/^[\s]*[-\*]\s+(.*)$/gm, '<li style="margin: 8px 0; padding-left: 8px; color: var(--text-primary);">$1</li>');
|
||||
|
||||
// Wrap consecutive list items in ul tags
|
||||
html = html.replace(/(<li[^>]*>.*?<\/li>\s*)+/gs, function(match) {
|
||||
return `<ul style="margin: 16px 0; padding-left: 20px; list-style-type: disc; color: var(--success-green);">${match}</ul>`;
|
||||
});
|
||||
|
||||
// Convert numbered lists (1. item, 2. item)
|
||||
html = html.replace(/^\s*\d+\.\s+(.*)$/gm, '<li style="margin: 8px 0; padding-left: 8px; color: var(--text-primary);">$1</li>');
|
||||
|
||||
// Wrap consecutive numbered list items in ol tags
|
||||
html = html.replace(/(<li[^>]*>.*?<\/li>\s*)+/gs, function(match) {
|
||||
if (match.includes('ul style')) return match; // Skip if already wrapped in ul
|
||||
return `<ol style="margin: 16px 0; padding-left: 20px; list-style-type: decimal; color: var(--success-green);">${match}</ol>`;
|
||||
});
|
||||
|
||||
// Convert line breaks to paragraphs
|
||||
const paragraphs = html.split(/\n\s*\n/);
|
||||
html = paragraphs.map(p => {
|
||||
const trimmed = p.trim();
|
||||
if (trimmed === '') return '';
|
||||
|
||||
// Skip if already wrapped in HTML tags
|
||||
if (trimmed.startsWith('<h') || trimmed.startsWith('<ul') || trimmed.startsWith('<ol') || trimmed.startsWith('<li')) {
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
return `<p style="margin: 12px 0; line-height: 1.6; color: var(--text-primary);">${trimmed}</p>`;
|
||||
}).filter(p => p !== '').join('');
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
// Track polling and results to prevent duplicates
|
||||
|
||||
@ -5,18 +5,75 @@
|
||||
|
||||
window.AgentUtils = {
|
||||
/**
|
||||
* Simple Text Formatter
|
||||
* Cleans AI-generated text and converts to readable HTML
|
||||
* Enhanced Markdown Parser
|
||||
* Converts markdown syntax to styled HTML with proper formatting
|
||||
*/
|
||||
parseMarkdown(text) {
|
||||
if (!text) return '';
|
||||
// Handle null, undefined, or non-string inputs
|
||||
if (!text || typeof text !== 'string') {
|
||||
return '';
|
||||
}
|
||||
|
||||
return text
|
||||
.replace(/\*\*/g, '') // Remove markdown bold syntax
|
||||
.replace(/\#{1,3}\s/g, '') // Remove header syntax
|
||||
.replace(/\n{3,}/g, '\n\n') // Reduce excessive line breaks
|
||||
.replace(/\n/g, '<br>') // Convert line breaks to HTML
|
||||
.trim();
|
||||
let html = text;
|
||||
|
||||
// Convert headers with proper styling
|
||||
html = html.replace(/^### (.*$)/gm, '<h3 style="font-size: 1.1em; font-weight: 600; margin: 12px 0 8px 0; color: #374151;">$1</h3>');
|
||||
html = html.replace(/^## (.*$)/gm, '<h2 style="font-size: 1.2em; font-weight: 600; margin: 14px 0 8px 0; color: #374151;">$1</h2>');
|
||||
html = html.replace(/^# (.*$)/gm, '<h1 style="font-size: 1.3em; font-weight: 600; margin: 16px 0 10px 0; color: #374151;">$1</h1>');
|
||||
|
||||
// Convert bold text
|
||||
html = html.replace(/\*\*(.*?)\*\*/g, '<strong style="font-weight: 500; color: #1f2937;">$1</strong>');
|
||||
|
||||
// Convert bullet points to proper lists
|
||||
const lines = html.split('\n');
|
||||
let inList = false;
|
||||
let processedLines = [];
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i].trim();
|
||||
|
||||
if (line.startsWith('- ')) {
|
||||
if (!inList) {
|
||||
processedLines.push('<ul style="margin: 8px 0; padding-left: 20px;">');
|
||||
inList = true;
|
||||
}
|
||||
processedLines.push(`<li style="margin: 3px 0; color: #4b5563;">${line.substring(2).trim()}</li>`);
|
||||
} else {
|
||||
if (inList) {
|
||||
processedLines.push('</ul>');
|
||||
inList = false;
|
||||
}
|
||||
processedLines.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
if (inList) {
|
||||
processedLines.push('</ul>');
|
||||
}
|
||||
|
||||
html = processedLines.join('\n');
|
||||
|
||||
// Reduce excessive line breaks and convert to paragraphs
|
||||
html = html.replace(/\n{3,}/g, '\n\n');
|
||||
|
||||
// Convert double line breaks to paragraph breaks
|
||||
const paragraphs = html.split('\n\n');
|
||||
html = paragraphs
|
||||
.filter(p => p.trim() !== '')
|
||||
.map(p => {
|
||||
const trimmed = p.trim();
|
||||
// Don't wrap headers or lists in paragraphs
|
||||
if (trimmed.startsWith('<h') || trimmed.startsWith('<ul') || trimmed.startsWith('</ul>') || trimmed.includes('<li')) {
|
||||
return trimmed;
|
||||
}
|
||||
return `<p style="margin: 8px 0; line-height: 1.4; color: #4b5563;">${trimmed}</p>`;
|
||||
})
|
||||
.join('');
|
||||
|
||||
// Convert remaining single line breaks to <br> tags
|
||||
html = html.replace(/\n/g, '<br>');
|
||||
|
||||
return html.trim();
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user