joermd commited on
Commit
c6156df
·
verified ·
1 Parent(s): 5643379

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +222 -208
index.html CHANGED
@@ -3,13 +3,13 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>منصة مراجعة النصوص والترجمات - شركة موندو لينجوا</title>
7
- <!-- استيراد Tailwind CSS, FontAwesome وMammoth -->
8
  <link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
9
- <script src="https://cdnjs.cloudflare.com/ajax/libs/mammoth/1.6.0/mammoth.browser.min.js"></script>
10
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
 
11
  <style>
12
- /* تأثيرات الحركة والتنسيقات */
13
  @keyframes gradient {
14
  0% { background-position: 0% 50%; }
15
  50% { background-position: 100% 50%; }
@@ -19,259 +19,265 @@
19
  background-size: 200% 200%;
20
  animation: gradient 15s ease infinite;
21
  }
 
22
  .transition-all { transition: all 0.3s ease-in-out; }
23
- .animate-scale { transition: transform 0.2s ease-in-out; }
24
- .animate-scale:hover { transform: scale(1.02); }
25
  .pulse-animation { animation: pulse 2s infinite; }
26
  @keyframes pulse {
27
  0% { box-shadow: 0 0 0 0 rgba(0,0,0,0.2); }
28
  70% { box-shadow: 0 0 0 10px rgba(0,0,0,0); }
29
  100% { box-shadow: 0 0 0 0 rgba(0,0,0,0); }
30
  }
31
-
32
- /* تنسيق النصوص والتظليل */
33
  .text-comparison { line-height: 1.8; white-space: pre-wrap; }
34
  .highlight-missing {
35
- background-color: #f87171;
36
  color: #fff;
37
  padding: 0 4px;
38
  border-radius: 3px;
39
  font-weight: bold;
40
  }
41
  .highlight-number {
42
- background-color: #facc15;
43
  color: #000;
44
  padding: 0 4px;
45
  border-radius: 3px;
46
  font-weight: bold;
47
  }
48
- .highlight-abbreviation {
49
- background-color: #34d399;
50
  color: #fff;
51
  padding: 0 4px;
52
  border-radius: 3px;
53
  font-weight: bold;
54
  }
55
-
56
- /* تقسيم الفقرات وترقيمها */
57
  .line-item {
58
  margin-bottom: 1rem;
59
  padding: 0.5rem;
60
- border-bottom: 1px dashed #ccc;
61
  }
62
  .line-number {
63
  font-weight: bold;
64
- color: #4B5563;
65
  margin-left: 0.5rem;
66
  }
67
- .line-text { display: inline-block; }
68
-
69
  /* تصميم البطاقات */
70
  .card {
71
- background-color: #fff;
72
  border-radius: 1rem;
73
- box-shadow: 0 10px 25px -5px rgba(0,0,0,0.1);
74
  padding: 2rem;
75
- border: 1px solid #f3f4f6;
76
  }
77
- .card-hover:hover {
78
- box-shadow: 0 10px 25px -5px rgba(0,0,0,0.2);
79
- transform: translateY(-3px);
80
- }
81
- .icon { margin-left: 0.5rem; }
82
- .upload-label {
83
  display: flex;
84
- flex-direction: row-reverse;
85
  align-items: center;
86
- justify-content: center;
 
 
 
 
 
 
 
 
 
87
  }
88
  </style>
89
  </head>
90
- <body class="bg-gradient-to-br from-gray-100 via-blue-100 to-indigo-100 min-h-screen">
91
  <div class="min-h-screen pb-12">
92
- <!-- رأس الصفحة -->
93
- <header class="bg-gradient-to-r from-indigo-800 via-purple-800 to-pink-800 animate-gradient text-white py-12 mb-12 shadow-2xl">
94
  <div class="max-w-6xl mx-auto px-4 text-center">
95
- <h1 class="text-6xl font-extrabold mb-4 animate-scale">
96
- منصة مراجعة النصوص والترجمات <i class="fas fa-chart-line icon"></i>
97
  </h1>
98
- <p class="text-2xl opacity-90">
99
- تحليل دقيق يشمل النصوص المفقودة، الأرقام/التواريخ، وفهم الاختصارات
100
  </p>
101
  </div>
102
  </header>
103
-
104
  <!-- المحتوى الرئيسي -->
105
- <main class="max-w-7xl mx-auto px-4 space-y-10">
106
- <!-- رفع الملفات -->
107
- <div class="card card-hover">
108
- <h2 class="text-3xl font-bold text-gray-800 border-b pb-3 mb-6">
109
- <i class="fas fa-file-upload icon text-indigo-600"></i> تحميل الملفات
110
  </h2>
111
- <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
112
  <!-- ملف المصدر -->
113
- <div class="group border-2 border-dashed border-indigo-300 rounded-xl p-10 text-center bg-indigo-50 hover:bg-indigo-100 transition-colors duration-300">
114
- <label class="cursor-pointer block upload-label">
 
 
115
  <input type="file" id="sourceFile" accept=".docx,.pdf" class="hidden">
116
- <span class="text-xl text-indigo-600 group-hover:text-indigo-700">ملف المصدر</span>
117
- <i class="fas fa-upload text-6xl text-indigo-500 mb-4"></i>
118
  </label>
119
  </div>
120
  <!-- ملف الهدف -->
121
- <div class="group border-2 border-dashed border-pink-300 rounded-xl p-10 text-center bg-pink-50 hover:bg-pink-100 transition-colors duration-300">
122
- <label class="cursor-pointer block upload-label">
 
 
123
  <input type="file" id="targetFile" accept=".docx,.pdf" class="hidden">
124
- <span class="text-xl text-pink-600 group-hover:text-pink-700">ملف الهدف</span>
125
- <i class="fas fa-download text-6xl text-pink-500 mb-4"></i>
126
  </label>
127
  </div>
128
  </div>
129
- <div id="processStatus" class="hidden mt-6">
130
- <div class="flex items-center justify-end space-x-3 bg-indigo-100 rounded-xl p-4">
131
- <span class="text-xl text-indigo-700">جارٍ معالجة الملف...</span>
132
- <div class="animate-spin h-10 w-10 border-4 border-indigo-600 rounded-full border-t-transparent"></div>
133
  </div>
134
  </div>
