| <!DOCTYPE html> |
| <html lang="ar" dir="rtl"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>مكتب الريحان للترجمة المعتمدة - نظام OCR</title> |
| <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"> |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.4.120/pdf.min.js"></script> |
| <style> |
| body { |
| font-family: Arial, sans-serif; |
| margin: 0; |
| padding: 20px; |
| background-color: #f8f9fa; |
| } |
| .header { |
| background-color: #3b82f6; |
| color: white; |
| padding: 15px; |
| border-radius: 10px; |
| margin-bottom: 20px; |
| text-align: center; |
| } |
| .container { |
| max-width: 800px; |
| margin: 0 auto; |
| } |
| .card { |
| background-color: white; |
| border-radius: 10px; |
| box-shadow: 0 2px 5px rgba(0,0,0,0.1); |
| padding: 20px; |
| margin-bottom: 20px; |
| } |
| .pdf-grid { |
| display: grid; |
| grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); |
| gap: 10px; |
| margin-top: 15px; |
| } |
| .pdf-page { |
| border: 1px solid #ddd; |
| border-radius: 5px; |
| padding: 5px; |
| position: relative; |
| cursor: pointer; |
| transition: all 0.2s; |
| } |
| .pdf-page:hover { |
| transform: translateY(-3px); |
| box-shadow: 0 3px 10px rgba(0,0,0,0.1); |
| } |
| .pdf-page.selected { |
| border: 2px solid #3b82f6; |
| } |
| .pdf-page img { |
| width: 100%; |
| height: auto; |
| border-radius: 3px; |
| } |
| .page-number { |
| position: absolute; |
| bottom: 0; |
| left: 0; |
| right: 0; |
| background-color: rgba(0,0,0,0.6); |
| color: white; |
| text-align: center; |
| font-size: 12px; |
| padding: 2px; |
| } |
| .btn-primary { |
| background-color: #3b82f6; |
| border-color: #3b82f6; |
| } |
| .btn-success { |
| background-color: #10b981; |
| border-color: #10b981; |
| } |
| .result-text { |
| max-height: 300px; |
| overflow-y: auto; |
| white-space: pre-wrap; |
| direction: rtl; |
| border: 1px solid #ddd; |
| padding: 10px; |
| border-radius: 5px; |
| background-color: #f8f9fa; |
| } |
| .spinner-border { |
| width: 1.5rem; |
| height: 1.5rem; |
| margin-left: 0.5rem; |
| } |
| .logo { |
| font-weight: bold; |
| font-size: 24px; |
| display: inline-block; |
| margin-bottom: 5px; |
| } |
| .logo span { |
| color: #bfdbfe; |
| } |
| .stats-badge { |
| background-color: #3b82f6; |
| color: white; |
| font-size: 14px; |
| padding: 5px 10px; |
| border-radius: 20px; |
| margin-right: 10px; |
| } |
| .stats-container { |
| display: flex; |
| align-items: center; |
| margin-bottom: 15px; |
| } |
| .page-preview { |
| margin-bottom: 10px; |
| border: 1px solid #ddd; |
| border-radius: 5px; |
| padding: 10px; |
| } |
| .page-preview h4 { |
| background-color: #f0f8ff; |
| padding: 5px; |
| border-radius: 3px; |
| margin-bottom: 10px; |
| } |
| </style> |
| </head> |
| <body> |
| <div class="container"> |
| <div class="header"> |
| <div class="logo">مكتب <span>الريحان</span></div> |
| <h1>نظام التعرف الضوئي على النصوص</h1> |
| <p class="mb-0">للترجمة المعتمدة - استخراج النصوص من الصور والملفات متعددة الصفحات</p> |
| </div> |
|
|
| |
| <div class="card" id="statsCard"> |
| <h3>إحصائيات النظام</h3> |
| <div class="stats-container"> |
| <div class="stats-badge"> |
| عدد الصفحات المعالجة: <span id="ocrCounter">0</span> |
| </div> |
| <div class="stats-badge"> |
| تاريخ آخر معالجة: <span id="lastOcrDate">-</span> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="card"> |
| <h3>تحميل الملف</h3> |
| <div class="mb-3"> |
| <input type="file" class="form-control" id="fileInput" accept=".pdf,.jpg,.jpeg,.png"> |
| <div class="form-text">يمكنك تحميل ملف PDF (حتى 100 صفحة) أو صورة</div> |
| </div> |
| <button id="processBtn" class="btn btn-primary">معالجة الملف</button> |
| </div> |
|
|
| |
| <div id="processingStatus" class="card d-none"> |
| <h3>حالة المعالجة</h3> |
| <div class="alert alert-info"> |
| <div class="d-flex align-items-center"> |
| <div class="spinner-border text-primary" role="status"></div> |
| <span id="statusText" class="ms-2">جاري معالجة الملف...</span> |
| </div> |
| </div> |
| <div class="progress mt-2"> |
| <div id="progressBar" class="progress-bar" role="progressbar" style="width: 0%"></div> |
| </div> |
| </div> |
|
|
| |
| <div id="pdfPagesCard" class="card d-none"> |
| <h3>صفحات الملف</h3> |
| <p>اختر الصفحات التي تريد معالجتها (انقر للتحديد)</p> |
| |
| <div class="mb-3"> |
| <button id="selectAllBtn" class="btn btn-sm btn-outline-primary me-2">تحديد الكل</button> |
| <button id="deselectAllBtn" class="btn btn-sm btn-outline-secondary">إلغاء تحديد الكل</button> |
| </div> |
| |
| <div id="pdfPagesContainer" class="pdf-grid"></div> |
| |
| <div class="mt-3"> |
| <button id="extractImagesBtn" class="btn btn-success me-2">تحويل إلى صور</button> |
| <button id="extractTextBtn" class="btn btn-primary">استخراج النص</button> |
| </div> |
| </div> |
|
|
| |
| <div id="resultsCard" class="card d-none"> |
| <h3>النص المستخرج</h3> |
| <div id="resultPreview"></div> |
| <div id="resultText" class="result-text mt-3"> |
| لم يتم استخراج نص بعد. |
| </div> |
| <div class="mt-3"> |
| <button id="copyTextBtn" class="btn btn-outline-primary me-2">نسخ النص</button> |
| <button id="downloadTextBtn" class="btn btn-success me-2">تنزيل النص</button> |
| <button id="downloadWordBtn" class="btn btn-success">تنزيل النص إلى Word</button> |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| |
| pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.4.120/pdf.worker.min.js'; |
| |
| |
| const RAPIDAPI_KEY = '32769fb369mshfdf6f5e28e26674p1f3764jsn2a31085a1fc7'; |
| const OCR_API_URL = 'https://ocr43.p.rapidapi.com/v1/results'; |
| |
| |
| let documentPages = []; |
| let selectedPages = []; |
| let extractedTexts = []; |
| let extractedPageNumbers = []; |
| let ocrPagesCount = 0; |
| |
| |
| document.addEventListener('DOMContentLoaded', function() { |
| const savedCount = localStorage.getItem('ocrPagesCount'); |
| const lastDate = localStorage.getItem('lastOcrDate'); |
| |
| if (savedCount) { |
| ocrPagesCount = parseInt(savedCount); |
| document.getElementById('ocrCounter').textContent = ocrPagesCount; |
| } |
| |
| if (lastDate) { |
| document.getElementById('lastOcrDate').textContent = lastDate; |
| } |
| }); |
| |
| |
| const fileInput = document.getElementById('fileInput'); |
| const processBtn = document.getElementById('processBtn'); |
| const processingStatus = document.getElementById('processingStatus'); |
| const statusText = document.getElementById('statusText'); |
| const progressBar = document.getElementById('progressBar'); |
| const pdfPagesCard = document.getElementById('pdfPagesCard'); |
| const pdfPagesContainer = document.getElementById('pdfPagesContainer'); |
| const selectAllBtn = document.getElementById('selectAllBtn'); |
| const deselectAllBtn = document.getElementById('deselectAllBtn'); |
| const extractImagesBtn = document.getElementById('extractImagesBtn'); |
| const extractTextBtn = document.getElementById('extractTextBtn'); |
| const resultsCard = document.getElementById('resultsCard'); |
| const resultText = document.getElementById('resultText'); |
| const resultPreview = document.getElementById('resultPreview'); |
| const copyTextBtn = document.getElementById('copyTextBtn'); |
| const downloadTextBtn = document.getElementById('downloadTextBtn'); |
| const downloadWordBtn = document.getElementById('downloadWordBtn'); |
| const ocrCounter = document.getElementById('ocrCounter'); |
| const lastOcrDate = document.getElementById('lastOcrDate'); |
| |
| |
| document.addEventListener('DOMContentLoaded', function() { |
| processBtn.addEventListener('click', processFile); |
| selectAllBtn.addEventListener('click', selectAllPages); |
| deselectAllBtn.addEventListener('click', deselectAllPages); |
| extractImagesBtn.addEventListener('click', extractImages); |
| extractTextBtn.addEventListener('click', extractText); |
| copyTextBtn.addEventListener('click', copyText); |
| downloadTextBtn.addEventListener('click', downloadText); |
| downloadWordBtn.addEventListener('click', downloadWord); |
| }); |
| |
| |
| function updateOcrCounter(count) { |
| ocrPagesCount += count; |
| ocrCounter.textContent = ocrPagesCount; |
| |
| |
| localStorage.setItem('ocrPagesCount', ocrPagesCount); |
| |
| |
| const now = new Date(); |
| const formattedDate = `${now.getFullYear()}-${(now.getMonth()+1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')} ${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`; |
| |
| lastOcrDate.textContent = formattedDate; |
| localStorage.setItem('lastOcrDate', formattedDate); |
| } |
| |
| |
| async function processFile() { |
| if (!fileInput.files || fileInput.files.length === 0) { |
| alert('الرجاء اختيار ملف أولاً'); |
| return; |
| } |
| |
| const file = fileInput.files[0]; |
| |
| |
| processingStatus.classList.remove('d-none'); |
| statusText.textContent = 'جاري معالجة الملف...'; |
| progressBar.style.width = '0%'; |
| |
| |
| pdfPagesCard.classList.add('d-none'); |
| resultsCard.classList.add('d-none'); |
| |
| |
| documentPages = []; |
| selectedPages = []; |
| extractedTexts = []; |
| extractedPageNumbers = []; |
| |
| try { |
| const fileType = file.name.split('.').pop().toLowerCase(); |
| |
| if (fileType === 'pdf') { |
| await processPdf(file); |
| } else if (['jpg', 'jpeg', 'png'].includes(fileType)) { |
| await processImage(file); |
| } else { |
| throw new Error('نوع الملف غير مدعوم. يرجى اختيار ملف PDF أو صورة.'); |
| } |
| |
| |
| pdfPagesCard.classList.remove('d-none'); |
| |
| |
| processingStatus.classList.add('d-none'); |
| |
| } catch (error) { |
| console.error('Error processing file:', error); |
| statusText.textContent = `خطأ: ${error.message}`; |
| } |
| } |
| |
| |
| async function processPdf(file) { |
| try { |
| |
| const arrayBuffer = await file.arrayBuffer(); |
| const pdfDoc = await pdfjsLib.getDocument({ data: arrayBuffer }).promise; |
| |
| |
| const numPages = pdfDoc.numPages; |
| if (numPages > 100) { |
| alert('هذا الملف يحتوي على أكثر من 100 صفحة. سيتم معالجة أول 100 صفحة فقط.'); |
| } |
| |
| |
| pdfPagesContainer.innerHTML = ''; |
| |
| |
| const maxPages = Math.min(numPages, 100); |
| for (let i = 1; i <= maxPages; i++) { |
| |
| progressBar.style.width = `${(i / maxPages) * 100}%`; |
| statusText.textContent = `جاري معالجة الصفحة ${i} من ${maxPages}...`; |
| |
| |
| const pageImage = await convertPdfPageToImage(pdfDoc, i); |
| |
| |
| documentPages.push({ |
| pageNumber: i, |
| imageData: pageImage.imageData, |
| width: pageImage.width, |
| height: pageImage.height |
| }); |
| |
| |
| createPageElement(pageImage.imageData, i); |
| } |
| |
| } catch (error) { |
| console.error('Error processing PDF:', error); |
| throw error; |
| } |
| } |
| |
| |
| async function processImage(file) { |
| try { |
| |
| const imageData = await readFileAsDataURL(file); |
| |
| |
| const img = new Image(); |
| await new Promise((resolve, reject) => { |
| img.onload = resolve; |
| img.onerror = reject; |
| img.src = imageData; |
| }); |
| |
| |
| pdfPagesContainer.innerHTML = ''; |
| |
| |
| documentPages = [{ |
| pageNumber: 1, |
| imageData: imageData, |
| width: img.width, |
| height: img.height |
| }]; |
| |
| |
| createPageElement(imageData, 1); |
| |
| |
| progressBar.style.width = '100%'; |
| statusText.textContent = 'تمت معالجة الصورة بنجاح'; |
| |
| } catch (error) { |
| console.error('Error processing image:', error); |
| throw error; |
| } |
| } |
| |
| |
| async function convertPdfPageToImage(pdfDoc, pageNumber, scale = 1.5) { |
| try { |
| |
| const page = await pdfDoc.getPage(pageNumber); |
| |
| |
| const canvas = document.createElement('canvas'); |
| const context = canvas.getContext('2d'); |
| |
| |
| const viewport = page.getViewport({ scale }); |
| canvas.width = viewport.width; |
| canvas.height = viewport.height; |
| |
| |
| await page.render({ |
| canvasContext: context, |
| viewport: viewport |
| }).promise; |
| |
| |
| return { |
| imageData: canvas.toDataURL('image/png'), |
| width: viewport.width, |
| height: viewport.height, |
| pageNumber: pageNumber |
| }; |
| } catch (error) { |
| console.error(`Error converting PDF page ${pageNumber} to image:`, error); |
| throw error; |
| } |
| } |
| |
| |
| function createPageElement(imageData, pageNumber) { |
| const pageDiv = document.createElement('div'); |
| pageDiv.className = 'pdf-page'; |
| pageDiv.dataset.page = pageNumber; |
| |
| const img = document.createElement('img'); |
| img.src = imageData; |
| img.alt = `صفحة ${pageNumber}`; |
| |
| const pageNumberDiv = document.createElement('div'); |
| pageNumberDiv.className = 'page-number'; |
| pageNumberDiv.textContent = `صفحة ${pageNumber}`; |
| |
| pageDiv.appendChild(img); |
| pageDiv.appendChild(pageNumberDiv); |
| |
| |
| pageDiv.addEventListener('click', function() { |
| this.classList.toggle('selected'); |
| |
| |
| const page = parseInt(this.dataset.page); |
| if (this.classList.contains('selected')) { |
| if (!selectedPages.includes(page)) { |
| selectedPages.push(page); |
| } |
| } else { |
| const index = selectedPages.indexOf(page); |
| if (index > -1) { |
| selectedPages.splice(index, 1); |
| } |
| } |
| }); |
| |
| pdfPagesContainer.appendChild(pageDiv); |
| } |
| |
| |
| function readFileAsDataURL(file) { |
| return new Promise((resolve, reject) => { |
| const reader = new FileReader(); |
| reader.onload = e => resolve(e.target.result); |
| reader.onerror = reject; |
| reader.readAsDataURL(file); |
| }); |
| } |
| |
| |
| function selectAllPages() { |
| document.querySelectorAll('.pdf-page').forEach(page => { |
| page.classList.add('selected'); |
| const pageNumber = parseInt(page.dataset.page); |
| if (!selectedPages.includes(pageNumber)) { |
| selectedPages.push(pageNumber); |
| } |
| }); |
| } |
| |
| |
| function deselectAllPages() { |
| document.querySelectorAll('.pdf-page').forEach(page => { |
| page.classList.remove('selected'); |
| }); |
| selectedPages = []; |
| } |
| |
| |
| function extractImages() { |
| if (documentPages.length === 0) { |
| alert('لا توجد صفحات للمعالجة'); |
| return; |
| } |
| |
| |
| const pagesToExtract = selectedPages.length > 0 |
| ? documentPages.filter(page => selectedPages.includes(page.pageNumber)) |
| : documentPages; |
| |
| if (pagesToExtract.length === 0) { |
| alert('الرجاء تحديد صفحة واحدة على الأقل'); |
| return; |
| } |
| |
| |
| pagesToExtract.forEach(page => { |
| const a = document.createElement('a'); |
| a.href = page.imageData; |
| a.download = `alrihan_page_${page.pageNumber}.png`; |
| document.body.appendChild(a); |
| a.click(); |
| document.body.removeChild(a); |
| }); |
| |
| |
| alert(`تم استخراج ${pagesToExtract.length} صورة بنجاح`); |
| } |
| |
| |
| async function extractText() { |
| if (documentPages.length === 0) { |
| alert('لا توجد صفحات للمعالجة'); |
| return; |
| } |
| |
| |
| const pagesToProcess = selectedPages.length > 0 |
| ? documentPages.filter(page => selectedPages.includes(page.pageNumber)) |
| : documentPages; |
| |
| if (pagesToProcess.length === 0) { |
| alert('الرجاء تحديد صفحة واحدة على الأقل'); |
| return; |
| } |
| |
| |
| processingStatus.classList.remove('d-none'); |
| statusText.textContent = 'جاري استخراج النص...'; |
| progressBar.style.width = '0%'; |
| |
| try { |
| extractedTexts = []; |
| extractedPageNumbers = []; |
| |
| |
| for (let i = 0; i < pagesToProcess.length; i++) { |
| const page = pagesToProcess[i]; |
| |
| |
| progressBar.style.width = `${((i + 1) / pagesToProcess.length) * 100}%`; |
| statusText.textContent = `جاري معالجة الصفحة ${i + 1} من ${pagesToProcess.length}...`; |
| |
| |
| const pageText = await extractTextFromImage(page.imageData, page.pageNumber); |
| extractedTexts.push(pageText); |
| extractedPageNumbers.push(page.pageNumber); |
| } |
| |
| |
| updateOcrCounter(pagesToProcess.length); |
| |
| |
| const combinedText = extractedTexts.join('\n\n'); |
| |
| |
| resultText.textContent = combinedText; |
| |
| |
| generateResultPreview(); |
| |
| resultsCard.classList.remove('d-none'); |
| |
| |
| processingStatus.classList.add('d-none'); |
| |
| |
| resultsCard.scrollIntoView({ behavior: 'smooth' }); |
| |
| } catch (error) { |
| console.error('Error extracting text:', error); |
| statusText.textContent = `خطأ: ${error.message}`; |
| } |
| } |
| |
| |
| function generateResultPreview() { |
| resultPreview.innerHTML = ''; |
| |
| if (extractedTexts.length === 0) { |
| return; |
| } |
| |
| |
| const previewPages = Math.min(extractedTexts.length, 3); |
| |
| for (let i = 0; i < previewPages; i++) { |
| const pageText = extractedTexts[i]; |
| const pageNumber = extractedPageNumbers[i]; |
| |
| |
| const previewDiv = document.createElement('div'); |
| previewDiv.className = 'page-preview'; |
| |
| const pageTitle = document.createElement('h4'); |
| pageTitle.textContent = `صفحة ${pageNumber}`; |
| |
| const textPreview = document.createElement('p'); |
| |
| const textContent = pageText.replace(`=== صفحة ${pageNumber} ===\n`, ''); |
| textPreview.textContent = textContent.length > 100 ? |
| textContent.substring(0, 100) + '...' : |
| textContent; |
| |
| previewDiv.appendChild(pageTitle); |
| previewDiv.appendChild(textPreview); |
| resultPreview.appendChild(previewDiv); |
| } |
| |
| |
| if (extractedTexts.length > 3) { |
| const morePages = document.createElement('p'); |
| morePages.className = 'text-muted'; |
| morePages.textContent = `+ ${extractedTexts.length - 3} صفحات أخرى...`; |
| resultPreview.appendChild(morePages); |
| } |
| } |
| |
| |
| async function extractTextFromImage(imageData, pageNumber) { |
| try { |
| |
| const response = await fetch(imageData); |
| const blob = await response.blob(); |
| |
| |
| const formData = new FormData(); |
| formData.append('image', blob, `page_${pageNumber}.png`); |
| |
| |
| const ocrResponse = await fetch(OCR_API_URL, { |
| method: 'POST', |
| headers: { |
| 'X-RapidAPI-Key': RAPIDAPI_KEY, |
| 'X-RapidAPI-Host': 'ocr43.p.rapidapi.com' |
| }, |
| body: formData |
| }); |
| |
| if (!ocrResponse.ok) { |
| throw new Error(`فشل في طلب OCR: ${ocrResponse.status}`); |
| } |
| |
| const data = await ocrResponse.json(); |
| |
| try { |
| |
| const text = data.results[0].entities[0].objects[0].entities[0].text; |
| return `=== صفحة ${pageNumber} ===\n${text}`; |
| } catch (e) { |
| console.error('Error parsing OCR response:', e); |
| return `=== صفحة ${pageNumber} ===\n[خطأ في معالجة النص]`; |
| } |
| } catch (error) { |
| console.error(`Error in OCR for page ${pageNumber}:`, error); |
| throw error; |
| } |
| } |
| |
| |
| function copyText() { |
| const text = resultText.textContent; |
| if (!text || text === 'لم يتم استخراج نص بعد.') { |
| alert('لا يوجد نص للنسخ'); |
| return; |
| } |
| |
| navigator.clipboard.writeText(text) |
| .then(() => alert('تم نسخ النص بنجاح')) |
| .catch(err => alert('حدث خطأ أثناء نسخ النص: ' + err)); |
| } |
| |
| |
| function downloadText() { |
| const text = resultText.textContent; |
| if (!text || text === 'لم يتم استخراج نص بعد.') { |
| alert('لا يوجد نص للتنزيل'); |
| return; |
| } |
| |
| const blob = new Blob([text], { type: 'text/plain;charset=utf-8' }); |
| const url = URL.createObjectURL(blob); |
| const a = document.createElement('a'); |
| a.href = url; |
| a.download = 'alrihan_ocr_text.txt'; |
| document.body.appendChild(a); |
| a.click(); |
| document.body.removeChild(a); |
| URL.revokeObjectURL(url); |
| } |
| |
| |
| function downloadWord() { |
| const text = resultText.textContent; |
| if (!text || text === 'لم يتم استخراج نص بعد.') { |
| alert('لا يوجد نص للتنزيل'); |
| return; |
| } |
| |
| |
| const pageTexts = []; |
| let currentPageText = ''; |
| const lines = text.split('\n'); |
| |
| for (let i = 0; i < lines.length; i++) { |
| const line = lines[i]; |
| |
| |
| if (line.startsWith('=== صفحة ') && line.endsWith(' ===')) { |
| |
| if (currentPageText) { |
| pageTexts.push(currentPageText); |
| currentPageText = ''; |
| } |
| |
| |
| currentPageText = line + '\n'; |
| } else { |
| |
| currentPageText += line + '\n'; |
| } |
| } |
| |
| |
| if (currentPageText) { |
| pageTexts.push(currentPageText); |
| } |
| |
| |
| let wordContent = ` |
| <!DOCTYPE html> |
| <html xmlns:o='urn:schemas-microsoft-com:office:office' |
| xmlns:w='urn:schemas-microsoft-com:office:word' |
| xmlns='http://www.w3.org/TR/REC-html40'> |
| <head> |
| <meta charset='utf-8'> |
| <title>مكتب الريحان للترجمة المعتمدة - نص OCR</title> |
| <style> |
| @page { |
| size: 21cm 29.7cm; |
| margin: 2cm; |
| } |
| body { |
| font-family: 'Arial', sans-serif; |
| direction: rtl; |
| text-align: right; |
| } |
| .page-title { |
| font-size: 18px; |
| font-weight: bold; |
| color: #3b82f6; |
| margin-bottom: 15px; |
| padding-bottom: 5px; |
| border-bottom: 1px solid #ccc; |
| } |
| .page-content { |
| margin-bottom: 15px; |
| line-height: 1.5; |
| page-break-after: always; |
| white-space: pre-wrap; |
| } |
| .footer { |
| font-size: 10px; |
| text-align: center; |
| color: #666; |
| margin-top: 20px; |
| } |
| .header { |
| text-align: center; |
| margin-bottom: 20px; |
| } |
| .header h1 { |
| color: #3b82f6; |
| margin-bottom: 5px; |
| } |
| .date { |
| font-size: 12px; |
| color: #666; |
| } |
| </style> |
| </head> |
| <body> |
| <div class="header"> |
| <h1>مكتب الريحان للترجمة المعتمدة - نص مستخرج بتقنية OCR</h1> |
| <div class="date">تاريخ الاستخراج: ${new Date().toLocaleDateString('ar-EG')}</div> |
| </div> |
| `; |
| |
| |
| pageTexts.forEach((pageText, index) => { |
| |
| const titleMatch = pageText.match(/=== صفحة (\d+) ===/); |
| const pageNumber = titleMatch ? titleMatch[1] : (index + 1); |
| |
| |
| const formattedPageText = pageText.replace(/=== صفحة \d+ ===\n/, ''); |
| |
| |
| wordContent += ` |
| <div class="page-content"> |
| <div class="page-title">صفحة ${pageNumber}</div> |
| <div>${formattedPageText.replace(/\n/g, '<br>')}</div> |
| </div> |
| `; |
| }); |
| |
| |
| wordContent += ` |
| <div class="footer"> |
| تم إنشاء هذا المستند بواسطة نظام مكتب الريحان للترجمة المعتمدة للتعرف الضوئي على النصوص |
| </div> |
| </body> |
| </html> |
| `; |
| |
| |
| const blob = new Blob(['\ufeff', wordContent], { type: 'application/msword' }); |
| const url = URL.createObjectURL(blob); |
| const a = document.createElement('a'); |
| a.href = url; |
| a.download = 'alrihan_ocr_text.doc'; |
| document.body.appendChild(a); |
| a.click(); |
| document.body.removeChild(a); |
| URL.revokeObjectURL(url); |
| } |
| </script> |
| </body> |
| </html> |