Update index.html
Browse files- index.html +56 -32
index.html
CHANGED
@@ -10,7 +10,7 @@
|
|
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 |
-
|
14 |
================================= */
|
15 |
@keyframes gradient {
|
16 |
0% { background-position: 0% 50%; }
|
@@ -56,13 +56,13 @@
|
|
56 |
font-weight: bold;
|
57 |
}
|
58 |
.highlight-meaning {
|
59 |
-
background-color: #E0E7FF;
|
60 |
padding: 0 4px;
|
61 |
border-radius: 3px;
|
62 |
font-weight: bold;
|
63 |
}
|
64 |
.highlight-doubt {
|
65 |
-
background-color: #DBEAFE; /* أزرق
|
66 |
color: #1E3A8A;
|
67 |
padding: 0 4px;
|
68 |
border-radius: 3px;
|
@@ -70,11 +70,11 @@
|
|
70 |
}
|
71 |
|
72 |
/* ================================
|
73 |
-
تنسيق الفقرات وترقيمها
|
74 |
================================= */
|
75 |
.line-item {
|
76 |
margin-bottom: 1rem;
|
77 |
-
padding: 0.
|
78 |
border-bottom: 1px dashed #ccc;
|
79 |
}
|
80 |
.line-number {
|
@@ -85,7 +85,7 @@
|
|
85 |
.line-text { display: inline-block; }
|
86 |
|
87 |
/* ================================
|
88 |
-
|
89 |
================================= */
|
90 |
.card {
|
91 |
background-color: #fff;
|
@@ -99,6 +99,13 @@
|
|
99 |
transform: translateY(-3px);
|
100 |
}
|
101 |
.icon { margin-right: 0.5rem; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
</style>
|
103 |
</head>
|
104 |
<body class="bg-gradient-to-br from-gray-100 via-blue-100 to-indigo-100 min-h-screen">
|
@@ -110,7 +117,7 @@
|
|
110 |
<i class="fas fa-chart-line icon"></i> نظام المقارنة والتحليل المتقدم
|
111 |
</h1>
|
112 |
<p class="text-xl opacity-90">
|
113 |
-
<i class="fas fa-info-circle icon"></i>
|
114 |
</p>
|
115 |
</div>
|
116 |
</header>
|
@@ -156,14 +163,14 @@
|
|
156 |
<label class="block text-lg font-bold text-gray-700 mb-3">
|
157 |
<i class="fas fa-language icon text-indigo-600"></i> النص المصدر
|
158 |
</label>
|
159 |
-
<textarea id="sourceText" dir="rtl" class="w-full px-6 py-4 border-2 border-gray-200 rounded-xl focus:ring-indigo-200 focus:border-indigo-400 transition-all resize-none text-lg" rows="
|
160 |
</div>
|
161 |
<!-- النص الهدف -->
|
162 |
<div class="group">
|
163 |
<label class="block text-lg font-bold text-gray-700 mb-3">
|
164 |
<i class="fas fa-language icon text-pink-600"></i> النص الهدف
|
165 |
</label>
|
166 |
-
<textarea id="targetText" dir="ltr" class="w-full px-6 py-4 border-2 border-gray-200 rounded-xl focus:ring-pink-200 focus:border-pink-400 transition-all resize-none text-lg" rows="
|
167 |
</div>
|
168 |
</div>
|
169 |
</div>
|
@@ -187,7 +194,7 @@
|
|
187 |
<label class="block text-lg font-bold text-gray-700 mb-3">
|
188 |
<i class="fas fa-edit icon text-green-600"></i> إدخال المصادر يدويًا
|
189 |
</label>
|
190 |
-
<textarea id="sourceExtraText" dir="rtl" class="w-full px-6 py-4 border-2 border-green-200 rounded-xl focus:ring-green-200 focus:border-green-400 transition-all resize-none text-lg" rows="
|
191 |
</div>
|
192 |
</div>
|
193 |
</div>
|
@@ -199,7 +206,7 @@
|
|
199 |
</div>
|
200 |
</button>
|
201 |
|
202 |
-
<!-- نتائج التحليل -->
|
203 |
<div id="resultSection" class="card hidden">
|
204 |
<h2 class="text-2xl font-bold text-gray-800 border-b pb-3 mb-6">
|
205 |
<i class="fas fa-search icon text-green-600"></i> نتائج التحليل والمقارنة
|
@@ -221,10 +228,10 @@
|
|
221 |
</div>
|
222 |
</div>
|
223 |
|
224 |
-
<!--
|
225 |
<div id="explanationBox" class="card hidden">
|
226 |
<h2 class="text-2xl font-bold text-gray-800 border-b pb-3 mb-6">
|
227 |
-
<i class="fas fa-info-circle icon text-green-600"></i> شرح الاختلافات
|
228 |
</h2>
|
229 |
<div id="explanationText" class="text-lg text-gray-700"></div>
|
230 |
</div>
|
@@ -235,18 +242,19 @@
|
|
235 |
جافا سكريبت: الوظائف والتحليل
|
236 |
================================= -->
|
237 |
<script>
|
|
|
238 |
const API_URL = 'https://api.deepseek.com/chat/completions';
|
239 |
const API_KEY = 'sk-15606736ed9e4aea8b7cc11a195d2b01';
|
240 |
-
const ANALYSIS_PROMPT = `أنت خبير لغوي وتقني متخصص في مراجعة الترجمة التقنية وتحليل النصوص
|
241 |
تعليمات:
|
242 |
-
1. قم بتحليل النص إلى فقرات
|
243 |
2. لا تقم بتعديل العلامات التالية:
|
244 |
- الأرقام والتواريخ محاطة بـ < و >.
|
245 |
- النصوص المفقودة محاطة بـ __ و __.
|
246 |
- النصوص الزائدة محاطة بـ <<EXTRA>> و <<\/EXTRA>>.
|
247 |
- اختلافات المعنى محاطة بـ [MEANING] و [/MEANING].
|
248 |
- علامات الشك أو الأخطاء البسيطة محاطة بـ [DOUBT] و [/DOUBT].
|
249 |
-
3.
|
250 |
|
251 |
النص المصدر:
|
252 |
{source}
|
@@ -254,7 +262,7 @@
|
|
254 |
النص الهدف:
|
255 |
{target}`;
|
256 |
|
257 |
-
// دوال مساعدة
|
258 |
function countWords(text) {
|
259 |
return text.trim().split(/\s+/).filter(word => word !== "").length;
|
260 |
}
|
@@ -264,8 +272,10 @@
|
|
264 |
function splitIntoLines(text) {
|
265 |
return text.split(/\n+/).map((line, i) => {
|
266 |
line = line.trim();
|
267 |
-
if(line && !line.endsWith('.')) {
|
268 |
-
|
|
|
|
|
269 |
}).join('');
|
270 |
}
|
271 |
function getLineNumber(text, substring) {
|
@@ -274,7 +284,7 @@
|
|
274 |
return text.substring(0, index).split("\n").length;
|
275 |
}
|
276 |
|
277 |
-
// دوال التظليل (Highlighting)
|
278 |
function applyHighlights(originalText, analysisOutput) {
|
279 |
let highlightedText = originalText;
|
280 |
let match;
|
@@ -288,7 +298,7 @@
|
|
288 |
highlightedText = highlightedText.replace(phraseRegex, replacement);
|
289 |
}
|
290 |
}
|
291 |
-
// النصوص المفقودة
|
292 |
const missingRegex = /__(.*?)__/g;
|
293 |
while ((match = missingRegex.exec(analysisOutput)) !== null) {
|
294 |
const phrase = match[1].trim();
|
@@ -331,7 +341,7 @@
|
|
331 |
return highlightedText;
|
332 |
}
|
333 |
|
334 |
-
// دالة توليد شرح تفصيلي للاختلافات مع أيقونات
|
335 |
function generateExplanation(sourceText, analysisOutput) {
|
336 |
let steps = [];
|
337 |
let match;
|
@@ -341,46 +351,52 @@
|
|
341 |
const iconMeaning = `<i class="fas fa-info-circle text-blue-600 mr-1"></i>`;
|
342 |
const iconDoubt = `<i class="fas fa-question-circle text-indigo-600 mr-1"></i>`;
|
343 |
|
|
|
344 |
const missingRegex = /__(.*?)__/g;
|
345 |
while ((match = missingRegex.exec(analysisOutput)) !== null) {
|
346 |
const phrase = match[1].trim();
|
347 |
if (phrase) {
|
348 |
const lineNum = getLineNumber(sourceText, phrase);
|
349 |
-
steps.push(`<li>${iconMissing} في السطر ${lineNum}
|
350 |
}
|
351 |
}
|
|
|
352 |
const numberRegex = /<([^<>]+)>/g;
|
353 |
while ((match = numberRegex.exec(analysisOutput)) !== null) {
|
354 |
const phrase = match[1].trim();
|
355 |
if (phrase) {
|
356 |
const lineNum = getLineNumber(sourceText, phrase);
|
357 |
-
steps.push(`<li>${iconNumber} في السطر ${lineNum}
|
358 |
}
|
359 |
}
|
|
|
360 |
const extraRegex = /<<EXTRA>>(.*?)<<\/EXTRA>>/g;
|
361 |
while ((match = extraRegex.exec(analysisOutput)) !== null) {
|
362 |
const phrase = match[1].trim();
|
363 |
if (phrase) {
|
364 |
const lineNum = getLineNumber(sourceText, phrase);
|
365 |
-
steps.push(`<li>${iconExtra} في السطر ${lineNum}
|
366 |
}
|
367 |
}
|
|
|
368 |
const meaningRegex = /\[MEANING\](.*?)\[\/MEANING\]/g;
|
369 |
while ((match = meaningRegex.exec(analysisOutput)) !== null) {
|
370 |
const phrase = match[1].trim();
|
371 |
if (phrase) {
|
372 |
const lineNum = getLineNumber(sourceText, phrase);
|
373 |
-
steps.push(`<li>${iconMeaning} في السطر ${lineNum}
|
374 |
}
|
375 |
}
|
|
|
376 |
const doubtRegex = /\[DOUBT\](.*?)\[\/DOUBT\]/g;
|
377 |
while ((match = doubtRegex.exec(analysisOutput)) !== null) {
|
378 |
const phrase = match[1].trim();
|
379 |
if (phrase) {
|
380 |
const lineNum = getLineNumber(sourceText, phrase);
|
381 |
-
steps.push(`<li>${iconDoubt} في السطر ${lineNum}
|
382 |
}
|
383 |
}
|
|
|
384 |
if (steps.length === 0) {
|
385 |
return `<p class="text-green-700"><i class="fas fa-check-circle mr-2"></i> لا توجد اختلافات ملحوظة بين النصين.</p>`;
|
386 |
}
|
@@ -454,7 +470,7 @@
|
|
454 |
}
|
455 |
});
|
456 |
|
457 |
-
// دالة عرض الأخطاء
|
458 |
function addError(message, type = 'error') {
|
459 |
const errorsList = document.getElementById('errorsList');
|
460 |
if (!errorsList) return;
|
@@ -467,7 +483,7 @@
|
|
467 |
errorsList.appendChild(errorDiv);
|
468 |
}
|
469 |
|
470 |
-
// معالجة عملية التحليل عند الضغط على
|
471 |
document.getElementById('submitBtn').addEventListener('click', async () => {
|
472 |
const sourceText = document.getElementById('sourceText').value;
|
473 |
const targetText = document.getElementById('targetText').value;
|
@@ -509,6 +525,7 @@
|
|
509 |
max_tokens: 2048,
|
510 |
stream: false
|
511 |
};
|
|
|
512 |
const response = await fetch(API_URL, {
|
513 |
method: 'POST',
|
514 |
headers: {
|
@@ -517,11 +534,14 @@
|
|
517 |
},
|
518 |
body: JSON.stringify(payload)
|
519 |
});
|
520 |
-
if (!response.ok) {
|
|
|
|
|
521 |
const data = await response.json();
|
522 |
const analysisOutput = data.choices[0].message.content.trim();
|
523 |
progressDiv.remove();
|
524 |
|
|
|
525 |
if (analysisOutput.includes('[MATCH]')) {
|
526 |
const checkDiv = document.createElement('div');
|
527 |
checkDiv.className = "p-4 rounded-xl bg-green-50 text-green-700 flex items-center";
|
@@ -529,26 +549,30 @@
|
|
529 |
document.getElementById('errorsList').appendChild(checkDiv);
|
530 |
document.getElementById('sourceTextReview').innerHTML = splitIntoLines(sourceText);
|
531 |
document.getElementById('targetTextReview').innerHTML = splitIntoLines(targetText);
|
532 |
-
document.getElementById('explanationText').innerHTML = `<p>النصوص متطابقة ولا
|
533 |
} else {
|
|
|
534 |
const sourceHighlighted = applyHighlights(sourceText, analysisOutput);
|
535 |
const targetHighlighted = applyHighlights(targetText, analysisOutput);
|
536 |
document.getElementById('sourceTextReview').innerHTML = splitIntoLines(sourceHighlighted);
|
537 |
document.getElementById('targetTextReview').innerHTML = splitIntoLines(targetHighlighted);
|
|
|
538 |
const explanationHTML = generateExplanation(sourceText, analysisOutput);
|
539 |
document.getElementById('explanationText').innerHTML = explanationHTML;
|
540 |
|
|
|
541 |
const numDiffCount = (analysisOutput.match(/<([^<>]+)>/g) || []).length;
|
542 |
const missingDiffCount = (analysisOutput.match(/__(.*?)__/g) || []).length;
|
543 |
const extraDiffCount = (analysisOutput.match(/<<EXTRA>>(.*?)<<\/EXTRA>>/g) || []).length;
|
544 |
const meaningDiffCount = (analysisOutput.match(/\[MEANING\](.*?)\[\/MEANING\]/g) || []).length;
|
545 |
const doubtDiffCount = (analysisOutput.match(/\[DOUBT\](.*?)\[\/DOUBT\]/g) || []).length;
|
|
|
546 |
if (numDiffCount || missingDiffCount || extraDiffCount || meaningDiffCount || doubtDiffCount) {
|
547 |
const summaryDiv = document.createElement('div');
|
548 |
summaryDiv.className = "p-4 rounded-xl bg-yellow-50 text-gray-800";
|
549 |
let summaryText = '<div class="font-bold mb-2">ملخص الاختلافات:</div><ul class="list-disc ml-4 space-y-1">';
|
550 |
-
if (numDiffCount) summaryText += `<li>اختلاف في الأرقام/التواريخ: ${numDiffCount}</li>`;
|
551 |
if (missingDiffCount) summaryText += `<li>النصوص المفقودة: ${missingDiffCount}</li>`;
|
|
|
552 |
if (extraDiffCount) summaryText += `<li>النصوص الزائدة: ${extraDiffCount}</li>`;
|
553 |
if (meaningDiffCount) summaryText += `<li>اختلاف في المعنى: ${meaningDiffCount}</li>`;
|
554 |
if (doubtDiffCount) summaryText += `<li>علامات الشك: ${doubtDiffCount}</li>`;
|
|
|
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 |
+
تأثيرات وخلفيات متحركة
|
14 |
================================= */
|
15 |
@keyframes gradient {
|
16 |
0% { background-position: 0% 50%; }
|
|
|
56 |
font-weight: bold;
|
57 |
}
|
58 |
.highlight-meaning {
|
59 |
+
background-color: #E0E7FF; /* أزرق فاتح لاختلاف المعنى */
|
60 |
padding: 0 4px;
|
61 |
border-radius: 3px;
|
62 |
font-weight: bold;
|
63 |
}
|
64 |
.highlight-doubt {
|
65 |
+
background-color: #DBEAFE; /* أزرق لعناصر الشك */
|
66 |
color: #1E3A8A;
|
67 |
padding: 0 4px;
|
68 |
border-radius: 3px;
|
|
|
70 |
}
|
71 |
|
72 |
/* ================================
|
73 |
+
تنسيق عرض الفقرات وترقيمها
|
74 |
================================= */
|
75 |
.line-item {
|
76 |
margin-bottom: 1rem;
|
77 |
+
padding: 0.75rem;
|
78 |
border-bottom: 1px dashed #ccc;
|
79 |
}
|
80 |
.line-number {
|
|
|
85 |
.line-text { display: inline-block; }
|
86 |
|
87 |
/* ================================
|
88 |
+
تصميم البطاقات والعناصر
|
89 |
================================= */
|
90 |
.card {
|
91 |
background-color: #fff;
|
|
|
99 |
transform: translateY(-3px);
|
100 |
}
|
101 |
.icon { margin-right: 0.5rem; }
|
102 |
+
|
103 |
+
/* ================================
|
104 |
+
تصميم شاشة الأخطاء والنتائج
|
105 |
+
================================= */
|
106 |
+
#errorsList div {
|
107 |
+
margin-bottom: 0.5rem;
|
108 |
+
}
|
109 |
</style>
|
110 |
</head>
|
111 |
<body class="bg-gradient-to-br from-gray-100 via-blue-100 to-indigo-100 min-h-screen">
|
|
|
117 |
<i class="fas fa-chart-line icon"></i> نظام المقارنة والتحليل المتقدم
|
118 |
</h1>
|
119 |
<p class="text-xl opacity-90">
|
120 |
+
<i class="fas fa-info-circle icon"></i> استخراج كافة المشاكل مع التركيز على النصوص المفقودة
|
121 |
</p>
|
122 |
</div>
|
123 |
</header>
|
|
|
163 |
<label class="block text-lg font-bold text-gray-700 mb-3">
|
164 |
<i class="fas fa-language icon text-indigo-600"></i> النص المصدر
|
165 |
</label>
|
166 |
+
<textarea id="sourceText" dir="rtl" class="w-full px-6 py-4 border-2 border-gray-200 rounded-xl focus:ring-indigo-200 focus:border-indigo-400 transition-all resize-none text-lg" rows="8" placeholder="اكتب النص المصدر هنا..."></textarea>
|
167 |
</div>
|
168 |
<!-- النص الهدف -->
|
169 |
<div class="group">
|
170 |
<label class="block text-lg font-bold text-gray-700 mb-3">
|
171 |
<i class="fas fa-language icon text-pink-600"></i> النص الهدف
|
172 |
</label>
|
173 |
+
<textarea id="targetText" dir="ltr" class="w-full px-6 py-4 border-2 border-gray-200 rounded-xl focus:ring-pink-200 focus:border-pink-400 transition-all resize-none text-lg" rows="8" placeholder="اكتب النص الهدف هنا..."></textarea>
|
174 |
</div>
|
175 |
</div>
|
176 |
</div>
|
|
|
194 |
<label class="block text-lg font-bold text-gray-700 mb-3">
|
195 |
<i class="fas fa-edit icon text-green-600"></i> إدخال المصادر يدويًا
|
196 |
</label>
|
197 |
+
<textarea id="sourceExtraText" dir="rtl" class="w-full px-6 py-4 border-2 border-green-200 rounded-xl focus:ring-green-200 focus:border-green-400 transition-all resize-none text-lg" rows="8" placeholder="اكتب المصادر هنا..."></textarea>
|
198 |
</div>
|
199 |
</div>
|
200 |
</div>
|
|
|
206 |
</div>
|
207 |
</button>
|
208 |
|
209 |
+
<!-- قسم عرض نتائج التحليل -->
|
210 |
<div id="resultSection" class="card hidden">
|
211 |
<h2 class="text-2xl font-bold text-gray-800 border-b pb-3 mb-6">
|
212 |
<i class="fas fa-search icon text-green-600"></i> نتائج التحليل والمقارنة
|
|
|
228 |
</div>
|
229 |
</div>
|
230 |
|
231 |
+
<!-- قسم الشرح التفصيلي للاختلافات -->
|
232 |
<div id="explanationBox" class="card hidden">
|
233 |
<h2 class="text-2xl font-bold text-gray-800 border-b pb-3 mb-6">
|
234 |
+
<i class="fas fa-info-circle icon text-green-600"></i> شرح الاختلافات المفصلة
|
235 |
</h2>
|
236 |
<div id="explanationText" class="text-lg text-gray-700"></div>
|
237 |
</div>
|
|
|
242 |
جافا سكريبت: الوظائف والتحليل
|
243 |
================================= -->
|
244 |
<script>
|
245 |
+
// إعدادات الـ API والبرومبت
|
246 |
const API_URL = 'https://api.deepseek.com/chat/completions';
|
247 |
const API_KEY = 'sk-15606736ed9e4aea8b7cc11a195d2b01';
|
248 |
+
const ANALYSIS_PROMPT = `أنت خبير لغوي وتقني متخصص في مراجعة الترجمة التقنية وتحليل النصوص بدقة عالية. مهمتك مقارنة النص المصدر والنص الهدف واستخراج كافة المشاكل مع التركيز بشكل خاص على النصوص المفقودة.
|
249 |
تعليمات:
|
250 |
+
1. قم بتحليل النص إلى فقرات منفصلة مع التأكد من انتهاء كل فقرة بنقطة.
|
251 |
2. لا تقم بتعديل العلامات التالية:
|
252 |
- الأرقام والتواريخ محاطة بـ < و >.
|
253 |
- النصوص المفقودة محاطة بـ __ و __.
|
254 |
- النصوص الزائدة محاطة بـ <<EXTRA>> و <<\/EXTRA>>.
|
255 |
- اختلافات المعنى محاطة بـ [MEANING] و [/MEANING].
|
256 |
- علامات الشك أو الأخطاء البسيطة محاطة بـ [DOUBT] و [/DOUBT].
|
257 |
+
3. قم باستخراج كافة المشاكل، وعلى رأسها النصوص المفقودة، مع تقديم شرح تفصيلي مدعوم بأيقونات توضيحية لكل فئة.
|
258 |
|
259 |
النص المصدر:
|
260 |
{source}
|
|
|
262 |
النص الهدف:
|
263 |
{target}`;
|
264 |
|
265 |
+
// دوال مساعدة للتعامل مع النصوص
|
266 |
function countWords(text) {
|
267 |
return text.trim().split(/\s+/).filter(word => word !== "").length;
|
268 |
}
|
|
|
272 |
function splitIntoLines(text) {
|
273 |
return 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 |
}
|
281 |
function getLineNumber(text, substring) {
|
|
|
284 |
return text.substring(0, index).split("\n").length;
|
285 |
}
|
286 |
|
287 |
+
// دوال التظليل (Highlighting) لكل نوع من المشاكل
|
288 |
function applyHighlights(originalText, analysisOutput) {
|
289 |
let highlightedText = originalText;
|
290 |
let match;
|
|
|
298 |
highlightedText = highlightedText.replace(phraseRegex, replacement);
|
299 |
}
|
300 |
}
|
301 |
+
// النصوص المفقودة (يتم استخراجها بأهمية خاصة)
|
302 |
const missingRegex = /__(.*?)__/g;
|
303 |
while ((match = missingRegex.exec(analysisOutput)) !== null) {
|
304 |
const phrase = match[1].trim();
|
|
|
341 |
return highlightedText;
|
342 |
}
|
343 |
|
344 |
+
// دالة توليد شرح تفصيلي للاختلافات مع أيقونات توضيحية لكل مشكلة
|
345 |
function generateExplanation(sourceText, analysisOutput) {
|
346 |
let steps = [];
|
347 |
let match;
|
|
|
351 |
const iconMeaning = `<i class="fas fa-info-circle text-blue-600 mr-1"></i>`;
|
352 |
const iconDoubt = `<i class="fas fa-question-circle text-indigo-600 mr-1"></i>`;
|
353 |
|
354 |
+
// استخراج النصوص المفقودة (تظهر كأ��لوية)
|
355 |
const missingRegex = /__(.*?)__/g;
|
356 |
while ((match = missingRegex.exec(analysisOutput)) !== null) {
|
357 |
const phrase = match[1].trim();
|
358 |
if (phrase) {
|
359 |
const lineNum = getLineNumber(sourceText, phrase);
|
360 |
+
steps.push(`<li>${iconMissing} <strong>نص مفقود</strong> في السطر ${lineNum}: <span class="highlight-missing">__${phrase}__</span> غير موجود في النص الهدف.</li>`);
|
361 |
}
|
362 |
}
|
363 |
+
// استخراج اختلافات الأرقام/التواريخ
|
364 |
const numberRegex = /<([^<>]+)>/g;
|
365 |
while ((match = numberRegex.exec(analysisOutput)) !== null) {
|
366 |
const phrase = match[1].trim();
|
367 |
if (phrase) {
|
368 |
const lineNum = getLineNumber(sourceText, phrase);
|
369 |
+
steps.push(`<li>${iconNumber} في السطر ${lineNum}: الرقم/التاريخ <span class="highlight-number">${phrase}</span> لا يتطابق بين المصدر والهدف.</li>`);
|
370 |
}
|
371 |
}
|
372 |
+
// استخراج النصوص الزائدة
|
373 |
const extraRegex = /<<EXTRA>>(.*?)<<\/EXTRA>>/g;
|
374 |
while ((match = extraRegex.exec(analysisOutput)) !== null) {
|
375 |
const phrase = match[1].trim();
|
376 |
if (phrase) {
|
377 |
const lineNum = getLineNumber(sourceText, phrase);
|
378 |
+
steps.push(`<li>${iconExtra} في السطر ${lineNum}: النص الزائد <span class="highlight-extra">${phrase}</span> موجود بشكل غير متوقع في النص الهدف.</li>`);
|
379 |
}
|
380 |
}
|
381 |
+
// استخراج اختلافات المعنى
|
382 |
const meaningRegex = /\[MEANING\](.*?)\[\/MEANING\]/g;
|
383 |
while ((match = meaningRegex.exec(analysisOutput)) !== null) {
|
384 |
const phrase = match[1].trim();
|
385 |
if (phrase) {
|
386 |
const lineNum = getLineNumber(sourceText, phrase);
|
387 |
+
steps.push(`<li>${iconMeaning} في السطر ${lineNum}: اختلاف في المعنى مع التعبير <span class="highlight-meaning">${phrase}</span>.</li>`);
|
388 |
}
|
389 |
}
|
390 |
+
// استخراج علامات الشك أو الأخطاء البسيطة
|
391 |
const doubtRegex = /\[DOUBT\](.*?)\[\/DOUBT\]/g;
|
392 |
while ((match = doubtRegex.exec(analysisOutput)) !== null) {
|
393 |
const phrase = match[1].trim();
|
394 |
if (phrase) {
|
395 |
const lineNum = getLineNumber(sourceText, phrase);
|
396 |
+
steps.push(`<li>${iconDoubt} في السطر ${lineNum}: علامة شك أو خطأ بسيط <span class="highlight-doubt">${phrase}</span> تحتاج مراجعة.</li>`);
|
397 |
}
|
398 |
}
|
399 |
+
|
400 |
if (steps.length === 0) {
|
401 |
return `<p class="text-green-700"><i class="fas fa-check-circle mr-2"></i> لا توجد اختلافات ملحوظة بين النصين.</p>`;
|
402 |
}
|
|
|
470 |
}
|
471 |
});
|
472 |
|
473 |
+
// دالة عرض الأخطاء والرسائل
|
474 |
function addError(message, type = 'error') {
|
475 |
const errorsList = document.getElementById('errorsList');
|
476 |
if (!errorsList) return;
|
|
|
483 |
errorsList.appendChild(errorDiv);
|
484 |
}
|
485 |
|
486 |
+
// معالجة عملية التحليل عند الضغط على زر "تحليل ومراجعة النصوص"
|
487 |
document.getElementById('submitBtn').addEventListener('click', async () => {
|
488 |
const sourceText = document.getElementById('sourceText').value;
|
489 |
const targetText = document.getElementById('targetText').value;
|
|
|
525 |
max_tokens: 2048,
|
526 |
stream: false
|
527 |
};
|
528 |
+
|
529 |
const response = await fetch(API_URL, {
|
530 |
method: 'POST',
|
531 |
headers: {
|
|
|
534 |
},
|
535 |
body: JSON.stringify(payload)
|
536 |
});
|
537 |
+
if (!response.ok) {
|
538 |
+
throw new Error('حدث خطأ بالشبكة: ' + response.statusText);
|
539 |
+
}
|
540 |
const data = await response.json();
|
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";
|
|
|
549 |
document.getElementById('errorsList').appendChild(checkDiv);
|
550 |
document.getElementById('sourceTextReview').innerHTML = splitIntoLines(sourceText);
|
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 |
+
|
570 |
if (numDiffCount || missingDiffCount || extraDiffCount || meaningDiffCount || doubtDiffCount) {
|
571 |
const summaryDiv = document.createElement('div');
|
572 |
summaryDiv.className = "p-4 rounded-xl bg-yellow-50 text-gray-800";
|
573 |
let summaryText = '<div class="font-bold mb-2">ملخص الاختلافات:</div><ul class="list-disc ml-4 space-y-1">';
|
|
|
574 |
if (missingDiffCount) summaryText += `<li>النصوص المفقودة: ${missingDiffCount}</li>`;
|
575 |
+
if (numDiffCount) summaryText += `<li>اختلاف في الأرقام/التواريخ: ${numDiffCount}</li>`;
|
576 |
if (extraDiffCount) summaryText += `<li>النصوص الزائدة: ${extraDiffCount}</li>`;
|
577 |
if (meaningDiffCount) summaryText += `<li>اختلاف في المعنى: ${meaningDiffCount}</li>`;
|
578 |
if (doubtDiffCount) summaryText += `<li>علامات الشك: ${doubtDiffCount}</li>`;
|