135
- </div>
136
-
137
- <!-- إدخال النصوص يدويًا -->
138
- <div class="card card-hover">
139
- <div class="space-y-8">
140
  <!-- النص المصدر -->
141
  <div class="group">
142
- <label class="block text-2xl font-bold text-gray-700 mb-4">
143
- <i class="fas fa-language icon text-indigo-600"></i> النص المصدر
144
  </label>
145
- <textarea id="sourceText" dir="rtl" class="w-full px-8 py-6 border-2 border-gray-200 rounded-xl focus:ring-indigo-200 focus:border-indigo-400 transition-all resize-none text-xl" rows="8" placeholder="اكتب النص المصدر هنا..."></textarea>
146
  </div>
147
  <!-- النص الهدف -->
148
  <div class="group">
149
- <label class="block text-2xl font-bold text-gray-700 mb-4">
150
- <i class="fas fa-language icon text-pink-600"></i> النص الهدف
151
  </label>
152
- <textarea id="targetText" dir="ltr" class="w-full px-8 py-6 border-2 border-gray-200 rounded-xl focus:ring-pink-200 focus:border-pink-400 transition-all resize-none text-xl" rows="8" placeholder="اكتب النص الهدف هنا..."></textarea>
153
  </div>
154
  </div>
155
- </div>
156
-
157
- <!-- المصادر الإضافية -->
158
- <div class="card card-hover">
159
- <h2 class="text-3xl font-bold text-gray-800 border-b pb-3 mb-6">
160
- <i class="fas fa-book-open icon text-green-600"></i> مصادر إضافية
161
  </h2>
162
- <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
163
  <!-- رفع ملف المصادر -->
164
- <div class="group border-2 border-dashed border-green-300 rounded-xl p-10 text-center bg-green-50 hover:bg-green-100 transition-colors duration-300">
165
- <label class="cursor-pointer block upload-label">
 
 
166
  <input type="file" id="sourceExtraFile" accept=".docx,.pdf" class="hidden">
167
- <span class="text-xl text-green-600 group-hover:text-green-700">تحميل ملف المصادر</span>
168
- <i class="fas fa-upload text-6xl text-green-500 mb-4"></i>
169
  </label>
170
  </div>
171
  <!-- إدخال المصادر يدويًا -->
172
  <div class="group">
173
- <label class="block text-2xl font-bold text-gray-700 mb-4">
174
- <i class="fas fa-edit icon text-green-600"></i> إدخال المصادر يدويًا
175
  </label>
176
- <textarea id="sourceExtraText" dir="rtl" class="w-full px-8 py-6 border-2 border-green-200 rounded-xl focus:ring-green-200 focus:border-green-400 transition-all resize-none text-xl" rows="8" placeholder="اكتب المصادر هنا..."></textarea>
177
  </div>
178
  </div>
179
- </div>
180
-
181
- <!-- زر التحليل والمراجعة -->
182
- <button id="submitBtn" class="w-full bg-gradient-to-r from-indigo-700 to-pink-700 hover:from-indigo-800 hover:to-pink-800 text-white font-bold py-6 px-10 rounded-xl transition-all transform hover:scale-105 focus:ring-indigo-200 text-2xl shadow-2xl hover:shadow-2xl pulse-animation">
183
- <div class="flex items-center justify-center">
184
- <span>تحليل ومراجعة النصوص</span>
185
- <i class="fas fa-sync-alt icon mr-4"></i>
186
- </div>
187
- </button>
188
-
189
- <!-- عرض نتائج التحليل -->
190
- <div id="resultSection" class="card hidden">
191
- <h2 class="text-3xl font-bold text-gray-800 border-b pb-4 mb-6">
192
- <i class="fas fa-search icon text-green-600"></i> نتائج التحليل والمقارنة
193
  </h2>
194
- <div id="errorsList" class="space-y-4 mb-6"></div>
195
- <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
196
- <div>
197
- <h4 class="text-2xl font-bold text-gray-700 mb-4">
198
- <i class="fas fa-file-alt icon text-indigo-600"></i> النص المصدر (مع التعليم)
199
- </h4>
200
- <div id="sourceTextReview" class="bg-indigo-50 rounded-xl p-8 min-h-[250px] border-2 border-indigo-200 text-comparison"></div>
 
 
 
 
 
 
 
 
 
 
 
 
201
  </div>
202
- <div>
203
- <h4 class="text-2xl font-bold text-gray-700 mb-4">
204
- <i class="fas fa-file-alt icon text-pink-600"></i> النص الهدف (بدون تعليم)
205
  </h4>
206
- <div id="targetTextReview" class="bg-gray-50 rounded-xl p-8 min-h-[250px] border-2 border-gray-300 text-comparison"></div>
207
  </div>
208
  </div>
209
- </div>
210
-
211
- <!-- شرح الاختلافات بالتفصيل -->
212
- <div id="explanationBox" class="card hidden">
213
- <h2 class="text-3xl font-bold text-gray-800 border-b pb-4 mb-6">
214
- <i class="fas fa-info-circle icon text-green-600"></i> شرح الاختلافات
215
- </h2>
216
- <div id="explanationText" class="text-2xl text-gray-700"></div>
217
- </div>
218
  </main>
219
  </div>
220
-
221
- <!-- جافا سكريبت: الوظائف والتحليل -->
222
  <script>
