Spaces:
Running
Running
Update index.html
Browse files- index.html +348 -21
index.html
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
-
|
|
|
2 |
<html lang="en">
|
3 |
<head>
|
4 |
<meta charset="UTF-8">
|
@@ -293,13 +294,14 @@
|
|
293 |
<button id="uploadBtn" class="bg-blue-500 hover:bg-blue-600 text-white py-3 px-4 rounded-lg flex items-center justify-center transition">
|
294 |
<i class="fas fa-upload mr-2"></i> Upload File
|
295 |
</button>
|
296 |
-
<button id="pasteBtn" class="bg-green-500 hover:green-600 text-white py-3 px-4 rounded-lg flex items-center justify-center transition">
|
297 |
<i class="fas fa-paste mr-2"></i> Paste Text
|
298 |
</button>
|
299 |
<div id="dropzone" class="dropzone bg-gray-50 py-3 px-4 rounded-lg flex items-center justify-center cursor-pointer">
|
300 |
<div class="text-center">
|
301 |
<i class="fas fa-file-import text-2xl text-gray-400 mb-1"></i>
|
302 |
<p class="text-gray-500">Drag & Drop File</p>
|
|
|
303 |
</div>
|
304 |
</div>
|
305 |
</div>
|
@@ -2631,51 +2633,159 @@
|
|
2631 |
}
|
2632 |
});
|
2633 |
|
2634 |
-
//
|
2635 |
function handleFile(file) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2636 |
const fileType = file.type;
|
2637 |
const fileName = file.name.toLowerCase();
|
|
|
2638 |
|
2639 |
-
|
2640 |
-
|
2641 |
-
|
2642 |
-
|
2643 |
-
|
2644 |
-
|
2645 |
-
|
2646 |
-
|
2647 |
-
|
2648 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2649 |
}
|
2650 |
}
|
2651 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2652 |
function readTextFile(file) {
|
2653 |
const reader = new FileReader();
|
2654 |
reader.onload = (e) => {
|
2655 |
-
|
|
|
|
|
|
|
2656 |
};
|
2657 |
-
reader.
|
|
|
|
|
|
|
|
|
2658 |
}
|
2659 |
|
|
|
2660 |
function readPDFFile(file) {
|
2661 |
-
// Check if PDF.js is available
|
2662 |
if (typeof pdfjsLib === 'undefined') {
|
2663 |
-
showToast('PDF.js not loaded.
|
|
|
2664 |
return;
|
2665 |
}
|
2666 |
|
2667 |
-
|
2668 |
-
documentContent.innerHTML = '<div class="text-center py-8"><div class="loading-spinner mx-auto"></div><p class="text-gray-500 mt-2">Processing PDF file...</p></div>';
|
2669 |
|
2670 |
-
|
2671 |
-
pdfjsLib.getDocument(URL.createObjectURL(file)).promise.then(pdf => {
|
2672 |
let text = '';
|
2673 |
const numPages = pdf.numPages;
|
2674 |
const pagePromises = [];
|
2675 |
|
|
|
|
|
|
|
2676 |
for (let i = 1; i <= numPages; i++) {
|
2677 |
pagePromises.push(pdf.getPage(i).then(page => {
|
2678 |
return page.getTextContent().then(textContent => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2679 |
return textContent.items.map(item => item.str).join(' ');
|
2680 |
});
|
2681 |
}));
|
@@ -2684,16 +2794,233 @@
|
|
2684 |
Promise.all(pagePromises).then(pagesText => {
|
2685 |
text = pagesText.join('\n\n');
|
2686 |
setDocumentContent(text);
|
|
|
|
|
|
|
2687 |
}).catch(error => {
|
2688 |
console.error('Error extracting PDF text:', error);
|
2689 |
showToast('Failed to extract text from PDF', 'error');
|
|
|
|
|
2690 |
});
|
2691 |
}).catch(error => {
|
2692 |
console.error('Error loading PDF:', error);
|
2693 |
showToast('Failed to load PDF file', 'error');
|
|
|
|
|
2694 |
});
|
2695 |
}
|
2696 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2697 |
// Set document content
|
2698 |
function setDocumentContent(text) {
|
2699 |
currentText = text;
|
|
|
1 |
+
<input type="file" id="fileInput" class="hidden" accept=".txt,.pdf,.doc,.docx,.odt,.rtf,.md,.markdown,.json,.html,.htm,.xml,.csv,.epub"></antml:parameter>
|
2 |
+
<parameter name="old_str"> <input type="file" id="fileInput" class="hidden" accept=".txt,.pdf,.doc,.docx,.odt,.rtf"><!DOCTYPE html>
|
3 |
<html lang="en">
|
4 |
<head>
|
5 |
<meta charset="UTF-8">
|
|
|
294 |
<button id="uploadBtn" class="bg-blue-500 hover:bg-blue-600 text-white py-3 px-4 rounded-lg flex items-center justify-center transition">
|
295 |
<i class="fas fa-upload mr-2"></i> Upload File
|
296 |
</button>
|
297 |
+
<button id="pasteBtn" class="bg-green-500 hover:bg-green-600 text-white py-3 px-4 rounded-lg flex items-center justify-center transition">
|
298 |
<i class="fas fa-paste mr-2"></i> Paste Text
|
299 |
</button>
|
300 |
<div id="dropzone" class="dropzone bg-gray-50 py-3 px-4 rounded-lg flex items-center justify-center cursor-pointer">
|
301 |
<div class="text-center">
|
302 |
<i class="fas fa-file-import text-2xl text-gray-400 mb-1"></i>
|
303 |
<p class="text-gray-500">Drag & Drop File</p>
|
304 |
+
<p class="text-xs text-gray-400 mt-1">Supports: TXT, PDF, DOC/DOCX, RTF, MD, JSON, HTML, XML, CSV</p>
|
305 |
</div>
|
306 |
</div>
|
307 |
</div>
|
|
|
2633 |
}
|
2634 |
});
|
2635 |
|
2636 |
+
// Enhanced file processing with size validation and progress
|
2637 |
function handleFile(file) {
|
2638 |
+
// Validate file size (50MB limit)
|
2639 |
+
const maxSize = 50 * 1024 * 1024; // 50MB
|
2640 |
+
if (file.size > maxSize) {
|
2641 |
+
showToast('File too large. Please upload a file smaller than 50MB.', 'error');
|
2642 |
+
return;
|
2643 |
+
}
|
2644 |
+
|
2645 |
const fileType = file.type;
|
2646 |
const fileName = file.name.toLowerCase();
|
2647 |
+
const fileExtension = fileName.split('.').pop();
|
2648 |
|
2649 |
+
// Show processing progress
|
2650 |
+
showFileProgress(fileName, 'processing');
|
2651 |
+
documentContent.innerHTML = `
|
2652 |
+
<div class="text-center py-8">
|
2653 |
+
<div class="loading-spinner mx-auto"></div>
|
2654 |
+
<p class="text-gray-500 mt-2">Processing ${fileName}...</p>
|
2655 |
+
<p class="text-xs text-gray-400 mt-1">File size: ${formatFileSize(file.size)}</p>
|
2656 |
+
</div>
|
2657 |
+
`;
|
2658 |
+
|
2659 |
+
try {
|
2660 |
+
switch (fileExtension) {
|
2661 |
+
case 'txt':
|
2662 |
+
readTextFile(file);
|
2663 |
+
break;
|
2664 |
+
case 'pdf':
|
2665 |
+
readPDFFile(file);
|
2666 |
+
break;
|
2667 |
+
case 'doc':
|
2668 |
+
case 'docx':
|
2669 |
+
readWordDocument(file);
|
2670 |
+
break;
|
2671 |
+
case 'rtf':
|
2672 |
+
readRTFFile(file);
|
2673 |
+
break;
|
2674 |
+
case 'md':
|
2675 |
+
case 'markdown':
|
2676 |
+
readMarkdownFile(file);
|
2677 |
+
break;
|
2678 |
+
case 'json':
|
2679 |
+
readJSONFile(file);
|
2680 |
+
break;
|
2681 |
+
case 'html':
|
2682 |
+
case 'htm':
|
2683 |
+
readHTMLFile(file);
|
2684 |
+
break;
|
2685 |
+
case 'xml':
|
2686 |
+
readXMLFile(file);
|
2687 |
+
break;
|
2688 |
+
case 'csv':
|
2689 |
+
readCSVFile(file);
|
2690 |
+
break;
|
2691 |
+
case 'odt':
|
2692 |
+
throw new Error('ODT files require conversion. Please save as DOC/DOCX or PDF.');
|
2693 |
+
case 'epub':
|
2694 |
+
throw new Error('EPUB files are not yet supported. Please extract text manually.');
|
2695 |
+
default:
|
2696 |
+
// Try to read as plain text if unknown extension
|
2697 |
+
if (fileType.startsWith('text/')) {
|
2698 |
+
readTextFile(file);
|
2699 |
+
} else {
|
2700 |
+
throw new Error(`Unsupported file type: .${fileExtension}. Please upload a supported document format.`);
|
2701 |
+
}
|
2702 |
+
}
|
2703 |
+
} catch (error) {
|
2704 |
+
console.error('Error processing file:', error);
|
2705 |
+
showToast('Error processing file: ' + error.message, 'error');
|
2706 |
+
documentContent.innerHTML = '<p class="text-gray-500 italic">Error loading document. Please try again.</p>';
|
2707 |
+
showFileProgress(fileName, 'error');
|
2708 |
}
|
2709 |
}
|
2710 |
|
2711 |
+
// File progress indicator
|
2712 |
+
function showFileProgress(fileName, status) {
|
2713 |
+
const progressEl = document.getElementById('fileProgress');
|
2714 |
+
if (!progressEl) {
|
2715 |
+
const progress = document.createElement('div');
|
2716 |
+
progress.id = 'fileProgress';
|
2717 |
+
progress.className = 'fixed bottom-4 right-4 bg-white border border-gray-200 rounded-lg shadow-lg p-3 z-50';
|
2718 |
+
document.body.appendChild(progress);
|
2719 |
+
}
|
2720 |
+
|
2721 |
+
const progressEl2 = document.getElementById('fileProgress');
|
2722 |
+
const statusIcons = {
|
2723 |
+
processing: '<i class="fas fa-spinner fa-spin text-blue-500 mr-2"></i>',
|
2724 |
+
success: '<i class="fas fa-check-circle text-green-500 mr-2"></i>',
|
2725 |
+
error: '<i class="fas fa-times-circle text-red-500 mr-2"></i>'
|
2726 |
+
};
|
2727 |
+
|
2728 |
+
progressEl2.innerHTML = `
|
2729 |
+
${statusIcons[status]}
|
2730 |
+
<span class="text-sm">${fileName}</span>
|
2731 |
+
`;
|
2732 |
+
|
2733 |
+
if (status !== 'processing') {
|
2734 |
+
setTimeout(() => {
|
2735 |
+
progressEl2.remove();
|
2736 |
+
}, 3000);
|
2737 |
+
}
|
2738 |
+
}
|
2739 |
+
|
2740 |
+
// Enhanced text file reader with encoding detection
|
2741 |
function readTextFile(file) {
|
2742 |
const reader = new FileReader();
|
2743 |
reader.onload = (e) => {
|
2744 |
+
const text = e.target.result;
|
2745 |
+
setDocumentContent(text);
|
2746 |
+
showFileProgress(file.name, 'success');
|
2747 |
+
showToast(`Loaded ${formatFileSize(file.size)} text file`, 'success');
|
2748 |
};
|
2749 |
+
reader.onerror = () => {
|
2750 |
+
showToast('Error reading text file', 'error');
|
2751 |
+
showFileProgress(file.name, 'error');
|
2752 |
+
};
|
2753 |
+
reader.readAsText(file, 'UTF-8');
|
2754 |
}
|
2755 |
|
2756 |
+
// Enhanced PDF reader with progress
|
2757 |
function readPDFFile(file) {
|
|
|
2758 |
if (typeof pdfjsLib === 'undefined') {
|
2759 |
+
showToast('PDF.js not loaded. Refreshing page...', 'error');
|
2760 |
+
setTimeout(() => window.location.reload(), 2000);
|
2761 |
return;
|
2762 |
}
|
2763 |
|
2764 |
+
const fileURL = URL.createObjectURL(file);
|
|
|
2765 |
|
2766 |
+
pdfjsLib.getDocument(fileURL).promise.then(pdf => {
|
|
|
2767 |
let text = '';
|
2768 |
const numPages = pdf.numPages;
|
2769 |
const pagePromises = [];
|
2770 |
|
2771 |
+
// Update progress as pages are processed
|
2772 |
+
let pagesProcessed = 0;
|
2773 |
+
|
2774 |
for (let i = 1; i <= numPages; i++) {
|
2775 |
pagePromises.push(pdf.getPage(i).then(page => {
|
2776 |
return page.getTextContent().then(textContent => {
|
2777 |
+
pagesProcessed++;
|
2778 |
+
const progress = (pagesProcessed / numPages) * 100;
|
2779 |
+
documentContent.innerHTML = `
|
2780 |
+
<div class="text-center py-8">
|
2781 |
+
<div class="loading-spinner mx-auto"></div>
|
2782 |
+
<p class="text-gray-500 mt-2">Processing PDF...</p>
|
2783 |
+
<div class="w-32 bg-gray-200 rounded-full h-2 mx-auto mt-3">
|
2784 |
+
<div class="bg-blue-600 h-2 rounded-full transition-all duration-300" style="width: ${progress}%"></div>
|
2785 |
+
</div>
|
2786 |
+
<p class="text-xs text-gray-400 mt-2">${pagesProcessed}/${numPages} pages</p>
|
2787 |
+
</div>
|
2788 |
+
`;
|
2789 |
return textContent.items.map(item => item.str).join(' ');
|
2790 |
});
|
2791 |
}));
|
|
|
2794 |
Promise.all(pagePromises).then(pagesText => {
|
2795 |
text = pagesText.join('\n\n');
|
2796 |
setDocumentContent(text);
|
2797 |
+
URL.revokeObjectURL(fileURL);
|
2798 |
+
showFileProgress(file.name, 'success');
|
2799 |
+
showToast(`Loaded PDF with ${numPages} pages`, 'success');
|
2800 |
}).catch(error => {
|
2801 |
console.error('Error extracting PDF text:', error);
|
2802 |
showToast('Failed to extract text from PDF', 'error');
|
2803 |
+
URL.revokeObjectURL(fileURL);
|
2804 |
+
showFileProgress(file.name, 'error');
|
2805 |
});
|
2806 |
}).catch(error => {
|
2807 |
console.error('Error loading PDF:', error);
|
2808 |
showToast('Failed to load PDF file', 'error');
|
2809 |
+
URL.revokeObjectURL(fileURL);
|
2810 |
+
showFileProgress(file.name, 'error');
|
2811 |
});
|
2812 |
}
|
2813 |
|
2814 |
+
// Word document reader (.doc/.docx)
|
2815 |
+
function readWordDocument(file) {
|
2816 |
+
const reader = new FileReader();
|
2817 |
+
reader.onload = async (e) => {
|
2818 |
+
try {
|
2819 |
+
// Use mammoth to convert docx to text
|
2820 |
+
const result = await mammoth.extractRawText({arrayBuffer: e.target.result});
|
2821 |
+
setDocumentContent(result.value);
|
2822 |
+
|
2823 |
+
if (result.messages.length > 0) {
|
2824 |
+
console.warn('Word processing warnings:', result.messages);
|
2825 |
+
}
|
2826 |
+
} catch (error) {
|
2827 |
+
console.error('Error reading Word document:', error);
|
2828 |
+
showToast('Error reading Word document. Please try saving as a different format.', 'error');
|
2829 |
+
}
|
2830 |
+
};
|
2831 |
+
reader.onerror = () => {
|
2832 |
+
showToast('Error reading Word document', 'error');
|
2833 |
+
};
|
2834 |
+
reader.readAsArrayBuffer(file);
|
2835 |
+
}
|
2836 |
+
|
2837 |
+
// RTF file reader
|
2838 |
+
function readRTFFile(file) {
|
2839 |
+
const reader = new FileReader();
|
2840 |
+
reader.onload = (e) => {
|
2841 |
+
let rtfText = e.target.result;
|
2842 |
+
|
2843 |
+
// Basic RTF to plain text conversion
|
2844 |
+
// Remove RTF control codes
|
2845 |
+
rtfText = rtfText.replace(/\\[a-z]+[0-9]*\s?/gi, '');
|
2846 |
+
rtfText = rtfText.replace(/[{}]/g, '');
|
2847 |
+
rtfText = rtfText.replace(/\\\\/g, '\\');
|
2848 |
+
rtfText = rtfText.replace(/\\'/g, "'");
|
2849 |
+
rtfText = rtfText.replace(/\\\n/g, '\n');
|
2850 |
+
rtfText = rtfText.replace(/\s+/g, ' ');
|
2851 |
+
rtfText = rtfText.trim();
|
2852 |
+
|
2853 |
+
setDocumentContent(rtfText);
|
2854 |
+
};
|
2855 |
+
reader.onerror = () => {
|
2856 |
+
showToast('Error reading RTF file', 'error');
|
2857 |
+
};
|
2858 |
+
reader.readAsText(file);
|
2859 |
+
}
|
2860 |
+
|
2861 |
+
// Markdown file reader
|
2862 |
+
function readMarkdownFile(file) {
|
2863 |
+
const reader = new FileReader();
|
2864 |
+
reader.onload = (e) => {
|
2865 |
+
let text = e.target.result;
|
2866 |
+
|
2867 |
+
// Convert basic Markdown to plain text
|
2868 |
+
// Remove Markdown syntax for better TTS
|
2869 |
+
text = text.replace(/^#{1,6}\s+/gm, ''); // Headers
|
2870 |
+
text = text.replace(/\*\*(.*?)\*\*/g, '$1'); // Bold
|
2871 |
+
text = text.replace(/\*(.*?)\*/g, '$1'); // Italic
|
2872 |
+
text = text.replace(/_(.*?)_/g, '$1'); // Italic underscore
|
2873 |
+
text = text.replace(/`(.*?)`/g, '$1'); // Inline code
|
2874 |
+
text = text.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1'); // Links
|
2875 |
+
text = text.replace(/!\[([^\]]*)\]\([^)]+\)/g, ''); // Images
|
2876 |
+
text = text.replace(/^>\s+/gm, ''); // Blockquotes
|
2877 |
+
text = text.replace(/^[\s]*-\s+/gm, '• '); // Unordered lists
|
2878 |
+
text = text.replace(/^[\s]*\d+\.\s+/gm, ''); // Ordered lists
|
2879 |
+
text = text.replace(/---+/g, ''); // Horizontal rules
|
2880 |
+
text = text.replace(/\n{3,}/g, '\n\n'); // Multiple newlines
|
2881 |
+
|
2882 |
+
setDocumentContent(text);
|
2883 |
+
};
|
2884 |
+
reader.onerror = () => {
|
2885 |
+
showToast('Error reading Markdown file', 'error');
|
2886 |
+
};
|
2887 |
+
reader.readAsText(file);
|
2888 |
+
}
|
2889 |
+
|
2890 |
+
// JSON file reader
|
2891 |
+
function readJSONFile(file) {
|
2892 |
+
const reader = new FileReader();
|
2893 |
+
reader.onload = (e) => {
|
2894 |
+
try {
|
2895 |
+
const jsonData = JSON.parse(e.target.result);
|
2896 |
+
|
2897 |
+
// Convert JSON to readable text
|
2898 |
+
let text = '';
|
2899 |
+
|
2900 |
+
function jsonToText(obj, prefix = '') {
|
2901 |
+
for (const [key, value] of Object.entries(obj)) {
|
2902 |
+
if (typeof value === 'object' && value !== null) {
|
2903 |
+
text += `${prefix}${key}:\n`;
|
2904 |
+
jsonToText(value, prefix + ' ');
|
2905 |
+
} else {
|
2906 |
+
text += `${prefix}${key}: ${value}\n`;
|
2907 |
+
}
|
2908 |
+
}
|
2909 |
+
}
|
2910 |
+
|
2911 |
+
jsonToText(jsonData);
|
2912 |
+
setDocumentContent(text);
|
2913 |
+
} catch (error) {
|
2914 |
+
showToast('Invalid JSON file', 'error');
|
2915 |
+
}
|
2916 |
+
};
|
2917 |
+
reader.onerror = () => {
|
2918 |
+
showToast('Error reading JSON file', 'error');
|
2919 |
+
};
|
2920 |
+
reader.readAsText(file);
|
2921 |
+
}
|
2922 |
+
|
2923 |
+
// HTML file reader
|
2924 |
+
function readHTMLFile(file) {
|
2925 |
+
const reader = new FileReader();
|
2926 |
+
reader.onload = (e) => {
|
2927 |
+
const htmlContent = e.target.result;
|
2928 |
+
|
2929 |
+
// Create a temporary DOM element to extract text
|
2930 |
+
const tempDiv = document.createElement('div');
|
2931 |
+
tempDiv.innerHTML = htmlContent;
|
2932 |
+
|
2933 |
+
// Remove script and style tags
|
2934 |
+
const scripts = tempDiv.querySelectorAll('script, style');
|
2935 |
+
scripts.forEach(script => script.remove());
|
2936 |
+
|
2937 |
+
// Extract text content
|
2938 |
+
let text = tempDiv.textContent || tempDiv.innerText || '';
|
2939 |
+
|
2940 |
+
// Clean up whitespace
|
2941 |
+
text = text.replace(/\s+/g, ' ');
|
2942 |
+
text = text.replace(/\n\s*\n/g, '\n\n');
|
2943 |
+
text = text.trim();
|
2944 |
+
|
2945 |
+
setDocumentContent(text);
|
2946 |
+
};
|
2947 |
+
reader.onerror = () => {
|
2948 |
+
showToast('Error reading HTML file', 'error');
|
2949 |
+
};
|
2950 |
+
reader.readAsText(file);
|
2951 |
+
}
|
2952 |
+
|
2953 |
+
// XML file reader
|
2954 |
+
function readXMLFile(file) {
|
2955 |
+
const reader = new FileReader();
|
2956 |
+
reader.onload = (e) => {
|
2957 |
+
try {
|
2958 |
+
const xmlContent = e.target.result;
|
2959 |
+
const parser = new DOMParser();
|
2960 |
+
const xmlDoc = parser.parseFromString(xmlContent, 'text/xml');
|
2961 |
+
|
2962 |
+
// Extract text content from XML
|
2963 |
+
let text = '';
|
2964 |
+
|
2965 |
+
function extractText(node) {
|
2966 |
+
if (node.nodeType === Node.TEXT_NODE) {
|
2967 |
+
text += node.textContent + ' ';
|
2968 |
+
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
2969 |
+
for (const child of node.childNodes) {
|
2970 |
+
extractText(child);
|
2971 |
+
}
|
2972 |
+
}
|
2973 |
+
}
|
2974 |
+
|
2975 |
+
extractText(xmlDoc.documentElement);
|
2976 |
+
|
2977 |
+
// Clean up text
|
2978 |
+
text = text.replace(/\s+/g, ' ');
|
2979 |
+
text = text.trim();
|
2980 |
+
|
2981 |
+
setDocumentContent(text);
|
2982 |
+
} catch (error) {
|
2983 |
+
showToast('Error parsing XML file', 'error');
|
2984 |
+
}
|
2985 |
+
};
|
2986 |
+
reader.onerror = () => {
|
2987 |
+
showToast('Error reading XML file', 'error');
|
2988 |
+
};
|
2989 |
+
reader.readAsText(file);
|
2990 |
+
}
|
2991 |
+
|
2992 |
+
// CSV file reader
|
2993 |
+
function readCSVFile(file) {
|
2994 |
+
const reader = new FileReader();
|
2995 |
+
reader.onload = (e) => {
|
2996 |
+
const csvContent = e.target.result;
|
2997 |
+
|
2998 |
+
// Parse CSV (simple implementation)
|
2999 |
+
const lines = csvContent.split('\n').filter(line => line.trim());
|
3000 |
+
const headers = lines[0].split(',').map(h => h.trim().replace(/"/g, ''));
|
3001 |
+
|
3002 |
+
let text = `CSV Data Summary:\n\n`;
|
3003 |
+
text += `Headers: ${headers.join(', ')}\n\n`;
|
3004 |
+
text += `Total rows: ${lines.length - 1}\n\n`;
|
3005 |
+
|
3006 |
+
// Add first few rows as example
|
3007 |
+
if (lines.length > 1) {
|
3008 |
+
text += 'First few rows:\n';
|
3009 |
+
for (let i = 1; i <= Math.min(5, lines.length - 1); i++) {
|
3010 |
+
const values = lines[i].split(',').map(v => v.trim().replace(/"/g, ''));
|
3011 |
+
text += `Row ${i}: ${values.join(', ')}\n`;
|
3012 |
+
}
|
3013 |
+
}
|
3014 |
+
|
3015 |
+
setDocumentContent(text);
|
3016 |
+
showToast('CSV file loaded. Showing data summary for TTS.', 'success');
|
3017 |
+
};
|
3018 |
+
reader.onerror = () => {
|
3019 |
+
showToast('Error reading CSV file', 'error');
|
3020 |
+
};
|
3021 |
+
reader.readAsText(file);
|
3022 |
+
}
|
3023 |
+
|
3024 |
// Set document content
|
3025 |
function setDocumentContent(text) {
|
3026 |
currentText = text;
|