joermd commited on
Commit
89b3f72
·
verified ·
1 Parent(s): f5f0451

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +62 -35
index.html CHANGED
@@ -228,6 +228,14 @@
228
  </h2>
229
  <div id="explanationText" class="text-lg text-gray-700"></div>
230
  </div>
 
 
 
 
 
 
 
 
231
  </main>
232
  </div>
233
 
@@ -235,14 +243,13 @@
235
  جافا سكريبت: الوظائف والتحليل
236
  ================================= -->
237
  <script>
238
- // تغليف الكود داخل دالة IIFE لمنع تسرب المتغيرات إلى النطاق العام
239
  (function() {
240
  "use strict";
241
 
242
  // تنبيه: يجب عدم تضمين مفتاح API في الكود العام؛ يُفضل تخزينه على الخادم واستخدام واجهة وسيطة
243
  const API_URL = 'https://api.deepseek.com/chat/completions';
244
  const API_KEY = 'sk-15606736ed9e4aea8b7cc11a195d2b01';
245
- const ANALYSIS_PROMPT = `أنت خبير لغوي وتقني متخصص في مراجعة الترجمة التقنية وتحليل النصوص بدقة. مهمتك مقارنة النص المصدر والنص الهدف واستخراج الاختلافات بدقة مع تحسين التظليل والتعليم.
246
  تعليمات:
247
  1. قم بتحليل النص إلى فقرات منفصلة، مع التأكد من انتهاء كل فقرة بنقطة.
248
  2. لا تقم بتعديل العلامات التالية:
@@ -272,9 +279,7 @@
272
  const splitIntoLines = text =>
273
  text.split(/\n+/).map((line, i) => {
274
  line = line.trim();
275
- if(line && !line.endsWith('.')) {
276
- line += '.';
277
- }
278
  return `<div class="line-item"><span class="line-number">${i+1}:</span><span class="line-text">${line}</span></div>`;
279
  }).join('');
280
 
@@ -354,7 +359,7 @@
354
  const iconMeaning = `<i class="fas fa-info-circle text-blue-600 mr-1"></i>`;
355
  const iconDoubt = `<i class="fas fa-question-circle text-indigo-600 mr-1"></i>`;
356
 
357
- // النصوص المفقودة
358
  const missingRegex = /__(.*?)__/g;
359
  while ((match = missingRegex.exec(analysisOutput)) !== null) {
360
  const phrase = match[1].trim();
@@ -405,6 +410,47 @@
405
  return `<ol class="list-decimal ml-6 space-y-2">${steps.join('')}</ol>`;
406
  };
407
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
408
  /* ===============================
409
  دالة معالجة الملفات (PDF و DOCX)
410
  =============================== */
@@ -412,7 +458,6 @@
412
  let text = "";
413
  try {
414
  if (file.type === 'application/pdf') {
415
- // يُنصح بمعالجة ملفات PDF على خادم مخصص بدلاً من العميل لتحسين الأداء والأمان
416
  const form = new FormData();
417
  form.append('image', file);
418
  const response = await fetch('https://demo.api4ai.cloud/ocr/v1/results', {
@@ -421,7 +466,6 @@
421
  headers: { 'A4A-CLIENT-APP-ID': 'sample' }
422
  });
423
  const data = await response.json();
424
- // تأكد من التحقق من بنية البيانات قبل الوصول إليها
425
  text = data.results?.[0]?.entities?.[0]?.objects?.[0]?.entities?.[0]?.text || "";
426
  } else if (file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
427
  const arrayBuffer = await file.arrayBuffer();
@@ -482,7 +526,6 @@
482
  document.getElementById('submitBtn').addEventListener('click', async () => {
483
  const sourceText = document.getElementById('sourceText').value;
484
  const targetText = document.getElementById('targetText').value;
485
- // إعادة تعيين قائمة الأخطاء
486
  document.getElementById('errorsList').innerHTML = '';
487
  document.getElementById('resultSection').classList.remove('hidden');
488
  document.getElementById('explanationBox').classList.remove('hidden');
@@ -492,7 +535,6 @@
492
  return;
493
  }
494
 
495
- // مقارنة عدد الكلمات وتحذير المستخدم إن كان هناك اختلاف
496
  const sourceWordCount = countWords(sourceText);
497
  const targetWordCount = countWords(targetText);
498
  if (sourceWordCount !== targetWordCount) {
@@ -500,7 +542,6 @@
500
  }
501
 
502
  try {
503
- // عرض مؤشر التحميل أثناء عملية التحليل
504
  const progressDiv = document.createElement('div');
505
  progressDiv.className = "bg-indigo-100 p-4 rounded-xl mb-4";
506
  progressDiv.innerHTML = `<div class="flex items-center">
@@ -509,7 +550,6 @@
509
  </div>`;
510
  document.getElementById('errorsList').appendChild(progressDiv);
511
 
512
- // تجهيز البرومبت مع استبدال النصوص المصدر والهدف
513
  const prompt = ANALYSIS_PROMPT
514
  .replace("{source}", sourceText)
515
  .replace("{target}", targetText);
@@ -541,7 +581,6 @@
541
  const analysisOutput = data.choices[0].message.content.trim();
542
  progressDiv.remove();
543
 
544
- // في حالة التطابق التام
545
  if (analysisOutput.includes('[MATCH]')) {
546
  const checkDiv = document.createElement('div');
547
  checkDiv.className = "p-4 rounded-xl bg-green-50 text-green-700 flex items-center";
@@ -551,41 +590,29 @@
551
  document.getElementById('targetTextReview').innerHTML = splitIntoLines(targetText);
552
  document.getElementById('explanationText').innerHTML = `<p>النصوص متطابقة ولا يوجد اختلاف يجب الإشارة إليه.</p>`;
553
  } else {
554
- // تطبيق التظليل على النصوص المصدر والهدف
555
  const sourceHighlighted = applyHighlights(sourceText, analysisOutput);
556
  const targetHighlighted = applyHighlights(targetText, analysisOutput);
557
  document.getElementById('sourceTextReview').innerHTML = splitIntoLines(sourceHighlighted);
558
  document.getElementById('targetTextReview').innerHTML = splitIntoLines(targetHighlighted);
559
- // توليد شرح تفصيلي للاختلافات
560
  const explanationHTML = generateExplanation(sourceText, analysisOutput);
561
  document.getElementById('explanationText').innerHTML = explanationHTML;
 
562
 
563
- // عرض ملخص للاختلافات إن وُجدت
564
- const numDiffCount = (analysisOutput.match(/<([^<>]+)>/g) || []).length;
565
- const missingDiffCount = (analysisOutput.match(/__(.*?)__/g) || []).length;
566
- const extraDiffCount = (analysisOutput.match(/<<EXTRA>>(.*?)<<\/EXTRA>>/g) || []).length;
567
- const meaningDiffCount = (analysisOutput.match(/\[MEANING\](.*?)\[\/MEANING\]/g) || []).length;
568
- const doubtDiffCount = (analysisOutput.match(/\[DOUBT\](.*?)\[\/DOUBT\]/g) || []).length;
569
- if (numDiffCount || missingDiffCount || extraDiffCount || meaningDiffCount || doubtDiffCount) {
570
- const summaryDiv = document.createElement('div');
571
- summaryDiv.className = "p-4 rounded-xl bg-yellow-50 text-gray-800";
572
- let summaryText = '<div class="font-bold mb-2">ملخص الاختلافات:</div><ul class="list-disc ml-4 space-y-1">';
573
- if (numDiffCount) summaryText += `<li>اختلاف في الأرقام/التواريخ: ${numDiffCount}</li>`;
574
- if (missingDiffCount) summaryText += `<li>النصوص المفقودة: ${missingDiffCount}</li>`;
575
- if (extraDiffCount) summaryText += `<li>النصوص الزائدة: ${extraDiffCount}</li>`;
576
- if (meaningDiffCount) summaryText += `<li>اختلاف في المعنى: ${meaningDiffCount}</li>`;
577
- if (doubtDiffCount) summaryText += `<li>علامات الشك: ${doubtDiffCount}</li>`;
578
- summaryText += '</ul>';
579
- summaryDiv.innerHTML = summaryText;
580
- document.getElementById('errorsList').appendChild(summaryDiv);
581
- }
582
  }
583
  } catch (error) {
584
  document.getElementById('errorsList').innerHTML = '';
585
  addError(`خطأ في التحليل: ${error.message}`);
586
  }
587
  });
588
-
589
  })();
590
  </script>
591
  </body>
 
228
  </h2>
229
  <div id="explanationText" class="text-lg text-gray-700"></div>
230
  </div>
231
+
232
+ <!-- قسم الكلمات المفقودة -->
233
+ <div id="missingWordsSection" class="card hidden">
234
+ <h2 class="text-2xl font-bold text-gray-800 border-b pb-3 mb-6">
235
+ <i class="fas fa-exclamation-triangle icon text-red-500"></i> الكلمات المفقودة
236
+ </h2>
237
+ <div id="missingWordsList" class="text-lg text-red-700"></div>
238
+ </div>
239
  </main>
240
  </div>
241
 
 
243
  جافا سكريبت: الوظائف والتحليل
244
  ================================= -->
245
  <script>
 
246
  (function() {
247
  "use strict";
248
 
249
  // تنبيه: يجب عدم تضمين مفتاح API في الكود العام؛ يُفضل تخزينه على الخادم واستخدام واجهة وسيطة
250
  const API_URL = 'https://api.deepseek.com/chat/completions';
251
  const API_KEY = 'sk-15606736ed9e4aea8b7cc11a195d2b01';
252
+ const ANALYSIS_PROMPT = `أنت خبير لغوي وتقني متخصص في مراجعة الترجمة التقنية وتحليل النصوص بدقة. مهمتك مقارنة النص المصدر والنص الهدف واستخراج الاختلافات مع تحسين التظليل والتعليم.
253
  تعليمات:
254
  1. قم بتحليل النص إلى فقرات منفصلة، مع التأكد من انتهاء كل فقرة بنقطة.
255
  2. لا تقم بتعديل العلامات التالية:
 
279
  const splitIntoLines = text =>
280
  text.split(/\n+/).map((line, i) => {
281
  line = line.trim();
282
+ if(line && !line.endsWith('.')) { line += '.'; }
 
 
283
  return `<div class="line-item"><span class="line-number">${i+1}:</span><span class="line-text">${line}</span></div>`;
284
  }).join('');
285
 
 
359
  const iconMeaning = `<i class="fas fa-info-circle text-blue-600 mr-1"></i>`;
360
  const iconDoubt = `<i class="fas fa-question-circle text-indigo-600 mr-1"></i>`;
361
 
362
+ // النصوص المفقودة (المعلمة مسبقاً)
363
  const missingRegex = /__(.*?)__/g;
364
  while ((match = missingRegex.exec(analysisOutput)) !== null) {
365
  const phrase = match[1].trim();
 
410
  return `<ol class="list-decimal ml-6 space-y-2">${steps.join('')}</ol>`;
411
  };
412
 
413
+ /* ===============================
414
+ دالة لاكتشاف الكلمات المفقودة باستخدام خوارزمية LCS
415
+ =============================== */
416
+ const detectMissingWords = (source, target) => {
417
+ const sourceWords = source.split(/\s+/);
418
+ const targetWords = target.split(/\s+/);
419
+ const m = sourceWords.length, n = targetWords.length;
420
+ const dp = Array(m + 1).fill(null).map(() => Array(n + 1).fill(0));
421
+ for (let i = 1; i <= m; i++) {
422
+ for (let j = 1; j <= n; j++) {
423
+ if (sourceWords[i - 1] === targetWords[j - 1]) {
424
+ dp[i][j] = dp[i - 1][j - 1] + 1;
425
+ } else {
426
+ dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
427
+ }
428
+ }
429
+ }
430
+ let i = m, j = n;
431
+ const lcs = [];
432
+ while (i > 0 && j > 0) {
433
+ if (sourceWords[i - 1] === targetWords[j - 1]) {
434
+ lcs.unshift(sourceWords[i - 1]);
435
+ i--; j--;
436
+ } else if (dp[i - 1][j] > dp[i][j - 1]) {
437
+ i--;
438
+ } else {
439
+ j--;
440
+ }
441
+ }
442
+ const missingWords = [];
443
+ let lcsIndex = 0;
444
+ for (let k = 0; k < sourceWords.length; k++) {
445
+ if (lcsIndex < lcs.length && sourceWords[k] === lcs[lcsIndex]) {
446
+ lcsIndex++;
447
+ } else {
448
+ missingWords.push(sourceWords[k]);
449
+ }
450
+ }
451
+ return missingWords;
452
+ };
453
+
454
  /* ===============================
455
  دالة معالجة الملفات (PDF و DOCX)
456
  =============================== */
 
458
  let text = "";
459
  try {
460
  if (file.type === 'application/pdf') {
 
461
  const form = new FormData();
462
  form.append('image', file);
463
  const response = await fetch('https://demo.api4ai.cloud/ocr/v1/results', {
 
466
  headers: { 'A4A-CLIENT-APP-ID': 'sample' }
467
  });
468
  const data = await response.json();
 
469
  text = data.results?.[0]?.entities?.[0]?.objects?.[0]?.entities?.[0]?.text || "";
470
  } else if (file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
471
  const arrayBuffer = await file.arrayBuffer();
 
526
  document.getElementById('submitBtn').addEventListener('click', async () => {
527
  const sourceText = document.getElementById('sourceText').value;
528
  const targetText = document.getElementById('targetText').value;
 
529
  document.getElementById('errorsList').innerHTML = '';
530
  document.getElementById('resultSection').classList.remove('hidden');
531
  document.getElementById('explanationBox').classList.remove('hidden');
 
535
  return;
536
  }
537
 
 
538
  const sourceWordCount = countWords(sourceText);
539
  const targetWordCount = countWords(targetText);
540
  if (sourceWordCount !== targetWordCount) {
 
542
  }
543
 
544
  try {
 
545
  const progressDiv = document.createElement('div');
546
  progressDiv.className = "bg-indigo-100 p-4 rounded-xl mb-4";
547
  progressDiv.innerHTML = `<div class="flex items-center">
 
550
  </div>`;
551
  document.getElementById('errorsList').appendChild(progressDiv);
552
 
 
553
  const prompt = ANALYSIS_PROMPT
554
  .replace("{source}", sourceText)
555
  .replace("{target}", targetText);
 
581
  const analysisOutput = data.choices[0].message.content.trim();
582
  progressDiv.remove();
583
 
 
584
  if (analysisOutput.includes('[MATCH]')) {
585
  const checkDiv = document.createElement('div');
586
  checkDiv.className = "p-4 rounded-xl bg-green-50 text-green-700 flex items-center";
 
590
  document.getElementById('targetTextReview').innerHTML = splitIntoLines(targetText);
591
  document.getElementById('explanationText').innerHTML = `<p>النصوص متطابقة ولا يوجد اختلاف يجب الإشارة إليه.</p>`;
592
  } else {
 
593
  const sourceHighlighted = applyHighlights(sourceText, analysisOutput);
594
  const targetHighlighted = applyHighlights(targetText, analysisOutput);
595
  document.getElementById('sourceTextReview').innerHTML = splitIntoLines(sourceHighlighted);
596
  document.getElementById('targetTextReview').innerHTML = splitIntoLines(targetHighlighted);
 
597
  const explanationHTML = generateExplanation(sourceText, analysisOutput);
598
  document.getElementById('explanationText').innerHTML = explanationHTML;
599
+ }
600
 
601
+ // الكشف عن الكلمات المفقودة باستخدام الدالة الجديدة
602
+ const missingWords = detectMissingWords(sourceText, targetText);
603
+ if (missingWords.length > 0) {
604
+ const missingWordsSection = document.getElementById('missingWordsSection');
605
+ const missingWordsList = document.getElementById('missingWordsList');
606
+ missingWordsList.innerHTML = `<ul class="list-disc ml-4">${missingWords.map(word => `<li>${word}</li>`).join('')}</ul>`;
607
+ missingWordsSection.classList.remove('hidden');
608
+ } else {
609
+ document.getElementById('missingWordsSection').classList.add('hidden');
 
 
 
 
 
 
 
 
 
 
610
  }
611
  } catch (error) {
612
  document.getElementById('errorsList').innerHTML = '';
613
  addError(`خطأ في التحليل: ${error.message}`);
614
  }
615
  });
 
616
  })();
617
  </script>
618
  </body>