223
  (function() {
224
  "use strict";
225
-
226
- // تعريف البرومت مع التعليمات الدقيقة ودعم الاختصارات
227
- const ANALYSIS_PROMPT = `أنت خبير لغوي وتقني متخصص في مراجعة الترجمة وتحليل النصوص بدقة عالية.
228
- مهمتك مقارنة النص المصدر والنص الهدف بدقة مع مراعاة فهم الاختصارات.
229
- إذا كانت النصوص متطابقة تماماً، أرجع [MATCH] فقط.
230
- أما إذا كان هناك اختلافات، فحدد الأنواع التالية:
231
- 1. النصوص المفقودة: الكلمات أو العبارات الموجودة في النص المصدر وغير موجودة في النص الهدف.
232
- 2. الأرقام والتواريخ: التي يجب أن تكون مطابقة بين النصين؛ وفي حال وجود اختلاف، قم بالإشارة إليه.
233
- 3. اختلاف المعنى: إذا كانت الترجمة تحمل معنى مختلفاً عن النص المصدر.
234
- 4. الاختصارات: يجب على النموذج فهم الاختصارات وتحليلها بدقة وعدم اعتبارها خطأ إذا كانت مستخدمة بشكل سليم.
235
- استخدم العلامات التالية لتعليم النص المصدر فقط:
236
- - النصوص المفقودة بين علامتي __ و __.
237
- - الأرقام والتواريخ بين علامتي < و >.
238
- - اختلاف المعنى بين علامتي [MEANING] و [/MEANING].
239
- - الاختصارات بين علامتي {ABBR} و {/ABBR}.
240
- قدم الناتج في شكل قائمة مفصلة مع شرح مختصر لكل اختلاف وذكر رقم السطر إن أمكن.
 
241
 
242
  النص المصدر:
243
  {source}
244
 
245
  النص الهدف:
246
  {target}`;
247
-
248
- // دوال مساعدة عامة
249
  const countWords = text =>
250
  text.trim().split(/\s+/).filter(word => word !== "").length;
251
-
252
  const escapeRegExp = string =>
253
  string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
254
-
255
- // تقسيم النص إلى فقرات مرقمة
256
  const splitIntoLines = text =>
257
  text.split(/\n+/).map((line, i) => {
258
  line = line.trim();
259
  if(line && !line.endsWith('.')) { line += '.'; }
260
  return `<div class="line-item"><span class="line-number">${i+1}:</span><span class="line-text">${line}</span></div>`;
261
  }).join('');
262
-
263
- // الحصول على رقم السطر الذي يحتوي على عبارة معينة
264
  const getLineNumber = (text, substring) => {
265
  const index = text.indexOf(substring);
266
  if (index === -1) return "غير محدد";
267
  return text.substring(0, index).split("\n").length;
268
  };
269
-
270
- // تطبيق التظليل على النص المصدر بناءً على نتائج التحليل
271
- const applyHighlights = (originalText, analysisOutput) => {
272
- let highlightedText = originalText;
273
  let match;
274
- // تظليل النصوص المفقودة
275
  const missingRegex = /__(.*?)__/g;
276
  while ((match = missingRegex.exec(analysisOutput)) !== null) {
277
  const phrase = match[1].trim();
@@ -281,7 +287,7 @@
281
  highlightedText = highlightedText.replace(phraseRegex, replacement);
282
  }
283
  }
284
- // تظليل الأرقام والتواريخ
285
  const numberRegex = /<([^<>]+)>/g;
286
  while ((match = numberRegex.exec(analysisOutput)) !== null) {
287
  const phrase = match[1].trim();
@@ -291,35 +297,33 @@
291
  highlightedText = highlightedText.replace(phraseRegex, replacement);
292
  }
293
  }
294
- // تظليل الاختصارات
295
- const abbrRegex = /{ABBR}(.*?){\/ABBR}/g;
296
- while ((match = abbrRegex.exec(analysisOutput)) !== null) {
297
  const phrase = match[1].trim();
298
  if (phrase) {
299
- const replacement = `<span class="highlight-abbreviation">${phrase}</span>`;
300
  const phraseRegex = new RegExp(escapeRegExp(phrase), 'g');
301
  highlightedText = highlightedText.replace(phraseRegex, replacement);
302
  }
303
  }
304
  return highlightedText;
305
  };
306
-
307
- // توليد شرح تفصيلي للاختلافات
308
  const generateExplanation = (sourceText, analysisOutput) => {
309
- let explanations = [];
310
  const iconMissing = `<i class="fas fa-exclamation-triangle mr-1"></i>`;
311
  const iconNumber = `<i class="fas fa-hashtag mr-1"></i>`;
312
  const iconMeaning = `<i class="fas fa-info-circle mr-1"></i>`;
313
- const iconAbbr = `<i class="fas fa-font mr-1"></i>`;
314
-
315
  // شرح النصوص المفقودة
316
  const missingRegex = /__(.*?)__/g;
317
- let match;
318
  while ((match = missingRegex.exec(analysisOutput)) !== null) {
319
  const phrase = match[1].trim();
320
  if (phrase) {
321
  const lineNum = getLineNumber(sourceText, phrase);
322
- explanations.push(`<p>${iconMissing} في السطر ${lineNum}: النص المفقود <span class="highlight-missing">${phrase}</span></p>`);
323
  }
324
  }
325
  // شرح الأرقام والتواريخ
@@ -328,7 +332,7 @@
328
  const phrase = match[1].trim();
329
  if (phrase) {
330
  const lineNum = getLineNumber(sourceText, phrase);
331
- explanations.push(`<p>${iconNumber} في السطر ${lineNum}: الرقم/التاريخ <span class="highlight-number">${phrase}</span></p>`);
332
  }
333
  }
334
  // شرح اختلاف المعنى
@@ -337,31 +341,16 @@
337
  const phrase = match[1].trim();
338
  if (phrase) {
339
  const lineNum = getLineNumber(sourceText, phrase);
340
- explanations.push(`<p>${iconMeaning} في السطر ${lineNum}: اختلاف المعنى <span class="highlight-missing">${phrase}</span></p>`);
341
- }
342
- }
343
- // شرح الاختصارات
344
- const abbrRegex = /{ABBR}(.*?){\/ABBR}/g;
345
- while ((match = abbrRegex.exec(analysisOutput)) !== null) {
346
- const phrase = match[1].trim();
347
- if (phrase) {
348
- const lineNum = getLineNumber(sourceText, phrase);
349
- explanations.push(`<p>${iconAbbr} في السطر ${lineNum}: الاختصار <span class="highlight-abbreviation">${phrase}</span></p>`);
350
  }
351
  }
352
-
353
- // التحقق من استخدام المصادر الخارجية
354
- const usedSource = analysisOutput.includes('[USED_SOURCE]');
355
- let sourceNote = usedSource ? `<p><i class="fas fa-book-reader mr-1"></i> تم استخدام مصادر خارجية لشرح الاختصارات والمصطلحات.</p>`
356
- : `<p><i class="fas fa-book mr-1"></i> لم يتم استخدام مصادر خارجية.</p>`;
357
-
358
- if (explanations.length === 0) {
359
- return `<p><i class="fas fa-check-circle mr-2"></i> لا توجد اختلافات ملحوظة بين النصين.</p>` + sourceNote;
360
  }
361
- return explanations.join('') + sourceNote;
362
  };
363
-
364
- // دالة معالجة الملفات (PDF و DOCX)
365
  const processFile = async file => {
366
  let text = "";
367
  try {
@@ -388,8 +377,8 @@
388
  }
389
  return text;
390
  };
391
-
392
- // التعامل مع رفع الملفات وإدخال النصوص
393
  const processFileInput = (inputId, targetTextAreaId, errorMsg) => {
394
  document.getElementById(inputId)?.addEventListener('change', async (event) => {
395
  const file = event.target.files[0];
@@ -405,13 +394,13 @@
405
  }
406
  });
407
  };
408
-
409
  // رفع ملفات المصدر، الهدف والمصادر الإضافية
410
  processFileInput('sourceFile', 'sourceText', 'خطأ في معالجة ملف المصدر');
411
  processFileInput('targetFile', 'targetText', 'خطأ في معالجة ملف الهدف');
412
  processFileInput('sourceExtraFile', 'sourceExtraText', 'خطأ في معالجة ملف المصادر الإضافية');
413
-
414
- // دالة عرض الأخطاء
415
  const addError = (message, type = 'error') => {
416
  const errorsList = document.getElementById('errorsList');
417
  if (!errorsList) return;
@@ -423,50 +412,69 @@
423
  </div>`;
424
  errorsList.appendChild(errorDiv);
425
  };
426
-
427
- // عملية التحليل والمقارنة عند الضغط على زر التحليل
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
428
  document.getElementById('submitBtn').addEventListener('click', async () => {
429
  const sourceText = document.getElementById('sourceText').value;
430
  const targetText = document.getElementById('targetText').value;
 
431
  document.getElementById('errorsList').innerHTML = '';
432
  document.getElementById('resultSection').classList.remove('hidden');
433
- document.getElementById('explanationBox').classList.remove('hidden');
434
-
435
  if (!sourceText || !targetText) {
436
  addError('يرجى إدخال كلا النصين المصدر والهدف');
437
  return;
438
  }
439
-
440
  const sourceWordCount = countWords(sourceText);
441
  const targetWordCount = countWords(targetText);
442
  if (sourceWordCount !== targetWordCount) {
443
  addError(`عدد كلمات النص المصدر (${sourceWordCount}) يختلف عن النص الهدف (${targetWordCount})`, 'warning');
444
  }
445
-
446
  try {
447
  const progressDiv = document.createElement('div');
448
- progressDiv.className = "bg-indigo-100 p-4 rounded-xl mb-4";
449
- progressDiv.innerHTML = `<div class="flex items-center justify-end">
450
- <span class="text-xl">جارٍ التحليل...</span>
451
- <div class="animate-spin h-10 w-10 border-4 border-indigo-600 rounded-full border-t-transparent ml-4"></div>
452
  </div>`;
453
  document.getElementById('errorsList').appendChild(progressDiv);
454
-
455
  const prompt = ANALYSIS_PROMPT
456
  .replace("{source}", sourceText)
457
  .replace("{target}", targetText);
458
-
459
  const payload = {
460
  model: "deepseek-chat",
461
  messages: [
462
- { role: "system", content: "أنت خبير في تحليل ومراجعة النصوص بدقة عالية، وتفهم الاختصارات ومعانيها الكاملة." },
463
  { role: "user", content: prompt }
464
  ],
465
  temperature: 0.3,
466
  max_tokens: 2048,
467
  stream: false
468
  };
469
-
470
  const response = await fetch('https://api.deepseek.com/chat/completions', {
471
  method: 'POST',
472
  headers: {
@@ -475,32 +483,38 @@
475
  },
476
  body: JSON.stringify(payload)
477
  });
478
-
479
- if (!response.ok) {
480
- throw new Error('حدث خطأ بالشبكة: ' + response.statusText);
481
  }
482
  const data = await response.json();
483
  const analysisOutput = data.choices[0].message.content.trim();
484
  progressDiv.remove();
485
-
486
- // في حالة التطابق التام
487
  if (analysisOutput.includes('[MATCH]')) {
488
  const checkDiv = document.createElement('div');
489
  checkDiv.className = "p-4 rounded-xl bg-green-50 text-green-700 flex items-center";
490
- checkDiv.innerHTML = `<i class="fas fa-check-circle mr-2"></i> <span>النصوص متطابقة تماماً</span>`;
491
  document.getElementById('errorsList').appendChild(checkDiv);
492
  document.getElementById('sourceTextReview').innerHTML = splitIntoLines(sourceText);
493
  document.getElementById('targetTextReview').innerHTML = splitIntoLines(targetText);
494
- document.getElementById('explanationText').innerHTML = `<p class="text-xl">النصوص متطابقة ولا يوجد اختلاف يجب الإشارة إليه.</p>`;
495
  } else {
496
- // تطبيق التظليل على النص المصدر فقط
497
  const sourceHighlighted = applyHighlights(sourceText, analysisOutput);
498
  document.getElementById('sourceTextReview').innerHTML = splitIntoLines(sourceHighlighted);
499
- // عرض النص الهدف بدون تعليم
500
  document.getElementById('targetTextReview').innerHTML = splitIntoLines(targetText);
501
  const explanationHTML = generateExplanation(sourceText, analysisOutput);
502
- document.getElementById('explanationText').innerHTML = explanationHTML;
 
 
 
 
 
 
503
  }
 
504
  } catch (error) {
505
  document.getElementById('errorsList').innerHTML = '';
506
  addError(`خطأ في التحليل: ${error.message}`);
@@ -509,4 +523,4 @@
509
  })();
510
  </script>
511
  </body>
512
- </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>منصة مراجعة النصوص والترجمات المتقدمة</title>
7
+ <!-- تضمين Tailwind CSS وFont Awesome وMammoth لتحليل ملفات DOCX -->
8
  <link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
 
9
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
10
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/mammoth/1.6.0/mammoth.browser.min.js"></script>
11
  <style>
12
+ /* تأثير تدرج الخلفية */
13
  @keyframes gradient {
14
  0% { background-position: 0% 50%; }
15
  50% { background-position: 100% 50%; }
 
19
  background-size: 200% 200%;
20
  animation: gradient 15s ease infinite;
21
  }
22
+ /* تأثيرات عامة */
23
  .transition-all { transition: all 0.3s ease-in-out; }
24
+ .hover-scale:hover { transform: scale(1.02); }
 
25
  .pulse-animation { animation: pulse 2s infinite; }
26
  @keyframes pulse {
27
  0% { box-shadow: 0 0 0 0 rgba(0,0,0,0.2); }
28
  70% { box-shadow: 0 0 0 10px rgba(0,0,0,0); }
29
  100% { box-shadow: 0 0 0 0 rgba(0,0,0,0); }
30
  }
31
+ /* تظليل النصوص */
 
32
  .text-comparison { line-height: 1.8; white-space: pre-wrap; }
33
  .highlight-missing {
34
+ background-color: #e3342f; /* أحمر غامق */
35
  color: #fff;
36
  padding: 0 4px;
37
  border-radius: 3px;
38
  font-weight: bold;
39
  }
40
  .highlight-number {
41
+ background-color: #ffed4a; /* أصفر */
42
  color: #000;
43
  padding: 0 4px;
44
  border-radius: 3px;
45
  font-weight: bold;
46
  }
47
+ .highlight-meaning {
48
+ background-color: #3490dc; /* أزرق فاتح */
49
  color: #fff;
50
  padding: 0 4px;
51
  border-radius: 3px;
52
  font-weight: bold;
53
  }
54
+ /* تصميم الفقرات والترقيم */
 
55
  .line-item {
56
  margin-bottom: 1rem;
57
  padding: 0.5rem;
58
+ border-bottom: 1px dashed #ddd;
59
  }
60
  .line-number {
61
  font-weight: bold;
62
+ color: #2d3748;
63
  margin-left: 0.5rem;
64
  }
 
 
65
  /* تصميم البطاقات */
66
  .card {
67
+ background-color: #ffffff;
68
  border-radius: 1rem;
69
+ box-shadow: 0 8px 20px -4px rgba(0, 0, 0, 0.1);
70
  padding: 2rem;
71
+ border: 1px solid #f1f5f9;
72
  }
73
+ .card:hover { box-shadow: 0 8px 20px -4px rgba(0, 0, 0, 0.15); }
74
+ /* تخصيص رفع الملفات: الأيقونات على اليمين */
75
+ .file-upload-label {
 
 
 
76
  display: flex;
77
+ justify-content: space-between;
78
  align-items: center;
79
+ }
80
+ /* تبويبات العرض (المعاينة والشرح) */
81
+ .tab {
82
+ cursor: pointer;
83
+ padding: 0.5rem 1rem;
84
+ border-bottom: 2px solid transparent;
85
+ }
86
+ .tab-active {
87
+ border-bottom-color: #4F46E5;
88
+ font-weight: bold;
89
  }
90
  </style>
91
  </head>
92
+ <body class="bg-gradient-to-br from-blue-100 via-purple-100 to-pink-100 min-h-screen">
93
  <div class="min-h-screen pb-12">
94
+ <!-- الرأس -->
95
+ <header class="bg-gradient-to-r from-blue-800 via-purple-800 to-pink-800 animate-gradient text-white py-10 shadow-2xl">
96
  <div class="max-w-6xl mx-auto px-4 text-center">
97
+ <h1 class="text-5xl font-extrabold mb-4 hover-scale">
98
+ <i class="fas fa-brain mr-2"></i> منصة مراجعة النصوص والترج��ات المتقدمة
99
  </h1>
100
+ <p class="text-xl opacity-90">
101
+ <i class="fas fa-search mr-2"></i> استعن بأحدث التقنيات لتحليل النصوص واستخراج الأخطاء بدقة عالية
102
  </p>
103
  </div>
104
  </header>
105
+
106
  <!-- المحتوى الرئيسي -->
107
+ <main class="max-w-6xl mx-auto px-4 space-y-10">
108
+ <!-- قسم رفع الملفات -->
109
+ <section class="card">
110
+ <h2 class="text-2xl font-bold text-gray-800 border-b pb-3 mb-6">
111
+ <i class="fas fa-cloud-upload-alt text-blue-600 mr-2"></i> رفع الملفات
112
  </h2>
113
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
114
  <!-- ملف المصدر -->
115
+ <div class="group border-2 border-dashed border-blue-300 rounded-xl p-6 text-center bg-blue-50 hover:bg-blue-100 transition-colors duration-300">
116
+ <label class="cursor-pointer block file-upload-label">
117
+ <span class="text-lg text-blue-600 group-hover:text-blue-700">ملف المصدر</span>
118
+ <i class="fas fa-upload text-5xl text-blue-500"></i>
119
  <input type="file" id="sourceFile" accept=".docx,.pdf" class="hidden">
 
 
120
  </label>
121
  </div>
122
  <!-- ملف الهدف -->
123
+ <div class="group border-2 border-dashed border-pink-300 rounded-xl p-6 text-center bg-pink-50 hover:bg-pink-100 transition-colors duration-300">
124
+ <label class="cursor-pointer block file-upload-label">
125
+ <span class="text-lg text-pink-600 group-hover:text-pink-700">ملف الهدف</span>
126
+ <i class="fas fa-download text-5xl text-pink-500"></i>
127
  <input type="file" id="targetFile" accept=".docx,.pdf" class="hidden">
 
 
128
  </label>
129
  </div>
130
  </div>
131
+ <div id="processStatus" class="hidden mt-4">
132
+ <div class="flex items-center justify-center space-x-3 bg-blue-100 rounded-xl p-4">
133
+ <div class="animate-spin h-8 w-8 border-4 border-blue-600 rounded-full border-t-transparent"></div>
134
+ <span class="text-lg text-blue-700">جارٍ معالجة الملف...</span>
135
  </div>
136
  </div>
137
+ </section>
138
+
139
+ <!-- قسم إدخال النصوص يدويًا -->
140
+ <section class="card">
141
+ <div class="space-y-6">
142
  <!-- النص المصدر -->
143
  <div class="group">
144
+ <label class="block text-lg font-bold text-gray-700 mb-3">
145
+ <i class="fas fa-pen-fancy text-blue-600 mr-2"></i> النص المصدر
146
  </label>
147
+ <textarea id="sourceText" dir="rtl" class="w-full px-6 py-4 border-2 border-gray-300 rounded-xl focus:ring-blue-200 focus:border-blue-400 transition-all resize-none text-lg" rows="6" placeholder="��كتب النص المصدر هنا..."></textarea>
148
  </div>
149
  <!-- النص الهدف -->
150
  <div class="group">
151
+ <label class="block text-lg font-bold text-gray-700 mb-3">
152
+ <i class="fas fa-pen-fancy text-pink-600 mr-2"></i> النص الهدف
153
  </label>
154
+ <textarea id="targetText" dir="ltr" class="w-full px-6 py-4 border-2 border-gray-300 rounded-xl focus:ring-pink-200 focus:border-pink-400 transition-all resize-none text-lg" rows="6" placeholder="اكتب النص الهدف هنا..."></textarea>
155
  </div>
156
  </div>
157
+ </section>
158
+
159
+ <!-- قسم المصادر الإضافية -->
160
+ <section class="card">
161
+ <h2 class="text-2xl font-bold text-gray-800 border-b pb-3 mb-6">
162
+ <i class="fas fa-bookmark text-green-600 mr-2"></i> المصادر الإضافية
163
  </h2>
164
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
165
  <!-- رفع ملف المصادر -->
166
+ <div class="group border-2 border-dashed border-green-300 rounded-xl p-6 text-center bg-green-50 hover:bg-green-100 transition-colors duration-300">
167
+ <label class="cursor-pointer block file-upload-label">
168
+ <span class="text-lg text-green-600 group-hover:text-green-700">تحميل ملف المصادر</span>
169
+ <i class="fas fa-upload text-5xl text-green-500"></i>
170
  <input type="file" id="sourceExtraFile" accept=".docx,.pdf" class="hidden">
 
 
171
  </label>
172
  </div>
173
  <!-- إدخال المصادر يدويًا -->
174
  <div class="group">
175
+ <label class="block text-lg font-bold text-gray-700 mb-3">
176
+ <i class="fas fa-edit text-green-600 mr-2"></i> إدخال المصادر يدويًا
177
  </label>
178
+ <textarea id="sourceExtraText" dir="rtl" class="w-full px-6 py-4 border-2 border-green-300 rounded-xl focus:ring-green-200 focus:border-green-400 transition-all resize-none text-lg" rows="6" placeholder="اكتب المصادر هنا..."></textarea>
179
  </div>
180
  </div>
181
+ </section>
182
+
183
+ <!-- زر التحليل -->
184
+ <section class="text-center">
185
+ <button id="submitBtn" class="w-full md:w-1/2 mx-auto bg-gradient-to-r from-blue-600 to-pink-600 hover:from-blue-700 hover:to-pink-700 text-white font-bold py-5 px-8 rounded-xl transition-all transform hover-scale pulse-animation text-xl shadow-xl">
186
+ <i class="fas fa-sync-alt mr-2"></i> تحليل ومراجعة النصوص
187
+ </button>
188
+ </section>
189
+
190
+ <!-- نافذة النتائج مع تبويبات للمعاينة والشرح -->
191
+ <section id="resultSection" class="card hidden">
192
+ <h2 class="text-2xl font-bold text-gray-800 border-b pb-3 mb-6">
193
+ <i class="fas fa-search text-green-600 mr-2"></i> نتائج التحليل
 
194
  </h2>
195
+ <div id="errorsList" class="space-y-3 mb-6"></div>
196
+ <div class="mb-4">
197
+ <span id="tabPreview" class="tab tab-active">المعاينة</span>
198
+ <span id="tabExplanation" class="tab">الشرح التفصيلي</span>
199
+ </div>
200
+ <div id="tabContent">
201
+ <div id="previewContent" class="grid grid-cols-1 md:grid-cols-2 gap-6">
202
+ <div>
203
+ <h4 class="text-lg font-semibold text-gray-700 mb-3">
204
+ <i class="fas fa-file-alt text-blue-600 mr-2"></i> النص المصدر (مع التعليم)
205
+ </h4>
206
+ <div id="sourceTextReview" class="bg-blue-50 rounded-xl p-6 min-h-[200px] border border-blue-200 text-comparison"></div>
207
+ </div>
208
+ <div>
209
+ <h4 class="text-lg font-semibold text-gray-700 mb-3">
210
+ <i class="fas fa-file-alt text-pink-600 mr-2"></i> النص الهدف (بدون تعليم)
211
+ </h4>
212
+ <div id="targetTextReview" class="bg-pink-50 rounded-xl p-6 min-h-[200px] border border-pink-200 text-comparison"></div>
213
+ </div>
214
  </div>
215
+ <div id="explanationContent" class="hidden">
216
+ <h4 class="text-lg font-semibold text-gray-700 mb-3">
217
+ <i class="fas fa-info-circle text-green-600 mr-2"></i> شرح الأخطاء
218
  </h4>
219
+ <div id="explanationText" class="text-lg text-gray-700"></div>
220
  </div>
221
  </div>
222
+ </section>
 
 
 
 
 
 
 
 
223
  </main>
224
  </div>
225
+
226
+ <!-- جافا سكريبت للتحليل ومراجعة النصوص -->
227
  <script>
228
  (function() {
229
  "use strict";
230
+ // تعليمات التحدي
231
+ // في هذا النموذج، هنالك اختلافات مخفية في النصوص.
232
+ // التحدي ا��مقدم هو: يجب على النموذج استخراج كافة الأخطاء.
233
+ // إذا استطاع اكتشافها بشكل صحيح، يحصل على جائزة (رسالة تحفيزية).
234
+ // أما إذا أخطأ في الاستخراج أو زعم وجود أخطاء غير موجودة، فسوف يعاقب برسالة تحذيرية.
235
+
236
+ const ANALYSIS_PROMPT = `أنت خبير لغوي وتقني متخصص في مراجعة الترجمات وتحليل النصوص بدقة متناهية. أمامك تحدي استخراج الأخطاء التالية من النصوص:
237
+ 1. النصوص المفقودة: الكلمات أو العبارات التي لم تُترجم من النص المصدر (يتم تعليمها في النص المصدر فقط).
238
+ 2. الأرقام والتواريخ: التي لا تتطابق بين النص المصدر والنص الهدف.
239
+ 3. اختلاف المعنى: إذا كان هناك تغيير جوهري في معنى النص.
240
+ مهمتك استخراج هذه الأخطاء بدقة. وإذا استطعت استخراجها جميعاً بشكل صحيح، ستحصل على جائزة تقديرية. أما إذا أخطأت أو أدلت بتقرير وجود أخطاء غير موجودة، فسوف تتعرض للانتقادات والعقاب.
241
+ يُرجى تعليم:
242
+ - النصوص المفقودة بوضعها بين علامتي __ والنص__.
243
+ - الأرقام والتواريخ بوضعها بين علامتي < والنص>.
244
+ - اختلاف المعنى بوضعها بين [MEANING] و [/MEANING].
245
+
246
+ قدم الناتج في شكل قائمة تفصيلية مع شرح فقرة بفقرة لكل خطأ مع ذكر رقم السطر إن أمكن.
247
 
248
  النص المصدر:
249
  {source}
250
 
251
  النص الهدف:
252
  {target}`;
253
+
254
+ /* دوال مساعدة */
255
  const countWords = text =>
256
  text.trim().split(/\s+/).filter(word => word !== "").length;
257
+
258
  const escapeRegExp = string =>
259
  string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
260
+
261
+ // تقسيم النص إلى أسطر مرقمة
262
  const splitIntoLines = text =>
263
  text.split(/\n+/).map((line, i) => {
264
  line = line.trim();
265
  if(line && !line.endsWith('.')) { line += '.'; }
266
  return `<div class="line-item"><span class="line-number">${i+1}:</span><span class="line-text">${line}</span></div>`;
267
  }).join('');
268
+
269
+ // الحصول على رقم السطر لنص معين
270
  const getLineNumber = (text, substring) => {
271
  const index = text.indexOf(substring);
272
  if (index === -1) return "غير محدد";
273
  return text.substring(0, index).split("\n").length;
274
  };
275
+
276
+ /* دوال التعليم والشرح */
277
+ const applyHighlights = (sourceText, analysisOutput) => {
278
+ let highlightedText = sourceText;
279
  let match;
280
+ // تعليم النصوص المفقودة
281
  const missingRegex = /__(.*?)__/g;
282
  while ((match = missingRegex.exec(analysisOutput)) !== null) {
283
  const phrase = match[1].trim();
 
287
  highlightedText = highlightedText.replace(phraseRegex, replacement);
288
  }
289
  }
290
+ // تعليم الأرقام والتواريخ
291
  const numberRegex = /<([^<>]+)>/g;
292
  while ((match = numberRegex.exec(analysisOutput)) !== null) {
293
  const phrase = match[1].trim();
 
297
  highlightedText = highlightedText.replace(phraseRegex, replacement);
298
  }
299
  }
300
+ // تعليم اختلاف المعنى
301
+ const meaningRegex = /\[MEANING\](.*?)\[\/MEANING\]/g;
302
+ while ((match = meaningRegex.exec(analysisOutput)) !== null) {
303
  const phrase = match[1].trim();
304
  if (phrase) {
305
+ const replacement = `<span class="highlight-meaning">${phrase}</span>`;
306
  const phraseRegex = new RegExp(escapeRegExp(phrase), 'g');
307
  highlightedText = highlightedText.replace(phraseRegex, replacement);
308
  }
309
  }
310
  return highlightedText;
311
  };
312
+
313
+ // توليد شرح تفصيلي للأخطاء
314
  const generateExplanation = (sourceText, analysisOutput) => {
315
+ let paragraphs = [];
316
  const iconMissing = `<i class="fas fa-exclamation-triangle mr-1"></i>`;
317
  const iconNumber = `<i class="fas fa-hashtag mr-1"></i>`;
318
  const iconMeaning = `<i class="fas fa-info-circle mr-1"></i>`;
319
+ let match;
 
320
  // شرح النصوص المفقودة
321
  const missingRegex = /__(.*?)__/g;
 
322
  while ((match = missingRegex.exec(analysisOutput)) !== null) {
323
  const phrase = match[1].trim();
324
  if (phrase) {
325
  const lineNum = getLineNumber(sourceText, phrase);
326
+ paragraphs.push(`<p>${iconMissing} في السطر ${lineNum}، النص المفقود: <span class="highlight-missing">${phrase}</span></p>`);
327
  }
328
  }
329
  // شرح الأرقام والتواريخ
 
332
  const phrase = match[1].trim();
333
  if (phrase) {
334
  const lineNum = getLineNumber(sourceText, phrase);
335
+ paragraphs.push(`<p>${iconNumber} في السطر ${lineNum}، الرقم/التاريخ: <span class="highlight-number">${phrase}</span></p>`);
336
  }
337
  }
338
  // شرح اختلاف المعنى
 
341
  const phrase = match[1].trim();
342
  if (phrase) {
343
  const lineNum = getLineNumber(sourceText, phrase);
344
+ paragraphs.push(`<p>${iconMeaning} في السطر ${lineNum}، اختلاف المعنى: <span class="highlight-meaning">${phrase}</span></p>`);
 
 
 
 
 
 
 
 
 
345
  }
346
  }
347
+ if (paragraphs.length === 0) {
348
+ return `<p><i class="fas fa-check-circle mr-2"></i> لا توجد أخطاء ملحوظة بين النصين. وهذا يعني أنك ستتعرض للعقاب لأن التحدي يتطلب إيجاد أخطاء!</p>`;
 
 
 
 
 
 
349
  }
350
+ return paragraphs.join('');
351
  };
352
+
353
+ /* دالة معالجة الملفات (PDF و DOCX) */
354
  const processFile = async file => {
355
  let text = "";
356
  try {
 
377
  }
378
  return text;
379
  };
380
+
381
+ /* التعامل مع رفع الملفات وإدخال النصوص */
382
  const processFileInput = (inputId, targetTextAreaId, errorMsg) => {
383
  document.getElementById(inputId)?.addEventListener('change', async (event) => {
384
  const file = event.target.files[0];
 
394
  }
395
  });
396
  };
397
+
398
  // رفع ملفات المصدر، الهدف والمصادر الإضافية
399
  processFileInput('sourceFile', 'sourceText', 'خطأ في معالجة ملف المصدر');
400
  processFileInput('targetFile', 'targetText', 'خطأ في معالجة ملف الهدف');
401
  processFileInput('sourceExtraFile', 'sourceExtraText', 'خطأ في معالجة ملف المصادر الإضافية');
402
+
403
+ /* دالة عرض الأخطاء */
404
  const addError = (message, type = 'error') => {
405
  const errorsList = document.getElementById('errorsList');
406
  if (!errorsList) return;
 
412
  </div>`;
413
  errorsList.appendChild(errorDiv);
414
  };
415
+
416
+ /* تبويبات العرض للمعاينة والشرح */
417
+ const setupTabs = () => {
418
+ const tabPreview = document.getElementById('tabPreview');
419
+ const tabExplanation = document.getElementById('tabExplanation');
420
+ const previewContent = document.getElementById('previewContent');
421
+ const explanationContent = document.getElementById('explanationContent');
422
+ tabPreview.addEventListener('click', () => {
423
+ tabPreview.classList.add('tab-active');
424
+ tabExplanation.classList.remove('tab-active');
425
+ previewContent.classList.remove('hidden');
426
+ explanationContent.classList.add('hidden');
427
+ });
428
+ tabExplanation.addEventListener('click', () => {
429
+ tabExplanation.classList.add('tab-active');
430
+ tabPreview.classList.remove('tab-active');
431
+ explanationContent.classList.remove('hidden');
432
+ previewContent.classList.add('hidden');
433
+ });
434
+ };
435
+
436
+ /* التعامل مع عملية التحليل */
437
  document.getElementById('submitBtn').addEventListener('click', async () => {
438
  const sourceText = document.getElementById('sourceText').value;
439
  const targetText = document.getElementById('targetText').value;
440
+ const sourceExtra = document.getElementById('sourceExtraText').value.trim();
441
  document.getElementById('errorsList').innerHTML = '';
442
  document.getElementById('resultSection').classList.remove('hidden');
443
+
 
444
  if (!sourceText || !targetText) {
445
  addError('يرجى إدخال كلا النصين المصدر والهدف');
446
  return;
447
  }
448
+
449
  const sourceWordCount = countWords(sourceText);
450
  const targetWordCount = countWords(targetText);
451
  if (sourceWordCount !== targetWordCount) {
452
  addError(`عدد كلمات النص المصدر (${sourceWordCount}) يختلف عن النص الهدف (${targetWordCount})`, 'warning');
453
  }
454
+
455
  try {
456
  const progressDiv = document.createElement('div');
457
+ progressDiv.className = "bg-blue-100 p-4 rounded-xl mb-4";
458
+ progressDiv.innerHTML = `<div class="flex items-center">
459
+ <div class="animate-spin h-6 w-6 border-4 border-blue-600 rounded-full border-t-transparent mr-3"></div>
460
+ <span>جارٍ التحليل...</span>
461
  </div>`;
462
  document.getElementById('errorsList').appendChild(progressDiv);
463
+
464
  const prompt = ANALYSIS_PROMPT
465
  .replace("{source}", sourceText)
466
  .replace("{target}", targetText);
 
467
  const payload = {
468
  model: "deepseek-chat",
469
  messages: [
470
+ { role: "system", content: "أنت خبير في تحليل ومراجعة النصوص، وعليك استخراج الأخطاء بدقة. تذكر: إذا اكتشفت جميع الأخطاء فستحصل على جائزة تحفيزية، وإذا أخطأت سواء بإيجاد أخطاء غير موجودة أو بعدم اكتشاف الأخطاء، فسوف تواجه عقوبة." },
471
  { role: "user", content: prompt }
472
  ],
473
  temperature: 0.3,
474
  max_tokens: 2048,
475
  stream: false
476
  };
477
+
478
  const response = await fetch('https://api.deepseek.com/chat/completions', {
479
  method: 'POST',
480
  headers: {
 
483
  },
484
  body: JSON.stringify(payload)
485
  });
486
+
487
+ if (!response.ok) {
488
+ throw new Error('حدث خطأ بالشبكة: ' + response.statusText);
489
  }
490
  const data = await response.json();
491
  const analysisOutput = data.choices[0].message.content.trim();
492
  progressDiv.remove();
493
+
494
+ // إذا كانت النصوص متطابقة تما��اً
495
  if (analysisOutput.includes('[MATCH]')) {
496
  const checkDiv = document.createElement('div');
497
  checkDiv.className = "p-4 rounded-xl bg-green-50 text-green-700 flex items-center";
498
+ checkDiv.innerHTML = `<i class="fas fa-check-circle mr-2"></i> <span>النصوص متطابقة تماماً، وهذا غير مقبول في هذا التحدي!</span>`;
499
  document.getElementById('errorsList').appendChild(checkDiv);
500
  document.getElementById('sourceTextReview').innerHTML = splitIntoLines(sourceText);
501
  document.getElementById('targetTextReview').innerHTML = splitIntoLines(targetText);
502
+ document.getElementById('explanationText').innerHTML = `<p>النصوص متطابقة ولا يوجد اختلاف يجب الإشارة إليه، لذا فشلت في التحدي وتم توقيع عقوبة!</p>`;
503
  } else {
504
+ // تطبيق التعليم على النص المصدر فقط
505
  const sourceHighlighted = applyHighlights(sourceText, analysisOutput);
506
  document.getElementById('sourceTextReview').innerHTML = splitIntoLines(sourceHighlighted);
 
507
  document.getElementById('targetTextReview').innerHTML = splitIntoLines(targetText);
508
  const explanationHTML = generateExplanation(sourceText, analysisOutput);
509
+ let sourcesNote = "";
510
+ if(sourceExtra) {
511
+ sourcesNote = `<p><i class="fas fa-bookmark mr-1"></i> المصادر مستخدمة.</p>`;
512
+ } else {
513
+ sourcesNote = `<p><i class="fas fa-ban mr-1"></i> لم يتم استخدام المصادر.</p>`;
514
+ }
515
+ document.getElementById('explanationText').innerHTML = sourcesNote + explanationHTML;
516
  }
517
+ setupTabs();
518
  } catch (error) {
519
  document.getElementById('errorsList').innerHTML = '';
520
  addError(`خطأ في التحليل: ${error.message}`);
 
523
  })();
524
  </script>
525
  </body>
526
+ </html>